From 2361c7d14fc97981901d578edd4f2413b5888bfd Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 13 Jan 2019 16:51:50 +0000 Subject: [PATCH] Flattened downloads menu. Added scrollbars to various menus (when they're too tall for the virtual screen height). Added warnings when qc draws to the screen outside of where it'll actually be displayed (freecs is guilty of this). r_showshaders will now work in q2. mod_texturelist will include a small preview, because I can. plug_list command will now also display some plugins which are not currently loaded. q1bsp now properly respects hitcontents (note that normally only hull 0 actually has contents other than solid+empty). q1bsp now correctly reports content values in tracelines (this fixes freecs being unable to detect func_water). Rewrote netgraph code. Now displays using polygons instead of textures for higher resolution graphs. Fixed texture bug that appears with nouveau's core contexts (texture unit switches were not happening). Added some better support for disabling vsync with nouveau, although its still broken fullscreen for some reason. Changed fteqcc's warning for unrecognised CRCs. Should be more descriptive about the usual cause (but less technical and potentially technically wrong). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5378 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- CMakeLists.txt | 97 ++++++++- engine/Makefile | 7 +- engine/client/cl_input.c | 16 +- engine/client/cl_main.c | 12 +- engine/client/cl_parse.c | 2 +- engine/client/cl_screen.c | 8 +- engine/client/cl_tent.c | 29 ++- engine/client/client.h | 4 +- engine/client/console.c | 77 ++++++-- engine/client/keys.c | 24 +-- engine/client/keys.h | 5 +- engine/client/m_download.c | 280 +++++++++++++++----------- engine/client/m_items.c | 251 ++++++++++++++++++++---- engine/client/m_multi.c | 50 +++-- engine/client/m_options.c | 44 ++++- engine/client/m_script.c | 1 - engine/client/m_single.c | 27 ++- engine/client/menu.c | 15 +- engine/client/menu.h | 15 +- engine/client/pr_menu.c | 44 +++-- engine/client/render.h | 3 + engine/client/renderer.c | 2 +- engine/client/sbar.c | 38 +++- engine/client/screen.h | 1 + engine/client/snd_dma.c | 8 +- engine/client/view.c | 127 ++++++++---- engine/common/com_mesh.c | 2 + engine/common/fs.c | 14 +- engine/common/gl_q2bsp.c | 119 ++++++----- engine/common/plugin.c | 68 +++++++ engine/common/pmovetst.c | 2 +- engine/common/q1bsp.c | 68 +++++-- engine/common/qvm.c | 10 +- engine/gl/gl_backend.c | 43 +++- engine/gl/gl_font.c | 7 +- engine/gl/gl_model.c | 102 +++++++--- engine/gl/gl_model.h | 2 +- engine/gl/gl_ngraph.c | 283 ++++++++++++++++----------- engine/gl/gl_shadow.c | 2 +- engine/gl/gl_vidcommon.c | 67 ++++--- engine/gl/gl_vidlinuxglx.c | 115 +++++++---- engine/gl/glquake.h | 3 +- engine/gl/glsupp.h | 8 +- engine/gl/r_bishaders.h | 9 +- engine/qclib/qccmain.c | 2 +- engine/server/pr_cmds.c | 2 +- engine/server/savegame.c | 5 +- engine/server/sv_move.c | 22 +-- engine/server/sv_send.c | 4 +- engine/server/world.c | 9 +- engine/shaders/glsl/defaultwall.glsl | 2 +- engine/shaders/glsl/defaultwarp.glsl | 1 + 52 files changed, 1532 insertions(+), 626 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34ca3bb4f..36d1cfc4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,11 +129,20 @@ IF(CMAKE_C_COMPILER_ID MATCHES "GNU") #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wc++-compat") #lul #TODO SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-prototypes") #for finding missing statics. #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") # + + #might as well do this, public builds use the regular Makefile. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native") + IF(CMAKE_BUILD_TYPE MATCHES "Debug") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + ELSE() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3") + ENDIF() ENDIF() IF(CMAKE_BUILD_TYPE MATCHES "Debug") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu89") -endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DEBUG") +ENDIF() IF(${ANDROID}) # FIND_PACKAGE(Freetype REQUIRED) @@ -232,6 +241,7 @@ ELSEIF(${UNIX}) #linux(ish) engine/client/snd_al.c engine/client/snd_alsa.c engine/client/snd_linux.c + engine/client/snd_pulse.c engine/client/snd_sdl.c #we use SDL audio even without sys_sdl, because of pulseaudio fucking over alsa, alsa fucking over oss3, and oss4 not being used. Either way, openal should be the default anyway. engine/client/cd_linux.c @@ -405,11 +415,92 @@ SET(FTE_COMMON_FILES engine/common/translate.c engine/common/zone.c + #important headers + engine/common/bothdefs.h engine/common/config_fteqw.h engine/common/config_minimal.h engine/common/config_nocompat.h engine/common/config_wastes.h - + engine/common/config_freecs.h + + #useless headers that I'll never search for + engine/client/api_menu.h + engine/client/cdaudio.h + engine/client/client.h + engine/client/cl_ignore.h + engine/client/cl_master.h + engine/client/clq3defs.h + engine/client/input.h + engine/client/keys.h + engine/client/menu.h + engine/client/merged.h + engine/client/modelgen.h + engine/client/quakedef.h + engine/client/render.h + engine/client/sbar.h + engine/client/screen.h + engine/client/sound.h + engine/client/spritegn.h +# engine/client/sys_plugfte.h + engine/client/vid.h + engine/client/view.h + engine/client/wad.h +# engine/client/winquake.h + engine/common/bothdefs.h + engine/common/bspfile.h + engine/common/cmd.h + engine/common/com_mesh.h + engine/common/common.h + engine/common/console.h + engine/common/crc.h + engine/common/cvar.h + engine/common/fs.h + engine/common/mathlib.h + engine/common/net.h + engine/common/netinc.h + engine/common/particles.h + engine/common/pmove.h + engine/common/pr_common.h + engine/common/protocol.h + engine/common/sys.h + engine/common/translate.h + engine/common/ui_public.h + engine/common/vm.h + engine/common/world.h + engine/common/zone.h + engine/gl/gl_draw.h + engine/gl/gl_model.h + engine/gl/glquake.h + engine/gl/glsupp.h + engine/gl/gl_terrain.h + engine/gl/gl_videgl.h + engine/gl/model_hl.h + engine/gl/shader.h + engine/http/iweb.h + engine/qclib/cmdlib.h + engine/qclib/execloop.h + engine/qclib/gui.h + engine/qclib/hash.h + engine/qclib/pr_comp.h + engine/qclib/progsint.h + engine/qclib/progslib.h + engine/qclib/progtype.h + engine/qclib/qcc.h + engine/qclib/qcd.h + engine/server/botlib.h + engine/server/progdefs.h + engine/server/progs.h + engine/server/q2game.h + engine/server/q3g_public.h + engine/server/server.h + #engine/server/svhl_gcapi.h + engine/server/sv_sql.h + #engine/sw/sw.h + #engine/sw/sw_spans.h + engine/vk/vkrenderer.h + engine/web/ftejslib.h + + #sigh engine/client/pr_skelobj.c engine/client/m_download.c @@ -740,7 +831,7 @@ FIND_PATH(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h) FIND_PATH(AVFORMAT_INCLUDE_DIR libavformat/avformat.h) FIND_PATH(AVUTIL_INCLUDE_DIR libavutil/avutil.h) FIND_PATH(AVSWSCALE_INCLUDE_DIR libswscale/swscale.h) -IF(AVFORMAT_INCLUDE_DIR) +IF((AVFORMAT_INCLUDE_DIR) AND (AVSWSCALE_INCLUDE_DIR)) FIND_LIBRARY(AVCODEC_LIBRARY avcodec) FIND_LIBRARY(AVFORMAT_LIBRARY avformat) FIND_LIBRARY(AVUTIL_LIBRARY avutil) diff --git a/engine/Makefile b/engine/Makefile index ffe075228..fc192b1d9 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -2242,7 +2242,12 @@ $(RELEASE_DIR)/iqm$(BITS): $(IQM_OBJECTS) $(CC) -o $(RELEASE_DIR)/iqm$(BITS) $(IQM_OBJECTS) -lstdc++ -lm iqm: $(RELEASE_DIR)/iqm$(BITS) -utils: httpserver iqm +MASTER_OBJECTS=server/sv_sys_unix.c common/sys_linux_threads.c common/net_ssl_gnutls.c server/sv_master.c common/net_wins.c common/cvar.c common/cmd.c common/sha1.c http/httpclient.c common/log.c common/fs.c common/fs_stdio.c common/common.c common/translate.c common/zone.c qclib/hash.c +$(RELEASE_DIR)/ftemaster$(BITS): $(MASTER_OBJECTS) + $(CC) -o $(RELEASE_DIR)/master$(BITS) $(MASTER_OBJECTS) -Icommon -Iclient -Iqclib -Igl -Iserver -DMASTERONLY -Dstricmp=strcasecmp -Dstrnicmp=strncasecmp -lm -ldl +master: $(RELEASE_DIR)/ftemaster$(BITS) + +utils: httpserver iqm master prefix ?= /usr/local exec_prefix ?= $(prefix) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index d2e020ad4..5d39939e6 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -45,6 +45,7 @@ static cvar_t cl_iDrive = CVARFD("cl_iDrive", "1", CVAR_SEMICHEAT, "Effectively cvar_t cl_run = CVARD("cl_run", "0", "Enables autorun, inverting the state of the +speed key."); cvar_t cl_fastaccel = CVARD("cl_fastaccel", "1", "Begin moving at full speed instantly, instead of waiting a frame or so."); extern cvar_t cl_rollspeed; +static cvar_t cl_sendchatstate = CVARD("cl_sendchatstate", "1", "Announce your chat state to the server in a privacy-violating kind of way. This allows other players to see your afk/at-console status."); cvar_t cl_prydoncursor = CVAR("cl_prydoncursor", ""); //for dp protocol cvar_t cl_instantrotate = CVARF("cl_instantrotate", "1", CVAR_SEMICHEAT); @@ -1811,10 +1812,17 @@ qboolean CLQW_SendCmd (sizebuf_t *buf, qboolean actuallysend) if (!clientcount) clientcount = 1; - chatstate = 0; - chatstate |= Key_Dest_Has(~kdm_game)?1:0; - chatstate |= vid.activeapp?0:2; + if (cl_sendchatstate.ival) + { + if (Key_Dest_Has(kdm_message|kdm_console|kdm_cwindows)) + chatstate |= 1; //chatting + else if (Key_Dest_Has(~(kdm_game|kdm_centerprint))) + chatstate |= 2; //afk. ezquake sends chatting, but neither are really appropriate. + if (!vid.activeapp || vid.isminimized) + chatstate |= 2; //afk. + //FIXME: flag as afk if no new inputs for a while. + } for (plnum = 0; plnumFont_CharVHeight(font_default))?font_console:font_default; - Font_BeginString(font_default, ((x<0)?vid.width:x), ((y<0)?vid.height - sb_lines:y), &px, &py); + Font_BeginString(font, ((x<0)?vid.width:x), ((y<0)?vid.height - sb_lines:y), &px, &py); if (x < 0) { @@ -1664,7 +1666,7 @@ void SCR_StringXY(const char *str, float x, float y) codepoint = unicode_decode(&error, str, &str, true); px = Font_DrawChar(px, py, CON_WHITEMASK, codepoint); } - Font_EndString(font_default); + Font_EndString(font); } /* diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 53cb6e884..5325976b1 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -282,9 +282,11 @@ sfx_t *cl_sfx_r_exp3; cvar_t cl_expsprite = CVARFD("cl_expsprite", "1", CVAR_ARCHIVE, "Display a central sprite in explosion effects. QuakeWorld typically does so, NQ mods should not (which is problematic when played with the qw protocol)."); cvar_t r_explosionlight = CVARFC("r_explosionlight", "1", CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback); cvar_t cl_truelightning = CVARF("cl_truelightning", "0", CVAR_SEMICHEAT); -cvar_t cl_beam_trace = CVAR("cl_beam_trace", "0"); -cvar_t cl_legacystains = CVARD("cl_legacystains", "1", "WARNING: this cvar will default to 0 and later removed at some point"); //FIXME: do as the description says! -cvar_t cl_shaftlight = {"gl_shaftlight", "0.8"}; +static cvar_t cl_beam_trace = CVAR("cl_beam_trace", "0"); +static cvar_t cl_legacystains = CVARD("cl_legacystains", "1", "WARNING: this cvar will default to 0 and later removed at some point"); //FIXME: do as the description says! +static cvar_t cl_shaftlight = CVAR("gl_shaftlight", "0.8"); +static cvar_t cl_part_density_fade_start = CVARD("cl_part_density_fade_start", "1024", "Specifies the distance at which ssqc's pointparticles will start to get less dense."); +static cvar_t cl_part_density_fade = CVARD("cl_part_density_fade", "1024", "Specifies the distance over which ssqc pointparticles density fades from all to none. If this is set to 0 then particles will spawn at their normal density regardless of location on the map."); typedef struct { sfx_t **sfx; @@ -412,6 +414,9 @@ void CL_InitTEnts (void) Cvar_Register (&r_explosionlight, "Temporary entity control"); Cvar_Register (&cl_legacystains, "Temporary entity control"); Cvar_Register (&cl_shaftlight, "Temporary entity control"); + + Cvar_Register (&cl_part_density_fade_start, "Temporary entity control"); + Cvar_Register (&cl_part_density_fade, "Temporary entity control"); } void CL_ShutdownTEnts (void) @@ -2264,7 +2269,8 @@ void CL_ParseTrailParticles(void) void CL_ParsePointParticles(qboolean compact) { vec3_t org, dir; - unsigned int count, effectindex; + unsigned int effectindex; + float count; effectindex = (unsigned short)MSG_ReadShort(); org[0] = MSG_ReadCoord(); @@ -2285,6 +2291,21 @@ void CL_ParsePointParticles(qboolean compact) effectindex = CL_TranslateParticleFromServer(effectindex); + if (cl.splitclients <= 1 && cl_part_density_fade.value > 0) + { + vec3_t move; + float dist; + VectorSubtract(org, cl.playerview[0].audio.origin, move); + dist = VectorLength(move); + if (dist > cl_part_density_fade_start.value) + { + dist -= cl_part_density_fade_start.value; + count = count - dist/cl_part_density_fade.value; + if (count < 0) + return; + } + } + if (P_RunParticleEffectType(org, dir, count, effectindex)) P_RunParticleEffect (org, dir, 15, 15); } diff --git a/engine/client/client.h b/engine/client/client.h index 71078ece8..b8e20aa06 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1270,7 +1270,7 @@ void CL_ParseQTVFile(vfsfile_t *f, const char *fname, qtvfile_t *result); // #define NET_TIMINGS 256 #define NET_TIMINGSMASK 255 -extern int packet_latency[NET_TIMINGS]; +extern float packet_latency[NET_TIMINGS]; int CL_CalcNet (float scale); void CL_CalcNet2 (float *pings, float *pings_min, float *pings_max, float *pingms_stddev, float *pingfr, int *pingfr_min, int *pingfr_max, float *dropped, float *choked, float *invalid); void CL_ClearParseState(void); @@ -1621,6 +1621,8 @@ void Editor_Draw(void); void Editor_Init(void); struct pubprogfuncs_s; void Editor_ProgsKilled(struct pubprogfuncs_s *dead); +#else +#define editormodal false #endif void SCR_StringToRGB (char *rgbstring, float *rgb, float rgbinputscale); diff --git a/engine/client/console.c b/engine/client/console.c index b96eec920..bb1e77d1d 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -635,7 +635,7 @@ void Con_ToggleConsole_f (void) } #ifdef CSQC_DAT - if (!(key_dest_mask & kdm_editor) && CSQC_ConsoleCommand(-1, "toggleconsole")) + if (!editormodal && CSQC_ConsoleCommand(-1, "toggleconsole")) { Key_Dest_Remove(kdm_console); return; @@ -2171,7 +2171,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in for (; l; l = l->older) { shader_t *pic = NULL; - int picw=0, pich=0; + float picw=0, pich=0; s = (conchar_t*)(l+1); if (lineagelimit) @@ -2202,23 +2202,59 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in imgname = Info_ValueForKey(linkinfo, "img"); if (*imgname) { - pic = R_RegisterPic(imgname, NULL); + char *fl = Info_ValueForKey(linkinfo, "imgtype"); + if (*fl) + pic = R_RegisterCustom(imgname, atoi(fl), NULL, NULL); + else + pic = R_RegisterPic(imgname, NULL); if (pic) { - imgname = Info_ValueForKey(linkinfo, "w"); + imgname = Info_ValueForKey(linkinfo, "s"); if (*imgname) - picw = (atoi(imgname) * charh) / 8.0; - else if (pic->width) - picw = (pic->width * vid.pixelwidth) / vid.width; + { + if (pic->width <= 0 || pic->height <= 0) + picw = pich = 64; + else if (pic->width > pic->height) + { + picw = atof(imgname); + pich = picw * (float)pic->height/pic->width; + } + else + { + pich = atof(imgname); + picw = pich * (float)pic->width/pic->height; + } + } else - picw = 64; - imgname = Info_ValueForKey(linkinfo, "h"); - if (*imgname) - pich = (atoi(imgname) * charh) / 8.0; - else if (pic->height) - pich = (pic->height * vid.pixelheight) / vid.height; - else - pich = 64; + { + imgname = Info_ValueForKey(linkinfo, "w"); + if (*imgname) + picw = atof(imgname); + else + picw = -1; + imgname = Info_ValueForKey(linkinfo, "h"); + if (*imgname) + pich = atof(imgname); + else + pich = -1; + + if (picw<0 && pich<0) + { + if (pic->width && pic->height) + { + pich = (pic->height * vid.pixelheight) / vid.height; + picw = (pic->width * vid.pixelwidth) / vid.width; + } + else + picw = pich = 64; + } + else if (picw<0) + picw = pich * (float)pic->width/pic->height; + else if (pich<0) + pich = picw * (float)pic->height/pic->width; + } + picw *= charh/8.0; + pich *= charh/8.0; if (picw >= ex-sx) { @@ -2799,9 +2835,16 @@ void Con_DrawConsole (int lines, qboolean noback) if (!Plug_ConsoleLinkMouseOver(mousecursor_x, mousecursor_y, mouseover+2, info)) #endif { - char *key = Info_ValueForKey(info, "tipimg"); + char *key; + key = Info_ValueForKey(info, "tipimg"); if (*key) - shader = R2D_SafeCachePic(key); + { + char *fl = Info_ValueForKey(info, "tipimgtype"); + if (*fl) + shader = R_RegisterCustom(key, atoi(fl), NULL, NULL); + else + shader = R2D_SafeCachePic(key); + } else { key = Info_ValueForKey(info, "tiprawimg"); diff --git a/engine/client/keys.c b/engine/client/keys.c index cafbc9337..46841ba34 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -2597,7 +2597,7 @@ void Key_Init (void) key_linepos = 0; key_dest_mask = kdm_game; - key_dest_absolutemouse = kdm_centerprint | kdm_console | kdm_editor | kdm_cwindows | kdm_emenu; + key_dest_absolutemouse = kdm_centerprint | kdm_console | kdm_cwindows | kdm_emenu; // // init ascii characters in console mode @@ -2700,15 +2700,6 @@ qboolean Key_MouseShouldBeFree(void) if (key_dest_absolutemouse & key_dest_mask) return true; - if (Key_Dest_Has(kdm_editor)) - return true; - -// if (!vid.activeapp) -// return true; - - if (Key_Dest_Has(kdm_emenu)) - return true; - #ifdef VM_UI if (UI_MenuState()) return false; @@ -2837,7 +2828,7 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down if (!down) { #ifdef MENU_DAT - if (Key_Dest_Has(kdm_gmenu) && !Key_Dest_Has(kdm_editor|kdm_console|kdm_cwindows)) + if (Key_Dest_Has(kdm_gmenu) && !Key_Dest_Has(kdm_console|kdm_cwindows)) MP_Keyup (key, unicode, devid); #endif #ifdef MENU_NATIVECODE @@ -2865,10 +2856,6 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down if (!cls.state && !Key_Dest_Has(~kdm_game) && !Media_PlayingFullScreen()) M_ToggleMenu_f (); } -#ifdef TEXTEDITOR - else if (Key_Dest_Has(kdm_editor)) - Editor_Key (key, unicode); -#endif else if (Key_Dest_Has(kdm_emenu)) M_Keydown (key, unicode); #ifdef MENU_NATIVECODE @@ -3019,13 +3006,6 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down return; } #endif -#ifdef TEXTEDITOR - if (Key_Dest_Has(kdm_editor)) - { - Editor_Key (key, unicode); - return; - } -#endif #ifdef VM_UI if (!Key_Dest_Has(~kdm_game) || !down) { diff --git a/engine/client/keys.h b/engine/client/keys.h index c55045e57..53ee21f90 100644 --- a/engine/client/keys.h +++ b/engine/client/keys.h @@ -257,9 +257,8 @@ typedef enum //highest has priority kdm_nmenu = 0, #endif kdm_emenu = 1u<<5, //engine's menus - kdm_editor = 1u<<6, - kdm_console = 1u<<7, - kdm_cwindows = 1u<<8, + kdm_console = 1u<<6, + kdm_cwindows = 1u<<7, } keydestmask_t; //unsigned int Key_Dest_Get(void); //returns highest priority destination diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 83c9e6ef0..29d103360 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -630,6 +630,7 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c char mirror[countof(p->mirror)][MAX_OSPATH]; int nummirrors = 0; int argc; + qboolean isauto; if (!f) return; @@ -729,6 +730,7 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c } continue; } + isauto = false; if (version > 1) { char pathname[256]; @@ -815,6 +817,8 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c flags &= ~DPF_ENABLED; //known about, (probably) cached, but not actually enabled. else if (!strncmp(arg, "installed=", 6) && version>2) flags |= parseflags & DPF_ENABLED; + else if (!strcmp(arg, "auto")) + isauto = true; //autoinstalled and NOT user-installed else if (!strncmp(arg, "root=", 5) && (parseflags&DPF_ENABLED)) { if (!Q_strcasecmp(arg+5, "bin")) @@ -974,7 +978,12 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c } } if (p->flags & DPF_ENABLED) - p->flags |= DPF_USERMARKED; //FIXME: we don't know if this was manual or auto + { + if (isauto) + p->flags |= DPF_AUTOMARKED; //FIXME: we don't know if this was manual or auto + else + p->flags |= DPF_USERMARKED; //FIXME: we don't know if this was manual or auto + } PM_InsertPackage(p); } @@ -1899,6 +1908,12 @@ static void PM_WriteInstalledPackages(void) COM_QuotedConcat("test=1", buf, sizeof(buf)); } + if ((p->flags & DPF_AUTOMARKED) && !(p->flags & DPF_USERMARKED)) + { + Q_strncatz(buf, " ", sizeof(buf)); + COM_QuotedConcat("auto", buf, sizeof(buf)); + } + buf[sizeof(buf)-2] = 0; //just in case. Q_strncatz(buf, "\n", sizeof(buf)); VFS_WRITE(f, buf, strlen(buf)); @@ -2986,61 +3001,85 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) #ifdef WEBCLIENT if (p->download) - Draw_FunString (x+4, y, va("%i", (int)p->download->qdownload.percent)); + Draw_FunStringWidth (x, y, va("%i%%", (int)p->download->qdownload.percent), 48, 2, false); else if (p->trymirrors) - Draw_FunString (x+4, y, "PND"); + Draw_FunStringWidth (x, y, "PND", 48, 2, false); else #endif { - if (!(p->flags & DPF_MARKED)) + if (p->flags & DPF_USERMARKED) { if (!(p->flags & DPF_ENABLED)) - { //!DPF_MARKED|!DPF_ENABLED: + { //DPF_MARKED|!DPF_ENABLED: if (p->flags & DPF_PURGE) - Draw_FunString (x, y, "DEL"); //purge - else if (p->flags & DPF_HIDDEN) - Draw_FunString (x+4, y, "---"); - else if (p->flags & DPF_CORRUPT) - Draw_FunString (x, y, "!!!"); + Draw_FunStringWidth (x, y, "GET", 48, 2, false); + else if (p->flags & (DPF_PRESENT)) + Draw_FunStringWidth (x, y, "USE", 48, 2, false); else - { - Draw_FunString (x+4, y, "^Ue080^Ue082"); - Draw_FunString (x+8, y, "^Ue081"); - if (p->flags & DPF_PRESENT) - Draw_FunString (x+8, y, "-"); - } + Draw_FunStringWidth (x, y, "GET", 48, 2, false); } else - { //!DPF_MARKED|DPF_ENABLED: - if ((p->flags & DPF_PURGE) || PM_PurgeOnDisable(p)) - Draw_FunString (x, y, "DEL"); + { //DPF_MARKED|DPF_ENABLED: + if (p->flags & DPF_PURGE) + Draw_FunStringWidth (x, y, "GET", 48, 2, false); //purge and reinstall. + else if (p->flags & DPF_CORRUPT) + Draw_FunStringWidth (x, y, "?""?""?", 48, 2, false); else - Draw_FunString (x, y, "REM"); + { + Draw_FunStringWidth (x, y, "^Ue080^Ue082", 48, 2, false); + Draw_FunStringWidth (x, y, "^Ue083", 48, 2, false); + } + } + } + else if (p->flags & DPF_MARKED) + { + if (!(p->flags & DPF_ENABLED)) + { //DPF_MARKED|!DPF_ENABLED: + if (p->flags & DPF_PURGE) + Draw_FunStringWidth (x, y, "^hGET", 48, 2, false); + else if (p->flags & (DPF_PRESENT)) + Draw_FunStringWidth (x, y, "^hUSE", 48, 2, false); + else + Draw_FunStringWidth (x, y, "^hGET", 48, 2, false); + } + else + { //DPF_MARKED|DPF_ENABLED: + if (p->flags & DPF_PURGE) + Draw_FunStringWidth (x, y, "^hGET", 48, 2, false); //purge and reinstall. + else if (p->flags & DPF_CORRUPT) + Draw_FunStringWidth (x, y, "?""?""?", 48, 2, false); + else + { + Draw_FunStringWidth (x, y, "^Ue080^Ue082", 48, 2, false); + Draw_FunStringWidth (x, y, "^Ue083", 48, 2, false); + } } } else { if (!(p->flags & DPF_ENABLED)) - { //DPF_MARKED|!DPF_ENABLED: + { //!DPF_MARKED|!DPF_ENABLED: if (p->flags & DPF_PURGE) - Draw_FunString (x, y, "GET"); - else if (p->flags & (DPF_PRESENT)) - Draw_FunString (x, y, "USE"); - else - Draw_FunString (x, y, "GET"); - } - else - { //DPF_MARKED|DPF_ENABLED: - if (p->flags & DPF_PURGE) - Draw_FunString (x, y, "GET"); //purge and reinstall. + Draw_FunStringWidth (x, y, "DEL", 48, 2, false); //purge + else if (p->flags & DPF_HIDDEN) + Draw_FunStringWidth (x, y, "---", 48, 2, false); else if (p->flags & DPF_CORRUPT) - Draw_FunString (x, y, "?""?""?"); + Draw_FunStringWidth (x, y, "!!!", 48, 2, false); else { - Draw_FunString (x+4, y, "^Ue080^Ue082"); - Draw_FunString (x+8, y, "^Ue083"); + Draw_FunStringWidth (x, y, "^Ue080^Ue082", 48, 2, false); + Draw_FunStringWidth (x, y, "^Ue081", 48, 2, false); + if (p->flags & DPF_PRESENT) + Draw_FunStringWidth (x, y, "-", 48, 2, false); } } + else + { //!DPF_MARKED|DPF_ENABLED: + if ((p->flags & DPF_PURGE) || PM_PurgeOnDisable(p)) + Draw_FunStringWidth (x, y, "DEL", 48, 2, false); + else + Draw_FunStringWidth (x, y, "REM", 48, 2, false); + } } } @@ -3053,9 +3092,9 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) // if (!(p->flags & (DPF_ENABLED|DPF_MARKED|DPF_PRESENT)) // continue; - if (&m->selecteditem->common == &c->common) - Draw_AltFunString (x+48, y, n); - else +// if (&m->selecteditem->common == &c->common) +// Draw_AltFunString (x+48, y, n); +// else Draw_FunString(x+48, y, n); } } @@ -3106,8 +3145,10 @@ static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key, unsig PM_MarkPackage(p, DPF_USERMARKED); //now: try to install break; + case DPF_AUTOMARKED: // + p->flags |= DPF_USERMARKED; + break; case DPF_USERMARKED: - case DPF_AUTOMARKED: case DPF_MARKED: p->flags |= DPF_PURGE; //now: re-get despite already having it. @@ -3174,11 +3215,11 @@ static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct men }; char *text; int setting = bound(0, pm_autoupdate.ival, 2); - text = va("Auto Update: %s", settings[setting]); - if (&m->selecteditem->common == &c->common) - Draw_AltFunString (x+4, y, text); - else - Draw_FunString (x+4, y, text); + text = va("Auto Update: ^a%s", settings[setting]); +// if (&m->selecteditem->common == &c->common) +// Draw_AltFunString (x, y, text); +// else + Draw_FunString (x, y, text); } static qboolean MD_AutoUpdate_Key (struct menucustom_s *c, struct menu_s *m, int key, unsigned int unicode) { @@ -3236,88 +3277,24 @@ static qboolean MD_RevertUpdates (union menuoption_s *mo,struct menu_s *m,int ke return false; } -static void MD_AddItemsToDownloadMenu(menu_t *m) +static int MD_AddItemsToDownloadMenu(menu_t *m, int y, const char *pathprefix) { char path[MAX_QPATH]; - int y; package_t *p; menucustom_t *c; char *slash; menuoption_t *mo; - dlmenu_t *info = m->data; - int prefixlen; - p = availablepackages; + int prefixlen = strlen(pathprefix); - prefixlen = strlen(info->pathprefix); - y = 48; - - MC_AddCommand(m, 0, 170, y, "Apply", MD_ApplyDownloads)->common.tooltip = "Enable/Disable/Download/Delete packages to match any changes made (you will be prompted with a list of the changes that will be made)."; - y+=8; - MC_AddCommand(m, 0, 170, y, "Back", MD_PopMenu); - y+=8; - if (!prefixlen) - { -#ifdef WEBCLIENT - MC_AddCommand(m, 0, 170, y, "Mark Updates", MD_MarkUpdatesButton)->common.tooltip = "Select any updated versions of packages that are already installed."; - y+=8; -#endif - - MC_AddCommand(m, 0, 170, y, "Revert Updates", MD_RevertUpdates)->common.tooltip = "Reset selection to only those packages that are currently installed."; - y+=8; - -#ifdef WEBCLIENT - c = MC_AddCustom(m, 0, y, p, 0); - c->draw = MD_AutoUpdate_Draw; - c->key = MD_AutoUpdate_Key; - c->common.width = 320; - c->common.height = 8; - y += 8; -#endif - } - - y+=4; //small gap + //add all packages in this dir for (p = availablepackages; p; p = p->next) { - if (strncmp(p->category, info->pathprefix, prefixlen)) + if (strncmp(p->category, pathprefix, prefixlen)) continue; if ((p->flags & DPF_HIDDEN) && (p->arch || !(p->flags & DPF_ENABLED))) continue; -// if (p->flags & DPF_TESTING) //hide testing updates -// if (!(p->flags & (DPF_ENABLED|DPF_MARKED|DPF_PRESENT)) -// continue; - slash = strchr(p->category+prefixlen, '/'); - if (slash) - { - Q_strncpyz(path, p->category, MAX_QPATH); - slash = strchr(path+prefixlen, '/'); - if (slash) - *slash = '\0'; - - for (mo = m->options; mo; mo = mo->common.next) - if (mo->common.type == mt_button) - if (!strcmp(mo->button.text+1, path + prefixlen)) - break; - if (!mo) - { - package_t *s; - menubutton_t *b; - for (s = availablepackages; s; s = s->next) - { - if (!strncmp(s->category, info->pathprefix, slash-path) || s->category[slash-path] != '/') - continue; - if (!(s->flags & DPF_ENABLED) != !(s->flags & DPF_MARKED)) - break; - } - - b = MC_AddConsoleCommand(m, 6*8, 170, y, va("%s%s", s?"!":" ", path+prefixlen), va("menu_download \"%s/\"", path)); - y += 8; - - if (!m->selecteditem) - m->selecteditem = (menuoption_t*)b; - } - } - else + if (!slash) { c = MC_AddCustom(m, 0, y, p, downloadablessequence); c->draw = MD_Draw; @@ -3331,16 +3308,59 @@ static void MD_AddItemsToDownloadMenu(menu_t *m) m->selecteditem = (menuoption_t*)c; } } + + //and then try to add any subdirs... + for (p = availablepackages; p; p = p->next) + { + if (strncmp(p->category, pathprefix, prefixlen)) + continue; + if ((p->flags & DPF_HIDDEN) && (p->arch || !(p->flags & DPF_ENABLED))) + continue; + + slash = strchr(p->category+prefixlen, '/'); + if (slash) + { + Q_strncpyz(path, p->category, MAX_QPATH); + slash = strchr(path+prefixlen, '/'); + if (slash) + *slash = '\0'; + + for (mo = m->options; mo; mo = mo->common.next) + if (mo->common.type == mt_text/*mt_button*/) + if (!strcmp(mo->button.text, path + prefixlen)) + break; + if (!mo) + { + package_t *s; + for (s = availablepackages; s; s = s->next) + { + if (!strncmp(s->category, pathprefix, slash-path) || s->category[slash-path] != '/') + continue; + if (!(s->flags & DPF_ENABLED) != !(s->flags & DPF_MARKED)) + break; + } + + y += 8; + MC_AddBufferedText(m, 48, 320, y, path+prefixlen, false, true); + y += 8; + Q_strncatz(path, "/", sizeof(path)); + y = MD_AddItemsToDownloadMenu(m, y, path); + } + } + } + return y; } #include "shader.h" static void MD_Download_UpdateStatus(struct menu_s *m) { dlmenu_t *info = m->data; - int i; + int i, y; package_t *p; unsigned int totalpackages=0, selectedpackages=0, addpackages=0, rempackages=0, downloads=0; menuoption_t *si; + menubutton_t *b, *d; + menucustom_t *c; if (info->downloadablessequence != downloadablessequence || !info->populated) { @@ -3427,7 +3447,39 @@ static void MD_Download_UpdateStatus(struct menu_s *m) } info->populated = true; - MD_AddItemsToDownloadMenu(m); + MC_AddFrameStart(m, 48); + y = 48; + b = MC_AddCommand(m, 48, 170, y, "Apply", MD_ApplyDownloads); + b->rightalign = false; + b->common.tooltip = "Enable/Disable/Download/Delete packages to match any changes made (you will be prompted with a list of the changes that will be made)."; + y+=8; + d = b = MC_AddCommand(m, 48, 170, y, "Back", MD_PopMenu); + b->rightalign = false; + y+=8; +#ifdef WEBCLIENT + b = MC_AddCommand(m, 48, 170, y, "Mark Updates", MD_MarkUpdatesButton); + b->rightalign = false; + b->common.tooltip = "Select any updated versions of packages that are already installed."; + y+=8; +#endif + b = MC_AddCommand(m, 48, 170, y, "Revert Updates", MD_RevertUpdates); + b->rightalign = false; + b->common.tooltip = "Reset selection to only those packages that are currently installed."; + y+=8; +#ifdef WEBCLIENT + c = MC_AddCustom(m, 48, y, p, 0); + c->draw = MD_AutoUpdate_Draw; + c->key = MD_AutoUpdate_Key; + c->common.width = 320; + c->common.height = 8; + y += 8; +#endif + y+=4; //small gap + MD_AddItemsToDownloadMenu(m, y, info->pathprefix); + if (!m->selecteditem) + m->selecteditem = (menuoption_t*)d; + m->cursoritem = (menuoption_t*)MC_AddWhiteText(m, 40, 0, m->selecteditem->common.posy, NULL, false); + MC_AddFrameEnd(m, 48); } si = m->mouseitem; diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 33c79f90f..064828b3a 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -306,7 +306,9 @@ static qboolean MI_Selectable(menuoption_t *op) return true; case mt_picture: return false; - case mt_childwindow: + case mt_framestart: + return false; + case mt_frameend: return true; case mt_box: return false; @@ -329,42 +331,67 @@ static qboolean MI_Selectable(menuoption_t *op) static qboolean M_MouseMoved(menu_t *menu) { + int ypos = menu->ypos, framescroll = 0; menuoption_t *option; // if (menu->prev && !menu->exclusive) // if (M_MouseMoved(menu->prev)) // return true; + if (bindingactive) + return true; for(option = menu->options; option; option = option->common.next) { - if (mousemoved && !bindingactive && !option->common.ishidden) + if (option->common.ishidden) + continue; + + if (mousecursor_x > menu->xpos+option->common.posx-option->common.extracollide && mousecursor_x < menu->xpos+option->common.posx+option->common.width) { - if (mousecursor_x > menu->xpos+option->common.posx-option->common.extracollide && mousecursor_x < menu->xpos+option->common.posx+option->common.width) + if (mousecursor_y > ypos+option->common.posy && mousecursor_y < ypos+option->common.posy+option->common.height) { - if (mousecursor_y > menu->ypos+option->common.posy && mousecursor_y < menu->ypos+option->common.posy+option->common.height) + if (MI_Selectable(option)) { - if (MI_Selectable(option)) + if (menu->mouseitem != option) { - if (menu->mouseitem != option) +/* if (!option->common.noselectionsound && vid.activeapp) { -/* if (!option->common.noselectionsound && vid.activeapp) - { #ifdef HEXEN2 - if (M_GameType() == MGT_HEXEN2) - S_LocalSound ("raven/menu1.wav"); - else + if (M_GameType() == MGT_HEXEN2) + S_LocalSound ("raven/menu1.wav"); + else #endif - S_LocalSound ("misc/menu1.wav"); - } -*/ - menu->mouseitem = option; - menu->tooltiptime = realtime + 1; - MenuTooltipChange(menu, menu->mouseitem->common.tooltip); + S_LocalSound ("misc/menu1.wav"); } -// if (menu->cursoritem) -// menu->cursoritem->common.posy = menu->selecteditem->common.posy; +*/ + menu->mouseitem = option; + menu->tooltiptime = realtime + 1; + MenuTooltipChange(menu, menu->mouseitem->common.tooltip); } +// if (menu->cursoritem) +// menu->cursoritem->common.posy = menu->selecteditem->common.posy; } } } + + switch(option->common.type) + { + case mt_framestart: + ypos += framescroll; + framescroll = 0; + break; + case mt_frameend: + { + menuoption_t *opt2; + int maxy = option->frame.common.posy; + for (opt2 = option->common.next; opt2; opt2 = opt2->common.next) + { + if (opt2->common.posy + opt2->common.height > maxy) + maxy = opt2->common.posy + opt2->common.height; + } + maxy -= vid.height-8; + framescroll += option->frame.frac * maxy; + ypos -= option->frame.frac * maxy; + } + break; + } } return true; } @@ -382,11 +409,67 @@ static void M_CheckMouseMove(void) M_MouseMoved(topmenu); } +static float M_DrawScrollbar(int x, int y, int width, int height, float frac, qboolean mgrabbed) +{ + float unused = 0; + mpic_t *pic; + int knob=y; + + R2D_ImageColours(1,1,1,1); + + pic = R2D_SafeCachePic("scrollbars/slidebg.tga"); + if (pic && R_GetShaderSizes(pic, NULL, NULL, false)>0) + { + unused = 8*2+64; //top+bottom are 8 pixels, knob is 64 + R2D_ScalePic(x + width - 8, y+8, 8, height-16, pic); + + pic = R2D_SafeCachePic("scrollbars/arrow_up.tga"); + R2D_ScalePic(x + width - 8, y, 8, 8, pic); + + pic = R2D_SafeCachePic("scrollbars/arrow_down.tga"); + R2D_ScalePic(x + width - 8, y + height - 8, 8, 8, pic); + + knob += 8; + knob += frac * (float)(height-(unused)); + + pic = R2D_SafeCachePic("scrollbars/slider.tga"); + R2D_ScalePic(x + width - 8, knob, 8, 64, pic); + } + else + { + unused = width; //top+bottom are invisible, knob is square + R2D_ImageColours(0.1, 0.1, 0.2, 1.0); + R2D_FillBlock(x, y, width, height); + + knob += frac * (height-unused); + + R2D_ImageColours(0.35, 0.35, 0.55, 1.0); + R2D_FillBlock(x, knob, width, width); + R2D_ImageColours(1,1,1,1); + } + + if (mgrabbed) + { + float my; + + my = mousecursor_y - y; + my -= unused/2; + my /= height-unused; + if (my > 1) + my = 1; + if (my < 0) + my = 0; + frac = my; + } + return frac; +} + static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) { int i; mpic_t *p; int pw,ph; + int framescroll = 0; if (option && option->common.type == mt_box && !option->common.ishidden) { @@ -394,17 +477,18 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu option = option->common.next; } - if (menu == topmenu && menu->mouseitem) + for (; option; option = option->common.next) { - float alphamax = 0.5, alphamin = 0.2; - R2D_ImageColours(.5,.4,0,(sin(realtime*2)+1)*0.5*(alphamax-alphamin)+alphamin); - R2D_FillBlock(xpos+menu->mouseitem->common.posx, ypos+menu->mouseitem->common.posy, menu->mouseitem->common.width, menu->mouseitem->common.height); - R2D_ImageColours(1,1,1,1); - } + if (option->common.ishidden) + continue; - while (option) - { - if (!option->common.ishidden) + if (menu == topmenu && menu->mouseitem == option) + { + float alphamax = 0.5, alphamin = 0.2; + R2D_ImageColours(.5,.4,0,(sin(realtime*2)+1)*0.5*(alphamax-alphamin)+alphamin); + R2D_FillBlock(xpos+menu->mouseitem->common.posx, ypos+menu->mouseitem->common.posy, menu->mouseitem->common.width, menu->mouseitem->common.height); + R2D_ImageColours(1,1,1,1); + } switch(option->common.type) { case mt_menucursor: @@ -457,14 +541,66 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu p = R2D_SafeCachePic(option->picture.picturename); if (R_GetShaderSizes(p, &pw, &ph, false)>0) - R2D_ScalePic(xpos+option->common.posx, ypos+option->common.posy, option->common.width?option->common.width:pw, option->common.height?option->common.height:ph, p); + { + float scale = (option->common.height?option->common.height:20.0)/ph; + R2D_ScalePic(xpos+option->common.posx, ypos+option->common.posy, option->common.width?option->common.width:(pw*scale), ph*scale, p); + } break; case mt_picture: p = R2D_SafeCachePic(option->picture.picturename); if (R_GetShaderSizes(p, NULL, NULL, false)>0) R2D_ScalePic(xpos+option->common.posx, ypos+option->common.posy, option->common.width, option->common.height, p); break; - case mt_childwindow: - MenuDrawItems(xpos+option->common.posx, ypos+option->common.posy, ((menu_t *)option->custom.dptr)->options, (menu_t *)option->custom.dptr); + case mt_framestart: + ypos += framescroll; + framescroll = 0; + if (R2D_Flush) + R2D_Flush(); + BE_Scissor(NULL); + break; + case mt_frameend: + { + srect_t srect; + menuoption_t *opt2; + extern qboolean keydown[]; + int maxy = option->frame.common.posy; + option->frame.common.width = 16; + option->frame.common.posx = vid.width - option->frame.common.width - xpos; + option->frame.common.height = vid.height-8-maxy - ypos; + for (opt2 = option->common.next; opt2; opt2 = opt2->common.next) + { + if (opt2->common.posy + opt2->common.height > maxy) + maxy = opt2->common.posy + opt2->common.height; + } + maxy -= vid.height-8; + + if (maxy < 0) + { + option->frame.mousedown = false; + option->frame.frac = 0; + option->frame.common.width = 0; + option->frame.common.height = 0; + } + else + { + if (!keydown[K_MOUSE1]) + option->frame.mousedown = false; + option->frame.frac = M_DrawScrollbar(xpos+option->frame.common.posx, ypos+option->common.posy, option->frame.common.width, option->frame.common.height, option->frame.frac, option->frame.mousedown); + + if (R2D_Flush) + R2D_Flush(); + srect.x = 0; + srect.y = (float)(ypos+option->common.posy) / vid.height; + srect.width = 1; + srect.height = 1 - srect.y; + srect.dmin = -99999; + srect.dmax = 99999; + srect.y = (1-srect.y) - srect.height; + BE_Scissor(&srect); + + framescroll += option->frame.frac * maxy; + ypos -= option->frame.frac * maxy; + } + } break; case mt_box: Draw_TextBox(xpos+option->common.posx, ypos+option->common.posy, option->box.width, option->box.height); @@ -627,7 +763,6 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu Sys_Error("Bad item type\n"); break; } - option = option->common.next; } } @@ -773,7 +908,7 @@ menubind_t *MC_AddBind(menu_t *menu, int cx, int bx, int y, const char *caption, return n; } -menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, char *picname) +menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, int height, char *picname) { char selname[MAX_QPATH]; menupicture_t *n; @@ -793,6 +928,7 @@ menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, char *picname n->common.iszone = true; n->common.posx = x; n->common.posy = y; + n->common.height = height; n->picturename = (char *)(n+1); strcpy(n->picturename, picname); @@ -1066,6 +1202,34 @@ menucheck_t *MC_AddCheckBox(menu_t *menu, int tx, int cx, int y, const char *tex menu->options = (menuoption_t *)n; return n; } +menuframe_t *MC_AddFrameStart(menu_t *menu, int y) +{ + menuframe_t *n = Z_Malloc(sizeof(menuframe_t)); + n->common.type = mt_framestart; + n->common.iszone = true; + n->common.posx = 0; + n->common.posy = y; + n->common.height = 0; + n->common.width = 0; + + n->common.next = menu->options; + menu->options = (menuoption_t *)n; + return n; +} +menuframe_t *MC_AddFrameEnd(menu_t *menu, int y) +{ + menuframe_t *n = Z_Malloc(sizeof(menuframe_t)); + n->common.type = mt_frameend; + n->common.iszone = true; + n->common.posx = 0; + n->common.posy = y; + n->common.height = 0; + n->common.width = 0; + + n->common.next = menu->options; + menu->options = (menuoption_t *)n; + return n; +} menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int tx, int cx, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits) { menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1); @@ -2021,6 +2185,7 @@ void M_Menu_Main_f (void) { if (R_GetShaderSizes(R2D_SafeCachePic("pics/m_main_quit"), NULL, NULL, true) > 0) { + int itemheight = 32; Key_Dest_Add(kdm_emenu); mainm = M_CreateMenu(0); @@ -2029,19 +2194,19 @@ void M_Menu_Main_f (void) MC_AddPicture(mainm, 0, 4, 38, 166, "pics/m_main_plaque"); MC_AddPicture(mainm, 0, 173, 36, 42, "pics/m_main_logo"); #ifndef CLIENTONLY - MC_AddSelectablePicture(mainm, 68, 13, "pics/m_main_game"); + MC_AddSelectablePicture(mainm, 68, 13, itemheight, "pics/m_main_game"); #endif - MC_AddSelectablePicture(mainm, 68, 53, "pics/m_main_multiplayer"); - MC_AddSelectablePicture(mainm, 68, 93, "pics/m_main_options"); - MC_AddSelectablePicture(mainm, 68, 133, "pics/m_main_video"); - MC_AddSelectablePicture(mainm, 68, 173, "pics/m_main_quit"); + MC_AddSelectablePicture(mainm, 68, 53, itemheight, "pics/m_main_multiplayer"); + MC_AddSelectablePicture(mainm, 68, 93, itemheight, "pics/m_main_options"); + MC_AddSelectablePicture(mainm, 68, 133, itemheight, "pics/m_main_video"); + MC_AddSelectablePicture(mainm, 68, 173, itemheight, "pics/m_main_quit"); #ifndef CLIENTONLY b = MC_AddConsoleCommand (mainm, 68, 320, 13, "", "menu_single\n"); b->common.tooltip = "Singleplayer."; mainm->selecteditem = (menuoption_t *)b; b->common.width = 12*20; - b->common.height = 32; + b->common.height = itemheight; #endif b = MC_AddConsoleCommand (mainm, 68, 320, 53, "", "menu_multi\n"); b->common.tooltip = "Multiplayer."; @@ -2049,19 +2214,19 @@ void M_Menu_Main_f (void) mainm->selecteditem = (menuoption_t *)b; #endif b->common.width = 12*20; - b->common.height = 32; + b->common.height = itemheight; b = MC_AddConsoleCommand (mainm, 68, 320, 93, "", "menu_options\n"); b->common.tooltip = "Options."; b->common.width = 12*20; - b->common.height = 32; + b->common.height = itemheight; b = MC_AddConsoleCommand (mainm, 68, 320, 133, "", "menu_video\n"); b->common.tooltip = "Video Options."; b->common.width = 12*20; - b->common.height = 32; + b->common.height = itemheight; b = MC_AddConsoleCommand (mainm, 68, 320, 173, "", "menu_quit\n"); b->common.tooltip = "Quit to DOS."; b->common.width = 12*20; - b->common.height = 32; + b->common.height = itemheight; mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, &resel, 42, mainm->selecteditem->common.posy); } diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index f03d8fb06..1c54375b2 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -439,38 +439,34 @@ void M_Menu_Setup_f (void) #ifdef Q2CLIENT if (M_GameType() == MGT_QUAKE2) //quake2 main menu. { - if (R2D_SafeCachePic("pics/m_banner_player_setup")) + static const char *modeloptions[] = { - static const char *modeloptions[] = - { - "male", - "female", - NULL - }; - mpic_t *p; - menucustom_t *cu; - Key_Dest_Add(kdm_emenu); + "male", + "female", + NULL + }; + mpic_t *p; + menucustom_t *cu; + Key_Dest_Add(kdm_emenu); - menu = M_CreateMenu(sizeof(setupmenu_t)); - info = menu->data; -// menu->key = MC_Main_Key; + menu = M_CreateMenu(sizeof(setupmenu_t)); + info = menu->data; +// menu->key = MC_Main_Key; - MC_AddPicture(menu, 0, 4, 38, 166, "pics/m_main_plaque"); - p = R2D_SafeCachePic("pics/m_main_logo"); - if (!p) - return; - MC_AddPicture(menu, 0, 173, 36, 42, "pics/m_main_logo"); + MC_AddPicture(menu, 0, 4, 38, 166, "pics/m_main_plaque"); + MC_AddPicture(menu, 0, 173, 36, 42, "pics/m_main_logo"); - menu->selecteditem = (menuoption_t*) - (info->nameedit = MC_AddEdit(menu, 64, 160, 40, "Your name", name.string)); - (info->modeledit = MC_AddCvarCombo(menu, 64, 160,72, "model", &skin, (const char **)modeloptions, (const char **)modeloptions)); - info->modeledit->selectedoption = !strncmp(skin.string, "female", 6); - cu = MC_AddCustom(menu, 64, 88+16, NULL, 0); - cu->draw = MSetupQ2_TransDraw; - cu->key = MSetupQ2_ChangeSkin; + MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_player_setup"); - menu->cursoritem = (menuoption_t*)MC_AddCursorSmall(menu, &resel, 54, 32); - } + menu->selecteditem = (menuoption_t*) + (info->nameedit = MC_AddEdit(menu, 64, 160, 40, "Your name", name.string)); + (info->modeledit = MC_AddCvarCombo(menu, 64, 160,72, "model", &skin, (const char **)modeloptions, (const char **)modeloptions)); + info->modeledit->selectedoption = !strncmp(skin.string, "female", 6); + cu = MC_AddCustom(menu, 64, 88+16, NULL, 0); + cu->draw = MSetupQ2_TransDraw; + cu->key = MSetupQ2_ChangeSkin; + + menu->cursoritem = (menuoption_t*)MC_AddCursorSmall(menu, &resel, 54, 32); return; } #endif diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 57656b3f1..30513d69e 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -123,7 +123,6 @@ menu_t *M_Options_Title(int *y, int infosize) { case MGT_QUAKE2: //q2... MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_options"); - *y += 32; break; #ifdef HEXEN2 case MGT_HEXEN2://h2 @@ -325,6 +324,9 @@ void M_Menu_Options_f (void) }; menu_t *menu = M_Options_Title(&y, 0); static menuresel_t resel; + int framey = y; + + MC_AddFrameStart(menu, framey); y = MC_AddBulk(menu, &resel, bulk, 16, 216, y); #ifdef PLUGINS @@ -348,6 +350,7 @@ void M_Menu_Options_f (void) MC_AddCvarCombo(menu, 16, 216, y, "Use Hud Plugin", &plug_sbar, hudplugopts, hudplugvalues); y += 8; } #endif + MC_AddFrameEnd(menu, framey); } #ifndef __CYGWIN__ @@ -667,7 +670,9 @@ void M_Menu_Audio_f (void) MB_END() }; static menuresel_t resel; + MC_AddFrameStart(menu, y); MC_AddBulk(menu, &resel, bulk, 16, 216, y); + MC_AddFrameEnd(menu, y); } #else @@ -764,7 +769,9 @@ void M_Menu_Particles_f (void) static menuresel_t resel; menu = M_Options_Title(&y, 0); + MC_AddFrameStart(menu, y); MC_AddBulk(menu, &resel, bulk, 16, 200, y); + MC_AddFrameEnd(menu, y); } const char *presetname[] = @@ -1202,7 +1209,9 @@ void M_Menu_FPS_f (void) MB_EDITCVAR("Skybox", "r_skybox"), MB_END() }; + MC_AddFrameStart(menu, y); MC_AddBulk(menu, &resel, bulk, 16, 216, y); + MC_AddFrameEnd(menu, y); } } @@ -1263,7 +1272,9 @@ void M_Menu_Render_f (void) MB_END() }; menu = M_Options_Title(&y, 0); + MC_AddFrameStart(menu, y); MC_AddBulk(menu, &resel, bulk, 16, 216, y); + MC_AddFrameEnd(menu, y); } #ifdef GLQUAKE @@ -1359,7 +1370,9 @@ void M_Menu_Textures_f (void) }; menu_t *menu = M_Options_Title(&y, 0); static menuresel_t resel; + MC_AddFrameStart(menu, y); MC_AddBulk(menu, &resel, bulk, 16, 216, y); + MC_AddFrameEnd(menu, y); } #endif @@ -1656,7 +1669,9 @@ void M_Menu_Lighting_f (void) MB_END() }; static menuresel_t resel; + MC_AddFrameStart(menu, y); MC_AddBulk(menu, &resel, bulk, 16, 216, y); + MC_AddFrameEnd(menu, y); } } @@ -2881,7 +2896,30 @@ void M_Menu_Video_f (void) int y; int resmodechoice, res2dmodechoice; int reschoices[ASPECT_RATIOS], res2dchoices[ASPECT_RATIOS]; - menu_t *menu = M_Options_Title(&y, sizeof(videomenuinfo_t)); + menu_t *menu; + + //not calling M_Options_Title because of quake2's different banner. + y = 32; + Key_Dest_Add(kdm_emenu); + menu = M_CreateMenu(sizeof(videomenuinfo_t)); + switch(M_GameType()) + { + case MGT_QUAKE2: //q2... + MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_video"); + break; +#ifdef HEXEN2 + case MGT_HEXEN2://h2 + MC_AddPicture(menu, 16, 0, 35, 176, "gfx/menu/hplaque.lmp"); + MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title3.lmp"); + y += 32; + break; +#endif + default: //q1 + MC_AddPicture(menu, 16, 4, 32, 144, "gfx/qplaque.lmp"); + MC_AddCenterPicture(menu, 4, 24, "gfx/p_option.lmp"); + break; + } + info = (videomenuinfo_t*)menu->data; snprintf(current3dres, sizeof(current3dres), "Current: %ix%i", vid.pixelwidth, vid.pixelheight); @@ -2963,7 +3001,9 @@ void M_Menu_Video_f (void) MB_END() }; + MC_AddFrameStart(menu, y); MC_AddBulk(menu, &resel, bulk, 16, 200, y); + MC_AddFrameEnd(menu, y); } /* diff --git a/engine/client/m_script.c b/engine/client/m_script.c index a4308a493..8104d02f5 100644 --- a/engine/client/m_script.c +++ b/engine/client/m_script.c @@ -89,7 +89,6 @@ void M_MenuS_Clear_f (void) void M_MenuS_Script_f (void) //create a menu. { - extern menu_t *topmenu; int items; menu_t *oldmenu; char *alias = Cmd_Argv(1); diff --git a/engine/client/m_single.c b/engine/client/m_single.c index f0868562f..fabdbee9f 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -241,7 +241,18 @@ void M_Menu_Save_f (void) menu->remove = M_Menu_LoadSave_UnloadShaders; menu->reset = M_Menu_LoadSave_UnloadShaders; - MC_AddCenterPicture (menu, 4, 24, "gfx/p_save.lmp"); + switch(M_GameType()) + { +#ifdef Q2CLIENT + case MGT_QUAKE2: + MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_save_game.pcx"); + break; +#endif + default: + MC_AddCenterPicture(menu, 4, 24, "gfx/p_save.lmp"); + break; + } + menu->cursoritem = (menuoption_t *)MC_AddRedText(menu, 8, 0, 32, NULL, false); M_ScanSaves (); @@ -271,8 +282,18 @@ void M_Menu_Load_f (void) menu->data = menu+1; menu->remove = M_Menu_LoadSave_UnloadShaders; menu->reset = M_Menu_LoadSave_UnloadShaders; - - MC_AddCenterPicture(menu, 4, 24, "gfx/p_load.lmp"); + + switch(M_GameType()) + { +#ifdef Q2CLIENT + case MGT_QUAKE2: + MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_load_game.pcx"); + break; +#endif + default: + MC_AddCenterPicture(menu, 4, 24, "gfx/p_load.lmp"); + break; + } M_ScanSaves (); diff --git a/engine/client/menu.c b/engine/client/menu.c index 0e95cfb34..4558b3a97 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -530,7 +530,7 @@ void M_Menu_Keys_f (void) { #ifdef Q2CLIENT case MGT_QUAKE2: - //fixme: no art? + MC_AddCenterPicture(menu, 0, 60, "pics/m_banner_customize.pcx"); y = 48; bindnames = q2bindnames; break; @@ -606,13 +606,14 @@ void M_Menu_Keys_f (void) return; } + MC_AddFrameStart(menu, 48+8); while (bindnames->name) { MC_AddBind(menu, 16, 170, y, bindnames->name, bindnames->command, NULL); y += 8; - bindnames++; } + MC_AddFrameEnd(menu, 48+8); } void M_UnbindCommand (const char *command) @@ -1479,12 +1480,11 @@ void M_Draw (int uimenu) #endif #ifndef NOBUILTINMENUS - {extern menu_t *topmenu; if (topmenu) { M_Complex_Draw (); stillactive = true; - }} + } #endif if (!stillactive) Key_Dest_Remove(kdm_emenu); @@ -1497,7 +1497,12 @@ void M_Keydown (int key, int unicode) if (topmenu) { if (key == K_MOUSE1) //mouse clicks are deferred until the release event. this is for touch screens and aiming. - menu_mousedown = true; + { + if (topmenu->mouseitem->common.type == mt_frameend) + topmenu->mouseitem->frame.mousedown = true; + else + menu_mousedown = true; + } else if (key == K_LSHIFT || key == K_RSHIFT || key == K_LALT || key == K_RALT || key == K_LCTRL || key == K_RCTRL) ; //modifiers are sent on up events instead. else diff --git a/engine/client/menu.h b/engine/client/menu.h index 00230abaf..2907be0fe 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -120,7 +120,8 @@ struct menu_s; typedef enum { - mt_childwindow, + mt_framestart, + mt_frameend, mt_button, mt_qbuttonbigfont, mt_hexen2buttonbigfont, @@ -243,6 +244,13 @@ typedef struct { char *command; } menubind_t; +typedef struct { + menucommon_t common; + qboolean mousedown; + float frac; + union menuoption_s *suboptions; +} menuframe_t; + typedef union menuoption_s { menucommon_t common; menubutton_t button; @@ -255,6 +263,7 @@ typedef union menuoption_s { menubox_t box; menucheck_t check; menubind_t bind; + menuframe_t frame; } menuoption_t; typedef struct menutooltip_s { @@ -308,7 +317,7 @@ menutext_t *MC_AddWhiteText(menu_t *menu, int lhs, int rhs, int y, const char *t menubind_t *MC_AddBind(menu_t *menu, int cx, int bx, int y, const char *caption, char *command, char *tooltip); menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height); menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, int width, int height, char *picname); -menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, char *picname); +menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, int height, char *picname); menupicture_t *MC_AddCenterPicture(menu_t *menu, int y, int height, char *picname); menupicture_t *MC_AddCursor(menu_t *menu, menuresel_t *resel, int x, int y); menuoption_t *MC_AddCursorSmall(menu_t *menu, menuresel_t *reselection, int x, int y); @@ -326,6 +335,8 @@ menucombo_t *MC_AddCvarCombo(menu_t *menu, int tx, int cx, int y, const char *ca menuedit_t *MC_AddEdit(menu_t *menu, int cx, int ex, int y, char *text, char *def); menuedit_t *MC_AddEditCvar(menu_t *menu, int cx, int ex, int y, char *text, char *name, qboolean slim); menucustom_t *MC_AddCustom(menu_t *menu, int x, int y, void *dptr, int dint); +menuframe_t *MC_AddFrameStart(menu_t *menu, int y); //call before items are added +menuframe_t *MC_AddFrameEnd(menu_t *menu, int y); //and call AFTER that stuff with the same y. typedef struct menubulk_s { menutype_t type; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 347884b3c..88cd50272 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -22,8 +22,16 @@ extern unsigned int r2d_be_flags; #define DRAWFLAG_2D (1u<<2) #define DRAWFLAG_TWOSIDED 0x400 #define DRAWFLAG_LINES 0x800 -static unsigned int PF_SelectDPDrawFlag(int flag) +static unsigned int PF_SelectDPDrawFlag(pubprogfuncs_t *prinst, int flag) { + if (r_refdef.warndraw) + { + if (!*r_refdef.rt_destcolour[0].texname) + { + r_refdef.warndraw = false; //don't spam too much + PR_RunWarning(prinst, "Detected attempt to draw to framebuffer where framebuffer is not valid\n"); + } + } csqc_dp_lastwas3d = false; //for compat with dp's stupid beginpolygon //flags: @@ -47,7 +55,7 @@ void QCBUILTIN PF_CL_drawfill (pubprogfuncs_t *prinst, struct globalvars_s *pr_g float alpha = G_FLOAT(OFS_PARM3); int flag = prinst->callargc >= 5?G_FLOAT(OFS_PARM4):0; - r2d_be_flags = PF_SelectDPDrawFlag(flag); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag); R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha); R2D_FillBlock(pos[0], pos[1], size[0], size[1]); r2d_be_flags = 0; @@ -473,7 +481,7 @@ void QCBUILTIN PF_CL_drawcolouredstring (pubprogfuncs_t *prinst, struct globalva COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), false); str = buffer; - r2d_be_flags = PF_SelectDPDrawFlag(flag); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag); PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &px, &py); ipx = px; R2D_ImageColours(r, g, b, alpha); @@ -542,7 +550,7 @@ void QCBUILTIN PF_CL_drawpic (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl else G_FLOAT(OFS_RETURN) = 1; - r2d_be_flags = PF_SelectDPDrawFlag(flag); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag); R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha); if ((size[0] < 0) ^ (size[1] < 0)) R2D_Image(pos[0]+size[0], pos[1]+size[1], -size[0], -size[1], 1, 1, 0, 0, p); @@ -588,7 +596,7 @@ void QCBUILTIN PF_CL_drawrotpic (pubprogfuncs_t *prinst, struct globalvars_s *pr Vector2Set(tcoords[2], 1, 1); Vector2Set(tcoords[3], 0, 1); - r2d_be_flags = PF_SelectDPDrawFlag(flag); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag); R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha); R2D_Image2dQuad((const vec2_t*)points, (const vec2_t*)tcoords, NULL, p); r2d_be_flags = 0; @@ -613,7 +621,7 @@ void QCBUILTIN PF_CL_drawsubpic (pubprogfuncs_t *prinst, struct globalvars_s *pr if (!p || !R_GetShaderSizes(p, NULL, NULL, false)) p = R2D_SafePicFromWad(picname); - r2d_be_flags = PF_SelectDPDrawFlag(flag); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag); R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha); if ((size[0] < 0) ^ (size[1] < 0)) R2D_Image(pos[0]+size[0], pos[1]+size[1], -size[0], -size[1], srcPos[0]+srcSize[0], srcPos[1]+srcSize[1], srcPos[0], srcPos[1], p); @@ -660,7 +668,7 @@ void QCBUILTIN PF_CL_drawrotsubpic (pubprogfuncs_t *prinst, struct globalvars_s Vector2Set(tcoords[2], srcPos[0]+srcSize[0] , srcPos[1]+srcSize[1] ); Vector2Set(tcoords[3], srcPos[0] , srcPos[1]+srcSize[1] ); - r2d_be_flags = PF_SelectDPDrawFlag(flag); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag); R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha); R2D_Image2dQuad((const vec2_t*)points, (const vec2_t*)tcoords, NULL, p); r2d_be_flags = 0; @@ -836,7 +844,7 @@ void QCBUILTIN PF_CL_drawcharacter (pubprogfuncs_t *prinst, struct globalvars_s if (chara < 32 && chara != '\t') chara |= 0xe000; - r2d_be_flags = PF_SelectDPDrawFlag(flag); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag); PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y); R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha); Font_DrawScaleChar(x, y, CON_WHITEMASK, chara); @@ -866,7 +874,7 @@ void QCBUILTIN PF_CL_drawrawstring (pubprogfuncs_t *prinst, struct globalvars_s return; } - r2d_be_flags = PF_SelectDPDrawFlag(flag); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flag); PR_CL_BeginString(prinst, pos[0], pos[1], size[0], size[1], &x, &y); R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha); @@ -914,7 +922,7 @@ void QCBUILTIN PF_CL_drawline (pubprogfuncs_t *prinst, struct globalvars_s *pr_g "}\n" "}\n"); - r2d_be_flags = PF_SelectDPDrawFlag(flags); + r2d_be_flags = PF_SelectDPDrawFlag(prinst, flags); R2D_ImageColours(rgb[0], rgb[1], rgb[2], alpha); R2D_Line(point1[0], point1[1], point2[0], point2[1], shader_draw_line); R2D_ImageColours(1,1,1,1); @@ -2579,8 +2587,8 @@ qboolean MP_Init (void) menuprogparms.ReadFile = MP_PRReadFile;//char *(*ReadFile) (char *fname, void *buffer, int *len); menuprogparms.FileSize = MP_PRFileSize;//int (*FileSize) (char *fname); //-1 if file does not exist menuprogparms.WriteFile = QC_WriteFile;//bool (*WriteFile) (char *name, void *data, int len); - menuprogparms.Printf = (void *)Con_Printf;//Con_Printf;//void (*printf) (char *, ...); - menuprogparms.Printf = (void *)Con_DPrintf;//Con_DPrintf;//void (*dprintf) (char *, ...); + menuprogparms.Printf = PR_Printf;//Con_Printf;//void (*printf) (char *, ...); + menuprogparms.DPrintf = PR_DPrintf;//Con_DPrintf;//void (*dprintf) (char *, ...); menuprogparms.Sys_Error = Sys_Error; menuprogparms.Abort = Menu_Abort; menuprogparms.CheckHeaderCrc = Menu_CheckHeaderCrc; @@ -2915,6 +2923,8 @@ qboolean MP_Keydown(int key, int unicode, unsigned int devid) PR_ExecuteProgram(menu_world.progs, mpfuncs.keydown); result = true; //doesn't have a return value, so if the menu is set up for key events, all events are considered eaten. } + if (R2D_Flush) + R2D_Flush(); inmenuprogs--; return result; } @@ -2954,6 +2964,8 @@ void MP_Keyup(int key, int unicode, unsigned int devid) G_FLOAT(OFS_PARM1) = unicode; PR_ExecuteProgram(menu_world.progs, mpfuncs.keyup); } + if (R2D_Flush) + R2D_Flush(); inmenuprogs--; } @@ -2973,6 +2985,8 @@ qboolean MP_MousePosition(float xabs, float yabs, unsigned int devid) G_FLOAT(OFS_PARM2) = (yabs * vid.height) / vid.pixelheight; G_FLOAT(OFS_PARM3) = devid; PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent); + if (R2D_Flush) + R2D_Flush(); inmenuprogs--; return G_FLOAT(OFS_RETURN); } @@ -2992,6 +3006,8 @@ qboolean MP_MouseMove(float xdelta, float ydelta, unsigned int devid) G_FLOAT(OFS_PARM2) = (ydelta * vid.height) / vid.pixelheight; G_FLOAT(OFS_PARM3) = devid; PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent); + if (R2D_Flush) + R2D_Flush(); inmenuprogs--; return G_FLOAT(OFS_RETURN); } @@ -3010,6 +3026,8 @@ qboolean MP_JoystickAxis(int axis, float value, unsigned int devid) G_FLOAT(OFS_PARM2) = value; G_FLOAT(OFS_PARM3) = devid; PR_ExecuteProgram (menu_world.progs, mpfuncs.inputevent); + if (R2D_Flush) + R2D_Flush(); inmenuprogs--; return G_FLOAT(OFS_RETURN); } @@ -3040,6 +3058,8 @@ qboolean MP_Toggle(int mode) G_FLOAT(OFS_PARM0) = mode; PR_ExecuteProgram(menu_world.progs, mpfuncs.toggle); } + if (R2D_Flush) + R2D_Flush(); inmenuprogs--; return true; diff --git a/engine/client/render.h b/engine/client/render.h index 3b2bd6580..4523f984e 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -308,6 +308,8 @@ typedef struct qbyte areabits[MAX_MAP_AREA_BYTES]; vec4_t userdata[16]; /*for custom glsl*/ + + qboolean warndraw; /*buggy gamecode likes drawing outside of te drawing logic*/ } refdef_t; extern refdef_t r_refdef; @@ -517,6 +519,7 @@ typedef struct unsigned short *extents; unsigned char *styles; unsigned char *shifts; + unsigned char defaultshift; } lightmapoverrides_t; typedef struct bspx_header_s bspx_header_t; void Mod_LoadLighting (struct model_s *loadmodel, bspx_header_t *bspx, qbyte *mod_base, lump_t *l, qboolean interleaveddeluxe, lightmapoverrides_t *overrides); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 20fd1efde..77a842d59 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -186,7 +186,7 @@ cvar_t r_part_rain = CVARFD ("r_part_rain", "0", "Enable particle effects to emit off of surfaces. Mainly used for weather or lava/slime effects."); cvar_t r_skyboxname = CVARFC ("r_skybox", "", CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM, R_SkyBox_Changed); -cvar_t r_softwarebanding_cvar = CVARFD ("r_softwarebanding", "0", CVAR_SHADERSYSTEM|CVAR_RENDERERLATCH, "Utilise the Quake colormap in order to emulate 8bit software rendering. This results in banding as well as other artifacts that some believe adds character. Also forces nearest sampling on affected surfaces (palette indicies do not interpolate well)."); +cvar_t r_softwarebanding_cvar = CVARFD ("r_softwarebanding", "0", CVAR_SHADERSYSTEM|CVAR_RENDERERLATCH|CVAR_ARCHIVE, "Utilise the Quake colormap in order to emulate 8bit software rendering. This results in banding as well as other artifacts that some believe adds character. Also forces nearest sampling on affected surfaces (palette indicies do not interpolate well)."); qboolean r_softwarebanding; cvar_t r_speeds = CVAR ("r_speeds", "0"); cvar_t r_stainfadeammount = CVAR ("r_stainfadeammount", "1"); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 90d71ab39..0bf209ccb 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -176,17 +176,17 @@ static int Sbar_BottomColour(player_info_t *p) #endif //Draws a pre-marked-up string with no width limit. doesn't support new lines -void Draw_ExpandedString(float x, float y, conchar_t *str) +void Draw_ExpandedString(struct font_s *font, float x, float y, conchar_t *str) { int px, py; unsigned int codeflags, codepoint; - Font_BeginString(font_default, x, y, &px, &py); + Font_BeginString(font, x, y, &px, &py); while(*str) { str = Font_Decode(str, &codeflags, &codepoint); px = Font_DrawChar(px, py, codeflags, codepoint); } - Font_EndString(font_default); + Font_EndString(font); } //Draws a marked-up string using the regular char set with no width limit. doesn't support new lines @@ -195,7 +195,7 @@ void Draw_FunString(float x, float y, const void *str) conchar_t buffer[2048]; COM_ParseFunString(CON_WHITEMASK, str, buffer, sizeof(buffer), false); - Draw_ExpandedString(x, y, buffer); + Draw_ExpandedString(font_default, x, y, buffer); } //Draws a marked up string using the alt char set (legacy mode would be |128) void Draw_AltFunString(float x, float y, const void *str) @@ -203,7 +203,7 @@ void Draw_AltFunString(float x, float y, const void *str) conchar_t buffer[2048]; COM_ParseFunString(CON_ALTMASK, str, buffer, sizeof(buffer), false); - Draw_ExpandedString(x, y, buffer); + Draw_ExpandedString(font_default, x, y, buffer); } //Draws a marked up string no wider than $width virtual pixels. @@ -285,7 +285,31 @@ static char *q2sb_nums[2][11] = static mpic_t *Sbar_Q2CachePic(char *name) { - return R2D_SafeCachePic(va("pics/%s.pcx", name)); + mpic_t *pic = R2D_SafeCachePic(va("pics/%s.pcx", name)); +#if defined(IMAGEFMT_PCX) + int xmin,ymin,swidth,sheight; + size_t length; + pcx_t *pcx = (pcx_t*)COM_LoadTempFile(va("pics/%s.pcx", name), 0, &length); + if (pcx && length >= sizeof(*pcx)) + { + xmin = LittleShort(pcx->xmin); + ymin = LittleShort(pcx->ymin); + swidth = LittleShort(pcx->xmax)-xmin+1; + sheight = LittleShort(pcx->ymax)-ymin+1; + + if (pcx->manufacturer == 0x0a + && pcx->version == 5 + && pcx->encoding == 1 + && pcx->bits_per_pixel == 8 + && swidth <= 1024 + && sheight <= 1024) + { + pic->width = swidth; + pic->height = sheight; + } + } +#endif + return pic; } #define ICON_WIDTH 24 @@ -1210,7 +1234,7 @@ void Sbar_DrawString (float x, float y, char *str) void Sbar_DrawExpandedString (float x, float y, conchar_t *str) { - Draw_ExpandedString (sbar_rect.x + x /*+ ((sbar_rect.width - 320)>>1) */, sbar_rect.y + y+ sbar_rect.height-SBAR_HEIGHT, str); + Draw_ExpandedString (font_default, sbar_rect.x + x /*+ ((sbar_rect.width - 320)>>1) */, sbar_rect.y + y+ sbar_rect.height-SBAR_HEIGHT, str); } void Draw_TinyString (float x, float y, const qbyte *str) diff --git a/engine/client/screen.h b/engine/client/screen.h index f123f1861..8e3a39b23 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -257,6 +257,7 @@ void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py) void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py); /*avoid using*/ void Font_Transform(float vx, float vy, int *px, int *py); int Font_CharHeight(void); +float Font_CharVHeight(struct font_s *font); float Font_CharScaleHeight(void); int Font_CharWidth(unsigned int charflags, unsigned int codepoint); float Font_CharScaleWidth(unsigned int charflags, unsigned int codepoint); diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index d314ca391..30f43f5df 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -1750,6 +1750,7 @@ extern sounddriver_t DSOUND_Output; sounddriver_t SDL_Output; #ifdef __linux__ sounddriver_t ALSA_Output; +sounddriver_t Pulse_Output; #endif sounddriver_t OSS_Output; #ifdef AVAIL_OPENAL @@ -1794,11 +1795,12 @@ static sounddriver_t *outputdrivers[] = &WASAPI_Output, //this is last, so that we can default to exclusive. woot. #endif - &SDL_Output, //prefered on linux + &SDL_Output, //prefered on linux. distros can ensure that its configured correctly. #ifdef __linux__ - &ALSA_Output, //pure shite + &Pulse_Output, //wasteful, and availability generally means Alsa is broken/defective. + &ALSA_Output, //pure shite, and availability generally means OSS is broken/defective. #endif - &OSS_Output, //good, but not likely to work any more on linux (unlike every other unix system with a decent opengl driver) + &OSS_Output, //good for low latency audio, but not likely to work any more on linux (unlike every other unix system with a decent opengl driver) #ifdef __DJGPP__ &SBLASTER_Output, //zomgwtfdos? #endif diff --git a/engine/client/view.c b/engine/client/view.c index b2d6da278..c173e591a 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1701,7 +1701,7 @@ static qboolean SCR_VRectForPlayer(vrect_t *vrect, int pnum, unsigned maxseats) return pnum < w*h; } -void Draw_ExpandedString(float x, float y, conchar_t *str); +void Draw_ExpandedString(struct font_s *font, float x, float y, conchar_t *str); static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam) { @@ -1753,6 +1753,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam) &tp_name_lg }; #endif + struct font_s *font = font_default; VectorCopy(org, tagcenter); tagcenter[2] += 32; @@ -1805,7 +1806,7 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam) { y -= 8; len = COM_ParseFunString(textflags, pname, buffer, sizeof(buffer), false) - buffer; - Draw_ExpandedString(x - len*4, y, buffer); + Draw_ExpandedString(font, x - len*4, y, buffer); } if (!haveinfo) @@ -1887,10 +1888,10 @@ static void SCR_DrawAutoID(vec3_t org, player_info_t *pl, qboolean isteam) if (len && (buffer[0] & CON_CHARMASK) == '{' && (buffer[len-1] & CON_CHARMASK) == '}') { //these are often surrounded by {} to make them white in chat messages, and recoloured. buffer[len-1] = 0; - Draw_ExpandedString(x + barwidth*0.5 + 4, y, buffer+1); + Draw_ExpandedString(font, x + barwidth*0.5 + 4, y, buffer+1); } else - Draw_ExpandedString(x + barwidth*0.5 + 4, y, buffer); + Draw_ExpandedString(font, x + barwidth*0.5 + 4, y, buffer); } } #else @@ -1915,8 +1916,40 @@ void R_DrawNameTags(void) if (r_projection.ival) //we don't actually know how to transform the points unless the projection is coded in advance. and it isn't. return; - if (cls.protocol == CP_QUAKE2) - return; //FIXME: q2 has its own ent logic, which messes stuff up here. + +#if defined(CSQC_DAT) || !defined(CLIENTONLY) + if (r_showshaders.ival && cl.worldmodel && cl.worldmodel->loadstate == MLS_LOADED) + { + trace_t trace; + char *str; + vec3_t targ; + vec2_t scale = {12,12}; + msurface_t *surf; + VectorMA(r_refdef.vieworg, 8192, vpn, targ); + //FIXME: should probably do a general trace, to hit (networked) submodels too + cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, PE_FRAMESTATE, NULL, r_refdef.vieworg, targ, vec3_origin, vec3_origin, false, ~0, &trace); + + surf = Mod_GetSurfaceNearPoint(cl.worldmodel, trace.endpos); + if (surf) + { + shader_t *shader = surf->texinfo->texture->shader; + char fname[MAX_QPATH]; + char *body = shader?Shader_GetShaderBody(shader, fname, countof(fname)):NULL; + if (body) + { +// Q_snprintfz(fname, sizeof(fname), ""); + str = va("^2%s^7\n%s\n{%s\n", fname, surf->texinfo->texture->name, body); + Z_Free(body); + } + else + str = va("hit '%s'", surf->texinfo->texture->name); + } + else + str = "hit nothing"; + R_DrawTextField(r_refdef.vrect.x + r_refdef.vrect.width/4, r_refdef.vrect.y, r_refdef.vrect.width/2, r_refdef.vrect.height, str, CON_WHITEMASK, CPRINT_LALIGN, font_console, scale); + } + else +#endif if (r_showfields.ival) { @@ -1982,6 +2015,56 @@ void R_DrawNameTags(void) } } } +#ifdef Q2SERVER //not enough fields for it to really be worth it. + if (w == &sv.world && svs.gametype == GT_QUAKE2 && ge) + { + struct q2edict_s *e; + + int best = 0; + float bestscore = 0, score = 0; + for (i = 1; i < ge->num_edicts; i++) + { + e = &ge->edicts[i]; + if (!e->inuse) + continue; + VectorInterpolate(e->mins, 0.5, e->maxs, org); + VectorAdd(org, e->s.origin, org); + VectorSubtract(org, r_refdef.vieworg, diff); + if (DotProduct(diff, diff) < 16*16) + continue; //ignore stuff too close(like the player themselves) + VectorNormalize(diff); + score = DotProduct(diff, vpn);// r_refdef.viewaxis[0]); + if (score > bestscore) + { + int hitent; + vec3_t imp; + if (CL_TraceLine(r_refdef.vieworg, org, imp, NULL, &hitent)>=1 || hitent == i) + { + best = i; + bestscore = score; + } + } + } + if (best) + { + e = &ge->edicts[best]; + VectorInterpolate(e->mins, 0.5, e->maxs, org); + VectorAdd(org, e->s.origin, org); + if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y)) + { + char *entstr = va("entity %i {\n\tmodelindex %i\n\torigin \"%f %f %f\"\n}\n", e->s.number, e->s.modelindex, e->s.origin[0], e->s.origin[1], e->s.origin[2]); + if (entstr) + { + vec2_t scale = {8,8}; + int x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x; + int y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y; + R_DrawTextField(x, y, vid.width - x, vid.height - y, entstr, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_console, scale); + } + } + } + } + else +#endif if (w && w->progs) { int best = 0; @@ -2036,36 +2119,8 @@ void R_DrawNameTags(void) } } -#if defined(CSQC_DAT) || !defined(CLIENTONLY) - if (r_showshaders.ival && cl.worldmodel && cl.worldmodel->loadstate == MLS_LOADED) - { - trace_t trace; - char *str; - vec3_t targ; - vec2_t scale = {12,12}; - msurface_t *surf; - VectorMA(r_refdef.vieworg, 8192, vpn, targ); - cl.worldmodel->funcs.NativeTrace(cl.worldmodel, 0, PE_FRAMESTATE, NULL, r_refdef.vieworg, targ, vec3_origin, vec3_origin, false, ~0, &trace); - - surf = Mod_GetSurfaceNearPoint(cl.worldmodel, trace.endpos); - if (surf) - { - shader_t *shader = surf->texinfo->texture->shader; - char fname[MAX_QPATH]; - char *body = shader?Shader_GetShaderBody(shader, fname, countof(fname)):NULL; - if (body) - { - str = va("%s:\n%s\n{%s\n", fname, surf->texinfo->texture->name, body); - Z_Free(body); - } - else - str = va("hit '%s'", surf->texinfo->texture->name); - } - else - str = "hit nothing"; - R_DrawTextField(r_refdef.vrect.x + r_refdef.vrect.width/4, r_refdef.vrect.y, r_refdef.vrect.width/2, r_refdef.vrect.height, str, CON_WHITEMASK, CPRINT_LALIGN, font_console, scale); - } -#endif + if (cls.protocol == CP_QUAKE2) + return; //FIXME: q2 has its own ent logic, which messes stuff up here. if (((!r_refdef.playerview->spectator && !cls.demoplayback) || !scr_autoid.ival) && (!cl.teamplay || !scr_autoid_team.ival)) return; diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index c2842864a..1b254b055 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -10,6 +10,8 @@ #endif #endif +//#include + //small helper to aid compiling. #if defined(SKELETALMODELS) || defined(MD3MODELS) #define SKELORTAGS diff --git a/engine/common/fs.c b/engine/common/fs.c index f925428c4..51e45bcc2 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -6466,12 +6466,16 @@ void FS_RegisterDefaultFileSystems(void) FS_RegisterFileSystemType(NULL, "PAK", FSPAK_LoadArchive, true); #endif #endif - FS_RegisterFileSystemType(NULL, "pk3dir", VFSOS_OpenPath, true); + FS_RegisterFileSystemType(NULL, "pk3dir", VFSOS_OpenPath, true); //used for git repos or whatever, to make packaging easier #ifdef PACKAGE_PK3 - FS_RegisterFileSystemType(NULL, "pk3", FSZIP_LoadArchive, true); - FS_RegisterFileSystemType(NULL, "pk4", FSZIP_LoadArchive, true); - FS_RegisterFileSystemType(NULL, "apk", FSZIP_LoadArchive, false); - FS_RegisterFileSystemType(NULL, "zip", FSZIP_LoadArchive, false); + FS_RegisterFileSystemType(NULL, "pk3", FSZIP_LoadArchive, true); //quake3's extension for zips + FS_RegisterFileSystemType(NULL, "pk4", FSZIP_LoadArchive, true); //quake4's extension for zips... +#ifdef Q2CLIENT + FS_RegisterFileSystemType(NULL, "pkz", FSZIP_LoadArchive, true); //q2pro uses a different extension + FS_RegisterFileSystemType(NULL, "pkx", FSZIP_LoadArchive, true); //q2xp naturally uses a different extension too... you'll be glad to know that yq2 uses pk3 instead. yay consistency - every engine uses something different! +#endif + FS_RegisterFileSystemType(NULL, "apk", FSZIP_LoadArchive, false); //android package + FS_RegisterFileSystemType(NULL, "zip", FSZIP_LoadArchive, false); //regular zip file (don't automatically read from these, because it gets messy) FS_RegisterFileSystemType(NULL, "exe", FSZIP_LoadArchive, false); //for self-extracting zips. #endif #ifdef PACKAGE_VPK diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 8717a7406..92c47da59 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -1538,7 +1538,7 @@ Mod_LoadFaces ================= */ #ifndef SERVERONLY -static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboolean lightofsisdouble) +static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboolean lightofsisdouble, lightmapoverrides_t *overrides) { dsface_t *in; msurface_t *out; @@ -1549,13 +1549,18 @@ static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboo unsigned short lmshift, lmscale; char buf[64]; - lmscale = atoi(Mod_ParseWorldspawnKey(mod, "lightmap_scale", buf, sizeof(buf))); - if (!lmscale) - lmshift = LMSHIFT_DEFAULT; + if (overrides->offsets) + lmshift = overrides->defaultshift; else { - for(lmshift = 0; lmscale > 1; lmshift++) - lmscale >>= 1; + lmscale = atoi(Mod_ParseWorldspawnKey(mod, "lightmap_scale", buf, sizeof(buf))); + if (!lmscale) + lmshift = LMSHIFT_DEFAULT; + else + { + for(lmshift = 0; lmscale > 1; lmshift++) + lmscale >>= 1; + } } in = (void *)(mod_base + l->fileofs); @@ -1602,14 +1607,25 @@ static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboo } #endif - out->lmshift = lmshift; + if (overrides->shifts) + out->lmshift = overrides->shifts[surfnum]; + else + out->lmshift = lmshift; CalcSurfaceExtents (mod, out); + if (overrides->extents) + { + out->extents[0] = overrides->extents[surfnum*2+0]; + out->extents[1] = overrides->extents[surfnum*2+1]; + } // lighting info for (i=0 ; istyles[i] = in->styles[i]; - i = LittleLong(in->lightofs); + if (overrides->offsets) + i = overrides->offsets[surfnum]; + else + i = LittleLong(in->lightofs); if (i == -1) out->samples = NULL; else if (lightofsisdouble) @@ -1629,6 +1645,11 @@ static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboo } } + if (overrides->extents) + { + for (i=0 ; istyles[i] = overrides->extents[surfnum*4+i]; + } } return true; @@ -4412,48 +4433,52 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole break; #ifndef SERVERONLY default: - // load into heap - noerrors = noerrors && Mod_LoadVertexes (mod, mod_base, &header.lumps[Q2LUMP_VERTEXES]); - if (header.version == BSPVERSION_Q2W) - /*noerrors = noerrors &&*/ Mod_LoadVertexNormals(mod, mod_base, &header.lumps[19]); - noerrors = noerrors && Mod_LoadEdges (mod, mod_base, &header.lumps[Q2LUMP_EDGES], false); - noerrors = noerrors && Mod_LoadSurfedges (mod, mod_base, &header.lumps[Q2LUMP_SURFEDGES]); - if (noerrors) - Mod_LoadLighting (mod, bspx, mod_base, &header.lumps[Q2LUMP_LIGHTING], header.version == BSPVERSION_Q2W, NULL); - noerrors = noerrors && CModQ2_LoadSurfaces (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO]); - noerrors = noerrors && CModQ2_LoadPlanes (mod, mod_base, &header.lumps[Q2LUMP_PLANES]); - noerrors = noerrors && CModQ2_LoadTexInfo (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO], loadname); - if (noerrors) - Mod_LoadEntities (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); - noerrors = noerrors && CModQ2_LoadFaces (mod, mod_base, &header.lumps[Q2LUMP_FACES], header.version == BSPVERSION_Q2W); - noerrors = noerrors && Mod_LoadMarksurfaces (mod, mod_base, &header.lumps[Q2LUMP_LEAFFACES], false); - noerrors = noerrors && CModQ2_LoadVisibility (mod, mod_base, &header.lumps[Q2LUMP_VISIBILITY]); - noerrors = noerrors && CModQ2_LoadBrushSides (mod, mod_base, &header.lumps[Q2LUMP_BRUSHSIDES]); - noerrors = noerrors && CModQ2_LoadBrushes (mod, mod_base, &header.lumps[Q2LUMP_BRUSHES]); - noerrors = noerrors && CModQ2_LoadLeafBrushes (mod, mod_base, &header.lumps[Q2LUMP_LEAFBRUSHES]); - noerrors = noerrors && CModQ2_LoadLeafs (mod, mod_base, &header.lumps[Q2LUMP_LEAFS]); - noerrors = noerrors && CModQ2_LoadNodes (mod, mod_base, &header.lumps[Q2LUMP_NODES]); - noerrors = noerrors && CModQ2_LoadSubmodels (mod, mod_base, &header.lumps[Q2LUMP_MODELS]); - noerrors = noerrors && CModQ2_LoadAreas (mod, mod_base, &header.lumps[Q2LUMP_AREAS]); - noerrors = noerrors && CModQ2_LoadAreaPortals (mod, mod_base, &header.lumps[Q2LUMP_AREAPORTALS]); - - if (!noerrors) { - return NULL; - } + lightmapoverrides_t overrides = {0}; + overrides.defaultshift = LMSHIFT_DEFAULT; + // load into heap + noerrors = noerrors && Mod_LoadVertexes (mod, mod_base, &header.lumps[Q2LUMP_VERTEXES]); + if (header.version == BSPVERSION_Q2W) + /*noerrors = noerrors &&*/ Mod_LoadVertexNormals(mod, mod_base, &header.lumps[19]); + noerrors = noerrors && Mod_LoadEdges (mod, mod_base, &header.lumps[Q2LUMP_EDGES], false); + noerrors = noerrors && Mod_LoadSurfedges (mod, mod_base, &header.lumps[Q2LUMP_SURFEDGES]); + if (noerrors) + Mod_LoadLighting (mod, bspx, mod_base, &header.lumps[Q2LUMP_LIGHTING], header.version == BSPVERSION_Q2W, &overrides); + noerrors = noerrors && CModQ2_LoadSurfaces (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO]); + noerrors = noerrors && CModQ2_LoadPlanes (mod, mod_base, &header.lumps[Q2LUMP_PLANES]); + noerrors = noerrors && CModQ2_LoadTexInfo (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO], loadname); + if (noerrors) + Mod_LoadEntities (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); + noerrors = noerrors && CModQ2_LoadFaces (mod, mod_base, &header.lumps[Q2LUMP_FACES], header.version == BSPVERSION_Q2W, &overrides); + noerrors = noerrors && Mod_LoadMarksurfaces (mod, mod_base, &header.lumps[Q2LUMP_LEAFFACES], false); + noerrors = noerrors && CModQ2_LoadVisibility (mod, mod_base, &header.lumps[Q2LUMP_VISIBILITY]); + noerrors = noerrors && CModQ2_LoadBrushSides (mod, mod_base, &header.lumps[Q2LUMP_BRUSHSIDES]); + noerrors = noerrors && CModQ2_LoadBrushes (mod, mod_base, &header.lumps[Q2LUMP_BRUSHES]); + noerrors = noerrors && CModQ2_LoadLeafBrushes (mod, mod_base, &header.lumps[Q2LUMP_LEAFBRUSHES]); + noerrors = noerrors && CModQ2_LoadLeafs (mod, mod_base, &header.lumps[Q2LUMP_LEAFS]); + noerrors = noerrors && CModQ2_LoadNodes (mod, mod_base, &header.lumps[Q2LUMP_NODES]); + noerrors = noerrors && CModQ2_LoadSubmodels (mod, mod_base, &header.lumps[Q2LUMP_MODELS]); + noerrors = noerrors && CModQ2_LoadAreas (mod, mod_base, &header.lumps[Q2LUMP_AREAS]); + noerrors = noerrors && CModQ2_LoadAreaPortals (mod, mod_base, &header.lumps[Q2LUMP_AREAPORTALS]); + + if (!noerrors) + { + return NULL; + } #ifndef CLIENTONLY - mod->funcs.FatPVS = Q23BSP_FatPVS; - mod->funcs.EdictInFatPVS = Q23BSP_EdictInFatPVS; - mod->funcs.FindTouchedLeafs = Q23BSP_FindTouchedLeafs; + mod->funcs.FatPVS = Q23BSP_FatPVS; + mod->funcs.EdictInFatPVS = Q23BSP_EdictInFatPVS; + mod->funcs.FindTouchedLeafs = Q23BSP_FindTouchedLeafs; #endif - mod->funcs.LightPointValues = GLQ2BSP_LightPointValues; - mod->funcs.StainNode = GLR_Q2BSP_StainNode; - mod->funcs.MarkLights = Q2BSP_MarkLights; - mod->funcs.ClusterPVS = CM_ClusterPVS; - mod->funcs.ClusterForPoint = CM_PointCluster; - mod->funcs.PointContents = Q2BSP_PointContents; - mod->funcs.NativeTrace = CM_NativeTrace; - mod->funcs.NativeContents = CM_NativeContents; + mod->funcs.LightPointValues = GLQ2BSP_LightPointValues; + mod->funcs.StainNode = GLR_Q2BSP_StainNode; + mod->funcs.MarkLights = Q2BSP_MarkLights; + mod->funcs.ClusterPVS = CM_ClusterPVS; + mod->funcs.ClusterForPoint = CM_PointCluster; + mod->funcs.PointContents = Q2BSP_PointContents; + mod->funcs.NativeTrace = CM_NativeTrace; + mod->funcs.NativeContents = CM_NativeContents; + } break; #endif } diff --git a/engine/common/plugin.c b/engine/common/plugin.c index 9d7b1d33a..0045d236e 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -2154,13 +2154,81 @@ void Plug_CloseAll_f(void) } } +int QDECL Plug_List_Print(const char *fname, qofs_t fsize, time_t modtime, void *parm, searchpathfuncs_t *spath) +{ +plugin_t *plug; + char plugname[MAX_QPATH]; + //lots of awkward logic so we hide modules for other cpus. + size_t nl = strlen(fname); + size_t u; + const char *knownarch[] = + { + "x32", "x64", "amd64", "x86", //various x86 ABIs + "arm", "arm64", "armhf", //various arm ABIs + "ppc", "unk", //various misc ABIs + }; + if (nl >= strlen(ARCH_DL_POSTFIX) && !Q_strcasecmp(fname+nl-strlen(ARCH_DL_POSTFIX), ARCH_DL_POSTFIX)) + { + nl -= strlen(ARCH_DL_POSTFIX); + for (u = 0; u < countof(knownarch); u++) + { + size_t al = strlen(knownarch[u]); + if (!Q_strncasecmp(fname+nl-al, knownarch[u], al)) + { + nl -= al; + break; + } + } + if (u == countof(knownarch) || !Q_strcasecmp(knownarch[u], ARCH_CPU_POSTFIX)) + { + if (nl > sizeof(plugname)-1) + nl = sizeof(plugname)-1; + if (nl>0&&fname[nl] == '_') + nl--; //ignore the _ before the ABI name. + memcpy(plugname, fname, nl); + plugname[nl] = 0; + + //don't bother printing it if its already loaded. + for (plug = plugs; plug; plug = plug->next) + { + const char *existing = VM_GetFilename(plug->vm); + if (!Q_strncasecmp(existing, parm, strlen(parm)) && !Q_strcasecmp(existing+strlen(parm), fname)) + return true; + } + Con_Printf("^[%s%s\\type\\plug_load %s\\^]: not loaded\n", (const char*)parm, fname, plugname+((!Q_strncasecmp(plugname,"fteplug_", 8))?8:0)); + } + } + return true; +} + void Plug_List_f(void) { + char binarypath[MAX_OSPATH]; + char rootpath[MAX_OSPATH]; + unsigned int u; + char *mssuck; plugin_t *plug; for (plug = plugs; plug; plug = plug->next) { VM_PrintInfo(plug->vm); } + + if (FS_NativePath("", FS_BINARYPATH, binarypath, sizeof(binarypath))) + { + while ((mssuck=strchr(binarypath, '\\'))) + *mssuck = '/'; + Sys_EnumerateFiles(binarypath, "fteplug_*" ARCH_DL_POSTFIX, Plug_List_Print, binarypath, NULL); + } + if (FS_NativePath("", FS_ROOT, rootpath, sizeof(rootpath))) + { + while ((mssuck=strchr(rootpath, '\\'))) + *mssuck = '/'; + if (strcmp(binarypath, rootpath)) + Sys_EnumerateFiles(rootpath, "fteplug_*" ARCH_DL_POSTFIX, Plug_List_Print, rootpath, NULL); + } + + for (u = 0; staticplugins[u].name; u++) + Plug_List_Print(staticplugins[u].name, 0, 0, "", NULL); } void Plug_Shutdown(qboolean preliminary) diff --git a/engine/common/pmovetst.c b/engine/common/pmovetst.c index d7a0cb5de..aed30a8c7 100644 --- a/engine/common/pmovetst.c +++ b/engine/common/pmovetst.c @@ -250,7 +250,7 @@ static qboolean PM_TransformedHullCheck (model_t *model, framestate_t *framestat return false; } - Q1BSP_RecursiveHullCheck (&box_hull, box_hull.firstclipnode, 0, 1, start_l, end_l, trace); + Q1BSP_RecursiveHullCheck (&box_hull, box_hull.firstclipnode, start_l, end_l, MASK_PLAYERSOLID, trace); } trace->endpos[0] += origin[0]; diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 2241302cf..2acda84ce 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -720,6 +720,27 @@ static int Q1_HullPointContents (hull_t *hull, int num, vec3_t p) #define DIST_EPSILON (0.03125) #if 1 + +static const q1toftecontents[] = +{ + 0,//EMPTY + FTECONTENTS_SOLID,//SOLID + FTECONTENTS_WATER,//WATER + FTECONTENTS_SLIME,//SLIME + FTECONTENTS_LAVA,//LAVA + FTECONTENTS_SKY,//SKY + FTECONTENTS_SOLID,//STRIPPED + FTECONTENTS_PLAYERCLIP,//CLIP + Q2CONTENTS_CURRENT_0,//FLOW_1 + Q2CONTENTS_CURRENT_90,//FLOW_2 + Q2CONTENTS_CURRENT_180,//FLOW_3 + Q2CONTENTS_CURRENT_270,//FLOW_4 + Q2CONTENTS_CURRENT_UP,//FLOW_5 + Q2CONTENTS_CURRENT_DOWN,//FLOW_6 + Q2CONTENTS_WINDOW,//TRANS + FTECONTENTS_LADDER,//LADDER +}; + enum { rht_solid, @@ -728,6 +749,7 @@ enum }; struct rhtctx_s { + unsigned int checkcontents; vec3_t start, end; mclipnode_t *clipnodes; mplane_t *planes; @@ -746,9 +768,11 @@ reenter: if (num < 0) { + unsigned int c = q1toftecontents[-1-num]; /*hit a leaf*/ - if (num == Q1CONTENTS_SOLID) + if (c & ctx->checkcontents) { + trace->contents = c; if (trace->allsolid) trace->startsolid = true; return rht_solid; @@ -756,10 +780,10 @@ reenter: else { trace->allsolid = false; - if (num == Q1CONTENTS_EMPTY) - trace->inopen = true; - else + if (c & FTECONTENTS_FLUID) trace->inwater = true; + else + trace->inopen = true; return rht_empty; } } @@ -813,9 +837,11 @@ reenter: if (midf > p2f) midf = p2f; VectorInterpolate(ctx->start, midf, ctx->end, mid); + //check the near side rht = Q1BSP_RecursiveHullTrace(ctx, node->children[side], p1f, midf, p1, mid, trace); if (rht != rht_empty && !trace->allsolid) return rht; + //check the far side rht = Q1BSP_RecursiveHullTrace(ctx, node->children[side^1], midf, p2f, mid, p2, trace); if (rht != rht_solid) return rht; @@ -847,24 +873,25 @@ reenter: return rht_impact; } -qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace) +qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, vec3_t p1, vec3_t p2, unsigned int hitcontents, trace_t *trace) { if (VectorEquals(p1, p2)) { /*points cannot cross planes, so do it faster*/ - switch(Q1_HullPointContents(hull, num, p1)) - { - case Q1CONTENTS_SOLID: + int q1 = Q1_HullPointContents(hull, num, p1); + unsigned int c = q1toftecontents[-1-q1]; + trace->contents = c; + if (c & hitcontents) trace->startsolid = true; - break; - case Q1CONTENTS_EMPTY: - trace->allsolid = false; - trace->inopen = true; - break; - default: + else if (c & FTECONTENTS_FLUID) + { trace->allsolid = false; trace->inwater = true; - break; + } + else + { + trace->allsolid = false; + trace->inopen = true; } return true; } @@ -875,7 +902,8 @@ qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, VectorCopy(p2, ctx.end); ctx.clipnodes = hull->clipnodes; ctx.planes = hull->planes; - return Q1BSP_RecursiveHullTrace(&ctx, num, p1f, p2f, p1, p2, trace) != rht_impact; + ctx.checkcontents = hitcontents; + return Q1BSP_RecursiveHullTrace(&ctx, num, 0, 1, p1, p2, trace) != rht_impact; } } @@ -1576,7 +1604,6 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, framestate_t *framestate, traceinfo.solidcontents = hitcontentsmask; Q1BSP_RecursiveBrushCheck(&traceinfo, model->rootnode, 0, 1, start, end); memcpy(trace, &traceinfo.trace, sizeof(trace_t)); - trace->contents = FTECONTENTS_SOLID; if (trace->fraction < 1) { float d1 = DotProduct(start, trace->plane.normal) - trace->plane.dist; @@ -1614,8 +1641,7 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, framestate_t *framestate, end_l[0] = DotProduct(tmp, axis[0]); end_l[1] = DotProduct(tmp, axis[1]); end_l[2] = DotProduct(tmp, axis[2]); - trace->contents = FTECONTENTS_SOLID; - Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, start_l, end_l, hitcontentsmask, trace); if (trace->fraction == 1) { @@ -1639,7 +1665,7 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, framestate_t *framestate, { VectorSubtract(start, offset, start_l); VectorSubtract(end, offset, end_l); - Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, start_l, end_l, hitcontentsmask, trace); if (trace->fraction == 1) { @@ -1756,7 +1782,7 @@ static qbyte *Q1BSP_ClusterPVS (model_t *model, int cluster, pvsbuffer_t *buffer static void SV_Q1BSP_AddToFatPVS (model_t *mod, vec3_t org, mnode_t *node, pvsbuffer_t *pvsbuffer) { mplane_t *plane; - float d; + float d; while (1) { diff --git a/engine/common/qvm.c b/engine/common/qvm.c index 34407ca2a..706c1d25c 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -933,19 +933,19 @@ void VM_PrintInfo(vm_t *vm) qvm_t *qvm; // Con_Printf("%s (%p): ", vm->name, vm->hInst); - Con_Printf("%s: ", vm->filename); + Con_Printf("^2%s", vm->filename); switch(vm->type) { case VM_NATIVE: - Con_Printf("native\n"); + Con_Printf(": native\n"); break; case VM_BUILTIN: - Con_Printf("built in\n"); + Con_Printf(": built in\n"); break; case VM_BYTECODE: - Con_Printf("interpreted\n"); + Con_Printf(": interpreted\n"); if((qvm=vm->hInst)) { Con_Printf(" code length: %d\n", qvm->len_cs); @@ -955,7 +955,7 @@ void VM_PrintInfo(vm_t *vm) break; default: - Con_Printf("unknown\n"); + Con_Printf(": unknown\n"); break; } } diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index c8224906a..32fe75b9e 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -429,8 +429,6 @@ void GL_SelectTexture(int target) shaderstate.currenttmu = target; if (qglActiveTextureARB) qglActiveTextureARB(target + mtexid0); - else if (qglSelectTextureSGIS) - qglSelectTextureSGIS(target + mtexid0); } void GL_SelectVBO(int vbo) @@ -3134,6 +3132,47 @@ static void BE_SubmitMeshChain(qboolean usetesselation) } return; } + else if (qglMultiDrawElements) + { //if we're drawing via a VBO then we don't really need DrawRangeElements any more. + //and avoiding so many calls into the driver also gives the driver a chance to optimise the draws instead of constantly checking if anything changed. + static GLsizei counts[1024]; + static const GLvoid *indicies[countof(counts)]; + GLsizei drawcount = 0; + GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); + + for (m = 0, mesh = shaderstate.meshes[0]; m < shaderstate.meshcount; ) + { + startv = mesh->vbofirstvert; + starti = mesh->vbofirstelement; + + endv = startv+mesh->numvertexes; + endi = starti+mesh->numindexes; + + //find consecutive surfaces + for (++m; m < shaderstate.meshcount; m++) + { + mesh = shaderstate.meshes[m]; + if (endi == mesh->vbofirstelement) + { + endv = mesh->vbofirstvert+mesh->numvertexes; + endi = mesh->vbofirstelement+mesh->numindexes; + } + else + { + break; + } + } + if (drawcount == countof(counts)) + { + qglMultiDrawElements(batchtype, counts, GL_INDEX_TYPE, indicies, drawcount); + drawcount = 0; + } + counts[drawcount] = endi-starti; + indicies[drawcount] = (index_t*)shaderstate.sourcevbo->indicies.gl.addr + starti; + drawcount++; + } + qglMultiDrawElements(batchtype, counts, GL_INDEX_TYPE, indicies, drawcount); + } else { GL_SelectEBO(shaderstate.sourcevbo->indicies.gl.vbo); diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 962aa5aeb..946e3ed0d 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -1206,6 +1206,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out, gw, gh, gw*4); if (c) { + c->flags = 0; //private glyph colours c->advance = gw; c->left = 0; c->top = 0; @@ -2386,7 +2387,7 @@ void Font_EndString(struct font_s *font) // Font_Flush(); // curfont = NULL; - R2D_Flush = Font_Flush; + R2D_Flush = font_foremesh.numindexes?Font_Flush:NULL; } //obtains the font's row height (each row of chars should be drawn using this increment) @@ -2394,6 +2395,10 @@ int Font_CharHeight(void) { return curfont->charheight; } +float Font_CharVHeight(struct font_s *font) +{ + return ((float)font->charheight * vid.height)/vid.rotpixelheight; +} //obtains the font's row height (each row of chars should be drawn using this increment) float Font_CharScaleHeight(void) diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 16744088b..010f41127 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -141,22 +141,38 @@ static void Mod_BatchList_f(void) { for (batch = mod->batches[i]; batch; batch = batch->next) { + char editname[MAX_QPATH]; + char *body = Shader_GetShaderBody(batch->texture->shader, editname, sizeof(editname)); + if (!body) + body = "SHADER NOT KNOWN"; + else + { + char *cr; + while ((cr = strchr(body, '\r'))) + *cr = ' '; + } + Con_Printf(" ^[%s\\tipimg\\%s\\tipimgtype\\%i\\tip\\{%s^]", batch->texture->shader->name, batch->texture->shader->name, batch->texture->shader->usageflags, body); + #if MAXRLIGHTMAPS > 1 if (batch->lightmap[3] >= 0) - Con_Printf(" %s lm=(%i:%i %i:%i %i:%i %i:%i) surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->lmlightstyle[0], batch->lightmap[1], batch->lmlightstyle[1], batch->lightmap[2], batch->lmlightstyle[2], batch->lightmap[3], batch->lmlightstyle[3], batch->maxmeshes); + Con_Printf("^2 lm=(%i:%i %i:%i %i:%i %i:%i)", batch->lightmap[0], batch->lmlightstyle[0], batch->lightmap[1], batch->lmlightstyle[1], batch->lightmap[2], batch->lmlightstyle[2], batch->lightmap[3], batch->lmlightstyle[3]); else if (batch->lightmap[2] >= 0) - Con_Printf(" %s lm=(%i:%i %i:%i %i:%i) surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->lmlightstyle[0], batch->lightmap[1], batch->lmlightstyle[1], batch->lightmap[2], batch->lmlightstyle[2], batch->maxmeshes); + Con_Printf("^2 lm=(%i:%i %i:%i %i:%i)", batch->lightmap[0], batch->lmlightstyle[0], batch->lightmap[1], batch->lmlightstyle[1], batch->lightmap[2], batch->lmlightstyle[2]); else if (batch->lightmap[1] >= 0) - Con_Printf(" %s lm=(%i:%i %i:%i) surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->lmlightstyle[0], batch->lightmap[1], batch->lmlightstyle[1], batch->maxmeshes); + Con_Printf("^2 lm=(%i:%i %i:%i)", batch->lightmap[0], batch->lmlightstyle[0], batch->lightmap[1], batch->lmlightstyle[1]); else if (batch->lightmap[1] >= 0) #else if (batch->lmlightstyle[0] != 255) #endif - Con_Printf(" %s lm=(%i:%i) surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->lmlightstyle[0], batch->maxmeshes); + Con_Printf("^2 lm=(%i:%i)", batch->lightmap[0], batch->lmlightstyle[0]); else - Con_Printf(" %s lm=%i surfs=%u\n", batch->texture->shader->name, batch->lightmap[0], batch->maxmeshes); + Con_Printf("^2 lm=%i", batch->lightmap[0]); count++; + + if (batch->envmap) + Con_Printf("^3 envmap=%s", batch->envmap->ident); + Con_Printf(" surfs=%u\n", batch->maxmeshes); } } Con_Printf("^h(%u batches, lm %i*%i, lux %s)\n", count, mod->lightmaps.width, mod->lightmaps.height, mod->lightmaps.deluxemapping?"true":"false"); @@ -173,6 +189,7 @@ static void Mod_TextureList_f(void) int count = 0; char *body; char editname[MAX_OSPATH]; + int preview = (Cmd_Argc()==1)?8:atoi(Cmd_Argv(1)); for (m=0 , mod=mod_known ; mname, tx->shader->usageflags, preview, body); + else + Con_Printf("^[\\img\\%s\\imgtype\\%i\\s\\%i\\tip\\{%s^]", tx->shader->name, tx->shader->usageflags, preview, body); + } if (*editname) - Con_Printf(" ^[^7%s\\edit\\%s\\tipimg\\%s\\tip\\{%s^]\n", tx->name, editname, tx->name, body); + Con_Printf(" ^[%s\\edit\\%s\\tipimg\\%s\\tipimgtype\\%i\\tip\\{%s^]\n", tx->name, editname, tx->name, tx->shader->usageflags, body); else - Con_Printf(" ^[^7%s\\tipimg\\%s\\tip\\{%s^]\n", tx->name, tx->name, body); + Con_Printf(" ^[%s\\tipimg\\%s\\tipimgtype\\%i\\tip\\{%s^]\n", tx->name, tx->shader->name, tx->shader->usageflags, body); count++; } } @@ -1759,14 +1783,46 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, } #ifndef SERVERONLY +#if 0//def Q2BSPS //Q2XP's alternative to lit files, for higher res lightmaps (that seem to have light coming from the wrong directions...) + if (loadmodel->fromgame == fg_quake2 && overrides && !interleaveddeluxe) + { + char litname[MAX_QPATH]; + size_t litsize; + qbyte *xplm; + COM_StripExtension(loadmodel->name, litname, sizeof(litname)); + Q_strncatz(litname, ".xplm", sizeof(litname)); + xplm = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize); + + if (litdata) + { + int scale; + size_t numsurfs = LittleLong(*(int *)&xplm[0]); + unsigned int *offsets = (unsigned int*)(xplm+4); + scale = xplm[(numsurfs+1)*4]; + + for (overrides->defaultshift=0; scale && !(scale&1); scale>>=1) + overrides->defaultshift++; + if (scale == 1) + { //its a supported shift + litdata = xplm+(numsurfs+1)*4+1; + samples = (litsize-(numsurfs+1)*4+1)/3; + overrides->offsets = offsets; + } + } + } +#endif if (!expdata && !litdata && r_loadlits.value) { - char *litnames[] = { - "%s.lit2", - "%s.hdr", - "%s.lit", - "lits/%s.lit2", - "lits/%s.lit" + struct + { + char *pattern; + int type; + } litnames[] = { + {"%s.lit2",2}, + {"%s.hdr",1}, + {"%s.lit",0}, + {"lits/%s.lit2",2}, + {"lits/%s.lit",0}, }; char litbasep[MAX_QPATH]; char litbase[MAX_QPATH]; @@ -1780,14 +1836,14 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, COM_StripExtension(loadmodel->name, litbasep, sizeof(litbasep)); COM_FileBase(loadmodel->name, litbase, sizeof(litbase)); - for (i = 0; i < sizeof(litnames)/sizeof(litnames[0]); i++) + for (i = 0; i < countof(litnames); i++) { - if (temp_lit2support.ival && !(i & 1)) + if (!temp_lit2support.ival && litnames[i].type==2) continue; - if (strchr(litnames[i], '/')) - Q_snprintfz(litname, sizeof(litname), litnames[i], litbase); + if (strchr(litnames[i].pattern, '/')) + Q_snprintfz(litname, sizeof(litname), litnames[i].pattern, litbase); else - Q_snprintfz(litname, sizeof(litname), litnames[i], litbasep); + Q_snprintfz(litname, sizeof(litname), litnames[i].pattern, litbasep); depth = COM_FDepthFile(litname, false); if (depth < bestdepth) { @@ -1797,10 +1853,10 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, } if (best >= 0) { - if (strchr(litnames[best], '/')) - Q_snprintfz(litname, sizeof(litname), litnames[best], litbase); + if (strchr(litnames[best].pattern, '/')) + Q_snprintfz(litname, sizeof(litname), litnames[best].pattern, litbase); else - Q_snprintfz(litname, sizeof(litname), litnames[best], litbasep); + Q_snprintfz(litname, sizeof(litname), litnames[best].pattern, litbasep); litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize); } else @@ -1828,7 +1884,7 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, litdata += 8; //header+version } else if (litver == 0x10001) - { + { //hdr lighting, e5bgr9 format if (l->filelen && samples*4 != (litsize-8)) Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname); else @@ -2098,6 +2154,8 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base, } else loadmodel->lightdata = expdata; + + //FIXME: no desaturation/gamma logic. return; } else if (litdata) diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 714acf111..827645536 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -556,7 +556,7 @@ void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tan void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node); void GLQ1BSP_LightPointValues(struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); -qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace); +qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, vec3_t p1, vec3_t p2, unsigned int hitcontents, struct trace_s *trace); /* ============================================================================== diff --git a/engine/gl/gl_ngraph.c b/engine/gl/gl_ngraph.c index a08179596..e58ac12fd 100644 --- a/engine/gl/gl_ngraph.c +++ b/engine/gl/gl_ngraph.c @@ -22,91 +22,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "shader.h" -extern qbyte *draw_chars; // 8*8 graphic characters - -static texid_t netgraphtexture; // netgraph texture -static shader_t *netgraphshader; - +void Draw_ExpandedString(struct font_s *font, float x, float y, conchar_t *str); static int timehistory[NET_TIMINGS]; static int findex; #define NET_GRAPHHEIGHT 32 -static qbyte ngraph_texels[NET_GRAPHHEIGHT][NET_TIMINGS]; - -static void R_LineGraph (int x, int h) +//#define GRAPHTEX +#ifdef GRAPHTEX +static texid_t netgraphtexture; // netgraph texture +static shader_t *netgraphshader; +static unsigned int ngraph_texels[NET_GRAPHHEIGHT][NET_TIMINGS]; +#else +static struct { - int i; - int s; - int color, color2 = 0xff; + unsigned int col; + float height; +} ngraph[NET_TIMINGS]; +#endif - s = NET_GRAPHHEIGHT; - - if (h == 10000 || h<0) - { - color = 0; // yellow - color2 = 1; - h=abs(h); - } - else if (h == 9999) - { - color = 2; // red - color2 = 3; - } - else if (h == 9998) - { - color = 4; // blue - color2 = 5; - } - else - { - color = 6; // white - color2 = 7; - } - - if (h>s) - h = s; - - for (i=0 ; i>4; - col = num&15; - source = draw_chars + (row<<10) + (col<<3); - - for (drawline = 8; drawline; drawline--, y++) - { - for (nx=0 ; nx<8 ; nx++) - if (source[nx] != 255) - ngraph_texels[y][nx+x] = 0x60 + source[nx]; - source += 128; - } -} -*/ - -/* -============== -R_NetGraph -============== -*/ //instead of assuming the quake palette, we should use a predictable lookup table. it makes the docs much easier. static unsigned ngraph_palette[] = { @@ -120,14 +54,79 @@ static unsigned ngraph_palette[] = 0xffefefef, //white2 0x00000000 //invisible. }; + +static void R_LineGraph (int x, float h) +{ + int s; + unsigned color, color2; + + s = NET_GRAPHHEIGHT; + + if (h == 10000 || h<0) + { + color = 0xff00ffff; // yellow + color2 = 0xff00efef; + h=fabs(h); + } + else if (h == 9999) + { + color = 0xff0000ff; // red + color2 = 0xff0000ff; + } + else if (h == 9998) + { + color = 0xffff0000; // blue + color2 = 0xffef0000; + } + else + { + color = 0xffffffff; // white + color2 = 0xffefefef; + } + +#ifdef GRAPHTEX + if (h>s) + h = s; + + for (i=0 ; i s) + ngraph[x].height = 1; + else + ngraph[x].height = h/(float)s; +#endif +} + +/* +============== +R_NetGraph +============== +*/ void R_NetGraph (void) { - int a, x, i, y; + int a, x, i; + float y; int lost; - char st[80]; - unsigned ngraph_pixels[NET_GRAPHHEIGHT][NET_TIMINGS]; float pi, po, bi, bo; + vec2_t p[4]; + vec2_t tc[4]; + vec4_t rgba[4]; + extern shader_t *shader_draw_fill; + conchar_t line[2048]; + float textheight, graphtop; + + float pings, pings_min, pings_max, pingms_stddev, pingfr, dropped, choked, invalid; + int pingfr_min, pingfr_max; + x = 0; if (r_netgraph.value < 0) { @@ -142,7 +141,7 @@ void R_NetGraph (void) } else { - int last = 10000; + float last = 10000; lost = CL_CalcNet(r_netgraph.value); for (a=0 ; a>1); + x = ((vid.width - 320)>>1); //eww x=-x; - y = vid.height - sb_lines - 24 - NET_GRAPHHEIGHT - 2*8; + y = vid.height - sb_lines - textheight - NET_GRAPHHEIGHT - 2*8/*box borders*/; - M_DrawTextBox (x, y, NET_TIMINGS/8, NET_GRAPHHEIGHT/8 + 3); - y += 8; + M_DrawTextBox (x, y, NET_TIMINGS/8, (NET_GRAPHHEIGHT + textheight)/8); + x = 8; + y += 8; //top border + graphtop = y+textheight; - sprintf(st, "%3i%% packet loss", lost); - Draw_FunString(8, y, st); - y += 8; + CL_CalcNet2(&pings, &pings_min, &pings_max, &pingms_stddev, &pingfr, &pingfr_min, &pingfr_max, &dropped, &choked, &invalid); + { + COM_ParseFunString(CON_WHITEMASK, va("%3.0f%% lost, %3.0f%% choked, %3.0f%% bad", dropped*100, choked*100, invalid*100), line, sizeof(line), false); + Draw_ExpandedString(font_console, x, y, line); + y += Font_CharVHeight(font_console); + + COM_ParseFunString(CON_WHITEMASK, va(" ping: %4.1fms %6.2f (%.1f-%.1f)\n", pings*1000, pingms_stddev, pings_min*1000, pings_max*1000), line, sizeof(line), false); + Draw_ExpandedString(font_console, x, y, line); + y += Font_CharVHeight(font_console); + } if (NET_GetRates(cls.sockets, &pi, &po, &bi, &bo)) { - Draw_FunString(8, y+0, va("in: %g %g\n", pi, bi)); //not relevent as a limit. - Draw_FunString(8, y+8, va("out: %g %g\n", po, bo)); //not relevent as a limit. + COM_ParseFunString(CON_WHITEMASK, va(" in: %.1f %.0fb\n", pi, bi), line, sizeof(line), false); + Draw_ExpandedString(font_console, x, y, line); + y += Font_CharVHeight(font_console); + COM_ParseFunString(CON_WHITEMASK, va(" out: %.1f %.0fb\n", po, bo), line, sizeof(line), false); + Draw_ExpandedString(font_console, x, y, line); + y += Font_CharVHeight(font_console); } - y += 16; +#ifdef HAVE_SERVER + if (sv.state && sv.allocated_client_slots != 1 && NET_GetRates(svs.sockets, &pi, &po, &bi, &bo)) + { + COM_ParseFunString(CON_WHITEMASK, va("sv in: %.1f %.0fb\n", pi, bi), line, sizeof(line), false); + Draw_ExpandedString(font_console, x, y, line); + y += Font_CharVHeight(font_console); + COM_ParseFunString(CON_WHITEMASK, va("svout: %.1f %.0fb\n", po, bo), line, sizeof(line), false); + Draw_ExpandedString(font_console, x, y, line); + y += Font_CharVHeight(font_console); + } +#endif - Image_Upload(netgraphtexture, TF_RGBA32, ngraph_pixels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_UIPIC|IF_NOMIPMAP|IF_NOPICMIP); - x=8; + y = graphtop; //rounding makes it ugly. + +#ifdef GRAPHTEX + Image_Upload(netgraphtexture, TF_RGBA32, ngraph_texels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_UIPIC|IF_NOMIPMAP|IF_NOPICMIP); R2D_Image(x, y, NET_TIMINGS, NET_GRAPHHEIGHT, 0, 0, 1, 1, netgraphshader); +#else + for (a=0 ; a>0)&0xff)/255.0, ((ngraph[a].col>>8)&0xff)/255.0, ((ngraph[a].col>>16)&0xff)/255.0, ((ngraph[a].col>>24)&0xff)/255.0); + Vector4Copy(rgba[2+0], rgba[2+1]); + + if (a) + R2D_Image2dQuad(p, tc, rgba, shader_draw_fill); + } +#endif } void R_FrameTimeGraph (int frametime) { int a, x, i, y; - unsigned ngraph_pixels[NET_GRAPHHEIGHT][NET_TIMINGS]; + + vec2_t p[4]; + vec2_t tc[4]; + vec4_t rgba[4]; + extern shader_t *shader_draw_fill; timehistory[findex++&NET_TIMINGSMASK] = frametime; @@ -197,28 +245,42 @@ void R_FrameTimeGraph (int frametime) R_LineGraph (NET_TIMINGS-1-a, timehistory[i]); } - // now load the netgraph texture into gl and draw it - for (y = 0; y < NET_GRAPHHEIGHT; y++) - for (x = 0; x < NET_TIMINGS; x++) - ngraph_pixels[y][x] = d_8to24rgbtable[ngraph_texels[y][x]]; - x = ((vid.width - 320)>>1); x=-x; - y = vid.height - sb_lines - 24 - NET_GRAPHHEIGHT - 1; + y = vid.height - sb_lines - 16 - NET_GRAPHHEIGHT; - M_DrawTextBox (x, y, NET_TIMINGS/8, NET_GRAPHHEIGHT/8 + 1); + M_DrawTextBox (x, y, NET_TIMINGS/8, NET_GRAPHHEIGHT/8); + x=8; y += 8; - y += 8; - - Image_Upload(netgraphtexture, TF_RGBA32, ngraph_pixels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_UIPIC|IF_NOMIPMAP|IF_NOPICMIP); +#ifdef GRAPHTEX + Image_Upload(netgraphtexture, TF_RGBA32, ngraph_texels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_UIPIC|IF_NOMIPMAP|IF_NOPICMIP); x=8; R2D_Image(x, y, NET_TIMINGS, NET_GRAPHHEIGHT, 0, 0, 1, 1, netgraphshader); +#else + for (a=0 ; a>0)&0xff)/255.0, ((ngraph[a].col>>8)&0xff)/255.0, ((ngraph[a].col>>16)&0xff)/255.0, ((ngraph[a].col>>24)&0xff)/255.0); + Vector4Copy(rgba[2+0], rgba[2+1]); + + if (a) + R2D_Image2dQuad(p, tc, rgba, shader_draw_fill); + } +#endif } void R_NetgraphInit(void) { - TEXASSIGN(netgraphtexture, Image_CreateTexture("***netgraph***", NULL, IF_UIPIC|IF_NOMIPMAP)); +#ifdef GRAPHTEX + TEXASSIGN(netgraphtexture, Image_CreateTexture("***netgraph***", NULL, IF_UIPIC|IF_NOMIPMAP|IF_CLAMP)); netgraphshader = R_RegisterShader("netgraph", SUF_NONE, "{\n" "program default2d\n" @@ -229,4 +291,5 @@ void R_NetgraphInit(void) "}\n" ); netgraphshader->defaulttextures->base = netgraphtexture; +#endif } diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index fb7e01f39..92d290faa 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -63,7 +63,7 @@ cvar_t r_shadow_realtime_dlight_ambient = CVAR ("r_shadow_realtime_dlight_ambie cvar_t r_shadow_realtime_dlight_diffuse = CVAR ("r_shadow_realtime_dlight_diffuse", "1"); cvar_t r_shadow_realtime_dlight_specular = CVAR ("r_shadow_realtime_dlight_specular", "4"); //excessive, but noticable. its called stylized, okay? shiesh, some people cvar_t r_shadow_playershadows = CVARD ("r_shadow_playershadows", "1", "Controls the presence of shadows on the local player."); -cvar_t r_shadow_shadowmapping = CVARD ("r_shadow_shadowmapping", "1", "Enables soft shadows instead of stencil shadows."); +cvar_t r_shadow_shadowmapping = CVARFD ("r_shadow_shadowmapping", "1", CVAR_ARCHIVE, "Enables soft shadows instead of stencil shadows."); cvar_t r_shadow_shadowmapping_precision = CVARD ("r_shadow_shadowmapping_precision", "1", "Scales the shadowmap detail level up or down."); extern cvar_t r_shadow_shadowmapping_nearclip; extern cvar_t r_shadow_shadowmapping_bias; diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 22dd62dff..609ae36f7 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -1,3 +1,27 @@ +/* + Lingering issues: + + nvidia vsync: + with vsync enabled and framerates fluctuating across the 1000fps boundary, there is serious stuttering, like its re-showing the previous frame again. + this only happens with windows gl, and not vulkan/d3d so I'm assuming this is a driver bug with it mispredicting timings. + workaround: enable bloom or something else that's wasteful in terms of gpu time, to keep it under 1000fps. + + nouveau vsync: + vsync seems forced when running fullscreen, but not when running windowed. + workaround: run windowed. + + nouveau framerates: + nouveau doesn't seem to have any pstate control enabled. + workaround: sudo echo AUTO>/sys/kernel/debug/dri/0/pstate + (you could also use different ids for explicit pstates - eg to return to a low-power state) + (the engine cannot do this, as it requires root, nor does it know WHICH dri device to control) + (more recent gpus might not support this at all due to nvidia blocking them, but works for my 750ti) + (note that nouveau's presentation engine isn't that good, so don't expect 5000fps, but it should make rtlights usable) + + core vs compatibility: + vid_gl_context_compatibility defaults to 1, because it still gives higher framerates (due to streaming vertex data from the cpu). +*/ + #include "quakedef.h" #ifdef GLQUAKE #include "glquake.h" @@ -170,6 +194,7 @@ void (APIENTRY *qglGetTexLevelParameteriv) (GLenum target, GLint level, GLenum p void (APIENTRY *qglGetTexEnviv) (GLenum target, GLenum pname, GLint *params); void (APIENTRY *qglDrawRangeElements) (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +void (APIENTRY *qglMultiDrawElements) (GLenum mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei drawcount); void (APIENTRY *qglArrayElement) (GLint i); void (APIENTRY *qglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); void (APIENTRY *qglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); @@ -238,11 +263,8 @@ FTEPFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT; qlpSelTexFUNC qglActiveTextureARB; #endif qlpSelTexFUNC qglClientActiveTextureARB; -qlpMTex3FUNC qglMultiTexCoord3fARB; -qlpMTex2FUNC qglMultiTexCoord2fARB; //generic multitexture -lpMTexFUNC qglMTexCoord2fSGIS; lpSelTexFUNC qglSelectTextureSGIS; int mtexid0; @@ -627,9 +649,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) #ifndef qglActiveTextureARB qglActiveTextureARB = NULL; #endif - qglMultiTexCoord2fARB = NULL; - qglMultiTexCoord3fARB = NULL; - qglMTexCoord2fSGIS = NULL; qglSelectTextureSGIS = NULL; mtexid0 = 0; @@ -709,12 +728,12 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) // if (GL_CheckExtension("GL_SGIS_generate_mipmap")) //a suprising number of implementations have this broken. // gl_config.sgis_generate_mipmap = true; - if (gl_config.gles) + if (gl_config.gles || gl_config_nofixedfunc) { #ifndef qglActiveTextureARB qglActiveTextureARB = (void *) getglext("glActiveTexture"); #endif - qglClientActiveTextureARB = (void *) getglext("glClientActiveTexture"); + qglClientActiveTextureARB = (void *) getglext("glClientActiveTexture"); //compat contexts only... qglSelectTextureSGIS = qglActiveTextureARB; mtexid0 = GL_TEXTURE0_ARB; if (!gl_config.nofixedfunc) @@ -728,19 +747,16 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglActiveTextureARB = (void *) getglext("glActiveTextureARB"); #endif qglClientActiveTextureARB = (void *) getglext("glClientActiveTextureARB"); - qglMultiTexCoord2fARB = (void *) getglext("glMultiTexCoord2fARB"); - qglMultiTexCoord3fARB = (void *) getglext("glMultiTexCoord3fARB"); qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_mtexarbable); gl_mtexable = true; - qglMTexCoord2fSGIS = qglMultiTexCoord2fARB; qglSelectTextureSGIS = qglActiveTextureARB; mtexid0 = GL_TEXTURE0_ARB; #ifndef qglActiveTextureARB - if (!qglActiveTextureARB || !qglClientActiveTextureARB || !qglMultiTexCoord2fARB) + if (!qglActiveTextureARB || !qglClientActiveTextureARB) gl_mtexable = false; else if (gl_mtexarbable == 1) { @@ -751,8 +767,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) { qglActiveTextureARB = NULL; qglClientActiveTextureARB = NULL; - qglMultiTexCoord2fARB = NULL; - qglMTexCoord2fSGIS = NULL; qglSelectTextureSGIS = NULL; gl_mtexable=false; gl_mtexarbable = false; @@ -1136,13 +1150,13 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) gl_config.arb_depth_texture |= GL_CheckExtension("GL_CHROMIUM_depth_texture"); //nacl gl_config.arb_depth_texture |= GL_CheckExtension("GL_WEBGL_depth_texture"); //webgl. duh. gl_config.arb_depth_texture |= GL_CheckExtension("GL_ANGLE_depth_texture"); //gah. should just use wildcards huh (no uploads) + gl_config.arb_shadow = gl_config.glversion>=3.0;//||GL_CheckExtension("GL_EXT_shadow_samplers"); } else { - gl_config.arb_depth_texture = GL_CheckExtension("GL_ARB_depth_texture"); + gl_config.arb_depth_texture = gl_config.glversion>=1.4 || GL_CheckExtension("GL_ARB_depth_texture"); + gl_config.arb_shadow = gl_config.glversion>=1.4||GL_CheckExtension("GL_ARB_shadow"); } - gl_config.arb_shadow = GL_CheckExtension("GL_ARB_shadow"); - gl_config.arb_shadow |= gl_config.glversion >= 3.0; //seems about right, for both gles and desktop... //gl_config.arb_shadow |= GL_CheckExtension("GL_EXT_shadow_samplers"); //gles2. nvidia fucks up. depend on brute-force. :s if (GL_CheckExtension("GL_ARB_seamless_cube_map")) @@ -2047,6 +2061,7 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int //150 [core|compatibility] == gl3.2 //300 ES == gles3 //310 ES == gles3.1 + //320 ES == gles3.2 //330, 400, 410, 420, 430 [core|compatibility] == gl?.?? if (gl_config_gles) @@ -2056,6 +2071,13 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int else if (ver <= 330) //gles3 is rougly gl3.3 so 300es==330ish ver = 300; } + else + { + if (ver == 100) + ver = 110; //gles2 is roughly equivelent to gl2 + else if (ver >= 300 && ver < 330) + ver = 330; //gles3 is roughly equivelent to gl3.3 + } if (gl_config_gles && ver != 100) @@ -2095,7 +2117,7 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int if (ver >= 130) { GLSlang_GenerateInternal(&glsl, - //gl3+ deprecated the some things. these are removed in forwards-compatible / core contexts. + //gl3+ deprecated some things. these are removed in forwards-compatible / core contexts. //varying became either in or out, which is important if you have geometry shaders... "#define varying in\n" //now only the 'texture' function exists, with overloads for each sampler type. @@ -2137,6 +2159,8 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int #else "#ifndef USE_ARB_SHADOW\n" //fall back on regular samplers if we must "#define sampler2DShadow sampler2D\n" + "#elif defined(GL_ES)\n" + "precision lowp sampler2DShadow;\n" //gah "#endif\n" #endif "uniform sampler2DShadow s_shadowmap;\n", @@ -2948,11 +2972,6 @@ void GL_ForgetPointers(void) #endif qglClientActiveTextureARB = NULL; qglSelectTextureSGIS = NULL; - qglMTexCoord2fSGIS = NULL; - qglMultiTexCoord2fARB = NULL; - qglMultiTexCoord3fARB = NULL; - qglMTexCoord2fSGIS = NULL; - qglSelectTextureSGIS = NULL; mtexid0 = 0; #ifndef GL_STATIC @@ -3204,6 +3223,8 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name)) if (qglDrawRangeElements == 0) qglDrawRangeElements = GL_DrawRangeElementsEmul; + qglMultiDrawElements = (void *)getglext("glMultiDrawElements"); //since gl2 + //fixme: definatly make non-core qglPushAttrib = (void *)getglcore("glPushAttrib"); qglPopAttrib = (void *)getglcore("glPopAttrib"); diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index 1f6336d34..6308e93f7 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -1309,7 +1309,10 @@ static struct const char * (*QueryExtensionsString)(Display * dpy, int screen); void *(*GetProcAddress) (char *name); - void (*SwapInterval) (Display *dpy, GLXDrawable drawable, int interval); + void (*SwapIntervalSGI) (int interval); //FFS! + void (*SwapIntervalMESA) (unsigned int interval); //FFS! + void (*SwapIntervalEXT) (Display *dpy, GLXDrawable drawable, int interval); + qboolean swaptear; GLXFBConfig *(*ChooseFBConfig)(Display *dpy, int screen, const int *attrib_list, int *nelements); int (*GetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int * value); @@ -1675,6 +1678,29 @@ static void *GLX_GetSymbol(char *name) return symb; } +static qboolean GLX_CheckExtension(const char *ext) +{ + const char *e = glx.glxextensions, *n; + size_t el = strlen(ext); + while(e && *e) + { + while (*e == ' ') + e++; + n = strchr(e, ' '); + if (!n) + n = n+strlen(e); + + if (n-e == el && !strncmp(ext, e, el)) + { + Con_DPrintf("GLX: Found %s\n", ext); + return true; + } + e = n; + } + Con_DPrintf("GLX: Missing %s\n", ext); + return false; +} + static qboolean GLX_InitLibrary(char *driver) { dllfunction_t funcs[] = @@ -1703,17 +1729,15 @@ static qboolean GLX_InitLibrary(char *driver) if (!glx.gllibrary) return false; + glx.QueryExtensionsString = GLX_GetSymbol("glXQueryExtensionsString"); glx.GetProcAddress = GLX_GetSymbol("glXGetProcAddress"); if (!glx.GetProcAddress) glx.GetProcAddress = GLX_GetSymbol("glXGetProcAddressARB"); - glx.QueryExtensionsString = GLX_GetSymbol("glXQueryExtensionsString"); glx.ChooseFBConfig = GLX_GetSymbol("glXChooseFBConfig"); glx.GetFBConfigAttrib = GLX_GetSymbol("glXGetFBConfigAttrib"); glx.GetVisualFromFBConfig = GLX_GetSymbol("glXGetVisualFromFBConfig"); glx.CreateContextAttribs = GLX_GetSymbol("glXCreateContextAttribsARB"); - glx.SwapInterval = GLX_GetSymbol("glXSwapIntervalEXT"); - return true; } @@ -1724,29 +1748,6 @@ static qboolean GLX_InitLibrary(char *driver) #define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3 #endif -static qboolean GLX_CheckExtension(const char *ext) -{ - const char *e = glx.glxextensions, *n; - size_t el = strlen(ext); - while(e && *e) - { - while (*e == ' ') - e++; - n = strchr(e, ' '); - if (!n) - n = n+strlen(e); - - if (n-e == el && !strncmp(ext, e, el)) - { - Con_DPrintf("GLX: Found %s\n", ext); - return true; - } - e = n; - } - Con_DPrintf("GLX: Missing %s\n", ext); - return false; -} - //Since GLX1.3 (equivelent to gl1.2) static GLXFBConfig GLX_GetFBConfig(rendererstate_t *info) { @@ -1757,9 +1758,6 @@ static GLXFBConfig GLX_GetFBConfig(rendererstate_t *info) qboolean hassrgb, hasmultisample;//, hasfloats; - if (glx.QueryExtensionsString) - glx.glxextensions = glx.QueryExtensionsString(vid_dpy, scrnum); - if (!glx.ChooseFBConfig || !glx.GetVisualFromFBConfig) { Con_Printf("Missing function pointer\n"); @@ -1832,7 +1830,7 @@ static GLXFBConfig GLX_GetFBConfig(rendererstate_t *info) if (!info->multisample || !hasmultisample) continue; attrib[n++] = GLX_SAMPLE_BUFFERS_ARB; attrib[n++] = True; - attrib[n++] = GLX_SAMPLES_ARB, attrib[n++] = info->multisample; + attrib[n++] = GLX_SAMPLES_ARB; attrib[n++] = info->multisample; } //attrib[n++] = GLX_ACCUM_RED_SIZE; attrib[n++] = 0; @@ -3432,14 +3430,28 @@ void GLVID_SwapBuffers (void) int n = vid_vsync.ival; if (cls.timedemo && cls.demoplayback) n = 0; + if (!glx.swaptear) + n = abs(n); if (glx.swapint != n) { glx.swapint = n; - if (glx.SwapInterval) + if (glx.SwapIntervalEXT) { - glx.SwapInterval(vid_dpy, vid_window, glx.swapint); - Con_Printf("Swap interval %i\n", glx.swapint); + glx.SwapIntervalEXT(vid_dpy, vid_window, glx.swapint); + Con_DPrintf("Swap interval changed to %i\n", glx.swapint); } + else if (glx.SwapIntervalMESA && glx.swapint>=0) + { + glx.SwapIntervalMESA(glx.swapint); + Con_DPrintf("Swap interval changed to %i\n", glx.swapint); + } + else if (glx.SwapIntervalSGI && glx.swapint>0) + { + glx.SwapIntervalSGI(glx.swapint); + Con_DPrintf("Swap interval changed to %i\n", glx.swapint); + } + else + Con_Printf("Unable to change swap interval to %i\n", glx.swapint); } } @@ -3836,6 +3848,8 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int break; #endif case PSL_GLX: + if (glx.QueryExtensionsString) + glx.glxextensions = glx.QueryExtensionsString(vid_dpy, scrnum); fbconfig = GLX_GetFBConfig(info); if (fbconfig) visinfo = glx.GetVisualFromFBConfig(vid_dpy, fbconfig); @@ -3930,9 +3944,38 @@ static qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int if (visinfo != &vinfodef) #endif x11.pXFree(visinfo); + + glx.SwapIntervalEXT = GLX_CheckExtension("GLX_EXT_swap_control")?GLX_GetSymbol("glXSwapIntervalEXT"):NULL; + glx.swaptear = glx.SwapIntervalEXT&&GLX_CheckExtension("GLX_EXT_swap_control_tear"); +// if (glx.swaptear) +// glx.QueryDrawable(vid_dpy, vid_window, 0x20F3, &glx.swaptear); + if (!glx.SwapIntervalEXT) + glx.SwapIntervalMESA = GLX_CheckExtension("GLX_MESA_swap_control")?GLX_GetSymbol("glXSwapIntervalMESA"):NULL; + if (!glx.SwapIntervalEXT && !glx.SwapIntervalMESA) + glx.SwapIntervalSGI = GLX_CheckExtension("GLX_SGI_swap_control")?GLX_GetSymbol("glXSwapIntervalSGI"):NULL; glx.swapint = vid_vsync.ival; - if (glx.SwapInterval) - glx.SwapInterval(vid_dpy, vid_window, glx.swapint); + if (!glx.swaptear) + glx.swapint = abs(glx.swapint); + if (*vid_vsync.string) + { + if (glx.SwapIntervalEXT /*&& (glx.swapint>=0 || swap_tear)*/) + { + glx.SwapIntervalEXT(vid_dpy, vid_window, glx.swapint); + Con_DPrintf("Swap interval %i\n", glx.swapint); + } + else if (glx.SwapIntervalMESA && glx.swapint>=0) + { + glx.SwapIntervalMESA(abs(glx.swapint)); + Con_DPrintf("Swap interval %i\n", glx.swapint); + } + else if (glx.SwapIntervalSGI && glx.swapint>0) + { + glx.SwapIntervalSGI(glx.swapint); + Con_DPrintf("Swap interval %i\n", glx.swapint); + } + else + Con_Printf("Unable to explicitly %s vsync\n", glx.swapint?"configure":"disable"); + } break; #ifdef USE_EGL case PSL_EGL: diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 9caf476c5..77425da35 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -1039,9 +1039,7 @@ extern PFNGLGENPROGRAMSARBPROC qglGenProgramsARB; extern FTEPFNGLLOCKARRAYSEXTPROC qglLockArraysEXT; extern FTEPFNGLUNLOCKARRAYSEXTPROC qglUnlockArraysEXT; -typedef void (APIENTRY *lpMTexFUNC) (GLenum en, GLfloat f1, GLfloat f2); typedef void (APIENTRY *lpSelTexFUNC) (GLenum en); -extern lpMTexFUNC qglMTexCoord2fSGIS; extern lpSelTexFUNC qglSelectTextureSGIS; //these functions are not available in gles2, for one reason or another @@ -1078,6 +1076,7 @@ extern FTEPFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT; extern void (APIENTRY *qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax); extern void (APIENTRY *qglDrawRangeElements) (GLenum, GLuint, GLuint, GLsizei, GLenum, const GLvoid *); +extern void (APIENTRY *qglMultiDrawElements) (GLenum mode, const GLsizei * count, GLenum type, const GLvoid * const * indices, GLsizei drawcount); extern void (APIENTRY *qglEnableClientState) (GLenum array); extern void (APIENTRY *qglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index 8926daf1b..a26630a9d 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -4,14 +4,14 @@ //contains the extra things that would otherwise be found in glext.h -typedef void (APIENTRY *qlpMTex2FUNC) (GLenum, GLfloat, GLfloat); -typedef void (APIENTRY *qlpMTex3FUNC) (GLenum, GLfloat, GLfloat, GLfloat); +//typedef void (APIENTRY *qlpMTex2FUNC) (GLenum, GLfloat, GLfloat); +//typedef void (APIENTRY *qlpMTex3FUNC) (GLenum, GLfloat, GLfloat, GLfloat); typedef void (APIENTRY *qlpSelTexFUNC) (GLenum); extern qlpSelTexFUNC qglActiveTextureARB; extern qlpSelTexFUNC qglClientActiveTextureARB; -extern qlpMTex3FUNC qglMultiTexCoord3fARB; -extern qlpMTex2FUNC qglMultiTexCoord2fARB; +//extern qlpMTex3FUNC qglMultiTexCoord3fARB; +//extern qlpMTex2FUNC qglMultiTexCoord2fARB; //This stuff is normally supplied in the header file. I don't actually have one of them, so it's here instead. #if 0 //change to 1 if you do actually have the file in question - and its up to date. diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 8eb14d80a..6c0bdc890 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -5193,7 +5193,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND #endif #ifdef GLQUAKE {QR_OPENGL, 110, "defaultwall", -"!!ver 100 150\n" +"!!ver 100 450\n" "!!permu TESS\n" "!!permu DELUXE\n" "!!permu FULLBRIGHT\n" @@ -6591,6 +6591,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND #endif #ifdef GLQUAKE {QR_OPENGL, 110, "defaultwarp", +"!!ver 100 450\n" "!!permu FOG\n" "!!cvarf r_wateralpha\n" "!!samps diffuse lightmap\n" @@ -9086,7 +9087,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;\n" -"if (r_glsl_ascii_mono != 0.0)\n" +"if (float(r_glsl_ascii_mono) != 0.0)\n" "gray = gray = pow(gray, 0.7); //quake is just too dark otherwise.\n" "else\n" "gray = gray = pow(gray, 0.45); //col*char is FAR too dark otherwise, and much of the colour will come from the col term anyway.\n" @@ -9102,7 +9103,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "if (gray > 0.8) n = 11512810.0; // #\n" "vec2 p = mod(uv/4.0, 2.0) - vec2(1.0);\n" -"if (r_glsl_ascii_mono != 0.0)\n" +"if (float(r_glsl_ascii_mono) != 0.0)\n" "col = vec3(character(n, p));\n" "else\n" "col = col*character(n, p); //note that this is kinda cheating.\n" @@ -10620,7 +10621,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND #endif #ifdef GLQUAKE {QR_OPENGL, 110, "rtlight", -"!!ver 100 150\n" +"!!ver 100 300\n" "!!permu TESS\n" "!!permu BUMP\n" "!!permu FRAMEBLEND\n" diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 218ac22b9..672a3b50b 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -3592,7 +3592,7 @@ static unsigned short QCC_PR_WriteProgdefs (char *filename) QCC_PR_Warning(WARN_SYSTEMCRC, NULL, 0, "please update your tenebrae system defs.\n"); break; default: - QCC_PR_Warning(WARN_SYSTEMCRC, NULL, 0, "progs CRC not recognised from quake nor clones\n"); + QCC_PR_Warning(WARN_SYSTEMCRC, NULL, 0, "system defs not recognised from quake nor clones\n"); break; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index f45811881..f4f7dd6b9 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -10920,7 +10920,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"runstandardplayerphysics",PF_runclientphys,0,0,0, 347, D("void(entity ent)", "Perform the engine's standard player movement prediction upon the given entity using the input_* globals to describe movement.")}, {"getplayerkeyvalue", PF_Fixme,0, 0, 0, 348, D("string(float playernum, string keyname)", "Look up a player's userinfo, to discover things like their name, topcolor, bottomcolor, skin, team, *ver.\nAlso includes scoreboard info like frags, ping, pl, userid, entertime, as well as voipspeaking and voiploudness.")},// (EXT_CSQC) {"getplayerkeyfloat", PF_Fixme,0, 0, 0, 0, D("float(float playernum, string keyname, optional float assumevalue)", "Cheaper version of getplayerkeyvalue that avoids the need for so many tempstrings.")}, - {"getplayerkeyblob", PF_Fixme,0, 0, 0, 0, D("int(float playernum, string keyname, optional void *outptr, int size)", "Obtains a copy of the full data blob. Will write up to size bytes and return the actual size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")}, + {"getplayerkeyblob", PF_Fixme,0, 0, 0, 0, D("int(float playernum, string keyname, optional void *outptr, int size)", "Obtains a copy of the full data blob. Will write up to size bytes but return the full size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")}, {"getlocalinfo", PF_getlocalinfo,0, 0, 0, 0, D("int(string keyname, optional void *outptr, int size)", "Obtains a copy of the full data blob. Will write up to size bytes and return the actual size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")}, {"setlocalinfo", PF_setlocalinfo,0, 0, 0, 0, D("void(string keyname, optional void *outptr, int size)", "Changes the server's localinfo. This data will be available for the following map, and will *usually* reload with saved games.")}, diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 689c122d5..dfc9e8e52 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -142,7 +142,7 @@ pbool SV_ExtendedSaveData(pubprogfuncs_t *progfuncs, void *loadctx, const char * l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_STRING)return false; sv.strings.sound_precache[idx] = PR_AddString(svprogfuncs, token, 0, false); } - else if (!strcmp(token, "particle_precache")) + else if (!strcmp(token, "particle_precache") || !strcmp(token, "particle")) { //particle_precache N "MODELNAME" l = COM_ParseTokenOut(l, NULL, token, sizeof(token), &tt);if (tt != TTP_RAWTOKEN)return false; idx = atoi(token); @@ -1674,6 +1674,9 @@ void SV_Savegame_f (void) Con_TPrintf ("Relative pathnames are not allowed\n"); return; } + //make sure the name is valid, eg if its omitted. + if (!*savename || strstr(savename, "..")) + savename = "quick"; #ifndef QUAKETC if (!Q_strcasecmp(Cmd_Argv(0), "savegame_legacy")) { diff --git a/engine/server/sv_move.c b/engine/server/sv_move.c index f15fdde2d..0c94ad39e 100644 --- a/engine/server/sv_move.c +++ b/engine/server/sv_move.c @@ -159,17 +159,17 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, vec3_t axis axis = eaxis; } -#ifndef CLIENTONLY - if (progstype != PROG_H2 || world != &sv.world) -#endif - eflags &= ~FLH2_NOZ|FLH2_HUNTFACE; - -// try the move +// try the move VectorCopy (ent->v->origin, oldorg); VectorAdd (ent->v->origin, move, neworg); // flying monsters don't step up - if ((eflags & (FL_SWIM | FL_FLY)) && !(eflags & (FLH2_NOZ|FLH2_HUNTFACE))) + if ((eflags & (FL_SWIM | FL_FLY)) +#if defined(HEXEN2) && defined(HAVE_SERVER) + //hexen2 has some extra logic for FLH2_HUNTFACE, but its buggy and thus never used. + //it would be nice to redefine the NOZ flag to instead force noenemy here, but that's not hexen2-compatible and FLH2_NOZ is bound to conflict with some quake mod. + && (world != &sv.world || progstype != PROG_H2 || !(eflags & (FLH2_NOZ|FLH2_HUNTFACE)))) +#endif { // try one move with vertical motion, then one without for (i=0 ; i<2 ; i++) @@ -182,8 +182,6 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, vec3_t axis { VectorSubtract(ent->v->origin, ((wedict_t*)PROG_TO_EDICT(world->progs, ent->v->enemy))->v->origin, end); dz = DotProduct(end, axis[2]); - if (eflags & FLH2_HUNTFACE) /*get the ent's origin_z to match its victims face*/ - dz += ((wedict_t*)PROG_TO_EDICT(world->progs, ent->v->enemy))->v->view_ofs[2]; if (dz > 40) VectorMA(neworg, -8, axis[2], neworg); if (dz < 30) @@ -193,7 +191,7 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, vec3_t axis trace = World_Move (world, ent->v->origin, ent->v->mins, ent->v->maxs, neworg, false, ent); if (set_move_trace) set_move_trace(world->progs, &trace); - + if (trace.fraction == 1) { if ( (eflags & FL_SWIM) && !(World_PointContents(world, trace.endpos) & FTECONTENTS_FLUID)) @@ -204,11 +202,11 @@ qboolean World_movestep (world_t *world, wedict_t *ent, vec3_t move, vec3_t axis World_LinkEdict (world, ent, true); return true; } - + if (noenemy || !enemy->entnum) break; } - + return false; } diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 25ceadf67..031ede39c 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -867,7 +867,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int break; if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) - { + { //always in range if within 1024 units (consistent with quakeworld). vec3_t delta; VectorSubtract(origin, split->edict->v->origin, delta); if (DotProduct(delta, delta) <= 1024*1024) @@ -2852,7 +2852,7 @@ static qboolean SV_SyncInfoBuf(client_t *client) if (info == &svs.info) pl = 255; //colourmaps being 1-based with these being 0-based means that only 0-254 are valid players, and 255 is unused, so lets use it for serverinfo blobs. else - pl = (client_t*)info-svs.clients; + pl = (client_t*)((char*)info-(char*)&((client_t*)NULL)->userinfo)-svs.clients; ClientReliableWrite_Begin(client, svc_setinfo, 7+strlen(enckey)+1+strlen(encval)+1); ClientReliableWrite_Byte(client, 255); //special meaning to say that this is a partial update diff --git a/engine/server/world.c b/engine/server/world.c index c53bdea56..c4b25b40f 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -136,7 +136,7 @@ qboolean World_BoxTrace(struct model_s *model, int hulloverride, int frame, vec3 trace->allsolid = true; VectorCopy (p2, trace->endpos); - return Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, p1, p2, trace); + return Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, p1, p2, against, trace); } qboolean World_CapsuleTrace(struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, qboolean capsule, unsigned int against, struct trace_s *trace) { @@ -1174,8 +1174,6 @@ wedict_t *World_TestEntityPosition (world_t *w, wedict_t *ent) return NULL; } -qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace); - //wrapper function. Rotates the start and end positions around the angles if needed. //qboolean TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_t *trace, vec3_t angles) qboolean World_TransformedTrace (struct model_s *model, int hulloverride, framestate_t *framestate, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean capsule, struct trace_s *trace, vec3_t origin, vec3_t angles, unsigned int hitcontentsmask) @@ -1223,9 +1221,10 @@ qboolean World_TransformedTrace (struct model_s *model, int hulloverride, frames VectorSubtract (start, origin, start_l); VectorSubtract (end, origin, end_l); VectorCopy (end_l, trace->endpos); - result = Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + result = Q1BSP_RecursiveHullCheck (hull, hull->firstclipnode, start_l, end_l, MASK_PLAYERSOLID, trace); VectorAdd (trace->endpos, origin, trace->endpos); - trace->contents = FTECONTENTS_BODY; + if (trace->contents) + trace->contents = FTECONTENTS_BODY; } else result = false; diff --git a/engine/shaders/glsl/defaultwall.glsl b/engine/shaders/glsl/defaultwall.glsl index c34f9106f..a4fabb2bb 100644 --- a/engine/shaders/glsl/defaultwall.glsl +++ b/engine/shaders/glsl/defaultwall.glsl @@ -1,4 +1,4 @@ -!!ver 100 150 +!!ver 100 450 !!permu TESS !!permu DELUXE !!permu FULLBRIGHT diff --git a/engine/shaders/glsl/defaultwarp.glsl b/engine/shaders/glsl/defaultwarp.glsl index 2d291bf4e..eb8b629e1 100644 --- a/engine/shaders/glsl/defaultwarp.glsl +++ b/engine/shaders/glsl/defaultwarp.glsl @@ -1,3 +1,4 @@ +!!ver 100 450 !!permu FOG !!cvarf r_wateralpha !!samps diffuse lightmap