diff --git a/doomsday/plugins/common/include/hu_lib.h b/doomsday/plugins/common/include/hu_lib.h index 717575cace..b85edf9109 100644 --- a/doomsday/plugins/common/include/hu_lib.h +++ b/doomsday/plugins/common/include/hu_lib.h @@ -194,12 +194,19 @@ typedef struct mn_object_s { void* data1; int data2; + // Auto initialized: + /// Current geometry. Rect* _geometry; + + /// MenuPage which owns this object (if any). + struct mn_page_s* _page; } mn_object_t; mn_obtype_e MNObject_Type(const mn_object_t* obj); +struct mn_page_s* MNObject_Page(const mn_object_t* obj); + int MNObject_Flags(const mn_object_t* obj); /** @@ -292,23 +299,48 @@ typedef enum { #define VALID_MNPAGE_FONTID(v) ((v) >= MENU_FONT1 && (v) < MENU_FONT_COUNT) typedef struct mn_page_s { - mn_object_t* objects; // List of objects. + /// Collection of objects on this page. + mn_object_t* objects; + int objectsCount; + + /// "Physical" geometry in fixed 320x200 screen coordinate space. Point2Raw origin; + Rect* geometry; + + /// Previous page else @c NULL + struct mn_page_s* previous; + + /// Title of this page. + ddstring_t title; + + /// Index of the currently focused object else @c -1 + int focus; + + /// Predefined fonts objects on this page. fontid_t fonts[MENU_FONT_COUNT]; + + /// Predefined colors for objects on this page. uint colors[MENU_COLOR_COUNT]; - void (*drawer) (struct mn_page_s* page, const Point2Raw* origin); + + /// Page drawing routine. + void (*drawer) (struct mn_page_s* page, const Point2Raw* offset); + + /// Menu command responder routine. int (*cmdResponder) (struct mn_page_s* page, menucommand_e cmd); - struct mn_page_s* previous; // Pointer to the previous page, if any. - void* data; - // Auto-initialized. - int objectsCount; - int focus; // Index of the focus object. - Rect* geometry; + /// User data. + void* userData; } mn_page_t; void MNPage_Initialize(mn_page_t* page); +void MNPage_SetTitle(mn_page_t* page, const char* title); + +void MNPage_SetX(mn_page_t* page, int x); +void MNPage_SetY(mn_page_t* page, int y); + +void MNPage_SetPreviousPage(mn_page_t* page, mn_page_t* prevPage); + /// @return Currently focused object else @c NULL mn_object_t* MNPage_FocusObject(mn_page_t* page); @@ -680,7 +712,6 @@ extern const mn_rendstate_t* mnRendState; short MN_MergeMenuEffectWithDrawTextFlags(short f); -int MN_CountObjects(mn_object_t* list); mn_object_t* MN_MustFindObjectOnPage(mn_page_t* page, int group, int flags); void MN_DrawPage(mn_page_t* page, float alpha, boolean showFocusCursor); diff --git a/doomsday/plugins/common/include/hu_menu.h b/doomsday/plugins/common/include/hu_menu.h index e8be781ff2..6bdaddbcd1 100644 --- a/doomsday/plugins/common/include/hu_menu.h +++ b/doomsday/plugins/common/include/hu_menu.h @@ -76,35 +76,7 @@ #define MENU_CURSOR_FRAMECOUNT 2 #define MENU_CURSOR_TICSPERFRAME 8 -extern mn_page_t MainMenu; -extern mn_page_t GameTypeMenu; -#if __JHEXEN__ -extern mn_page_t PlayerClassMenu; -#endif -#if __JDOOM__ || __JHERETIC__ -extern mn_page_t EpisodeMenu; -#endif -//extern mn_page_t SkillMenu; -extern mn_page_t OptionsMenu; -extern mn_page_t SoundMenu; -extern mn_page_t GameplayMenu; -extern mn_page_t HudMenu; -extern mn_page_t AutomapMenu; -extern mn_object_t AutomapMenuObjects[]; -#if __JHERETIC__ || __JHEXEN__ -extern mn_page_t FilesMenu; -#endif -extern mn_page_t LoadMenu; -extern mn_page_t SaveMenu; -extern mn_page_t MultiplayerMenu; -extern mn_page_t PlayerSetupMenu; -#if __JHERETIC__ || __JHEXEN__ -extern mn_page_t InventoryMenu; -#endif -extern mn_page_t WeaponMenu; - extern int menuTime; - extern boolean menuNominatingQuickSaveSlot; /// Register the console commands, variables, etc..., of this module. @@ -137,6 +109,13 @@ void Hu_MenuTicker(timespan_t ticLength); /// @return @c true if the menu is presently visible. boolean Hu_MenuIsVisible(void); +mn_page_t* Hu_MenuFindPageByName(const char* name); + +mn_page_t* Hu_MenuNewPage(const char* name, const Point2Raw* origin, + void (*drawer) (struct mn_page_s* page, const Point2Raw* origin), + int (*cmdResponder) (struct mn_page_s* page, menucommand_e cmd), + void* userData); + /** * This is the main menu drawing routine (called every tic by the drawing * loop) Draws the current menu 'page' by calling the funcs attached to @@ -147,8 +126,7 @@ void Hu_MenuDrawer(void); void Hu_MenuDrawFocusCursor(int x, int y, int focusObjectHeight, float alpha); void Hu_MenuDrawPageTitle(const char* title, int x, int y); - -void Hu_MenuDrawPageNavigation(mn_page_t* page, int x, int y); +void Hu_MenuDrawPageHelp(const char* help, int x, int y); /// @return @c true if the input event @a ev was eaten. int Hu_MenuPrivilegedResponder(event_t* ev); @@ -189,8 +167,6 @@ mn_page_t* Hu_MenuActivePage(void); */ void Hu_MenuSetActivePage(mn_page_t* page); -void Hu_MenuComposeSubpageString(mn_page_t* page, size_t bufSize, char* buf); - /** * Initialize a new singleplayer game according to the options set via the menu. * @param confirmed If @c true this game configuration has already been confirmed. diff --git a/doomsday/plugins/common/include/m_ctrl.h b/doomsday/plugins/common/include/m_ctrl.h index 98656de968..0ea95f4f6c 100644 --- a/doomsday/plugins/common/include/m_ctrl.h +++ b/doomsday/plugins/common/include/m_ctrl.h @@ -31,8 +31,6 @@ #include "hu_lib.h" -extern mn_page_t ControlsMenu; - void Hu_MenuInitControlsPage(void); void Hu_MenuDrawControlsPage(mn_page_t* page, const Point2Raw* origin); void Hu_MenuControlGrabDrawer(const char* niceName, float alpha); diff --git a/doomsday/plugins/common/src/g_game.c b/doomsday/plugins/common/src/g_game.c index e2bf9d77b5..500afade9a 100644 --- a/doomsday/plugins/common/src/g_game.c +++ b/doomsday/plugins/common/src/g_game.c @@ -3289,7 +3289,7 @@ static void openLoadMenu(void) /// \fixme This should be called automatically when opening the page /// thus making this function redundant. Hu_MenuUpdateGameSaveWidgets(); - Hu_MenuSetActivePage(&LoadMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("LoadGame")); } static void openSaveMenu(void) @@ -3298,7 +3298,7 @@ static void openSaveMenu(void) /// \fixme This should be called automatically when opening the page /// thus making this function redundant. Hu_MenuUpdateGameSaveWidgets(); - Hu_MenuSetActivePage(&SaveMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("SaveGame")); } int G_QuickLoadGameResponse(msgresponse_t response, void* context) @@ -3385,7 +3385,7 @@ void G_QuickSaveGame(void) { Hu_MenuCommand(MCMD_OPEN); Hu_MenuUpdateGameSaveWidgets(); - Hu_MenuSetActivePage(&SaveMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("SaveGame")); menuNominatingQuickSaveSlot = true; return; } diff --git a/doomsday/plugins/common/src/hu_lib.c b/doomsday/plugins/common/src/hu_lib.c index ef41350db0..28b9bc103e 100644 --- a/doomsday/plugins/common/src/hu_lib.c +++ b/doomsday/plugins/common/src/hu_lib.c @@ -697,13 +697,6 @@ static void MNEdit_LoadResources(void) pEditMiddle = R_DeclarePatch(MNDATA_EDIT_BACKGROUND_PATCH_MIDDLE); } -int MN_CountObjects(mn_object_t* list) -{ - int count; - for(count = 0; MNObject_Type(list) != MN_NONE; list++, count++); - return count; -} - mn_object_t* MN_MustFindObjectOnPage(mn_page_t* page, int group, int flags) { mn_object_t* obj = MNPage_FindObject(page, group, flags); @@ -856,6 +849,68 @@ static void applyPageLayout(mn_page_t* page) } } +static void composeSubpageString(mn_page_t* page, char* buf, size_t bufSize) +{ + assert(page); + if(!buf || 0 == bufSize) return; + dd_snprintf(buf, bufSize, "Page %i/%i", 0, 0); +} + +static void drawPageNavigation(mn_page_t* page, int x, int y) +{ + const int currentPage = 0;//(page->firstObject + page->numVisObjects/2) / page->numVisObjects + 1; + const int totalPages = 1;//(int)ceil((float)page->objectsCount/page->numVisObjects); +#if __JDOOM__ || __JDOOM64__ + char buf[1024]; +#endif + + if(!page || totalPages <= 1) return; + +#if __JDOOM__ || __JDOOM64__ + composeSubpageString(page, buf, 1024); + + DGL_Enable(DGL_TEXTURE_2D); + FR_SetFont(FID(GF_FONTA)); + FR_SetColorv(cfg.menuTextColors[1]); + FR_SetAlpha(mnRendState->pageAlpha); + + FR_DrawTextXY3(buf, x, y, ALIGN_TOP, MN_MergeMenuEffectWithDrawTextFlags(0)); + + DGL_Disable(DGL_TEXTURE_2D); +#else + DGL_Enable(DGL_TEXTURE_2D); + DGL_Color4f(1, 1, 1, mnRendState->pageAlpha); + + GL_DrawPatchXY2( pInvPageLeft[currentPage == 0 || (menuTime & 8)], x - 144, y, ALIGN_RIGHT); + GL_DrawPatchXY2(pInvPageRight[currentPage == totalPages-1 || (menuTime & 8)], x + 144, y, ALIGN_LEFT); + + DGL_Disable(DGL_TEXTURE_2D); +#endif +} + +static void drawPageHeading(mn_page_t* page, const Point2Raw* offset) +{ + Point2Raw origin; + + if(!page) return; + + /// \kludge no title = no heading. + if(Str_IsEmpty(&page->title)) return; + + origin.x = SCREENWIDTH/2; + origin.y = (SCREENHEIGHT/2) - ((SCREENHEIGHT/2-5)/cfg.menuScale); + if(offset) + { + origin.x += offset->x; + origin.y += offset->y; + } + + FR_PushAttrib(); + Hu_MenuDrawPageTitle(Str_Text(&page->title), origin.x, origin.y); origin.y += 16; + drawPageNavigation(page, origin.x, origin.y); + FR_PopAttrib(); +} + void MN_DrawPage(mn_page_t* page, float alpha, boolean showFocusCursor) { mn_object_t* focusObj; @@ -959,7 +1014,7 @@ void MN_DrawPage(mn_page_t* page, float alpha, boolean showFocusCursor) FR_PopAttrib(); } - // Finally, the focus cursor? + // How about a focus cursor? /// \todo cursor should be drawn on top of the page drawer. if(showFocusCursor && focusObj) { @@ -969,6 +1024,8 @@ void MN_DrawPage(mn_page_t* page, float alpha, boolean showFocusCursor) DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); + drawPageHeading(page, NULL/*no offset*/); + // The page has its own drawer. if(page->drawer) { @@ -984,6 +1041,30 @@ static boolean MNActionInfo_IsActionExecuteable(mn_actioninfo_t* info) return (info->callback != 0); } +void MNPage_SetTitle(mn_page_t* page, const char* title) +{ + assert(page); + Str_Set(&page->title, title? title : ""); +} + +void MNPage_SetX(mn_page_t* page, int x) +{ + assert(page); + page->origin.x = x; +} + +void MNPage_SetY(mn_page_t* page, int y) +{ + assert(page); + page->origin.y = y; +} + +void MNPage_SetPreviousPage(mn_page_t* page, mn_page_t* prevPage) +{ + assert(page); + page->previous = prevPage; +} + mn_object_t* MNPage_FocusObject(mn_page_t* page) { assert(page); @@ -1246,6 +1327,12 @@ mn_obtype_e MNObject_Type(const mn_object_t* obj) return obj->_type; } +mn_page_t* MNObject_Page(const mn_object_t* obj) +{ + assert(obj); + return obj->_page; +} + int MNObject_Flags(const mn_object_t* obj) { assert(obj); diff --git a/doomsday/plugins/common/src/hu_menu.c b/doomsday/plugins/common/src/hu_menu.c index 20048cd81b..edd7e2db28 100644 --- a/doomsday/plugins/common/src/hu_menu.c +++ b/doomsday/plugins/common/src/hu_menu.c @@ -113,23 +113,18 @@ void Hu_MenuDrawPlayerClassPage(mn_page_t* page, const Point2Raw* origin); void Hu_MenuDrawEpisodePage(mn_page_t* page, const Point2Raw* origin); #endif void Hu_MenuDrawOptionsPage(mn_page_t* page, const Point2Raw* origin); -void Hu_MenuDrawSoundPage(mn_page_t* page, const Point2Raw* origin); -void Hu_MenuDrawGameplayPage(mn_page_t* page, const Point2Raw* origin); -void Hu_MenuDrawHudPage(mn_page_t* page, const Point2Raw* origin); -#if __JHERETIC__ || __JHEXEN__ -void Hu_MenuDrawInventoryPage(mn_page_t* page, const Point2Raw* origin); -#endif void Hu_MenuDrawWeaponsPage(mn_page_t* page, const Point2Raw* origin); void Hu_MenuDrawLoadGamePage(mn_page_t* page, const Point2Raw* origin); void Hu_MenuDrawSaveGamePage(mn_page_t* page, const Point2Raw* origin); void Hu_MenuDrawMultiplayerPage(mn_page_t* page, const Point2Raw* origin); void Hu_MenuDrawPlayerSetupPage(mn_page_t* page, const Point2Raw* origin); -void Hu_MenuDrawAutomapPage(mn_page_t* page, const Point2Raw* origin); int Hu_MenuColorWidgetCmdResponder(mn_page_t* page, menucommand_e cmd); +static void initAllPages(void); +static void destroyAllPages(void); + static void initAllObjectsOnAllPages(void); -static void destroyAllObjectsOnAllPages(void); static void Hu_MenuUpdateCursorState(void); @@ -338,46 +333,28 @@ mndata_button_t btn_main_quit_game = { false, NULL, "Quit Game" }; mn_object_t MainMenuObjects[] = { #if __JDOOM__ - { MN_BUTTON, 0, 0, 'n', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_new_game, &GameTypeMenu }, - { MN_BUTTON, 0, 0, 'o', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_options, &OptionsMenu }, + { MN_BUTTON, 0, 0, 'n', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_new_game, "GameType" }, + { MN_BUTTON, 0, 0, 'o', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_options, "Options" }, { MN_BUTTON, 0, 0, 'l', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectLoadGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_load_game }, { MN_BUTTON, 0, 0, 's', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectSaveGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_save_game }, { MN_BUTTON, 0, MNF_ID0, 'r', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectHelp, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_help }, { MN_BUTTON, 0, 0, 'q', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectQuitGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_quit_game }, #elif __JDOOM64__ - { MN_BUTTON, 0, 0, 'n', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_new_game, &GameTypeMenu }, - { MN_BUTTON, 0, 0, 'o', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_options, &OptionsMenu }, + { MN_BUTTON, 0, 0, 'n', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_new_game, "GameType" }, + { MN_BUTTON, 0, 0, 'o', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_options, "Options" }, { MN_BUTTON, 0, 0, 'l', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectLoadGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_load_game }, { MN_BUTTON, 0, 0, 's', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectSaveGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_save_game }, { MN_BUTTON, 0, 0, 'q', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectQuitGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_quit_game }, #else - { MN_BUTTON, 0, 0, 'n', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_new_game, &GameTypeMenu }, - { MN_BUTTON, 0, 0, 'o', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_options, &OptionsMenu }, - { MN_BUTTON, 0, 0, 'f', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_game_files, &FilesMenu }, + { MN_BUTTON, 0, 0, 'n', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_new_game, "GameType" }, + { MN_BUTTON, 0, 0, 'o', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_options, "Options" }, + { MN_BUTTON, 0, 0, 'f', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_game_files, "Files" }, { MN_BUTTON, 0, 0, 'i', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectHelp, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_help }, { MN_BUTTON, 0, 0, 'q', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectQuitGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_main_quit_game }, #endif { MN_NONE } }; -mn_page_t MainMenu = { - MainMenuObjects, -#if __JHEXEN__ || __JHERETIC__ - { 110, 56 }, -#else - { 97, 64 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawMainPage, -#if defined(__JDOOM__) && !defined(__JDOOM64__) - //0, 0, - //0, 6 -#else - //0, 0, - //0, 5 -#endif -}; - mndata_button_t btn_gametype_singleplayer = { false, NULL, (const char*)TXT_SINGLEPLAYER }; mndata_button_t btn_gametype_multiplayer = { false, NULL, (const char*)TXT_MULTIPLAYER }; @@ -387,49 +364,16 @@ mn_object_t GameTypeMenuObjects[] = { { MN_NONE } }; -mn_page_t GameTypeMenu = { - GameTypeMenuObjects, -#if __JDOOM__ || __JDOOM64__ - { 97, 65 }, -#else - { 104, 65 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawGameTypePage, NULL, - &MainMenu, - //0, 2 -}; - #if __JHEXEN__ mndata_mobjpreview_t mop_playerclass_preview; mn_object_t* PlayerClassMenuObjects; mndata_button_t* PlayerClassMenuButtons; - -mn_page_t PlayerClassMenu = { - 0, { 66, 66 }, { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawPlayerClassPage, NULL, - &GameTypeMenu, - //0, 0 -}; #endif #if __JDOOM__ || __JHERETIC__ mn_object_t* EpisodeMenuObjects; mndata_button_t* EpisodeMenuButtons; - -mn_page_t EpisodeMenu = { - 0, -# if __JDOOM__ - { 48, 63 }, -# else - { 80, 50 }, -# endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawEpisodePage, NULL, - &GameTypeMenu, - //0, 0 -}; #endif #if __JDOOM__ || __JDOOM64__ @@ -457,14 +401,6 @@ static mn_object_t SkillMenuObjects[] = { { MN_BUTTON, 0, MNF_ID4, 0, MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionInitNewGame, NULL, NULL, NULL, Hu_MenuFocusSkillMode }, MNButton_CommandResponder, NULL, NULL, &btn_skill_nightmare, NULL, SM_NIGHTMARE }, { MN_NONE } }; - -mn_page_t SkillMenu = { - SkillMenuObjects, - { 120, 44 }, { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawSkillPage, NULL, - &PlayerClassMenu, - //0, 5 -}; #elif __JHERETIC__ static mn_object_t SkillMenuObjects[] = { { MN_BUTTON, 0, MNF_ID0, 'w', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionInitNewGame, NULL, NULL, NULL, Hu_MenuFocusSkillMode }, MNButton_CommandResponder, NULL, NULL, &btn_skill_baby, NULL, SM_BABY }, @@ -474,14 +410,6 @@ static mn_object_t SkillMenuObjects[] = { { MN_BUTTON, 0, MNF_ID4, 'p', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionInitNewGame, NULL, NULL, NULL, Hu_MenuFocusSkillMode }, MNButton_CommandResponder, NULL, NULL, &btn_skill_nightmare, NULL, SM_NIGHTMARE }, { MN_NONE } }; - -mn_page_t SkillMenu = { - SkillMenuObjects, - { 38, 30 }, { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawSkillPage, NULL, - &EpisodeMenu, - //0, 5 -}; #elif __JDOOM64__ static mn_object_t SkillMenuObjects[] = { { MN_BUTTON, 0, MNF_ID0, 'g', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionInitNewGame, NULL, NULL, NULL, Hu_MenuFocusSkillMode }, MNButton_CommandResponder, NULL, NULL, &btn_skill_baby, NULL, SM_BABY }, @@ -490,13 +418,6 @@ static mn_object_t SkillMenuObjects[] = { { MN_BUTTON, 0, MNF_ID3, 'w', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionInitNewGame, NULL, NULL, NULL, Hu_MenuFocusSkillMode }, MNButton_CommandResponder, NULL, NULL, &btn_skill_hard, NULL, SM_HARD }, { MN_NONE } }; -static mn_page_t SkillMenu = { - SkillMenuObjects, - { 48, 63 }, { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawSkillPage, NULL, - &GameTypeMenu, - //0, 4 -}; #else static mn_object_t SkillMenuObjects[] = { { MN_BUTTON, 0, MNF_ID0, 'y', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionInitNewGame, NULL, NULL, NULL, Hu_MenuFocusSkillMode }, MNButton_CommandResponder, NULL, NULL, &btn_skill_baby, NULL, SM_BABY }, @@ -506,14 +427,6 @@ static mn_object_t SkillMenuObjects[] = { { MN_BUTTON, 0, MNF_ID4|MNF_NO_ALTTEXT, 'n', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionInitNewGame, NULL, NULL, NULL, Hu_MenuFocusSkillMode }, MNButton_CommandResponder, NULL, NULL, &btn_skill_nightmare, NULL, SM_NIGHTMARE }, { MN_NONE } }; - -mn_page_t SkillMenu = { - SkillMenuObjects, - { 48, 63 }, { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawSkillPage, NULL, - &EpisodeMenu, - //0, 5 -}; #endif #if __JHERETIC__ || __JHEXEN__ @@ -525,14 +438,6 @@ static mn_object_t FilesMenuObjects[] = { { MN_BUTTON, 0, 0, 's', MENU_FONT2, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectSaveGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_files_save_game }, { MN_NONE } }; - -mn_page_t FilesMenu = { - FilesMenuObjects, - { 110, 60 }, { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - NULL, NULL, - &MainMenu, - //0, 2 -}; #endif mndata_edit_t edit_saveslots[NUMSAVESLOTS] = { @@ -562,19 +467,6 @@ static mn_object_t LoadMenuObjects[] = { { MN_NONE } }; -mn_page_t LoadMenu = { - LoadMenuObjects, -#if __JDOOM__ || __JDOOM64__ - { 80, 54 }, -#else - { 70, 30 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawLoadGamePage, NULL, - &MainMenu, - //0, NUMSAVESLOTS -}; - static mn_object_t SaveMenuObjects[] = { { MN_EDIT, 0, MNF_ID0, '0', MENU_FONT1, MENU_COLOR1, MNEdit_UpdateGeometry, MNEdit_Drawer, { NULL, Hu_MenuSelectSaveSlot, Hu_MenuSaveSlotEdit, NULL, NULL, Hu_MenuDefaultFocusAction }, MNEdit_CommandResponder, MNEdit_Responder, NULL, &edit_saveslots[0], NULL, MNF_ID0 }, { MN_EDIT, 0, MNF_ID1, '1', MENU_FONT1, MENU_COLOR1, MNEdit_UpdateGeometry, MNEdit_Drawer, { NULL, Hu_MenuSelectSaveSlot, Hu_MenuSaveSlotEdit, NULL, NULL, Hu_MenuDefaultFocusAction }, MNEdit_CommandResponder, MNEdit_Responder, NULL, &edit_saveslots[1], NULL, MNF_ID1 }, @@ -589,19 +481,6 @@ static mn_object_t SaveMenuObjects[] = { { MN_NONE } }; -mn_page_t SaveMenu = { - SaveMenuObjects, -#if __JDOOM__ || __JDOOM64__ - { 80, 54 }, -#else - { 64, 10 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawSaveGamePage, NULL, - &MainMenu, - //0, 1+NUMSAVESLOTS -}; - mndata_button_t btn_options_end_game = { false, NULL, "End Game" }; mndata_button_t btn_options_control_panel = { false, NULL, "Control Panel" }; mndata_button_t btn_options_controls = { false, NULL, "Controls" }; @@ -619,38 +498,20 @@ mndata_button_t btn_options_joystick = { false, NULL, "Joystick" }; static mn_object_t OptionsMenuObjects[] = { { MN_BUTTON, 0, 0, 'e', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectEndGame, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_end_game }, { MN_BUTTON, 0, 0, 'p', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectControlPanelLink, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_control_panel }, - { MN_BUTTON, 0, 0, 'c', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_controls, &ControlsMenu }, - { MN_BUTTON, 0, 0, 'g', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_gameplay, &GameplayMenu }, - { MN_BUTTON, 0, 0, 'h', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_hud, &HudMenu }, - { MN_BUTTON, 0, 0, 'a', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_automap, &AutomapMenu }, - { MN_BUTTON, 0, 0, 'w', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_weapons, &WeaponMenu }, + { MN_BUTTON, 0, 0, 'c', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_controls, "ControlOptions" }, + { MN_BUTTON, 0, 0, 'g', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_gameplay, "GameplayOptions" }, + { MN_BUTTON, 0, 0, 'h', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_hud, "HudOptions" }, + { MN_BUTTON, 0, 0, 'a', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_automap, "AutomapOptions" }, + { MN_BUTTON, 0, 0, 'w', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_weapons, "WeaponOptions" }, #if __JHERETIC__ || __JHEXEN__ - { MN_BUTTON, 0, 0, 'i', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_inventory, &InventoryMenu }, + { MN_BUTTON, 0, 0, 'i', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_inventory, "InventoryOptions" }, #endif - { MN_BUTTON, 0, 0, 's', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_sound, &SoundMenu }, + { MN_BUTTON, 0, 0, 's', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuActionSetActivePage, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_sound, "SoundOptions" }, { MN_BUTTON, 0, 0, 'm', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectControlPanelLink, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_mouse, NULL, 2 }, { MN_BUTTON, 0, 0, 'j', MENU_FONT1, MENU_COLOR1, MNButton_UpdateGeometry, MNButton_Drawer, { NULL, Hu_MenuSelectControlPanelLink, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_options_joystick, NULL, 2 }, { MN_NONE } }; -mn_page_t OptionsMenu = { - OptionsMenuObjects, -#if __JHERETIC__ || __JHEXEN__ - { 110, 63 }, -#else - { 110, 63 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawOptionsPage, NULL, - &MainMenu, - //0, -#if __JHERETIC__ || __JHEXEN__ - //11 -#else - //10 -#endif -}; - mndata_slider_t sld_sound_sfx_volume = { 0, 255, 0, 5, false, "sound-volume" }; mndata_slider_t sld_sound_music_volume = { 0, 255, 0, 5, false, "music-volume" }; @@ -668,21 +529,6 @@ mn_object_t SoundMenuObjects[] = { { MN_NONE } }; -mn_page_t SoundMenu = { - SoundMenuObjects, -#if __JHEXEN__ - { 97, 25 }, -#elif __JHERETIC__ - { 97, 30 }, -#elif __JDOOM__ || __JDOOM64__ - { 97, 40 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawSoundPage, NULL, - &OptionsMenu, - //0, 5 -}; - #if __JDOOM64__ mndata_slider_t sld_hud_viewsize = { 3, 11, 0, 1, false, "view-size" }; #else @@ -968,27 +814,6 @@ static mn_object_t HudMenuObjects[] = { { MN_NONE } }; -mn_page_t HudMenu = { - HudMenuObjects, -#if __JDOOM__ || __JDOOM64__ - { 97, 40 }, -#else - { 97, 28 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawHudPage, NULL, - &OptionsMenu, -#if __JHEXEN__ - //0, 15 // 21 -#elif __JHERETIC__ - //0, 15 // 23 -#elif __JDOOM64__ - //0, 19 -#elif __JDOOM__ - //0, 19 -#endif -}; - #if __JHERETIC__ || __JHEXEN__ mndata_slider_t sld_inv_uptime = { 0, 30, 0, 1.f, true, "hud-inventory-timer", "Disabled", NULL, " second", " seconds" }; mndata_slider_t sld_inv_maxvisslots = { 0, 16, 0, 1, false, "hud-inventory-slot-max", "Automatic" }; @@ -1027,14 +852,6 @@ static mn_object_t InventoryMenuObjects[] = { { MN_BUTTON, 1, 0, 'e',MENU_FONT1, MENU_COLOR3, MNButton_UpdateGeometry, MNButton_Drawer, { Hu_MenuCvarButton, NULL, NULL, NULL, NULL, Hu_MenuDefaultFocusAction }, MNButton_CommandResponder, NULL, NULL, &btn_inv_full_show_empty_slots }, { MN_NONE } }; - -mn_page_t InventoryMenu = { - InventoryMenuObjects, - { 78, 48 }, { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawInventoryPage, NULL, - &OptionsMenu, - //0, 12, { 12, 48 } -}; #endif mndata_listitem_t listit_weapons_order[NUM_WEAPON_TYPES] = { @@ -1136,21 +953,6 @@ static mn_object_t WeaponMenuObjects[] = { { MN_NONE } }; -mn_page_t WeaponMenu = { - WeaponMenuObjects, -#if __JDOOM__ || __JDOOM64__ - { 78, 40 }, -#elif __JHERETIC__ - { 78, 26 }, -#elif __JHEXEN__ - { 78, 38 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawWeaponsPage, NULL, - &OptionsMenu, - //0, 12, { 12, 38 } -}; - mndata_slider_t sld_map_opacity = { 0, 1, 0, 0.1f, true, "map-opacity" }; mndata_slider_t sld_map_lineopacity = { 0, 1, 0, 0.1f, true, "map-alpha-lines" }; mndata_slider_t sld_map_doorglow = { 0, 200, 0, 5, true, "map-door-glow" }; @@ -1241,23 +1043,6 @@ mn_object_t AutomapMenuObjects[] = { { MN_NONE } }; -mn_page_t AutomapMenu = { - AutomapMenuObjects, -#if __JHERETIC__ || __JHEXEN__ - { 64, 28 }, -#else - { 70, 40 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawAutomapPage, NULL, - &OptionsMenu, -#if __JHERETIC__ || __JHEXEN__ - //0, 11, { 11, 28 } -#else - //0, 13, { 13, 40 } -#endif -}; - mndata_text_t txt_gameplay_always_run = { "Always Run" }; mndata_text_t txt_gameplay_use_lookspring = { "Use LookSpring" }; mndata_text_t txt_gameplay_use_autoaim = { "Use AutoAim" }; @@ -1375,29 +1160,6 @@ static mn_object_t GameplayMenuObjects[] = { { MN_NONE } }; -mn_page_t GameplayMenu = { - GameplayMenuObjects, -#if __JHEXEN__ - { 88, 25 }, -#elif __JHERETIC__ - { 30, 40 }, -#else - { 30, 40 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawGameplayPage, NULL, - &OptionsMenu, -#if __JHEXEN__ - //0, 6, { 6, 25 } -#elif __JDOOM64__ - //0, 16, { 16, 40 } -#elif __JDOOM__ - //0, 18, { 18, 40 } -#else - //0, 11, { 11, 40 } -#endif -}; - mndata_button_t btn_multiplayer_join_game = { false, NULL, "Join Game" }; mndata_button_t btn_multiplayer_player_setup = { false, NULL, "Player Setup" }; @@ -1407,19 +1169,6 @@ mn_object_t MultiplayerMenuObjects[] = { { MN_NONE } }; -mn_page_t MultiplayerMenu = { - MultiplayerMenuObjects, -#if __JHERETIC__ || __JHEXEN__ - { 97, 65 }, -#else - { 97, 65 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawMultiplayerPage, NULL, - &GameTypeMenu, - //0, 2 -}; - mndata_mobjpreview_t mop_player_preview; mndata_edit_t edit_player_name = { "", "", 0, NULL, "net-name" }; @@ -1484,23 +1233,6 @@ mn_object_t PlayerSetupMenuObjects[] = { { MN_NONE } }; -mn_page_t PlayerSetupMenu = { - PlayerSetupMenuObjects, -#if __JHERETIC__ || __JHEXEN__ - { 70, 54 }, -#else - { 70, 54 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawPlayerSetupPage, NULL, - &MultiplayerMenu, -#if __JHEXEN__ - //0, 7 -#else - //0, 5 -#endif -}; - mndata_slider_t sld_colorwidget_red = { 0, 1, 0, .05f, true }; @@ -1536,51 +1268,15 @@ static mn_object_t ColorWidgetMenuObjects[] = { { MN_NONE } }; -static mn_page_t ColorWidgetMenu = { - ColorWidgetMenuObjects, -#if __JHERETIC__ || __JHEXEN__ - { 98, 60 }, -#else - { 98, 60 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - NULL, Hu_MenuColorWidgetCmdResponder, - &OptionsMenu, - //0, 8 -}; - static boolean inited = false; -static mn_page_t* pages[] = { - &MainMenu, - &GameTypeMenu, -#if __JHEXEN__ - &PlayerClassMenu, -#endif -#if __JDOOM__ || __JHERETIC__ - &EpisodeMenu, -#endif - &SkillMenu, - &MultiplayerMenu, - &PlayerSetupMenu, -#if __JHERETIC__ || __JHEXEN__ - &FilesMenu, -#endif - &LoadMenu, - &SaveMenu, - &OptionsMenu, - &ControlsMenu, - &GameplayMenu, - &HudMenu, - &AutomapMenu, - &WeaponMenu, -#if __JHERETIC__ || __JHEXEN__ - &InventoryMenu, -#endif - &SoundMenu, - &ColorWidgetMenu, - NULL -}; +typedef struct { + mn_page_t* page; + ddstring_t name; // Symbolic name. +} pagerecord_t; + +static int pageCount; +static pagerecord_t* pages; // Cvars for the menu: cvartemplate_t menuCVars[] = { @@ -1650,46 +1346,18 @@ static boolean chooseCloseMethod(void) return Con_GetInteger("con-transition-tics") == 0? MCMD_CLOSE : MCMD_CLOSEFAST; } -mn_page_t* Hu_MenuFindPageForName(const char* name) +mn_page_t* Hu_MenuFindPageByName(const char* name) { - const struct pagename_pair_s { - mn_page_t* page; - const char* name; - } pairs[] = { - { &MainMenu, "Main" }, - { &GameTypeMenu, "GameType" }, -#if __JHEXEN__ - { &PlayerClassMenu, "PlayerClass" }, -#endif -#if __JDOOM__ || __JHERETIC__ - { &EpisodeMenu, "Episode" }, -#endif - { &SkillMenu, "Skill" }, - { &OptionsMenu, "Options" }, - { &SoundMenu, "SoundOptions" }, - { &GameplayMenu, "GameplayOptions" }, - { &HudMenu, "HudOptions" }, - { &AutomapMenu, "AutomapOptions" }, -#if __JHERETIC__ || __JHEXEN__ - { &FilesMenu, "Files" }, -#endif - { &LoadMenu, "LoadGame" }, - { &SaveMenu, "SaveGame" }, - { &MultiplayerMenu, "Multiplayer" }, - { &PlayerSetupMenu, "PlayerSetup" }, -#if __JHERETIC__ || __JHEXEN__ - { &InventoryMenu, "InventoryOptions" }, -#endif - { &WeaponMenu, "WeaponOptions" }, - { &ControlsMenu, "ControlOptions" }, - { NULL } - }; - size_t i; - for(i = 0; pairs[i].page; ++i) + if(name && name[0]) { - if(!stricmp(name, pairs[i].name)) + int i; + for(i = 0; i < pageCount; ++i) { - return pairs[i].page; + pagerecord_t* rec = pages + i; + if(!stricmp(name, Str_Text(&rec->name))) + { + return rec->page; + } } } return NULL; @@ -1713,7 +1381,7 @@ static void Hu_MenuUpdateCursorState(void) mn_object_t* obj; if(colorWidgetActive) - page = &ColorWidgetMenu; + page = Hu_MenuFindPageByName("ColorWidget"); else page = Hu_MenuActivePage(); @@ -1727,14 +1395,6 @@ static void Hu_MenuUpdateCursorState(void) cursorHasRotation = false; } -void Hu_MenuComposeSubpageString(mn_page_t* page, size_t bufSize, char* buf) -{ - assert(page); - if(!buf || 0 == bufSize) return; - dd_snprintf(buf, bufSize, "PAGE %i/%i", 0, 0/*(page->firstObject + page->numVisObjects/2) / page->numVisObjects + 1, - (int)ceil((float)page->objectsCount/page->numVisObjects)*/); -} - void Hu_MenuLoadResources(void) { char buffer[9]; @@ -1815,6 +1475,14 @@ void Hu_MenuLoadResources(void) void Hu_MenuInitSkillMenu(void) { +#if __JHEXEN__ + const Point2Raw origin = { 120, 44 }; +#elif __JHERETIC__ + const Point2Raw origin = { 38, 30 }; +#else + const Point2Raw origin = { 48, 63 }; +#endif + mn_page_t* page; #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ struct skillbutton_s { int pageObjectId; @@ -1829,10 +1497,32 @@ void Hu_MenuInitSkillMenu(void) # endif }; int i; +#endif + + page = Hu_MenuNewPage("Skill", &origin, Hu_MenuDrawSkillPage, NULL, NULL); + page->objects = SkillMenuObjects; +#if __JHEXEN__ + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("PlayerClass")); +#elif __JHERETIC__ + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Episode")); +#elif __JDOOM64__ + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); +#else // __JDOOM__ + if(gameModeBits & (GM_ANY_DOOM2|GM_DOOM_CHEX)) + { + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + } + else + { + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Episode")); + } +#endif + +#if __JDOOM__ || __JDOOM64__ || __JHERETIC__ for(i = 0; i < NUM_SKILL_MODES; ++i) { const struct skillbutton_s* sb = &skillButtons[i]; - mn_object_t* obj = MN_MustFindObjectOnPage(&SkillMenu, 0, sb->pageObjectId); + mn_object_t* obj = MN_MustFindObjectOnPage(page, 0, sb->pageObjectId); mndata_button_t* btn = (mndata_button_t*)obj->_typedata; btn->text = GET_TXT(sb->textDefId); @@ -1862,8 +1552,22 @@ static int compareWeaponPriority(const void* _a, const void* _b) void Hu_MenuInitWeaponsMenu(void) { +#if __JDOOM__ || __JDOOM64__ + const Point2Raw origin = { 78, 40 }; +#elif __JHERETIC__ + const Point2Raw origin = { 78, 26 }; +#elif __JHEXEN__ + const Point2Raw origin = { 78, 38 }; +#endif + mn_page_t* page; + qsort(listit_weapons_order, NUMLISTITEMS(listit_weapons_order), sizeof(listit_weapons_order[0]), compareWeaponPriority); + + page = Hu_MenuNewPage("WeaponOptions", &origin, Hu_MenuDrawWeaponsPage, NULL, NULL); + MNPage_SetTitle(page, "Weapons Options"); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->objects = WeaponMenuObjects; } #if __JDOOM__ || __JHERETIC__ @@ -1872,9 +1576,15 @@ void Hu_MenuInitWeaponsMenu(void) */ void Hu_MenuInitEpisodeMenu(void) { +#if __JDOOM__ + const Point2Raw origin = { 48, 63 }; +#else + const Point2Raw origin = { 80, 50 }; +#endif int i, numEpisodes; mn_object_t* obj; mndata_button_t* btn; + mn_page_t* page; #if __JDOOM__ if(gameModeBits & (GM_ANY_DOOM2|GM_DOOM_CHEX)) @@ -1922,7 +1632,7 @@ void Hu_MenuInitEpisodeMenu(void) else { obj->actions[MNA_ACTIVEOUT].callback = Hu_MenuActionSetActivePage; - obj->data1 = &SkillMenu; + obj->data1 = "Skill"; #if __JHERETIC__ if(gameMode == heretic_extended && i == 5) { @@ -1939,8 +1649,9 @@ void Hu_MenuInitEpisodeMenu(void) } obj->_type = MN_NONE; - // Finalize setup. - EpisodeMenu.objects = EpisodeMenuObjects; + page = Hu_MenuNewPage("Episode", &origin, Hu_MenuDrawEpisodePage, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + page->objects = EpisodeMenuObjects; } #endif @@ -1950,9 +1661,11 @@ void Hu_MenuInitEpisodeMenu(void) */ void Hu_MenuInitPlayerClassMenu(void) { + const Point2Raw pageOrigin = { 66, 66 }; + mndata_button_t* btn; uint i, n, count; mn_object_t* obj; - mndata_button_t* btn; + mn_page_t* page; // First determine the number of selectable player classes. count = 0; @@ -2019,10 +1732,79 @@ void Hu_MenuInitPlayerClassMenu(void) // Terminate. obj->_type = MN_NONE; - // Finalize setup. - PlayerClassMenu.objects = PlayerClassMenuObjects; + page = Hu_MenuNewPage("PlayerClass", &pageOrigin, Hu_MenuDrawPlayerClassPage, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + page->objects = PlayerClassMenuObjects; +} +#endif + +mn_page_t* MNPage_New(const Point2Raw* origin, + void (*drawer) (struct mn_page_s* page, const Point2Raw* origin), + int (*cmdResponder) (struct mn_page_s* page, menucommand_e cmd), + void* userData) +{ + mn_page_t* page = (mn_page_t*) malloc(sizeof(*page)); + if(!page) Con_Error("MNPage::New: Failed on allocation of %lu bytes for new MenuPage.", (unsigned long) sizeof(*page)); + + page->origin.x = origin? origin->x : 0; + page->origin.y = origin? origin->y : 0; + + page->objects = NULL; + page->objectsCount = 0; + + page->drawer = drawer; + page->cmdResponder = cmdResponder; + page->previous = NULL; + page->userData = userData; + + Str_Init(&page->title); + + memset(page->fonts, 0, sizeof(page->fonts)); + page->fonts[0] = FID(GF_FONTA); + page->fonts[1] = FID(GF_FONTB); + + memset(page->colors, 0, sizeof(page->colors)); + page->colors[0] = 0; + page->colors[1] = 1; + page->colors[2] = 2; + + page->focus = -1; /// \fixme Make this a page flag. + page->geometry = Rect_New(); + + return page; } + +static mn_page_t* addPageToCollection(mn_page_t* page, const char* name) +{ + if(page) + { + pagerecord_t* rec; + + pages = (pagerecord_t*)realloc(pages, sizeof(*pages) * ++pageCount); + if(!pages) Con_Error("addPageToCollection: Failed on (re)allocation of %lu bytes enlarging Pages collection.", (unsigned long) sizeof(*pages) * pageCount); + + rec = &pages[pageCount-1]; + rec->page = page; + Str_Init(&rec->name); Str_Set(&rec->name, name); + } + return page; +} + +mn_page_t* Hu_MenuNewPage(const char* name, const Point2Raw* origin, + void (*drawer) (struct mn_page_s* page, const Point2Raw* origin), + int (*cmdResponder) (struct mn_page_s* page, menucommand_e cmd), + void* userData) +{ + if(!name || !name[0]) + { +#if _DEBUG + Con_Message("Warning: Hu_MenuNewPage: Attempt to create page with invalid name '%s', ignoring.\n", name); #endif + return NULL; + } + + return addPageToCollection(MNPage_New(origin, drawer, cmdResponder, userData), name); +} void Hu_MenuInit(void) { @@ -2030,6 +1812,9 @@ void Hu_MenuInit(void) if(inited) return; + pageCount = 0; + pages = NULL; + mnAlpha = mnTargetAlpha = 0; menuActivePage = NULL; menuActive = false; @@ -2042,16 +1827,6 @@ void Hu_MenuInit(void) Hu_MenuLoadResources(); - Hu_MenuInitSkillMenu(); -#if __JDOOM__ || __JHERETIC__ - Hu_MenuInitEpisodeMenu(); -#endif -#if __JHEXEN__ - Hu_MenuInitPlayerClassMenu(); -#endif - Hu_MenuInitControlsPage(); - Hu_MenuInitWeaponsMenu(); - // Set default Yes/No strings. for(cvb = mnCVarButtons; cvb->cvarname; cvb++) { @@ -2059,18 +1834,14 @@ void Hu_MenuInit(void) if(!cvb->no) cvb->no = "No"; } + initAllPages(); initAllObjectsOnAllPages(); #if __JDOOM__ if(gameModeBits & GM_ANY_DOOM2) { - mn_object_t* obj = MN_MustFindObjectOnPage(&MainMenu, 0, MNF_ID0); // Read This! + mn_object_t* obj = MN_MustFindObjectOnPage(Hu_MenuFindPageByName("Main"), 0, MNF_ID0); // Read This! MNObject_SetFlags(obj, FO_SET, MNF_DISABLED|MNF_HIDDEN|MNF_NO_FOCUS); - MainMenu.origin.y += 8; - } - if(gameModeBits & (GM_ANY_DOOM2|GM_DOOM_CHEX)) - { - SkillMenu.previous = &GameTypeMenu; } #endif @@ -2081,7 +1852,7 @@ void Hu_MenuShutdown(void) { if(!inited) return; - destroyAllObjectsOnAllPages(); + destroyAllPages(); inited = false; } @@ -2256,7 +2027,7 @@ void Hu_MenuDrawFocusCursor(int x, int y, int focusObjectHeight, float alpha) void Hu_MenuDrawPageTitle(const char* title, int x, int y) { - if(!title) return; + if(!title || !title[0]) return; DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(FID(GF_FONTB)); @@ -2268,37 +2039,18 @@ void Hu_MenuDrawPageTitle(const char* title, int x, int y) DGL_Disable(DGL_TEXTURE_2D); } -void Hu_MenuDrawPageNavigation(mn_page_t* page, int x, int y) +void Hu_MenuDrawPageHelp(const char* help, int x, int y) { -#if __JDOOM__ || __JDOOM64__ - char buf[1024]; - - if(!page) return; - - Hu_MenuComposeSubpageString(page, 1024, buf); + if(!help || !help[0]) return; DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(FID(GF_FONTA)); FR_SetColorv(cfg.menuTextColors[1]); FR_SetAlpha(mnRendState->pageAlpha); - FR_DrawTextXY3(buf, x, y, ALIGN_TOP, MN_MergeMenuEffectWithDrawTextFlags(0)); - - DGL_Disable(DGL_TEXTURE_2D); -#else - const boolean havePrevPage = true;//page->firstObject; - const boolean haveNextPage = true;//!(page->firstObject + page->numVisObjects >= page->objectsCount); - - if(!page) return; - - DGL_Enable(DGL_TEXTURE_2D); - DGL_Color4f(1, 1, 1, mnRendState->pageAlpha); - - GL_DrawPatchXY2( pInvPageLeft[!havePrevPage || (menuTime & 8)], x - 144, y, ALIGN_RIGHT); - GL_DrawPatchXY2(pInvPageRight[!haveNextPage || (menuTime & 8)], x + 144, y, ALIGN_LEFT); + FR_DrawTextXY3(help, x, y, ALIGN_BOTTOM, MN_MergeMenuEffectWithDrawTextFlags(0)); DGL_Disable(DGL_TEXTURE_2D); -#endif } static void drawOverlayBackground(float darken) @@ -2382,7 +2134,7 @@ void Hu_MenuDrawer(void) } else { - MN_DrawPage(&ColorWidgetMenu, 1, true); + MN_DrawPage(Hu_MenuFindPageByName("ColorWidget"), 1, true); } endOverlayDraw(); @@ -2426,26 +2178,18 @@ void Hu_MenuNavigatePage(mn_page_t* page, int pageDelta) #endif } -static void initPage(mn_page_t* page) +static void initPageObjects(mn_page_t* page) { mn_object_t* obj; - int i; assert(page); - page->geometry = Rect_New(); - - page->focus = -1; /// \fixme Make this a page flag. - page->objectsCount = MN_CountObjects(page->objects); - - for(i = 0; i < (int)MENU_FONT_COUNT; ++i) - { - if(0 == (gamefontid_t)page->fonts[i]) continue; - page->fonts[i] = FID((gamefontid_t)page->fonts[i]); - } + page->objectsCount = 0; - // Init objects. for(obj = page->objects; MNObject_Type(obj) != MN_NONE; obj++) { + page->objectsCount += 1; + + obj->_page = page; obj->_geometry = Rect_New(); MNObject_SetFlags(obj, FO_CLEAR, MNF_FOCUS); @@ -2543,16 +2287,7 @@ static void initPage(mn_page_t* page) } } -static void initAllObjectsOnAllPages(void) -{ - mn_page_t** pageIt; - for(pageIt = pages; *pageIt; pageIt++) - { - initPage(*pageIt); - } -} - -static void destroyPage(mn_page_t* page) +static void destroyPageObjects(mn_page_t* page) { mn_object_t* obj; if(!page) return; @@ -2564,19 +2299,240 @@ static void destroyPage(mn_page_t* page) obj->_geometry = NULL; } } +} + +static void destroyPage(mn_page_t* page) +{ + if(!page) return; + + destroyPageObjects(page); + + Str_Free(&page->title); + if(page->geometry) { Rect_Delete(page->geometry); page->geometry = NULL; } + + free(page); } -static void destroyAllObjectsOnAllPages(void) +static void initAllPages(void) { - mn_page_t** pageIt; - for(pageIt = pages; *pageIt; pageIt++) + mn_page_t* page; + { - destroyPage(*pageIt); +#if __JHERETIC__ || __JHEXEN__ + const Point2Raw origin = { 98, 60 }; +#else + const Point2Raw origin = { 98, 60 }; +#endif + + page = Hu_MenuNewPage("ColorWidget", &origin, NULL, Hu_MenuColorWidgetCmdResponder, NULL); + page->objects = ColorWidgetMenuObjects; + } + + { +#if __JHEXEN__ || __JHERETIC__ + Point2Raw origin = { 110, 56 }; +#else + Point2Raw origin = { 97, 64 }; +#endif + //{ (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, + +#if __JDOOM__ + if(gameModeBits & GM_ANY_DOOM2) + origin.y += 8; +#endif + + page = Hu_MenuNewPage("Main", &origin, Hu_MenuDrawMainPage, NULL, NULL); + page->objects = MainMenuObjects; + } + + { +#if __JDOOM__ || __JDOOM64__ + Point2Raw origin = { 97, 65 }; +#else + Point2Raw origin = { 104, 65 }; +#endif + + page = Hu_MenuNewPage("GameType", &origin, Hu_MenuDrawGameTypePage, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); + page->objects = GameTypeMenuObjects; + } + +#if __JDOOM__ || __JHERETIC__ + Hu_MenuInitEpisodeMenu(); +#endif +#if __JHEXEN__ + Hu_MenuInitPlayerClassMenu(); +#endif + + Hu_MenuInitSkillMenu(); + + { +#if __JHERETIC__ || __JHEXEN__ + const Point2Raw origin = { 97, 65 }; +#else + const Point2Raw origin = { 97, 65 }; +#endif + + page = Hu_MenuNewPage("Multiplayer", &origin, Hu_MenuDrawMultiplayerPage, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + page->objects = MultiplayerMenuObjects; + } + + { +#if __JHERETIC__ || __JHEXEN__ + const Point2Raw origin = { 70, 54 }; +#else + const Point2Raw origin = { 70, 54 }; +#endif + + page = Hu_MenuNewPage("PlayerSetup", &origin, Hu_MenuDrawPlayerSetupPage, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Multiplayer")); + page->objects = PlayerSetupMenuObjects; + } + +#if __JHERETIC__ || __JHEXEN__ + { + Point2Raw origin = { 110, 60 }; + + page = Hu_MenuNewPage("Files", &origin, NULL, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); + page->objects = FilesMenuObjects; + } +#endif + + { +#if __JDOOM__ || __JDOOM64__ + const Point2Raw origin = { 80, 54 }; +#else + const Point2Raw origin = { 70, 30 }; +#endif + + page = Hu_MenuNewPage("LoadGame", &origin, Hu_MenuDrawLoadGamePage, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); + page->objects = LoadMenuObjects; + } + + { +#if __JDOOM__ || __JDOOM64__ + const Point2Raw origin = { 80, 54 }; +#else + const Point2Raw origin = { 64, 10 }; +#endif + + page = Hu_MenuNewPage("SaveGame", &origin, Hu_MenuDrawSaveGamePage, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); + page->objects = SaveMenuObjects; + } + + { +#if __JHERETIC__ || __JHEXEN__ + const Point2Raw origin = { 110, 63 }; +#else + const Point2Raw origin = { 110, 63 }; +#endif + + page = Hu_MenuNewPage("Options", &origin, Hu_MenuDrawOptionsPage, NULL, NULL); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); + page->objects = OptionsMenuObjects; + } + + { +#if __JHEXEN__ + const Point2Raw origin = { 88, 25 }; +#elif __JHERETIC__ + const Point2Raw origin = { 30, 40 }; +#else + const Point2Raw origin = { 30, 40 }; +#endif + + page = Hu_MenuNewPage("GameplayOptions", &origin, NULL, NULL, NULL); + MNPage_SetTitle(page, "Gameplay Options"); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->objects = GameplayMenuObjects; + } + + { +#if __JDOOM__ || __JDOOM64__ + const Point2Raw origin = { 97, 40 }; +#else + const Point2Raw origin = { 97, 28 }; +#endif + + page = Hu_MenuNewPage("HudOptions", &origin, NULL, NULL, NULL); + MNPage_SetTitle(page, "HUD Options"); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->objects = HudMenuObjects; + } + + { +#if __JHERETIC__ || __JHEXEN__ + const Point2Raw origin = { 64, 28 }; +#else + const Point2Raw origin = { 70, 40 }; +#endif + + page = Hu_MenuNewPage("AutomapOptions", &origin, NULL, NULL, NULL); + MNPage_SetTitle(page, "Automap Options"); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->objects = AutomapMenuObjects; + } + + Hu_MenuInitWeaponsMenu(); + +#if __JHERETIC__ || __JHEXEN__ + { + const Point2Raw origin = { 78, 48 }; + + page = Hu_MenuNewPage("InventoryOptions", &origin, NULL, NULL, NULL); + MNPage_SetTitle(page, "Inventory Options"); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->objects = InventoryMenuObjects; + } +#endif + + { +#if __JHEXEN__ + const Point2Raw origin = { 97, 25 }; +#elif __JHERETIC__ + const Point2Raw origin = { 97, 30 }; +#elif __JDOOM__ || __JDOOM64__ + const Point2Raw origin = { 97, 40 }; +#endif + + page = Hu_MenuNewPage("SoundOptions", &origin, NULL, NULL, NULL); + MNPage_SetTitle(page, "Sound Options"); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->objects = SoundMenuObjects; + } + + Hu_MenuInitControlsPage(); +} + +static void destroyAllPages(void) +{ + int i; + if(!pages) return; + for(i = 0; i < pageCount; ++i) + { + pagerecord_t* rec = pages + i; + destroyPage(rec->page); + Str_Free(&rec->name); + } + free(pages); +} + +static void initAllObjectsOnAllPages(void) +{ + int i; + for(i = 0; i < pageCount; ++i) + { + pagerecord_t* rec = pages + i; + initPageObjects(rec->page); } } @@ -2586,7 +2542,7 @@ int Hu_MenuColorWidgetCmdResponder(mn_page_t* page, menucommand_e cmd) switch(cmd) { case MCMD_NAV_OUT: { - mn_object_t* obj = (mn_object_t*)page->data; + mn_object_t* obj = (mn_object_t*)page->userData; MNObject_SetFlags(obj, FO_CLEAR, MNF_ACTIVE); S_LocalSound(SFX_MENU_CANCEL, NULL); colorWidgetActive = false; @@ -2601,11 +2557,11 @@ int Hu_MenuColorWidgetCmdResponder(mn_page_t* page, menucommand_e cmd) case MCMD_NAV_PAGEDOWN: return true; // Eat these. case MCMD_SELECT: { - mn_object_t* obj = (mn_object_t*)page->data; + mn_object_t* obj = (mn_object_t*)page->userData; MNObject_SetFlags(obj, FO_CLEAR, MNF_ACTIVE); S_LocalSound(SFX_MENU_ACCEPT, NULL); colorWidgetActive = false; - MNColorBox_CopyColor(obj, 0, MN_MustFindObjectOnPage(&ColorWidgetMenu, 0, MNF_ID0)); + MNColorBox_CopyColor(obj, 0, MN_MustFindObjectOnPage(page, 0, MNF_ID0)); /// \kludge We should re-focus on the object instead. cursorAngle = 0; // Stop cursor rotation animation dead (don't rewind). @@ -2711,7 +2667,7 @@ void Hu_MenuCommand(menucommand_e cmd) // Determine the page which will respond to this command. if(colorWidgetActive) - page = &ColorWidgetMenu; + page = Hu_MenuFindPageByName("ColorWidget"); else page = Hu_MenuActivePage(); @@ -2769,7 +2725,7 @@ void Hu_MenuCommand(menucommand_e cmd) Hu_MenuSetAlpha(1); menuActive = true; menuTime = 0; - Hu_MenuSetActivePage(&MainMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("Main")); // Enable the menu binding class DD_Execute(true, "activatebcontext menu"); @@ -2863,10 +2819,13 @@ int Hu_MenuSelectLoadSlot(mn_object_t* obj, mn_actionid_t action, void* paramate { mndata_edit_t* edit = (mndata_edit_t*)obj->_typedata; const int saveSlot = edit->data2; + mn_page_t* saveGamePage; if(MNA_ACTIVEOUT != action) return 1; - MNPage_SetFocus(&SaveMenu, MNPage_FindObject(&SaveMenu, 0, obj->data2)); + saveGamePage = Hu_MenuFindPageByName("SaveGame"); + MNPage_SetFocus(saveGamePage, MNPage_FindObject(saveGamePage, 0, obj->data2)); + G_LoadGame(saveSlot); Hu_MenuCommand(chooseCloseMethod()); return 0; @@ -2971,6 +2930,8 @@ void Hu_MenuDrawPlayerClassPage(mn_page_t* page, const Point2Raw* origin) DGL_Color4f(1, 1, 1, mnRendState->pageAlpha); GL_DrawPatchXY(pPlayerClassBG[pClass % 3], origin->x + BG_X, origin->y + BG_Y); + DGL_Disable(DGL_TEXTURE_2D); + #undef BG_X #undef BG_Y } @@ -2985,17 +2946,14 @@ void Hu_MenuDrawEpisodePage(mn_page_t* page, const Point2Raw* origin) if(obj && obj == MNPage_FocusObject(page)) { const char* str = notDesignedForMessage; + Point2Raw origin; composeNotDesignedForMessage(GET_TXT(TXT_SINGLEPLAYER)); - DGL_Enable(DGL_TEXTURE_2D); - FR_SetFont(FID(GF_FONTA)); - FR_SetColorv(cfg.menuTextColors[1]); - FR_SetAlpha(mnRendState->pageAlpha); + origin.x = SCREENWIDTH/2; + origin.y = (SCREENHEIGHT/2) + ((SCREENHEIGHT/2-5)/cfg.menuScale); - FR_DrawTextXY3(str, SCREENWIDTH/2, SCREENHEIGHT - 2, ALIGN_BOTTOM, MN_MergeMenuEffectWithDrawTextFlags(0)); - - DGL_Disable(DGL_TEXTURE_2D); + Hu_MenuDrawPageHelp(notDesignedForMessage, origin.x, origin.y); } #else // __JDOOM__ DGL_Enable(DGL_TEXTURE_2D); @@ -3040,6 +2998,7 @@ void Hu_MenuUpdateGameSaveWidgets(void) MNF_ID6, MNF_ID7 #endif }; + mn_page_t* page; int i; if(!menuActive) return; @@ -3050,9 +3009,10 @@ void Hu_MenuUpdateGameSaveWidgets(void) SV_UpdateGameSaveInfo(); // Update widgets. + page = Hu_MenuFindPageByName("LoadGame"); for(i = 0; i < NUMSAVESLOTS; ++i) { - mn_object_t* obj = MN_MustFindObjectOnPage(&LoadMenu, 0, saveSlotObjectIds[i]); + mn_object_t* obj = MN_MustFindObjectOnPage(page, 0, saveSlotObjectIds[i]); mndata_edit_t* edit = (mndata_edit_t*) obj->_typedata; const gamesaveinfo_t* info = SV_GetGameSaveInfoForSlot(edit->data2); const char* text = ""; @@ -3075,6 +3035,7 @@ int Hu_MenuSelectSaveSlot(mn_object_t* obj, mn_actionid_t action, void* paramate mndata_edit_t* edit = (mndata_edit_t*)obj->_typedata; const int saveSlot = edit->data2; const char* saveName = MNEdit_Text(obj); + mn_page_t* page; if(MNA_ACTIVEOUT != action) return 1; @@ -3086,8 +3047,12 @@ int Hu_MenuSelectSaveSlot(mn_object_t* obj, mn_actionid_t action, void* paramate if(!G_SaveGame2(saveSlot, saveName)) return 0; - MNPage_SetFocus(&SaveMenu, MN_MustFindObjectOnPage(&SaveMenu, 0, obj->data2)); - MNPage_SetFocus(&LoadMenu, MN_MustFindObjectOnPage(&LoadMenu, 0, obj->data2)); + page = Hu_MenuFindPageByName("SaveGame"); + MNPage_SetFocus(page, MN_MustFindObjectOnPage(page, 0, obj->data2)); + + page = Hu_MenuFindPageByName("LoadGame"); + MNPage_SetFocus(page, MN_MustFindObjectOnPage(page, 0, obj->data2)); + Hu_MenuCommand(chooseCloseMethod()); return 0; } @@ -3242,20 +3207,21 @@ int Hu_MenuCvarSlider(mn_object_t* obj, mn_actionid_t action, void* paramaters) int Hu_MenuActivateColorWidget(mn_object_t* obj, mn_actionid_t action, void* paramaters) { mn_object_t* cboxMix, *sldrRed, *sldrGreen, *sldrBlue, *textAlpha, *sldrAlpha; + mn_page_t* colorWidgetPage = Hu_MenuFindPageByName("ColorWidget"); if(action != MNA_ACTIVE) return 1; - cboxMix = MN_MustFindObjectOnPage(&ColorWidgetMenu, 0, MNF_ID0); - sldrRed = MN_MustFindObjectOnPage(&ColorWidgetMenu, 0, MNF_ID1); - sldrGreen = MN_MustFindObjectOnPage(&ColorWidgetMenu, 0, MNF_ID2); - sldrBlue = MN_MustFindObjectOnPage(&ColorWidgetMenu, 0, MNF_ID3); - textAlpha = MN_MustFindObjectOnPage(&ColorWidgetMenu, 0, MNF_ID4); - sldrAlpha = MN_MustFindObjectOnPage(&ColorWidgetMenu, 0, MNF_ID5); + cboxMix = MN_MustFindObjectOnPage(colorWidgetPage, 0, MNF_ID0); + sldrRed = MN_MustFindObjectOnPage(colorWidgetPage, 0, MNF_ID1); + sldrGreen = MN_MustFindObjectOnPage(colorWidgetPage, 0, MNF_ID2); + sldrBlue = MN_MustFindObjectOnPage(colorWidgetPage, 0, MNF_ID3); + textAlpha = MN_MustFindObjectOnPage(colorWidgetPage, 0, MNF_ID4); + sldrAlpha = MN_MustFindObjectOnPage(colorWidgetPage, 0, MNF_ID5); colorWidgetActive = true; - MNPage_Initialize(&ColorWidgetMenu); - ColorWidgetMenu.data = obj; + MNPage_Initialize(colorWidgetPage); + colorWidgetPage->userData = obj; MNColorBox_CopyColor(cboxMix, 0, obj); MNSlider_SetValue(sldrRed, MNSLIDER_SVF_NO_ACTION, MNColorBox_Redf(obj)); @@ -3344,50 +3310,19 @@ void Hu_MenuDrawOptionsPage(mn_page_t* page, const Point2Raw* origin) #endif } -void Hu_MenuDrawSoundPage(mn_page_t* page, const Point2Raw* origin) +void Hu_MenuDrawWeaponsPage(mn_page_t* page, const Point2Raw* offset) { - Hu_MenuDrawPageTitle("Sound Options", SCREENWIDTH/2, origin->y - 28); -} - -void Hu_MenuDrawGameplayPage(mn_page_t* page, const Point2Raw* origin) -{ - Hu_MenuDrawPageTitle("Gameplay", SCREENWIDTH/2, origin->y - 28); -} - -void Hu_MenuDrawWeaponsPage(mn_page_t* page, const Point2Raw* origin) -{ - Hu_MenuDrawPageTitle("Weapons", SCREENWIDTH/2, origin->y - 28); - Hu_MenuDrawPageNavigation(page, SCREENWIDTH/2, origin->y - 12); - // Inform the user how to change the order. if(MNPage_FocusObject(page) == MN_MustFindObjectOnPage(page, 0, MNF_ID0)) { - const char* str = "Use left/right to move weapon up/down"; - - DGL_Enable(DGL_TEXTURE_2D); - FR_SetFont(FID(GF_FONTA)); - FR_SetColorv(cfg.menuTextColors[1]); - FR_SetAlpha(mnRendState->pageAlpha); - - FR_DrawTextXY3(str, SCREENWIDTH/2, SCREENHEIGHT/2 + (95/cfg.menuScale), ALIGN_BOTTOM, MN_MergeMenuEffectWithDrawTextFlags(0)); - - DGL_Disable(DGL_TEXTURE_2D); + const char* helpText = "Use left/right to move weapon up/down"; + Point2Raw origin; + origin.x = SCREENWIDTH/2; + origin.y = (SCREENHEIGHT/2) + ((SCREENHEIGHT/2-5)/cfg.menuScale); + Hu_MenuDrawPageHelp(helpText, origin.x, origin.y); } } -#if __JHERETIC__ || __JHEXEN__ -void Hu_MenuDrawInventoryPage(mn_page_t* page, const Point2Raw* origin) -{ - Hu_MenuDrawPageTitle("Inventory Options", SCREENWIDTH/2, origin->y - 28); -} -#endif - -void Hu_MenuDrawHudPage(mn_page_t* page, const Point2Raw* origin) -{ - Hu_MenuDrawPageTitle("HUD options", SCREENWIDTH/2, origin->y - 28); - Hu_MenuDrawPageNavigation(page, SCREENWIDTH/2, origin->y - 12); -} - void Hu_MenuDrawMultiplayerPage(mn_page_t* page, const Point2Raw* origin) { Hu_MenuDrawPageTitle(GET_TXT(TXT_MULTIPLAYER), SCREENWIDTH/2, origin->y - 28); @@ -3402,14 +3337,14 @@ int Hu_MenuActionSetActivePage(mn_object_t* obj, mn_actionid_t action, void* par { assert(obj); if(MNA_ACTIVEOUT != action) return 1; - Hu_MenuSetActivePage((mn_page_t*)obj->data1); + Hu_MenuSetActivePage(Hu_MenuFindPageByName((char*)obj->data1)); return 0; } int Hu_MenuUpdateColorWidgetColor(mn_object_t* obj, mn_actionid_t action, void* paramaters) { float value = MNSlider_Value(obj); - mn_object_t* cboxMix = MN_MustFindObjectOnPage(&ColorWidgetMenu, 0, MNF_ID0); + mn_object_t* cboxMix = MN_MustFindObjectOnPage(Hu_MenuFindPageByName("ColorWidget"), 0, MNF_ID0); if(MNA_MODIFIED != action) return 1; @@ -3463,23 +3398,24 @@ int Hu_MenuSelectSingleplayer(mn_object_t* obj, mn_actionid_t action, void* para } #if __JHEXEN__ - Hu_MenuSetActivePage(&PlayerClassMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("PlayerClass")); #elif __JHERETIC__ - Hu_MenuSetActivePage(&EpisodeMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("Episode")); #elif __JDOOM64__ - Hu_MenuSetActivePage(&SkillMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("Skill")); #else // __JDOOM__ if(gameModeBits & (GM_ANY_DOOM2|GM_DOOM_CHEX)) - Hu_MenuSetActivePage(&SkillMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("Skill")); else - Hu_MenuSetActivePage(&EpisodeMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("Episode")); #endif return 0; } int Hu_MenuSelectMultiplayer(mn_object_t* obj, mn_actionid_t action, void* paramaters) { - mn_object_t* labelObj = MN_MustFindObjectOnPage(&MultiplayerMenu, 0, MNF_ID0); + mn_page_t* multiplayerPage = Hu_MenuFindPageByName("Multiplayer"); + mn_object_t* labelObj = MN_MustFindObjectOnPage(multiplayerPage, 0, MNF_ID0); mndata_button_t* btn = (mndata_button_t*)labelObj->_typedata; if(MNA_ACTIVEOUT != action) return 1; @@ -3493,7 +3429,7 @@ int Hu_MenuSelectMultiplayer(mn_object_t* obj, mn_actionid_t action, void* param { btn->text = "Join Game"; } - Hu_MenuSetActivePage(&MultiplayerMenu); + Hu_MenuSetActivePage(multiplayerPage); return 0; } @@ -3513,9 +3449,10 @@ int Hu_MenuSelectJoinGame(mn_object_t* obj, mn_actionid_t action, void* paramate int Hu_MenuSelectPlayerSetup(mn_object_t* obj, mn_actionid_t action, void* paramaters) { - mn_object_t* mop = MN_MustFindObjectOnPage(&PlayerSetupMenu, 0, MNF_ID0); - mn_object_t* name = MN_MustFindObjectOnPage(&PlayerSetupMenu, 0, MNF_ID1); - mn_object_t* color = MN_MustFindObjectOnPage(&PlayerSetupMenu, 0, MNF_ID3); + mn_page_t* playerSetupPage = Hu_MenuFindPageByName("PlayerSetup"); + mn_object_t* mop = MN_MustFindObjectOnPage(playerSetupPage, 0, MNF_ID0); + mn_object_t* name = MN_MustFindObjectOnPage(playerSetupPage, 0, MNF_ID1); + mn_object_t* color = MN_MustFindObjectOnPage(playerSetupPage, 0, MNF_ID3); #if __JHEXEN__ mn_object_t* class_; #endif @@ -3534,13 +3471,13 @@ int Hu_MenuSelectPlayerSetup(mn_object_t* obj, mn_actionid_t action, void* param MNList_SelectItemByValue(color, MNLIST_SIF_NO_ACTION, cfg.netColor); #if __JHEXEN__ - class_ = MN_MustFindObjectOnPage(&PlayerSetupMenu, 0, MNF_ID2); + class_ = MN_MustFindObjectOnPage(playerSetupPage, 0, MNF_ID2); MNList_SelectItemByValue(class_, MNLIST_SIF_NO_ACTION, cfg.netClass); #endif MNEdit_SetText(name, MNEDIT_STF_NO_ACTION|MNEDIT_STF_REPLACEOLD, Con_GetString("net-name")); - Hu_MenuSetActivePage(&PlayerSetupMenu); + Hu_MenuSetActivePage(playerSetupPage); return 0; } @@ -3553,7 +3490,7 @@ int Hu_MenuSelectPlayerSetupPlayerClass(mn_object_t* obj, mn_actionid_t action, selection = MNList_Selection(obj); if(selection >= 0) { - mn_object_t* mop = MN_MustFindObjectOnPage(&PlayerSetupMenu, 0, MNF_ID0); + mn_object_t* mop = MN_MustFindObjectOnPage(MNObject_Page(obj), 0, MNF_ID0); MNMobjPreview_SetPlayerClass(mop, selection); MNMobjPreview_SetMobjType(mop, PCLASS_INFO(selection)->mobjType); } @@ -3569,7 +3506,7 @@ int Hu_MenuSelectPlayerColor(mn_object_t* obj, mn_actionid_t action, void* param selection = MNList_Selection(obj); if(selection >= 0) { - mn_object_t* mop = MN_MustFindObjectOnPage(&PlayerSetupMenu, 0, MNF_ID0); + mn_object_t* mop = MN_MustFindObjectOnPage(MNObject_Page(obj), 0, MNF_ID0); MNMobjPreview_SetTranslationMap(mop, selection); } return 0; @@ -3605,7 +3542,7 @@ int Hu_MenuSelectAcceptPlayerSetup(mn_object_t* obj, mn_actionid_t action, void* DD_Executef(false, "setcolor %i", cfg.netColor); } - Hu_MenuSetActivePage(&MultiplayerMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("Multiplayer")); return 0; } @@ -3636,7 +3573,7 @@ int Hu_MenuSelectLoadGame(mn_object_t* obj, mn_actionid_t action, void* paramate } Hu_MenuUpdateGameSaveWidgets(); - Hu_MenuSetActivePage(&LoadMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("LoadGame")); return 0; } @@ -3670,13 +3607,14 @@ int Hu_MenuSelectSaveGame(mn_object_t* obj, mn_actionid_t action, void* paramate Hu_MenuCommand(MCMD_OPEN); Hu_MenuUpdateGameSaveWidgets(); - Hu_MenuSetActivePage(&SaveMenu); + Hu_MenuSetActivePage(Hu_MenuFindPageByName("SaveGame")); return 0; } #if __JHEXEN__ int Hu_MenuSelectPlayerClass(mn_object_t* obj, mn_actionid_t action, void* paramaters) { + mn_page_t* skillPage = Hu_MenuFindPageByName("Skill"); int option = obj->data2; mn_object_t* skillObj; const char* text; @@ -3698,38 +3636,38 @@ int Hu_MenuSelectPlayerClass(mn_object_t* obj, mn_actionid_t action, void* param mnPlrClass = option; } - skillObj = MN_MustFindObjectOnPage(&SkillMenu, 0, MNF_ID0); + skillObj = MN_MustFindObjectOnPage(skillPage, 0, MNF_ID0); text = GET_TXT(PCLASS_INFO(mnPlrClass)->skillModeNames[SM_BABY]); ((mndata_button_t*)skillObj->_typedata)->text = text; MNObject_SetShortcut(skillObj, text[0]); - skillObj = MN_MustFindObjectOnPage(&SkillMenu, 0, MNF_ID1); + skillObj = MN_MustFindObjectOnPage(skillPage, 0, MNF_ID1); text = GET_TXT(PCLASS_INFO(mnPlrClass)->skillModeNames[SM_EASY]); ((mndata_button_t*)skillObj->_typedata)->text = text; MNObject_SetShortcut(skillObj, text[0]); - skillObj = MN_MustFindObjectOnPage(&SkillMenu, 0, MNF_ID2); + skillObj = MN_MustFindObjectOnPage(skillPage, 0, MNF_ID2); text = GET_TXT(PCLASS_INFO(mnPlrClass)->skillModeNames[SM_MEDIUM]); ((mndata_button_t*)skillObj->_typedata)->text = text; MNObject_SetShortcut(skillObj, text[0]); - skillObj = MN_MustFindObjectOnPage(&SkillMenu, 0, MNF_ID3); + skillObj = MN_MustFindObjectOnPage(skillPage, 0, MNF_ID3); text = GET_TXT(PCLASS_INFO(mnPlrClass)->skillModeNames[SM_HARD]); ((mndata_button_t*)skillObj->_typedata)->text = text; MNObject_SetShortcut(skillObj, text[0]); - skillObj = MN_MustFindObjectOnPage(&SkillMenu, 0, MNF_ID4); + skillObj = MN_MustFindObjectOnPage(skillPage, 0, MNF_ID4); text = GET_TXT(PCLASS_INFO(mnPlrClass)->skillModeNames[SM_NIGHTMARE]); ((mndata_button_t*)skillObj->_typedata)->text = text; MNObject_SetShortcut(skillObj, text[0]); switch(mnPlrClass) { - case PCLASS_FIGHTER: SkillMenu.origin.x = 120; break; - case PCLASS_CLERIC: SkillMenu.origin.x = 116; break; - case PCLASS_MAGE: SkillMenu.origin.x = 112; break; + case PCLASS_FIGHTER: MNPage_SetX(skillPage, 120); break; + case PCLASS_CLERIC: MNPage_SetX(skillPage, 116); break; + case PCLASS_MAGE: MNPage_SetX(skillPage, 112); break; } - Hu_MenuSetActivePage(&SkillMenu); + Hu_MenuSetActivePage(skillPage); return 0; } @@ -3740,7 +3678,7 @@ int Hu_MenuFocusOnPlayerClass(mn_object_t* obj, mn_actionid_t action, void* para if(MNA_FOCUS != action) return 1; - mop = MN_MustFindObjectOnPage(&PlayerClassMenu, 0, MNF_ID0); + mop = MN_MustFindObjectOnPage(MNObject_Page(obj), 0, MNF_ID0); MNMobjPreview_SetPlayerClass(mop, plrClass); MNMobjPreview_SetMobjType(mop, (PCLASS_NONE == plrClass? MT_NONE : PCLASS_INFO(plrClass)->mobjType)); @@ -3840,20 +3778,11 @@ int Hu_MenuSelectControlPanelLink(mn_object_t* obj, mn_actionid_t action, void* #undef NUM_PANEL_NAMES } -/** - * Draws the automap options menu - */ -void Hu_MenuDrawAutomapPage(mn_page_t* page, const Point2Raw* origin) -{ - Hu_MenuDrawPageTitle("Automap Options", SCREENWIDTH/2, origin->y - 28); - Hu_MenuDrawPageNavigation(page, SCREENWIDTH/2, origin->y - 12); -} - D_CMD(MenuOpen) { if(argc > 1) { - mn_page_t* page = Hu_MenuFindPageForName(argv[1]); + mn_page_t* page = Hu_MenuFindPageByName(argv[1]); if(page) { Hu_MenuCommand(MCMD_OPEN); diff --git a/doomsday/plugins/common/src/m_ctrl.c b/doomsday/plugins/common/src/m_ctrl.c index f4b0f6bfe3..a4504ce6fe 100644 --- a/doomsday/plugins/common/src/m_ctrl.c +++ b/doomsday/plugins/common/src/m_ctrl.c @@ -66,27 +66,6 @@ typedef struct bindingdrawerdata_s { static mn_object_t* ControlsMenuItems; static mndata_text_t* ControlsMenuTexts; -mn_page_t ControlsMenu = { - NULL, -#if __JDOOM__ || __JDOOM64__ - { 32, 40 }, -#elif __JHERETIC__ - { 32, 26 }, -#elif __JHEXEN__ - { 32, 21 }, -#endif - { (fontid_t)GF_FONTA, (fontid_t)GF_FONTB }, { 0, 1, 2 }, - Hu_MenuDrawControlsPage, NULL, - &OptionsMenu, -#if __JDOOM__ || __JDOOM64__ - //0, 17, { 17, 40 } -#elif __JHERETIC__ - //0, 15, { 15, 26 } -#elif __JHEXEN__ - //0, 16, { 16, 21 } -#endif -}; - static mndata_bindings_t controlConfig[] = { { "Movement" }, @@ -280,11 +259,19 @@ int Hu_MenuActivateBindingsGrab(mn_object_t* obj, mn_actionid_t action, void* pa void Hu_MenuInitControlsPage(void) { +#if __JDOOM__ || __JDOOM64__ + const Point2Raw pageOrigin = { 32, 40 }; +#elif __JHERETIC__ + const Point2Raw pageOrigin = { 32, 40 }; +#elif __JHEXEN__ + const Point2Raw pageOrigin = { 32, 40 }; +#endif int i, textCount, bindingsCount, totalItems, group; int configCount = sizeof(controlConfig) / sizeof(controlConfig[0]); size_t objectIdx, textIdx; + mn_page_t* page; - VERBOSE( Con_Message("Hu_MenuInitControlsPage: Creating controls items.\n") ); + VERBOSE( Con_Message("Hu_MenuInitControlsPage: Creating controls items.\n") ) textCount = 0; bindingsCount = 0; @@ -369,15 +356,14 @@ void Hu_MenuInitControlsPage(void) bindingsObj->actions[MNA_FOCUS].callback = Hu_MenuDefaultFocusAction; bindingsObj->_typedata = binds; bindingsObj->_group = group; - - if(!ControlsMenu.focus) - ControlsMenu.focus = bindingsObj - ControlsMenuItems; } } ControlsMenuItems[objectIdx]._type = MN_NONE; // Terminate. - ControlsMenu.objects = ControlsMenuItems; - ControlsMenu.objectsCount = totalItems; + page = Hu_MenuNewPage("ControlOptions", &pageOrigin, Hu_MenuDrawControlsPage, NULL, NULL); + page->objects = ControlsMenuItems; + MNPage_SetTitle(page, "Controls"); + MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); } static void drawSmallText(const char* string, int x, int y, float alpha) @@ -633,19 +619,12 @@ void MNBindings_UpdateGeometry(mn_object_t* obj, mn_page_t* page) /** * Hu_MenuDrawControlsPage */ -void Hu_MenuDrawControlsPage(mn_page_t* page, const Point2Raw* origin) +void Hu_MenuDrawControlsPage(mn_page_t* page, const Point2Raw* offset) { - Hu_MenuDrawPageTitle("Controls", SCREENWIDTH/2, origin->y - 28); - Hu_MenuDrawPageNavigation(page, SCREENWIDTH/2, origin->y - 12); - - DGL_Enable(DGL_TEXTURE_2D); - FR_SetFont(FID(GF_FONTA)); - FR_SetColorv(cfg.menuTextColors[1]); - FR_SetAlpha(mnRendState->pageAlpha); - - FR_DrawTextXY3("Select to assign new, [Del] to clear", SCREENWIDTH/2, (SCREENHEIGHT/2) + ((SCREENHEIGHT/2-5)/cfg.menuScale), ALIGN_BOTTOM, MN_MergeMenuEffectWithDrawTextFlags(0)); - - DGL_Disable(DGL_TEXTURE_2D); + Point2Raw origin; + origin.x = SCREENWIDTH/2; + origin.y = (SCREENHEIGHT/2) + ((SCREENHEIGHT/2-5)/cfg.menuScale); + Hu_MenuDrawPageHelp("Select to assign new, [Del] to clear", origin.x, origin.y); } void Hu_MenuControlGrabDrawer(const char* niceName, float alpha)