diff --git a/engine/Makefile b/engine/Makefile index 0a44bf7f7..9b06498ad 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -1261,8 +1261,12 @@ ifeq ($(FTE_TARGET),web) COMMON_OBJS+=sys_web.o fs_web.o WEB_PREJS ?= --pre-js web/prejs.js # WEB_MEMORY?=402653184 #384mb - ASMJS_MEMORY?=536870912 #512mb (required for asm.js) -# ASMJS_MEMORY?=268435456 #256mb (required for asm.js) +# ASMJS_MEMORY?=16777216 #16mb +# ASMJS_MEMORY?=33554432 #32mb + ASMJS_MEMORY?=268435456 #256mb +# ASMJS_MEMORY?=536870912 #512mb +# ASMJS_MEMORY?=1073741824 #1025mb +# ASMJS_MEMORY?=2147483648 #2048mb WEB_MEMORY?=$(ASMJS_MEMORY) JSLIBS=--js-library web/ftejslib.js -s LEGACY_GL_EMULATION=0 EMCC_ARGS=$(JSLIBS) $(WEB_PREJS) --shell-file web/fteshell.html -s ERROR_ON_UNDEFINED_SYMBOLS=1 @@ -1292,7 +1296,7 @@ ifeq ($(FTE_TARGET),web) #GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) cd_null.o #GL_LDFLAGS=$(GLLDFLAGS) GLB_DIR=gl_web - GL_EXE_NAME=../ftewebgl.html + GL_EXE_NAME=../ftewebgl.js GL_LDFLAGS=$(GLLDFLAGS) $(IMAGELDFLAGS) $(OGGVORBISLDFLAGS) GL_CFLAGS=$(GLCFLAGS) @@ -1695,15 +1699,17 @@ EMSCRIPTENPATH=$(realpath $(EMSCRIPTENROOT)):$(realpath $(EMSCRIPTENROOT)/clang/ web-rel: @$(MAKE) gl-rel FTE_TARGET=web PATH="$(EMSCRIPTENPATH)" CC="emcc.bat" + cp $(BASE_DIR)/fteshell.html $(RELEASE_DIR)/ftewebgl.html @gzip -f $(RELEASE_DIR)/ftewebgl.html @gzip -f $(RELEASE_DIR)/ftewebgl.js - @gzip -f $(RELEASE_DIR)/ftewebgl.html.mem + @gzip -f $(RELEASE_DIR)/ftewebgl.js.mem web-dbg: @$(MAKE) gl-dbg FTE_TARGET=web PATH="$(EMSCRIPTENPATH)" CC="emcc.bat" + cp $(BASE_DIR)/fteshell.html $(RELEASE_DIR)/ftewebgl.html @gzip -f $(DEBUG_DIR)/ftewebgl.html @gzip -f $(DEBUG_DIR)/ftewebgl.js - @gzip -f $(DEBUG_DIR)/ftewebgl.html.map + @gzip -f $(DEBUG_DIR)/ftewebgl.js.map ################################################# #android diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 284e4bec4..cad376322 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -972,12 +972,12 @@ void CLQW_ParsePacketEntities (qboolean delta) cl.inframes[newpacket].frameid = cls.netchan.incoming_sequence; cl.inframes[newpacket].receivedtime = realtime; - if (cls.protocol == CP_QUAKEWORLD && cls.demoplayback == DPB_MVD) + if (cls.protocol == CP_QUAKEWORLD && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)) { extern float olddemotime; //time from the most recent demo packet cl.oldgametime = cl.gametime; cl.oldgametimemark = cl.gametimemark; - cl.gametime = olddemotime; + cl.gametime = olddemotime + cl.demogametimebias; cl.gametimemark = realtime; } else if (!(cls.fteprotocolextensions & PEXT_ACCURATETIMINGS) && cls.protocol == CP_QUAKEWORLD) @@ -3399,6 +3399,7 @@ void CL_LinkPacketEntities (void) static int flicker; int trailef, trailidx; int modelflags; + struct itemtimer_s *timer, **timerlink; pack = cl.currentpackentities; if (!pack) @@ -3417,22 +3418,43 @@ void CL_LinkPacketEntities (void) CSQC_DeltaStart(cl.currentpacktime); #endif + + for (timerlink = &cl.itemtimers; (timer=*timerlink); ) + { + if (cl.time > timer->end) + { + *timerlink = timer->next; + Z_Free(timer); + } + else + { + timerlink = &(*timerlink)->next; + if (timer->entnum >= cl.maxlerpents) + continue; + le = &cl.lerpents[timer->entnum]; + if (le->sequence != cl.lerpentssequence) + continue; + R_AddItemTimer(timer->origin, cl.time*90 + timer->origin[0] + timer->origin[1] + timer->origin[2], timer->radius, (cl.time - timer->start) / timer->duration); + } + } + for (newpnum=0 ; newpnumnum_entities ; newpnum++) { state = &pack->entities[newpnum]; - - - if (cl_numvisedicts == cl_maxvisedicts) - { - break; - } - #ifdef CSQC_DAT if (CSQC_DeltaUpdate(state)) continue; #endif + if (cl_numvisedicts == cl_maxvisedicts) + break; + + if (state->number >= cl.maxlerpents) + continue; + + le = &cl.lerpents[state->number]; + ent = &cl_visedicts[cl_numvisedicts]; ent->rtype = RT_MODEL; ent->playerindex = -1; @@ -3445,11 +3467,6 @@ void CL_LinkPacketEntities (void) ent->light_known = 0; ent->forcedshader = NULL; - if (state->number >= cl.maxlerpents) - continue; - - le = &cl.lerpents[state->number]; - memset(&ent->framestate, 0, sizeof(ent->framestate)); VectorCopy(le->origin, ent->origin); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 2fd651361..f178e5a6d 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -2919,6 +2919,7 @@ void CLQW_ParseServerData (void) /*mvds have different parsing*/ if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV) { + extern float olddemotime; int i,j; if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS) @@ -2933,6 +2934,8 @@ void CLQW_ParseServerData (void) cl.oldgametime = cl.gametime; cl.oldgametimemark = realtime; + cl.demogametimebias = cl.gametime - olddemotime; + for (j = 0; j < MAX_SPLITS; j++) { cl.playerview[j].playernum = cl.allocated_client_slots + j; @@ -4261,9 +4264,15 @@ void CLQW_ParseStartSoundPacket(void) S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation, 0, 0, 0); } - - if (ent == cl.playerview[0].playernum+1) - TP_CheckPickupSound(cl.sound_name[sound_num], pos); + for (i = 0; i < cl.splitclients; i++) + { + if (ent == cl.playerview[i].playernum+1) + { + TP_CheckPickupSound(cl.sound_name[sound_num], pos, i); + return; + } + } + TP_CheckPickupSound(cl.sound_name[sound_num], pos, -1); } #ifdef Q2CLIENT @@ -4427,8 +4436,15 @@ void CLNQ_ParseStartSoundPacket(void) S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation, timeofs, pitchadj, flags); } - if (ent == cl.playerview[0].playernum+1) - TP_CheckPickupSound(cl.sound_name[sound_num], pos); + for (i = 0; i < cl.splitclients; i++) + { + if (ent == cl.playerview[i].playernum+1) + { + TP_CheckPickupSound(cl.sound_name[sound_num], pos, i); + return; + } + } + TP_CheckPickupSound(cl.sound_name[sound_num], pos, -1); } #endif diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index edaa19a22..bfaef20e3 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -1300,6 +1300,21 @@ void SCR_Init (void) void SCR_DeInit (void) { + int i; + if (scr_curcursor) + { + rf->VID_SetCursor(scr_curcursor); + scr_curcursor = NULL; + } + for (i = 0; i < countof(key_customcursor); i++) + { + if (key_customcursor[i].handle) + { + rf->VID_DestroyCursor(key_customcursor[i].handle); + key_customcursor[i].handle = NULL; + } + key_customcursor[i].dirty = true; + } if (scr_initialized) { scr_initialized = false; diff --git a/engine/client/client.h b/engine/client/client.h index a2e300894..318c8d1d4 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -753,6 +753,7 @@ typedef struct float gametimemark; float oldgametime; //used as the old time to lerp cl.time from. float oldgametimemark; //if it's 0, cl.time will casually increase. + float demogametimebias; //mvd timings are weird. float minpitch; float maxpitch; @@ -829,6 +830,18 @@ typedef struct float predicted_step_time; float predicted_step; + + struct itemtimer_s + { + float end; + int entnum; + float start; + float duration; + vec3_t origin; + float radius; + struct itemtimer_s *next; + } *itemtimers; + //interpolation+snapshots float packfrac; packet_entities_t *currentpackentities; @@ -1354,7 +1367,7 @@ void QDECL vectoangles(vec3_t fwd, vec3_t ang); void CL_Say (qboolean team, char *extra); int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr); -void TP_CheckPickupSound(char *s, vec3_t org); +void TP_CheckPickupSound(char *s, vec3_t org, int seat); qboolean TP_CheckSoundTrigger (char *str); int TP_CountPlayers (void); char* TP_EnemyName (void); diff --git a/engine/client/image.c b/engine/client/image.c index a5e83343b..ba6c20dcf 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -4527,8 +4527,8 @@ void Image_Upload (texid_t tex, uploadfmt_t fmt, void *data, void *palette, in Image_GenerateMips(&mips, flags); Image_ChangeFormat(&mips, fmt); rf->IMG_LoadTextureMips(tex, &mips); - tex->width = mips.mip[0].width; - tex->height = mips.mip[0].height; + tex->width = width; + tex->height = height; tex->status = TEX_LOADED; for (i = 0; i < mips.mipcount; i++) diff --git a/engine/client/m_options.c b/engine/client/m_options.c index e4816c1f2..3b4ec2ea9 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -387,8 +387,10 @@ struct audiomenuinfo { char **outdevnames; char **outdevdescs; +#ifdef VOICECHAT char **capdevnames; char **capdevdescs; +#endif }; void M_Menu_Audio_Remove(menu_t *menu) { @@ -400,12 +402,14 @@ void M_Menu_Audio_Remove(menu_t *menu) for (i = 0; info->outdevdescs[i]; i++) Z_Free(info->outdevdescs[i]); Z_Free(info->outdevdescs); +#ifdef VOICECHAT for (i = 0; info->capdevnames[i]; i++) Z_Free(info->capdevnames[i]); Z_Free(info->capdevnames); for (i = 0; info->capdevdescs[i]; i++) Z_Free(info->capdevdescs[i]); Z_Free(info->capdevdescs); +#endif } struct audiomenuinfo *M_Menu_Audio_Setup(menu_t *menu) { @@ -1110,7 +1114,8 @@ void M_Menu_Textures_f (void) MB_COMBOCVAR("2D Filter Mode", gl_texturemode2d, texture2dfilternames, texture2dfiltervalues, "Chooses the texture filtering method used for HUD, menus, and other 2D assets."), MB_COMBOCVAR("Anisotropy", gl_texture_anisotropic_filtering, anisotropylevels, anisotropyvalues, NULL), MB_SPACING(4), - MB_CHECKBOXCVAR("Deluxemapping", r_deluxemapping, 0), + MB_CHECKBOXCVAR("Software-style Rendering", r_softwarebanding_cvar, 0), + MB_CHECKBOXCVAR("Deluxemapping", r_deluxemapping_cvar, 0), MB_CHECKBOXCVAR("Specular Highlights", gl_specular, 0), // MB_CHECKBOXCVAR("Detail Textures", gl_detail, 0), MB_CHECKBOXCVAR("offsetmapping", r_glsl_offsetmapping, 0), diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 43a86a7e8..a4d06ab45 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -3000,7 +3000,7 @@ TRACE(("dbg: Surf_NewMap: tp\n")); void Surf_PreNewMap(void) { - r_loadbumpmapping = r_deluxemapping.ival || r_glsl_offsetmapping.ival; + r_loadbumpmapping = r_deluxemapping || r_glsl_offsetmapping.ival; #ifdef RTLIGHTS r_loadbumpmapping |= r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival; #endif diff --git a/engine/client/render.h b/engine/client/render.h index 544827616..3a99c38c0 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -568,7 +568,10 @@ extern cvar_t r_telestyle; extern cvar_t r_dynamic; extern cvar_t r_novis; extern cvar_t r_netgraph; -extern cvar_t r_deluxemapping; +extern cvar_t r_deluxemapping_cvar; +extern qboolean r_deluxemapping; +extern cvar_t r_softwarebanding_cvar; +extern qboolean r_softwarebanding; #ifdef R_XFLIP extern cvar_t r_xflip; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index e80e9ff24..febcbb36c 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -39,8 +39,13 @@ void QDECL SCR_Viewsize_Callback (struct cvar_s *var, char *oldvalue); void QDECL SCR_Fov_Callback (struct cvar_s *var, char *oldvalue); void QDECL Image_TextureMode_Callback (struct cvar_s *var, char *oldvalue); +#ifdef FTE_TARGET_WEB //webgl sucks too much to get a stable framerate without vsync. +cvar_t vid_vsync = CVARAF ("vid_wait", "1", + "vid_vsync", CVAR_ARCHIVE); +#else cvar_t vid_vsync = CVARAF ("vid_wait", "0", "vid_vsync", CVAR_ARCHIVE); +#endif cvar_t _windowed_mouse = CVARF ("_windowed_mouse","1", CVAR_ARCHIVE); @@ -71,7 +76,7 @@ cvar_t r_bouncysparks = CVARFD ("r_bouncysparks", "1", CVAR_ARCHIVE, "Enables particle interaction with world surfaces, allowing for bouncy particles, stains, and decals."); cvar_t r_drawentities = CVAR ("r_drawentities", "1"); -cvar_t r_drawflat = CVARF ("r_drawflat", "0", +cvar_t r_drawflat = CVARAF ("r_drawflat", "0", "gl_textureless", CVAR_ARCHIVE | CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM); cvar_t r_wireframe = CVARFD ("r_wireframe", "0", CVAR_CHEAT, "Developer feature where everything is drawn with wireframe over the top. Only active where cheats are permitted."); @@ -135,7 +140,8 @@ 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 = SCVARF ("r_skybox", "", CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM); -cvar_t r_softwarebanding = CVARFD ("r_softwarebanding", "0", CVAR_SHADERSYSTEM, "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, "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 = SCVAR ("r_speeds", "0"); cvar_t r_stainfadeammount = SCVAR ("r_stainfadeammount", "1"); cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1"); @@ -283,8 +289,9 @@ cvar_t gl_ati_truform_type = CVAR ("gl_ati_truform_type", "1"); cvar_t gl_ati_truform_tesselation = CVAR ("gl_ati_truform_tesselation", "3"); cvar_t gl_blend2d = CVAR ("gl_blend2d", "1"); cvar_t gl_blendsprites = CVARD ("gl_blendsprites", "0", "Blend sprites instead of alpha testing them"); -cvar_t r_deluxemapping = CVARAFD ("r_deluxemapping", "0", "r_glsl_deluxemapping", - CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Enables bumpmapping based upon precomputed light directions"); +cvar_t r_deluxemapping_cvar = CVARAFD ("r_deluxemapping", "0", "r_glsl_deluxemapping", + CVAR_ARCHIVE, "Enables bumpmapping based upon precomputed light directions"); +qboolean r_deluxemapping; cvar_t r_shaderblobs = CVARD ("r_shaderblobs", "0", "If enabled, can massively accelerate vid restarts / loading (especially with the d3d renderer). Can cause issues when upgrading engine versions, so this is disabled by default."); cvar_t gl_compress = CVARFD ("gl_compress", "0", CVAR_ARCHIVE, "Enable automatic texture compression even for textures which are not pre-compressed."); cvar_t gl_conback = CVARFDC ("gl_conback", "", @@ -451,7 +458,7 @@ void GLRenderer_Init(void) Cvar_Register (&gl_smoothcrosshair, GRAPHICALNICETIES); - Cvar_Register (&r_deluxemapping, GRAPHICALNICETIES); + Cvar_Register (&r_deluxemapping_cvar, GRAPHICALNICETIES); Cvar_Register (&r_glsl_offsetmapping, GRAPHICALNICETIES); Cvar_Register (&r_glsl_offsetmapping_scale, GRAPHICALNICETIES); Cvar_Register (&r_glsl_offsetmapping_reliefmapping, GRAPHICALNICETIES); @@ -668,7 +675,7 @@ void Renderer_Init(void) Cvar_Register (&r_mirroralpha, GLRENDEREROPTIONS); Cvar_Register (&r_skyboxname, GRAPHICALNICETIES); Cbuf_AddText("alias sky r_skybox\n", RESTRICT_LOCAL); /*alternative name for users*/ - Cvar_Register (&r_softwarebanding, GRAPHICALNICETIES); + Cvar_Register (&r_softwarebanding_cvar, GRAPHICALNICETIES); Cvar_Register(&r_dodgytgafiles, "Bug fixes"); Cvar_Register(&r_dodgypcxfiles, "Bug fixes"); @@ -1111,6 +1118,9 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr) pmove.numphysent = 0; pmove.physents[0].model = NULL; + r_softwarebanding = r_softwarebanding_cvar.ival; + r_deluxemapping = r_deluxemapping_cvar.ival; + if (qrenderer != QR_NONE) //graphics stuff only when not dedicated { size_t sz; diff --git a/engine/client/sbar.c b/engine/client/sbar.c index c8c86b7f4..693b4f2b3 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -2155,7 +2155,7 @@ void Sbar_DrawScoreboard (void) if (cl.spectator) { int t = cl.playerview[pnum].cam_spec_track; - if (t < 0) + if (t < 0 || !CAM_ISLOCKED(&cl.playerview[pnum])) continue; if (cl.players[t].statsf[STAT_HEALTH] <= 0) deadcount++; diff --git a/engine/client/snd_al.c b/engine/client/snd_al.c index dfb511a32..406700fac 100644 --- a/engine/client/snd_al.c +++ b/engine/client/snd_al.c @@ -14,8 +14,11 @@ FIXME: a capture device would be useful (voice chat). #ifdef AVAIL_OPENAL #ifdef FTE_TARGET_WEB -//our javascript port doesn't support dynamic linking. -#define OPENAL_STATIC + //emscripten provides an openal -> webaudio wrapper. its not the best, but does get the job done. + #define OPENAL_STATIC //our javascript port doesn't support dynamic linking (bss+data segments get too messy). + #define SDRVNAME "WebAudio" //IE doesn't support webaudio, resulting in noticable error messages about no openal, which is technically incorrect. So lets be clear about this. +#else + #define SDRVNAME "OpenAL" #endif #ifdef OPENAL_STATIC @@ -278,7 +281,7 @@ static AL_API ALvoid (AL_APIENTRY *palEffectf)(ALuint effect, ALenum param, ALfl static AL_API ALvoid (AL_APIENTRY *palEffectfv)(ALuint effect, ALenum param, const ALfloat *pflValues); #endif -#define SOUNDVARS "OpenAL variables" +#define SOUNDVARS SDRVNAME" variables" extern sfx_t *known_sfx; @@ -830,13 +833,13 @@ static qboolean OpenAL_Init(soundcardinfo_t *sc, const char *devname) if (!OpenAL_InitLibrary()) { - Con_Printf("OpenAL is not installed\n"); + Con_Printf(SDRVNAME" is not installed\n"); return false; } if (oali->OpenAL_Context) { - Con_Printf("OpenAL: only able to load one device at a time\n"); + Con_Printf(SDRVNAME": only able to load one device at a time\n"); return false; } @@ -1085,17 +1088,17 @@ static qboolean QDECL OpenAL_InitCard(soundcardinfo_t *sc, const char *devname) if (!devname || !*devname) devname = palcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); - Con_Printf("Initiating OpenAL: %s.\n", devname); + Con_Printf("Initiating "SDRVNAME": %s.\n", devname); if (OpenAL_Init(sc, devname) == false) { - Con_Printf(CON_ERROR "OpenAL init failed\n"); + Con_Printf(CON_ERROR SDRVNAME " init failed\n"); return false; } oali = sc->handle; - Con_DPrintf("OpenAL AL Extension : %s\n",palGetString(AL_EXTENSIONS)); - Con_DPrintf("OpenAL ALC Extension : %s\n",palcGetString(oali->OpenAL_Device,ALC_EXTENSIONS)); + Con_DPrintf(SDRVNAME" AL Extension : %s\n",palGetString(AL_EXTENSIONS)); + Con_DPrintf(SDRVNAME" ALC Extension : %s\n",palcGetString(oali->OpenAL_Device,ALC_EXTENSIONS)); sc->Lock = OpenAL_LockBuffer; sc->Unlock = OpenAL_UnlockBuffer; @@ -1142,7 +1145,6 @@ static qboolean QDECL OpenAL_InitCard(soundcardinfo_t *sc, const char *devname) return true; } -#define SDRVNAME "OpenAL" static qboolean QDECL OpenAL_Enumerate(void (QDECL *callback)(const char *driver, const char *devicecode, const char *readabledevice)) { const char *devnames; @@ -1154,7 +1156,11 @@ static qboolean QDECL OpenAL_Enumerate(void (QDECL *callback)(const char *driver devnames = palcGetString(NULL, ALC_DEVICE_SPECIFIER); while(*devnames) { +#ifdef FTE_TARGET_WEB + callback(SDRVNAME, devnames, va("WebAudio:%s", devnames)); +#else callback(SDRVNAME, devnames, va("OAL:%s", devnames)); +#endif devnames += strlen(devnames)+1; } return true; diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index c23dd3384..02a9b65ce 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -4275,4 +4275,122 @@ void Sys_Sleep (double seconds) { Sleep(seconds * 1000); } + + + + +HCURSOR hArrowCursor, hCustomCursor; +void *WIN_CreateCursor(char *filename, float hotx, float hoty, float scale) +{ + int width, height; + BITMAPV5HEADER bi; + DWORD x,y; + HCURSOR hAlphaCursor = NULL; + ICONINFO ii; + HDC maindc; + + qbyte *rgbadata, *rgbadata_start, *bgradata, *bgradata_start; + qboolean hasalpha; + void *filedata; + int filelen; + if (!filename || !*filename) + return NULL; + filelen = FS_LoadFile(filename, &filedata); + if (!filedata) + return NULL; + + rgbadata_start = Read32BitImageFile(filedata, filelen, &width, &height, &hasalpha, "cursor"); + FS_FreeFile(filedata); + if (!rgbadata_start) + return NULL; + + if (scale != 1) + { + int nw,nh; + qbyte *nd; + nw = width * scale; + nh = height * scale; + if (nw <= 0 || nh <= 0 || nw > 128 || nh > 128) //don't go crazy. + return NULL; + nd = BZ_Malloc(nw*nh*4); + Image_ResampleTexture((unsigned int*)rgbadata_start, width, height, (unsigned int*)nd, nw, nh); + width = nw; + height = nh; + BZ_Free(rgbadata_start); + rgbadata_start = nd; + } + + memset(&bi,0, sizeof(BITMAPV5HEADER)); + bi.bV5Size = sizeof(BITMAPV5HEADER); + bi.bV5Width = width; + bi.bV5Height = height; + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + // The following mask specification specifies a supported 32 BPP + // alpha format for Windows XP. + //FIXME: can we not just specify it as RGBA? meh. + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + // Create the DIB section with an alpha channel. + maindc = GetDC(mainwindow); + ii.hbmColor = CreateDIBSection(maindc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&bgradata_start, NULL, 0); + ReleaseDC(mainwindow, maindc); + + if (!ii.hbmColor) + { + BZ_Free(rgbadata_start); + return NULL; + } + + for (rgbadata=rgbadata_start,y=0;ymodelindex; + bestidx = ent->number; bestskin = ent->skinnum; *pitem = item; } } + if (!bestidx) + for (i=1; imodelindex]; + if (!item) + continue; + if ( ! (item->itemflag & flags) ) + continue; + + VectorCopy(baseline->origin, v); + VectorSubtract (v, org, v); + VectorAdd (v, item->offset, v); + dist = VectorLength (v); +// Com_Printf ("%s %f\n", item->modelname, dist); + + if (dist <= bestdist) { + bestdist = dist; + bestidx = i; + bestskin = baseline->skinnum; + *pitem = item; + } + } + if (bestidx && (*pitem)->itemflag == it_armor) - return bestskin + 1; // 1=green, 2=yellow, 3=red + if (bestskin >= 0 && bestskin <= 3) + *pitem += bestskin + 1; return bestidx; } @@ -2708,7 +2741,7 @@ static qboolean CheckTrigger (void) return count; } -static void ExecTookTrigger (char *s, int flag, vec3_t org) +static void ExecTookTrigger_ (char *s, int flag, vec3_t org) { int pkflags_dmm, tookflags_dmm; @@ -2732,6 +2765,34 @@ static void ExecTookTrigger (char *s, int flag, vec3_t org) TP_ExecTrigger ("f_took", false); } +/* +void TP_GetSimpleItemTexture () +{ +} +*/ + +static void TP_ItemTaken (char *s, int flag, vec3_t org, int entnum, item_t *item, int seat) +{ + if (seat == 0) + ExecTookTrigger_(s, flag, org); + +/* if (entnum < cl_baselines_count && cl_baselines[entnum].modelindex && item && item->respawntime && (cl.spectator || cls.demoplayback)) + { + struct itemtimer_s *timer = Z_Malloc(sizeof(*timer)); + timer->next = cl.itemtimers; + cl.itemtimers = timer; + timer->origin[0] = cl_baselines[entnum].origin[0] + item->offset[0]; + timer->origin[1] = cl_baselines[entnum].origin[1] + item->offset[1]; + timer->origin[2] = cl_baselines[entnum].origin[2]; + timer->start = cl.time; + timer->duration = item->respawntime; + timer->end = cl.time + item->respawntime; + timer->radius = item->radius; + timer->entnum = entnum; + } +*/ +} + void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_info_t *info) { // if (TP_NeedRefreshSkins()) @@ -2763,7 +2824,7 @@ void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_ { if ((state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && !(oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2))) { - ExecTookTrigger (tp_name_flag.string, it_flag, cl.inframes[cl.validsequence & UPDATE_MASK].playerstate[cl.playerview[SP].playernum].origin); + ExecTookTrigger_ (tp_name_flag.string, it_flag, cl.inframes[cl.validsequence & UPDATE_MASK].playerstate[cl.playerview[SP].playernum].origin); } else if (!(state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && (oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2))) { @@ -2773,24 +2834,47 @@ void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_ } } -void TP_CheckPickupSound (char *s, vec3_t org) +void TP_CheckPickupSound (char *s, vec3_t org, int seat) { + int entnum; + item_t *item; + //if we're spectating, we don't want to do any actual triggers, so pretend it was someone else. if (cl.spectator) - return; + seat = -1; + + //FIXME: on items/itembk2.wav kill relevant item timer. if (!strcmp(s, "items/damage.wav")) - ExecTookTrigger (tp_name_quad.string, it_quad, org); + { + entnum = FindNearestItem (org, it_quad, &item); + TP_ItemTaken (tp_name_quad.string, it_quad, org, entnum, item, seat); + } else if (!strcmp(s, "items/protect.wav")) - ExecTookTrigger (tp_name_pent.string, it_pent, org); + { + entnum = FindNearestItem (org, it_pent, &item); + TP_ItemTaken (tp_name_pent.string, it_pent, org, entnum, item, seat); + } else if (!strcmp(s, "items/inv1.wav")) - ExecTookTrigger (tp_name_ring.string, it_ring, org); + { + entnum = FindNearestItem (org, it_ring, &item); + TP_ItemTaken (tp_name_ring.string, it_ring, org, entnum, item, seat); + } else if (!strcmp(s, "items/suit.wav")) - ExecTookTrigger (tp_name_suit.string, it_suit, org); + { + entnum = FindNearestItem (org, it_suit, &item); + TP_ItemTaken (tp_name_suit.string, it_suit, org, entnum, item, seat); + } else if (!strcmp(s, "items/health1.wav") || !strcmp(s, "items/r_item1.wav")) - ExecTookTrigger (tp_name_health.string, it_health, org); + { + entnum = FindNearestItem (org, it_health, &item); + TP_ItemTaken (tp_name_health.string, it_health, org, entnum, item, seat); + } else if (!strcmp(s, "items/r_item2.wav")) - ExecTookTrigger (tp_name_mh.string, it_mh, org); + { + entnum = FindNearestItem (org, it_mh, &item); + TP_ItemTaken (tp_name_mh.string, it_mh, org, entnum, item, seat); + } else goto more; return; @@ -2802,27 +2886,26 @@ more: // weapons if (!strcmp(s, "weapons/pkup.wav")) { - item_t *item; - if (FindNearestItem (it_weapons, &item)) { - ExecTookTrigger (item->cvar->string, item->itemflag, org); - } - else + entnum = FindNearestItem (org, it_weapons, &item); + if (item) + TP_ItemTaken (item->cvar->string, item->itemflag, org, entnum, item, seat); + else if (seat >= 0) { // we don't know what entity caused the sound, try to guess... if (vars.stat_framecounts[STAT_ITEMS] == cls.framecount) { if (vars.items & ~vars.olditems & IT_LIGHTNING) - ExecTookTrigger (tp_name_lg.string, it_lg, cl.playerview[SP].simorg); + TP_ItemTaken (tp_name_lg.string, it_lg, cl.playerview[SP].simorg, entnum, item, seat); else if (vars.items & ~vars.olditems & IT_ROCKET_LAUNCHER) - ExecTookTrigger (tp_name_rl.string, it_rl, cl.playerview[SP].simorg); + TP_ItemTaken (tp_name_rl.string, it_rl, cl.playerview[SP].simorg, entnum, item, seat); else if (vars.items & ~vars.olditems & IT_GRENADE_LAUNCHER) - ExecTookTrigger (tp_name_gl.string, it_gl, cl.playerview[SP].simorg); + TP_ItemTaken (tp_name_gl.string, it_gl, cl.playerview[SP].simorg, entnum, item, seat); else if (vars.items & ~vars.olditems & IT_SUPER_NAILGUN) - ExecTookTrigger (tp_name_sng.string, it_sng, cl.playerview[SP].simorg); + TP_ItemTaken (tp_name_sng.string, it_sng, cl.playerview[SP].simorg, entnum, item, seat); else if (vars.items & ~vars.olditems & IT_NAILGUN) - ExecTookTrigger (tp_name_ng.string, it_ng, cl.playerview[SP].simorg); + TP_ItemTaken (tp_name_ng.string, it_ng, cl.playerview[SP].simorg, entnum, item, seat); else if (vars.items & ~vars.olditems & IT_SUPER_SHOTGUN) - ExecTookTrigger (tp_name_ssg.string, it_ssg, cl.playerview[SP].simorg); + TP_ItemTaken (tp_name_ssg.string, it_ssg, cl.playerview[SP].simorg, entnum, item, seat); } } return; @@ -2833,16 +2916,20 @@ more: { item_t *item; qbool armor_updated; - int armortype; armor_updated = (vars.stat_framecounts[STAT_ARMOR] == cls.framecount); - armortype = FindNearestItem (it_armor, &item); - if (armortype == 1 || (!armortype && armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 100)) - ExecTookTrigger (tp_name_ga.string, it_ga, org); - else if (armortype == 2 || (!armortype && armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 150)) - ExecTookTrigger (tp_name_ya.string, it_ya, org); - else if (armortype == 3 || (!armortype && armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 200)) - ExecTookTrigger (tp_name_ra.string, it_ra, org); + entnum = FindNearestItem (org, it_armor, &item); + if (item) + TP_ItemTaken (item->cvar->string, item->itemflag, org, entnum, item, seat); + else if (seat >= 0) + { + if (armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 100) + TP_ItemTaken (tp_name_ga.string, it_ga, org, entnum, NULL, seat); + else if (armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 150) + TP_ItemTaken (tp_name_ya.string, it_ya, org, entnum, NULL, seat); + else if (armor_updated && cl.playerview[SP].stats[STAT_ARMOR] == 200) + TP_ItemTaken (tp_name_ra.string, it_ra, org, entnum, NULL, seat); + } return; } @@ -2850,9 +2937,10 @@ more: if (!strcmp (s, "weapons/lock4.wav")) { item_t *item; - if (!FindNearestItem (it_ammo|it_pack|it_runes, &item)) + entnum = FindNearestItem (org, it_ammo|it_pack|it_runes, &item); + if (!item && seat < 0) return; - ExecTookTrigger (item->cvar->string, item->itemflag, org); + TP_ItemTaken (item->cvar->string, item->itemflag, org, entnum, item, seat); } } @@ -3290,7 +3378,7 @@ void TP_StatChanged (int stat, int value) if (i & (IT_KEY1|IT_KEY2)) { if (cl.teamfortress && !cl.spectator) { - ExecTookTrigger (tp_name_flag.string, it_flag, + ExecTookTrigger_ (tp_name_flag.string, it_flag, cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[cl.playerview[SP].playernum].origin); } } diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index 7d73c8bbe..7c473dd9f 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -31,7 +31,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define FTEPLUGIN #define pCvar_Register Cvar_Get #define pCvar_GetFloat(x) Cvar_FindVar(x)->value -#define pSys_Error Sys_Error +#define Sys_Errorf Sys_Error +#define pSys_Error(p) Sys_Errorf("%s",p) #define Plug_Init Plug_ODE_Init #endif @@ -2228,7 +2229,7 @@ static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed) dMassSetCylinderTotal(&mass, massval, axisindex+1, radius, length); break; default: - pSys_Error(va("World_ODE_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid)); + Sys_Errorf("World_ODE_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid); } Matrix3x4_InvertTo4x4_Simple(ed->ode.ode_offsetmatrix, ed->ode.ode_offsetimatrix); ed->ode.ode_massbuf = BZ_Malloc(sizeof(dMass)); diff --git a/engine/d3d/d3d11_backend.c b/engine/d3d/d3d11_backend.c index cf598e25f..32ab87f7c 100644 --- a/engine/d3d/d3d11_backend.c +++ b/engine/d3d/d3d11_backend.c @@ -1946,20 +1946,20 @@ static void BE_ApplyUniforms(program_t *prog, int permu) shaderstate.lcbuffer //light buffer that changes rarelyish }; //FIXME: how many of these calls can we avoid? - ID3D11DeviceContext_IASetInputLayout(d3ddevctx, prog->permu[permu].handle.hlsl.layout); - ID3D11DeviceContext_VSSetShader(d3ddevctx, prog->permu[permu].handle.hlsl.vert, NULL, 0); - ID3D11DeviceContext_HSSetShader(d3ddevctx, prog->permu[permu].handle.hlsl.hull, NULL, 0); - ID3D11DeviceContext_DSSetShader(d3ddevctx, prog->permu[permu].handle.hlsl.domain, NULL, 0); - ID3D11DeviceContext_GSSetShader(d3ddevctx, prog->permu[permu].handle.hlsl.geom, NULL, 0); - ID3D11DeviceContext_PSSetShader(d3ddevctx, prog->permu[permu].handle.hlsl.frag, NULL, 0); - ID3D11DeviceContext_IASetPrimitiveTopology(d3ddevctx, prog->permu[permu].handle.hlsl.topology); + ID3D11DeviceContext_IASetInputLayout(d3ddevctx, prog->permu[permu].h.hlsl.layout); + ID3D11DeviceContext_VSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.vert, NULL, 0); + ID3D11DeviceContext_HSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.hull, NULL, 0); + ID3D11DeviceContext_DSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.domain, NULL, 0); + ID3D11DeviceContext_GSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.geom, NULL, 0); + ID3D11DeviceContext_PSSetShader(d3ddevctx, prog->permu[permu].h.hlsl.frag, NULL, 0); + ID3D11DeviceContext_IASetPrimitiveTopology(d3ddevctx, prog->permu[permu].h.hlsl.topology); ID3D11DeviceContext_VSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); - if (prog->permu[permu].handle.hlsl.hull) + if (prog->permu[permu].h.hlsl.hull) ID3D11DeviceContext_HSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); - if (prog->permu[permu].handle.hlsl.domain) + if (prog->permu[permu].h.hlsl.domain) ID3D11DeviceContext_DSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); - if (prog->permu[permu].handle.hlsl.geom) + if (prog->permu[permu].h.hlsl.geom) ID3D11DeviceContext_GSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); ID3D11DeviceContext_PSSetConstantBuffers(d3ddevctx, 0, 3, cbuf); } @@ -1971,13 +1971,13 @@ static void BE_RenderMeshProgram(const shader_t *s, unsigned int vertcount, unsi program_t *p = s->prog; - if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.hlsl.vert) + if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].h.loaded) perm |= PERMUTATION_BUMPMAP; - if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.hlsl.vert) + if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].h.loaded) perm |= PERMUTATION_FULLBRIGHT; - if (p->permu[perm|PERMUTATION_UPPERLOWER].handle.hlsl.vert && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay))) + if (p->permu[perm|PERMUTATION_UPPERLOWER].h.loaded && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay))) perm |= PERMUTATION_UPPERLOWER; - if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.hlsl.vert) + if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].h.loaded) perm |= PERMUTATION_FOG; // if (r_glsl_offsetmapping.ival && TEXLOADED(shaderstate.curtexnums->bump) && p->handle[perm|PERMUTATION_OFFSET.hlsl.vert) // perm |= PERMUTATION_OFFSET; diff --git a/engine/d3d/d3d11_shader.c b/engine/d3d/d3d11_shader.c index ba78e6bc6..5f9e67fb0 100644 --- a/engine/d3d/d3d11_shader.c +++ b/engine/d3d/d3d11_shader.c @@ -220,9 +220,9 @@ void D3D11Shader_DeleteProg(program_t *prog, unsigned int permu) ID3D11InputLayout *layout; ID3D11PixelShader *frag; ID3D11VertexShader *vert; - vert = prog->permu[permu].handle.hlsl.vert; - frag = prog->permu[permu].handle.hlsl.frag; - layout = prog->permu[permu].handle.hlsl.layout; + vert = prog->permu[permu].h.hlsl.vert; + frag = prog->permu[permu].h.hlsl.frag; + layout = prog->permu[permu].h.hlsl.layout; if (vert) ID3D11VertexShader_Release(vert); if (frag) @@ -241,25 +241,25 @@ static qboolean D3D11Shader_CreateShaders(program_t *prog, const char *name, int { qboolean success = true; - if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, vblob, vsize, NULL, (ID3D11VertexShader**)&prog->permu[permu].handle.hlsl.vert))) + if (FAILED(ID3D11Device_CreateVertexShader(pD3DDev11, vblob, vsize, NULL, (ID3D11VertexShader**)&prog->permu[permu].h.hlsl.vert))) success = false; if (hblob || dblob) { - prog->permu[permu].handle.hlsl.topology = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; - if (FAILED(ID3D11Device_CreateHullShader(pD3DDev11, hblob, hsize, NULL, (ID3D11HullShader**)&prog->permu[permu].handle.hlsl.hull))) + prog->permu[permu].h.hlsl.topology = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; + if (FAILED(ID3D11Device_CreateHullShader(pD3DDev11, hblob, hsize, NULL, (ID3D11HullShader**)&prog->permu[permu].h.hlsl.hull))) success = false; - if (FAILED(ID3D11Device_CreateDomainShader(pD3DDev11, dblob, dsize, NULL, (ID3D11DomainShader**)&prog->permu[permu].handle.hlsl.domain))) + if (FAILED(ID3D11Device_CreateDomainShader(pD3DDev11, dblob, dsize, NULL, (ID3D11DomainShader**)&prog->permu[permu].h.hlsl.domain))) success = false; } else - prog->permu[permu].handle.hlsl.topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + prog->permu[permu].h.hlsl.topology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - if (gblob && FAILED(ID3D11Device_CreateGeometryShader(pD3DDev11, gblob, gsize, NULL, (ID3D11GeometryShader**)&prog->permu[permu].handle.hlsl.geom))) + if (gblob && FAILED(ID3D11Device_CreateGeometryShader(pD3DDev11, gblob, gsize, NULL, (ID3D11GeometryShader**)&prog->permu[permu].h.hlsl.geom))) success = false; - if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, fblob, fsize, NULL, (ID3D11PixelShader**)&prog->permu[permu].handle.hlsl.frag))) + if (FAILED(ID3D11Device_CreatePixelShader(pD3DDev11, fblob, fsize, NULL, (ID3D11PixelShader**)&prog->permu[permu].h.hlsl.frag))) success = false; if (success) @@ -350,7 +350,7 @@ static qboolean D3D11Shader_CreateShaders(program_t *prog, const char *name, int decl[elements].InstanceDataStepRate = 0; elements++; */ - if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, vblob, vsize, (ID3D11InputLayout**)&prog->permu[permu].handle.hlsl.layout))) + if (FAILED(ID3D11Device_CreateInputLayout(pD3DDev11, decl, elements, vblob, vsize, (ID3D11InputLayout**)&prog->permu[permu].h.hlsl.layout))) { Con_Printf("HLSL Shader %s requires unsupported inputs\n", name); success = false; @@ -479,12 +479,12 @@ qboolean D3D11Shader_CreateProgram (program_t *prog, const char *name, unsigned fsformat = "ps_4_0_level_9_1"; } - prog->permu[permu].handle.hlsl.vert = NULL; - prog->permu[permu].handle.hlsl.frag = NULL; - prog->permu[permu].handle.hlsl.hull = NULL; - prog->permu[permu].handle.hlsl.domain = NULL; - prog->permu[permu].handle.hlsl.geom = NULL; - prog->permu[permu].handle.hlsl.layout = NULL; + prog->permu[permu].h.hlsl.vert = NULL; + prog->permu[permu].h.hlsl.frag = NULL; + prog->permu[permu].h.hlsl.hull = NULL; + prog->permu[permu].h.hlsl.domain = NULL; + prog->permu[permu].h.hlsl.geom = NULL; + prog->permu[permu].h.hlsl.layout = NULL; if (pD3DCompile) { diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 4de4e974c..a52974c3f 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -1748,17 +1748,17 @@ static void R_FetchPlayerColour(unsigned int cv, vec3_t rgb) static void BE_ApplyUniforms(program_t *prog, int permu) { + struct programpermu_s *perm = &prog->permu[permu]; + shaderprogparm_t *pp; vec4_t param4; int h; int i; - IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->permu[permu].handle.hlsl.vert); - IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[permu].handle.hlsl.frag); - for (i = 0; i < prog->numparams; i++) + IDirect3DDevice9_SetVertexShader(pD3DDev9, perm->h.hlsl.vert); + IDirect3DDevice9_SetPixelShader(pD3DDev9, perm->h.hlsl.frag); + for (i = 0, pp = perm->parm; i < perm->numparms; i++, pp++) { - h = prog->permu[permu].parm[i]; - if (h == -1) - continue; - switch (prog->parm[i].type) + h = pp->handle; + switch (pp->type) { case SP_M_PROJECTION: IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, d3d_trueprojection, 4); @@ -1865,7 +1865,7 @@ static void BE_ApplyUniforms(program_t *prog, int permu) case SP_CVARF: case SP_CVAR3F: case SP_TEXTURE: - Con_Printf("shader property %i not implemented\n", prog->parm[i].type); + Con_Printf("shader property %i not implemented\n", pp->type); break; } } @@ -1881,27 +1881,27 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in if (shaderstate.batchvbo && shaderstate.batchvbo->numbones) { - if (p->permu[perm|PERMUTATION_SKELETAL].handle.hlsl.vert) + if (p->permu[perm|PERMUTATION_SKELETAL].h.loaded) perm |= PERMUTATION_SKELETAL; else return; } - if (TEXVALID(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.hlsl.vert) + if (TEXVALID(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].h.loaded) perm |= PERMUTATION_BUMPMAP; - if (TEXVALID(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.hlsl.vert) + if (TEXVALID(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].h.loaded) perm |= PERMUTATION_FULLBRIGHT; - if (p->permu[perm|PERMUTATION_UPPERLOWER].handle.hlsl.vert && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay))) + if (p->permu[perm|PERMUTATION_UPPERLOWER].h.loaded && (TEXLOADED(shaderstate.curtexnums->upperoverlay) || TEXLOADED(shaderstate.curtexnums->loweroverlay))) perm |= PERMUTATION_UPPERLOWER; - if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.hlsl.vert) + if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].h.loaded) perm |= PERMUTATION_FOG; - if (p->permu[perm|PERMUTATION_FRAMEBLEND].handle.hlsl.vert && shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff) + if (p->permu[perm|PERMUTATION_FRAMEBLEND].h.loaded && shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff) { perm |= PERMUTATION_FRAMEBLEND; vdec |= D3D_VDEC_POS2; } -// if (p->permu[perm|PERMUTATION_DELUXE].handle.hlsl.vert && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) +// if (p->permu[perm|PERMUTATION_DELUXE].h.loaded && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) // perm |= PERMUTATION_DELUXE; - if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.hlsl.vert) + if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].h.loaded) perm |= PERMUTATION_LIGHTSTYLES; BE_ApplyUniforms(p, perm); diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index cb5cb3359..b0363a2d0 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -155,8 +155,8 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un return false; } - prog->permu[permu].handle.hlsl.vert = NULL; - prog->permu[permu].handle.hlsl.frag = NULL; + prog->permu[permu].h.hlsl.vert = NULL; + prog->permu[permu].h.hlsl.frag = NULL; if (pD3DXCompileShader) { @@ -190,11 +190,11 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un success = true; defines[0].Name = "VERTEX_SHADER"; - if (FAILED(pD3DXCompileShader(vert, strlen(vert), defines, NULL, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].handle.hlsl.ctabv))) + if (FAILED(pD3DXCompileShader(vert, strlen(vert), defines, NULL, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].h.hlsl.ctabv))) success = false; else { - IDirect3DDevice9_CreateVertexShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DVertexShader9**)&prog->permu[permu].handle.hlsl.vert); + IDirect3DDevice9_CreateVertexShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DVertexShader9**)&prog->permu[permu].h.hlsl.vert); code->lpVtbl->Release(code); } if (errors) @@ -205,11 +205,11 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un } defines[0].Name = "FRAGMENT_SHADER"; - if (FAILED(pD3DXCompileShader(frag, strlen(frag), defines, NULL, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].handle.hlsl.ctabf))) + if (FAILED(pD3DXCompileShader(frag, strlen(frag), defines, NULL, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->permu[permu].h.hlsl.ctabf))) success = false; else { - IDirect3DDevice9_CreatePixelShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DPixelShader9**)&prog->permu[permu].handle.hlsl.frag); + IDirect3DDevice9_CreatePixelShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DPixelShader9**)&prog->permu[permu].h.hlsl.frag); code->lpVtbl->Release(code); } if (errors) @@ -254,13 +254,13 @@ static int D3D9Shader_FindUniform(union programhandle_u *h, int type, const char return -1; } -static void D3D9Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvartypes) +static void D3D9Shader_ProgAutoFields(program_t *prog, const char *progname, char **cvarnames, int *cvartypes) { + struct programpermu_s *pp; unsigned int i, p; - qboolean found; int uniformloc; char tmpname[128]; - cvar_t *cvar; + cvar_t *cvar[128]; static const char *defaultsamplers[] = { @@ -289,66 +289,76 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cv #define ALTLIGHTMAPSAMP 13 #define ALTDELUXMAPSAMP 16 - prog->numparams = 0; - prog->nofixedcompat = true; + prog->defaulttextures = 0; + prog->numsamplers = 0; - /*set cvar uniforms*/ - for (i = 0; cvarnames[i]; i++) + memset(cvar, 0, sizeof(cvar)); + + for (p = 0; p < PERMUTATIONS; p++) { - for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) - tmpname[p] = cvarnames[i][p]; - tmpname[p] = 0; - cvar = Cvar_FindVar(tmpname); - if (!cvar) + int maxparms = 0; + pp = &prog->permu[p]; + pp->parm = NULL; + pp->numparms = 0; + if (!pp->h.loaded) continue; - cvar->flags |= CVAR_SHADERSYSTEM; - for (p = 0; p < PERMUTATIONS; p++) + IDirect3DDevice9_SetVertexShader(pD3DDev9, pp->h.hlsl.vert); + IDirect3DDevice9_SetPixelShader(pD3DDev9, pp->h.hlsl.frag); + + for (i = 0; shader_unif_names[i].name; i++) { - if (!prog->permu[p].handle.hlsl.vert || !prog->permu[p].handle.hlsl.frag) - continue; - uniformloc = D3D9Shader_FindUniform(&prog->permu[p].handle, 1, va("cvar_%s", tmpname)); + uniformloc = D3D9Shader_FindUniform(&pp->h, 0, shader_unif_names[i].name); if (uniformloc != -1) { - vec4_t v = {cvar->value, 0, 0, 0}; - IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->permu[p].handle.hlsl.vert); + if (pp->numparms == maxparms) + { + maxparms = maxparms?maxparms*2:8; + pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms); + } + pp->parm[pp->numparms].handle = uniformloc; + pp->parm[pp->numparms].type = shader_unif_names[i].ptype; + pp->numparms++; + } + } + + for (i = 0; cvarnames[i] && i < countof(cvar); i++) + { + if (!cvar[i]) + { + for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) + tmpname[p] = cvarnames[i][p]; + tmpname[p] = 0; + cvar[i] = Cvar_FindVar(tmpname); + if (!cvar[i]) + continue; + cvar[i]->flags |= CVAR_SHADERSYSTEM; + } + + uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 1, va("cvar_%s", tmpname)); + if (uniformloc != -1) + { + vec4_t v = {cvar[i]->value, 0, 0, 0}; + IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->permu[p].h.hlsl.vert); IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, v, 1); } - uniformloc = D3D9Shader_FindUniform(&prog->permu[p].handle, 2, va("cvar_%s", tmpname)); + uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, va("cvar_%s", tmpname)); if (uniformloc != -1) { - vec4_t v = {cvar->value, 0, 0, 0}; - IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].handle.hlsl.frag); + vec4_t v = {cvar[i]->value, 0, 0, 0}; + IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].h.hlsl.frag); IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, v, 1); } } - } - for (i = 0; shader_unif_names[i].name; i++) - { - found = false; - for (p = 0; p < PERMUTATIONS; p++) - { - uniformloc = D3D9Shader_FindUniform(&prog->permu[p].handle, 0, shader_unif_names[i].name); - if (uniformloc != -1) - found = true; - prog->permu[p].parm[prog->numparams] = uniformloc; - } - if (found) - { - prog->parm[prog->numparams].type = shader_unif_names[i].ptype; - prog->numparams++; - } - } - /*set texture uniforms*/ - for (p = 0; p < PERMUTATIONS; p++) - { + + /*set texture uniforms*/ for (i = 0; i < 8; i++) { - uniformloc = D3D9Shader_FindUniform(&prog->permu[p].handle, 2, va("s_t%i", i)); + uniformloc = D3D9Shader_FindUniform(&pp->h, 2, va("s_t%i", i)); if (uniformloc != -1) { int v[4] = {i}; - IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].handle.hlsl.frag); + IDirect3DDevice9_SetPixelShader(pD3DDev9, pp->h.hlsl.frag); IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1); if (prog->numsamplers < i+1) @@ -361,7 +371,7 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cv //figure out which ones are needed. if (prog->defaulttextures & (1u<permu[p].handle, 2, defaultsamplers[i]); + uniformloc = D3D9Shader_FindUniform(&pp->h, 2, defaultsamplers[i]); if (uniformloc != -1) prog->defaulttextures |= (1u<permu[p].handle.glsl.handle) + if (!prog->permu[p].h.loaded) continue; sampnum = prog->numsamplers; for (i = 0; i < sizeof(defaultsamplers)/sizeof(defaultsamplers[0]); i++) { if (prog->defaulttextures & (1u<permu[p].handle, 2, defaultsamplers[i]); + uniformloc = D3D9Shader_FindUniform(&prog->permu[p].h, 2, defaultsamplers[i]); if (uniformloc != -1) { int v[4] = {sampnum}; - IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].handle.hlsl.frag); + IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->permu[p].h.hlsl.frag); IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1); } sampnum++; @@ -404,28 +414,28 @@ static void D3D9Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cv void D3D9Shader_DeleteProg(program_t *prog, unsigned int permu) { - if (prog->permu[permu].handle.hlsl.vert) + if (prog->permu[permu].h.hlsl.vert) { - IDirect3DVertexShader9 *vs = prog->permu[permu].handle.hlsl.vert; - prog->permu[permu].handle.hlsl.vert = NULL; + IDirect3DVertexShader9 *vs = prog->permu[permu].h.hlsl.vert; + prog->permu[permu].h.hlsl.vert = NULL; IDirect3DVertexShader9_Release(vs); } - if (prog->permu[permu].handle.hlsl.frag) + if (prog->permu[permu].h.hlsl.frag) { - IDirect3DPixelShader9 *fs = prog->permu[permu].handle.hlsl.frag; - prog->permu[permu].handle.hlsl.frag = NULL; + IDirect3DPixelShader9 *fs = prog->permu[permu].h.hlsl.frag; + prog->permu[permu].h.hlsl.frag = NULL; IDirect3DPixelShader9_Release(fs); } - if (prog->permu[permu].handle.hlsl.ctabv) + if (prog->permu[permu].h.hlsl.ctabv) { - LPD3DXCONSTANTTABLE vct = prog->permu[permu].handle.hlsl.ctabv; - prog->permu[permu].handle.hlsl.ctabv = NULL; + LPD3DXCONSTANTTABLE vct = prog->permu[permu].h.hlsl.ctabv; + prog->permu[permu].h.hlsl.ctabv = NULL; IUnknown_Release(vct); } - if (prog->permu[permu].handle.hlsl.ctabf) + if (prog->permu[permu].h.hlsl.ctabf) { - LPD3DXCONSTANTTABLE fct = prog->permu[permu].handle.hlsl.ctabf; - prog->permu[permu].handle.hlsl.ctabf = NULL; + LPD3DXCONSTANTTABLE fct = prog->permu[permu].h.hlsl.ctabf; + prog->permu[permu].h.hlsl.ctabf = NULL; IUnknown_Release(fct); } } diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index f9e70cb04..b9895eb50 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -346,6 +346,25 @@ static LRESULT WINAPI D3D9_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA INS_RawInput_Read((HANDLE)lParam); break; + case WM_SETCURSOR: + //only use a custom cursor if the cursor is inside the client area + switch(lParam&0xffff) + { + case 0: + break; + case HTCLIENT: + if (hCustomCursor) //custom cursor enabled + SetCursor(hCustomCursor); + else //fallback on an arrow cursor, just so we have something visible at startup or so + SetCursor(hArrowCursor); + lRet = TRUE; + break; + default: + lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam); + break; + } + break; + case WM_GETMINMAXINFO: { RECT windowrect; @@ -665,7 +684,7 @@ static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette) CLASSNAME }; - wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hCursor = hArrowCursor = LoadCursor (NULL,IDC_ARROW); vid_initializing = true; @@ -734,6 +753,12 @@ static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette) // D3D9BE_Reset(false); + //FIXME: old hardware is not guarenteed to support hardware cursors. + //this should not be a problem on dx9+ hardware, but might on earlier stuff. + rf->VID_CreateCursor = WIN_CreateCursor; + rf->VID_DestroyCursor = WIN_DestroyCursor; + rf->VID_SetCursor = WIN_SetCursor; + return true; } diff --git a/engine/d3d/vid_d3d11.c b/engine/d3d/vid_d3d11.c index 979a5e8bf..87af9e6b7 100644 --- a/engine/d3d/vid_d3d11.c +++ b/engine/d3d/vid_d3d11.c @@ -484,6 +484,25 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR INS_RawInput_Read((HANDLE)lParam); break; + case WM_SETCURSOR: + //only use a custom cursor if the cursor is inside the client area + switch(lParam&0xffff) + { + case 0: + break; + case HTCLIENT: + if (hCustomCursor) //custom cursor enabled + SetCursor(hCustomCursor); + else //fallback on an arrow cursor, just so we have something visible at startup or so + SetCursor(hArrowCursor); + lRet = TRUE; + break; + default: + lRet = DefWindowProcW (hWnd, uMsg, wParam, lParam); + break; + } + break; + case WM_GETMINMAXINFO: { RECT windowrect; @@ -921,7 +940,7 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette) }; wc.style = CS_HREDRAW | CS_VREDRAW; - wc.hCursor = LoadCursor (NULL,IDC_ARROW); + wc.hCursor = hArrowCursor = LoadCursor (NULL,IDC_ARROW); wc.hInstance = global_hInstance; vid_initializing = true; @@ -983,6 +1002,10 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette) mouseactive = false; } + rf->VID_CreateCursor = WIN_CreateCursor; + rf->VID_DestroyCursor = WIN_DestroyCursor; + rf->VID_SetCursor = WIN_SetCursor; + return true; } #endif diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index fe9a8271a..6dde88b67 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -710,7 +710,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e (tex->upperoverlay && (tex->upperoverlay->status == TEX_LOADING || tex->upperoverlay->status == TEX_LOADED))) return shader; } - if (shader->prog && shader->prog->permu[PERMUTATION_UPPERLOWER].handle.glsl.handle && !h2playertranslations) + if (shader->prog && shader->prog->permu[PERMUTATION_UPPERLOWER].h.loaded && !h2playertranslations) { //this shader can do permutations. this means we can generate only a black image, with separate top+bottom textures. tc = 0xfe000000; bc = 0xfe000000; @@ -1442,7 +1442,7 @@ void R_GAlias_DrawBatch(batch_t *batch) { if (batch->surf_first == surfnum) { - /*needrecolour =*/ Alias_GAliasBuildMesh(&mesh, &batch->vbo, inf, surfnum, e, batch->shader->prog && batch->shader->prog->permu[PERMUTATION_SKELETAL].handle.glsl.handle); + /*needrecolour =*/ Alias_GAliasBuildMesh(&mesh, &batch->vbo, inf, surfnum, e, batch->shader->prog && batch->shader->prog->permu[PERMUTATION_SKELETAL].h.loaded); batch->mesh = &meshl; if (!mesh.numindexes) { diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 31ad582ac..b7d7c9138 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -2962,13 +2962,10 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, if (entunchanged) return; - for (i = 0; i < prog->numparams; i++) + p = prog->permu[perm].parm; + for (i = prog->permu[perm].numparms; i > 0; i--, p++) { - p = &prog->parm[i]; - ph = prog->permu[perm].parm[i]; - if (ph == -1) - continue; /*not in this permutation*/ - + ph = p->handle; switch(p->type) { /* @@ -3390,39 +3387,39 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas perm = 0; if (shaderstate.sourcevbo->numbones) { - if (p->permu[perm|PERMUTATION_SKELETAL].handle.glsl.handle) + if (p->permu[perm|PERMUTATION_SKELETAL].h.loaded) perm |= PERMUTATION_SKELETAL; else return; } - if (p->permu[perm|PERMUTATION_FRAMEBLEND].handle.glsl.handle && shaderstate.sourcevbo->coord2.gl.addr) + if (p->permu[perm|PERMUTATION_FRAMEBLEND].h.loaded && shaderstate.sourcevbo->coord2.gl.addr) perm |= PERMUTATION_FRAMEBLEND; - if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.glsl.handle) + if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].h.loaded) perm |= PERMUTATION_BUMPMAP; - if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.glsl.handle) + if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].h.loaded) perm |= PERMUTATION_FULLBRIGHT; - if ((TEXLOADED(shaderstate.curtexnums->loweroverlay) || TEXLOADED(shaderstate.curtexnums->upperoverlay)) && p->permu[perm|PERMUTATION_UPPERLOWER].handle.glsl.handle) + if ((TEXLOADED(shaderstate.curtexnums->loweroverlay) || TEXLOADED(shaderstate.curtexnums->upperoverlay)) && p->permu[perm|PERMUTATION_UPPERLOWER].h.loaded) perm |= PERMUTATION_UPPERLOWER; - if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.glsl.handle) + if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].h.loaded) perm |= PERMUTATION_FOG; // if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl.handle && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) // perm |= PERMUTATION_DELUXE; - if (TEXLOADED(shaderstate.curtexnums->reflectcube) && p->permu[perm|PERMUTATION_REFLECTCUBEMASK].handle.glsl.handle) + if (TEXLOADED(shaderstate.curtexnums->reflectcube) && p->permu[perm|PERMUTATION_REFLECTCUBEMASK].h.loaded) perm |= PERMUTATION_REFLECTCUBEMASK; #if MAXRLIGHTMAPS > 1 - if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.glsl.handle) + if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].h.loaded) perm |= PERMUTATION_LIGHTSTYLES; #endif - GL_SelectProgram(p->permu[perm].handle.glsl.handle); + GL_SelectProgram(p->permu[perm].h.glsl.handle); #ifndef FORCESTATE - if (shaderstate.lastuniform == p->permu[perm].handle.glsl.handle) + if (shaderstate.lastuniform == shaderstate.currentprogram) i = true; else #endif { i = false; - shaderstate.lastuniform = p->permu[perm].handle.glsl.handle; + shaderstate.lastuniform = shaderstate.currentprogram; } BE_Program_Set_Attributes(p, perm, i); @@ -3477,7 +3474,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas shaderstate.lastpasstmus = i; //in case it was already lower } BE_EnableShaderAttributes(p->permu[perm].attrmask, shaderstate.sourcevbo->vao); - BE_SubmitMeshChain(p->permu[perm].handle.glsl.usetesselation); + BE_SubmitMeshChain(p->permu[perm].h.glsl.usetesselation); } qboolean GLBE_LightCullModel(vec3_t org, model_t *model) @@ -4856,7 +4853,7 @@ void GLBE_RenderToTextureUpdate2d(qboolean destchanged) else GLBE_FBO_Push(NULL); - GL_Set2D(false); + GL_Set2D(false); } else { diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 84fb82303..83d3fd8cc 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -44,6 +44,8 @@ http://prideout.net/archive/bloom/ contains some sample code #ifdef GLQUAKE #include "shader.h" #include "glquake.h" +#include "gl_draw.h" + cvar_t r_bloom = CVARAFD("r_bloom", "0", "gl_bloom", CVAR_ARCHIVE, "Enables bloom (light bleeding from bright objects). Fractional values reduce the amount shown."); cvar_t r_bloom_filter = CVARD("r_bloom_filter", "0.7 0.7 0.7", "Controls how bright the image must get before it will bloom (3 separate values, in RGB order)."); cvar_t r_bloom_size = CVARD("r_bloom_size", "4", "Target bloom kernel size (assuming a video width of 320)."); @@ -204,11 +206,18 @@ void R_BloomBlend (texid_t source, int x, int y, int w, int h) TEXASSIGN(pingtex[0][0], Image_CreateTexture(name, NULL, IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR)); Image_Upload(pingtex[0][0], TF_RGBA32, NULL, NULL, texwidth[0], texheight[0], IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR); } + + if (R2D_Flush) + R2D_Flush(); + oldfbo = GLBE_FBO_Update(&fbo_bloom, 0, &pingtex[0][0], 1, r_nulltex, 0, 0, 0); GLBE_FBO_Sources(source, r_nulltex); qglViewport (0, 0, texwidth[0], texheight[0]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomfilter); + if (R2D_Flush) + R2D_Flush(); + intex = pingtex[0][0]; for (pixels = 1, i = 0; pixels < targetpixels && i < MAXLEVELS; i++, pixels <<= 1) @@ -227,6 +236,8 @@ void R_BloomBlend (texid_t source, int x, int y, int w, int h) Image_Upload(pingtex[1][i], TF_RGBA32, NULL, NULL, texwidth[i], texheight[i], IF_CLAMP|IF_NOMIPMAP|IF_NOPICMIP|IF_LINEAR); } + if (R2D_Flush) + R2D_Flush(); //downsize the blur, for added accuracy if (i > 0 && r_bloom_downsize.ival) { @@ -235,6 +246,8 @@ void R_BloomBlend (texid_t source, int x, int y, int w, int h) GLBE_FBO_Sources(pingtex[0][i-1], r_nulltex); qglViewport (0, 0, texwidth[i], texheight[i]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomrescale); + if (R2D_Flush) + R2D_Flush(); intex = pingtex[0][i]; r_worldentity.glowmod[0] = 1.0 / intex->width; } @@ -247,6 +260,8 @@ void R_BloomBlend (texid_t source, int x, int y, int w, int h) qglViewport (0, 0, pingtex[1][i]->width, pingtex[1][i]->height); BE_SelectEntity(&r_worldentity); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur); + if (R2D_Flush) + R2D_Flush(); r_worldentity.glowmod[0] = 0; r_worldentity.glowmod[1] = 1.0 / pingtex[1][i]->height; @@ -261,6 +276,9 @@ void R_BloomBlend (texid_t source, int x, int y, int w, int h) r_worldentity.glowmod[0] = 0; r_worldentity.glowmod[1] = 0; + if (R2D_Flush) + R2D_Flush(); + GL_Set2D(false); bloomfinal->defaulttextures->base = intex; diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 8f5edb5f6..141aea3ef 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -5334,7 +5334,7 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) BE_VBO_Data(&ctx, arrays->tvector, sizeof(arrays->tvector [0])*numverts, &bb->vbo.tvector); BE_VBO_Finish(&ctx, arrays->index, sizeof(arrays->index [0])*numindicies, &bb->vbo.indicies); - bb->mesh.xyz_array = (avec4_t*)(bb+1); + bb->mesh.xyz_array = (vecV_t*)(bb+1); memcpy(bb->mesh.xyz_array, arrays->coord, sizeof(*bb->mesh.xyz_array) * numverts); bb->mesh.st_array = (vec2_t*)(bb->mesh.xyz_array+numverts); memcpy(bb->mesh.st_array, arrays->texcoord, sizeof(*bb->mesh.st_array) * numverts); diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 0db1280cf..237c3de32 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -32,7 +32,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern cvar_t r_shadow_bumpscale_basetexture; extern cvar_t r_replacemodels; extern cvar_t gl_lightmap_average; -extern cvar_t r_softwarebanding; cvar_t mod_loadentfiles = CVAR("sv_loadentfiles", "1"); cvar_t mod_loadentfiles_dir = CVAR("sv_loadentfiles_dir", ""); cvar_t mod_external_vis = CVARD("mod_external_vis", "1", "Attempt to load .vis patches for quake maps, allowing transparent water to work properly."); @@ -1743,7 +1742,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean samples = ql2->lmsize; litdata = shifts+ql2->numsurfs; - if (r_deluxemapping.ival) + if (r_deluxemapping) luxdata = litdata+samples*3; } } @@ -1805,7 +1804,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean } - if (!luxdata && r_loadlits.ival && r_deluxemapping.ival) + if (!luxdata && r_loadlits.ival && r_deluxemapping) { //the map util has a '-scalecos X' parameter. use 0 if you're going to use only just lux. without lux scalecos 0 is hideous. char luxname[MAX_QPATH]; size_t luxsz = 0; @@ -1870,7 +1869,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean #endif #ifdef RUNTIMELIGHTING - if (r_loadlits.value == 2 && !lightmodel && (!litdata || (!luxdata && r_deluxemapping.ival))) + if (r_loadlits.value == 2 && !lightmodel && (!litdata || (!luxdata && r_deluxemapping))) { if (!litdata) writelitfile = true; @@ -1897,7 +1896,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean } } /*if we're relighting, make sure there's the proper lux data to be updated*/ - if (lightmodel == loadmodel && r_deluxemapping.ival && !luxdata) + if (lightmodel == loadmodel && r_deluxemapping && !luxdata) { int i; luxdata = ZG_Malloc(&loadmodel->memgroup, samples*3); diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 1d6bd4296..ba7ab7de9 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1652,22 +1652,31 @@ texid_t R_RenderPostProcess (texid_t sourcetex, int type, shader_t *shader, char if (r_refdef.flags & type) { r_refdef.flags &= ~type; - GLBE_FBO_Sources(sourcetex, r_nulltex); if (r_refdef.flags & RDF_ALLPOSTPROC) { //there's other post-processing passes that still need to be applied. //thus we need to write this output to a texture. int w = (r_refdef.vrect.width * vid.pixelwidth) / vid.width; int h = (r_refdef.vrect.height * vid.pixelheight) / vid.height; + if (R2D_Flush) + R2D_Flush(); + GLBE_FBO_Sources(sourcetex, r_nulltex); sourcetex = R2D_RT_Configure(restexname, w, h, TF_RGBA32); GLBE_FBO_Update(&fbo_postproc, 0, &sourcetex, 1, r_nulltex, w, h, 0); - R2D_ScalePic(0, vid.pixelheight-r_refdef.vrect.height, r_refdef.vrect.width, r_refdef.vrect.height, shader); + R2D_ScalePic(0, 0, r_refdef.vrect.width, r_refdef.vrect.height, shader); + if (R2D_Flush) + R2D_Flush(); GLBE_RenderToTextureUpdate2d(true); } else { //yay, dump it to the screen //update stuff now that we're not rendering the 3d scene + if (R2D_Flush) + R2D_Flush(); + GLBE_FBO_Sources(sourcetex, r_nulltex); R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, shader); + if (R2D_Flush) + R2D_Flush(); } } @@ -1916,6 +1925,9 @@ void GLR_RenderView (void) R_BloomBlend(sourcetex, r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height); } + if (R2D_Flush) + R2D_Flush(); + GLBE_FBO_Sources(r_nulltex, r_nulltex); if (gl_motionblur.value>0 && gl_motionblur.value < 1 && qglCopyTexImage2D) diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index a054c0d7b..4666b6d24 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -43,8 +43,7 @@ sh_config_t sh_config; cvar_t r_vertexlight = CVARFD("r_vertexlight", "0", CVAR_SHADERSYSTEM, "Hack loaded shaders to remove detail pass and lightmap sampling for faster rendering."); cvar_t r_forceprogramify = CVARAFD("r_forceprogramify", "0", "dpcompat_makeshitup", CVAR_SHADERSYSTEM, "Reduce the shader to a single texture, and then make stuff up about its mother. The resulting fist fight results in more colour when you shine a light upon its face.\nSet to 2 to ignore 'depthfunc equal' and 'tcmod scale' in order to tolerate bizzare shaders made for a bizzare engine."); extern cvar_t r_glsl_offsetmapping_reliefmapping; -extern cvar_t r_deluxemapping; -extern cvar_t r_fastturb, r_fastsky, r_skyboxname, r_softwarebanding; +extern cvar_t r_fastturb, r_fastsky, r_skyboxname; extern cvar_t r_drawflat; extern cvar_t r_shaderblobs; @@ -269,7 +268,9 @@ static qboolean Shader_EvaluateCondition(shader_t *shader, char **ptr) else if (!Q_stricmp(token, "lightmap")) conditiontrue = conditiontrue == !r_fullbright.value; else if (!Q_stricmp(token, "deluxmap")) - conditiontrue = conditiontrue == r_deluxemapping.ival; + conditiontrue = conditiontrue == r_deluxemapping; + else if (!Q_stricmp(token, "softwarebanding")) + conditiontrue = conditiontrue == r_softwarebanding; //normalmaps are generated if they're not already known. else if (!Q_stricmp(token, "normalmap")) @@ -1368,7 +1369,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip for (p = 0; p < PERMUTATIONS; p++) { - memset(&prog->permu[p].handle, 0, sizeof(prog->permu[p].handle)); + memset(&prog->permu[p].h, 0, sizeof(prog->permu[p].h)); if (nopermutation & p) { continue; @@ -1390,7 +1391,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip permutationdefines[pn++] = "#define RELIEFMAPPING\n"; } - if (r_deluxemapping.ival) //fixme: should be per-model really + if (r_deluxemapping) //fixme: should be per-model really permutationdefines[pn++] = "#define DELUXE\n"; } permutationdefines[pn++] = NULL; @@ -1455,7 +1456,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip } if (sh_config.pProgAutoFields) - sh_config.pProgAutoFields(prog, cvarnames, cvartypes); + sh_config.pProgAutoFields(prog, name, cvarnames, cvartypes); if (blobfile && blobadded) { @@ -1937,7 +1938,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p else token = Shader_ParseSensString(ptr); -#ifdef GLQUAKE +#if 0//def GLQUAKE if (qrenderer == QR_OPENGL) { int p; @@ -5010,7 +5011,7 @@ void Shader_DefaultBSPQ2(const char *shortname, shader_t *s, const void *args) "}\n" ); } - else if (r_softwarebanding.ival) + else if (r_softwarebanding) { /*alpha bended*/ Shader_DefaultScript(shortname, s, @@ -5168,7 +5169,7 @@ void Shader_DefaultBSPQ1(const char *shortname, shader_t *s, const void *args) ); } - if (!builtin && r_softwarebanding.ival) + if (!builtin && r_softwarebanding) { /*alpha bended*/ builtin = ( diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 06d2dbc7f..4df24e5a2 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -2178,7 +2178,7 @@ union programhandle_u GLSlang_CreateProgram(const char *name, int ver, const cha qboolean GLSlang_ValidateProgramPermu(program_t *prog, const char *name, unsigned int permu, qboolean noerrors, vfsfile_t *blobfile) { - return GLSlang_ValidateProgram(&prog->permu[permu].handle, name, noerrors, blobfile); + return GLSlang_ValidateProgram(&prog->permu[permu].h, name, noerrors, blobfile); } qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile) { @@ -2205,8 +2205,8 @@ qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned return false; //can happen in gles2 #endif - prog->permu[permu].handle = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, tcs, tes, geom, frag, noerrors, blobfile); - if (prog->permu[permu].handle.glsl.handle) + prog->permu[permu].h = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, tcs, tes, geom, frag, noerrors, blobfile); + if (prog->permu[permu].h.glsl.handle) return true; return false; } @@ -2233,31 +2233,31 @@ static qboolean GLSlang_LoadBlob(program_t *prog, const char *name, unsigned int VFS_READ(blobfile, &length, sizeof(length)); binary = BZ_Malloc(length); VFS_READ(blobfile, binary, length); - VFS_READ(blobfile, &prog->permu[permu].handle.glsl.usetesselation, sizeof(prog->permu[permu].handle.glsl.usetesselation)); + VFS_READ(blobfile, &prog->permu[permu].h.glsl.usetesselation, sizeof(prog->permu[permu].h.glsl.usetesselation)); - prog->permu[permu].handle.glsl.handle = qglCreateProgramObjectARB(); - qglProgramBinary(prog->permu[permu].handle.glsl.handle, fmt, binary, length); + prog->permu[permu].h.glsl.handle = qglCreateProgramObjectARB(); + qglProgramBinary(prog->permu[permu].h.glsl.handle, fmt, binary, length); BZ_Free(binary); - qglGetProgramParameteriv_(prog->permu[permu].handle.glsl.handle, GL_OBJECT_LINK_STATUS_ARB, &success); + qglGetProgramParameteriv_(prog->permu[permu].h.glsl.handle, GL_OBJECT_LINK_STATUS_ARB, &success); if (!success) { - qglDeleteProgramObject_(prog->permu[permu].handle.glsl.handle); - memset(&prog->permu[permu].handle, 0, sizeof(prog->permu[permu].handle)); + qglDeleteProgramObject_(prog->permu[permu].h.glsl.handle); + memset(&prog->permu[permu].h, 0, sizeof(prog->permu[permu].h)); } return !!success; } static void GLSlang_DeleteProg(program_t *prog, unsigned int permu) { - if (prog->permu[permu].handle.glsl.handle) + if (prog->permu[permu].h.glsl.handle) { - qglDeleteProgramObject_(prog->permu[permu].handle.glsl.handle); - prog->permu[permu].handle.glsl.handle = 0; + qglDeleteProgramObject_(prog->permu[permu].h.glsl.handle); + prog->permu[permu].h.glsl.handle = 0; } } -static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvartypes) +static void GLSlang_ProgAutoFields(program_t *prog, const char *progname, char **cvarnames, int *cvartypes) { static const char *defaultsamplers[] = { @@ -2286,23 +2286,21 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart #define ALTLIGHTMAPSAMP 13 #define ALTDELUXMAPSAMP 16 - unsigned int i, p; - qboolean found; + unsigned int i, j, p; int uniformloc; char tmpname[128]; - cvar_t *cvar; - - prog->numparams = 0; + cvar_t *cvar[128]; + struct programpermu_s *pp; //figure out visible attributes for (p = 0; p < PERMUTATIONS; p++) { - if (!prog->permu[p].handle.glsl.handle) + if (!prog->permu[p].h.loaded) continue; - GLSlang_UseProgram(prog->permu[p].handle.glsl.handle); + GLSlang_UseProgram(prog->permu[p].h.glsl.handle); for (i = 0; shader_attr_names[i].name; i++) { - uniformloc = qglGetAttribLocationARB(prog->permu[p].handle.glsl.handle, shader_attr_names[i].name); + uniformloc = qglGetAttribLocationARB(prog->permu[p].h.glsl.handle, shader_attr_names[i].name); if (uniformloc != -1) { if (shader_attr_names[i].ptype != uniformloc) @@ -2313,98 +2311,81 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart } } - //figure out the uniforms - for (i = 0; shader_unif_names[i].name; i++) - { - found = false; - for (p = 0; p < PERMUTATIONS; p++) - { - if (!prog->permu[p].handle.glsl.handle) - continue; - GLSlang_UseProgram(prog->permu[p].handle.glsl.handle); - - uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, shader_unif_names[i].name); - if (uniformloc != -1) - found = true; - - if (prog->numparams == SHADER_PROGPARMS_MAX) - { - if (found) - break; - } - else - prog->permu[p].parm[prog->numparams] = uniformloc; - } - if (found) - { - if (prog->numparams == SHADER_PROGPARMS_MAX) - Con_Printf("Too many paramters for program (ignoring %s)\n", shader_unif_names[i].name); - else - { - prog->parm[prog->numparams].type = shader_unif_names[i].ptype; - prog->numparams++; - } - } - } - /*set cvar unirforms*/ - for (i = 0; cvarnames[i]; i++) - { - char *tmpval; - if (prog->numparams == SHADER_PROGPARMS_MAX) - { - Con_Printf("Too many cvar paramters for program\n"); - break; - } - for (p = 0; cvarnames[i][p] && (unsigned char)cvarnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) - tmpname[p] = cvarnames[i][p]; - tmpname[p] = 0; - tmpval = strchr(tmpname, '='); - if (tmpval) - *tmpval++ = 0; - else - tmpval = "0"; - while(p > 0 && (tmpname[p-1] == ' ' || tmpname[p-1] == '\t')) - tmpname[--p] = 0; - cvar = Cvar_Get(tmpname, tmpval, CVAR_SHADERSYSTEM, "glsl cvars"); - if (!cvar) - continue; -// cvar->flags |= CVAR_SHADERSYSTEM; - prog->parm[prog->numparams].type = cvartypes[i]; - prog->parm[prog->numparams].pval = cvar; - found = false; - for (p = 0; p < PERMUTATIONS; p++) - { - char uniformname[64]; - if (!prog->permu[p].handle.glsl.handle) - continue; - GL_SelectProgram(prog->permu[p].handle.glsl.handle); - Q_snprintfz(uniformname, sizeof(uniformname), "cvar_%s", tmpname); - uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, uniformname); - if (uniformloc != -1) - { - //qglUniform1fARB(uniformloc, cvar->value); - found = true; - } - prog->permu[p].parm[prog->numparams] = uniformloc; - } - if (found) - prog->numparams++; - } - + memset(cvar, 0, sizeof(cvar)); prog->numsamplers = 0; prog->defaulttextures = 0; - /*set texture uniforms*/ for (p = 0; p < PERMUTATIONS; p++) { - if (!prog->permu[p].handle.glsl.handle) + int maxparms = 0; + pp = &prog->permu[p]; + if (!pp->h.loaded) continue; - if (!(prog->permu[p].attrmask & (1u<permu[p].attrmask |= (1u<permu[p].handle.glsl.handle); + pp->numparms = 0; + pp->parm = NULL; + + GLSlang_UseProgram(prog->permu[p].h.glsl.handle); //we'll probably be setting samplers anyway. + for (i = 0; shader_unif_names[i].name; i++) + { + uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, shader_unif_names[i].name); + if (uniformloc >= 0) + { + if (pp->numparms >= maxparms) + { + maxparms = pp->numparms?pp->numparms * 2:8; + pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms); + } + pp->parm[pp->numparms].type = shader_unif_names[i].ptype; + pp->parm[pp->numparms].handle = uniformloc; + pp->numparms++; + } + } + + /*set cvar uniforms*/ + /*FIXME: enumerate cvars automatically instead*/ + for (i = 0; cvarnames[i] && i < countof(cvar); i++) + { + char *tmpval; + + if (!cvar[i]) + { + for (j = 0; cvarnames[i][j] && (unsigned char)cvarnames[i][j] > 32 && j < sizeof(tmpname)-1; j++) + tmpname[j] = cvarnames[i][j]; + tmpname[j] = 0; + tmpval = strchr(tmpname, '='); + if (tmpval) + *tmpval++ = 0; + else + tmpval = "0"; + while(j > 0 && (tmpname[j-1] == ' ' || tmpname[j-1] == '\t')) + tmpname[--j] = 0; + cvar[i] = Cvar_Get(tmpname, tmpval, CVAR_SHADERSYSTEM, "glsl cvars"); + if (!cvar[i]) + continue; + //cvar[i]->flags |= CVAR_SHADERSYSTEM; + } + + uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, va("cvar_%s", cvar[i]->name)); + if (uniformloc >= 0) + { + if (pp->numparms >= maxparms) + { + maxparms = pp->numparms?pp->numparms * 2:8; + pp->parm = BZ_Realloc(pp->parm, sizeof(*pp->parm) * maxparms); + } + pp->parm[pp->numparms].type = cvartypes[i]; + pp->parm[pp->numparms].pval = cvar[i]; + pp->parm[pp->numparms].handle = uniformloc; + pp->numparms++; + } + } + + //now scan/set texture uniforms + if (!(pp->attrmask & (1u<attrmask |= (1u<permu[p].handle.glsl.handle, tmpname); + uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, tmpname); if (uniformloc != -1) { qglUniform1iARB(uniformloc, i); @@ -2417,7 +2398,7 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart //figure out which ones are needed. if (prog->defaulttextures & (1u<permu[p].handle.glsl.handle, defaultsamplers[i]); + uniformloc = qglGetUniformLocationARB(pp->h.glsl.handle, defaultsamplers[i]); if (uniformloc != -1) prog->defaulttextures |= (1u<defaulttextures) { unsigned int sampnum; - /*set default texture uniforms*/ + /*set default texture uniforms now that we know the right sampler ids*/ for (p = 0; p < PERMUTATIONS; p++) { - if (!prog->permu[p].handle.glsl.handle) + if (!prog->permu[p].h.glsl.handle) continue; sampnum = prog->numsamplers; - GLSlang_UseProgram(prog->permu[p].handle.glsl.handle); + GLSlang_UseProgram(prog->permu[p].h.glsl.handle); for (i = 0; i < sizeof(defaultsamplers)/sizeof(defaultsamplers[0]); i++) { if (prog->defaulttextures & (1u<permu[p].handle.glsl.handle, defaultsamplers[i]); + uniformloc = qglGetUniformLocationARB(prog->permu[p].h.glsl.handle, defaultsamplers[i]); if (uniformloc != -1) qglUniform1iARB(uniformloc, sampnum); sampnum++; diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 2773c77e5..6d113039b 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -120,7 +120,6 @@ static qboolean vid_canalttab = false; static qboolean vid_wassuspended = false; extern qboolean mouseactive; // from in_win.c static HICON hIcon; -static HCURSOR hArrowCursor, hCustomCursor; extern qboolean vid_isfullscreen; unsigned short originalgammaramps[3][256]; @@ -586,117 +585,6 @@ RECT centerrect(unsigned int parentleft, unsigned int parenttop, unsigned int pa return r; } -void *WIN_CreateCursor(char *filename, float hotx, float hoty, float scale) -{ - int width, height; - BITMAPV5HEADER bi; - DWORD x,y; - HCURSOR hAlphaCursor = NULL; - ICONINFO ii; - - qbyte *rgbadata, *rgbadata_start, *bgradata, *bgradata_start; - qboolean hasalpha; - void *filedata; - int filelen; - if (!filename || !*filename) - return NULL; - filelen = FS_LoadFile(filename, &filedata); - if (!filedata) - return NULL; - - rgbadata_start = Read32BitImageFile(filedata, filelen, &width, &height, &hasalpha, "cursor"); - FS_FreeFile(filedata); - if (!rgbadata_start) - return NULL; - - if (scale != 1) - { - int nw,nh; - qbyte *nd; - nw = width * scale; - nh = height * scale; - if (nw <= 0 || nh <= 0 || nw > 128 || nh > 128) //don't go crazy. - return NULL; - nd = BZ_Malloc(nw*nh*4); - Image_ResampleTexture((unsigned int*)rgbadata_start, width, height, (unsigned int*)nd, nw, nh); - width = nw; - height = nh; - BZ_Free(rgbadata_start); - rgbadata_start = nd; - } - - memset(&bi,0, sizeof(BITMAPV5HEADER)); - bi.bV5Size = sizeof(BITMAPV5HEADER); - bi.bV5Width = width; - bi.bV5Height = height; - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - // The following mask specification specifies a supported 32 BPP - // alpha format for Windows XP. - //FIXME: can we not just specify it as RGBA? meh. - bi.bV5RedMask = 0x00FF0000; - bi.bV5GreenMask = 0x0000FF00; - bi.bV5BlueMask = 0x000000FF; - bi.bV5AlphaMask = 0xFF000000; - - // Create the DIB section with an alpha channel. - ii.hbmColor = CreateDIBSection(maindc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&bgradata_start, NULL, 0); - - if (!ii.hbmColor) - { - BZ_Free(rgbadata_start); - return NULL; - } - - for (rgbadata=rgbadata_start,y=0;yfuncs, stack, &ofs, 4*1024); + PR_SaveCallStack (progfuncs, stack, &ofs, 4*1024); PR_RunError (&progfuncs->funcs, stack); free(stack); return -1; diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 876fb4f9f..f726841f7 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -1391,6 +1391,32 @@ const QCC_eval_t *QCC_SRef_EvalConst(QCC_sref_t ref) return NULL; } +const char *QCC_GetRefName(QCC_ref_t *ref, char *buffer, size_t buffersize) +{ + switch(ref->type) + { + case REF_FIELD: + case REF_NONVIRTUAL: + QC_snprintfz(buffer, buffersize, "%s.%s", QCC_GetSRefName(ref->base), QCC_GetSRefName(ref->index)); + return buffer; + case REF_ARRAY: + case REF_STRING: + QC_snprintfz(buffer, buffersize, "%s[%s]", QCC_GetSRefName(ref->base), QCC_GetSRefName(ref->index)); + return buffer; + case REF_POINTER: + QC_snprintfz(buffer, buffersize, "%s->%s", QCC_GetSRefName(ref->base), QCC_GetSRefName(ref->index)); + return buffer; + case REF_ACCESSOR: + //FIXME + break; + case REF_ARRAYHEAD: + case REF_GLOBAL: + default: + break; + } + return QCC_GetSRefName(ref->base); +} + /* ============ PR_Statement @@ -1428,7 +1454,7 @@ static int QCC_ShouldConvert(QCC_type_t *from, etype_t wanted) /*impossible*/ return -1; } -QCC_sref_t QCC_SupplyConversionForAssignment(QCC_sref_t to, QCC_sref_t from, QCC_type_t *wanted, pbool fatal) +QCC_sref_t QCC_SupplyConversionForAssignment(QCC_ref_t *to, QCC_sref_t from, QCC_type_t *wanted, pbool fatal) { int o; @@ -1443,25 +1469,25 @@ QCC_sref_t QCC_SupplyConversionForAssignment(QCC_sref_t to, QCC_sref_t from, QCC return from; if (flag_typeexplicit) { - char totypename[256], fromtypename[256]; + char totypename[256], fromtypename[256], destname[256]; TypeName(wanted, totypename, sizeof(totypename)); TypeName(from.cast, fromtypename, sizeof(fromtypename)); - QCC_PR_ParseErrorPrintSRef(ERR_TYPEMISMATCH, from, "Implicit type mismatch on assignment to %s. Needed %s, got %s.", QCC_GetSRefName(to), totypename, fromtypename); + QCC_PR_ParseErrorPrintSRef(ERR_TYPEMISMATCH, from, "Implicit type mismatch on assignment to %s. Needed %s, got %s.", QCC_GetRefName(to, destname, sizeof(destname)), totypename, fromtypename); } if (o < 0) { if (fatal && wanted->type != ev_variant && from.cast->type != ev_variant) { - char totypename[256], fromtypename[256]; + char totypename[256], fromtypename[256], destname[256]; TypeName(wanted, totypename, sizeof(totypename)); TypeName(from.cast, fromtypename, sizeof(fromtypename)); if (flag_laxcasts) { - QCC_PR_ParseWarning(WARN_LAXCAST, "Implicit type mismatch on assignment to %s. Needed %s, got %s.", QCC_GetSRefName(to), totypename, fromtypename); + QCC_PR_ParseWarning(WARN_LAXCAST, "Implicit type mismatch on assignment to %s. Needed %s, got %s.", QCC_GetRefName(to, destname, sizeof(destname)), totypename, fromtypename); QCC_PR_ParsePrintSRef(WARN_LAXCAST, from); } else - QCC_PR_ParseErrorPrintSRef(ERR_TYPEMISMATCH, from, "Implicit type mismatch on assignment to %s. Needed %s, got %s.", QCC_GetSRefName(to), totypename, fromtypename); + QCC_PR_ParseErrorPrintSRef(ERR_TYPEMISMATCH, from, "Implicit type mismatch on assignment to %s. Needed %s, got %s.", QCC_GetRefName(to, destname, sizeof(destname)), totypename, fromtypename); } return from; } @@ -8282,7 +8308,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags) //convert so we don't have issues with: i = (int)(float)(i+f) //this will also catch things like vec *= vec; which would be trying to store a float into a vector. - rhsd = QCC_SupplyConversionForAssignment(lhsr->base, rhsd, lhsr->cast, true); + rhsd = QCC_SupplyConversionForAssignment(lhsr, rhsd, lhsr->cast, true); } else { @@ -8304,7 +8330,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags) rhsd.cast = lhsr->cast; } else - rhsd = QCC_SupplyConversionForAssignment(lhsr->base, rhsd, lhsr->cast, true); + rhsd = QCC_SupplyConversionForAssignment(lhsr, rhsd, lhsr->cast, true); } rhsd = QCC_StoreToRef(lhsr, rhsd, true, false); //FIXME: this should not always be true, but we don't know if the caller actually needs it qcc_usefulstatement = true; diff --git a/engine/qclib/qccgui.c b/engine/qclib/qccgui.c index 00c076802..b1a563753 100644 --- a/engine/qclib/qccgui.c +++ b/engine/qclib/qccgui.c @@ -67,6 +67,7 @@ void GUI_RevealOptions(void); #define SCI_STYLESETITALIC 2054 #define SCI_STYLESETSIZE 2055 #define SCI_STYLESETFONT 2056 +#define SCI_STYLERESETDEFAULT 2058 #define SCI_STYLESETUNDERLINE 2059 #define SCI_STYLESETCASE 2060 #define SCI_AUTOCSHOW 2100 @@ -160,6 +161,7 @@ void GUI_RevealOptions(void); #define SCE_C_TASKMARKER 26 #define SCE_C_ESCAPESEQUENCE 27 +#define STYLE_DEFAULT 32 #define STYLE_BRACELIGHT 34 #define STYLE_BRACEBAD 35 #define STYLE_LASTPREDEFINED 39 @@ -872,6 +874,11 @@ HWND CreateAnEditControl(HWND parent, pbool *scintillaokay) if (scintillaokay) { FILE *f; + + SendMessage(newc, SCI_STYLERESETDEFAULT, 0, 0); + SendMessage(newc, SCI_STYLESETFONT, STYLE_DEFAULT, (LPARAM)"Consolas"); + SendMessage(newc, SCI_STYLECLEARALL, 0, 0); + SendMessage(newc, SCI_SETCODEPAGE, SC_CP_UTF8, 0); SendMessage(newc, SCI_SETLEXER, SCLEX_CPP, 0); SendMessage(newc, SCI_STYLESETFORE, SCE_C_DEFAULT, RGB(0x00, 0x00, 0x00)); @@ -990,6 +997,8 @@ HWND CreateAnEditControl(HWND parent, pbool *scintillaokay) continue; if (c[0] == '/' && c[1] == '/') continue; + if (c[0] == '\r' || c[0] == '\n' || !c[0]) + continue; msg = strtoul(c, &c, 0); while(*c == ' ' || *c == '\t') c++; @@ -1627,7 +1636,7 @@ char *GetTooltipText(editor_t *editor, int pos, pbool dwell) static void scin_get_line_indent(HWND editpane, int lineidx, char *indentbuf, size_t sizeofbuf) { int i; - int len; + size_t len; while (lineidx --> 0) { len = SendMessage(editpane, SCI_LINELENGTH, lineidx, 0); @@ -3157,7 +3166,28 @@ void RunEngine(void) PostMessage(mainwindow, WM_SIZE, 0, 0); } +static void SetProgsSrcFileAndPath(char *filename) +{ + char *s, *s2; + strcpy(progssrcdir, filename); + for(s = progssrcdir; s; s = s2) + { + s2 = strchr(s+1, '\\'); + if (!s2) + break; + s = s2; + } + if (s) + { + *s = '\0'; + strcpy(progssrcname, s+1); + } + else + strcpy(progssrcname, filename); + SetCurrentDirectory(progssrcdir); + *progssrcdir = '\0'; +} HWND targitem_hexen2; HWND targitem_fte; @@ -3219,7 +3249,6 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message, break; case IDI_O_CHANGE_PROGS_SRC: { - char *s, *s2; char filename[MAX_PATH]; char oldpath[MAX_PATH+10]; OPENFILENAME ofn; @@ -3235,24 +3264,7 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message, ofn.lpstrInitialDir = oldpath; if (GetOpenFileName(&ofn)) { - strcpy(progssrcdir, filename); - for(s = progssrcdir; s; s = s2) - { - s2 = strchr(s+1, '\\'); - if (!s2) - break; - s = s2; - } - if (s) - { - *s = '\0'; - strcpy(progssrcname, s+1); - } - else - strcpy(progssrcname, filename); - - SetCurrentDirectory(progssrcdir); - *progssrcdir = '\0'; + SetProgsSrcFileAndPath(filename); } resetprogssrc = true; } @@ -3764,6 +3776,9 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message, CLIENTCREATESTRUCT ccs; HMENU rootmenu, windowmenu, m; + + DragAcceptFiles(hWnd, TRUE); + rootmenu = CreateMenu(); AppendMenu(rootmenu, MF_POPUP, (UINT_PTR)(m = CreateMenu()), "&File"); @@ -3873,9 +3888,24 @@ static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message, case WM_CTLCOLORBTN: return (LRESULT)GetSysColorBrush(COLOR_HIGHLIGHT);//COLOR_BACKGROUND; case WM_DESTROY: + DragAcceptFiles(hWnd, FALSE); mainwindow = NULL; break; + case WM_DROPFILES: + { + HDROP p = (HDROP)wParam; + char fname[MAX_PATH]; + if (DragQueryFile(p, ~0, (LPSTR) NULL, 0) == 1) + { + DragQueryFile(p, 0, fname, sizeof(fname)); + SetProgsSrcFileAndPath(fname); + resetprogssrc = true; + } + DragFinish(p); + } + break; + case WM_SIZE: GetClientRect(mainwindow, &rect); if (projecttree) @@ -4858,8 +4888,9 @@ void AddSourceFile(const char *parentpath, const char *filename) } } +//called when progssrcname has changed. //progssrcname should already have been set. -void SetProgsSrc(void) +void UpdateFileList(void) { FILE *f; @@ -5128,7 +5159,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (resetprogssrc) { //this here, with the compiler below, means that we don't run recursivly. resetprogssrc = false; - SetProgsSrc(); + UpdateFileList(); } EditorsRun(); diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 86a73b11d..a9442b773 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -9276,7 +9276,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"localcmd", PF_localcmd, 46, 46, 46, 0, D("void(string, ...)", "Adds the string to the console command queue. Commands will not be executed immediately, but rather at the start of the following frame.")}, {"nextent", PF_nextent, 47, 47, 47, 0, D("entity(entity)", "Returns the following entity. Skips over removed entities. Returns world when passed the last valid entity.")}, {"particle", PF_particle, 48, 0, 48, 48, D("void(vector pos, vector dir, float colour, float count)", "Spawn 'count' particles around 'pos' moving in the direction 'dir', with a palette colour index between 'colour' and 'colour+8'.")}, //48 nq readded. This isn't present in QW protocol (fte added it back). - {"changeyaw", PF_changeyaw, 49, 49, 49, 0, D("#define ChangeYaw changeyaw\nvoid()", "Changes the self.angles_y field towards self.ideal_yaw by up to self.yawspeed.")}, + {"changeyaw", PF_changeyaw, 49, 49, 49, 0, D("#define ChangeYaw changeyaw\nvoid()", "Changes the self.angles_y field towards self.ideal_yaw by up to self.yaw_speed.")}, // {"qtest_precacheitem", NULL, 50}, // defined QTest builtin that is never called {"vectoangles", PF_vectoangles, 51, 51, 51, 0, D("vector(vector fwd, optional vector up)", "Returns the angles (+x=UP) required to orient an entity to look in the given direction. The 'up' argument is required if you wish to set a roll angle, otherwise it will be limited to just monster-style turning.")}, diff --git a/engine/web/ftejslib.h b/engine/web/ftejslib.h index 5accdf519..4ba893941 100644 --- a/engine/web/ftejslib.h +++ b/engine/web/ftejslib.h @@ -24,6 +24,7 @@ int emscriptenfte_ws_recv(int sockid, void *data, int len); //receive data from //misc stuff for printf replacements void emscriptenfte_alert(const char *msg); void emscriptenfte_print(const char *msg); +void emscriptenfte_setupmainloop(int(*mainloop)(void)); void emscriptenfte_abortmainloop(const char *caller); //we're trying to avoid including libpng+libjpeg+libogg in javascript due to it being redundant bloat. diff --git a/engine/web/ftejslib.js b/engine/web/ftejslib.js index 284aa39ef..49acaf3ed 100644 --- a/engine/web/ftejslib.js +++ b/engine/web/ftejslib.js @@ -325,8 +325,6 @@ mergeInto(LibraryManager.library, }); }); } - if (Module.print === undefined) - Module.print = function(msg){console.log(msg);}; var ctx = Browser.createContext(Module['canvas'], true, true); if (ctx == null) { @@ -375,10 +373,38 @@ mergeInto(LibraryManager.library, { document.title = Pointer_stringify(txt); }, - emscriptenfte_abortmainloop : function(msg) + emscriptenfte_abortmainloop : function(fname) { - msg = Pointer_stringify(msg); - throw 'oh noes! something bad happened in ' + msg + '!'; + fname = Pointer_stringify(fname); + throw 'oh noes! something bad happened in ' + fname + '!\n' + Module['stackTrace'](); + }, + + emscriptenfte_setupmainloop : function(fnc) + { + Module['noExitRuntime'] = true; + + //Module.abort = abort = function(msg) {}; + + Module["sched"] = function() + { + var dovsync = false; + if (ABORT) + return; + try + { + dovsync = Runtime.dynCall('i', fnc, []); + } + catch(err) + { + console.log(err); + } + if (dovsync) + Browser.requestAnimationFrame(Module["sched"]); + else + setTimeout(Module["sched"], 0); + }; + //don't start it instantly, so we can distinguish between types of errors (emscripten sucks!). + setTimeout(Module["sched"], 1); }, emscriptenfte_ticks_ms : function() diff --git a/engine/web/fteshell.html b/engine/web/fteshell.html index 94ccf297f..4213b3c61 100644 --- a/engine/web/fteshell.html +++ b/engine/web/fteshell.html @@ -6,12 +6,12 @@ FTE QuakeWorld @@ -22,57 +22,67 @@
- - - {{{ SCRIPT }}} - - + \ No newline at end of file diff --git a/engine/web/prejs.js b/engine/web/prejs.js index ed8eb1ce1..3ee0c5d9e 100644 --- a/engine/web/prejs.js +++ b/engine/web/prejs.js @@ -1,7 +1,3 @@ -Module['preRun'] = function() -{ -}; - { Module['arguments'] = ['-nohome']; diff --git a/engine/web/sys_web.c b/engine/web/sys_web.c index 0492302eb..006ea7699 100644 --- a/engine/web/sys_web.c +++ b/engine/web/sys_web.c @@ -1,395 +1,401 @@ -#include "quakedef.h" - -#include -#ifdef MULTITHREAD -#include -#endif - -#include - -#include -#include "ftejslib.h" - -#ifndef isDedicated -qboolean isDedicated; -#endif - -void Sys_Error (const char *error, ...) -{ - va_list argptr; - char string[1024]; - - va_start (argptr,error); - vsnprintf (string, sizeof (string), error, argptr); - va_end (argptr); - Sys_Printf("Error: %s\n", string); - - Con_Print ("Quake Error: "); - Con_Print (string); - Con_Print ("\n"); - - Host_Shutdown (); - emscriptenfte_alert(string); - exit (1); -} - -void Sys_RecentServer(char *command, char *target, char *title, char *desc) -{ -} - -qboolean Sys_RandomBytes(qbyte *string, int len) -{ - return false; -} - -//print into stdout -void Sys_Printf (char *fmt, ...) -{ - va_list argptr; - char buf[1024]; - - va_start (argptr,fmt); - vsnprintf (buf, sizeof(buf), fmt, argptr); - emscriptenfte_print(buf); - va_end (argptr); -} - -unsigned int Sys_Milliseconds(void) -{ - static int first = true; - static unsigned long oldtime = 0, curtime = 0; - unsigned long newtime; - - newtime = emscriptenfte_ticks_ms(); //return Date.now() - - if (first) - { - first = false; - oldtime = newtime; - } - if (newtime < oldtime) - Con_Printf("Sys_Milliseconds stepped backwards!\n"); - else - curtime += newtime - oldtime; - oldtime = newtime; - return curtime; -} - -//return the current time, in the form of a double -double Sys_DoubleTime (void) -{ - return Sys_Milliseconds() / 1000.0; -} - -//create a directory -void Sys_mkdir (char *path) -{ -} - -//unlink a file -qboolean Sys_remove (char *path) -{ - emscriptenfte_buf_delete(path); - return true; -} - -qboolean Sys_Rename (char *oldfname, char *newfname) -{ - return emscriptenfte_buf_rename(oldfname, newfname); - return false; -} - -//someone used the 'quit' command -#include "glquake.h" -void Sys_Quit (void) -{ - if (host_initialized) - { - qglClearColor(0,0,0,1); - qglClear(GL_COLOR_BUFFER_BIT); - Draw_FunString (0, 0, "Reload the page to restart"); - - Host_Shutdown(); - } - - exit (0); -} - -int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t *), void *parm, searchpathfuncs_t *spath) -{ - Con_DPrintf("Warning: Sys_EnumerateFiles not implemented\n"); - return true; -} - -//blink window if possible (it's not) -void Sys_ServerActivity(void) -{ -} - -void Sys_CloseLibrary(dllhandle_t *lib) -{ -} -dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs) -{ - return NULL; -} -void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname) -{ - return NULL; -} - - - - - -void Sys_Init(void) -{ - extern cvar_t vid_width, vid_height, vid_fullscreen; - //vid_fullscreen takes effect only on mouse clicks, any suggestion to do a vid_restart is pointless. - vid_fullscreen.flags &= ~CVAR_RENDERERLATCH; - //these are not really supported. so silence any spam that suggests we do something about something not even supported. - vid_width.flags &= ~CVAR_RENDERERLATCH; - vid_height.flags &= ~CVAR_RENDERERLATCH; -} -void Sys_Shutdown(void) -{ -} - - - -int VARGS Sys_DebugLog(char *file, char *fmt, ...) -{ - return 0; -}; - - - -qboolean Sys_InitTerminal(void) -{ - return true; -} -char *Sys_ConsoleInput(void) -{ - return NULL; -} -void Sys_CloseTerminal (void) -{ -} - -void Sys_MainLoop(void) -{ - static float oldtime; - float newtime, time; - newtime = Sys_DoubleTime (); - if (!oldtime) - oldtime = newtime; - time = newtime - oldtime; - Host_Frame (time); - oldtime = newtime; -} - -int QDECL main(int argc, char **argv) -{ - quakeparms_t parms; - - memset(&parms, 0, sizeof(parms)); - - - parms.basedir = ""; - - parms.argc = argc; - parms.argv = (const char**)argv; - - COM_InitArgv (parms.argc, parms.argv); - - TL_InitLanguages(""); - - Sys_Printf ("Host_Init\n"); - Host_Init (&parms); - - //-1 fps should give vsync - emscripten_set_main_loop(Sys_MainLoop, -1, false); - return 0; -} - -qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate) -{ - return false; -} - - - -static char *clipboard_buffer; -char *Sys_GetClipboard(void) -{ - return clipboard_buffer; -} - -void Sys_CloseClipboard(char *bf) -{ -} - -void Sys_SaveClipboard(char *text) -{ - free(clipboard_buffer); - clipboard_buffer = strdup(text); -} - -#ifdef MULTITHREAD -/* Thread creation calls */ -void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize) -{ - // SDL threads do not support setting thread stack size - return (void *)SDL_CreateThread(func, args); -} - -void Sys_WaitOnThread(void *thread) -{ - SDL_WaitThread((SDL_Thread *)thread, NULL); -} - - -/* Mutex calls */ -// SDL mutexes don't have try-locks for mutexes in the spec so we stick with 1-value semaphores -void *Sys_CreateMutex(void) -{ - return (void *)SDL_CreateSemaphore(1); -} - -qboolean Sys_TryLockMutex(void *mutex) -{ - return !SDL_SemTryWait(mutex); -} - -qboolean Sys_LockMutex(void *mutex) -{ - return !SDL_SemWait(mutex); -} - -qboolean Sys_UnlockMutex(void *mutex) -{ - return !SDL_SemPost(mutex); -} - -void Sys_DestroyMutex(void *mutex) -{ - SDL_DestroySemaphore(mutex); -} - -/* Conditional wait calls */ -typedef struct condvar_s -{ - SDL_mutex *mutex; - SDL_cond *cond; -} condvar_t; - -void *Sys_CreateConditional(void) -{ - condvar_t *condv; - SDL_mutex *mutex; - SDL_cond *cond; - - condv = (condvar_t *)malloc(sizeof(condvar_t)); - if (!condv) - return NULL; - - mutex = SDL_CreateMutex(); - cond = SDL_CreateCond(); - - if (mutex) - { - if (cond) - { - condv->cond = cond; - condv->mutex = mutex; - - return (void *)condv; - } - else - SDL_DestroyMutex(mutex); - } - - free(condv); - return NULL; -} - -qboolean Sys_LockConditional(void *condv) -{ - return !SDL_mutexP(((condvar_t *)condv)->mutex); -} - -qboolean Sys_UnlockConditional(void *condv) -{ - return !SDL_mutexV(((condvar_t *)condv)->mutex); -} - -qboolean Sys_ConditionWait(void *condv) -{ - return !SDL_CondWait(((condvar_t *)condv)->cond, ((condvar_t *)condv)->mutex); -} - -qboolean Sys_ConditionSignal(void *condv) -{ - return !SDL_CondSignal(((condvar_t *)condv)->cond); -} - -qboolean Sys_ConditionBroadcast(void *condv) -{ - return !SDL_CondBroadcast(((condvar_t *)condv)->cond); -} - -void Sys_DestroyConditional(void *condv) -{ - condvar_t *cv = (condvar_t *)condv; - - SDL_DestroyCond(cv->cond); - SDL_DestroyMutex(cv->mutex); - free(cv); -} -#endif - -void Sys_Sleep (double seconds) -{ - SDL_Delay(seconds * 1000); -} - -//emscripten does not support the full set of sdl functions, so we stub the extras. -int SDL_GetGammaRamp(Uint16 *redtable, Uint16 *greentable, Uint16 *bluetable) -{ - return -1; -} -int SDL_SetGammaRamp(const Uint16 *redtable, const Uint16 *greentable, const Uint16 *bluetable) -{ - return -1; -} -//SDL_GL_GetAttribute -void SDL_UnloadObject(void *object) -{ -} -void *SDL_LoadObject(const char *sofile) -{ - return NULL; -} -void *SDL_LoadFunction(void *handle, const char *name) -{ - return NULL; -} -Uint8 SDL_GetAppState(void) -{ - return SDL_APPACTIVE; -} -#define socklen_t int -/* -int getsockname(int socket, struct sockaddr *address, socklen_t *address_len) -{ - return -1; -} -int getpeername(int socket, struct sockaddr *address, socklen_t *address_len) -{ - return -1; -} -ssize_t sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len) -{ - return -1; -} -*/ +#include "quakedef.h" + +#include +#ifdef MULTITHREAD +#include +#endif + +#include + +#include +#include "ftejslib.h" + +#ifndef isDedicated +qboolean isDedicated; +#endif + +quakeparms_t parms; + +void Sys_Error (const char *error, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr,error); + vsnprintf (string, sizeof (string), error, argptr); + va_end (argptr); + Sys_Printf("Error: %s\n", string); + + Con_Print ("Quake Error: "); + Con_Print (string); + Con_Print ("\n"); + + Host_Shutdown (); + emscriptenfte_alert(string); + exit (1); +} + +void Sys_RecentServer(char *command, char *target, char *title, char *desc) +{ +} + +qboolean Sys_RandomBytes(qbyte *string, int len) +{ + return false; +} + +//print into stdout +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + char buf[1024]; + + va_start (argptr,fmt); + vsnprintf (buf, sizeof(buf), fmt, argptr); + emscriptenfte_print(buf); + va_end (argptr); +} + +unsigned int Sys_Milliseconds(void) +{ + static int first = true; + static unsigned long oldtime = 0, curtime = 0; + unsigned long newtime; + + newtime = emscriptenfte_ticks_ms(); //return Date.now() + + if (first) + { + first = false; + oldtime = newtime; + } + if (newtime < oldtime) + Con_Printf("Sys_Milliseconds stepped backwards!\n"); + else + curtime += newtime - oldtime; + oldtime = newtime; + return curtime; +} + +//return the current time, in the form of a double +double Sys_DoubleTime (void) +{ + return Sys_Milliseconds() / 1000.0; +} + +//create a directory +void Sys_mkdir (char *path) +{ +} + +//unlink a file +qboolean Sys_remove (char *path) +{ + emscriptenfte_buf_delete(path); + return true; +} + +qboolean Sys_Rename (char *oldfname, char *newfname) +{ + return emscriptenfte_buf_rename(oldfname, newfname); + return false; +} + +//someone used the 'quit' command +#include "glquake.h" +void Sys_Quit (void) +{ + if (host_initialized) + { + qglClearColor(0,0,0,1); + qglClear(GL_COLOR_BUFFER_BIT); + Draw_FunString (0, 0, "Reload the page to restart"); + + Host_Shutdown(); + } + + exit (0); +} + +int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, qofs_t, time_t mtime, void *, searchpathfuncs_t *), void *parm, searchpathfuncs_t *spath) +{ + Con_DPrintf("Warning: Sys_EnumerateFiles not implemented\n"); + return true; +} + +//blink window if possible (it's not) +void Sys_ServerActivity(void) +{ +} + +void Sys_CloseLibrary(dllhandle_t *lib) +{ +} +dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs) +{ + return NULL; +} +void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname) +{ + return NULL; +} + + + + + +void Sys_Init(void) +{ + extern cvar_t vid_width, vid_height, vid_fullscreen; + //vid_fullscreen takes effect only on mouse clicks, any suggestion to do a vid_restart is pointless. + vid_fullscreen.flags &= ~CVAR_RENDERERLATCH; + //these are not really supported. so silence any spam that suggests we do something about something not even supported. + vid_width.flags &= ~CVAR_RENDERERLATCH; + vid_height.flags &= ~CVAR_RENDERERLATCH; +} +void Sys_Shutdown(void) +{ +} + + + +int VARGS Sys_DebugLog(char *file, char *fmt, ...) +{ + return 0; +}; + + + +qboolean Sys_InitTerminal(void) +{ + return true; +} +char *Sys_ConsoleInput(void) +{ + return NULL; +} +void Sys_CloseTerminal (void) +{ +} + +int Sys_MainLoop(void) +{ + extern cvar_t vid_vsync; + static float oldtime; + float newtime, time; + newtime = Sys_DoubleTime (); + if (!oldtime) + oldtime = newtime; + time = newtime - oldtime; + if (!host_initialized) + { + Sys_Printf ("Host_Init\n"); + Host_Init (&parms); + return 1; + } + + oldtime = newtime; + Host_Frame (time); + + return vid_vsync.ival; +} + +int QDECL main(int argc, char **argv) +{ + memset(&parms, 0, sizeof(parms)); + + + parms.basedir = ""; + + parms.argc = argc; + parms.argv = (const char**)argv; + + COM_InitArgv (parms.argc, parms.argv); + + TL_InitLanguages(""); + + emscriptenfte_setupmainloop(Sys_MainLoop); + return 0; +} + +qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate) +{ + return false; +} + + + +static char *clipboard_buffer; +char *Sys_GetClipboard(void) +{ + return clipboard_buffer; +} + +void Sys_CloseClipboard(char *bf) +{ +} + +void Sys_SaveClipboard(char *text) +{ + free(clipboard_buffer); + clipboard_buffer = strdup(text); +} + +#ifdef MULTITHREAD +/* Thread creation calls */ +void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize) +{ + // SDL threads do not support setting thread stack size + return (void *)SDL_CreateThread(func, args); +} + +void Sys_WaitOnThread(void *thread) +{ + SDL_WaitThread((SDL_Thread *)thread, NULL); +} + + +/* Mutex calls */ +// SDL mutexes don't have try-locks for mutexes in the spec so we stick with 1-value semaphores +void *Sys_CreateMutex(void) +{ + return (void *)SDL_CreateSemaphore(1); +} + +qboolean Sys_TryLockMutex(void *mutex) +{ + return !SDL_SemTryWait(mutex); +} + +qboolean Sys_LockMutex(void *mutex) +{ + return !SDL_SemWait(mutex); +} + +qboolean Sys_UnlockMutex(void *mutex) +{ + return !SDL_SemPost(mutex); +} + +void Sys_DestroyMutex(void *mutex) +{ + SDL_DestroySemaphore(mutex); +} + +/* Conditional wait calls */ +typedef struct condvar_s +{ + SDL_mutex *mutex; + SDL_cond *cond; +} condvar_t; + +void *Sys_CreateConditional(void) +{ + condvar_t *condv; + SDL_mutex *mutex; + SDL_cond *cond; + + condv = (condvar_t *)malloc(sizeof(condvar_t)); + if (!condv) + return NULL; + + mutex = SDL_CreateMutex(); + cond = SDL_CreateCond(); + + if (mutex) + { + if (cond) + { + condv->cond = cond; + condv->mutex = mutex; + + return (void *)condv; + } + else + SDL_DestroyMutex(mutex); + } + + free(condv); + return NULL; +} + +qboolean Sys_LockConditional(void *condv) +{ + return !SDL_mutexP(((condvar_t *)condv)->mutex); +} + +qboolean Sys_UnlockConditional(void *condv) +{ + return !SDL_mutexV(((condvar_t *)condv)->mutex); +} + +qboolean Sys_ConditionWait(void *condv) +{ + return !SDL_CondWait(((condvar_t *)condv)->cond, ((condvar_t *)condv)->mutex); +} + +qboolean Sys_ConditionSignal(void *condv) +{ + return !SDL_CondSignal(((condvar_t *)condv)->cond); +} + +qboolean Sys_ConditionBroadcast(void *condv) +{ + return !SDL_CondBroadcast(((condvar_t *)condv)->cond); +} + +void Sys_DestroyConditional(void *condv) +{ + condvar_t *cv = (condvar_t *)condv; + + SDL_DestroyCond(cv->cond); + SDL_DestroyMutex(cv->mutex); + free(cv); +} +#endif + +void Sys_Sleep (double seconds) +{ + SDL_Delay(seconds * 1000); +} + +//emscripten does not support the full set of sdl functions, so we stub the extras. +int SDL_GetGammaRamp(Uint16 *redtable, Uint16 *greentable, Uint16 *bluetable) +{ + return -1; +} +int SDL_SetGammaRamp(const Uint16 *redtable, const Uint16 *greentable, const Uint16 *bluetable) +{ + return -1; +} +//SDL_GL_GetAttribute +void SDL_UnloadObject(void *object) +{ +} +void *SDL_LoadObject(const char *sofile) +{ + return NULL; +} +void *SDL_LoadFunction(void *handle, const char *name) +{ + return NULL; +} +Uint8 SDL_GetAppState(void) +{ + return SDL_APPACTIVE; +} +#define socklen_t int +/* +int getsockname(int socket, struct sockaddr *address, socklen_t *address_len) +{ + return -1; +} +int getpeername(int socket, struct sockaddr *address, socklen_t *address_len) +{ + return -1; +} +ssize_t sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len) +{ + return -1; +} +*/