}
-typedef void (*mod_framegroupify_parsegroups_t) (unsigned int i, int start, int len, float fps, qboolean loop, void *pass);
+typedef void (*mod_framegroupify_parsegroups_t) (unsigned int i, int start, int len, float fps, qboolean loop, const char *name, void *pass);
int Mod_FrameGroupify_ParseGroups(const char *buf, mod_framegroupify_parsegroups_t cb, void *pass)
{
float fps;
unsigned int i;
qboolean loop;
+ char name[64];
bufptr = buf;
i = 0;
for(;;)
{
// an anim scene!
- if (!COM_ParseToken_Simple(&bufptr, true, false))
+
+ // REQUIRED: fetch start
+ if (!COM_ParseToken_Simple(&bufptr, true, false, true))
break;
if (!strcmp(com_token, "\n"))
continue; // empty line
start = atoi(com_token);
- if (!COM_ParseToken_Simple(&bufptr, true, false))
+
+ // REQUIRED: fetch length
+ if (!COM_ParseToken_Simple(&bufptr, true, false, true))
break;
if (!strcmp(com_token, "\n"))
{
continue;
}
len = atoi(com_token);
- if (!COM_ParseToken_Simple(&bufptr, true, false))
+
+ // OPTIONAL args start
+ if (!COM_ParseToken_Simple(&bufptr, true, false, true))
break;
- // we default to looping as it's usually wanted, so to NOT loop you append a 0
+
+ // OPTIONAL: fetch fps
+ fps = 20;
if (strcmp(com_token, "\n"))
{
fps = atof(com_token);
- if (!COM_ParseToken_Simple(&bufptr, true, false))
+ if (!COM_ParseToken_Simple(&bufptr, true, false, true))
break;
- if (strcmp(com_token, "\n"))
- loop = atoi(com_token) != 0;
- else
- loop = true;
}
- else
+
+ // OPTIONAL: fetch loopflag
+ loop = true;
+ if (strcmp(com_token, "\n"))
+ {
+ loop = (atoi(com_token) != 0);
+ if (!COM_ParseToken_Simple(&bufptr, true, false, true))
+ break;
+ }
+
+ // OPTIONAL: fetch name
+ name[0] = 0;
+ if (strcmp(com_token, "\n"))
{
- fps = 20;
- loop = true;
+ strlcpy(name, com_token, sizeof(name));
+ if (!COM_ParseToken_Simple(&bufptr, true, false, true))
+ break;
}
+ // OPTIONAL: remaining unsupported tokens (eat them)
+ while (strcmp(com_token, "\n"))
+ {
+ if (!COM_ParseToken_Simple(&bufptr, true, false, true))
+ {
+ bufptr = NULL;
+ break;
+ }
+ }
+ if(!bufptr)
+ break;
+
+ //Con_Printf("data: %d %d %d %f %d (%s)\n", i, start, len, fps, loop, name);
+
if(cb)
- cb(i, start, len, fps, loop, pass);
+ cb(i, start, len, fps, loop, (name[0] ? name : NULL), pass);
++i;
}
return i;
}
-void Mod_FrameGroupify_ParseGroups_Count (unsigned int i, int start, int len, float fps, qboolean loop, void *pass)
-{
- unsigned int *cnt = (unsigned int *) pass;
- ++*cnt;
-}
-
-void Mod_FrameGroupify_ParseGroups_Store (unsigned int i, int start, int len, float fps, qboolean loop, void *pass)
+static void Mod_FrameGroupify_ParseGroups_Store (unsigned int i, int start, int len, float fps, qboolean loop, const char *name, void *pass)
{
dp_model_t *mod = (dp_model_t *) pass;
animscene_t *anim = &mod->animscenes[i];
- dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d_anim", i);
+ if(name)
+ strlcpy(anim->name, name, sizeof(anim[i].name));
+ else
+ dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d_anim", i);
anim->firstframe = bound(0, start, mod->num_poses - 1);
anim->framecount = bound(1, len, mod->num_poses - anim->firstframe);
anim->framerate = max(1, fps);
{
if (strcasecmp (entry->shader.name, shader->name) == 0)
{
- unsigned char *start, *end, *start2;
- start = (unsigned char *) (&shader->Q3SHADERINFO_COMPARE_START);
- end = ((unsigned char *) (&shader->Q3SHADERINFO_COMPARE_END)) + sizeof(shader->Q3SHADERINFO_COMPARE_END);
- start2 = (unsigned char *) (&entry->shader.Q3SHADERINFO_COMPARE_START);
- if(memcmp(start, start2, end - start))
- Con_DPrintf("Shader '%s' already defined, ignoring mismatching redeclaration\n", shader->name);
+ // redeclaration
+ if(shader->dpshaderkill)
+ {
+ // killed shader is a redeclarion? we can safely ignore it
+ return;
+ }
+ else if(entry->shader.dpshaderkill)
+ {
+ // replace the old shader!
+ // this will skip the entry allocating part
+ // below and just replace the shader
+ break;
+ }
else
- Con_DPrintf("Shader '%s' already defined\n", shader->name);
- return;
+ {
+ unsigned char *start, *end, *start2;
+ start = (unsigned char *) (&shader->Q3SHADERINFO_COMPARE_START);
+ end = ((unsigned char *) (&shader->Q3SHADERINFO_COMPARE_END)) + sizeof(shader->Q3SHADERINFO_COMPARE_END);
+ start2 = (unsigned char *) (&entry->shader.Q3SHADERINFO_COMPARE_START);
+ if(memcmp(start, start2, end - start))
+ Con_DPrintf("Shader '%s' already defined, ignoring mismatching redeclaration\n", shader->name);
+ else
+ Con_DPrintf("Shader '%s' already defined\n", shader->name);
+ return;
+ }
}
lastEntry = entry;
entry = entry->chain;
extern cvar_t mod_noshader_default_offsetmapping;
extern cvar_t mod_q3shader_default_offsetmapping;
+extern cvar_t mod_q3shader_default_offsetmapping_scale;
+extern cvar_t mod_q3shader_default_offsetmapping_bias;
extern cvar_t mod_q3shader_default_polygonoffset;
extern cvar_t mod_q3shader_default_polygonfactor;
+extern cvar_t mod_q3shader_force_addalpha;
void Mod_LoadQ3Shaders(void)
{
int j;
char *custsurfaceparmnames[256]; // VorteX: q3map2 has 64 but well, someone will need more
unsigned long custsurfaceparms[256];
int numcustsurfaceparms;
+ qboolean dpshaderkill;
Mod_FreeQ3Shaders();
Vector4Set(shader.reflectcolor4f, 1, 1, 1, 1);
shader.r_water_wateralpha = 1;
shader.offsetmapping = (mod_q3shader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
- shader.offsetscale = 1;
+ shader.offsetscale = mod_q3shader_default_offsetmapping_scale.value;
+ shader.offsetbias = mod_q3shader_default_offsetmapping_bias.value;
shader.specularscalemod = 1;
shader.specularpowermod = 1;
shader.biaspolygonoffset = mod_q3shader_default_polygonoffset.value;
layer->blendfunc[0] = GL_ONE;
layer->blendfunc[1] = GL_ONE;
}
+ else if (!strcasecmp(parameter[1], "addalpha"))
+ {
+ layer->blendfunc[0] = GL_SRC_ALPHA;
+ layer->blendfunc[1] = GL_ONE;
+ }
else if (!strcasecmp(parameter[1], "filter"))
{
layer->blendfunc[0] = GL_DST_COLOR;
else if (!strcasecmp(parameter[k+1], "GL_DST_COLOR"))
layer->blendfunc[k] = GL_DST_COLOR;
else if (!strcasecmp(parameter[k+1], "GL_DST_ALPHA"))
- layer->blendfunc[k] = GL_ONE_MINUS_DST_ALPHA;
+ layer->blendfunc[k] = GL_DST_ALPHA;
else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_COLOR"))
layer->blendfunc[k] = GL_ONE_MINUS_SRC_COLOR;
else if (!strcasecmp(parameter[k+1], "GL_ONE_MINUS_SRC_ALPHA"))
shader.textureblendalpha = true;
}
}
- layer->texflags = TEXF_ALPHA;
+
+ if(mod_q3shader_force_addalpha.integer)
+ {
+ // for a long while, DP treated GL_ONE GL_ONE as GL_SRC_ALPHA GL_ONE
+ // this cvar brings back this behaviour
+ if(layer->blendfunc[0] == GL_ONE && layer->blendfunc[1] == GL_ONE)
+ layer->blendfunc[0] = GL_SRC_ALPHA;
+ }
+
+ layer->texflags = 0;
+ if (layer->alphatest)
+ layer->texflags |= TEXF_ALPHA;
+ switch(layer->blendfunc[0])
+ {
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ layer->texflags |= TEXF_ALPHA;
+ break;
+ }
+ switch(layer->blendfunc[1])
+ {
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ layer->texflags |= TEXF_ALPHA;
+ break;
+ }
if (!(shader.surfaceparms & Q3SURFACEPARM_NOMIPMAPS))
layer->texflags |= TEXF_MIPMAP;
if (!(shader.textureflags & Q3TEXTUREFLAG_NOPICMIP))
strlcpy(shader.dpreflectcube, parameter[1], sizeof(shader.dpreflectcube));
else if (!strcasecmp(parameter[0], "dpmeshcollisions"))
shader.dpmeshcollisions = true;
- else if (!strcasecmp(parameter[0], "dpshaderkillifcvarzero") && numparameters >= 2)
+ // this sets dpshaderkill to true if dpshaderkillifcvarzero was used, and to false if dpnoshaderkillifcvarzero was used
+ else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvarzero")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvarzero")) && numparameters >= 2)
{
if (Cvar_VariableValue(parameter[1]) == 0.0f)
- shader.dpshaderkill = true;
+ shader.dpshaderkill = dpshaderkill;
}
- else if (!strcasecmp(parameter[0], "dpshaderkillifcvar") && numparameters >= 2)
+ // this sets dpshaderkill to true if dpshaderkillifcvar was used, and to false if dpnoshaderkillifcvar was used
+ else if (((dpshaderkill = !strcasecmp(parameter[0], "dpshaderkillifcvar")) || !strcasecmp(parameter[0], "dpnoshaderkillifcvar")) && numparameters >= 2)
{
- if (Cvar_VariableValue(parameter[1]) != 0.0f)
- shader.dpshaderkill = true;
+ const char *op = NULL;
+ if (numparameters >= 3)
+ op = parameter[2];
+ if(!op)
+ {
+ if (Cvar_VariableValue(parameter[1]) != 0.0f)
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, "=="))
+ {
+ if (Cvar_VariableValue(parameter[1]) == atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, "!="))
+ {
+ if (Cvar_VariableValue(parameter[1]) != atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, ">"))
+ {
+ if (Cvar_VariableValue(parameter[1]) > atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, "<"))
+ {
+ if (Cvar_VariableValue(parameter[1]) < atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, ">="))
+ {
+ if (Cvar_VariableValue(parameter[1]) >= atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else if (numparameters >= 4 && !strcmp(op, "<="))
+ {
+ if (Cvar_VariableValue(parameter[1]) <= atof(parameter[3]))
+ shader.dpshaderkill = dpshaderkill;
+ }
+ else
+ {
+ Con_DPrintf("%s parsing warning: unknown dpshaderkillifcvar op \"%s\", or not enough arguments\n", search->filenames[fileindex], op);
+ }
}
else if (!strcasecmp(parameter[0], "sky") && numparameters >= 2)
{
{
shader.rtlightambient = atof(parameter[1]);
}
- else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 3)
+ else if (!strcasecmp(parameter[0], "dpoffsetmapping") && numparameters >= 2)
{
if (!strcasecmp(parameter[1], "disable") || !strcasecmp(parameter[1], "none") || !strcasecmp(parameter[1], "off"))
shader.offsetmapping = OFFSETMAPPING_OFF;
- else if (!strcasecmp(parameter[1], "default"))
+ else if (!strcasecmp(parameter[1], "default") || !strcasecmp(parameter[1], "normal"))
shader.offsetmapping = OFFSETMAPPING_DEFAULT;
else if (!strcasecmp(parameter[1], "linear"))
shader.offsetmapping = OFFSETMAPPING_LINEAR;
else if (!strcasecmp(parameter[1], "relief"))
shader.offsetmapping = OFFSETMAPPING_RELIEF;
- shader.offsetscale = atof(parameter[2]);
+ if (numparameters >= 3)
+ shader.offsetscale = atof(parameter[2]);
+ if (numparameters >= 5)
+ {
+ if(!strcasecmp(parameter[3], "bias"))
+ shader.offsetbias = atof(parameter[4]);
+ else if(!strcasecmp(parameter[3], "match"))
+ shader.offsetbias = 1.0f - atof(parameter[4]);
+ else if(!strcasecmp(parameter[3], "match8"))
+ shader.offsetbias = 1.0f - atof(parameter[4]) / 255.0f;
+ else if(!strcasecmp(parameter[3], "match16"))
+ shader.offsetbias = 1.0f - atof(parameter[4]) / 65535.0f;
+ }
}
else if (!strcasecmp(parameter[0], "deformvertexes") && numparameters >= 2)
{
// unless later loaded from the shader
texture->offsetmapping = (mod_noshader_default_offsetmapping.value) ? OFFSETMAPPING_DEFAULT : OFFSETMAPPING_OFF;
texture->offsetscale = 1;
+ texture->offsetbias = 0;
texture->specularscalemod = 1;
texture->specularpowermod = 1;
+ texture->rtlightambient = 0;
// WHEN ADDING DEFAULTS HERE, REMEMBER TO SYNC TO SHADER LOADING ABOVE
// HERE, AND Q1BSP LOADING
// JUST GREP FOR "specularscalemod = 1".
Vector2Copy(shader->r_water_waterscroll, texture->r_water_waterscroll);
texture->offsetmapping = shader->offsetmapping;
texture->offsetscale = shader->offsetscale;
+ texture->offsetbias = shader->offsetbias;
texture->specularscalemod = shader->specularscalemod;
texture->specularpowermod = shader->specularpowermod;
texture->rtlightambient = shader->rtlightambient;