mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-03-20 18:01:16 +00:00
Implement scrolling menu backgrounds
This commit is contained in:
parent
32dc47207d
commit
1e6369e8de
5 changed files with 64 additions and 94 deletions
|
@ -732,6 +732,8 @@ void D_StartTitle(void)
|
|||
F_StartTitleScreen();
|
||||
CON_ToggleOff();
|
||||
|
||||
currentMenu = &MainDef; // reset the current menu ID
|
||||
|
||||
// Reset the palette
|
||||
if (rendermode != render_none)
|
||||
V_SetPaletteLump("PLAYPAL");
|
||||
|
|
130
src/f_finale.c
130
src/f_finale.c
|
@ -80,7 +80,7 @@ static patch_t *ttspop5;
|
|||
static patch_t *ttspop6;
|
||||
static patch_t *ttspop7;
|
||||
|
||||
static void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname);
|
||||
void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname);
|
||||
|
||||
//
|
||||
// PROMPT STATE
|
||||
|
@ -182,111 +182,58 @@ static void F_NewCutscene(const char *basetext)
|
|||
cutscene_textcount = TICRATE/2;
|
||||
}
|
||||
|
||||
//
|
||||
// F_DrawPatchCol
|
||||
//
|
||||
static void F_DrawPatchCol(INT32 x, INT32 yoffs, patch_t *patch, INT32 col)
|
||||
{
|
||||
const column_t *column;
|
||||
const UINT8 *source;
|
||||
UINT8 *desttop, *dest = NULL;
|
||||
const UINT8 *deststop, *destbottom;
|
||||
size_t count;
|
||||
|
||||
desttop = screens[0] + x*vid.dupx;
|
||||
deststop = screens[0] + vid.rowbytes * vid.height;
|
||||
destbottom = desttop + vid.height*vid.width;
|
||||
|
||||
do {
|
||||
INT32 topdelta, prevdelta = -1;
|
||||
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[col]));
|
||||
|
||||
// step through the posts in a column
|
||||
while (column->topdelta != 0xff)
|
||||
{
|
||||
topdelta = column->topdelta;
|
||||
if (topdelta <= prevdelta)
|
||||
topdelta += prevdelta;
|
||||
prevdelta = topdelta;
|
||||
source = (const UINT8 *)column + 3;
|
||||
dest = desttop + topdelta*vid.width;
|
||||
count = column->length;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
INT32 dupycount = vid.dupy;
|
||||
|
||||
while (dupycount-- && dest < destbottom)
|
||||
{
|
||||
INT32 dupxcount = vid.dupx;
|
||||
while (dupxcount-- && dest <= deststop)
|
||||
*dest++ = *source;
|
||||
|
||||
dest += (vid.width - vid.dupx);
|
||||
}
|
||||
source++;
|
||||
}
|
||||
column = (const column_t *)((const UINT8 *)column + column->length + 4);
|
||||
}
|
||||
|
||||
desttop += SHORT(patch->height)*vid.dupy*vid.width;
|
||||
} while(dest < destbottom);
|
||||
}
|
||||
|
||||
//
|
||||
// F_SkyScroll
|
||||
//
|
||||
static void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname)
|
||||
void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname)
|
||||
{
|
||||
INT32 scrolled, x, mx, fakedwidth;
|
||||
INT32 yscrolled, y, my, fakedheight;
|
||||
patch_t *pat;
|
||||
INT32 xscrolled, x, xneg = (scrollxspeed > 0) - (scrollxspeed < 0), tilex;
|
||||
INT32 yscrolled, y, yneg = (scrollyspeed > 0) - (scrollyspeed < 0), tiley;
|
||||
boolean xispos = (scrollxspeed >= 0), yispos = (scrollyspeed >= 0);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT16 patwidth, patheight;
|
||||
INT32 pw, ph; // scaled by dupz
|
||||
patch_t *pat;
|
||||
INT32 i, j;
|
||||
|
||||
if (rendermode == render_none)
|
||||
return;
|
||||
|
||||
if (!patchname || !patchname[0])
|
||||
{
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
||||
V_DrawFill(0, 0, vid.width, vid.height, 31);
|
||||
return;
|
||||
}
|
||||
|
||||
pat = W_CachePatchName("TITLESKY", PU_CACHE);
|
||||
pat = W_CachePatchName(patchname, PU_CACHE);
|
||||
|
||||
patwidth = SHORT(pat->width);
|
||||
animtimer = ((finalecount*scrollxspeed)/16 + patwidth) % patwidth;
|
||||
|
||||
patheight = SHORT(pat->height);
|
||||
skullAnimCounter = ((finalecount*scrollyspeed)/16 + patheight) % patheight;
|
||||
pw = patwidth * dupz;
|
||||
ph = patheight * dupz;
|
||||
|
||||
if (rendermode == render_soft && !scrollyspeed)
|
||||
{ // if only hardware rendering could be this elegant and complete
|
||||
// keep the old behavior for non-vertical scrolling because *shrug*
|
||||
fakedwidth = vid.width / vid.dupx;
|
||||
fakedheight = vid.height / vid.dupy;
|
||||
scrolled = (patwidth - animtimer) - 1;
|
||||
yscrolled = (patheight - skullAnimCounter) - 1;
|
||||
for (x = 0, mx = scrolled; x < fakedwidth; x++, mx = (mx+1)%patwidth)
|
||||
{
|
||||
for (y = 0, my = yscrolled; y < fakedheight; y++, my = (my+1)%patheight)
|
||||
F_DrawPatchCol(x, y, pat, mx);
|
||||
}
|
||||
}
|
||||
else if (rendermode != render_none)
|
||||
{ // if only software rendering could be this simple and retarded
|
||||
// but this does work! because post scrolling goes over my head :upside_down:
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
INT32 pw = patwidth * dupz, ph = patheight * dupz;
|
||||
scrolled = animtimer * dupz;
|
||||
yscrolled = skullAnimCounter * dupz;
|
||||
CONS_Printf("XScroll %d> YScroll %d\n", scrolled, yscrolled);
|
||||
for (x = 0; x < vid.width; x += pw)
|
||||
{
|
||||
for (y = 0; y < vid.height; y += ph)
|
||||
{
|
||||
if (scrolled > 0)
|
||||
V_DrawScaledPatch(scrolled - pw, yscrolled - ph/2, V_NOSCALESTART, pat);
|
||||
tilex = max(FixedCeil(FixedDiv(vid.width, pw)) >> FRACBITS, 1)+2; // one tile on both sides of center
|
||||
tiley = max(FixedCeil(FixedDiv(vid.height, ph)) >> FRACBITS, 1)+2;
|
||||
|
||||
V_DrawScaledPatch(x + scrolled, yscrolled - ph/2, V_NOSCALESTART, pat);
|
||||
}
|
||||
animtimer = ((finalecount*scrollxspeed)/16 + patwidth*xneg) % (patwidth);
|
||||
skullAnimCounter = ((finalecount*scrollyspeed)/16 + patheight*yneg) % (patheight);
|
||||
|
||||
// coordinate offsets
|
||||
xscrolled = animtimer * dupz;
|
||||
yscrolled = skullAnimCounter * dupz;
|
||||
|
||||
for (x = (xispos) ? -pw*(tilex-1)+pw : 0, i = 0;
|
||||
i < tilex;
|
||||
x += pw, i++)
|
||||
{
|
||||
for (y = (yispos) ? -ph*(tiley-1)+ph : 0, j = 0;
|
||||
j < tiley;
|
||||
y += ph, j++)
|
||||
{
|
||||
V_DrawScaledPatch(
|
||||
(xispos) ? xscrolled - x : x + xscrolled,
|
||||
(yispos) ? yscrolled - y : y + yscrolled,
|
||||
V_NOSCALESTART, pat);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1564,8 +1511,7 @@ void F_TitleScreenDrawer(void)
|
|||
return; // We likely came here from retrying. Don't do a damn thing.
|
||||
|
||||
// Draw that sky!
|
||||
if (!titlemapinaction)
|
||||
F_SkyScroll(titlescrollxspeed, titlescrollyspeed, "TITLESKY");
|
||||
M_DrawScrollingBackground("TITLESKY");
|
||||
|
||||
// Don't draw outside of the title screewn, or if the patch isn't there.
|
||||
if (!ttwing || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS))
|
||||
|
|
|
@ -40,6 +40,7 @@ void F_TextPromptTicker(void);
|
|||
void F_GameEndDrawer(void);
|
||||
void F_IntroDrawer(void);
|
||||
void F_TitleScreenDrawer(void);
|
||||
void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname);
|
||||
|
||||
void F_GameEvaluationDrawer(void);
|
||||
void F_StartGameEvaluation(void);
|
||||
|
|
23
src/m_menu.c
23
src/m_menu.c
|
@ -2202,7 +2202,7 @@ menumeta_t menumeta[NUMMENUTYPES];
|
|||
// return false - continue
|
||||
typedef boolean (*menutree_iterator)(UINT32, INT32, INT32 *, void **);
|
||||
|
||||
static INT32 M_IterateMenuTree(menutree_iterator itfunc, void **input)
|
||||
static INT32 M_IterateMenuTree(menutree_iterator itfunc, void *input)
|
||||
{
|
||||
INT32 i, retval = 0;
|
||||
UINT32 bitmask, menutype;
|
||||
|
@ -2218,7 +2218,7 @@ static INT32 M_IterateMenuTree(menutree_iterator itfunc, void **input)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static INT32 M_IterateMenuTreeFromTop(menutree_iterator itfunc, void **input)
|
||||
static INT32 M_IterateMenuTreeFromTop(menutree_iterator itfunc, void *input)
|
||||
{
|
||||
INT32 i, retval = 0;
|
||||
UINT32 bitmask, menutype;
|
||||
|
@ -2272,6 +2272,20 @@ static boolean MIT_DrawBackground(UINT32 menutype, INT32 level, INT32 *retval, v
|
|||
return false;
|
||||
}
|
||||
|
||||
static boolean MIT_DrawScrollingBackground(UINT32 menutype, INT32 level, INT32 *retval, void **input)
|
||||
{
|
||||
char *defaultname = (char*)*input;
|
||||
|
||||
if (menumeta[menutype].bgname[0])
|
||||
{
|
||||
F_SkyScroll(menumeta[menutype].titlescrollxspeed, menumeta[menutype].titlescrollyspeed, menumeta[menutype].bgname);
|
||||
return true;
|
||||
}
|
||||
else if (!level && defaultname && defaultname[0])
|
||||
F_SkyScroll(titlescrollxspeed, titlescrollyspeed, defaultname);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ====================================
|
||||
// TREE RETRIEVAL
|
||||
// ====================================
|
||||
|
@ -2300,6 +2314,11 @@ static void M_DrawBackground(char *defaultname)
|
|||
M_IterateMenuTree(MIT_DrawBackground, defaultname);
|
||||
}
|
||||
|
||||
void M_DrawScrollingBackground(char *defaultname)
|
||||
{
|
||||
M_IterateMenuTree(MIT_DrawScrollingBackground, defaultname);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// BASIC MENU HANDLING
|
||||
// =========================================================================
|
||||
|
|
|
@ -141,6 +141,8 @@ typedef struct
|
|||
|
||||
extern menumeta_t menumeta[NUMMENUTYPES];
|
||||
|
||||
void M_DrawScrollingBackground(char *defaultname);
|
||||
|
||||
// Called by main loop,
|
||||
// saves config file and calls I_Quit when user exits.
|
||||
// Even when the menu is not displayed,
|
||||
|
|
Loading…
Reference in a new issue