Fix web+android targets. Fix some relatively recent quake2 bugs.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5695 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-05-16 13:12:58 +00:00
parent c949500da8
commit 80474cc3be
10 changed files with 162 additions and 124 deletions

View File

@ -3468,6 +3468,17 @@ static void PM_PromptApplyChanges(void)
} }
} }
#endif #endif
#ifdef HAVE_CLIENT
static void PM_AddSubList_Callback(void *ctx, promptbutton_t opt)
{
if (opt == PROMPT_YES)
{
PM_AddSubList(ctx, "", true, true);
PM_WriteInstalledPackages();
}
Z_Free(ctx);
}
#endif
//names packages that were listed from the manifest. //names packages that were listed from the manifest.
//if 'mark' is true, then this is an initial install. //if 'mark' is true, then this is an initial install.
@ -3537,27 +3548,31 @@ void PM_Command_f(void)
if (!strcmp(act, "sources") || !strcmp(act, "addsource")) if (!strcmp(act, "sources") || !strcmp(act, "addsource"))
{ {
#ifdef WEBCLIENT #ifdef WEBCLIENT
if (Cmd_Argc() == 2) if (Cmd_Argc() == 2)
{ {
int i; int i;
for (i = 0; i < numdownloadablelists; i++) for (i = 0; i < numdownloadablelists; i++)
Con_Printf("%s %s\n", downloadablelist[i].url, downloadablelist[i].save?"(explicit)":"(implicit)"); Con_Printf("%s %s\n", downloadablelist[i].url, downloadablelist[i].save?"(explicit)":"(implicit)");
Con_Printf("<%i sources>\n", numdownloadablelists); Con_Printf("<%i sources>\n", numdownloadablelists);
} }
else else
{ {
PM_AddSubList(Cmd_Argv(2), "", true, true); #ifdef HAVE_CLIENT
PM_WriteInstalledPackages(); Menu_Prompt(PM_AddSubList_Callback, Z_StrDup(Cmd_Argv(2)), va("Add updates source?\n%s", Cmd_Argv(2)), "Confirm", NULL, "Cancel");
} #else
#endif PM_AddSubList(Cmd_Argv(2), "", true, true);
PM_WriteInstalledPackages();
#endif
}
#endif
} }
else if (!strcmp(act, "remsource")) else if (!strcmp(act, "remsource"))
{ {
#ifdef WEBCLIENT #ifdef WEBCLIENT
PM_RemSubList(Cmd_Argv(2)); PM_RemSubList(Cmd_Argv(2));
PM_WriteInstalledPackages(); PM_WriteInstalledPackages();
#endif #endif
} }
else else
{ {

View File

@ -4,7 +4,7 @@
#ifdef VKQUAKE #ifdef VKQUAKE
//we need some types available elsewhere, but don't really want to have to include the entire vulkan api everywhere. //we need some types available elsewhere, but don't really want to have to include the entire vulkan api everywhere.
//unfortunately, vulkan's handle types are not well defined. //unfortunately, vulkan's handle types are not well defined.
#if defined(__LP64__) || defined(_WIN64) #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#define VulkanAPIRandomness void* #define VulkanAPIRandomness void*
#elif defined(_MSC_VER) && _MSC_VER < 1300 #elif defined(_MSC_VER) && _MSC_VER < 1300
#define VulkanAPIRandomness __int64 #define VulkanAPIRandomness __int64

View File

@ -57,19 +57,10 @@ typedef struct vrsetup_s
} d3d; } d3d;
struct struct
{ //sometimes pointers, sometimes ints. nasty datatypes that suck. this is hideous. { //these are ALWAYS pointers in vulkan (annoyingly unlike many of its typedefs).
#ifndef VulkanAPIRandomness void *instance;
#if defined(__LP64__) || defined(_WIN64) void *physicaldevice;
#define VulkanAPIRandomness void* void *device;
#elif defined(_MSC_VER) && _MSC_VER < 1300
#define VulkanAPIRandomness __int64
#else
#define VulkanAPIRandomness long long
#endif
#endif
VulkanAPIRandomness instance;
VulkanAPIRandomness physicaldevice;
VulkanAPIRandomness device;
unsigned int queuefamily; unsigned int queuefamily;
unsigned int queueindex; unsigned int queueindex;
} vk; } vk;

