mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-24 13:21:20 +00:00
Merge branch 'next' into walllight
This commit is contained in:
commit
2a1b790ce9
19 changed files with 743 additions and 68 deletions
|
@ -450,15 +450,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t
|
|||
|
||||
texture = textures[texnum];
|
||||
|
||||
mipmap->flags = TF_WRAPXY;
|
||||
mipmap->width = (UINT16)texture->width;
|
||||
mipmap->height = (UINT16)texture->height;
|
||||
mipmap->format = textureformat;
|
||||
|
||||
blockwidth = texture->width;
|
||||
blockheight = texture->height;
|
||||
blocksize = (blockwidth * blockheight);
|
||||
block = MakeBlock(&grtex->mipmap);
|
||||
blocksize = blockwidth * blockheight;
|
||||
block = MakeBlock(mipmap);
|
||||
|
||||
// Composite the columns together.
|
||||
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
|
||||
|
@ -488,7 +483,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t
|
|||
realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH);
|
||||
}
|
||||
|
||||
HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch);
|
||||
HWR_DrawTexturePatchInCache(mipmap, blockwidth, blockheight, texture, patch, realpatch);
|
||||
|
||||
if (free_patch)
|
||||
Patch_Free(realpatch);
|
||||
|
@ -680,25 +675,24 @@ void HWR_InitMapTextures(void)
|
|||
gl_maptexturesloaded = false;
|
||||
}
|
||||
|
||||
static void DeleteTextureMipmap(GLMipmap_t *grMipmap)
|
||||
static void DeleteTextureMipmap(GLMipmap_t *grMipmap, boolean delete_mipmap)
|
||||
{
|
||||
HWD.pfnDeleteTexture(grMipmap);
|
||||
|
||||
// Chroma-keyed textures do not own their texture data, so do not free it
|
||||
if (!(grMipmap->flags & TF_CHROMAKEYED))
|
||||
if (delete_mipmap)
|
||||
Z_Free(grMipmap->data);
|
||||
}
|
||||
|
||||
static void FreeMapTexture(GLMapTexture_t *tex)
|
||||
static void FreeMapTexture(GLMapTexture_t *tex, boolean delete_chromakeys)
|
||||
{
|
||||
if (tex->mipmap.nextcolormap)
|
||||
{
|
||||
DeleteTextureMipmap(tex->mipmap.nextcolormap);
|
||||
DeleteTextureMipmap(tex->mipmap.nextcolormap, delete_chromakeys);
|
||||
free(tex->mipmap.nextcolormap);
|
||||
tex->mipmap.nextcolormap = NULL;
|
||||
}
|
||||
|
||||
DeleteTextureMipmap(&tex->mipmap);
|
||||
DeleteTextureMipmap(&tex->mipmap, true);
|
||||
}
|
||||
|
||||
void HWR_FreeMapTextures(void)
|
||||
|
@ -707,8 +701,8 @@ void HWR_FreeMapTextures(void)
|
|||
|
||||
for (i = 0; i < gl_numtextures; i++)
|
||||
{
|
||||
FreeMapTexture(&gl_textures[i]);
|
||||
FreeMapTexture(&gl_flats[i]);
|
||||
FreeMapTexture(&gl_textures[i], true);
|
||||
FreeMapTexture(&gl_flats[i], false);
|
||||
}
|
||||
|
||||
// now the heap don't have any 'user' pointing to our
|
||||
|
@ -741,22 +735,7 @@ void HWR_LoadMapTextures(size_t pnumtextures)
|
|||
// --------------------------------------------------------------------------
|
||||
// Make sure texture is downloaded and set it as the source
|
||||
// --------------------------------------------------------------------------
|
||||
static void GetMapTexture(INT32 tex, GLMapTexture_t *grtex, GLMipmap_t *mipmap)
|
||||
{
|
||||
// Generate texture if missing from the cache
|
||||
if (!mipmap->data && !mipmap->downloaded)
|
||||
HWR_GenerateTexture(tex, grtex, mipmap);
|
||||
|
||||
// If hardware does not have the texture, then call pfnSetTexture to upload it
|
||||
if (!mipmap->downloaded)
|
||||
HWD.pfnSetTexture(mipmap);
|
||||
HWR_SetCurrentTexture(mipmap);
|
||||
|
||||
// The system-memory data can be purged now.
|
||||
Z_ChangeTag(mipmap->data, PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
|
||||
GLMapTexture_t *HWR_GetTexture(INT32 tex)
|
||||
GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed)
|
||||
{
|
||||
if (tex < 0 || tex >= (signed)gl_numtextures)
|
||||
{
|
||||
|
@ -769,7 +748,46 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex)
|
|||
|
||||
GLMapTexture_t *grtex = &gl_textures[tex];
|
||||
|
||||
GetMapTexture(tex, grtex, &grtex->mipmap);
|
||||
GLMipmap_t *grMipmap = &grtex->mipmap;
|
||||
GLMipmap_t *originalMipmap = grMipmap;
|
||||
|
||||
if (!originalMipmap->downloaded)
|
||||
{
|
||||
originalMipmap->flags = TF_WRAPXY;
|
||||
originalMipmap->width = (UINT16)textures[tex]->width;
|
||||
originalMipmap->height = (UINT16)textures[tex]->height;
|
||||
originalMipmap->format = textureformat;
|
||||
}
|
||||
|
||||
// If chroma-keyed, create or use a different mipmap for the variant
|
||||
if (chromakeyed && !textures[tex]->transparency)
|
||||
{
|
||||
// Allocate it if it wasn't already
|
||||
if (!originalMipmap->nextcolormap)
|
||||
{
|
||||
GLMipmap_t *newMipmap = calloc(1, sizeof (*grMipmap));
|
||||
if (newMipmap == NULL)
|
||||
I_Error("%s: Out of memory", "HWR_GetTexture");
|
||||
|
||||
newMipmap->flags = originalMipmap->flags | TF_CHROMAKEYED;
|
||||
newMipmap->width = originalMipmap->width;
|
||||
newMipmap->height = originalMipmap->height;
|
||||
newMipmap->format = originalMipmap->format;
|
||||
originalMipmap->nextcolormap = newMipmap;
|
||||
}
|
||||
|
||||
// Generate, upload and bind the variant texture instead of the original one
|
||||
grMipmap = originalMipmap->nextcolormap;
|
||||
}
|
||||
|
||||
if (!grMipmap->data)
|
||||
HWR_GenerateTexture(tex, grtex, grMipmap);
|
||||
|
||||
if (!grMipmap->downloaded)
|
||||
HWD.pfnSetTexture(grMipmap);
|
||||
HWR_SetCurrentTexture(grMipmap);
|
||||
|
||||
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
|
||||
|
||||
return grtex;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ void HWR_GetPatch(patch_t *patch);
|
|||
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
|
||||
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
|
||||
|
||||
GLMapTexture_t *HWR_GetTexture(INT32 tex);
|
||||
GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed);
|
||||
void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed);
|
||||
void HWR_GetRawFlat(lumpnum_t flatlumpnum);
|
||||
|
||||
|
|
|
@ -978,7 +978,7 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph
|
|||
else
|
||||
repeats = 1;
|
||||
|
||||
GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture);
|
||||
GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture, true);
|
||||
float xscale = FixedToFloat(gl_sidedef->scalex_mid);
|
||||
float yscale = FixedToFloat(gl_sidedef->scaley_mid);
|
||||
|
||||
|
@ -1237,7 +1237,7 @@ static void HWR_ProcessSeg(void)
|
|||
// check TOP TEXTURE
|
||||
if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture)
|
||||
{
|
||||
grTex = HWR_GetTexture(gl_toptexture);
|
||||
grTex = HWR_GetTexture(gl_toptexture, false);
|
||||
xscale = FixedToFloat(abs(gl_sidedef->scalex_top));
|
||||
yscale = FixedToFloat(abs(gl_sidedef->scaley_top));
|
||||
|
||||
|
@ -1327,7 +1327,7 @@ static void HWR_ProcessSeg(void)
|
|||
// check BOTTOM TEXTURE
|
||||
if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture)
|
||||
{
|
||||
grTex = HWR_GetTexture(gl_bottomtexture);
|
||||
grTex = HWR_GetTexture(gl_bottomtexture, false);
|
||||
xscale = FixedToFloat(abs(gl_sidedef->scalex_bottom));
|
||||
yscale = FixedToFloat(abs(gl_sidedef->scaley_bottom));
|
||||
|
||||
|
@ -1441,7 +1441,7 @@ static void HWR_ProcessSeg(void)
|
|||
// Single sided line... Deal only with the middletexture (if one exists)
|
||||
if (gl_midtexture && gl_linedef->special != SPECIAL_HORIZON_LINE) // (Ignore horizon line for OGL)
|
||||
{
|
||||
grTex = HWR_GetTexture(gl_midtexture);
|
||||
grTex = HWR_GetTexture(gl_midtexture, false);
|
||||
xscale = FixedToFloat(gl_sidedef->scalex_mid);
|
||||
yscale = FixedToFloat(gl_sidedef->scaley_mid);
|
||||
|
||||
|
@ -1615,7 +1615,7 @@ static void HWR_ProcessSeg(void)
|
|||
// -- Monster Iestyn 26/06/18
|
||||
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
|
||||
|
||||
grTex = HWR_GetTexture(texnum);
|
||||
grTex = HWR_GetTexture(texnum, true);
|
||||
xscale = FixedToFloat(side->scalex_mid);
|
||||
yscale = FixedToFloat(side->scaley_mid);
|
||||
|
||||
|
@ -1772,7 +1772,7 @@ static void HWR_ProcessSeg(void)
|
|||
// -- Monster Iestyn 26/06/18
|
||||
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
|
||||
|
||||
grTex = HWR_GetTexture(texnum);
|
||||
grTex = HWR_GetTexture(texnum, true);
|
||||
xscale = FixedToFloat(side->scalex_mid);
|
||||
yscale = FixedToFloat(side->scaley_mid);
|
||||
|
||||
|
@ -4113,7 +4113,7 @@ static void HWR_CreateDrawNodes(void)
|
|||
else if (sortnode[sortindex[i]].wall)
|
||||
{
|
||||
if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture))
|
||||
HWR_GetTexture(sortnode[sortindex[i]].wall->texnum);
|
||||
HWR_GetTexture(sortnode[sortindex[i]].wall->texnum, true);
|
||||
HWR_RenderWall(sortnode[sortindex[i]].wall->wallVerts, &sortnode[sortindex[i]].wall->Surf, sortnode[sortindex[i]].wall->blend, sortnode[sortindex[i]].wall->fogwall,
|
||||
sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap);
|
||||
}
|
||||
|
@ -5093,6 +5093,8 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
|
||||
HWD.pfnSetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
|
||||
|
||||
HWR_GetTexture(texturetranslation[skytexture], false);
|
||||
|
||||
if (cv_glskydome.value)
|
||||
{
|
||||
FTransform dometransform;
|
||||
|
@ -5108,8 +5110,6 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
HWR_SetTransformAiming(&dometransform, player, false);
|
||||
dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
|
||||
|
||||
HWR_GetTexture(texturetranslation[skytexture]);
|
||||
|
||||
if (gl_sky.texture != texturetranslation[skytexture])
|
||||
{
|
||||
HWR_ClearSkyDome();
|
||||
|
@ -5129,7 +5129,6 @@ static void HWR_DrawSkyBackground(player_t *player)
|
|||
float aspectratio;
|
||||
float angleturn;
|
||||
|
||||
HWR_GetTexture(texturetranslation[skytexture]);
|
||||
aspectratio = (float)vid.width/(float)vid.height;
|
||||
|
||||
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
|
||||
|
|
238
src/m_menu.c
238
src/m_menu.c
|
@ -140,6 +140,7 @@ static char *char_notes = NULL;
|
|||
|
||||
boolean menuactive = false;
|
||||
boolean fromlevelselect = false;
|
||||
tic_t shieldprompt_timer = 0; // Show a prompt about the new Shield button for old configs // TODO: 2.3: Remove
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -3161,6 +3162,7 @@ static void Command_Manual_f(void)
|
|||
if (modeattacking)
|
||||
return;
|
||||
M_StartControlPanel();
|
||||
if (shieldprompt_timer) return; // TODO: 2.3: Delete this line
|
||||
currentMenu = &MISC_HelpDef;
|
||||
itemOn = 0;
|
||||
}
|
||||
|
@ -3340,6 +3342,7 @@ boolean M_Responder(event_t *ev)
|
|||
if (modeattacking)
|
||||
return true;
|
||||
M_StartControlPanel();
|
||||
if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line
|
||||
M_Options(0);
|
||||
// Uncomment the below if you want the menu to reset to the top each time like before. M_SetupNextMenu will fix it automatically.
|
||||
//OP_SoundOptionsDef.lastOn = 0;
|
||||
|
@ -3350,6 +3353,7 @@ boolean M_Responder(event_t *ev)
|
|||
if (modeattacking)
|
||||
return true;
|
||||
M_StartControlPanel();
|
||||
if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line
|
||||
M_Options(0);
|
||||
M_VideoModeMenu(0);
|
||||
return true;
|
||||
|
@ -3361,6 +3365,7 @@ boolean M_Responder(event_t *ev)
|
|||
if (modeattacking)
|
||||
return true;
|
||||
M_StartControlPanel();
|
||||
if (shieldprompt_timer) return true; // TODO: 2.3: Delete this line
|
||||
M_Options(0);
|
||||
M_SetupNextMenu(&OP_MainDef);
|
||||
return true;
|
||||
|
@ -3631,6 +3636,230 @@ void M_Drawer(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Handle the "Do you want to assign Shield Ability now?" pop-up for old configs // TODO: 2.3: Remove this line...
|
||||
static UINT8 shieldprompt_currentchoice = 0; // ...and this line...
|
||||
|
||||
static void M_ShieldPromptUseDefaults(void) // ...and this function
|
||||
{
|
||||
// With a default config from v2.2.10 to v2.2.13, the B button will be set to Custom 1,
|
||||
// and Controls per Key defaults to "One", so it will override the default Shield button.
|
||||
// A default config from v2.2.0 to v2.2.9 has Next Weapon on B, so it suffers from this too.
|
||||
|
||||
// So for "Use default Shield Ability buttons", we should update old configs to mitigate gamepad conflicts
|
||||
// (even with "Several" Controls per Key!), and show a message with the default bindings
|
||||
|
||||
for (setupcontrols = gamecontrol; true; setupcontrols = gamecontrolbis) // Do stuff for both P1 and P2
|
||||
{
|
||||
INT32 JOY1 = (setupcontrols == gamecontrol) ? KEY_JOY1 : KEY_2JOY1; // Is this for P1 or for P2?
|
||||
|
||||
if ((setupcontrols[GC_CUSTOM1][0] == JOY1+1 || setupcontrols[GC_CUSTOM1][1] == JOY1+1)
|
||||
&& (setupcontrols[GC_CUSTOM2][0] == JOY1+3 || setupcontrols[GC_CUSTOM2][1] == JOY1+3)
|
||||
&& (setupcontrols[GC_CUSTOM3][0] == JOY1+8 || setupcontrols[GC_CUSTOM3][1] == JOY1+8))
|
||||
{
|
||||
// If the player has v2.2.13's default gamepad Custom 1/2/3 buttons,
|
||||
// shuffle Custom 1/2/3 around to make room for Shield Ability on B
|
||||
UINT8 shield_slot = (setupcontrols[GC_SHIELD ][0] == KEY_NULL ) ? 0 : 1;
|
||||
UINT8 custom1_slot = (setupcontrols[GC_CUSTOM1][0] == JOY1+1) ? 0 : 1;
|
||||
UINT8 custom2_slot = (setupcontrols[GC_CUSTOM2][0] == JOY1+3) ? 0 : 1;
|
||||
UINT8 custom3_slot = (setupcontrols[GC_CUSTOM3][0] == JOY1+8) ? 0 : 1;
|
||||
|
||||
setupcontrols[GC_SHIELD ][shield_slot ] = JOY1+1; // Assign Shield Ability to B
|
||||
setupcontrols[GC_CUSTOM1][custom1_slot] = JOY1+3; // Move Custom 1 from B to Y
|
||||
setupcontrols[GC_CUSTOM2][custom2_slot] = JOY1+8; // Move Custom 2 from Y to LS
|
||||
setupcontrols[GC_CUSTOM3][custom3_slot] = KEY_NULL; // Unassign Custom 3 from LS...
|
||||
// (The alternative would be to check and update the ENTIRE gamepad layout.
|
||||
// That'd be nice, but it would mess with people that are used to the old defaults.)
|
||||
}
|
||||
else if ((setupcontrols[GC_WEAPONNEXT][0] == JOY1+1 || setupcontrols[GC_WEAPONNEXT][1] == JOY1+1)
|
||||
&& (setupcontrols[GC_WEAPONPREV][0] == JOY1+2 || setupcontrols[GC_WEAPONPREV][1] == JOY1+2))
|
||||
{
|
||||
// Or if the user has a default config from v2.2.0 to v2.2.9,
|
||||
// the B button will be Next Weapon, and X will be Previous Weapon.
|
||||
// It's "safe" to discard one of them, you just have to press X multiple times to select in the other direction
|
||||
UINT8 shield_slot = (setupcontrols[GC_SHIELD ][0] == KEY_NULL ) ? 0 : 1;
|
||||
UINT8 nweapon_slot = (setupcontrols[GC_WEAPONNEXT][0] == JOY1+1) ? 0 : 1;
|
||||
UINT8 pweapon_slot = (setupcontrols[GC_WEAPONPREV][0] == JOY1+2) ? 0 : 1;
|
||||
|
||||
setupcontrols[GC_SHIELD ][shield_slot ] = JOY1+1; // Assign Shield Ability to B
|
||||
setupcontrols[GC_WEAPONNEXT][nweapon_slot] = JOY1+3; // Move Next Weapon from B to X
|
||||
setupcontrols[GC_WEAPONPREV][pweapon_slot] = KEY_NULL; // Unassign Previous Weapon from X
|
||||
}
|
||||
|
||||
if (setupcontrols == gamecontrolbis) // If we've already updated both players, break out
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Now, show a message about the default Shield Ability bindings
|
||||
if ((gamecontrol[GC_SHIELD][0] == KEY_LALT && gamecontrol[GC_SHIELD][1] == KEY_JOY1+1)
|
||||
|| (gamecontrol[GC_SHIELD][0] == KEY_JOY1+1 && gamecontrol[GC_SHIELD][1] == KEY_LALT))
|
||||
{
|
||||
// Left Alt and the B button are both assigned
|
||||
M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x82""Left Alt\x80"" key on keyboard,\nand the \x85""B button\x80"" on gamepads."
|
||||
"\n\nYou can always reassign it\nin the Options menu later."
|
||||
"\n\n\nPress 'Enter' to continue\n"),
|
||||
NULL, MM_NOTHING);
|
||||
MessageDef.x = 43; // Change the pop-up message's background position/width
|
||||
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 27;
|
||||
}
|
||||
else if (gamecontrol[GC_SHIELD][0] == KEY_LALT || gamecontrol[GC_SHIELD][1] == KEY_LALT)
|
||||
{
|
||||
// Left Alt is assigned, but the B button isn't.
|
||||
M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x82""Left Alt\x80"" key on keyboard.\nThe \x85""B button\x80"" on gamepads was taken."
|
||||
"\n\nYou can always reassign it\nin the Options menu later."
|
||||
"\n\n\nPress 'Enter' to continue\n"),
|
||||
NULL, MM_NOTHING);
|
||||
MessageDef.x = 24; // Change the pop-up message's background position/width
|
||||
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 32;
|
||||
}
|
||||
else if (gamecontrol[GC_SHIELD][0] == KEY_JOY1+1 || gamecontrol[GC_SHIELD][1] == KEY_JOY1+1)
|
||||
{
|
||||
// The B button is assigned, but Left Alt isn't
|
||||
M_StartMessage(M_GetText("Shield Ability defaults to\nthe \x85""B button\x80"" on gamepads.\nThe \x82""Left Alt\x80"" key on keyboard was taken."
|
||||
"\n\nYou can always reassign it\nin the Options menu later."
|
||||
"\n\n\nPress 'Enter' to continue\n"),
|
||||
NULL, MM_NOTHING);
|
||||
MessageDef.x = 8; // Change the pop-up message's background position/width
|
||||
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 36;
|
||||
}
|
||||
else if (gamecontrol[GC_SHIELD][0] == KEY_NULL && gamecontrol[GC_SHIELD][1] == KEY_NULL)
|
||||
{
|
||||
// Neither Left Alt nor the B button are assigned
|
||||
M_StartMessage(M_GetText("Shield Ability is unassigned!\nThe \x82""Left Alt\x80"" key on keyboard and\nthe \x85""B button\x80"" on gamepads were taken."
|
||||
"\n\nYou should assign Shield Ability\nin the Options menu later."
|
||||
"\n\n\nPress 'Enter' to continue\n"),
|
||||
NULL, MM_NOTHING);
|
||||
MessageDef.x = 19; // Change the pop-up message's background position/width
|
||||
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 33;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Neither Left Alt nor the B button are assigned... but something else is???
|
||||
// (This can technically happen if you edit your config or use setcontrol in the console before opening the menu)
|
||||
char keystr[16+16+2+7+1]; // Two 16-char keys + two colour codes + "' and '" + null
|
||||
|
||||
if (gamecontrol[GC_SHIELD][0] != KEY_NULL && gamecontrol[GC_SHIELD][1] != KEY_NULL)
|
||||
STRBUFCPY(keystr, va("%s\x80""' and '\x82""%s",
|
||||
G_KeyNumToName(gamecontrol[GC_SHIELD][0]),
|
||||
G_KeyNumToName(gamecontrol[GC_SHIELD][1])));
|
||||
else if (gamecontrol[GC_SHIELD][0] != KEY_NULL)
|
||||
STRBUFCPY(keystr, G_KeyNumToName(gamecontrol[GC_SHIELD][0]));
|
||||
else //if (gamecontrol[GC_SHIELD][1] != KEY_NULL)
|
||||
STRBUFCPY(keystr, G_KeyNumToName(gamecontrol[GC_SHIELD][1]));
|
||||
|
||||
M_StartMessage(va("Shield Ability is assigned to\n'\x82""%s\x80""'."
|
||||
"\n\nYou can always reassign it\nin the Options menu later."
|
||||
"\n\n\nPress 'Enter' to continue\n",
|
||||
keystr), NULL, MM_NOTHING);
|
||||
MessageDef.x = 23; // Change the pop-up message's background position/width
|
||||
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 32;
|
||||
}
|
||||
}
|
||||
|
||||
static void M_HandleShieldPromptMenu(INT32 choice) // TODO: 2.3: Remove
|
||||
{
|
||||
switch (choice)
|
||||
{
|
||||
case KEY_ESCAPE:
|
||||
if (I_GetTime() <= shieldprompt_timer) // Don't mash past the pop-up by accident!
|
||||
break;
|
||||
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
noFurtherInput = true;
|
||||
shieldprompt_timer = 0;
|
||||
M_ShieldPromptUseDefaults();
|
||||
break;
|
||||
|
||||
case KEY_ENTER:
|
||||
if (I_GetTime() <= shieldprompt_timer) // Don't mash past the pop-up by accident!
|
||||
break;
|
||||
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
noFurtherInput = true;
|
||||
shieldprompt_timer = 0;
|
||||
|
||||
if (shieldprompt_currentchoice == 0)
|
||||
{
|
||||
OP_ChangeControlsDef.lastOn = 8; // Highlight Shield Ability in the controls menu
|
||||
M_Setup1PControlsMenu(0); // Set up P1's controls menu and call M_SetupNextMenu
|
||||
}
|
||||
else if (shieldprompt_currentchoice == 1) // Copy the Spin buttons to the Shield buttons
|
||||
{
|
||||
CV_SetValue(&cv_controlperkey, 2); // Make sure that Controls per Key is "Several"
|
||||
|
||||
gamecontrol [GC_SHIELD][0] = gamecontrol [GC_SPIN][0];
|
||||
gamecontrol [GC_SHIELD][1] = gamecontrol [GC_SPIN][1];
|
||||
gamecontrolbis[GC_SHIELD][0] = gamecontrolbis[GC_SPIN][0];
|
||||
gamecontrolbis[GC_SHIELD][1] = gamecontrolbis[GC_SPIN][1];
|
||||
CV_SetValue(&cv_shieldaxis, cv_spinaxis.value);
|
||||
CV_SetValue(&cv_shieldaxis2, cv_spinaxis2.value);
|
||||
|
||||
M_StartMessage(M_GetText("Spin and Shield Ability are now\nthe same button."
|
||||
"\n\nYou can always reassign them\nin the Options menu later."
|
||||
"\n\n\nPress 'Enter' to continue\n"),
|
||||
NULL, MM_NOTHING);
|
||||
MessageDef.x = 36; // Change the pop-up message's background position/width
|
||||
MessageDef.lastOn = (MessageDef.lastOn & ~0xFF) | 29;
|
||||
}
|
||||
else
|
||||
M_ShieldPromptUseDefaults();
|
||||
break;
|
||||
|
||||
case KEY_UPARROW:
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
shieldprompt_currentchoice = (shieldprompt_currentchoice+2)%3;
|
||||
break;
|
||||
|
||||
case KEY_DOWNARROW:
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
shieldprompt_currentchoice = (shieldprompt_currentchoice+1)%3;
|
||||
break;
|
||||
}
|
||||
|
||||
MessageDef.prevMenu = &MainDef;
|
||||
}
|
||||
|
||||
static void M_DrawShieldPromptMenu(void) // TODO: 2.3: Remove
|
||||
{
|
||||
INT16 cursorx = (BASEVIDWIDTH/2) - 24;
|
||||
|
||||
V_DrawFill(10-3, 68-3, 300+6, 40+6, 159);
|
||||
// V_DrawCenteredString doesn't centre newlines, so we have to draw each line separately
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 68, V_ALLOWLOWERCASE, "Welcome back! Since you last played,");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 76, V_ALLOWLOWERCASE, "Spin has been split into separate");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 84, V_ALLOWLOWERCASE, "\"Spin\" and \"Shield Ability\" controls.");
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 98, V_ALLOWLOWERCASE, "Do you want to assign Shield Ability now?");
|
||||
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 164,
|
||||
(shieldprompt_currentchoice == 0) ? V_YELLOWMAP : 0, "Open Control Setup");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 172,
|
||||
(shieldprompt_currentchoice == 1) ? V_YELLOWMAP : 0, "Keep the old behaviour");
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, 180,
|
||||
(shieldprompt_currentchoice == 2) ? V_YELLOWMAP : 0, "Use default Shield Ability buttons");
|
||||
|
||||
switch (shieldprompt_currentchoice)
|
||||
{
|
||||
case 0: cursorx -= V_StringWidth("Open Control Setup", 0)/2; break;
|
||||
case 1: cursorx -= V_StringWidth("Keep the old behaviour", 0)/2; break;
|
||||
default: cursorx -= V_StringWidth("Use default Shield Ability buttons", 0)/2; break;
|
||||
}
|
||||
V_DrawScaledPatch(cursorx, 164 + (shieldprompt_currentchoice*8), 0, W_CachePatchName("M_CURSOR", PU_PATCH));
|
||||
}
|
||||
|
||||
static menuitem_t OP_ShieldPromptMenu[] = {{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleShieldPromptMenu, 0}}; // TODO: 2.3: Remove
|
||||
|
||||
menu_t OP_ShieldPromptDef = { // TODO: 2.3: Remove
|
||||
MN_SPECIAL,
|
||||
NULL,
|
||||
1,
|
||||
&MainDef,
|
||||
OP_ShieldPromptMenu,
|
||||
M_DrawShieldPromptMenu,
|
||||
0, 0, 0, NULL
|
||||
};
|
||||
|
||||
//
|
||||
// M_StartControlPanel
|
||||
//
|
||||
|
@ -3662,6 +3891,15 @@ void M_StartControlPanel(void)
|
|||
currentMenu = &MainDef;
|
||||
itemOn = singleplr;
|
||||
M_UpdateItemOn();
|
||||
|
||||
if (shieldprompt_timer) // For old configs, show a pop-up about the new Shield button // TODO: 2.3: Remove
|
||||
{
|
||||
S_StartSound(NULL, sfx_strpst);
|
||||
noFurtherInput = true;
|
||||
shieldprompt_timer = I_GetTime() + TICRATE; // Don't mash past the pop-up by accident!
|
||||
|
||||
M_SetupNextMenu(&OP_ShieldPromptDef);
|
||||
}
|
||||
}
|
||||
else if (modeattacking)
|
||||
{
|
||||
|
|
|
@ -176,6 +176,7 @@ typedef struct
|
|||
extern menupres_t menupres[NUMMENUTYPES];
|
||||
extern UINT32 prevMenuId;
|
||||
extern UINT32 activeMenuId;
|
||||
extern tic_t shieldprompt_timer; // Show a prompt about the new Shield button for old configs // TODO: 2.3: Remove
|
||||
|
||||
void M_InitMenuPresTables(void);
|
||||
UINT8 M_GetYoungestChildMenu(void);
|
||||
|
|
|
@ -560,6 +560,11 @@ void M_FirstLoadConfig(void)
|
|||
COM_BufInsertText(va("exec \"%s\"\n", configfile));
|
||||
// no COM_BufExecute() needed; that does it right away
|
||||
|
||||
// For configs loaded at startup only, check for pre-Shield-button configs // TODO: 2.3: Remove
|
||||
if (GETMAJOREXECVERSION(cv_execversion.value) < 55 // Pre-v2.2.14 configs
|
||||
&& cv_execversion.value != 25) // Make sure that the config exists, too
|
||||
shieldprompt_timer = 1;
|
||||
|
||||
// don't filter anymore vars and don't let this convsvar be changed
|
||||
COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION));
|
||||
CV_ToggleExecVersion(false);
|
||||
|
|
|
@ -21,6 +21,32 @@ void DVector3_Load(dvector3_t *vec, double x, double y, double z)
|
|||
vec->z = z;
|
||||
}
|
||||
|
||||
void DVector3_Copy(dvector3_t *a_o, const dvector3_t *a_i)
|
||||
{
|
||||
memcpy(a_o, a_i, sizeof(dvector3_t));
|
||||
}
|
||||
|
||||
void DVector3_Add(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o)
|
||||
{
|
||||
a_o->x = a_i->x + a_c->x;
|
||||
a_o->y = a_i->y + a_c->y;
|
||||
a_o->z = a_i->z + a_c->z;
|
||||
}
|
||||
|
||||
void DVector3_Subtract(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o)
|
||||
{
|
||||
a_o->x = a_i->x - a_c->x;
|
||||
a_o->y = a_i->y - a_c->y;
|
||||
a_o->z = a_i->z - a_c->z;
|
||||
}
|
||||
|
||||
void DVector3_Multiply(const dvector3_t *a_i, double a_c, dvector3_t *a_o)
|
||||
{
|
||||
a_o->x = a_i->x * a_c;
|
||||
a_o->y = a_i->y * a_c;
|
||||
a_o->z = a_i->z * a_c;
|
||||
}
|
||||
|
||||
double DVector3_Magnitude(const dvector3_t *a_normal)
|
||||
{
|
||||
double xs = a_normal->x * a_normal->x;
|
||||
|
|
|
@ -19,6 +19,10 @@ typedef struct
|
|||
} dvector3_t;
|
||||
|
||||
void DVector3_Load(dvector3_t *vec, double x, double y, double z);
|
||||
void DVector3_Copy(dvector3_t *a_o, const dvector3_t *a_i);
|
||||
void DVector3_Add(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o);
|
||||
void DVector3_Subtract(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o);
|
||||
void DVector3_Multiply(const dvector3_t *a_i, double a_c, dvector3_t *a_o);
|
||||
double DVector3_Magnitude(const dvector3_t *a_normal);
|
||||
double DVector3_Normalize(dvector3_t *a_normal);
|
||||
void DVector3_Negate(dvector3_t *a_o);
|
||||
|
|
|
@ -60,6 +60,8 @@ typedef UINT8 lighttable_t;
|
|||
#define CMF_FADEFULLBRIGHTSPRITES 1
|
||||
#define CMF_FOG 4
|
||||
|
||||
#define TEXTURE_255_IS_TRANSPARENT
|
||||
|
||||
// ExtraColormap type. Use for extra_colormaps from now on.
|
||||
typedef struct extracolormap_s
|
||||
{
|
||||
|
|
|
@ -154,9 +154,11 @@ void R_VideoErase(size_t ofs, INT32 count);
|
|||
|
||||
void R_DrawColumn_8(void);
|
||||
void R_DrawColumnClamped_8(void);
|
||||
void R_Draw2sMultiPatchColumn_8(void);
|
||||
void R_DrawShadeColumn_8(void);
|
||||
void R_DrawTranslucentColumn_8(void);
|
||||
void R_DrawTranslucentColumnClamped_8(void);
|
||||
void R_Draw2sMultiPatchTranslucentColumn_8(void);
|
||||
void R_DrawDropShadowColumn_8(void);
|
||||
void R_DrawTranslatedColumn_8(void);
|
||||
void R_DrawTranslatedTranslucentColumn_8(void);
|
||||
|
|
183
src/r_draw8.c
183
src/r_draw8.c
|
@ -192,6 +192,189 @@ void R_DrawColumnClamped_8(void)
|
|||
}
|
||||
}
|
||||
|
||||
void R_Draw2sMultiPatchColumn_8(void)
|
||||
{
|
||||
INT32 count;
|
||||
register UINT8 *dest;
|
||||
register fixed_t frac;
|
||||
fixed_t fracstep;
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
|
||||
if (count < 0) // Zero length, column does not exceed a pixel.
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Framebuffer destination address.
|
||||
dest = &topleft[dc_yl*vid.width + dc_x];
|
||||
|
||||
count++;
|
||||
|
||||
// Determine scaling, which is the only mapping to be done.
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
|
||||
|
||||
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
|
||||
// This is as fast as it gets.
|
||||
{
|
||||
register const UINT8 *source = dc_source;
|
||||
register const lighttable_t *colormap = dc_colormap;
|
||||
register INT32 heightmask = dc_texheight-1;
|
||||
register UINT8 val;
|
||||
if (dc_texheight & heightmask) // not a power of 2 -- killough
|
||||
{
|
||||
heightmask++;
|
||||
heightmask <<= FRACBITS;
|
||||
|
||||
if (frac < 0)
|
||||
while ((frac += heightmask) < 0);
|
||||
else
|
||||
while (frac >= heightmask)
|
||||
frac -= heightmask;
|
||||
|
||||
do
|
||||
{
|
||||
// Re-map color indices from wall texture column
|
||||
// using a lighting/special effects LUT.
|
||||
// heightmask is the Tutti-Frutti fix
|
||||
val = source[frac>>FRACBITS];
|
||||
|
||||
if (val != TRANSPARENTPIXEL)
|
||||
*dest = colormap[val];
|
||||
|
||||
dest += vid.width;
|
||||
|
||||
// Avoid overflow.
|
||||
if (fracstep > 0x7FFFFFFF - frac)
|
||||
frac += fracstep - heightmask;
|
||||
else
|
||||
frac += fracstep;
|
||||
|
||||
while (frac >= heightmask)
|
||||
frac -= heightmask;
|
||||
} while (--count);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((count -= 2) >= 0) // texture height is a power of 2
|
||||
{
|
||||
val = source[(frac>>FRACBITS) & heightmask];
|
||||
if (val != TRANSPARENTPIXEL)
|
||||
*dest = colormap[val];
|
||||
dest += vid.width;
|
||||
frac += fracstep;
|
||||
val = source[(frac>>FRACBITS) & heightmask];
|
||||
if (val != TRANSPARENTPIXEL)
|
||||
*dest = colormap[val];
|
||||
dest += vid.width;
|
||||
frac += fracstep;
|
||||
}
|
||||
if (count & 1)
|
||||
{
|
||||
val = source[(frac>>FRACBITS) & heightmask];
|
||||
if (val != TRANSPARENTPIXEL)
|
||||
*dest = colormap[val];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void R_Draw2sMultiPatchTranslucentColumn_8(void)
|
||||
{
|
||||
INT32 count;
|
||||
register UINT8 *dest;
|
||||
register fixed_t frac;
|
||||
fixed_t fracstep;
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
|
||||
if (count < 0) // Zero length, column does not exceed a pixel.
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Framebuffer destination address.
|
||||
dest = &topleft[dc_yl*vid.width + dc_x];
|
||||
|
||||
count++;
|
||||
|
||||
// Determine scaling, which is the only mapping to be done.
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
|
||||
|
||||
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
|
||||
// This is as fast as it gets.
|
||||
{
|
||||
register const UINT8 *source = dc_source;
|
||||
register const UINT8 *transmap = dc_transmap;
|
||||
register const lighttable_t *colormap = dc_colormap;
|
||||
register INT32 heightmask = dc_texheight-1;
|
||||
register UINT8 val;
|
||||
if (dc_texheight & heightmask) // not a power of 2 -- killough
|
||||
{
|
||||
heightmask++;
|
||||
heightmask <<= FRACBITS;
|
||||
|
||||
if (frac < 0)
|
||||
while ((frac += heightmask) < 0);
|
||||
else
|
||||
while (frac >= heightmask)
|
||||
frac -= heightmask;
|
||||
|
||||
do
|
||||
{
|
||||
// Re-map color indices from wall texture column
|
||||
// using a lighting/special effects LUT.
|
||||
// heightmask is the Tutti-Frutti fix
|
||||
val = source[frac>>FRACBITS];
|
||||
|
||||
if (val != TRANSPARENTPIXEL)
|
||||
*dest = *(transmap + (colormap[val]<<8) + (*dest));
|
||||
|
||||
dest += vid.width;
|
||||
|
||||
// Avoid overflow.
|
||||
if (fracstep > 0x7FFFFFFF - frac)
|
||||
frac += fracstep - heightmask;
|
||||
else
|
||||
frac += fracstep;
|
||||
|
||||
while (frac >= heightmask)
|
||||
frac -= heightmask;
|
||||
} while (--count);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((count -= 2) >= 0) // texture height is a power of 2
|
||||
{
|
||||
val = source[(frac>>FRACBITS) & heightmask];
|
||||
if (val != TRANSPARENTPIXEL)
|
||||
*dest = *(transmap + (colormap[val]<<8) + (*dest));
|
||||
dest += vid.width;
|
||||
frac += fracstep;
|
||||
val = source[(frac>>FRACBITS) & heightmask];
|
||||
if (val != TRANSPARENTPIXEL)
|
||||
*dest = *(transmap + (colormap[val]<<8) + (*dest));
|
||||
dest += vid.width;
|
||||
frac += fracstep;
|
||||
}
|
||||
if (count & 1)
|
||||
{
|
||||
val = source[(frac>>FRACBITS) & heightmask];
|
||||
if (val != TRANSPARENTPIXEL)
|
||||
*dest = *(transmap + (colormap[val]<<8) + (*dest));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief The R_DrawShadeColumn_8 function
|
||||
Experiment to make software go faster. Taken from the Boom source
|
||||
*/
|
||||
|
|
48
src/r_fps.c
48
src/r_fps.c
|
@ -120,6 +120,19 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe
|
|||
return out;
|
||||
}
|
||||
|
||||
static double R_LerpDouble(double from, double to, double frac)
|
||||
{
|
||||
return from + (frac * (to - from));
|
||||
}
|
||||
|
||||
static dvector3_t *R_LerpDVector3(const dvector3_t *from, const dvector3_t *to, double frac, dvector3_t *out)
|
||||
{
|
||||
DVector3_Subtract(to, from, out);
|
||||
DVector3_Multiply(out, frac, out);
|
||||
DVector3_Add(from, out, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// recalc necessary stuff for mouseaiming
|
||||
// slopes are already calculated for the full possible view (which is 4*viewheight).
|
||||
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
|
||||
|
@ -497,6 +510,14 @@ void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope)
|
|||
FV2_Copy(&interp->dynslope.bakd, &slope->d);
|
||||
|
||||
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta;
|
||||
|
||||
DVector3_Copy(&interp->dynslope.oldorigin, &slope->dorigin);
|
||||
DVector3_Copy(&interp->dynslope.bakorigin, &slope->dorigin);
|
||||
|
||||
DVector3_Copy(&interp->dynslope.oldnormdir, &slope->dnormdir);
|
||||
DVector3_Copy(&interp->dynslope.baknormdir, &slope->dnormdir);
|
||||
|
||||
interp->dynslope.olddzdelta = interp->dynslope.bakdzdelta = slope->dzdelta;
|
||||
}
|
||||
|
||||
void R_InitializeLevelInterpolators(void)
|
||||
|
@ -561,6 +582,21 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp)
|
|||
FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o);
|
||||
FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d);
|
||||
interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta;
|
||||
|
||||
DVector3_Copy(&interp->dynslope.oldorigin, &interp->dynslope.bakorigin);
|
||||
DVector3_Copy(&interp->dynslope.oldnormdir, &interp->dynslope.baknormdir);
|
||||
interp->dynslope.olddzdelta = interp->dynslope.bakdzdelta;
|
||||
|
||||
if (interp->dynslope.slope->moved)
|
||||
{
|
||||
P_CalculateSlopeVectors(interp->dynslope.slope);
|
||||
|
||||
interp->dynslope.slope->moved = false;
|
||||
}
|
||||
|
||||
DVector3_Copy(&interp->dynslope.bakorigin, &interp->dynslope.slope->dorigin);
|
||||
DVector3_Copy(&interp->dynslope.baknormdir, &interp->dynslope.slope->dnormdir);
|
||||
interp->dynslope.bakdzdelta = interp->dynslope.slope->dzdelta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -646,7 +682,13 @@ void R_ApplyLevelInterpolators(fixed_t frac)
|
|||
R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o);
|
||||
R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d);
|
||||
interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac);
|
||||
interp->dynslope.slope->moved = true;
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
double dfrac = FixedToDouble(frac);
|
||||
R_LerpDVector3(&interp->dynslope.oldorigin, &interp->dynslope.bakorigin, dfrac, &interp->dynslope.slope->dorigin);
|
||||
R_LerpDVector3(&interp->dynslope.oldnormdir, &interp->dynslope.baknormdir, dfrac, &interp->dynslope.slope->dnormdir);
|
||||
interp->dynslope.slope->dzdelta = R_LerpDouble(interp->dynslope.olddzdelta, interp->dynslope.bakdzdelta, dfrac);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -704,6 +746,10 @@ void R_RestoreLevelInterpolators(void)
|
|||
FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako);
|
||||
FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd);
|
||||
interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta;
|
||||
|
||||
DVector3_Copy(&interp->dynslope.slope->dorigin, &interp->dynslope.bakorigin);
|
||||
DVector3_Copy(&interp->dynslope.slope->dnormdir, &interp->dynslope.baknormdir);
|
||||
interp->dynslope.slope->dzdelta = interp->dynslope.bakdzdelta;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,6 +115,9 @@ typedef struct levelinterpolator_s {
|
|||
vector3_t oldo, bako;
|
||||
vector2_t oldd, bakd;
|
||||
fixed_t oldzdelta, bakzdelta;
|
||||
dvector3_t oldorigin, bakorigin;
|
||||
dvector3_t oldnormdir, baknormdir;
|
||||
double olddzdelta, bakdzdelta;
|
||||
} dynslope;
|
||||
};
|
||||
} levelinterpolator_t;
|
||||
|
|
144
src/r_segs.c
144
src/r_segs.c
|
@ -120,6 +120,98 @@ static INT16 R_BottomLightLevel(side_t *side, UINT8 base_lightlevel)
|
|||
}
|
||||
*/
|
||||
|
||||
// If we have a multi-patch texture on a 2sided wall (rare) then we draw
|
||||
// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this
|
||||
// way we don't have to store extra post_t info with each column for
|
||||
// multi-patch textures. They are not normally needed as multi-patch
|
||||
// textures don't have holes in it. At least not for now.
|
||||
static void R_Render2sidedMultiPatchColumn(column_t *column, unsigned lengthcol)
|
||||
{
|
||||
INT32 topscreen, bottomscreen;
|
||||
|
||||
post_t *post = &column->posts[0];
|
||||
if (!post->length)
|
||||
return;
|
||||
|
||||
topscreen = sprtopscreen;
|
||||
bottomscreen = topscreen + spryscale * lengthcol;
|
||||
|
||||
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
|
||||
dc_yh = (bottomscreen-1)>>FRACBITS;
|
||||
|
||||
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
|
||||
{
|
||||
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
|
||||
dc_yh = (windowbottom - 1)>>FRACBITS;
|
||||
}
|
||||
|
||||
if (dc_yh >= mfloorclip[dc_x])
|
||||
dc_yh = mfloorclip[dc_x] - 1;
|
||||
if (dc_yl <= mceilingclip[dc_x])
|
||||
dc_yl = mceilingclip[dc_x] + 1;
|
||||
|
||||
if (dc_yl >= vid.height || dc_yh < 0)
|
||||
return;
|
||||
|
||||
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
|
||||
{
|
||||
dc_source = column->pixels + post->data_offset;
|
||||
dc_postlength = post->length;
|
||||
|
||||
if (colfunc == colfuncs[BASEDRAWFUNC])
|
||||
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])();
|
||||
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
|
||||
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])();
|
||||
else
|
||||
colfunc();
|
||||
}
|
||||
}
|
||||
|
||||
static void R_RenderFlipped2sidedMultiPatchColumn(column_t *column, unsigned lengthcol)
|
||||
{
|
||||
INT32 topscreen, bottomscreen;
|
||||
|
||||
void (*localcolfunc)(void);
|
||||
|
||||
post_t *post = &column->posts[0];
|
||||
if (!post->length)
|
||||
return;
|
||||
|
||||
topscreen = sprtopscreen;
|
||||
bottomscreen = topscreen + spryscale * lengthcol;
|
||||
|
||||
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
|
||||
dc_yh = (bottomscreen-1)>>FRACBITS;
|
||||
|
||||
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
|
||||
{
|
||||
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
|
||||
dc_yh = (windowbottom - 1)>>FRACBITS;
|
||||
}
|
||||
|
||||
if (dc_yh >= mfloorclip[dc_x])
|
||||
dc_yh = mfloorclip[dc_x] - 1;
|
||||
if (dc_yl <= mceilingclip[dc_x])
|
||||
dc_yl = mceilingclip[dc_x] + 1;
|
||||
|
||||
if (dc_yl >= vid.height || dc_yh < 0)
|
||||
return;
|
||||
|
||||
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
|
||||
{
|
||||
dc_postlength = post->length;
|
||||
|
||||
if (colfunc == colfuncs[BASEDRAWFUNC])
|
||||
localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCH];
|
||||
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
|
||||
localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS];
|
||||
else
|
||||
localcolfunc = colfunc;
|
||||
|
||||
R_DrawFlippedPost(column->pixels + post->data_offset, post->length, localcolfunc);
|
||||
}
|
||||
}
|
||||
|
||||
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
||||
{
|
||||
size_t pindex;
|
||||
|
@ -207,7 +299,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
// Texture must be cached
|
||||
R_CheckTextureCache(texnum);
|
||||
|
||||
if (vertflip) // vertically flipped?
|
||||
// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
|
||||
// are not stored per-column with post info in SRB2
|
||||
if (!textures[texnum]->transparency)
|
||||
{
|
||||
if (vertflip) // vertically flipped?
|
||||
colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn;
|
||||
else
|
||||
colfunc_2s = R_Render2sidedMultiPatchColumn;
|
||||
}
|
||||
else if (vertflip) // vertically flipped?
|
||||
colfunc_2s = R_DrawFlippedMaskedColumn;
|
||||
else
|
||||
colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
|
||||
|
@ -836,7 +937,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
// Texture must be cached
|
||||
R_CheckTextureCache(texnum);
|
||||
|
||||
if (vertflip) // vertically flipped?
|
||||
// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
|
||||
// are not stored per-column with post info in SRB2
|
||||
if (!textures[texnum]->transparency)
|
||||
{
|
||||
if (vertflip) // vertically flipped?
|
||||
colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn;
|
||||
else
|
||||
colfunc_2s = R_Render2sidedMultiPatchColumn;
|
||||
}
|
||||
else if (vertflip) // vertically flipped?
|
||||
colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
|
||||
else
|
||||
colfunc_2s = R_DrawRepeatMaskedColumn;
|
||||
|
@ -919,21 +1029,25 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
{
|
||||
dc_iscale = 0xffffffffu / (unsigned)spryscale;
|
||||
|
||||
// Column has a single post and it matches the texture height, use regular column drawers
|
||||
if (col->num_posts == 1 && col->posts[0].topdelta == 0 && col->posts[0].length == (unsigned)dc_texheight)
|
||||
// Skip if texture is multipatch
|
||||
if (textures[texnum]->transparency)
|
||||
{
|
||||
if (fuzzy)
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
// Column has a single post and it matches the texture height, use regular column drawers
|
||||
if (col->num_posts == 1 && col->posts[0].topdelta == 0 && col->posts[0].length == (unsigned)dc_texheight)
|
||||
{
|
||||
if (fuzzy)
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
else
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
}
|
||||
else
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise use column drawers with extra checks
|
||||
if (fuzzy)
|
||||
colfunc = R_DrawTranslucentColumnClamped_8;
|
||||
else
|
||||
colfunc = R_DrawColumnClamped_8;
|
||||
{
|
||||
// Otherwise use column drawers with extra checks
|
||||
if (fuzzy)
|
||||
colfunc = colfuncs[COLDRAWFUNC_CLAMPEDTRANS];
|
||||
else
|
||||
colfunc = colfuncs[COLDRAWFUNC_CLAMPED];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -147,9 +147,9 @@ static void R_DrawFlippedColumnInCache(column_t *column, UINT8 *cache, texpatch_
|
|||
|
||||
if (count > 0)
|
||||
{
|
||||
for (; dest < cache + position + count; --source, is_opaque++)
|
||||
for (; dest < cache + position + count; --source, dest++, is_opaque++)
|
||||
{
|
||||
*dest++ = *source;
|
||||
*dest = *source;
|
||||
*is_opaque = true;
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +295,6 @@ UINT8 *R_GenerateTexture(size_t texnum)
|
|||
UINT16 lumpnum = patch->lump;
|
||||
UINT8 *pdata;
|
||||
softwarepatch_t *realpatch;
|
||||
boolean holey = false;
|
||||
|
||||
#ifndef NO_PNG_LUMPS
|
||||
UINT8 header[PNG_HEADER_SIZE];
|
||||
|
@ -310,9 +309,11 @@ UINT8 *R_GenerateTexture(size_t texnum)
|
|||
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
|
||||
realpatch = (softwarepatch_t *)pdata;
|
||||
|
||||
texture->transparency = false;
|
||||
|
||||
// Check the patch for holes.
|
||||
if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height))
|
||||
holey = true;
|
||||
texture->transparency = true;
|
||||
else
|
||||
{
|
||||
UINT8 *colofs = (UINT8 *)realpatch->columnofs;
|
||||
|
@ -332,12 +333,12 @@ UINT8 *R_GenerateTexture(size_t texnum)
|
|||
col = (doompost_t *)((UINT8 *)col + col->length + 4);
|
||||
}
|
||||
if (y < texture->height)
|
||||
holey = true; // this texture is HOLEy! D:
|
||||
texture->transparency = true; // this texture is HOLEy! D:
|
||||
}
|
||||
}
|
||||
|
||||
// If the patch uses transparency, we have to save it this way.
|
||||
if (holey)
|
||||
if (texture->transparency)
|
||||
{
|
||||
texture->flip = patch->flip;
|
||||
|
||||
|
@ -378,6 +379,15 @@ UINT8 *R_GenerateTexture(size_t texnum)
|
|||
temp_columns = Z_Calloc(sizeof(column_t) * texture->width, PU_STATIC, NULL);
|
||||
temp_block = Z_Calloc(total_pixels, PU_STATIC, NULL);
|
||||
|
||||
#ifdef TEXTURE_255_IS_TRANSPARENT
|
||||
texture->transparency = false;
|
||||
|
||||
// Transparency hack
|
||||
memset(temp_block, TRANSPARENTPIXEL, total_pixels);
|
||||
#else
|
||||
texture->transparency = true;
|
||||
#endif
|
||||
|
||||
for (x = 0; x < texture->width; x++)
|
||||
{
|
||||
column_t *column = &temp_columns[x];
|
||||
|
@ -474,13 +484,27 @@ UINT8 *R_GenerateTexture(size_t texnum)
|
|||
// Now write the columns
|
||||
column_posts = Z_Calloc(sizeof(unsigned) * texture->width, PU_STATIC, NULL);
|
||||
|
||||
#ifdef TEXTURE_255_IS_TRANSPARENT
|
||||
total_posts = texture->width;
|
||||
temp_posts = Z_Realloc(temp_posts, sizeof(post_t) * total_posts, PU_CACHE, NULL);
|
||||
#endif
|
||||
|
||||
for (x = 0; x < texture->width; x++)
|
||||
{
|
||||
post_t *post = NULL;
|
||||
boolean was_opaque = false;
|
||||
|
||||
column_t *column = &temp_columns[x];
|
||||
|
||||
#ifdef TEXTURE_255_IS_TRANSPARENT
|
||||
post = &temp_posts[x];
|
||||
post->topdelta = 0;
|
||||
post->length = texture->height;
|
||||
post->data_offset = 0;
|
||||
column_posts[x] = x;
|
||||
column->num_posts = 1;
|
||||
#else
|
||||
boolean was_opaque = false;
|
||||
|
||||
column_posts[x] = (unsigned)-1;
|
||||
|
||||
for (INT32 y = 0; y < texture->height; y++)
|
||||
|
@ -510,6 +534,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
|
|||
|
||||
post->length++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels);
|
||||
|
|
|
@ -54,6 +54,7 @@ typedef struct
|
|||
char name[8];
|
||||
UINT32 hash;
|
||||
UINT8 type; // TEXTURETYPE_*
|
||||
boolean transparency;
|
||||
INT16 width, height;
|
||||
UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
|
||||
void *flat; // The texture, as a flat.
|
||||
|
|
|
@ -112,6 +112,10 @@ void SCR_SetDrawFuncs(void)
|
|||
colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8;
|
||||
colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8;
|
||||
colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8;
|
||||
colfuncs[COLDRAWFUNC_CLAMPED] = R_DrawColumnClamped_8;
|
||||
colfuncs[COLDRAWFUNC_CLAMPEDTRANS] = R_DrawTranslucentColumnClamped_8;
|
||||
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8;
|
||||
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8;
|
||||
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8;
|
||||
|
||||
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8;
|
||||
|
|
|
@ -97,6 +97,10 @@ enum
|
|||
COLDRAWFUNC_SHADE,
|
||||
COLDRAWFUNC_SHADOWED,
|
||||
COLDRAWFUNC_TRANSTRANS,
|
||||
COLDRAWFUNC_CLAMPED,
|
||||
COLDRAWFUNC_CLAMPEDTRANS,
|
||||
COLDRAWFUNC_TWOSMULTIPATCH,
|
||||
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
|
||||
COLDRAWFUNC_FOG,
|
||||
|
||||
COLDRAWFUNC_MAX
|
||||
|
|
|
@ -582,7 +582,7 @@ boolean Snake_JoyGrabber(void *opaque, event_t *ev)
|
|||
{
|
||||
snake_t *snake = opaque;
|
||||
|
||||
if (ev->type == ev_joystick && ev->key == 0)
|
||||
if (snake != NULL && ev->type == ev_joystick && ev->key == 0)
|
||||
{
|
||||
snake->joyevents[snake->joyeventcount] = ev;
|
||||
snake->joyeventcount++;
|
||||
|
|
Loading…
Reference in a new issue