Replace prevmenu with menustack

menustack[0] replaces both menuactive and activeMenuId
Hopefully this is the last major change to the codebase...
This commit is contained in:
GenericHeroGuy 2025-03-23 01:42:39 +01:00
parent 4933f96422
commit a609c7b5ce
20 changed files with 184 additions and 284 deletions

View file

@ -254,7 +254,7 @@ static void CONS_Bind_f(void)
CONS_Printf("\x82%s", M_GetText("Bind table :\n")); CONS_Printf("\x82%s", M_GetText("Bind table :\n"));
na = 0; na = 0;
for (key = 0; key < NUMINPUTS; key++) for (key = 0; key < NUMINPUTS; key++)
if (!menuactive && bindtable[key]) if (!menustack[0] && bindtable[key])
{ {
CONS_Printf("%s : \"%s\"\n", G_KeynumToString(key), bindtable[key]); CONS_Printf("%s : \"%s\"\n", G_KeynumToString(key), bindtable[key]);
na = 1; na = 1;
@ -978,7 +978,7 @@ boolean CON_Responder(event_t *ev)
// check other keys only if console prompt is active // check other keys only if console prompt is active
if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!! if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!!
{ {
if (! menuactive && bindtable[key]) if (!menustack[0] && bindtable[key])
{ {
COM_BufAddText(bindtable[key]); COM_BufAddText(bindtable[key]);
COM_BufAddText("\n"); COM_BufAddText("\n");

View file

@ -575,7 +575,7 @@ static inline void CL_DrawConnectionStatus(void)
INT32 ccstime = I_GetTime(); INT32 ccstime = I_GetTime();
// Draw background fade // Draw background fade
if (!menuactive) // menu already draws its own fade if (!menustack[0]) // menu already draws its own fade
V_DrawFadeScreen(0xFF00, 16); // force default V_DrawFadeScreen(0xFF00, 16); // force default
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES

View file

@ -1062,8 +1062,6 @@ void D_StartTitle(void)
F_StartTitleScreen(); F_StartTitleScreen();
M_SetCurrentMenu(MN_MAIN); // reset the current menu ID
// Reset the palette // Reset the palette
if (rendermode != render_none) if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL"); V_SetPaletteLump("PLAYPAL");

View file

@ -3302,7 +3302,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
if (paused) if (paused)
{ {
if (!menuactive || netgame) if (!menustack[0] || netgame)
S_PauseAudio(); S_PauseAudio();
} }
else else

View file

@ -2154,10 +2154,9 @@ static menu_t *allocmenu(INT32 num)
if (menu == NULL) if (menu == NULL)
{ {
menudefs[num] = menu = Z_Calloc(sizeof(menu_t), PU_STATIC, NULL); menudefs[num] = menu = Z_Calloc(sizeof(menu_t), PU_STATIC, NULL);
menu->menuid = num;
}
if (menu->drawroutine == NULL)
menu->drawroutine = M_DrawGenericMenu; menu->drawroutine = M_DrawGenericMenu;
}
return menu; return menu;
} }
@ -2576,17 +2575,6 @@ void readmenu(MYFILE *f, INT32 num)
{ {
menudef->headerpic = Z_StrDup(word2); menudef->headerpic = Z_StrDup(word2);
} }
else if (fastcmp(word, "PREVMENU"))
{
value = get_menutype(word2);
if (value == MN_NONE)
{
deh_warning("Menu %d: unknown previous menu '%s'", num, word2);
continue;
}
allocmenu(value);
menudef->prevMenu = value;
}
else if (fastcmp(word, "DRAWROUTINE")) else if (fastcmp(word, "DRAWROUTINE"))
{ {
void (*drawer)(void) = get_menudrawer(word2); void (*drawer)(void) = get_menudrawer(word2);

View file

@ -659,13 +659,13 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
{ {
if (introchanged) if (introchanged)
{ {
menuactive = false; M_ClearMenus(true);
I_UpdateMouseGrab(); I_UpdateMouseGrab();
COM_BufAddText("playintro"); COM_BufAddText("playintro");
} }
else if (titlechanged) else if (titlechanged)
{ {
menuactive = false; M_ClearMenus(true);
I_UpdateMouseGrab(); I_UpdateMouseGrab();
COM_BufAddText("exitgame"); // Command_ExitGame_f() but delayed COM_BufAddText("exitgame"); // Command_ExitGame_f() but delayed
} }

View file

@ -172,7 +172,6 @@ extern boolean digital_disabled;
// ========================= // =========================
// //
extern boolean menuactive; // Menu overlaid?
extern UINT8 paused; // Game paused? extern UINT8 paused; // Game paused?
extern UINT8 window_notinfocus; // are we in focus? (backend independant -- handles auto pausing and display of "focus lost" message) extern UINT8 window_notinfocus; // are we in focus? (backend independant -- handles auto pausing and display of "focus lost" message)
extern INT32 window_x; extern INT32 window_x;

View file

@ -1168,8 +1168,7 @@ void F_GameEndTicker(void)
void F_InitMenuPresValues(void) void F_InitMenuPresValues(void)
{ {
menuanimtimer = 0; menuanimtimer = 0;
prevMenuId = 0; M_ClearMenus(false); // TODO maybe call exit funcs here? but that triggers an infinite loop in replay hut...
activeMenuId = MN_MAIN;
// Set defaults for presentation values // Set defaults for presentation values
strncpy(curbgname, "TITLESKY", 9); strncpy(curbgname, "TITLESKY", 9);
@ -1611,7 +1610,7 @@ void F_TitleScreenTicker(boolean run)
} }
// Hold up for a bit if menu or console active // Hold up for a bit if menu or console active
if (menuactive || CON_Ready()) if (menustack[0] || CON_Ready())
{ {
demoIdleLeft = demoIdleTime; demoIdleLeft = demoIdleTime;
return; return;

View file

@ -1651,13 +1651,11 @@ void G_ConfirmRewind(tic_t rewindtime)
{ {
SINT8 i; SINT8 i;
tic_t j; tic_t j;
boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled; boolean oldsounddisabled = sound_disabled;
INT32 olddp1 = displayplayers[0], olddp2 = displayplayers[1], olddp3 = displayplayers[2], olddp4 = displayplayers[3]; INT32 olddp1 = displayplayers[0], olddp2 = displayplayers[1], olddp3 = displayplayers[2], olddp4 = displayplayers[3];
UINT8 oldss = splitscreen; UINT8 oldss = splitscreen;
menuactive = false; // Prevent loops
CV_StealthSetValue(&cv_renderview, 0); CV_StealthSetValue(&cv_renderview, 0);
if (rewindtime <= starttime) if (rewindtime <= starttime)
@ -1693,7 +1691,6 @@ void G_ConfirmRewind(tic_t rewindtime)
} }
demo.rewinding = false; demo.rewinding = false;
menuactive = oldmenuactive; // Bring the menu back up
sound_disabled = oldsounddisabled; // Re-enable SFX sound_disabled = oldsounddisabled; // Re-enable SFX
wipegamestate = gamestate; // No fading back in! wipegamestate = gamestate; // No fading back in!

View file

@ -1609,7 +1609,7 @@ boolean G_Responder(event_t *ev)
if (modeattacking && !demo.playback && (gamestate == GS_LEVEL)) if (modeattacking && !demo.playback && (gamestate == GS_LEVEL))
{ {
pausebreakkey = (ev->data1 == KEY_PAUSE); pausebreakkey = (ev->data1 == KEY_PAUSE);
if (menuactive || pausedelay < 0 || leveltime < 2) if (menustack[0] || pausedelay < 0 || leveltime < 2)
return true; return true;
if (pausedelay < 1+(NEWTICRATE/2)) if (pausedelay < 1+(NEWTICRATE/2))

View file

@ -19,6 +19,7 @@
#include "d_net.h" #include "d_net.h"
#include "console.h" #include "console.h"
#include "i_joy.h" // JOYAXISRANGE #include "i_joy.h" // JOYAXISRANGE
#include "m_menu.h" // menustack
#define MAXMOUSESENSITIVITY 100 // sensitivity steps #define MAXMOUSESENSITIVITY 100 // sensitivity steps
@ -176,7 +177,7 @@ void G_MapEventsToControls(event_t *ev)
break; break;
case ev_mouse: // buttons are virtual keys case ev_mouse: // buttons are virtual keys
if (menuactive) if (menustack[0])
{ {
break; break;
} }
@ -211,7 +212,7 @@ void G_MapEventsToControls(event_t *ev)
break; break;
case ev_joystick: // buttons are virtual keys case ev_joystick: // buttons are virtual keys
if (menuactive) if (menustack[0])
{ {
break; break;
} }

View file

@ -196,7 +196,7 @@ int LUA_PushGlobals(lua_State *L, const char *word)
lua_pushboolean(L, modifiedgame && !savemoddata); lua_pushboolean(L, modifiedgame && !savemoddata);
return 1; return 1;
} else if (fastcmp(word,"menuactive")) { } else if (fastcmp(word,"menuactive")) {
lua_pushboolean(L, menuactive); lua_pushboolean(L, menustack[0]);
return 1; return 1;
} else if (fastcmp(word,"paused")) { } else if (fastcmp(word,"paused")) {
lua_pushboolean(L, paused); lua_pushboolean(L, paused);

View file

@ -62,7 +62,7 @@ typedef struct
// Cheat responders // Cheat responders
/*static UINT8 cheatf_ultimate(void) /*static UINT8 cheatf_ultimate(void)
{ {
if (menuactive && (currentMenu != &MainDef && currentMenu != &SP_LoadDef)) if (menustack[0] != MN_MAIN && menustack[0] != MN_SP_LOAD))
return 0; // Only on the main menu, or the save select! return 0; // Only on the main menu, or the save select!
BwehHehHe(); BwehHehHe();
@ -82,7 +82,7 @@ static UINT8 cheatf_warp(void)
/*if (modifiedgame) /*if (modifiedgame)
* return 0;*/ * return 0;*/
if (menuactive && activeMenuId != MN_MAIN) if (menustack[0] != MN_MAIN)
return 0; // Only on the main menu! return 0; // Only on the main menu!
// Temporarily unlock EVERYTHING. // Temporarily unlock EVERYTHING.
@ -117,7 +117,7 @@ static UINT8 cheatf_devmode(void)
if (modifiedgame) if (modifiedgame)
return 0; return 0;
if (menuactive && activeMenuId != MN_MAIN) if (menustack[0] != MN_MAIN)
return 0; // Only on the main menu! return 0; // Only on the main menu!
S_StartSound(0, sfx_itemup); S_StartSound(0, sfx_itemup);

View file

@ -147,7 +147,6 @@ const char *quitmsg[NUM_QUITMESSAGES];
// Stuff for customizing the player select screen Tails 09-22-2003 // Stuff for customizing the player select screen Tails 09-22-2003
description_t description[MAXSKINS]; description_t description[MAXSKINS];
boolean menuactive = false;
boolean fromlevelselect = false; boolean fromlevelselect = false;
typedef enum typedef enum
@ -168,6 +167,7 @@ static UINT32 serverlistpage;
INT16 startmap; // Mario, NiGHTS, or just a plain old normal game? INT16 startmap; // Mario, NiGHTS, or just a plain old normal game?
menu_t *menudefs[NUMMENUTYPES] = {NULL}; // pointers to all menudefs menu_t *menudefs[NUMMENUTYPES] = {NULL}; // pointers to all menudefs
menutype_t menustack[NUMMENULEVELS]; // stack of active menus, [0] == current menu
static menu_t *currentMenu; // current menudef static menu_t *currentMenu; // current menudef
static INT16 itemOn = 1; // menu item skull is on, Hack by Tails 09-18-2002 static INT16 itemOn = 1; // menu item skull is on, Hack by Tails 09-18-2002
static INT16 skullAnimCounter = 10; // skull animation counter static INT16 skullAnimCounter = 10; // skull animation counter
@ -288,14 +288,6 @@ static UINT32 M_ServersPerPage(void)
return (UINT32)spp; return (UINT32)spp;
} }
// set the current menu, but without doing everything that M_SetupNextMenu does
// is this even necessary...?
void M_SetCurrentMenu(menutype_t num)
{
currentMenu = menudefs[num];
activeMenuId = num;
}
// ========================================================================== // ==========================================================================
// CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE. // CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE.
// ========================================================================== // ==========================================================================
@ -486,7 +478,7 @@ void M_OpenGLOptionsMenu(INT32 choice)
(void)choice; (void)choice;
if (rendermode == render_opengl) if (rendermode == render_opengl)
M_SetupNextMenu(MN_OP_OPENGL); M_EnterMenu(MN_OP_OPENGL, true);
else else
M_StartMessage(M_GetText("You must be in OpenGL mode\nto access this menu.\n\n(Press a key)\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("You must be in OpenGL mode\nto access this menu.\n\n(Press a key)\n"), NULL, MM_NOTHING);
} }
@ -537,7 +529,7 @@ void Nextmap_OnChange(void)
leveltitle = cv_nextmap.value ? G_BuildMapTitle(cv_nextmap.value) : Z_StrDup("Random"); leveltitle = cv_nextmap.value ? G_BuildMapTitle(cv_nextmap.value) : Z_StrDup("Random");
cv_nextmap.string = cv_nextmap.zstring = leveltitle; cv_nextmap.string = cv_nextmap.zstring = leveltitle;
if (activeMenuId == MN_SP_TIMEATTACK) if (menustack[0] == MN_SP_TIMEATTACK)
{ {
// see also p_setup.c's P_LoadRecordGhosts // see also p_setup.c's P_LoadRecordGhosts
const char *gamemode = (levellistmode == LLM_ITEMBREAKER) ? "IB" : "RA"; const char *gamemode = (levellistmode == LLM_ITEMBREAKER) ? "IB" : "RA";
@ -666,7 +658,7 @@ static void Dummystaff_OnChange(void)
// Newgametype. Used for gametype changes. // Newgametype. Used for gametype changes.
static void Newgametype_OnChange(void) static void Newgametype_OnChange(void)
{ {
if (menuactive && cv_nextmap.value) if (menustack[0] && cv_nextmap.value)
{ {
INT32 gt = cv_newgametype.value; INT32 gt = cv_newgametype.value;
@ -727,10 +719,6 @@ void Moviemode_option_Onchange(void)
// MENU PRESENTATION PARAMETER HANDLING (BACKGROUNDS) // MENU PRESENTATION PARAMETER HANDLING (BACKGROUNDS)
// ========================================================================= // =========================================================================
// menu IDs are equal to current/prevMenu in most cases, except MN_SPECIAL when we don't want to operate on Message, Pause, etc.
UINT32 prevMenuId = 0;
UINT32 activeMenuId = 0;
menupres_t menupres[NUMMENUTYPES]; menupres_t menupres[NUMMENUTYPES];
void M_InitMenuPresTables(void) void M_InitMenuPresTables(void)
@ -971,7 +959,7 @@ boolean M_Responder(event_t *ev)
break; break;
} }
} }
else if (menuactive) else if (menustack[0])
{ {
if (ev->type == ev_joystick && deviceplayer == 0) if (ev->type == ev_joystick && deviceplayer == 0)
{ {
@ -1053,7 +1041,7 @@ boolean M_Responder(event_t *ev)
for (size_t r = 0; r < sizeof(joyremap)/sizeof(*joyremap); r++) for (size_t r = 0; r < sizeof(joyremap)/sizeof(*joyremap); r++)
{ {
INT32 gc = joyremap[r][0]; INT32 gc = joyremap[r][0];
if (gc == gc_brake && !menuactive) if (gc == gc_brake && !menustack[0])
continue; // don't open the menu with brake! continue; // don't open the menu with brake!
if (G_ControlBoundToKey(0, gc, ch, true)) if (G_ControlBoundToKey(0, gc, ch, true))
@ -1068,7 +1056,7 @@ boolean M_Responder(event_t *ev)
return false; return false;
// F-Keys // F-Keys
if (!menuactive) if (!menustack[0])
{ {
noFurtherInput = true; noFurtherInput = true;
@ -1090,7 +1078,7 @@ boolean M_Responder(event_t *ev)
return true; return true;
M_StartControlPanel(); M_StartControlPanel();
M_Options(0); M_Options(0);
M_SetCurrentMenu(MN_OP_SOUND); M_EnterMenu(MN_OP_SOUND, true);
itemOn = 0; itemOn = 0;
return true; return true;
@ -1100,6 +1088,7 @@ boolean M_Responder(event_t *ev)
return true; return true;
M_StartControlPanel(); M_StartControlPanel();
M_Options(0); M_Options(0);
M_EnterMenu(MN_OP_VIDEO, true);
M_VideoModeMenu(0); M_VideoModeMenu(0);
return true; return true;
#endif #endif
@ -1112,7 +1101,6 @@ boolean M_Responder(event_t *ev)
return true; return true;
M_StartControlPanel(); M_StartControlPanel();
M_Options(0); M_Options(0);
M_SetupNextMenu(MN_OP_MAIN);
return true; return true;
// Screenshots on F8 now handled elsewhere // Screenshots on F8 now handled elsewhere
@ -1200,7 +1188,7 @@ boolean M_Responder(event_t *ev)
routine = M_ChangeCvar; routine = M_ChangeCvar;
} }
if (activeMenuId == MN_PLAYBACK && !con_destlines) if (menustack[0] == MN_PLAYBACK && !con_destlines)
{ {
playback_last_menu_interaction_leveltime = leveltime; playback_last_menu_interaction_leveltime = leveltime;
// Flip left/right with up/down for the playback menu, since it's a horizontal icon row. // Flip left/right with up/down for the playback menu, since it's a horizontal icon row.
@ -1281,7 +1269,7 @@ boolean M_Responder(event_t *ev)
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{ {
if (activeMenuId != MN_OP_SOUND || itemOn > 3) if (menustack[0] != MN_OP_SOUND || itemOn > 3)
S_StartSound(NULL, sfx_menu1); S_StartSound(NULL, sfx_menu1);
routine(0); routine(0);
} }
@ -1291,7 +1279,7 @@ boolean M_Responder(event_t *ev)
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{ {
if (activeMenuId != MN_OP_SOUND || itemOn > 3) if (menustack[0] != MN_OP_SOUND || itemOn > 3)
S_StartSound(NULL, sfx_menu1); S_StartSound(NULL, sfx_menu1);
routine(1); routine(1);
} }
@ -1301,7 +1289,7 @@ boolean M_Responder(event_t *ev)
noFurtherInput = true; noFurtherInput = true;
currentMenu->lastOn = itemOn; currentMenu->lastOn = itemOn;
if (activeMenuId == MN_PLAYBACK) if (menustack[0] == MN_PLAYBACK)
{ {
boolean held = (boolean)playback_enterheld; boolean held = (boolean)playback_enterheld;
if (held) if (held)
@ -1323,7 +1311,7 @@ boolean M_Responder(event_t *ev)
break; break;
case IT_SUBMENU: case IT_SUBMENU:
currentMenu->lastOn = itemOn; currentMenu->lastOn = itemOn;
M_SetupNextMenu(currentMenu->menuitems[itemOn].itemaction.submenu); M_EnterMenu(currentMenu->menuitems[itemOn].itemaction.submenu, true);
break; break;
} }
} }
@ -1333,7 +1321,12 @@ boolean M_Responder(event_t *ev)
//case KEY_JOY1 + 2: //case KEY_JOY1 + 2:
noFurtherInput = true; noFurtherInput = true;
currentMenu->lastOn = itemOn; currentMenu->lastOn = itemOn;
if (currentMenu->prevMenu) if (menustack[0] == MN_SP_TIMEATTACK)
{
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
D_StartTitle();
}
else
{ {
//If we entered the game search menu, but didn't enter a game, //If we entered the game search menu, but didn't enter a game,
//make sure the game doesn't still think we're in a netgame. //make sure the game doesn't still think we're in a netgame.
@ -1342,18 +1335,8 @@ boolean M_Responder(event_t *ev)
netgame = false; netgame = false;
multiplayer = false; multiplayer = false;
} }
M_ExitMenu();
if (activeMenuId == MN_SP_TIMEATTACK)
{
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
menuactive = false;
D_StartTitle();
}
else
M_SetupNextMenu(currentMenu->prevMenu);
} }
else
M_ClearMenus(true);
return true; return true;
@ -1377,7 +1360,7 @@ boolean M_Responder(event_t *ev)
|| cv == &cv_newgametype) || cv == &cv_newgametype)
return true; return true;
if (activeMenuId != MN_OP_SOUND || itemOn > 3) if (menustack[0] != MN_OP_SOUND || itemOn > 3)
S_StartSound(NULL, sfx_menu1); S_StartSound(NULL, sfx_menu1);
routine(-1); routine(-1);
return true; return true;
@ -1491,13 +1474,10 @@ boolean M_DemoResponder(event_t *ev)
// //
void M_Drawer(void) void M_Drawer(void)
{ {
if (currentMenu == &MessageDef) if (menustack[0])
menuactive = true;
if (menuactive)
{ {
// now that's more readable with a faded background (yeah like Quake...) // now that's more readable with a faded background (yeah like Quake...)
if (!WipeInAction && activeMenuId != MN_PLAYBACK) // Replay playback has its own background if (!WipeInAction && menustack[0] != MN_PLAYBACK) // Replay playback has its own background
V_DrawFadeScreen(0xFF00, 16); V_DrawFadeScreen(0xFF00, 16);
if (currentMenu->drawroutine) if (currentMenu->drawroutine)
@ -1506,7 +1486,7 @@ void M_Drawer(void)
currentMenu->drawroutine(); // call current menu Draw routine currentMenu->drawroutine(); // call current menu Draw routine
} }
if (activeMenuId == MN_MAIN) if (menustack[0] == MN_MAIN)
{ {
INT32 texty = vid.height - 10*vid.dupy; INT32 texty = vid.height - 10*vid.dupy;
#define addtext(f, str) {\ #define addtext(f, str) {\
@ -1552,27 +1532,25 @@ void M_Drawer(void)
void M_StartControlPanel(void) void M_StartControlPanel(void)
{ {
// intro might call this repeatedly // intro might call this repeatedly
if (menuactive) if (menustack[0])
{ {
CON_ToggleOff(); // move away console CON_ToggleOff(); // move away console
return; return;
} }
menuactive = true;
if (demo.playback) if (demo.playback)
{ {
M_SetCurrentMenu(MN_PLAYBACK); M_EnterMenu(MN_PLAYBACK, true);
playback_last_menu_interaction_leveltime = leveltime; playback_last_menu_interaction_leveltime = leveltime;
} }
else if (!Playing()) else if (!Playing())
{ {
M_SetCurrentMenu(MN_MAIN); M_EnterMenu(MN_MAIN, true);
M_SetItemOn(MN_MAIN, "SINGLE"); M_SetItemOn(MN_MAIN, "SINGLE");
} }
else if (modeattacking) else if (modeattacking)
{ {
M_SetCurrentMenu(MN_MAPAUSE); M_EnterMenu(MN_MAPAUSE, true);
M_SetItemOn(MN_MAPAUSE, "CONTIN"); M_SetItemOn(MN_MAPAUSE, "CONTIN");
} }
else if (!(netgame || multiplayer)) // Single Player else if (!(netgame || multiplayer)) // Single Player
@ -1590,7 +1568,7 @@ void M_StartControlPanel(void)
M_SetItemStatus(MN_SPAUSE, "EMBLEM", M_SecretUnlocked(SECRET_EMBLEMHINTS) ? IT_STRING|IT_CALL : IT_DISABLED); M_SetItemStatus(MN_SPAUSE, "EMBLEM", M_SecretUnlocked(SECRET_EMBLEMHINTS) ? IT_STRING|IT_CALL : IT_DISABLED);
M_SetCurrentMenu(MN_SPAUSE); M_EnterMenu(MN_SPAUSE, true);
M_SetItemOn(MN_SPAUSE, "CONTIN"); M_SetItemOn(MN_SPAUSE, "CONTIN");
} }
else // multiplayer else // multiplayer
@ -1704,7 +1682,7 @@ void M_StartControlPanel(void)
} }
#endif #endif
M_SetCurrentMenu(MN_MPAUSE); M_EnterMenu(MN_MPAUSE, true);
M_SetItemOn(MN_MPAUSE, "CONTIN"); M_SetItemOn(MN_MPAUSE, "CONTIN");
} }
@ -1721,36 +1699,33 @@ void M_EndModeAttackRun(void)
// //
void M_ClearMenus(boolean callexitmenufunc) void M_ClearMenus(boolean callexitmenufunc)
{ {
if (!menuactive) if (currentMenu && currentMenu->quitroutine && callexitmenufunc)
return;
if (currentMenu->quitroutine && callexitmenufunc)
currentMenu->quitroutine(0); currentMenu->quitroutine(0);
#ifndef DC // Save the config file. I'm sick of crashing the game later and losing all my changes! #ifndef DC // Save the config file. I'm sick of crashing the game later and losing all my changes!
COM_BufAddText(va("saveconfig \"%s\" -silent\n", configfile)); if (menustack[0])
COM_BufAddText(va("saveconfig \"%s\" -silent\n", configfile));
#endif //Alam: But not on the Dreamcast's VMUs #endif //Alam: But not on the Dreamcast's VMUs
if (currentMenu == &MessageDef) // Oh sod off! memset(menustack, 0, sizeof(menustack));
M_SetCurrentMenu(MN_MAIN); // Not like it matters currentMenu = NULL;
menuactive = false;
hidetitlemap = false; hidetitlemap = false;
} }
// //
// M_SetupNextMenu // M_SetupNextMenu
// //
void M_SetupNextMenu(menutype_t menunum) static void M_SetupNextMenu(menutype_t menunum, boolean callexit)
{ {
INT16 i; INT16 i;
menu_t *menudef = menudefs[menunum]; menu_t *menudef = menudefs[menunum];
I_Assert(menudef);
// If you're going from a menu to itself, why are you running the quitroutine? You're not quitting it! -SH // If you're going from a menu to itself, why are you running the quitroutine? You're not quitting it! -SH
if (currentMenu != menudef && currentMenu->quitroutine) if (callexit && currentMenu && currentMenu != menudef && currentMenu->quitroutine)
currentMenu->quitroutine(0); currentMenu->quitroutine(0);
currentMenu = menudef; currentMenu = menudef;
activeMenuId = menunum;
itemOn = currentMenu->lastOn; itemOn = currentMenu->lastOn;
// in case of... // in case of...
@ -1774,6 +1749,34 @@ void M_SetupNextMenu(menutype_t menunum)
hidetitlemap = false; hidetitlemap = false;
} }
// pop the active menu from the stack
void M_ExitMenu(void)
{
size_t i;
for (i = 0; i < NUMMENULEVELS-1; i++)
menustack[i] = menustack[i+1];
menustack[NUMMENULEVELS-1] = MN_NONE;
if (menustack[0])
M_SetupNextMenu(menustack[0], true);
else
M_ClearMenus(true);
}
// push a new menu to the stack
void M_EnterMenu(menutype_t menunum, boolean callexit)
{
size_t i = NUMMENULEVELS-1;
if (menustack[i])
CONS_Alert(CONS_WARNING, "Max menu depth (%d) exceeded!\n", NUMMENULEVELS);
do menustack[i] = menustack[i-1]; while (--i); // one-line do-while loop... that's something :^)
menustack[0] = menunum;
M_SetupNextMenu(menunum, callexit);
}
// Guess I'll put this here, idk // Guess I'll put this here, idk
boolean M_MouseNeeded(void) boolean M_MouseNeeded(void)
{ {
@ -1796,7 +1799,7 @@ void M_Ticker(void)
followertimer++; followertimer++;
if (activeMenuId == MN_PLAYBACK) if (menustack[0] == MN_PLAYBACK)
{ {
if (playback_enterheld > 0) if (playback_enterheld > 0)
playback_enterheld--; playback_enterheld--;
@ -2276,7 +2279,7 @@ void M_DrawPauseMenu(void)
{ {
#ifdef HAVE_DISCORDRPC #ifdef HAVE_DISCORDRPC
// kind of hackily baked in here // kind of hackily baked in here
if (activeMenuId == MN_MPAUSE && discordRequestList != NULL) if (menustack[0] == MN_MPAUSE && discordRequestList != NULL)
{ {
const tic_t freq = TICRATE/2; const tic_t freq = TICRATE/2;
@ -2648,10 +2651,8 @@ static menuitem_t MessageMenu[] = {0};
menu_t MessageDef = menu_t MessageDef =
{ {
MN_NONE, // id
NULL, // title NULL, // title
1, // # of menu items 1, // # of menu items
MN_NONE, // previous menu (TO HACK)
MessageMenu, // menuitem_t -> MessageMenu, // menuitem_t ->
M_DrawMessageMenu, // drawing routine -> M_DrawMessageMenu, // drawing routine ->
0, 0, // x, y (TO HACK) 0, 0, // x, y (TO HACK)
@ -2704,11 +2705,6 @@ void M_StartMessage(const char *string, void *routine,
M_StartControlPanel(); // can't put menuactive to true M_StartControlPanel(); // can't put menuactive to true
if (currentMenu == &MessageDef) // Prevent recursion
MessageDef.prevMenu = demo.playback ? MN_PLAYBACK : MN_MAIN;
else
MessageDef.prevMenu = activeMenuId;
MessageDef.menuitems[0].text = message; MessageDef.menuitems[0].text = message;
MessageDef.menuitems[0].alphaKey = (UINT8)itemtype; MessageDef.menuitems[0].alphaKey = (UINT8)itemtype;
if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING; if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING;
@ -2753,9 +2749,7 @@ void M_StartMessage(const char *string, void *routine,
MessageDef.lastOn = (INT16)((strlines<<8)+max); MessageDef.lastOn = (INT16)((strlines<<8)+max);
//M_SetupNextMenu();
currentMenu = &MessageDef; currentMenu = &MessageDef;
activeMenuId = MN_NONE;
itemOn = 0; itemOn = 0;
} }
@ -2828,8 +2822,10 @@ static void M_DrawMessageMenu(void)
static void M_StopMessage(INT32 choice) static void M_StopMessage(INT32 choice)
{ {
(void)choice; (void)choice;
if (menuactive) if (menustack[0])
M_SetupNextMenu(MessageDef.prevMenu); M_SetupNextMenu(menustack[0], true);
else
M_ClearMenus(true);
} }
// ========= // =========
@ -2895,12 +2891,7 @@ void M_HandleImageDef(INT32 choice)
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
// ====================== // ======================
@ -2912,7 +2903,7 @@ void M_AddonsOptions(INT32 choice)
(void)choice; (void)choice;
Addons_option_Onchange(); Addons_option_Onchange();
M_SetupNextMenu(MN_OP_ADDONS); M_EnterMenu(MN_OP_ADDONS, true);
} }
#define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make addons!" #define LOCATIONSTRING1 "Visit \x83SRB2.ORG/MODS\x80 to get & make addons!"
@ -2980,8 +2971,7 @@ void M_Addons(INT32 choice)
addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC); addonsp[NUM_EXT+3] = W_CachePatchName("M_FSRCH", PU_STATIC);
addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_STATIC); addonsp[NUM_EXT+4] = W_CachePatchName("M_FSAVE", PU_STATIC);
menudefs[MN_AD_MAIN]->prevMenu = activeMenuId; M_EnterMenu(MN_AD_MAIN, true);
M_SetupNextMenu(MN_AD_MAIN);
} }
#define width 4 #define width 4
@ -3051,7 +3041,7 @@ static char *M_AddonsHeaderPath(void)
} }
#define UNEXIST S_StartSound(NULL, sfx_s26d);\ #define UNEXIST S_StartSound(NULL, sfx_s26d);\
M_SetupNextMenu(menudefs[MN_AD_MAIN]->prevMenu);\ M_ExitMenu();\
M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING) M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING)
#define CLEARNAME Z_Free(refreshdirname);\ #define CLEARNAME Z_Free(refreshdirname);\
@ -3448,10 +3438,7 @@ void M_HandleAddons(INT32 choice)
// Secret menu! // Secret menu!
//MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); //MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
if (currentMenu->prevMenu) M_ExitMenu();
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
} }
} }
@ -3514,8 +3501,8 @@ void M_ReplayHut(INT32 choice)
PrepReplayList(); PrepReplayList();
menuactive = true; M_ClearMenus(true);
M_SetupNextMenu(MN_MISC_REPLAYHUT); M_EnterMenu(MN_MISC_REPLAYHUT, true);
G_SetGamestate(GS_TIMEATTACK); G_SetGamestate(GS_TIMEATTACK);
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
@ -3602,9 +3589,8 @@ void M_HandleReplayHutList(INT32 choice)
PrepReplayList(); PrepReplayList();
break; break;
default: default:
// We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen!
currentMenu->lastOn = itemOn; currentMenu->lastOn = itemOn;
M_SetCurrentMenu(MN_MISC_REPLAYSTART); M_EnterMenu(MN_MISC_REPLAYSTART, false); // ReplayDef's quit routine would boot us back to the title screen
replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1; replayScrollTitle = 0; replayScrollDelay = TICRATE; replayScrollDir = 1;
@ -4025,7 +4011,6 @@ void M_QuitReplayHut(INT32 choice)
(void)choice; (void)choice;
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
menuactive = false;
D_StartTitle(); D_StartTitle();
if (demolist) if (demolist)
@ -4335,7 +4320,7 @@ void M_PandorasBox(INT32 choice)
(void)choice; (void)choice;
CV_StealthSetValue(&cv_dummyrings, players[consoleplayer].rings); CV_StealthSetValue(&cv_dummyrings, players[consoleplayer].rings);
CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives); CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives);
M_SetupNextMenu(MN_SR_PANDORA); M_EnterMenu(MN_SR_PANDORA, true);
} }
void M_ExitPandorasBox(INT32 choice) void M_ExitPandorasBox(INT32 choice)
@ -4464,16 +4449,13 @@ void M_Options(INT32 choice)
M_SetItemStatus(MN_OP_GAME, "ENCORE", M_SecretUnlocked(SECRET_ENCORE) ? IT_CVAR|IT_STRING : IT_SECRET); M_SetItemStatus(MN_OP_GAME, "ENCORE", M_SecretUnlocked(SECRET_ENCORE) ? IT_CVAR|IT_STRING : IT_SECRET);
menudefs[MN_OP_MAIN]->prevMenu = activeMenuId; M_EnterMenu(MN_OP_MAIN, true);
M_SetupNextMenu(MN_OP_MAIN);
} }
void M_Manual(INT32 choice) void M_Manual(INT32 choice)
{ {
(void)choice; (void)choice;
M_EnterMenu(MN_HELP, true);
menudefs[MN_HELP]->prevMenu = choice == INT32_MAX ? MN_NONE : activeMenuId;
M_SetupNextMenu(MN_HELP);
} }
static void M_RetryResponse(INT32 ch) static void M_RetryResponse(INT32 ch)
@ -4669,7 +4651,7 @@ void M_EmblemHints(INT32 choice)
{ {
(void)choice; (void)choice;
M_SetItemStatus(MN_SR_EMBLEMHINT, "RADAR", M_SecretUnlocked(SECRET_ITEMFINDER) ? IT_CVAR|IT_STRING : IT_SECRET); M_SetItemStatus(MN_SR_EMBLEMHINT, "RADAR", M_SecretUnlocked(SECRET_ITEMFINDER) ? IT_CVAR|IT_STRING : IT_SECRET);
M_SetupNextMenu(MN_SR_EMBLEMHINT); M_EnterMenu(MN_SR_EMBLEMHINT, true);
M_SetItemOn(MN_SR_EMBLEMHINT, "BACK"); // always start on back. M_SetItemOn(MN_SR_EMBLEMHINT, "BACK"); // always start on back.
} }
@ -4728,7 +4710,7 @@ void M_DrawSkyRoom(void)
M_DrawGenericMenu(); M_DrawGenericMenu();
if (activeMenuId == MN_OP_SOUND) if (menustack[0] == MN_OP_SOUND)
{ {
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x,
currentMenu->y+M_GetItemY(MN_OP_SOUND, "SNDENA"), currentMenu->y+M_GetItemY(MN_OP_SOUND, "SNDENA"),
@ -4810,12 +4792,7 @@ void M_HandleSoundTest(INT32 choice)
break; break;
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
static musicdef_t *curplaying = NULL; static musicdef_t *curplaying = NULL;
@ -4842,7 +4819,7 @@ void M_MusicTest(INT32 choice)
st_sel = 0; st_sel = 0;
M_SetupNextMenu(MN_SR_SOUNDTEST); M_EnterMenu(MN_SR_SOUNDTEST, true);
} }
void M_DrawMusicTest(void) void M_DrawMusicTest(void)
@ -5142,10 +5119,7 @@ void M_HandleMusicTest(INT32 choice)
Z_Free(soundtestdefs); Z_Free(soundtestdefs);
soundtestdefs = NULL; soundtestdefs = NULL;
if (currentMenu->prevMenu) M_ExitMenu();
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
} }
} }
@ -5179,7 +5153,7 @@ void M_SinglePlayerMenu(INT32 choice)
M_SetItemStatus(MN_SP_MAIN, "GP", IT_CALL|IT_STRING); M_SetItemStatus(MN_SP_MAIN, "GP", IT_CALL|IT_STRING);
M_SetItemStatus(MN_SP_MAIN, "TA", M_SecretUnlocked(SECRET_TIMEATTACK) ? IT_CALL|IT_STRING : IT_SECRET); M_SetItemStatus(MN_SP_MAIN, "TA", M_SecretUnlocked(SECRET_TIMEATTACK) ? IT_CALL|IT_STRING : IT_SECRET);
M_SetItemStatus(MN_SP_MAIN, "IT", M_SecretUnlocked(SECRET_ITEMBREAKER) ? IT_CALL|IT_STRING : IT_SECRET); M_SetItemStatus(MN_SP_MAIN, "IT", M_SecretUnlocked(SECRET_ITEMBREAKER) ? IT_CALL|IT_STRING : IT_SECRET);
M_SetupNextMenu(MN_SP_MAIN); M_EnterMenu(MN_SP_MAIN, true);
} }
// =============== // ===============
@ -5243,7 +5217,7 @@ void M_Statistics(INT32 choice)
if (statsMax < 0) if (statsMax < 0)
statsMax = 0; statsMax = 0;
M_SetupNextMenu(MN_SP_LEVELSTATS); M_EnterMenu(MN_SP_LEVELSTATS, true);
} }
static void M_DrawStatsMaps(void) static void M_DrawStatsMaps(void)
@ -5504,12 +5478,7 @@ void M_HandleLevelStats(INT32 choice)
break; break;
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
void M_GrandPrixTemp(INT32 choice) void M_GrandPrixTemp(INT32 choice)
@ -5521,7 +5490,7 @@ void M_GrandPrixTemp(INT32 choice)
return; return;
} }
M_PatchSkinNameTable(); M_PatchSkinNameTable();
M_SetupNextMenu(MN_SP_GRANDPRIX); M_EnterMenu(MN_SP_GRANDPRIX, true);
} }
// Start Grand Prix! // Start Grand Prix!
@ -5606,7 +5575,7 @@ void M_DrawTimeAttackMenu(void)
V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
M_DrawMenuTitle(); M_DrawMenuTitle();
if (activeMenuId == MN_SP_TIMEATTACK) if (menustack[0] == MN_SP_TIMEATTACK)
M_DrawLevelSelectOnly(true, false); M_DrawLevelSelectOnly(true, false);
// draw menu (everything else goes on top of it) // draw menu (everything else goes on top of it)
@ -5649,7 +5618,7 @@ void M_DrawTimeAttackMenu(void)
INT32 soffset = 40, strw = V_StringWidth(str, 0); INT32 soffset = 40, strw = V_StringWidth(str, 0);
// hack to keep the menu from overlapping the level icon // hack to keep the menu from overlapping the level icon
if (activeMenuId != MN_SP_TIMEATTACK || cv == &cv_nextmap) if (menustack[0] != MN_SP_TIMEATTACK || cv == &cv_nextmap)
soffset = 0; soffset = 0;
// Should see nothing but strings // Should see nothing but strings
@ -5711,7 +5680,7 @@ void M_DrawTimeAttackMenu(void)
// ALWAYS DRAW player name, level name, skin and color even when not on this menu! // ALWAYS DRAW player name, level name, skin and color even when not on this menu!
// TODO: this whole thing needs to go // TODO: this whole thing needs to go
menu_t *tamenu = menudefs[MN_SP_TIMEATTACK]; menu_t *tamenu = menudefs[MN_SP_TIMEATTACK];
if (activeMenuId != MN_SP_TIMEATTACK) if (menustack[0] != MN_SP_TIMEATTACK)
{ {
consvar_t *ncv; consvar_t *ncv;
INT16 first = M_MenuItemRange(MN_SP_TIMEATTACK, "NAME", "LEVEL", 4); INT16 first = M_MenuItemRange(MN_SP_TIMEATTACK, "NAME", "LEVEL", 4);
@ -5761,7 +5730,8 @@ void M_TimeAttack(INT32 choice)
M_PatchSkinNameTable(); M_PatchSkinNameTable();
M_PrepareLevelSelect(); M_PrepareLevelSelect();
M_SetupNextMenu(MN_SP_TIMEATTACK); M_ClearMenus(true);
M_EnterMenu(MN_SP_TIMEATTACK, true);
G_SetGamestate(GS_TIMEATTACK); G_SetGamestate(GS_TIMEATTACK);
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
@ -5794,7 +5764,8 @@ void M_ItemBreaker(INT32 choice)
M_PatchSkinNameTable(); M_PatchSkinNameTable();
M_PrepareLevelSelect(); M_PrepareLevelSelect();
M_SetupNextMenu(MN_SP_TIMEATTACK); M_ClearMenus(true);
M_EnterMenu(MN_SP_TIMEATTACK, true);
G_SetGamestate(GS_TIMEATTACK); G_SetGamestate(GS_TIMEATTACK);
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
@ -5883,12 +5854,7 @@ void M_HandleStaffReplay(INT32 choice)
break; break;
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
// Player has selected the "REPLAY" from the time attack screen // Player has selected the "REPLAY" from the time attack screen
@ -5900,27 +5866,24 @@ void M_ReplayTimeAttack(INT32 choice)
modeattacking = (levellistmode == LLM_ITEMBREAKER ? ATTACKING_ITEMBREAK : ATTACKING_TIME); // set modeattacking before G_DoPlayDemo so the map loader knows modeattacking = (levellistmode == LLM_ITEMBREAKER ? ATTACKING_ITEMBREAK : ATTACKING_TIME); // set modeattacking before G_DoPlayDemo so the map loader knows
demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed
if (activeMenuId == MN_SP_REPLAY) switch(choice) {
{ default:
switch(choice) { case 0: // best time
default: which = "time-best";
case 0: // best time break;
which = "time-best"; case 1: // best lap
break; which = "lap-best";
case 1: // best lap break;
which = "lap-best"; case 2: // last
break; which = "last";
case 2: // last break;
which = "last"; case 3: // guest
break; // srb2/replay/main/map01-guest.lmp
case 3: // guest G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), gamemode));
// srb2/replay/main/map01-guest.lmp return;
G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), gamemode));
return;
}
// srb2/replay/main/map01-sonic-time-best.lmp
G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, gamemode, which));
} }
// srb2/replay/main/map01-sonic-time-best.lmp
G_DoPlayDemo(va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), cv_chooseskin.string, gamemode, which));
} }
static void M_EraseGuest(INT32 choice) static void M_EraseGuest(INT32 choice)
@ -5930,7 +5893,7 @@ static void M_EraseGuest(INT32 choice)
(void)choice; (void)choice;
if (FIL_FileExists(rguest)) if (FIL_FileExists(rguest))
remove(rguest); remove(rguest);
M_SetupNextMenu(MN_SP_TIMEATTACK); M_ExitMenu();
CV_AddValue(&cv_nextmap, -1); CV_AddValue(&cv_nextmap, -1);
CV_AddValue(&cv_nextmap, 1); CV_AddValue(&cv_nextmap, 1);
M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING); M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING);
@ -5952,7 +5915,7 @@ static void M_OverwriteGuest(const char *which)
} }
FIL_WriteFile(rguest, buf, len); FIL_WriteFile(rguest, buf, len);
Z_Free(rguest); Z_Free(rguest);
M_SetupNextMenu(MN_SP_TIMEATTACK); M_ExitMenu();
CV_AddValue(&cv_nextmap, -1); CV_AddValue(&cv_nextmap, -1);
CV_AddValue(&cv_nextmap, 1); CV_AddValue(&cv_nextmap, 1);
M_StartMessage(M_GetText("Guest replay data saved.\n"),NULL,MM_NOTHING); M_StartMessage(M_GetText("Guest replay data saved.\n"),NULL,MM_NOTHING);
@ -6020,9 +5983,11 @@ void M_ModeAttackEndGame(INT32 choice)
M_StartControlPanel(); M_StartControlPanel();
if (modeattacking) if (modeattacking)
M_SetCurrentMenu(MN_SP_TIMEATTACK); {
M_ClearMenus(true);
M_EnterMenu(MN_SP_TIMEATTACK, true);
}
itemOn = currentMenu->lastOn;
G_SetGamestate(GS_TIMEATTACK); G_SetGamestate(GS_TIMEATTACK);
modeattacking = ATTACKING_NONE; modeattacking = ATTACKING_NONE;
S_ChangeMusicInternal("racent", true); S_ChangeMusicInternal("racent", true);
@ -6212,12 +6177,7 @@ void M_HandleServerPage(INT32 choice)
break; break;
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
void M_Connect(INT32 choice) void M_Connect(INT32 choice)
@ -6473,7 +6433,7 @@ static void M_ConnectMenu(INT32 choice)
// first page of servers // first page of servers
serverlistpage = 0; serverlistpage = 0;
M_SetupNextMenu(MN_MP_CONNECT); M_EnterMenu(MN_MP_CONNECT, true);
itemOn = 0; itemOn = 0;
#if defined (MASTERSERVER) && defined (HAVE_THREADS) #if defined (MASTERSERVER) && defined (HAVE_THREADS)
@ -6555,7 +6515,7 @@ void M_StartServer(INT32 choice)
(void)choice; (void)choice;
if (activeMenuId == MN_MP_OFFLINESERVER) if (menustack[0] == MN_MP_OFFLINESERVER)
netgame = false; netgame = false;
else else
netgame = true; netgame = true;
@ -6584,7 +6544,7 @@ void M_StartServer(INT32 choice)
SplitScreen_OnChange(); SplitScreen_OnChange();
} }
if (activeMenuId == MN_MP_OFFLINESERVER) // offline server if (menustack[0] == MN_MP_OFFLINESERVER) // offline server
{ {
paused = false; paused = false;
SV_StartSinglePlayerServer(); SV_StartSinglePlayerServer();
@ -6713,7 +6673,7 @@ void M_MapChange(INT32 choice)
CV_SetValue(&cv_nextmap, gamemap); CV_SetValue(&cv_nextmap, gamemap);
M_PrepareLevelSelect(); M_PrepareLevelSelect();
M_SetupNextMenu(MN_CHANGELEVEL); M_EnterMenu(MN_CHANGELEVEL, true);
} }
void M_StartOfflineServerMenu(INT32 choice) void M_StartOfflineServerMenu(INT32 choice)
@ -6721,7 +6681,7 @@ void M_StartOfflineServerMenu(INT32 choice)
(void)choice; (void)choice;
levellistmode = LLM_CREATESERVER; levellistmode = LLM_CREATESERVER;
M_PrepareLevelSelect(); M_PrepareLevelSelect();
M_SetupNextMenu(MN_MP_OFFLINESERVER); M_EnterMenu(MN_MP_OFFLINESERVER, true);
} }
void M_StartServerMenu(INT32 choice) void M_StartServerMenu(INT32 choice)
@ -6729,8 +6689,7 @@ void M_StartServerMenu(INT32 choice)
(void)choice; (void)choice;
levellistmode = LLM_CREATESERVER; levellistmode = LLM_CREATESERVER;
M_PrepareLevelSelect(); M_PrepareLevelSelect();
M_SetupNextMenu(MN_MP_SERVER); M_EnterMenu(MN_MP_SERVER, true);
} }
// ============== // ==============
@ -6887,12 +6846,7 @@ void M_SetupMultiHandler(INT32 choice)
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu (currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
// Tails 11-19-2002 // Tails 11-19-2002
@ -6987,12 +6941,7 @@ void M_HandleConnectIP(INT32 choice)
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu (currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
// ======================== // ========================
@ -7515,12 +7464,7 @@ void M_HandleSetupMultiPlayer(INT32 choice)
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu (currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
// start the multiplayer setup menu // start the multiplayer setup menu
@ -7564,8 +7508,7 @@ void M_SetupMultiPlayer(INT32 choice)
else else
M_SetItemStatus(MN_MP_PLAYERSETUP, "FOLLOW", IT_KEYHANDLER|IT_STRING); M_SetItemStatus(MN_MP_PLAYERSETUP, "FOLLOW", IT_KEYHANDLER|IT_STRING);
menudefs[MN_MP_PLAYERSETUP]->prevMenu = activeMenuId; M_EnterMenu(MN_MP_PLAYERSETUP, true);
M_SetupNextMenu(MN_MP_PLAYERSETUP);
} }
// start the multiplayer setup menu, for secondary player (splitscreen mode) // start the multiplayer setup menu, for secondary player (splitscreen mode)
@ -7608,8 +7551,7 @@ void M_SetupMultiPlayer2(INT32 choice)
else else
M_SetItemStatus(MN_MP_PLAYERSETUP, "FOLLOW", IT_KEYHANDLER | IT_STRING); M_SetItemStatus(MN_MP_PLAYERSETUP, "FOLLOW", IT_KEYHANDLER | IT_STRING);
menudefs[MN_MP_PLAYERSETUP]->prevMenu = activeMenuId; M_EnterMenu(MN_MP_PLAYERSETUP, true);
M_SetupNextMenu(MN_MP_PLAYERSETUP);
} }
// start the multiplayer setup menu, for third player (splitscreen mode) // start the multiplayer setup menu, for third player (splitscreen mode)
@ -7652,8 +7594,7 @@ void M_SetupMultiPlayer3(INT32 choice)
else else
M_SetItemStatus(MN_MP_PLAYERSETUP, "FOLLOW", IT_KEYHANDLER | IT_STRING); M_SetItemStatus(MN_MP_PLAYERSETUP, "FOLLOW", IT_KEYHANDLER | IT_STRING);
menudefs[MN_MP_PLAYERSETUP]->prevMenu = activeMenuId; M_EnterMenu(MN_MP_PLAYERSETUP, true);
M_SetupNextMenu(MN_MP_PLAYERSETUP);
} }
// start the multiplayer setup menu, for third player (splitscreen mode) // start the multiplayer setup menu, for third player (splitscreen mode)
@ -7696,8 +7637,7 @@ void M_SetupMultiPlayer4(INT32 choice)
else else
M_SetItemStatus(MN_MP_PLAYERSETUP, "FOLLOW", IT_KEYHANDLER | IT_STRING); M_SetItemStatus(MN_MP_PLAYERSETUP, "FOLLOW", IT_KEYHANDLER | IT_STRING);
menudefs[MN_MP_PLAYERSETUP]->prevMenu = activeMenuId; M_EnterMenu(MN_MP_PLAYERSETUP, true);
M_SetupNextMenu(MN_MP_PLAYERSETUP);
} }
void M_QuitMultiPlayerMenu(INT32 choice) void M_QuitMultiPlayerMenu(INT32 choice)
@ -7946,7 +7886,7 @@ void M_ScreenshotOptions(INT32 choice)
Screenshot_option_Onchange(); Screenshot_option_Onchange();
Moviemode_mode_Onchange(); Moviemode_mode_Onchange();
M_SetupNextMenu(MN_OP_SCREENSHOTS); M_EnterMenu(MN_OP_SCREENSHOTS, true);
} }
// ============= // =============
@ -8014,7 +7954,7 @@ void M_SetupJoystickMenu(INT32 choice)
#endif #endif
} }
M_SetupNextMenu(MN_OP_JOYSTICKSET); M_EnterMenu(MN_OP_JOYSTICKSET, true);
} }
void M_Setup1PJoystickMenu(INT32 choice) void M_Setup1PJoystickMenu(INT32 choice)
@ -8115,7 +8055,7 @@ void M_Setup1PControlsMenu(INT32 choice)
M_SetItemStatus(MN_OP_CHANGECONTROLS, "CENTER", IT_CONTROL); // Center View M_SetItemStatus(MN_OP_CHANGECONTROLS, "CENTER", IT_CONTROL); // Center View
*/ */
M_SetupNextMenu(MN_OP_CHANGECONTROLS); M_EnterMenu(MN_OP_CHANGECONTROLS, true);
} }
void M_Setup2PControlsMenu(INT32 choice) void M_Setup2PControlsMenu(INT32 choice)
@ -8148,7 +8088,7 @@ void M_Setup2PControlsMenu(INT32 choice)
M_SetItemStatus(MN_OP_CHANGECONTROLS, "CENTER", IT_GRAYEDOUT2); // Center View M_SetItemStatus(MN_OP_CHANGECONTROLS, "CENTER", IT_GRAYEDOUT2); // Center View
*/ */
M_SetupNextMenu(MN_OP_CHANGECONTROLS); M_EnterMenu(MN_OP_CHANGECONTROLS, true);
} }
void M_Setup3PControlsMenu(INT32 choice) void M_Setup3PControlsMenu(INT32 choice)
@ -8181,7 +8121,7 @@ void M_Setup3PControlsMenu(INT32 choice)
M_SetItemStatus(MN_OP_CHANGECONTROLS, "CENTER", IT_GRAYEDOUT2); // Center View M_SetItemStatus(MN_OP_CHANGECONTROLS, "CENTER", IT_GRAYEDOUT2); // Center View
*/ */
M_SetupNextMenu(MN_OP_CHANGECONTROLS); M_EnterMenu(MN_OP_CHANGECONTROLS, true);
} }
void M_Setup4PControlsMenu(INT32 choice) void M_Setup4PControlsMenu(INT32 choice)
@ -8214,7 +8154,7 @@ void M_Setup4PControlsMenu(INT32 choice)
M_SetItemStatus(MN_OP_CHANGECONTROLS, "CENTER", IT_GRAYEDOUT2); // Center View M_SetItemStatus(MN_OP_CHANGECONTROLS, "CENTER", IT_GRAYEDOUT2); // Center View
*/ */
M_SetupNextMenu(MN_OP_CHANGECONTROLS); M_EnterMenu(MN_OP_CHANGECONTROLS, true);
} }
#define controlheight 18 #define controlheight 18
@ -8419,7 +8359,6 @@ static void M_ChangecontrolResponse(event_t *ev)
{ {
// This buffer assumes a 125-character message plus a 32-character control name (per controltochangetext buffer size) // This buffer assumes a 125-character message plus a 32-character control name (per controltochangetext buffer size)
static char tmp[158]; static char tmp[158];
menutype_t prev = currentMenu->prevMenu;
if (controltochange == gc_pause) if (controltochange == gc_pause)
sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nyou may select another key. \n\nHit another key for\n%s\nESC for Cancel"), sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nyou may select another key. \n\nHit another key for\n%s\nESC for Cancel"),
@ -8429,7 +8368,6 @@ static void M_ChangecontrolResponse(event_t *ev)
controltochangetext); controltochangetext);
M_StartMessage(tmp, FUNCPTRCAST(M_ChangecontrolResponse), MM_EVENTHANDLER); M_StartMessage(tmp, FUNCPTRCAST(M_ChangecontrolResponse), MM_EVENTHANDLER);
currentMenu->prevMenu = prev;
S_StartSound(NULL, sfx_s3k42); S_StartSound(NULL, sfx_s3k42);
return; return;
@ -8563,7 +8501,7 @@ void M_VideoModeMenu(INT32 choice)
vidm_column_size = (vidm_nummodes+2) / 3; vidm_column_size = (vidm_nummodes+2) / 3;
M_SetupNextMenu(MN_OP_VIDEOMODE); M_EnterMenu(MN_OP_VIDEOMODE, true);
} }
void M_DrawVideoMenu(void) void M_DrawVideoMenu(void)
@ -8747,10 +8685,7 @@ void M_HandleVideoMode(INT32 ch)
break; break;
case KEY_ESCAPE: // this one same as M_Responder case KEY_ESCAPE: // this one same as M_Responder
if (currentMenu->prevMenu) M_ExitMenu();
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
break; break;
default: default:
@ -9025,12 +8960,7 @@ void M_HandleMonitorToggles(INT32 choice)
} }
if (exitmenu) if (exitmenu)
{ M_ExitMenu();
if (currentMenu->prevMenu)
M_SetupNextMenu(currentMenu->prevMenu);
else
M_ClearMenus(true);
}
} }
// ========= // =========
@ -9247,14 +9177,9 @@ void M_DrawDiscordRequests(void)
// No other requests // No other requests
M_SetItemStatus(MN_MPAUSE, "DISCRQ", IT_GRAYEDOUT); M_SetItemStatus(MN_MPAUSE, "DISCRQ", IT_GRAYEDOUT);
if (currentMenu->prevMenu) M_ExitMenu();
{ if (menustack[0] == MN_MPAUSE)
M_SetupNextMenu(currentMenu->prevMenu); M_SetItemOn(MN_MPAUSE, "CONTIN");
if (activeMenuId == MN_MPAUSE)
M_SetItemOn(MN_MPAUSE, "CONTIN");
}
else
M_ClearMenus(true);
return; return;
} }