View File

@ -702,6 +702,25 @@ static qboolean FS_Manifest_ParseTokens(ftemanifest_t *man)
{ {
int i; int i;
char *newdir = Cmd_Argv(1); char *newdir = Cmd_Argv(1);
qboolean basegame = !Q_strcasecmp(cmd, "basegame");
for (i = 0; i < sizeof(man->gamepath) / sizeof(man->gamepath[0]); i++)
{
if (man->gamepath[i].path)
{
if (!Q_strcasecmp(man->gamepath[i].path, newdir))
{
if (basegame && !(man->gamepath[i].flags & GAMEDIR_BASEGAME))
{
Z_Free(man->gamepath[i].path);
man->gamepath[i].path = NULL; //if we're adding a basegame when there's a mod game with the same name then drop the redundant mod name
man->gamepath[i].flags = 0;
}
else
return true; //already in there, don't add a conflicting one.
}
}
}
for (i = 0; i < sizeof(man->gamepath) / sizeof(man->gamepath[0]); i++) for (i = 0; i < sizeof(man->gamepath) / sizeof(man->gamepath[0]); i++)
{ {

View File

@ -435,7 +435,7 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
R_SetupGL R_SetupGL
============= =============
*/ */
static void R_SetupGL (vec3_t axisorigin[4], vec4_t fovoverrides, texid_t fbo) static void R_SetupGL (vec3_t axisorigin[4], vec4_t fovoverrides, float projmatrix[16]/*for webvr*/, texid_t fbo)
{ {
int x, x2, y2, y, w, h; int x, x2, y2, y, w, h;
vec3_t newa; vec3_t newa;
@ -559,67 +559,56 @@ static void R_SetupGL (vec3_t axisorigin[4], vec4_t fovoverrides, texid_t fbo)
r_refdef.pxrect.maxheight = vid.fbpheight; r_refdef.pxrect.maxheight = vid.fbpheight;
} }
if (fovoverrides) if (projmatrix)
{ {
fov_l = fovoverrides[0]; memcpy(r_refdef.m_projection_std, projmatrix, sizeof(r_refdef.m_projection_std));
fov_r = fovoverrides[1]; memcpy(r_refdef.m_projection_view, projmatrix, sizeof(r_refdef.m_projection_view));
fov_d = fovoverrides[2]; r_refdef.flipcull = 0;
fov_u = fovoverrides[3];
fov_x = fov_r-fov_l;
fov_y = fov_u-fov_d;
fovv_x = fov_x;
fovv_y = fov_y;
r_refdef.flipcull = ((fov_u < fov_d)^(fov_r < fov_l))?SHADER_CULL_FLIP:0;
} }
else else
{ {
fov_x = r_refdef.fov_x; if (fovoverrides)
fov_y = r_refdef.fov_y;
fovv_x = r_refdef.fovv_x;
fovv_y = r_refdef.fovv_y;
if ((*r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname) && strcmp(r_refdef.rt_destcolour[0].texname, "megascreeny"))
{ {
r_refdef.pxrect.y = r_refdef.pxrect.maxheight - (r_refdef.pxrect.height+r_refdef.pxrect.y); fov_l = fovoverrides[0];
fov_y *= -1; fov_r = fovoverrides[1];
fovv_y *= -1; fov_d = fovoverrides[2];
r_refdef.flipcull ^= SHADER_CULL_FLIP; fov_u = fovoverrides[3];
fov_x = fov_r-fov_l;
fov_y = fov_u-fov_d;
fovv_x = fov_x;
fovv_y = fov_y;
r_refdef.flipcull = ((fov_u < fov_d)^(fov_r < fov_l))?SHADER_CULL_FLIP:0;
} }
else if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP)) else
{ {
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); fov_x = r_refdef.fov_x;
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); fov_y = r_refdef.fov_y;
fovv_x = r_refdef.fovv_x;
fovv_y = r_refdef.fovv_y;
fovv_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); if ((*r_refdef.rt_destcolour[0].texname || *r_refdef.rt_depth.texname) && strcmp(r_refdef.rt_destcolour[0].texname, "megascreeny"))
fovv_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); {
r_refdef.pxrect.y = r_refdef.pxrect.maxheight - (r_refdef.pxrect.height+r_refdef.pxrect.y);
fov_y *= -1;
fovv_y *= -1;
r_refdef.flipcull ^= SHADER_CULL_FLIP;
}
else if ((r_refdef.flags & RDF_UNDERWATER) && !(r_refdef.flags & RDF_WATERWARP))
{
fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
fovv_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value);
fovv_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value);
}
fov_l = -fov_x / 2;
fov_r = fov_x / 2;
fov_d = -fov_y / 2;
fov_u = fov_y / 2;
} }
fov_l = -fov_x / 2;
fov_r = fov_x / 2;
fov_d = -fov_y / 2;
fov_u = fov_y / 2;
}
GL_ViewportUpdate();
#ifdef FTE_TARGET_WEB
if (r_refdef.stereomethod == STEREO_WEBVR)
{
float vm[16], em[16];
emscriptenfte_getvreyedata(i, r_refdef.m_projection_std, em);
memcpy(r_refdef.m_projection_view, r_refdef.m_projection_std, sizeof(r_refdef.m_projection_view));
Matrix4x4_Identity(em);
Matrix4x4_CM_ModelViewMatrixFromAxis(vm, vpn, vright, vup, r_origin);
Matrix4_Multiply(vm, em, r_refdef.m_view);
//fixme: read the axis+org back out...
// Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_origin);
}
else
#endif
{
if (r_refdef.useperspective) if (r_refdef.useperspective)
{ {
int stencilshadows = Sh_StencilShadowsActive(); int stencilshadows = Sh_StencilShadowsActive();
@ -652,14 +641,16 @@ static void R_SetupGL (vec3_t axisorigin[4], vec4_t fovoverrides, texid_t fbo)
} }
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_origin); Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_origin);
r_refdef.m_projection_view[2+4*0] *= 0.333;
r_refdef.m_projection_view[2+4*1] *= 0.333;
r_refdef.m_projection_view[2+4*2] *= 0.333;
r_refdef.m_projection_view[2+4*3] *= 0.333;
r_refdef.m_projection_view[14] -= 0.666;
//FIXME: bias, so that we use -1 to -.333 range instead of -.333 to 0.333
} }
//bias the viewmodel depth range to a third: -1 through -0.333 (instead of -1 to 1)
r_refdef.m_projection_view[2+4*0] *= 0.333;
r_refdef.m_projection_view[2+4*1] *= 0.333;
r_refdef.m_projection_view[2+4*2] *= 0.333;
r_refdef.m_projection_view[2+4*3] *= 0.333;
r_refdef.m_projection_view[14] -= 0.666;
GL_ViewportUpdate();
} }
if (qglLoadMatrixf) if (qglLoadMatrixf)
@ -754,7 +745,7 @@ static void R_RenderEyeScene (texid_t rendertarget, vec4_t fovoverride, vec3_t a
vid.fbpheight = rendertarget->height; vid.fbpheight = rendertarget->height;
} }
R_SetupGL (axisorigin, fovoverride, rendertarget); R_SetupGL (axisorigin, fovoverride, NULL, rendertarget);
R_RenderScene_Internal(); R_RenderScene_Internal();
if (rendertarget) if (rendertarget)
@ -811,9 +802,25 @@ static void R_RenderScene (void)
qglClear (GL_DEPTH_BUFFER_BIT); qglClear (GL_DEPTH_BUFFER_BIT);
r_framecount++; r_framecount++;
R_SetupGL (NULL, NULL, NULL); R_SetupGL (NULL, NULL, NULL, NULL);
R_RenderScene_Internal(); R_RenderScene_Internal();
} }
#ifdef FTE_TARGET_WEB
else if (r_refdef.stereomethod == STEREO_WEBVR)
{
float projmatrix[16], eyematrix[16];
GL_ForceDepthWritable();
qglClear (GL_DEPTH_BUFFER_BIT);
r_framecount++;
for (i = 0; i < stereoframes; i++)
{
emscriptenfte_getvreyedata(i, projmatrix, eyematrix);
R_SetupGL (eyematrix, NULL, projmatrix, NULL);
R_RenderScene_Internal();
}
}
#endif
else for (i = 0; i < stereoframes; i++) else for (i = 0; i < stereoframes; i++)
{ {
switch (stereomode) switch (stereomode)
@ -880,7 +887,7 @@ static void R_RenderScene (void)
axisorg[3][0] = 0; axisorg[3][0] = 0;
axisorg[3][1] = stereooffset[i]; axisorg[3][1] = stereooffset[i];
axisorg[3][2] = 0; axisorg[3][2] = 0;
R_SetupGL (axisorg, NULL, NULL); R_SetupGL (axisorg, NULL, NULL, NULL);
R_RenderScene_Internal (); R_RenderScene_Internal ();
} }

