diff --git a/src/d_main.cpp b/src/d_main.cpp index 4a66805e8..1c63c3c6a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1426,9 +1426,6 @@ void D_SRB2Main(void) // adapt tables to SRB2's needs, including extra slots for dehacked file support P_ResetData(15); - // initiate menu metadata before SOCcing them - M_InitMenuPresTables(); - // init title screen display params if (M_GetUrlProtocolArg() || M_CheckParm("-connect")) F_InitMenuPresValues(); diff --git a/src/deh_soc.c b/src/deh_soc.c index 905c5f07c..d4ee562ce 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -2121,142 +2121,142 @@ void readmenu(MYFILE *f, INT32 num) if (fastcmp(word, "BACKGROUNDNAME")) { - strncpy(menupres[num].bgname, word2, 8); + strncpy(menudefs[num].bgname, word2, 8); titlechanged = true; } else if (fastcmp(word, "HIDEBACKGROUND")) { - menupres[num].bghide = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); + menudefs[num].bghide = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "BACKGROUNDCOLOR")) { - menupres[num].bgcolor = get_number(word2); + menudefs[num].bgcolor = get_number(word2); titlechanged = true; } else if (fastcmp(word, "HIDETITLEPICS") || fastcmp(word, "HIDEPICS") || fastcmp(word, "TITLEPICSHIDE")) { // true by default, except MM_MAIN - menupres[num].hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); + menudefs[num].hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "TITLEPICSMODE")) { if (fastcmp(word2, "USER")) - menupres[num].ttmode = TTMODE_USER; + menudefs[num].ttmode = TTMODE_USER; else if (fastcmp(word2, "HIDE") || fastcmp(word2, "HIDDEN") || fastcmp(word2, "NONE")) { - menupres[num].ttmode = TTMODE_USER; - menupres[num].ttname[0] = 0; - menupres[num].hidetitlepics = true; + menudefs[num].ttmode = TTMODE_USER; + menudefs[num].ttname[0] = 0; + menudefs[num].hidetitlepics = true; } else if (fastcmp(word2, "KART")) - menupres[num].ttmode = TTMODE_KART; + menudefs[num].ttmode = TTMODE_KART; titlechanged = true; } else if (fastcmp(word, "TITLEPICSSCALE")) { // Don't handle Alacroix special case here; see Maincfg section. - menupres[num].ttscale = max(1, min(8, (UINT8)get_number(word2))); + menudefs[num].ttscale = max(1, min(8, (UINT8)get_number(word2))); titlechanged = true; } else if (fastcmp(word, "TITLEPICSNAME")) { - strncpy(menupres[num].ttname, word2, 9); + strncpy(menudefs[num].ttname, word2, 9); titlechanged = true; } else if (fastcmp(word, "TITLEPICSX")) { - menupres[num].ttx = (INT16)get_number(word2); + menudefs[num].ttx = (INT16)get_number(word2); titlechanged = true; } else if (fastcmp(word, "TITLEPICSY")) { - menupres[num].tty = (INT16)get_number(word2); + menudefs[num].tty = (INT16)get_number(word2); titlechanged = true; } else if (fastcmp(word, "TITLEPICSLOOP")) { - menupres[num].ttloop = (INT16)get_number(word2); + menudefs[num].ttloop = (INT16)get_number(word2); titlechanged = true; } else if (fastcmp(word, "TITLEPICSTICS")) { - menupres[num].tttics = (UINT16)get_number(word2); + menudefs[num].tttics = (UINT16)get_number(word2); titlechanged = true; } else if (fastcmp(word, "TITLESCROLLSPEED") || fastcmp(word, "TITLESCROLLXSPEED") || fastcmp(word, "SCROLLSPEED") || fastcmp(word, "SCROLLXSPEED")) { - menupres[num].titlescrollxspeed = get_number(word2); + menudefs[num].titlescrollxspeed = get_number(word2); titlechanged = true; } else if (fastcmp(word, "TITLESCROLLYSPEED") || fastcmp(word, "SCROLLYSPEED")) { - menupres[num].titlescrollyspeed = get_number(word2); + menudefs[num].titlescrollyspeed = get_number(word2); titlechanged = true; } else if (fastcmp(word, "MUSIC")) { - strncpy(menupres[num].musname, word2, 7); - menupres[num].musname[6] = 0; + strncpy(menudefs[num].musname, word2, 7); + menudefs[num].musname[6] = 0; titlechanged = true; } else if (fastcmp(word, "MUSICTRACK")) { - menupres[num].mustrack = ((UINT16)value - 1); + menudefs[num].mustrack = ((UINT16)value - 1); titlechanged = true; } else if (fastcmp(word, "MUSICLOOP")) { // true by default except MM_MAIN - menupres[num].muslooping = (value || word2[0] == 'T' || word2[0] == 'Y'); + menudefs[num].muslooping = (value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "NOMUSIC")) { - menupres[num].musstop = (value || word2[0] == 'T' || word2[0] == 'Y'); + menudefs[num].musstop = (value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "IGNOREMUSIC")) { - menupres[num].musignore = (value || word2[0] == 'T' || word2[0] == 'Y'); + menudefs[num].musignore = (value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "FADESTRENGTH")) { // one-based, <= 0 means use default value. 1-32 - menupres[num].fadestrength = get_number(word2)-1; + menudefs[num].fadestrength = get_number(word2)-1; titlechanged = true; } else if (fastcmp(word, "NOENTERBUBBLE")) { - menupres[num].enterbubble = !(value || word2[0] == 'T' || word2[0] == 'Y'); + menudefs[num].enterbubble = !(value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "NOEXITBUBBLE")) { - menupres[num].exitbubble = !(value || word2[0] == 'T' || word2[0] == 'Y'); + menudefs[num].exitbubble = !(value || word2[0] == 'T' || word2[0] == 'Y'); titlechanged = true; } else if (fastcmp(word, "ENTERTAG")) { - menupres[num].entertag = get_number(word2); + menudefs[num].entertag = get_number(word2); titlechanged = true; } else if (fastcmp(word, "EXITTAG")) { - menupres[num].exittag = get_number(word2); + menudefs[num].exittag = get_number(word2); titlechanged = true; } else if (fastcmp(word, "ENTERWIPE")) { - menupres[num].enterwipe = get_number(word2); + menudefs[num].enterwipe = get_number(word2); titlechanged = true; } else if (fastcmp(word, "EXITWIPE")) { - menupres[num].exitwipe = get_number(word2); + menudefs[num].exitwipe = get_number(word2); titlechanged = true; } // MENUDEF STARTS HERE diff --git a/src/f_finale.c b/src/f_finale.c index f1f5c749b..cb370def6 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1191,9 +1191,9 @@ void F_InitMenuPresValues(void) curtttics = tttics; // Find current presentation values - //M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY"); - //M_SetMenuCurFadeValue(16); - //M_SetMenuCurTitlePics(); + M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY"); + M_SetMenuCurFadeValue(16); + M_SetMenuCurTitlePics(); LUA_HUD_DestroyDrawList(luahuddrawlist_title); luahuddrawlist_title = LUA_HUD_CreateDrawList(); @@ -1325,7 +1325,7 @@ void F_StartTitleScreen(void) { ttuser_count = 0; finalecount = 0; - wipetypepost = menupres[MN_MAIN].enterwipe; + wipetypepost = menudefs[MN_MAIN].enterwipe; } else wipegamestate = GS_TITLESCREEN; @@ -1378,8 +1378,8 @@ void F_StartTitleScreen(void) camera[0].height = 0; // Run enter linedef exec for MN_MAIN, since this is where we start - if (menupres[MN_MAIN].entertag) - P_LinedefExecute(menupres[MN_MAIN].entertag, players[displayplayers[0]].mo, NULL); + if (menudefs[MN_MAIN].entertag) + P_LinedefExecute(menudefs[MN_MAIN].entertag, players[displayplayers[0]].mo, NULL); wipegamestate = prevwipegamestate; } @@ -1542,8 +1542,8 @@ void F_TitleScreenTicker(boolean run) else if (finalecount == 50) { // Now start the music - if (menupres[MN_MAIN].musname[0]) - S_ChangeMusic(menupres[MN_MAIN].musname, menupres[MN_MAIN].mustrack, menupres[MN_MAIN].muslooping); + if (menudefs[MN_MAIN].musname[0]) + S_ChangeMusic(menudefs[MN_MAIN].musname, menudefs[MN_MAIN].mustrack, menudefs[MN_MAIN].muslooping); else S_ChangeMusicInternal("titles", looptitle); S_StartSound(NULL, sfx_s23c); diff --git a/src/info.c b/src/info.c index 824253974..c795446eb 100644 --- a/src/info.c +++ b/src/info.c @@ -220,6 +220,7 @@ void P_ResetData(INT32 flags) if (init) { memset(menudefs, 0, sizeof(menudefs)); + M_InitMenuPresTables(); for (i = 0; i < MAXMENUTYPES; i++) menudefs[i].drawroutine = M_DrawGenericMenu; diff --git a/src/m_menu.c b/src/m_menu.c index 2d1b9a50e..09c41eb42 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -755,8 +755,6 @@ void Moviemode_option_Onchange(void) // MENU PRESENTATION PARAMETER HANDLING (BACKGROUNDS) // ========================================================================= -menupres_t menupres[MAXMENUTYPES]; - void M_InitMenuPresTables(void) { INT32 i; @@ -766,39 +764,503 @@ void M_InitMenuPresTables(void) for (i = 0; i < MAXMENUTYPES; i++) { // so-called "undefined" - menupres[i].fadestrength = -1; - menupres[i].hidetitlepics = -1; // inherits global hidetitlepics - menupres[i].ttmode = TTMODE_NONE; - menupres[i].ttscale = UINT8_MAX; - menupres[i].ttname[0] = 0; - menupres[i].ttx = INT16_MAX; - menupres[i].tty = INT16_MAX; - menupres[i].ttloop = INT16_MAX; - menupres[i].tttics = UINT16_MAX; - menupres[i].enterwipe = -1; - menupres[i].exitwipe = -1; - menupres[i].bgcolor = -1; - menupres[i].titlescrollxspeed = INT32_MAX; - menupres[i].titlescrollyspeed = INT32_MAX; - menupres[i].bghide = true; + menudefs[i].fadestrength = -1; + menudefs[i].hidetitlepics = -1; // inherits global hidetitlepics + menudefs[i].ttmode = TTMODE_NONE; + menudefs[i].ttscale = UINT8_MAX; + menudefs[i].ttname[0] = 0; + menudefs[i].ttx = INT16_MAX; + menudefs[i].tty = INT16_MAX; + menudefs[i].ttloop = INT16_MAX; + menudefs[i].tttics = UINT16_MAX; + menudefs[i].enterwipe = -1; + menudefs[i].exitwipe = -1; + menudefs[i].bgcolor = -1; + menudefs[i].titlescrollxspeed = INT32_MAX; + menudefs[i].titlescrollyspeed = INT32_MAX; + menudefs[i].bghide = true; // default true - menupres[i].enterbubble = true; - menupres[i].exitbubble = true; + menudefs[i].enterbubble = true; + menudefs[i].exitbubble = true; if (i != MN_MAIN) { - menupres[i].muslooping = true; + menudefs[i].muslooping = true; } if (i == MN_SP_TIMEATTACK) - strncpy(menupres[i].musname, "_recat", 7); + strncpy(menudefs[i].musname, "_recat", 7); else if (i == MN_SR_SOUNDTEST) { - *menupres[i].musname = '\0'; - menupres[i].musstop = true; + *menudefs[i].musname = '\0'; + menudefs[i].musstop = true; } } } +// ==================================== +// TREE ITERATION +// ==================================== + +// UINT32 menutype - current menutype_t +// INT32 level - current level up the tree, higher means younger +// INT32 *retval - Return value +// void *input - Pointer to input of any type +// +// return true - stop iterating +// return false - continue +typedef boolean (*menutree_iterator)(UINT32, INT32, INT32 *, void **, boolean fromoldest); + +// HACK: Used in the ChangeMusic iterator because we only allow +// a single input. Maybe someday use this struct program-wide. +typedef struct +{ + char musname[7]; + UINT16 mustrack; + boolean muslooping; +} menupresmusic_t; + +static INT32 M_IterateMenuTree(menutree_iterator itfunc, void *input) +{ + INT32 i, retval = 0; + + for (i = NUMMENULEVELS; i >= 0; i--) + { + if (itfunc(menustack[i], i, &retval, &input, false)) + break; + } + + return retval; +} + +// ==================================== +// ITERATORS +// ==================================== + +static boolean MIT_GetMenuAtLevel(UINT32 menutype, INT32 level, INT32 *retval, void **input, boolean fromoldest) +{ + INT32 *inputptr = (INT32*)*input; + INT32 targetlevel = *inputptr; + if (menutype) + { + if (level == targetlevel || targetlevel < 0) + { + *retval = menutype; + return true; + } + } + else if (targetlevel >= 0) + { + // offset targetlevel by failed attempts; this should only happen in beginning of iteration + if (fromoldest) + (*inputptr)++; + else + (*inputptr)--; // iterating backwards, so count from highest + } + return false; +} + +static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, void **input, boolean fromoldest) +{ + char *defaultname = (char*)*input; + + (void)retval; + (void)fromoldest; + + if (!menutype) // if there's nothing in this level, do nothing + return false; + + if (menudefs[menutype].bgcolor >= 0) + { + curbgcolor = menudefs[menutype].bgcolor; + return true; + } + else if (menudefs[menutype].bghide && titlemapinaction) // hide the background + { + curbghide = true; + return true; + } + else if (menudefs[menutype].bgname[0]) + { + strncpy(curbgname, menudefs[menutype].bgname, 8); + curbgxspeed = menudefs[menutype].titlescrollxspeed != INT32_MAX ? menudefs[menutype].titlescrollxspeed : titlescrollxspeed; + curbgyspeed = menudefs[menutype].titlescrollyspeed != INT32_MAX ? menudefs[menutype].titlescrollyspeed : titlescrollyspeed; + return true; + } + else if (!level) + { + /*if (M_GetYoungestChildMenu() == MN_SP_PLAYER || !defaultname || !defaultname[0]) + curbgcolor = 31; + else*/ if (titlemapinaction) // hide the background by default in titlemap + curbghide = true; + else + { + strncpy(curbgname, defaultname, 9); + curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; + curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; + } + } + return false; +} + +static boolean MIT_ChangeMusic(UINT32 menutype, INT32 level, INT32 *retval, void **input, boolean fromoldest) +{ + menupresmusic_t *defaultmusic = (menupresmusic_t*)*input; + + (void)retval; + (void)fromoldest; + + if (!menutype) // if there's nothing in this level, do nothing + return false; + + if (menudefs[menutype].musname[0]) + { + S_ChangeMusic(menudefs[menutype].musname, menudefs[menutype].mustrack, menudefs[menutype].muslooping); + return true; + } + else if (menudefs[menutype].musstop) + { + S_StopMusic(); + return true; + } + else if (menudefs[menutype].musignore) + return true; + else if (!level && defaultmusic && defaultmusic->musname[0]) + S_ChangeMusic(defaultmusic->musname, defaultmusic->mustrack, defaultmusic->muslooping); + return false; +} + +static boolean MIT_SetCurFadeValue(UINT32 menutype, INT32 level, INT32 *retval, void **input, boolean fromoldest) +{ + UINT8 defaultvalue = *(UINT8*)*input; + + (void)retval; + (void)fromoldest; + + if (!menutype) // if there's nothing in this level, do nothing + return false; + + if (menudefs[menutype].fadestrength >= 0) + { + curfadevalue = (menudefs[menutype].fadestrength % 32); + return true; + } + else if (!level) + curfadevalue = (gamestate == GS_TIMEATTACK) ? 0 : (defaultvalue % 32); + return false; +} + +static boolean MIT_SetCurTitlePics(UINT32 menutype, INT32 level, INT32 *retval, void **input, boolean fromoldest) +{ + (void)input; + (void)retval; + (void)fromoldest; + + if (!menutype) // if there's nothing in this level, do nothing + return false; + + if (menudefs[menutype].hidetitlepics >= 0) + { + curhidepics = menudefs[menutype].hidetitlepics; + return true; + } + else if (menudefs[menutype].ttmode == TTMODE_USER) + { + if (menudefs[menutype].ttname[0]) + { + curhidepics = menudefs[menutype].hidetitlepics; + curttmode = menudefs[menutype].ttmode; + curttscale = (menudefs[menutype].ttscale != UINT8_MAX ? menudefs[menutype].ttscale : ttscale); + strncpy(curttname, menudefs[menutype].ttname, sizeof(curttname)-1); + curttx = (menudefs[menutype].ttx != INT16_MAX ? menudefs[menutype].ttx : ttx); + curtty = (menudefs[menutype].tty != INT16_MAX ? menudefs[menutype].tty : tty); + curttloop = (menudefs[menutype].ttloop != INT16_MAX ? menudefs[menutype].ttloop : ttloop); + curtttics = (menudefs[menutype].tttics != UINT16_MAX ? menudefs[menutype].tttics : tttics); + } + else + curhidepics = menudefs[menutype].hidetitlepics; + return true; + } + else if (menudefs[menutype].ttmode != TTMODE_NONE) + { + curhidepics = menudefs[menutype].hidetitlepics; + curttmode = menudefs[menutype].ttmode; + curttscale = (menudefs[menutype].ttscale != UINT8_MAX ? menudefs[menutype].ttscale : ttscale); + return true; + } + else if (!level) + { + curhidepics = hidetitlepics; + curttmode = ttmode; + curttscale = ttscale; + strncpy(curttname, ttname, 9); + curttx = ttx; + curtty = tty; + curttloop = ttloop; + curtttics = tttics; + } + return false; +} + +// ==================================== +// TREE RETRIEVAL +// ==================================== + +UINT8 M_GetYoungestChildMenu(void) // aka the active menu +{ + INT32 targetlevel = -1; + return M_IterateMenuTree(MIT_GetMenuAtLevel, &targetlevel); +} + +// ==================================== +// EFFECTS +// ==================================== + +void M_ChangeMenuMusic(const char *defaultmusname, boolean defaultmuslooping) +{ + menupresmusic_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); +} + +void M_SetMenuCurBackground(const char *defaultname) +{ + char name[9] = ""; + strncpy(name, defaultname, 8); + name[8] = '\0'; + M_IterateMenuTree(MIT_SetCurBackground, &name); +} + +void M_SetMenuCurFadeValue(UINT8 defaultvalue) +{ + M_IterateMenuTree(MIT_SetCurFadeValue, &defaultvalue); +} + +void M_SetMenuCurTitlePics(void) +{ + M_IterateMenuTree(MIT_SetCurTitlePics, NULL); +} + +// ==================================== +// MENU STATE +// ==================================== + +static INT32 exitlevel, enterlevel, anceslevel; +static INT16 exittype, entertype; +static INT16 exitwipe, enterwipe; +static boolean exitbubble, enterbubble; +static INT16 exittag, entertag; + +static void M_HandleMenuPresState(menutype_t newMenuType) +{ + menu_t *newMenu = &menudefs[newMenuType]; + INT32 i; + //UINT32 bitmask; // G: we use stacks around here + SINT8 prevtype, activetype, menutype; + + if (!newMenu) + return; + + // Look for MN_SPECIAL here, because our iterators can't look at new menu IDs + // G: we don't do special cases around here + /*for (i = 0; i <= NUMMENULEVELS; i++) + { + bitmask = ((1 << MENUBITS) - 1) << (MENUBITS*i); + menutype = (newMenu->menuid & bitmask) >> (MENUBITS*i); + prevtype = (currentMenu->menuid & bitmask) >> (MENUBITS*i); + if (menutype == MN_SPECIAL || prevtype == MN_SPECIAL) + return; + }*/ + + if (/*currentMenu && newMenu && currentMenu->menuid == newMenu->menuid*/currentMenu == newMenu) // same menu? + return; + + exittype = entertype = exitlevel = enterlevel = anceslevel = exitwipe = enterwipe = -1; + exitbubble = enterbubble = true; + + // G: nope... doesn't exist anymore + //prevMenuId = menustack[0];//currentMenu ? currentMenu->menuid : 0; + //activeMenuId = newMenuType;//newMenu ? newMenu->menuid : 0; + + // Set defaults for presentation values + strncpy(curbgname, "TITLESKY", 9); + curfadevalue = 16; + curhidepics = hidetitlepics; + curbgcolor = -1; + curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed; + curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed; + curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus + + curttmode = ttmode; + curttscale = ttscale; + strncpy(curttname, ttname, 9); + curttx = ttx; + curtty = tty; + curttloop = ttloop; + curtttics = tttics; + + // don't do the below during the in-game menus + if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK) + return; + + M_SetMenuCurFadeValue(16); + M_SetMenuCurTitlePics(); + + // Loop through both menu IDs in parallel and look for type changes + // The youngest child in activeMenuId is the entered menu + // The youngest child in prevMenuId is the exited menu + + // 0. Get the type and level of each menu, and level of common ancestor + // 1. Get the wipes for both, then run the exit wipe + // 2. Change music (so that execs can change it again later) + // 3. Run each exit exec on the prevMenuId up to the common ancestor (UNLESS NoBubbleExecs) + // 4. Run each entrance exec on the activeMenuId down from the common ancestor (UNLESS NoBubbleExecs) + // 5. Run the entrance wipe + + // Get the parameters for each menu + for (i = NUMMENULEVELS; i >= 0; i--) + { + //prevtype = (prevMenuId & bitmask) >> (MENUBITS*i); + //activetype = (activeMenuId & bitmask) >> (MENUBITS*i); + prevtype = menustack[max(i-1, 0)]; // G: uhhh i dunno + activetype = menustack[max(i-1, 0)]; + + if (prevtype && (exittype < 0)) + { + exittype = prevtype; + exitlevel = i; + exitwipe = menudefs[exittype].exitwipe; + exitbubble = menudefs[exittype].exitbubble; + exittag = menudefs[exittype].exittag; + } + + if (activetype && (entertype < 0)) + { + entertype = activetype; + enterlevel = i; + enterwipe = menudefs[entertype].enterwipe; + enterbubble = menudefs[entertype].enterbubble; + entertag = menudefs[entertype].entertag; + } + + if (prevtype && activetype && prevtype == activetype && anceslevel < 0) + { + anceslevel = i; + break; + } + } + + // if no common ancestor (top menu), force a wipe. Look for a specified wipe first. + // Don't force a wipe if you're actually going to/from the main menu + if (anceslevel < 0 && exitwipe < 0 && newMenu != &menudefs[MN_MAIN] && currentMenu != &menudefs[MN_MAIN]) + { + for (i = NUMMENULEVELS; i >= 0; i--) + { + prevtype = menustack[max(i-1, 0)]; + + if (menudefs[prevtype].exitwipe >= 0) + { + exitwipe = menudefs[prevtype].exitwipe; + break; + } + } + + if (exitwipe < 0) + exitwipe = menudefs[MN_MAIN].exitwipe; + } + + // do the same for enter wipe + if (anceslevel < 0 && enterwipe < 0 && newMenu != &menudefs[MN_MAIN] && currentMenu != &menudefs[MN_MAIN]) + { + for (i = NUMMENULEVELS; i >= 0; i--) + { + activetype = menustack[max(i-1, 0)]; + + if (menudefs[activetype].enterwipe >= 0) + { + exitwipe = menudefs[activetype].enterwipe; + break; + } + } + + if (enterwipe < 0) + enterwipe = menudefs[MN_MAIN].enterwipe; + } + + // Change the music + M_ChangeMenuMusic("_title", false); + + // Run the linedef execs + if (titlemapinaction) + { + // Run the exit tags + if (enterlevel <= exitlevel) // equals is an edge case + { + if (exitbubble) + { + for (i = exitlevel; i > anceslevel; i--) // don't run the common ancestor's exit tag + { + menutype = menustack[i]; + if (menudefs[menutype].exittag) + P_LinedefExecute(menudefs[menutype].exittag, players[displayplayers[0]].mo, NULL); + } + } + else if (exittag) + P_LinedefExecute(exittag, players[displayplayers[0]].mo, NULL); + } + + // Run the enter tags + if (enterlevel >= exitlevel) // equals is an edge case + { + if (enterbubble) + { + for (i = anceslevel+1; i <= enterlevel; i++) // don't run the common ancestor's enter tag + { + menutype = menustack[i]; + if (menudefs[menutype].entertag) + P_LinedefExecute(menudefs[menutype].entertag, players[displayplayers[0]].mo, NULL); + } + } + else if (entertag) + P_LinedefExecute(entertag, players[displayplayers[0]].mo, NULL); + } + } + + + // Set the wipes for next frame + if ( + (exitwipe >= 0 && enterlevel <= exitlevel) || + (enterwipe >= 0 && enterlevel >= exitlevel) || + (anceslevel < 0 && newMenu != &menudefs[MN_MAIN] && currentMenu != &menudefs[MN_MAIN]) + ) + { + if (gamestate == GS_TIMEATTACK) + wipetypepre = ((exitwipe && enterlevel <= exitlevel) || anceslevel < 0) ? exitwipe : -1; // force default + else + // HACK: INT16_MAX signals to not wipe + // because 0 is a valid index and -1 means default + wipetypepre = ((exitwipe && enterlevel <= exitlevel) || anceslevel < 0) ? exitwipe : INT16_MAX; + wipetypepost = ((enterwipe && enterlevel >= exitlevel) || anceslevel < 0) ? enterwipe : INT16_MAX; + wipegamestate = -1; // G: FORCEWIPE + + // If just one of the above is a force not-wipe, + // mirror the other wipe. + if (wipetypepre != INT16_MAX && wipetypepost == INT16_MAX) + wipetypepost = wipetypepre; + else if (wipetypepost != INT16_MAX && wipetypepre == INT16_MAX) + wipetypepre = wipetypepost; + + // D_Display runs the next step of processing + } +} + // ========================================================================= // BASIC MENU HANDLING // ========================================================================= @@ -1586,6 +2048,8 @@ static void M_SetupNextMenu(menutype_t menunum, boolean callexit) if (callexit && currentMenu && currentMenu != menudef && currentMenu->quitroutine) currentMenu->quitroutine(0); + M_HandleMenuPresState(menunum); + currentMenu = menudef; itemOn = currentMenu->lastOn; diff --git a/src/m_menu.h b/src/m_menu.h index 567701f53..e9c4c422e 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -51,46 +51,12 @@ typedef enum extern menutype_t menustack[NUMMENULEVELS]; -typedef struct -{ - char bgname[8]; // name for background gfx lump; lays over titlemap if this is set - SINT8 fadestrength; // darken background when displaying this menu, strength 0-31 or -1 for undefined - INT32 bgcolor; // fill color, overrides bg name. -1 means follow bg name rules. - INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting - INT32 titlescrollyspeed; // y scroll - boolean bghide; // for titlemaps, hide the background. - - SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting - ttmode_enum ttmode; // title wing animation mode; default TTMODE_KART - UINT8 ttscale; // scale of title wing gfx (FRACUNIT / ttscale); -1 means undefined, inherits global setting - char ttname[9]; // lump name of title wing gfx. If name length is <= 6, engine will attempt to load numbered frames (TTNAMExx) - INT16 ttx; // X position of title wing - INT16 tty; // Y position of title wing - INT16 ttloop; // # frame to loop; -1 means dont loop - UINT16 tttics; // # of tics per frame - - char musname[7]; ///< Music track to play. "" for no music. - 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 musstop; ///< Don't play any music - boolean musignore; ///< Let the current music keep playing - - boolean enterbubble; // run all entrance line execs after common ancestor and up to child. If false, only run the child's exec - boolean exitbubble; // run all exit line execs from child and up to before common ancestor. If false, only run the child's exec - INT32 entertag; // line exec to run on menu enter, if titlemap - INT32 exittag; // line exec to run on menu exit, if titlemap - INT16 enterwipe; // wipe type to run on menu enter, -1 means default - INT16 exitwipe; // wipe type to run on menu exit, -1 means default -} menupres_t; - -extern menupres_t menupres[MAXMENUTYPES]; - void M_InitMenuPresTables(void); -//UINT8 M_GetYoungestChildMenu(void); -//void M_ChangeMenuMusic(const char *defaultmusname, boolean defaultmuslooping); -//void M_SetMenuCurBackground(const char *defaultname); -//void M_SetMenuCurFadeValue(UINT8 defaultvalue); -//void M_SetMenuCurTitlePics(void); +UINT8 M_GetYoungestChildMenu(void); +void M_ChangeMenuMusic(const char *defaultmusname, boolean defaultmuslooping); +void M_SetMenuCurBackground(const char *defaultname); +void M_SetMenuCurFadeValue(UINT8 defaultvalue); +void M_SetMenuCurTitlePics(void); // Called by main loop, // saves config file and calls I_Quit when user exits. @@ -226,6 +192,37 @@ struct menu_t menufunc_f *enterroutine; // called before enter a menu menufunc_f *quitroutine; // called before quit a menu menufunc_f *keyhandler; // called before key press is processed + + // MENUPRES STUFF BELOW + + char bgname[8]; // name for background gfx lump; lays over titlemap if this is set + SINT8 fadestrength; // darken background when displaying this menu, strength 0-31 or -1 for undefined + INT32 bgcolor; // fill color, overrides bg name. -1 means follow bg name rules. + INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting + INT32 titlescrollyspeed; // y scroll + boolean bghide; // for titlemaps, hide the background. + + SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting + ttmode_enum ttmode; // title wing animation mode; default TTMODE_KART + UINT8 ttscale; // scale of title wing gfx (FRACUNIT / ttscale); -1 means undefined, inherits global setting + char ttname[9]; // lump name of title wing gfx. If name length is <= 6, engine will attempt to load numbered frames (TTNAMExx) + INT16 ttx; // X position of title wing + INT16 tty; // Y position of title wing + INT16 ttloop; // # frame to loop; -1 means dont loop + UINT16 tttics; // # of tics per frame + + char musname[7]; ///< Music track to play. "" for no music. + 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 musstop; ///< Don't play any music + boolean musignore; ///< Let the current music keep playing + + boolean enterbubble; // run all entrance line execs after common ancestor and up to child. If false, only run the child's exec + boolean exitbubble; // run all exit line execs from child and up to before common ancestor. If false, only run the child's exec + INT32 entertag; // line exec to run on menu enter, if titlemap + INT32 exittag; // line exec to run on menu exit, if titlemap + INT16 enterwipe; // wipe type to run on menu enter, -1 means default + INT16 exitwipe; // wipe type to run on menu exit, -1 means default }; extern menu_t menudefs[MAXMENUTYPES];