View file

@ -34,10 +34,8 @@ extern "C" {
// MENUS // MENUS
// //
// If menu hierarchies go deeper, change this up to 5. // max size of menu stack
// Zero-based, inclusive. #define NUMMENULEVELS 8
#define NUMMENULEVELS 3
#define MENUBITS 6
// Menu IDs sectioned by numeric places to signify hierarchy // Menu IDs sectioned by numeric places to signify hierarchy
/** /**
@ -170,11 +168,9 @@ typedef enum
NUMMENUTYPES, NUMMENUTYPES,
} menutype_t; // up to 63 } menutype_t; // up to 63
#define NUMMENUFREESLOTS (NUMMENUTYPES - MN_FIRSTFREESLOT) #define NUMMENUFREESLOTS (NUMMENUTYPES - MN_FIRSTFREESLOT)
#define MTREE2(a,b) (a | (b<<MENUBITS))
#define MTREE3(a,b,c) MTREE2(a, MTREE2(b,c))
#define MTREE4(a,b,c,d) MTREE2(a, MTREE3(b,c,d))
extern menu_t *menudefs[NUMMENUTYPES]; extern menu_t *menudefs[NUMMENUTYPES];
extern menutype_t menustack[NUMMENULEVELS];
typedef struct typedef struct
{ {
@ -209,8 +205,6 @@ typedef struct
} menupres_t; } menupres_t;
extern menupres_t menupres[NUMMENUTYPES]; extern menupres_t menupres[NUMMENUTYPES];
extern UINT32 prevMenuId;
extern UINT32 activeMenuId;
void M_InitMenuPresTables(void); void M_InitMenuPresTables(void);
//UINT8 M_GetYoungestChildMenu(void); //UINT8 M_GetYoungestChildMenu(void);
@ -376,10 +370,8 @@ struct menuitem_t
struct menu_t struct menu_t
{ {
UINT32 menuid; // ID to encode menu type and hierarchy
const char *headerpic; const char *headerpic;
INT16 numitems; // # of menu items INT16 numitems; // # of menu items
menutype_t prevMenu; // previous menu
menuitem_t *menuitems; // menu items menuitem_t *menuitems; // menu items
void (*drawroutine)(void); // draw routine void (*drawroutine)(void); // draw routine
INT16 x, y; // x, y of menu INT16 x, y; // x, y of menu
@ -387,8 +379,8 @@ struct menu_t
void (*quitroutine)(INT32 choice); // called before quit a menu void (*quitroutine)(INT32 choice); // called before quit a menu
}; };
void M_SetupNextMenu(menutype_t menu); void M_EnterMenu(menutype_t menu, boolean callexit);
void M_SetCurrentMenu(menutype_t menu); void M_ExitMenu(void);
void M_ClearMenus(boolean callexitmenufunc); void M_ClearMenus(boolean callexitmenufunc);
menuitem_t *M_CheckMenuItem(menutype_t type, const char *name); menuitem_t *M_CheckMenuItem(menutype_t type, const char *name);
menuitem_t *M_GetMenuItem(menutype_t type, const char *name); menuitem_t *M_GetMenuItem(menutype_t type, const char *name);

View file

@ -1611,7 +1611,7 @@ boolean M_ScreenshotResponder(event_t *ev)
ch = ev->data1; ch = ev->data1;
if (ch >= NUMKEYS && menuactive) // If it's not a keyboard key, then don't allow it in the menus! if (ch >= NUMKEYS && menustack[0]) // If it's not a keyboard key, then don't allow it in the menus!
return false; return false;
if (G_ControlBoundToKey(0, gc_screenshot, ch, true)) if (G_ControlBoundToKey(0, gc_screenshot, ch, true))

View file

@ -49,6 +49,7 @@
#include "m_cheat.h" #include "m_cheat.h"
// Thok camera snap (ctrl-f "chalupa") // Thok camera snap (ctrl-f "chalupa")
#include "g_input.h" #include "g_input.h"
#include "m_menu.h" // menustack
// SRB2kart // SRB2kart
#include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems #include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems
@ -191,7 +192,7 @@ boolean P_AutoPause(void)
if (netgame || modeattacking || gamestate == GS_TITLESCREEN) if (netgame || modeattacking || gamestate == GS_TITLESCREEN)
return false; return false;
return ((menuactive && !demo.playback) || ( window_notinfocus && cv_pauseifunfocused.value )); return ((menustack[0] && !demo.playback) || ( window_notinfocus && cv_pauseifunfocused.value ));
} }
// //

View file

@ -478,13 +478,13 @@ void SCR_ChangeRenderer(void)
if (M_CheckParm("-nogl")) if (M_CheckParm("-nogl"))
{ {
CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n"); CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n");
if (menuactive) if (menustack[0])
M_StartMessage(M_GetText("OpenGL rendering was disabled!\n\n(Press a key)\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("OpenGL rendering was disabled!\n\n(Press a key)\n"), NULL, MM_NOTHING);
} }
else else
{ {
CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); CONS_Alert(CONS_ERROR, "OpenGL never loaded\n");
if (menuactive) if (menustack[0])
M_StartMessage(M_GetText("OpenGL never loaded\n\n(Press a key)\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("OpenGL never loaded\n\n(Press a key)\n"), NULL, MM_NOTHING);
} }
CV_SetValue(&cv_renderer, render_soft); CV_SetValue(&cv_renderer, render_soft);

View file

@ -121,7 +121,7 @@ static SDL_bool disable_fullscreen = SDL_FALSE;
#define USE_FULLSCREEN (disable_fullscreen||!allow_fullscreen)?0:cv_fullscreen.value #define USE_FULLSCREEN (disable_fullscreen||!allow_fullscreen)?0:cv_fullscreen.value
static SDL_bool disable_mouse = SDL_FALSE; static SDL_bool disable_mouse = SDL_FALSE;
#define USE_MOUSEINPUT (!disable_mouse && cv_usemouse.value && havefocus) #define USE_MOUSEINPUT (!disable_mouse && cv_usemouse.value && havefocus)
#define MOUSE_MENU false //(!disable_mouse && cv_usemouse.value && menuactive && !USE_FULLSCREEN) #define MOUSE_MENU false //(!disable_mouse && cv_usemouse.value && menustack[0] && !USE_FULLSCREEN)
#define MOUSEBUTTONS_MAX MOUSEBUTTONS #define MOUSEBUTTONS_MAX MOUSEBUTTONS
// first entry in the modelist which is not bigger than MAXVIDWIDTHxMAXVIDHEIGHT // first entry in the modelist which is not bigger than MAXVIDWIDTHxMAXVIDHEIGHT
@ -386,7 +386,7 @@ static boolean IgnoreMouse(void)
{ {
if (cv_alwaysgrabmouse.value) if (cv_alwaysgrabmouse.value)
return false; return false;
if (menuactive) if (menustack[0])
return !M_MouseNeeded(); return !M_MouseNeeded();
if (paused || con_destlines || chat_on) if (paused || con_destlines || chat_on)
return true; return true;
@ -1005,7 +1005,7 @@ void I_GetEvent(void)
CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy); CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy);
// update the menu // update the menu
if (activeMenuId == MN_OP_JOYSTICKSET) if (menustack[0] == MN_OP_JOYSTICKSET)
M_SetupJoystickMenu(0); M_SetupJoystickMenu(0);
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
@ -1065,7 +1065,7 @@ void I_GetEvent(void)
CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy); CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy);
// update the menu // update the menu
if (activeMenuId == MN_OP_JOYSTICKSET) if (menustack[0] == MN_OP_JOYSTICKSET)
M_SetupJoystickMenu(0); M_SetupJoystickMenu(0);
break; break;
case SDL_DROPFILE: case SDL_DROPFILE:

View file

@ -858,7 +858,7 @@ void ST_AskToJoinEnvelope(void)
{ {
const tic_t freq = TICRATE/2; const tic_t freq = TICRATE/2;
if (menuactive) if (menustack[0])
return; return;
if ((leveltime % freq) < freq/2) if ((leveltime % freq) < freq/2)