View File

@ -311,7 +311,7 @@ void VID_Register(void)
gles1rendererinfo.description = "OpenGL ES 1"; gles1rendererinfo.description = "OpenGL ES 1";
memset(&gles1rendererinfo.name, 0, sizeof(gles1rendererinfo.name)); //make sure there's no 'gl' etc names. memset(&gles1rendererinfo.name, 0, sizeof(gles1rendererinfo.name)); //make sure there's no 'gl' etc names.
gles1rendererinfo.name[0] = "gles1"; gles1rendererinfo.name[0] = "gles1";
R_RegisterRenderer(&gles1rendererinfo); R_RegisterRenderer(NULL, &gles1rendererinfo);
} }

View File

@ -4652,11 +4652,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"vec4 skybox = textureCube(s_reflectcube, pos);\n" "vec4 skybox = textureCube(s_reflectcube, pos);\n"
//Fun question: should sky be fogged as if infinite, or as if an actual surface? //Fun question: should sky be fogged as if infinite, or as if an actual surface?
"#ifdef FOG\n"
"#if 1\n" "#if 1\n"
"skybox.rgb = mix(skybox.rgb, w_fogcolour_ float(r_skyfog)*w_fogalpha); //flat fog ignoring actual geometry\n" "skybox.rgb = mix(skybox.rgb, w_fogcolour_ float(r_skyfog)*w_fogalpha); //flat fog ignoring actual geometry\n"
"#else\n" "#else\n"
"skybox.rgb = mix(skybox.rgb, fog3(skybox.rgb), float(r_skyfog)); //fog in terms of actual geometry distance\n" "skybox.rgb = mix(skybox.rgb, fog3(skybox.rgb), float(r_skyfog)); //fog in terms of actual geometry distance\n"
"#endif\n" "#endif\n"
"#endif\n"
"gl_FragColor = skybox;\n" "gl_FragColor = skybox;\n"
"}\n" "}\n"
"#endif\n" "#endif\n"

