diff --git a/src/d_main.c b/src/d_main.c index ec9677173..fa89e549e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1096,6 +1096,9 @@ void D_SRB2Main(void) // adapt tables to SRB2's needs, including extra slots for dehacked file support P_PatchInfoTables(); + // initiate menu metadata before SOCcing them + MN_InitInfoTables(); + //---------------------------------------------------- READY TIME // we need to check for dedicated before initialization of some subsystems diff --git a/src/dehacked.c b/src/dehacked.c index 286a4729b..c3db3f57e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1963,6 +1963,7 @@ static void readmenu(MYFILE *f, INT32 num) } else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "HIDEPICS")) { + // true by default, except MM_MAIN menumeta[num].hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } @@ -2004,12 +2005,14 @@ static void readmenu(MYFILE *f, INT32 num) } else if (fastcmp(word, "MUSICLOOP")) { + // true by default except MM_MAIN menumeta[num].muslooping = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } - else if (fastcmp(word, "FADESCREEN")) + else if (fastcmp(word, "FADESTRENGTH")) { - menumeta[num].fadescreen = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); + // one-based, <= 0 means use default value. 1-32 + menumeta[num].fadestrength = value-1; titlechanged = true; } else if (fastcmp(word, "EXITPARENTS")) diff --git a/src/f_finale.c b/src/f_finale.c index 6c2695a2c..c6963cdfa 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -80,8 +80,6 @@ static patch_t *ttspop5; static patch_t *ttspop6; static patch_t *ttspop7; -void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname); - // // PROMPT STATE // @@ -182,64 +180,6 @@ static void F_NewCutscene(const char *basetext) cutscene_textcount = TICRATE/2; } -// -// F_SkyScroll -// -void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname) -{ - 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, vid.width, vid.height, 31); - return; - } - - pat = W_CachePatchName(patchname, PU_CACHE); - - patwidth = SHORT(pat->width); - patheight = SHORT(pat->height); - pw = patwidth * dupz; - ph = patheight * dupz; - - 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; - - 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); - } - } - - W_UnlockCachedPatch(pat); -} - // ============= // INTRO SCENE // ============= @@ -670,7 +610,7 @@ static void F_IntroDrawScene(void) } else { - F_SkyScroll(80*4, 0, "TITLESKY"); + M_SkyScroll(80*4, 0, "TITLESKY"); if (timetonext == 6) { stoptimer = finalecount; @@ -1413,6 +1353,8 @@ void F_GameEndTicker(void) // ============== void F_StartTitleScreen(void) { + MN_Start(); + if (menumeta[MN_MAIN].musname[0]) S_ChangeMusic(menumeta[MN_MAIN].musname, menumeta[MN_MAIN].mustrack, menumeta[MN_MAIN].muslooping); else @@ -1507,6 +1449,8 @@ void F_StartTitleScreen(void) // (no longer) De-Demo'd Title Screen void F_TitleScreenDrawer(void) { + boolean hidepics; + if (modeattacking) return; // We likely came here from retrying. Don't do a damn thing. @@ -1518,7 +1462,8 @@ void F_TitleScreenDrawer(void) return; // rei|miru: use title pics? - if (hidetitlepics) + hidepics = M_GetHideTitlePics(); + if (hidepics) #ifdef HAVE_BLUA goto luahook; #else diff --git a/src/f_finale.h b/src/f_finale.h index 0b84bd5b0..d2cc4da07 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -40,7 +40,6 @@ 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); diff --git a/src/g_game.c b/src/g_game.c index e250bacc5..c04e707cd 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1954,6 +1954,7 @@ void G_Ticker(boolean run) break; case GS_TIMEATTACK: + MN_Ticker(run); break; case GS_INTRO: @@ -1993,6 +1994,7 @@ void G_Ticker(boolean run) if (titlemapinaction) P_Ticker(run); // then intentionally fall through /* FALLTHRU */ case GS_WAITINGPLAYERS: + MN_Ticker(run); F_TitleScreenTicker(run); break; diff --git a/src/m_menu.c b/src/m_menu.c index 4b113e560..8899e2a73 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2192,6 +2192,16 @@ menu_t *currentMenu = &MainDef; // ========================================================================= menumeta_t menumeta[NUMMENUTYPES]; +static tic_t xscrolltimer; +static tic_t yscrolltimer; +static INT32 menuanimtimer; + +typedef struct +{ + char musname[7]; + UINT16 mustrack; + boolean muslooping; +} menumetamusic_t; // UINT32 menutype - current menutype_t // INT32 level - current level up the tree, higher means younger @@ -2258,31 +2268,58 @@ static boolean MIT_GetEdgeLevel(UINT32 menutype, INT32 level, INT32 *retval, voi return false; } -static boolean MIT_DrawBackground(UINT32 menutype, INT32 level, INT32 *retval, void **input) -{ - char *defaultname = (char*)*input; - - if (menumeta[menutype].bgname[0]) - { - V_DrawPatchFill(W_CachePatchName(menumeta[menutype].bgname, PU_CACHE)); - return true; - } - else if (!level && defaultname && defaultname[0]) - V_DrawPatchFill(W_CachePatchName(defaultname, PU_CACHE)); - 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); + M_SkyScroll(menumeta[menutype].titlescrollxspeed, menumeta[menutype].titlescrollyspeed, menumeta[menutype].bgname); return true; } else if (!level && defaultname && defaultname[0]) - F_SkyScroll(titlescrollxspeed, titlescrollyspeed, defaultname); + M_SkyScroll(titlescrollxspeed, titlescrollyspeed, defaultname); + return false; +} + +static boolean MIT_ChangeMusic(UINT32 menutype, INT32 level, INT32 *retval, void **input) +{ + menumetamusic_t *defaultmusic = (menumetamusic_t*)*input; + + if (menumeta[menutype].musname[0]) + { + S_ChangeMusic(menumeta[menutype].musname, menumeta[menutype].mustrack, menumeta[menutype].muslooping); + return true; + } + else if (!level && defaultmusic && defaultmusic->musname[0]) + S_ChangeMusic(defaultmusic->musname, defaultmusic->mustrack, defaultmusic->muslooping); + return false; +} + +static boolean MIT_FadeScreen(UINT32 menutype, INT32 level, INT32 *retval, void **input) +{ + UINT8 defaultvalue = *(UINT8*)*input; + if (menumeta[menutype].fadestrength >= 0) + { + if (menumeta[menutype].fadestrength % 32) + V_DrawFadeScreen(0xFF00, menumeta[menutype].fadestrength % 32); + return true; + } + else if (!level && (defaultvalue % 32)) + V_DrawFadeScreen(0xFF00, defaultvalue % 32); + return false; +} + +static boolean MIT_GetHideTitlePics(UINT32 menutype, INT32 level, INT32 *retval, void **input) +{ + (void)input; + if (menumeta[menutype].hidetitlepics >= 0) + { + *retval = menumeta[menutype].hidetitlepics; + return true; + } + else if (!level) + *retval = -1; return false; } @@ -2309,16 +2346,37 @@ static UINT8 M_GetYoungestChildLevel() // aka the active menu // EFFECTS // ==================================== -static void M_DrawBackground(char *defaultname) -{ - M_IterateMenuTree(MIT_DrawBackground, defaultname); -} - void M_DrawScrollingBackground(char *defaultname) { M_IterateMenuTree(MIT_DrawScrollingBackground, defaultname); } +static void M_ChangeMusic(char *defaultmusname, boolean defaultmuslooping) +{ + menumetamusic_t defaultmusic; + + if (!defaultmusname) + defaultmusname = ""; + + strncpy(defaultmusic.musname, defaultmusname, 7); + defaultmusic.musname[6] = 0; + defaultmusic.mustrack = 0; + defaultmusic.muslooping = defaultmuslooping; + + M_IterateMenuTree(MIT_ChangeMusic, &defaultmusic); +} + +static void M_DrawFadeScreen(UINT8 defaultvalue) +{ + M_IterateMenuTree(MIT_FadeScreen, &defaultvalue); +} + +boolean M_GetHideTitlePics(void) +{ + INT32 retval = M_IterateMenuTree(MIT_GetHideTitlePics, NULL); + return (retval >= 0 ? retval : hidetitlepics); +} + // ========================================================================= // BASIC MENU HANDLING // ========================================================================= @@ -2807,7 +2865,7 @@ void M_Drawer(void) { // now that's more readable with a faded background (yeah like Quake...) if (!WipeInAction) - V_DrawFadeScreen(0xFF00, 16); + M_DrawFadeScreen(16); if (currentMenu->drawroutine) currentMenu->drawroutine(); // call current menu Draw routine @@ -3108,6 +3166,103 @@ void M_Init(void) #endif } +// ========================================================================== +// COMMON MENU DRAW ROUTINES +// ========================================================================== + +void MN_InitInfoTables(void) +{ + INT32 i; + + // Called in d_main before SOC can get to the tables + // Set menumeta defaults + for (i = 0; i < NUMMENUTYPES; i++) + { + if (i != MN_MAIN) + { + menumeta[i].muslooping = true; + } + // so-called "undefined" + menumeta[i].fadestrength = -1; + menumeta[i].hidetitlepics = -1; // inherits global hidetitlepics + } +} + +void MN_Start(void) +{ + menuanimtimer = 0; +} + +void MN_Ticker(boolean run) +{ + if (run) + menuanimtimer++; +} + +// +// M_SkyScroll +// +void M_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname) +{ + 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, vid.width, vid.height, 31); + return; + } + + if (!scrollxspeed && !scrollyspeed) + { + V_DrawPatchFill(W_CachePatchName(patchname, PU_CACHE)); + return; + } + + pat = W_CachePatchName(patchname, PU_CACHE); + + patwidth = SHORT(pat->width); + patheight = SHORT(pat->height); + pw = patwidth * dupz; + ph = patheight * dupz; + + 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; + + xscrolltimer = ((menuanimtimer*scrollxspeed)/16 + patwidth*xneg) % (patwidth); + yscrolltimer = ((menuanimtimer*scrollyspeed)/16 + patheight*yneg) % (patheight); + + // coordinate offsets + xscrolled = xscrolltimer * dupz; + yscrolled = yscrolltimer * 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); + } + } + + W_UnlockCachedPatch(pat); +} + // ========================================================================== // SPECIAL MENU OPTION DRAW ROUTINES GO HERE // ========================================================================== @@ -4646,7 +4801,10 @@ static void M_DrawLevelPlatterMenu(void) const INT32 cursorx = (sizeselect ? 0 : (lscol*lshseperation)); if (gamestate == GS_TIMEATTACK) - M_DrawBackground("SRB2BACK"); + { + M_DrawScrollingBackground("SRB2BACK"); + M_DrawFadeScreen(0); + } // finds row at top of the screen while (y > -8) @@ -4848,7 +5006,7 @@ static void M_DrawMessageMenu(void) // hack: draw RA background in RA menus if (gamestate == GS_TIMEATTACK) - M_DrawBackground("SRB2BACK"); + M_DrawScrollingBackground("SRB2BACK"); M_DrawTextBox(currentMenu->x, y - 8, (max+7)>>3, mlines); @@ -7142,12 +7300,8 @@ static void M_SetupChoosePlayer(INT32 choice) return; } - if (Playing() == false) - { - S_StopMusic(); - S_ChangeMusicInternal("_chsel", true); - } + M_ChangeMusic("_chsel", true); SP_PlayerDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_PlayerDef); @@ -7242,7 +7396,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Black BG V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - //M_DrawBackground("SRB2BACK"); + //M_DrawScrollingBackground("SRB2BACK"); // Character select profile images!1 M_DrawTextBox(0, my, 16, 20); @@ -7629,10 +7783,13 @@ void M_DrawTimeAttackMenu(void) INT32 i, x, y, cursory = 0; UINT16 dispstatus; patch_t *PictureOfUrFace; + menutype_t menutype = M_GetYoungestChildMenu(); - S_ChangeMusicInternal("_inter", true); // Eww, but needed for when user hits escape during demo playback + M_ChangeMusic("_inter", true); // Eww, but needed for when user hits escape during demo playback - M_DrawBackground("SRB2BACK"); + M_DrawScrollingBackground("SRB2BACK"); + + M_DrawFadeScreen(0); M_DrawMenuTitle(); @@ -7808,7 +7965,7 @@ static void M_TimeAttack(INT32 choice) Nextmap_OnChange(); G_SetGamestate(GS_TIMEATTACK); - S_ChangeMusicInternal("_inter", true); + M_ChangeMusic("_inter", true); itemOn = tastart; // "Start" is selected. } @@ -7819,9 +7976,11 @@ void M_DrawNightsAttackMenu(void) INT32 i, x, y, cursory = 0; UINT16 dispstatus; - S_ChangeMusicInternal("_inter", true); // Eww, but needed for when user hits escape during demo playback + M_ChangeMusic("_inter", true); // Eww, but needed for when user hits escape during demo playback - M_DrawBackground("SRB2BACK"); + M_DrawScrollingBackground("SRB2BACK"); + + M_DrawFadeScreen(0); M_DrawMenuTitle(); @@ -7985,7 +8144,7 @@ static void M_NightsAttack(INT32 choice) Nextmap_OnChange(); G_SetGamestate(GS_TIMEATTACK); - S_ChangeMusicInternal("_inter", true); + M_ChangeMusic("_inter", true); itemOn = nastart; // "Start" is selected. } @@ -8219,7 +8378,7 @@ static void M_ModeAttackEndGame(INT32 choice) itemOn = currentMenu->lastOn; G_SetGamestate(GS_TIMEATTACK); modeattacking = ATTACKING_NONE; - S_ChangeMusicInternal("_inter", true); + M_ChangeMusic("_inter", true); Nextmap_OnChange(); } diff --git a/src/m_menu.h b/src/m_menu.h index e33642b0d..979165e98 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -125,7 +125,7 @@ typedef enum typedef struct { char bgname[8]; // name for background gfx lump; lays over titlemap if this is set - boolean hidetitlepics; // hide title gfx per menu; inherits global setting + SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting INT32 titlescrollyspeed; // y scroll @@ -133,7 +133,7 @@ typedef struct UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. boolean muslooping; ///< Loop the music - boolean fadescreen; // darken background when displaying this menu + SINT8 fadestrength; // darken background when displaying this menu, strength 0-31 or -1 for undefined boolean exitparents; // run exit line exec on parent menus when entering a child menu INT32 entertag; // line exec to run on menu enter, if titlemap INT32 exittag; // line exec to run on menu exit, if titlemap @@ -142,6 +142,12 @@ typedef struct extern menumeta_t menumeta[NUMMENUTYPES]; void M_DrawScrollingBackground(char *defaultname); +void M_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, char *patchname); +boolean M_GetHideTitlePics(void); +void MN_Ticker(boolean run); +void MN_Start(void); +void MN_InitInfoTables(void); + // Called by main loop, // saves config file and calls I_Quit when user exits.