View File

@ -2066,21 +2066,24 @@ void SV_Begin_Core(client_t *split)
if (split->spawned) if (split->spawned)
{ {
//NEH_RESTOREGAME if (svprogfuncs)
//officially RestoreGame tells the mod when the game has been loaded.
//this allows mods to send any stuffcmds the client will have forgotten.
//the original intention would not have been client-specific (and indeed nehahra only saves in singleplayer)
//doing it elsewhere unfortunately results in race conditions.
func_t f = PR_FindFunction(svprogfuncs, "RestoreGame", PR_ANY);
if (f)
{ {
pr_global_struct->time = sv.world.physicstime; //NEH_RESTOREGAME
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict); //officially RestoreGame tells the mod when the game has been loaded.
PR_ExecuteProgram (svprogfuncs, f); //this allows mods to send any stuffcmds the client will have forgotten.
} //the original intention would not have been client-specific (and indeed nehahra only saves in singleplayer)
//doing it elsewhere unfortunately results in race conditions.
func_t f = PR_FindFunction(svprogfuncs, "RestoreGame", PR_ANY);
if (f)
{
pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict);
PR_ExecuteProgram (svprogfuncs, f);
}
SV_SendFixAngle(split, NULL, FIXANGLE_FIXED, false); SV_SendFixAngle(split, NULL, FIXANGLE_FIXED, false);
split->edict->v->fixangle = FIXANGLE_NO; //no point doing it again split->edict->v->fixangle = FIXANGLE_NO; //no point doing it again
}
return; return;
} }
split->spawned = true; split->spawned = true;
@ -2248,20 +2251,19 @@ void SV_Begin_Core(client_t *split)
} }
} }
} }
} SV_SendFixAngle(split, NULL, FIXANGLE_FIXED, false);
split->edict->v->fixangle = FIXANGLE_NO; //no point doing it again
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
split->dp_ping = NULL; split->dp_ping = NULL;
split->dp_pl = NULL; split->dp_pl = NULL;
if (progstype == PROG_NQ) if (progstype == PROG_NQ)
{ {
split->dp_ping = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, split->edict, "ping", ev_float, NULL); split->dp_ping = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, split->edict, "ping", ev_float, NULL);
split->dp_pl = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, split->edict, "ping_packetloss", ev_float, NULL); split->dp_pl = (float*)sv.world.progs->GetEdictFieldValue(sv.world.progs, split->edict, "ping_packetloss", ev_float, NULL);
} }
#endif #endif
}
SV_SendFixAngle(split, NULL, FIXANGLE_FIXED, false);
split->edict->v->fixangle = FIXANGLE_NO; //no point doing it again
} }
/* /*

View File

@ -343,7 +343,7 @@ static int SVQ2_FindIndex (const char *name, int start, int max, int overflowtyp
case 1: case 1:
overflowstrings = sv.strings.q2_extramodels; overflowstrings = sv.strings.q2_extramodels;
max = countof(sv.strings.q2_extramodels); max = countof(sv.strings.q2_extramodels);
i++; //do not allow 255 to be allocated, ever. just live with the gap. i++; //do not allow 255 to be allocated, ever. just live with the gap (255 means special things).
start = 0x8000; start = 0x8000;
break; break;
case 2: case 2:

View File

@ -37,10 +37,12 @@ void main ()
vec4 skybox = textureCube(s_reflectcube, pos); vec4 skybox = textureCube(s_reflectcube, pos);
//Fun question: should sky be fogged as if infinite, or as if an actual surface? //Fun question: should sky be fogged as if infinite, or as if an actual surface?
#if 1 #ifdef FOG
skybox.rgb = mix(skybox.rgb, w_fogcolour_ float(r_skyfog)*w_fogalpha); //flat fog ignoring actual geometry #if 1
#else skybox.rgb = mix(skybox.rgb, w_fogcolour_ float(r_skyfog)*w_fogalpha); //flat fog ignoring actual geometry
skybox.rgb = mix(skybox.rgb, fog3(skybox.rgb), float(r_skyfog)); //fog in terms of actual geometry distance #else
skybox.rgb = mix(skybox.rgb, fog3(skybox.rgb), float(r_skyfog)); //fog in terms of actual geometry distance
#endif
#endif #endif
gl_FragColor = skybox; gl_FragColor = skybox;
} }