diff --git a/doomsday/plugins/common/include/hu_lib.h b/doomsday/plugins/common/include/hu_lib.h index 0ee138f864..c08396165b 100644 --- a/doomsday/plugins/common/include/hu_lib.h +++ b/doomsday/plugins/common/include/hu_lib.h @@ -24,8 +24,10 @@ #include "common.h" #include "hu_stuff.h" -struct mn_object_s; -struct mn_page_s; +#ifdef __cplusplus +struct mn_object_t; +struct mn_page_t; +#endif typedef enum menucommand_e { MCMD_OPEN, // Open the menu. @@ -86,11 +88,14 @@ typedef enum { #define MNF_ID0 0x80000000 ///@} -typedef enum { +#ifdef __cplusplus + +enum flagop_t +{ FO_CLEAR, FO_SET, FO_TOGGLE -} flagop_t; +}; /** * Logical Menu (object) Action identifiers. Associated with/to events which @@ -98,7 +103,8 @@ typedef enum { * or "actioned" through the type-specific event/command responders of the * various widgets, according to their own widget-specific logic. */ -typedef enum { +enum mn_actionid_t +{ MNA_NONE = -1, MNACTION_FIRST = 0, MNA_MODIFIED = MNACTION_FIRST, /// Object's internal "modified" status changed. @@ -108,7 +114,7 @@ typedef enum { MNA_FOCUSOUT, /// Loses selection "focus". MNA_FOCUS, /// Gains selection "focus". MNACTION_LAST = MNA_FOCUS -} mn_actionid_t; +}; /// Total number of known Menu Actions. #define MNACTION_COUNT (MNACTION_LAST + 1 - MNACTION_FIRST) @@ -120,7 +126,8 @@ typedef enum { * Menu Action Info (Record). Holds information about an "actionable" menu * event, such as an object being activated or upon receiving focus. */ -typedef struct { +struct mn_actioninfo_t +{ /// Callback to be made when this action is executed. Can be @c NULL in /// which case attempts to action this will be NOPs. /// @@ -129,13 +136,14 @@ typedef struct { /// @param parameters Passed to the callback from event which actioned this. /// @return Callback return value. Callback should return zero if the action /// was recognised and processed, regardless of outcome. - int (*callback) (struct mn_object_s *ob, mn_actionid_t action, void *parameters); -} mn_actioninfo_t; + int (*callback) (mn_object_t *ob, mn_actionid_t action, void *parameters); +}; /** * MNObject. Abstract base from which all menu page objects must be derived. */ -typedef struct mn_object_s { +struct mn_object_t +{ /// Type of the object. mn_obtype_e _type; @@ -160,29 +168,29 @@ typedef struct mn_object_s { int _pageColorIdx; /// Process time (the "tick") for this object. - void (*ticker) (struct mn_object_s *ob); + void (*ticker) (mn_object_t *ob); /// Calculate geometry for this when visible on the specified page. - void (*updateGeometry) (struct mn_object_s *ob, struct mn_page_s *page); + void (*updateGeometry) (mn_object_t *ob, mn_page_t *page); /// Draw this at the specified offset within the owning view-space. /// Can be @c NULL in which case this will never be drawn. - void (*drawer) (struct mn_object_s *ob, Point2Raw const *origin); + void (*drawer) (mn_object_t *ob, Point2Raw const *origin); /// Info about "actionable event" callbacks. mn_actioninfo_t actions[MNACTION_COUNT]; /// Respond to the given (menu) @a command. Can be @c NULL. /// @return @c true if the command is eaten. - int (*cmdResponder) (struct mn_object_s *ob, menucommand_e command); + int (*cmdResponder) (mn_object_t *ob, menucommand_e command); /// Respond to the given (input) event @a ev. Can be @c NULL. /// @return @c true if the event is eaten. - int (*responder) (struct mn_object_s *ob, event_t *ev); + int (*responder) (mn_object_t *ob, event_t *ev); /// Respond to the given (input) event @a ev. Can be @c NULL. /// @return @c true if the event is eaten. - int (*privilegedResponder) (struct mn_object_s *ob, event_t *ev); + int (*privilegedResponder) (mn_object_t *ob, event_t *ev); void *_typedata; // Type-specific extra data. @@ -196,18 +204,14 @@ typedef struct mn_object_s { Rect *_geometry; /// MenuPage which owns this object (if any). - struct mn_page_s *_page; + mn_page_t *_page; int timer; -} mn_object_t; - -#ifdef __cplusplus -extern "C" { -#endif +}; mn_obtype_e MNObject_Type(mn_object_t const *ob); -struct mn_page_s* MNObject_Page(mn_object_t const *ob); +mn_page_t *MNObject_Page(mn_object_t const *ob); int MNObject_Flags(mn_object_t const *ob); @@ -289,9 +293,7 @@ dd_bool MNObject_HasAction(mn_object_t *ob, mn_actionid_t action); */ int MNObject_ExecAction(mn_object_t *ob, mn_actionid_t action, void *parameters); -#ifdef __cplusplus -} // extern "C" -#endif +#endif // __cplusplus typedef enum { MENU_COLOR1 = 0, @@ -333,17 +335,21 @@ typedef enum { #define MPF_NEVER_SCROLL 0x2 ///< Page scrolling is disabled. ///@} -typedef struct mn_page_s { +#ifdef __cplusplus + +struct mn_page_t +{ +public: /// Collection of objects on this page. - mn_object_t *objects; - int objectsCount; + 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; + mn_page_t *previous; /// Title of this page. ddstring_t title; @@ -361,108 +367,122 @@ typedef struct mn_page_s { uint colors[MENU_COLOR_COUNT]; /// Process time (the "tick") for this object. - void (*ticker) (struct mn_page_s *page); + void (*ticker) (mn_page_t *page); /// Page drawing routine. - void (*drawer) (struct mn_page_s *page, Point2Raw const *offset); + void (*drawer) (mn_page_t *page, Point2Raw const *offset); /// Menu-command responder routine. - int (*cmdResponder) (struct mn_page_s *page, menucommand_e cmd); + int (*cmdResponder) (mn_page_t *page, menucommand_e cmd); /// User data. void *userData; - int timer; -} mn_page_t; + int _timer; -#ifdef __cplusplus -extern "C" { -#endif +public: + mn_page_t(Point2Raw const &origin = Point2Raw(), int flags = 0, + void (*ticker) (mn_page_t *page) = 0, + void (*drawer) (mn_page_t *page, Point2Raw const *origin) = 0, + int (*cmdResponder) (mn_page_t *page, menucommand_e cmd) = 0, + void *userData = 0); -void MNPage_Initialize(mn_page_t *page); + ~mn_page_t(); -/// Call the ticker routine for each object. -void MNPage_Ticker(mn_page_t *page); + mn_object_t *objects() const; -void MNPage_SetTitle(mn_page_t *page, char const *title); + int objectsCount() const; -void MNPage_SetX(mn_page_t *page, int x); -void MNPage_SetY(mn_page_t *page, int y); + void initialize(); -void MNPage_SetPreviousPage(mn_page_t *page, mn_page_t *prevPage); + void initObjects(); + void updateObjects(); -void MNPage_Refocus(mn_page_t *page); + /// Call the ticker routine for each object. + void tick(); -/// @return Currently focused object; otherwise @c 0. -mn_object_t *MNPage_FocusObject(mn_page_t *page); + void setTitle(char const *title); -void MNPage_ClearFocusObject(mn_page_t *page); + void setX(int x); + void setY(int y); -/** - * Attempt to give focus to the MNObject @a ob which is thought to be on the - * page. If @a ob is found to present and is not currently in-focus, an out-focus - * action is first sent to the presently focused object, then this page's focused - * object is set before finally executing an in-focus action on the new object. - * If the object is not found on this page then nothing will happen. - * - * @param ob MNObject to be given focus. - */ -void MNPage_SetFocus(mn_page_t *page, mn_object_t *ob); + void setPreviousPage(mn_page_t *prevPage); -/** - * Determines the size of the menu cursor for the currently focused widget. If - * no widget is currently focused the default cursor size (i.e., the effective - * line height for @c MENU_FONT1) is used. (Which means this should @em not be - * called to determine whether the cursor is actually in use -- for that purpose, - * use @ref MNPage_FocusObject() instead). - */ -int MNPage_CursorSize(mn_page_t *page); + void refocus(); -/** - * Retrieve an object on this page in the specified object group. - * - * @param flags @ref mnobjectFlags used to locate the object. All flags specified - * must be set. - * - * @return Found MNObject else @c NULL - */ -mn_object_t *MNPage_FindObject(mn_page_t *page, int group, int flags); + /// @return Currently focused object; otherwise @c 0. + mn_object_t *focusObject(); -/** - * Retrieve a predefined color triplet associated with this page by it's logical - * page color identifier. - * - * @param id Unique identifier of the predefined color being retrieved. - * @param rgb Found color values are written here, else set to white. - */ -void MNPage_PredefinedColor(mn_page_t *page, mn_page_colorid_t id, float rgb[3]); + void clearFocusObject(); -/** - * Retrieve a predefined Doomsday font-identifier associated with this page - * by it's logical page font identifier. - * - * @param id Unique identifier of the predefined font being retrieved. - * - * @return Identifier of the found font else @c 0 - */ -fontid_t MNPage_PredefinedFont(mn_page_t *page, mn_page_fontid_t id); + /** + * Attempt to give focus to the MNObject @a ob which is thought to be on the + * page. If @a ob is found to present and is not currently in-focus, an out-focus + * action is first sent to the presently focused object, then this page's focused + * object is set before finally executing an in-focus action on the new object. + * If the object is not found on this page then nothing will happen. + * + * @param ob MNObject to be given focus. + */ + void setFocus(mn_object_t *ob); -void MNPage_SetPredefinedFont(mn_page_t *page, mn_page_fontid_t id, fontid_t fontId); + /** + * Determines the size of the menu cursor for the currently focused widget. If + * no widget is currently focused the default cursor size (i.e., the effective + * line height for @c MENU_FONT1) is used. (Which means this should @em not be + * called to determine whether the cursor is actually in use -- for that purpose, + * use @ref MNPage_FocusObject() instead). + */ + int cursorSize(); -/** - * Returns the effective line height for the predefined @c MENU_FONT1. - * - * @param lineOffset If not @c 0 the line offset is written here. - */ -int MNPage_LineHeight2(mn_page_t *page, int *lineOffset); -int MNPage_LineHeight(mn_page_t *page/*, lineOffset = 0*/); + /** + * Retrieve an object on this page in the specified object group. + * + * @param flags @ref mnobjectFlags used to locate the object. All flags specified + * must be set. + * + * @return Found MNObject else @c NULL + */ + mn_object_t *findObject(int group, int flags); -/// @return Current time in tics since page activation. -int MNPage_Timer(mn_page_t *page); + int findObjectIndex(mn_object_t *ob); -#ifdef __cplusplus -} // extern "C" -#endif + /** + * Retrieve a predefined color triplet associated with this page by it's logical + * page color identifier. + * + * @param id Unique identifier of the predefined color being retrieved. + * @param rgb Found color values are written here, else set to white. + */ + void predefinedColor(mn_page_colorid_t id, float rgb[3]); + + /** + * Retrieve a predefined Doomsday font-identifier associated with this page + * by it's logical page font identifier. + * + * @param id Unique identifier of the predefined font being retrieved. + * + * @return Identifier of the found font else @c 0 + */ + fontid_t predefinedFont(mn_page_fontid_t id); + + void setPredefinedFont(mn_page_fontid_t id, fontid_t fontId); + + /** + * Returns the effective line height for the predefined @c MENU_FONT1. + * + * @param lineOffset If not @c 0 the line offset is written here. + */ + int lineHeight(int *lineOffset = 0); + + /// @return Current time in tics since page activation. + int timer(); + + void applyPageLayout(); + +private: + void giveChildFocus(mn_object_t *ob, dd_bool allowRefocus); +}; /** * Rect objects. @@ -475,10 +495,6 @@ typedef struct mndata_rect_s { patchid_t patch; } mndata_rect_t; -#ifdef __cplusplus -extern "C" { -#endif - mn_object_t *MNRect_New(void); void MNRect_Delete(mn_object_t *ob); @@ -495,10 +511,6 @@ void MNRect_UpdateGeometry(mn_object_t *ob, mn_page_t *page); */ void MNRect_SetBackgroundPatch(mn_object_t *ob, patchid_t patch); -#ifdef __cplusplus -} // extern "C" -#endif - /** * @defgroup mnTextFlags MNText Flags */ @@ -519,10 +531,6 @@ typedef struct mndata_text_s { int flags; } mndata_text_t; -#ifdef __cplusplus -extern "C" { -#endif - mn_object_t *MNText_New(void); void MNText_Delete(mn_object_t *ob); @@ -532,10 +540,6 @@ void MNText_UpdateGeometry(mn_object_t *ob, mn_page_t *page); int MNText_SetFlags(mn_object_t *ob, flagop_t op, int flags); -#ifdef __cplusplus -} // extern "C" -#endif - /** * @defgroup mnButtonFlags MNButton Flags */ @@ -563,10 +567,6 @@ typedef struct mndata_button_s { int flags; } mndata_button_t; -#ifdef __cplusplus -extern "C" { -#endif - mn_object_t *MNButton_New(void); void MNButton_Delete(mn_object_t *ob); @@ -577,10 +577,6 @@ void MNButton_UpdateGeometry(mn_object_t *ob, mn_page_t *page); int MNButton_SetFlags(mn_object_t *ob, flagop_t op, int flags); -#ifdef __cplusplus -} // extern "C" -#endif - /** * Edit field. */ @@ -613,10 +609,6 @@ typedef struct mndata_edit_s { void *data1; } mndata_edit_t; -#ifdef __cplusplus -extern "C" { -#endif - mn_object_t *MNEdit_New(void); void MNEdit_Delete(mn_object_t *ob); @@ -647,10 +639,6 @@ ddstring_t const *MNEdit_Text(mn_object_t *ob); */ void MNEdit_SetText(mn_object_t *ob, int flags, char const *string); -#ifdef __cplusplus -} // extern "C" -#endif - /** * List selection. */ @@ -675,10 +663,6 @@ typedef struct mndata_list_s { int numvis; } mndata_list_t; -#ifdef __cplusplus -extern "C" { -#endif - mn_object_t *MNList_New(void); void MNList_Delete(mn_object_t *ob); @@ -731,10 +715,6 @@ dd_bool MNList_SelectItem(mn_object_t *ob, int flags, int itemIndex); */ dd_bool MNList_SelectItemByValue(mn_object_t *ob, int flags, int itemIndex); -#ifdef __cplusplus -} // extern "C" -#endif - /** * Color preview box. */ @@ -753,10 +733,6 @@ typedef struct mndata_colorbox_s { void *data4; } mndata_colorbox_t; -#ifdef __cplusplus -extern "C" { -#endif - mn_object_t *MNColorBox_New(void); void MNColorBox_Delete(mn_object_t *ob); @@ -823,10 +799,6 @@ dd_bool MNColorBox_SetAlphaf(mn_object_t *ob, int flags, float alpha); */ dd_bool MNColorBox_CopyColor(mn_object_t *ob, int flags, mn_object_t const *otherObj); -#ifdef __cplusplus -} // extern "C" -#endif - /** * Graphical slider. */ @@ -861,10 +833,6 @@ typedef struct mndata_slider_s { void *data5; } mndata_slider_t; -#ifdef __cplusplus -extern "C" { -#endif - mn_object_t *MNSlider_New(void); void MNSlider_Delete(mn_object_t *ob); @@ -893,10 +861,6 @@ float MNSlider_Value(mn_object_t const *ob); */ void MNSlider_SetValue(mn_object_t *ob, int flags, float value); -#ifdef __cplusplus -} // extern "C" -#endif - /** * Mobj preview visual. */ @@ -910,10 +874,6 @@ typedef struct mndata_mobjpreview_s { int plrClass; /// Player class identifier. } mndata_mobjpreview_t; -#ifdef __cplusplus -extern "C" { -#endif - mn_object_t *MNMobjPreview_New(void); void MNMobjPreview_Delete(mn_object_t *ob); @@ -926,10 +886,6 @@ void MNMobjPreview_SetTranslationMap(mn_object_t *ob, int tMap); void MNMobjPreview_Drawer(mn_object_t *ob, Point2Raw const *origin); void MNMobjPreview_UpdateGeometry(mn_object_t *ob, mn_page_t *page); -#ifdef __cplusplus -} // extern "C" -#endif - // Menu render state: typedef struct mn_rendstate_s { float pageAlpha; @@ -939,7 +895,7 @@ typedef struct mn_rendstate_s { fontid_t textFonts[MENU_FONT_COUNT]; } mn_rendstate_t; -DENG_EXTERN_C mn_rendstate_t const *mnRendState; +extern mn_rendstate_t const *mnRendState; /** * @defgroup menuEffectFlags Menu Effect Flags @@ -952,10 +908,6 @@ DENG_EXTERN_C mn_rendstate_t const *mnRendState; #define MEF_EVERYTHING (MEF_TEXT_TYPEIN|MEF_TEXT_SHADOW|MEF_TEXT_GLITTER) ///@} -#ifdef __cplusplus -extern "C" { -#endif - short MN_MergeMenuEffectWithDrawTextFlags(short f); mn_object_t *MN_MustFindObjectOnPage(mn_page_t *page, int group, int flags); @@ -967,9 +919,25 @@ void MN_DrawPage(mn_page_t *page, float alpha, dd_bool showFocusCursor); */ void Hu_MenuCommand(menucommand_e cmd); -#ifdef __cplusplus -} // extern "C" -#endif +struct cvarbutton_t +{ + char active; + char const *cvarname; + char const *yes; + char const *no; + int mask; + + cvarbutton_t(char active = 0, char const *cvarname = 0, char const *yes = 0, char const *no = 0, + int mask = 0) + : active(active) + , cvarname(cvarname) + , yes(yes) + , no(no) + , mask(mask) + {} +}; + +#endif // __cplusplus typedef enum { GUI_NONE, diff --git a/doomsday/plugins/common/include/hu_menu.h b/doomsday/plugins/common/include/hu_menu.h index 2fe9e8dd1b..1ddf90f6e9 100644 --- a/doomsday/plugins/common/include/hu_menu.h +++ b/doomsday/plugins/common/include/hu_menu.h @@ -20,16 +20,15 @@ #ifndef LIBCOMMON_HU_MENU_H #define LIBCOMMON_HU_MENU_H +#ifdef __cplusplus #include "dd_types.h" #include "hu_lib.h" -DENG_EXTERN_C int menuTime; -DENG_EXTERN_C dd_bool menuNominatingQuickSaveSlot; +extern int menuTime; +extern dd_bool menuNominatingQuickSaveSlot; -#ifdef __cplusplus -extern "C" { -#endif +extern cvarbutton_t mnCVarButtons[]; // Sounds played in the menu. #if __JDOOM__ || __JDOOM64__ @@ -81,7 +80,7 @@ extern "C" { #define MENU_CURSOR_TICSPERFRAME 8 /// Register the console commands, variables, etc..., of this module. -void Hu_MenuRegister(void); +void Hu_MenuRegister(); /** * Menu initialization. @@ -90,17 +89,17 @@ void Hu_MenuRegister(void); * Initializes the various vars, fonts, adjust the menu structs and * anything else that needs to be done before the menu can be used. */ -void Hu_MenuInit(void); +void Hu_MenuInit(); /** * Menu shutdown, to be called when the game menu is no longer needed. */ -void Hu_MenuShutdown(void); +void Hu_MenuShutdown(); /** * Load any resources the menu needs. */ -void Hu_MenuLoadResources(void); +void Hu_MenuLoadResources(); /** * Updates on Game Tick. @@ -108,7 +107,7 @@ void Hu_MenuLoadResources(void); void Hu_MenuTicker(timespan_t ticLength); /// @return @c true if the menu is presently visible. -dd_bool Hu_MenuIsVisible(void); +dd_bool Hu_MenuIsVisible(); mn_page_t *Hu_MenuFindPageByName(char const *name); @@ -132,9 +131,9 @@ mn_page_t *Hu_MenuNewPage(char const *name, Point2Raw const *origin, int flags, * loop) Draws the current menu 'page' by calling the funcs attached to * each menu obj. */ -void Hu_MenuDrawer(void); +void Hu_MenuDrawer(); -void Hu_MenuPageTicker(struct mn_page_s *page); +void Hu_MenuPageTicker(mn_page_t *page); void Hu_MenuDrawFocusCursor(int x, int y, int focusObjectHeight, float alpha); @@ -156,12 +155,12 @@ int Hu_MenuFallbackResponder(event_t *ev); /** * @return @c true iff the menu is currently active (open). */ -dd_bool Hu_MenuIsActive(void); +dd_bool Hu_MenuIsActive(); /** * @return Current alpha level of the menu. */ -float Hu_MenuAlpha(void); +float Hu_MenuAlpha(); /** * Set the alpha level of the entire menu. @@ -173,7 +172,7 @@ void Hu_MenuSetAlpha(float alpha); /** * Retrieve the currently active page. */ -mn_page_t *Hu_MenuActivePage(void); +mn_page_t *Hu_MenuActivePage(); /** * Change the current active page. @@ -204,8 +203,5 @@ int Hu_MenuUpdateColorWidgetColor(mn_object_t *ob, mn_actionid_t action, void *p D_CMD(MenuOpen); D_CMD(MenuCommand); -#ifdef __cplusplus -} // extern "C" -#endif - +#endif // __cplusplus #endif // LIBCOMMON_HU_MENU_H diff --git a/doomsday/plugins/common/src/hu_lib.cpp b/doomsday/plugins/common/src/hu_lib.cpp index 96664501d2..87b607b213 100644 --- a/doomsday/plugins/common/src/hu_lib.cpp +++ b/doomsday/plugins/common/src/hu_lib.cpp @@ -718,9 +718,9 @@ static void MNEdit_LoadResources() mn_object_t *MN_MustFindObjectOnPage(mn_page_t *page, int group, int flags) { - mn_object_t *ob = MNPage_FindObject(page, group, flags); - if(!ob) - Con_Error("MN_MustFindObjectOnPage: Failed to locate object in group #%i with flags %i on page %p.", group, flags, page); + DENG2_ASSERT(page != 0); + mn_object_t *ob = page->findObject(group, flags); + if(!ob) Con_Error("MN_MustFindObjectOnPage: Failed to locate object in group #%i with flags %i on page %p.", group, flags, page); return ob; } @@ -745,11 +745,11 @@ static void setupRenderStateForPageDrawing(mn_page_t *page, float alpha) for(int i = 0; i < MENU_FONT_COUNT; ++i) { - rs.textFonts[i] = MNPage_PredefinedFont(page, mn_page_fontid_t(i)); + rs.textFonts[i] = page->predefinedFont(mn_page_fontid_t(i)); } for(int i = 0; i < MENU_COLOR_COUNT; ++i) { - MNPage_PredefinedColor(page, mn_page_colorid_t(i), rs.textColors[i]); + page->predefinedColor(mn_page_colorid_t(i), rs.textColors[i]); rs.textColors[i][CA] = alpha; // For convenience. } @@ -766,9 +766,9 @@ static void updatePageObjectGeometries(mn_page_t *page) if(!page) return; // Update objects. - for(int i = 0; i < page->objectsCount; ++i) + for(int i = 0; i < page->objectsCount(); ++i) { - mn_object_t *ob = &page->objects[i]; + mn_object_t *ob = &page->objects()[i]; if(MNObject_Type(ob) == MN_NONE) continue; @@ -788,65 +788,56 @@ dd_bool MNObject_IsDrawable(mn_object_t *ob) return !(MNObject_Type(ob) == MN_NONE || !ob->drawer || (MNObject_Flags(ob) & MNF_HIDDEN)); } -int MNPage_LineHeight2(mn_page_t *page, int *lineOffset) +int mn_page_t::lineHeight(int *lineOffset) { - DENG2_ASSERT(page != 0); - fontid_t oldFont = FR_Font(); /// @kludge We cannot yet query line height from the font... - FR_SetFont(MNPage_PredefinedFont(page, MENU_FONT1)); - int lineHeight = FR_TextHeight("{case}WyQ"); + FR_SetFont(predefinedFont(MENU_FONT1)); + int lh = FR_TextHeight("{case}WyQ"); if(lineOffset) { - *lineOffset = MAX_OF(1, .5f + lineHeight * .34f); + *lineOffset = de::max(1.f, .5f + lh * .34f); } // Restore the old font. FR_SetFont(oldFont); - return lineHeight; + return lh; } -int MNPage_LineHeight(mn_page_t *page) +void mn_page_t::applyPageLayout() { - return MNPage_LineHeight2(page, 0); -} - -static void applyPageLayout(mn_page_t *page) -{ - if(!page) return; - - Rect_SetXY(page->geometry, 0, 0); - Rect_SetWidthHeight(page->geometry, 0, 0); + Rect_SetXY(geometry, 0, 0); + Rect_SetWidthHeight(geometry, 0, 0); // Apply layout logic to this page. - if(page->flags & MPF_LAYOUT_FIXED) + if(flags & MPF_LAYOUT_FIXED) { // This page uses a fixed layout. - for(int i = 0; i < page->objectsCount; ++i) + for(int i = 0; i < _objectsCount; ++i) { - mn_object_t *ob = &page->objects[i]; + mn_object_t *ob = &_objects[i]; if(!MNObject_IsDrawable(ob)) continue; Rect_SetXY(ob->_geometry, ob->_origin.x, ob->_origin.y); - Rect_Unite(page->geometry, ob->_geometry); + Rect_Unite(geometry, ob->_geometry); } return; } // This page uses a dynamic layout. int lineOffset; - int lineHeight = MNPage_LineHeight2(page, &lineOffset); + int lh = lineHeight(&lineOffset); Point2Raw origin; - for(int i = 0; i < page->objectsCount;) + for(int i = 0; i < _objectsCount; ) { - mn_object_t *ob = &page->objects[i]; - mn_object_t *nextOb = i+1 < page->objectsCount? &page->objects[i+1] : 0; + mn_object_t *ob = &_objects[i]; + mn_object_t *nextOb = i + 1 < _objectsCount? &_objects[i + 1] : 0; if(!MNObject_IsDrawable(ob)) { @@ -860,7 +851,7 @@ static void applyPageLayout(mn_page_t *page) if(MNObject_Flags(ob) & MNF_POSITION_FIXED) { Rect_SetXY(ob->_geometry, ob->_origin.x, ob->_origin.y); - Rect_Unite(page->geometry, ob->_geometry); + Rect_Unite(geometry, ob->_geometry); // To the next object. i += 1; @@ -897,12 +888,12 @@ static void applyPageLayout(mn_page_t *page) origin.y += Rect_United(ob->_geometry, nextOb->_geometry, &united) ->size.height + lineOffset; - Rect_UniteRaw(page->geometry, &united); + Rect_UniteRaw(geometry, &united); // Extra spacing between object groups. - if(i+2 < page->objectsCount && - nextOb->_group != page->objects[i+2]._group) - origin.y += lineHeight; + if(i+2 < _objectsCount && + nextOb->_group != _objects[i + 2]._group) + origin.y += lh; // Proceed to the next object! i += 2; @@ -910,13 +901,13 @@ static void applyPageLayout(mn_page_t *page) } } - Rect_Unite(page->geometry, ob->_geometry); + Rect_Unite(geometry, ob->_geometry); origin.y += Rect_Height(ob->_geometry) + lineOffset; // Extra spacing between object groups. if(nextOb && nextOb->_group != ob->_group) - origin.y += lineHeight; + origin.y += lh; // Proceed to the next object! i += 1; @@ -1015,10 +1006,10 @@ void MN_DrawPage(mn_page_t *page, float alpha, dd_bool showFocusCursor) FR_PopAttrib(); // We can now layout the widgets of this page. - applyPageLayout(page); + page->applyPageLayout(); // Determine the origin of the focus object (this dictates the page scroll location). - focusObj = MNPage_FocusObject(page); + focusObj = page->focusObject(); if(focusObj && !MNObject_IsDrawable(focusObj)) { focusObj = 0; @@ -1027,7 +1018,7 @@ void MN_DrawPage(mn_page_t *page, float alpha, dd_bool showFocusCursor) // Are we focusing? if(focusObj) { - focusObjHeight = MNPage_CursorSize(page); + focusObjHeight = page->cursorSize(); // Determine the origin and dimensions of the cursor. /// @todo Each object should define a focus origin... @@ -1043,7 +1034,7 @@ void MN_DrawPage(mn_page_t *page, float alpha, dd_bool showFocusCursor) mndata_list_t const *list = (mndata_list_t *)focusObj->_typedata; FR_PushAttrib(); - FR_SetFont(MNPage_PredefinedFont(page, mn_page_fontid_t(MNObject_Font(focusObj)))); + FR_SetFont(page->predefinedFont(mn_page_fontid_t(MNObject_Font(focusObj)))); focusObjHeight = FR_CharHeight('A') * (1+MNDATA_LIST_LEADING); cursorOrigin.y += (list->selection - list->first) * focusObjHeight; FR_PopAttrib(); @@ -1081,9 +1072,9 @@ void MN_DrawPage(mn_page_t *page, float alpha, dd_bool showFocusCursor) } // Draw child objects. - for(i = 0; i < page->objectsCount; ++i) + for(i = 0; i < page->objectsCount(); ++i) { - mn_object_t *ob = &page->objects[i]; + mn_object_t *ob = &page->objects()[i]; RectRaw geometry; if(MNObject_Type(ob) == MN_NONE || !ob->drawer) continue; @@ -1123,116 +1114,149 @@ static dd_bool MNActionInfo_IsActionExecuteable(mn_actioninfo_t* info) return (info->callback != 0); } -void MNPage_SetTitle(mn_page_t *page, const char* title) +mn_page_t::mn_page_t(Point2Raw const &origin, int flags, + void (*ticker) (mn_page_t *page), + void (*drawer) (mn_page_t *page, Point2Raw const *origin), + int (*cmdResponder) (mn_page_t *page, menucommand_e cmd), + void *userData) + : _objects (0) + , _objectsCount(0) + , origin (origin) + , geometry (Rect_New()) + , previous (0) + , focus (-1) /// @todo Make this a page flag. + , flags (flags) + , ticker (ticker) + , drawer (drawer) + , cmdResponder (cmdResponder) + , userData (userData) +{ + Str_InitStd(&title); + + fontid_t fontId = FID(GF_FONTA); + for(int i = 0; i < MENU_FONT_COUNT; ++i) + { + fonts[i] = fontId; + } + + de::zap(colors); + colors[1] = 1; + colors[2] = 2; +} + +mn_page_t::~mn_page_t() { - DENG2_ASSERT(page); - Str_Set(&page->title, title? title : ""); + Str_Free(&title); + if(geometry) Rect_Delete(geometry); + + for(mn_object_t *ob = _objects; MNObject_Type(ob) != MN_NONE; ob++) + { + if(ob->_geometry) Rect_Delete(ob->_geometry); + } } -void MNPage_SetX(mn_page_t *page, int x) +mn_object_t *mn_page_t::objects() const { - DENG2_ASSERT(page); - page->origin.x = x; + return _objects; } -void MNPage_SetY(mn_page_t *page, int y) +int mn_page_t::objectsCount() const { - DENG2_ASSERT(page); - page->origin.y = y; + return _objectsCount; } -void MNPage_SetPreviousPage(mn_page_t *page, mn_page_t *prevPage) +void mn_page_t::setTitle(char const *newTitle) { - DENG2_ASSERT(page); - page->previous = prevPage; + Str_Set(&title, newTitle? newTitle : ""); } -mn_object_t *MNPage_FocusObject(mn_page_t *page) +void mn_page_t::setX(int x) { - DENG2_ASSERT(page != 0); - if(!page->objectsCount || page->focus < 0) return 0; - return &page->objects[page->focus]; + origin.x = x; } -void MNPage_ClearFocusObject(mn_page_t *page) +void mn_page_t::setY(int y) { - mn_object_t *ob; - int i; - DENG2_ASSERT(page); - if(page->focus >= 0) + origin.y = y; +} + +void mn_page_t::setPreviousPage(mn_page_t *newPrevious) +{ + previous = newPrevious; +} + +mn_object_t *mn_page_t::focusObject() +{ + if(!_objectsCount || focus < 0) return 0; + return &_objects[focus]; +} + +void mn_page_t::clearFocusObject() +{ + if(focus >= 0) { - ob = &page->objects[page->focus]; + mn_object_t *ob = &_objects[focus]; if(MNObject_Flags(ob) & MNF_ACTIVE) { return; } } - page->focus = -1; - ob = page->objects; - for(i = 0; i < page->objectsCount; ++i, ob++) + focus = -1; + mn_object_t *ob = _objects; + for(int i = 0; i < _objectsCount; ++i, ob++) { MNObject_SetFlags(ob, FO_CLEAR, MNF_FOCUS); } - MNPage_Refocus(page); + refocus(); } -int MNPage_CursorSize(mn_page_t *page) +int mn_page_t::cursorSize() { - mn_object_t *focusObj = MNPage_FocusObject(page); - int focusObjHeight = focusObj? Size2_Height(MNObject_Size(focusObj)) : 0; + mn_object_t *focusOb = focusObject(); + int focusObHeight = focusOb? Size2_Height(MNObject_Size(focusOb)) : 0; // Ensure the cursor is at least as tall as the effective line height for // the page. This is necessary because some mods replace the menu button // graphics with empty and/or tiny images (e.g., Hell Revealed 2). /// @note Handling this correctly would mean separate physical/visual /// geometries for menu widgets. - return MAX_OF(focusObjHeight, MNPage_LineHeight(page)); + return de::max(focusObHeight, lineHeight()); } -mn_object_t *MNPage_FindObject(mn_page_t *page, int group, int flags) +mn_object_t *mn_page_t::findObject(int group, int flags) { - mn_object_t *ob = page->objects; + mn_object_t *ob = _objects; for(; MNObject_Type(ob) != MN_NONE; ob++) { if(MNObject_IsGroupMember(ob, group) && (MNObject_Flags(ob) & flags) == flags) return ob; } - return NULL; + return 0; // Not found. } -static int MNPage_FindObjectIndex(mn_page_t *page, mn_object_t *ob) +int mn_page_t::findObjectIndex(mn_object_t *ob) { - int i; - DENG2_ASSERT(page && ob); - - for(i = 0; i < page->objectsCount; ++i) + DENG2_ASSERT(ob != 0); + for(int i = 0; i < _objectsCount; ++i) { - if(ob == page->objects+i) + if(ob == &_objects[i]) + { return i; + } } return -1; // Not found. } -#if 0 -static mn_object_t *MNPage_ObjectByIndex(mn_page_t *page, int idx) -{ - DENG2_ASSERT(page); - if(idx < 0 || idx >= page->objectsCount) - Con_Error("MNPage::ObjectByIndex: Index #%i invalid for page %p.", idx, page); - return page->objects + idx; -} -#endif - /// @pre @a ob is a child of @a page. -static void MNPage_GiveChildFocus(mn_page_t *page, mn_object_t *ob, dd_bool allowRefocus) +void mn_page_t::giveChildFocus(mn_object_t *ob, dd_bool allowRefocus) { - DENG2_ASSERT(page && ob); + DENG2_ASSERT(ob != 0); - if(!(0 > page->focus)) + if(!(0 > focus)) { - if(ob != page->objects + page->focus) + if(ob != _objects + focus) { - mn_object_t *oldFocusOb = page->objects + page->focus; + mn_object_t *oldFocusOb = _objects + focus; if(MNObject_HasAction(oldFocusOb, MNA_FOCUSOUT)) { MNObject_ExecAction(oldFocusOb, MNA_FOCUSOUT, NULL); @@ -1245,7 +1269,7 @@ static void MNPage_GiveChildFocus(mn_page_t *page, mn_object_t *ob, dd_bool allo } } - page->focus = ob - page->objects; + focus = ob - _objects; MNObject_SetFlags(ob, FO_SET, MNF_FOCUS); if(MNObject_HasAction(ob, MNA_FOCUS)) { @@ -1253,34 +1277,30 @@ static void MNPage_GiveChildFocus(mn_page_t *page, mn_object_t *ob, dd_bool allo } } -void MNPage_SetFocus(mn_page_t *page, mn_object_t *ob) +void mn_page_t::setFocus(mn_object_t *ob) { - int objIndex = MNPage_FindObjectIndex(page, ob); - if(objIndex < 0) + int obIndex = findObjectIndex(ob); + if(obIndex < 0) { -#if _DEBUG - Con_Error("MNPage::Focus: Failed to determine index for object %p on page %p.", ob, page); -#endif + DENG2_ASSERT(!"mn_page_t::Focus: Failed to determine index for object."); return; } - MNPage_GiveChildFocus(page, page->objects + objIndex, false); + giveChildFocus(_objects + obIndex, false); } -void MNPage_Refocus(mn_page_t *page) +void mn_page_t::refocus() { - DENG2_ASSERT(page); - // If we haven't yet visited this page then find the first focusable // object and select it. - if(0 > page->focus) + if(0 > focus) { int i, giveFocus = -1; // First look for a default focus object. There should only be one // but find the last with this flag... - for(i = 0; i < page->objectsCount; ++i) + for(i = 0; i < _objectsCount; ++i) { - mn_object_t *ob = &page->objects[i]; + mn_object_t *ob = &_objects[i]; if((MNObject_Flags(ob) & MNF_DEFAULT) && !(MNObject_Flags(ob) & (MNF_DISABLED|MNF_NO_FOCUS))) { giveFocus = i; @@ -1289,9 +1309,9 @@ void MNPage_Refocus(mn_page_t *page) // No default focus? Find the first focusable object. if(-1 == giveFocus) - for(i = 0; i < page->objectsCount; ++i) + for(i = 0; i < _objectsCount; ++i) { - mn_object_t *ob = &page->objects[i]; + mn_object_t *ob = &_objects[i]; if(!(MNObject_Flags(ob) & (MNF_DISABLED|MNF_NO_FOCUS))) { giveFocus = i; @@ -1301,31 +1321,28 @@ void MNPage_Refocus(mn_page_t *page) if(-1 != giveFocus) { - MNPage_GiveChildFocus(page, page->objects + giveFocus, false); + giveChildFocus(_objects + giveFocus, false); } else { - App_Log(DE2_DEV_WARNING, "MNPage::Refocus: No focusable object on page"); + LOGDEV_WARNING("mn_page_t::refocus: No focusable object on page"); } } else { // We've been here before; re-focus on the last focused object. - MNPage_GiveChildFocus(page, page->objects + page->focus, true); + giveChildFocus(_objects + focus, true); } } -void MNPage_Initialize(mn_page_t *page) +void mn_page_t::initialize() { - mn_object_t *ob; - int i; - DENG2_ASSERT(page); - // Reset page timer. - page->timer = 0; + _timer = 0; // (Re)init objects. - for(i = 0, ob = page->objects; i < page->objectsCount; ++i, ob++) + mn_object_t *ob = _objects; + for(int i = 0; i < _objectsCount; ++i, ob++) { // Reset object timer. ob->timer = 0; @@ -1333,10 +1350,10 @@ void MNPage_Initialize(mn_page_t *page) switch(MNObject_Type(ob)) { case MN_BUTTON: { - mndata_button_t* btn = (mndata_button_t *)ob->_typedata; + mndata_button_t *btn = (mndata_button_t *)ob->_typedata; if(btn->staydownMode) { - const dd_bool activate = (*(char*) ob->data1); + dd_bool const activate = (*(char *) ob->data1); MNObject_SetFlags(ob, (activate? FO_SET:FO_CLEAR), MNF_ACTIVE); } break; } @@ -1360,94 +1377,249 @@ void MNPage_Initialize(mn_page_t *page) } } - if(0 == page->objectsCount) + if(!_objectsCount) { // Presumably objects will be added later. return; } - MNPage_Refocus(page); + refocus(); } -void MNPage_Ticker(mn_page_t *page) +void mn_page_t::initObjects() { - mn_object_t *ob; - int i; + _objectsCount = 0; + + for(mn_object_t *ob = _objects; MNObject_Type(ob) != MN_NONE; ob++) + { + _objectsCount += 1; + + ob->_page = this; + ob->_geometry = Rect_New(); + + ob->timer = 0; + MNObject_SetFlags(ob, FO_CLEAR, MNF_FOCUS); + + if(0 != ob->_shortcut) + { + int shortcut = ob->_shortcut; + ob->_shortcut = 0; // Clear invalid defaults. + MNObject_SetShortcut(ob, shortcut); + } + + switch(MNObject_Type(ob)) + { + case MN_TEXT: { + mndata_text_t *txt = (mndata_text_t *)ob->_typedata; + MNObject_SetFlags(ob, FO_SET, MNF_NO_FOCUS); + + if(txt->text && (PTR2INT(txt->text) > 0 && PTR2INT(txt->text) < NUMTEXT)) + { + txt->text = GET_TXT(PTR2INT(txt->text)); + } + break; } + + case MN_BUTTON: { + /*mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED);*/ + mndata_button_t *btn = (mndata_button_t *)ob->_typedata; + + if(btn->text && (PTR2INT(btn->text) > 0 && PTR2INT(btn->text) < NUMTEXT)) + { + btn->text = GET_TXT(PTR2INT(btn->text)); + /// @todo Should not be done here. + MNObject_SetShortcut(ob, btn->text[0]); + } + break; } + + case MN_EDIT: { + mndata_edit_t *edit = (mndata_edit_t *) ob->_typedata; + if(edit->emptyString && (PTR2INT(edit->emptyString) > 0 && PTR2INT(edit->emptyString) < NUMTEXT)) + { + edit->emptyString = GET_TXT(PTR2INT(edit->emptyString)); + } + break; } + + case MN_LIST: + case MN_LISTINLINE: { + mndata_list_t *list = (mndata_list_t *) ob->_typedata; + + for(int i = 0; i < list->count; ++i) + { + mndata_listitem_t *item = &((mndata_listitem_t *)list->items)[i]; + if(item->text && (PTR2INT(item->text) > 0 && PTR2INT(item->text) < NUMTEXT)) + { + item->text = GET_TXT(PTR2INT(item->text)); + } + } + break; } + + case MN_COLORBOX: { + mndata_colorbox_t *cbox = (mndata_colorbox_t *) ob->_typedata; + + if(!cbox->rgbaMode) + cbox->a = 1.f; + if(0 >= cbox->width) + cbox->width = MNDATA_COLORBOX_WIDTH; + if(0 >= cbox->height) + cbox->height = MNDATA_COLORBOX_HEIGHT; + break; } + + case MN_MOBJPREVIEW: + MNObject_SetFlags(ob, FO_SET, MNF_NO_FOCUS); + break; + + default: break; + } + } +} + +/// Main task is to update objects linked to cvars. +void mn_page_t::updateObjects() +{ + for(mn_object_t *ob = _objects; MNObject_Type(ob) != MN_NONE; ob++) + { + switch(MNObject_Type(ob)) + { + case MN_TEXT: + case MN_MOBJPREVIEW: + MNObject_SetFlags(ob, FO_SET, MNF_NO_FOCUS); + break; + + case MN_BUTTON: { + mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); + mndata_button_t *btn = (mndata_button_t *)ob->_typedata; + + if(action && action->callback == Hu_MenuCvarButton) + { + if(ob->data1) + { + // This button has already been initialized. + cvarbutton_t *cvb = (cvarbutton_t *) ob->data1; + cvb->active = (Con_GetByte(cvb->cvarname) & (cvb->mask? cvb->mask : ~0)) != 0; + //strcpy(obj->text, cvb->active ? cvb->yes : cvb->no); + btn->text = cvb->active ? cvb->yes : cvb->no; + continue; + } + + // Find the cvarbutton representing this one. + for(cvarbutton_t *cvb = mnCVarButtons; cvb->cvarname; cvb++) + { + if(!strcmp((char const *)btn->data, cvb->cvarname) && ob->data2 == cvb->mask) + { + cvb->active = (Con_GetByte(cvb->cvarname) & (cvb->mask? cvb->mask : ~0)) != 0; + ob->data1 = (void*) cvb; + + btn->yes = cvb->yes; + btn->no = cvb->no; + btn->text = (cvb->active ? btn->yes : btn->no); + break; + } + } + } + break; } + + case MN_LIST: + case MN_LISTINLINE: { + mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); + mndata_list_t *list = (mndata_list_t *) ob->_typedata; + + if(action && action->callback == Hu_MenuCvarList) + { + MNList_SelectItemByValue(ob, MNLIST_SIF_NO_ACTION, Con_GetInteger((char const *)list->data)); + } + break; } + + case MN_EDIT: { + mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); + mndata_edit_t *edit = (mndata_edit_t *) ob->_typedata; + + if(action && action->callback == Hu_MenuCvarEdit) + { + MNEdit_SetText(ob, MNEDIT_STF_NO_ACTION, Con_GetString((char const *)edit->data1)); + } + break; } + + case MN_SLIDER: { + mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); + mndata_slider_t *sldr = (mndata_slider_t *) ob->_typedata; + if(action && action->callback == Hu_MenuCvarSlider) + { + float value; + if(sldr->floatMode) + value = Con_GetFloat((char const *)sldr->data1); + else + value = Con_GetInteger((char const *)sldr->data1); + MNSlider_SetValue(ob, MNSLIDER_SVF_NO_ACTION, value); + } + break; } + + case MN_COLORBOX: { + mndata_colorbox_t *cbox = (mndata_colorbox_t *) ob->_typedata; + mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); + + if(action && action->callback == Hu_MenuCvarColorBox) + { + float rgba[4]; + rgba[CR] = Con_GetFloat((char const *)cbox->data1); + rgba[CG] = Con_GetFloat((char const *)cbox->data2); + rgba[CB] = Con_GetFloat((char const *)cbox->data3); + rgba[CA] = (cbox->rgbaMode? Con_GetFloat((char const *)cbox->data4) : 1.f); + MNColorBox_SetColor4fv(ob, MNCOLORBOX_SCF_NO_ACTION, rgba); + } + break; } + + default: break; + } + } +} + +void mn_page_t::tick() +{ // Call the ticker of each object, unless they're hidden or paused. - for(i = 0, ob = page->objects; i < page->objectsCount; ++i, ob++) + mn_object_t *ob = _objects; + for(int i = 0; i < _objectsCount; ++i, ob++) { if((MNObject_Flags(ob) & MNF_PAUSED) || (MNObject_Flags(ob) & MNF_HIDDEN)) continue; if(ob->ticker) + { ob->ticker(ob); + } // Advance object timer. ob->timer++; } - page->timer++; + _timer++; } -fontid_t MNPage_PredefinedFont(mn_page_t *page, mn_page_fontid_t id) +fontid_t mn_page_t::predefinedFont(mn_page_fontid_t id) { - DENG2_ASSERT(page); - if(!VALID_MNPAGE_FONTID(id)) - { -#if _DEBUG - Con_Error("MNPage::PredefinedFont: Invalid font id #%i.", (int)id); - exit(1); // Unreachable. -#endif - return 0; // Not a valid font id. - } - return page->fonts[id]; + DENG2_ASSERT(VALID_MNPAGE_FONTID(id)); + return fonts[id]; } -void MNPage_SetPredefinedFont(mn_page_t *page, mn_page_fontid_t id, fontid_t fontId) +void mn_page_t::setPredefinedFont(mn_page_fontid_t id, fontid_t fontId) { - DENG2_ASSERT(page); - if(!VALID_MNPAGE_FONTID(id)) - { - DENG2_ASSERT(!"MNPage::SetPredefinedFont: Invalid font id"); - return; - } - page->fonts[id] = fontId; + DENG2_ASSERT(VALID_MNPAGE_FONTID(id)); + fonts[id] = fontId; } -void MNPage_PredefinedColor(mn_page_t *page, mn_page_colorid_t id, float rgb[3]) +void mn_page_t::predefinedColor(mn_page_colorid_t id, float rgb[3]) { - uint colorIndex; - DENG2_ASSERT(page); - - if(!rgb) - { -#if _DEBUG - Con_Error("MNPage::PredefinedColor: Invalid 'rgb' reference."); - exit(1); // Unreachable. -#endif - return; - } - if(!VALID_MNPAGE_COLORID(id)) - { -#if _DEBUG - Con_Error("MNPage::PredefinedColor: Invalid color id '%i'.", (int)id); - exit(1); // Unreachable. -#endif - rgb[CR] = rgb[CG] = rgb[CB] = 1; - return; - } - - colorIndex = page->colors[id]; + DENG2_ASSERT(rgb != 0); + DENG2_ASSERT(VALID_MNPAGE_COLORID(id)); + uint colorIndex = colors[id]; rgb[CR] = cfg.menuTextColors[colorIndex][CR]; rgb[CG] = cfg.menuTextColors[colorIndex][CG]; rgb[CB] = cfg.menuTextColors[colorIndex][CB]; } -int MNPage_Timer(mn_page_t *page) +int mn_page_t::timer() { - DENG2_ASSERT(page); - return page->timer; + return _timer; } mn_obtype_e MNObject_Type(const mn_object_t *ob) @@ -1766,7 +1938,7 @@ void MNText_Drawer(mn_object_t *ob, Point2Raw const *origin) if((ob->_flags & MNF_FOCUS) && cfg.menuTextFlashSpeed > 0) { float const speed = cfg.menuTextFlashSpeed / 2.f; - t = (1 + sin(MNPage_Timer(ob->_page) / (float)TICSPERSEC * speed * DD_PI)) / 2; + t = (1 + sin(ob->_page->timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; } lerpColor(color, rs.textColors[ob->_pageColorIdx], cfg.menuTextFlashColor, t, false/*rgb mode*/); @@ -1811,7 +1983,7 @@ void MNText_UpdateGeometry(mn_object_t *ob, mn_page_t *page) Rect_SetWidthHeight(ob->_geometry, info.geometry.size.width, info.geometry.size.height); return; } - FR_SetFont(MNPage_PredefinedFont(page, mn_page_fontid_t(ob->_pageFontIdx))); + FR_SetFont(page->predefinedFont(mn_page_fontid_t(ob->_pageFontIdx))); FR_TextSize(&size, txt->text); Rect_SetWidthHeight(ob->_geometry, size.width, size.height); } @@ -1951,7 +2123,7 @@ void MNEdit_Drawer(mn_object_t *ob, Point2Raw const *_origin) if(!(ob->_flags & MNF_ACTIVE) && (ob->_flags & MNF_FOCUS) && cfg.menuTextFlashSpeed > 0) { float const speed = cfg.menuTextFlashSpeed / 2.f; - t = (1 + sin(MNPage_Timer(ob->_page) / (float)TICSPERSEC * speed * DD_PI)) / 2; + t = (1 + sin(ob->_page->timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; } lerpColor(color, cfg.menuTextColors[MNDATA_EDIT_TEXT_COLORIDX], cfg.menuTextFlashColor, t, false/*rgb mode*/); @@ -2197,7 +2369,7 @@ void MNList_Drawer(mn_object_t *ob, Point2Raw const *_origin) if(flashSelection && cfg.menuTextFlashSpeed > 0) { float const speed = cfg.menuTextFlashSpeed / 2.f; - t = (1 + sin(MNPage_Timer(ob->_page) / (float)TICSPERSEC * speed * DD_PI)) / 2; + t = (1 + sin(ob->_page->timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; } lerpColor(flashColor, rs.textColors[ob->_pageColorIdx], cfg.menuTextFlashColor, t, false/*rgb mode*/); @@ -2485,7 +2657,7 @@ void MNList_UpdateGeometry(mn_object_t *ob, mn_page_t *page) mndata_list_t *list = (mndata_list_t *)ob->_typedata; Rect_SetWidthHeight(ob->_geometry, 0, 0); - FR_SetFont(MNPage_PredefinedFont(page, mn_page_fontid_t(ob->_pageFontIdx))); + FR_SetFont(page->predefinedFont(mn_page_fontid_t(ob->_pageFontIdx))); RectRaw itemGeometry; for(int i = 0; i < list->count; ++i) @@ -2510,7 +2682,7 @@ void MNListInline_UpdateGeometry(mn_object_t *ob, mn_page_t *page) mndata_listitem_t *item = ((mndata_listitem_t *) list->items) + list->selection; Size2Raw size; - FR_SetFont(MNPage_PredefinedFont(page, mn_page_fontid_t(ob->_pageFontIdx))); + FR_SetFont(page->predefinedFont(mn_page_fontid_t(ob->_pageFontIdx))); FR_TextSize(&size, item->text); Rect_SetWidthHeight(ob->_geometry, size.width, size.height); } @@ -2562,7 +2734,7 @@ void MNButton_Drawer(mn_object_t *ob, Point2Raw const *origin) if((ob->_flags & MNF_FOCUS) && cfg.menuTextFlashSpeed > 0) { const float speed = cfg.menuTextFlashSpeed / 2.f; - t = (1 + sin(MNPage_Timer(ob->_page) / (float)TICSPERSEC * speed * DD_PI)) / 2; + t = (1 + sin(ob->_page->timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; } lerpColor(color, rs.textColors[ob->_pageColorIdx], cfg.menuTextFlashColor, t, false/*rgb mode*/); @@ -2688,7 +2860,7 @@ void MNButton_UpdateGeometry(mn_object_t *ob, mn_page_t *page) } } - FR_SetFont(MNPage_PredefinedFont(page, mn_page_fontid_t(ob->_pageFontIdx))); + FR_SetFont(page->predefinedFont(mn_page_fontid_t(ob->_pageFontIdx))); FR_TextSize(&size, text); Rect_SetWidthHeight(ob->_geometry, size.width, size.height); @@ -3441,7 +3613,7 @@ void MNSlider_TextualValueUpdateGeometry(mn_object_t *ob, mn_page_t *page) mndata_slider_t *sldr = (mndata_slider_t *)ob->_typedata; - fontid_t const font = MNPage_PredefinedFont(page, mn_page_fontid_t(ob->_pageFontIdx)); + fontid_t const font = page->predefinedFont(mn_page_fontid_t(ob->_pageFontIdx)); float const value = de::clamp(sldr->min, sldr->value, sldr->max); char textualValue[41]; char const *str = composeValueString(value, 0, sldr->floatMode, 0, diff --git a/doomsday/plugins/common/src/hu_menu.cpp b/doomsday/plugins/common/src/hu_menu.cpp index 5ede42bbe2..8f4ab270ee 100644 --- a/doomsday/plugins/common/src/hu_menu.cpp +++ b/doomsday/plugins/common/src/hu_menu.cpp @@ -26,8 +26,9 @@ #include #include #include +#include +#include #include - #include "am_map.h" #include "g_common.h" #include "g_controls.h" @@ -55,24 +56,6 @@ using namespace common; # define FIXED_LINE_HEIGHT (19+1) #endif -struct cvarbutton_t -{ - char active; - char const *cvarname; - char const *yes; - char const *no; - int mask; - - cvarbutton_t(char active = 0, char const *cvarname = 0, char const *yes = 0, char const *no = 0, - int mask = 0) - : active(active) - , cvarname(cvarname) - , yes(yes) - , no(no) - , mask(mask) - {} -}; - int Hu_MenuActionSetActivePage(mn_object_t *ob, mn_actionid_t action, void *parameters); int Hu_MenuActionInitNewGame(mn_object_t *ob, mn_actionid_t action, void *parameters); @@ -143,7 +126,6 @@ static void initAllPages(); static void destroyAllPages(); static void initAllObjectsOnAllPages(); -static void updatePageObjects(mn_page_t *page); static void Hu_MenuUpdateCursorState(); @@ -649,14 +631,8 @@ static mn_object_t HudMenuObjects[] = { static dd_bool inited; -struct pagerecord_t -{ - mn_page_t *page; - ddstring_t name; // Symbolic name. -}; - -static int pageCount; -static pagerecord_t *pages; +typedef QMap Pages; +static Pages pages; static menucommand_e chooseCloseMethod() { @@ -669,13 +645,10 @@ mn_page_t *Hu_MenuFindPageByName(char const *name) { if(name && name[0]) { - for(int i = 0; i < pageCount; ++i) + Pages::iterator found = pages.find(String(name).toLower()); + if(found != pages.end()) { - pagerecord_t *rec = pages + i; - if(!stricmp(name, Str_Text(&rec->name))) - { - return rec->page; - } + return *found; } } return 0; // Not found. @@ -696,7 +669,7 @@ static void Hu_MenuUpdateCursorState() if(menuActive) { mn_page_t *page = colorWidgetActive? Hu_MenuFindPageByName("ColorWidget") : Hu_MenuActivePage(); - if(mn_object_t *ob = MNPage_FocusObject(page)) + if(mn_object_t *ob = page->focusObject()) { cursorHasRotation = Hu_MenuHasCursorRotation(ob); return; @@ -792,7 +765,7 @@ void Hu_MenuInitColorWidgetPage() uint const numObjects = 10; mn_page_t *page = Hu_MenuNewPage("ColorWidget", &origin, MPF_NEVER_SCROLL, Hu_MenuPageTicker, NULL, Hu_MenuColorWidgetCmdResponder, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -960,7 +933,7 @@ void Hu_MenuInitColorWidgetPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } void Hu_MenuInitMainPage() @@ -989,7 +962,7 @@ void Hu_MenuInitMainPage() #else mn_page_t *page = Hu_MenuNewPage("Main", &origin, MPF_LAYOUT_FIXED|MPF_NEVER_SCROLL, Hu_MenuPageTicker, Hu_MenuDrawMainPage, NULL, NULL); #endif - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTB)); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTB)); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -1181,7 +1154,7 @@ void Hu_MenuInitMainPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } void Hu_MenuInitGameTypePage() @@ -1194,8 +1167,8 @@ void Hu_MenuInitGameTypePage() uint const numObjects = 3; mn_page_t *page = Hu_MenuNewPage("GameType", &origin, 0, Hu_MenuPageTicker, Hu_MenuDrawGameTypePage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTB)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTB)); + page->setPreviousPage(Hu_MenuFindPageByName("Main")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -1240,7 +1213,7 @@ void Hu_MenuInitGameTypePage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } void Hu_MenuInitSkillPage() @@ -1275,21 +1248,21 @@ void Hu_MenuInitSkillPage() uint const numObjects = NUM_SKILL_MODES + 1; mn_page_t *page = Hu_MenuNewPage("Skill", &origin, MPF_LAYOUT_FIXED|MPF_NEVER_SCROLL, Hu_MenuPageTicker, Hu_MenuDrawSkillPage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTB)); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTB)); #if __JHEXEN__ - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("PlayerClass")); + page->setPreviousPage(Hu_MenuFindPageByName("PlayerClass")); #elif __JHERETIC__ - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Episode")); + page->setPreviousPage(Hu_MenuFindPageByName("Episode")); #elif __JDOOM64__ - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + page->setPreviousPage(Hu_MenuFindPageByName("GameType")); #else // __JDOOM__ if(gameModeBits & (GM_ANY_DOOM2|GM_DOOM_CHEX)) { - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + page->setPreviousPage(Hu_MenuFindPageByName("GameType")); } else { - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Episode")); + page->setPreviousPage(Hu_MenuFindPageByName("Episode")); } #endif @@ -1329,7 +1302,7 @@ void Hu_MenuInitSkillPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; #if __JDOOM__ if(gameMode != doom2_hacx && gameMode != doom_chex) @@ -1350,8 +1323,8 @@ void Hu_MenuInitMultiplayerPage() uint const numObjects = 3; mn_page_t *page = Hu_MenuNewPage("Multiplayer", &origin, 0, Hu_MenuPageTicker, Hu_MenuDrawMultiplayerPage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTB)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTB)); + page->setPreviousPage(Hu_MenuFindPageByName("GameType")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -1393,7 +1366,7 @@ void Hu_MenuInitMultiplayerPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } void Hu_MenuInitPlayerSetupPage() @@ -1410,9 +1383,9 @@ void Hu_MenuInitPlayerSetupPage() #endif mn_page_t *page = Hu_MenuNewPage("PlayerSetup", &origin, 0, Hu_MenuPageTicker, Hu_MenuDrawPlayerSetupPage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPredefinedFont(page, MENU_FONT2, FID(GF_FONTB)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Multiplayer")); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPredefinedFont(MENU_FONT2, FID(GF_FONTB)); + page->setPreviousPage(Hu_MenuFindPageByName("Multiplayer")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -1624,7 +1597,7 @@ void Hu_MenuInitPlayerSetupPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } void Hu_MenuInitSaveOptionsPage() @@ -1633,9 +1606,9 @@ void Hu_MenuInitSaveOptionsPage() uint const numObjects = 8; mn_page_t *page = Hu_MenuNewPage("SaveOptions", &origin, 0, Hu_MenuPageTicker, NULL, NULL, NULL); - MNPage_SetTitle(page, "Save Options"); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->setTitle("Save Options"); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Options")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -1751,7 +1724,7 @@ void Hu_MenuInitSaveOptionsPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } #if __JHERETIC__ || __JHEXEN__ @@ -1761,8 +1734,8 @@ void Hu_MenuInitFilesPage() uint const numObjects = 3; mn_page_t *page = Hu_MenuNewPage("Files", &origin, MPF_LAYOUT_FIXED|MPF_NEVER_SCROLL, Hu_MenuPageTicker, NULL, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTB)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTB)); + page->setPreviousPage(Hu_MenuFindPageByName("Main")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -1807,18 +1780,18 @@ void Hu_MenuInitFilesPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } #endif -static void deleteGameSave(de::String slotId) +static void deleteGameSave(String slotId) { DD_Executef(true, "deletegamesave %s", slotId.toLatin1().constData()); } int Hu_MenuLoadSlotCommandResponder(mn_object_t *ob, menucommand_e cmd) { - DENG_ASSERT(ob != 0 && ob->_type == MN_EDIT); + DENG2_ASSERT(ob != 0 && ob->_type == MN_EDIT); if(MCMD_DELETE == cmd && (ob->_flags & MNF_FOCUS) && !(ob->_flags & MNF_ACTIVE) && !(ob->_flags & MNF_DISABLED)) { @@ -1831,7 +1804,7 @@ int Hu_MenuLoadSlotCommandResponder(mn_object_t *ob, menucommand_e cmd) int Hu_MenuSaveSlotCommandResponder(mn_object_t *ob, menucommand_e cmd) { - DENG_ASSERT(ob != 0); + DENG2_ASSERT(ob != 0); if(MCMD_DELETE == cmd && (ob->_flags & MNF_FOCUS) && !(ob->_flags & MNF_ACTIVE) && !(ob->_flags & MNF_DISABLED)) { @@ -1925,14 +1898,14 @@ void Hu_MenuInitLoadGameAndSaveGamePages() saveMenuObjects[i]._type = MN_NONE; mn_page_t *page = Hu_MenuNewPage("LoadGame", &origin, MPF_LAYOUT_FIXED|MPF_NEVER_SCROLL, Hu_MenuPageTicker, Hu_MenuDrawLoadGamePage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); - page->objects = loadMenuObjects; + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Main")); + page->_objects = loadMenuObjects; page = Hu_MenuNewPage("SaveGame", &origin, MPF_LAYOUT_FIXED|MPF_NEVER_SCROLL, Hu_MenuPageTicker, Hu_MenuDrawSaveGamePage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); - page->objects = saveMenuObjects; + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Main")); + page->_objects = saveMenuObjects; } void Hu_MenuInitOptionsPage() @@ -1949,8 +1922,8 @@ void Hu_MenuInitOptionsPage() #endif mn_page_t *page = Hu_MenuNewPage("Options", &origin, 0, Hu_MenuPageTicker, Hu_MenuDrawOptionsPage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Main")); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Main")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -2174,7 +2147,7 @@ void Hu_MenuInitOptionsPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } void Hu_MenuInitGameplayOptionsPage() @@ -2197,9 +2170,9 @@ void Hu_MenuInitGameplayOptionsPage() #endif mn_page_t *page = Hu_MenuNewPage("GameplayOptions", &origin, 0, Hu_MenuPageTicker, NULL, NULL, NULL); - MNPage_SetTitle(page, "Gameplay Options"); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->setTitle("Gameplay Options"); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Options")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -2914,7 +2887,7 @@ void Hu_MenuInitGameplayOptionsPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } void Hu_MenuInitHUDOptionsPage() @@ -2926,10 +2899,10 @@ void Hu_MenuInitHUDOptionsPage() #endif mn_page_t *page = Hu_MenuNewPage("HudOptions", &origin, 0, Hu_MenuPageTicker, NULL, NULL, NULL); - MNPage_SetTitle(page, "HUD Options"); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); - page->objects = HudMenuObjects; + page->setTitle("HUD Options"); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Options")); + page->_objects = HudMenuObjects; } void Hu_MenuInitAutomapOptionsPage() @@ -2946,9 +2919,9 @@ void Hu_MenuInitAutomapOptionsPage() #endif mn_page_t *page = Hu_MenuNewPage("AutomapOptions", &origin, 0, Hu_MenuPageTicker, NULL, NULL, NULL); - MNPage_SetTitle(page, "Automap Options"); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->setTitle("Automap Options"); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Options")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -3413,7 +3386,7 @@ void Hu_MenuInitAutomapOptionsPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } static int compareWeaponPriority(void const *_a, void const *_b) @@ -3490,9 +3463,9 @@ void Hu_MenuInitWeaponsPage() }; mn_page_t *page = Hu_MenuNewPage("WeaponOptions", &origin, 0, Hu_MenuPageTicker, Hu_MenuDrawWeaponsPage, NULL, NULL); - MNPage_SetTitle(page, "Weapons Options"); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->setTitle("Weapons Options"); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Options")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -3796,7 +3769,7 @@ void Hu_MenuInitWeaponsPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } #if __JHERETIC__ || __JHEXEN__ @@ -3806,9 +3779,9 @@ void Hu_MenuInitInventoryOptionsPage() uint const numObjects = 16; mn_page_t *page = Hu_MenuNewPage("InventoryOptions", &origin, 0, Hu_MenuPageTicker, NULL, NULL, NULL); - MNPage_SetTitle(page, "Inventory Options"); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->setTitle("Inventory Options"); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Options")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -4062,7 +4035,7 @@ void Hu_MenuInitInventoryOptionsPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } #endif @@ -4078,9 +4051,9 @@ void Hu_MenuInitSoundOptionsPage() uint const numObjects = 6; mn_page_t *page = Hu_MenuNewPage("SoundOptions", &origin, 0, Hu_MenuPageTicker, NULL, NULL, NULL); - MNPage_SetTitle(page, "Sound Options"); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->setTitle("Sound Options"); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Options")); mn_object_t *objects = (mn_object_t *)Z_Calloc(sizeof(*objects) * numObjects, PU_GAMESTATIC, 0); mn_object_t *ob = objects; @@ -4177,7 +4150,7 @@ void Hu_MenuInitSoundOptionsPage() ob->_type = MN_NONE; - page->objects = objects; + page->_objects = objects; } #if __JDOOM__ || __JHERETIC__ @@ -4269,10 +4242,10 @@ void Hu_MenuInitEpisodePage() ob->_type = MN_NONE; mn_page_t *page = Hu_MenuNewPage("Episode", &origin, MPF_LAYOUT_FIXED|MPF_NEVER_SCROLL, Hu_MenuPageTicker, Hu_MenuDrawEpisodePage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTB)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTB)); + page->setPreviousPage(Hu_MenuFindPageByName("GameType")); - page->objects = objects; + page->_objects = objects; } #endif @@ -4383,92 +4356,47 @@ void Hu_MenuInitPlayerClassPage() ob->_type = MN_NONE; mn_page_t *page = Hu_MenuNewPage("PlayerClass", &pageOrigin, MPF_LAYOUT_FIXED|MPF_NEVER_SCROLL, Hu_MenuPageTicker, Hu_MenuDrawPlayerClassPage, NULL, NULL); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTB)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("GameType")); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTB)); + page->setPreviousPage(Hu_MenuFindPageByName("GameType")); - page->objects = objects; + page->_objects = objects; } #endif -mn_page_t *MNPage_New(Point2Raw const *origin, int flags, - void (*ticker) (struct mn_page_s *page), - void (*drawer) (struct mn_page_s *page, Point2Raw const *origin), - int (*cmdResponder) (struct mn_page_s *page, menucommand_e cmd), - void *userData) +static mn_page_t *addPageToCollection(mn_page_t *page, String name) { - mn_page_t *page = (mn_page_t *) M_Malloc(sizeof(*page)); - - page->origin.x = origin? origin->x : 0; - page->origin.y = origin? origin->y : 0; - page->flags = flags; - page->objects = 0; - page->objectsCount = 0; - page->ticker = ticker; - page->drawer = drawer; - page->cmdResponder = cmdResponder; - page->previous = 0; - page->userData = userData; - Str_Init(&page->title); - - fontid_t fontId = FID(GF_FONTA); - for(int i = 0; i < MENU_FONT_COUNT; ++i) + String nameInIndex = name.toLower(); + if(pages.contains(nameInIndex)) { - page->fonts[i] = fontId; + delete pages[nameInIndex]; } - - de::zap(page->colors); - page->colors[0] = 0; - page->colors[1] = 1; - page->colors[2] = 2; - page->focus = -1; /// @todo Make this a page flag. - page->geometry = Rect_New(); - + pages.insert(nameInIndex, page); return page; } -static mn_page_t *addPageToCollection(mn_page_t *page, char const *name) -{ - if(page) - { - pages = (pagerecord_t *)M_Realloc(pages, sizeof(*pages) * ++pageCount); - - pagerecord_t *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, Point2Raw const *origin, int flags, - void (*ticker) (struct mn_page_s* page), - void (*drawer) (struct mn_page_s* page, Point2Raw const *origin), - int (*cmdResponder) (struct mn_page_s* page, menucommand_e cmd), - void* userData) +mn_page_t *Hu_MenuNewPage(char const *name, Point2Raw const *origin, int flags, + void (*ticker) (mn_page_t *page), + void (*drawer) (mn_page_t *page, Point2Raw const *origin), + int (*cmdResponder) (mn_page_t *page, menucommand_e cmd), + void *userData) { - if(!name || !name[0]) - { - DENG_ASSERT(!"Hu_MenuNewPage: Attempt to create page with an invalid name"); - return NULL; - } - - return addPageToCollection(MNPage_New(origin, flags, ticker, drawer, cmdResponder, userData), name); + DENG2_ASSERT(origin != 0); + DENG2_ASSERT(name != 0 && name[0]); + return addPageToCollection(new mn_page_t(*origin, flags, ticker, drawer, cmdResponder, userData), name); } void Hu_MenuInit() { - cvarbutton_t* cvb; + cvarbutton_t *cvb; if(inited) return; - pageCount = 0; - pages = NULL; - mnAlpha = mnTargetAlpha = 0; - menuActivePage = NULL; - menuActive = false; + menuActivePage = 0; + menuActive = false; cursorHasRotation = false; - cursorAngle = 0; - cursorAnimFrame = 0; + cursorAngle = 0; + cursorAnimFrame = 0; cursorAnimCounter = MENU_CURSOR_TICSPERFRAME; DD_Execute(true, "deactivatebcontext menu"); @@ -4609,14 +4537,14 @@ void Hu_MenuSetActivePage2(mn_page_t *page, dd_bool canReactivate) if(menuActivePage == page) { if(!canReactivate) return; - MNPage_ClearFocusObject(page); + page->clearFocusObject(); } - updatePageObjects(page); + page->updateObjects(); // This is now the "active" page. menuActivePage = page; - MNPage_Initialize(page); + page->initialize(); } void Hu_MenuSetActivePage(mn_page_t *page) @@ -4739,8 +4667,6 @@ void Hu_MenuDrawer() #define OVERLAY_DARKEN .7f dgl_borderedprojectionstate_t bp; - dd_bool showFocusCursor = true; - mn_object_t* focusObj; if(!Hu_MenuIsVisible()) return; @@ -4749,10 +4675,11 @@ void Hu_MenuDrawer() GL_BeginBorderedProjection(&bp); // First determine whether the focus cursor should be visible. - focusObj = MNPage_FocusObject(Hu_MenuActivePage()); - if(focusObj && (MNObject_Flags(focusObj) & MNF_ACTIVE)) + mn_object_t *focusOb = Hu_MenuActivePage()->focusObject(); + dd_bool showFocusCursor = true; + if(focusOb && (MNObject_Flags(focusOb) & MNF_ACTIVE)) { - if(MNObject_Type(focusObj) == MN_COLORBOX || MNObject_Type(focusObj) == MN_BINDINGS) + if(MNObject_Type(focusOb) == MN_COLORBOX || MNObject_Type(focusOb) == MN_BINDINGS) { showFocusCursor = false; } @@ -4773,9 +4700,9 @@ void Hu_MenuDrawer() GL_EndBorderedProjection(&bp); // Drawing any overlays? - if(focusObj && (MNObject_Flags(focusObj) & MNF_ACTIVE)) + if(focusOb && (MNObject_Flags(focusOb) & MNF_ACTIVE)) { - switch(MNObject_Type(focusObj)) + switch(MNObject_Type(focusOb)) { case MN_COLORBOX: case MN_BINDINGS: @@ -4783,9 +4710,9 @@ void Hu_MenuDrawer() GL_BeginBorderedProjection(&bp); beginOverlayDraw(); - if(MNObject_Type(focusObj) == MN_BINDINGS) + if(MNObject_Type(focusOb) == MN_BINDINGS) { - Hu_MenuControlGrabDrawer(MNBindings_ControlName(focusObj), 1); + Hu_MenuControlGrabDrawer(MNBindings_ControlName(focusOb), 1); } else { @@ -4805,7 +4732,7 @@ void Hu_MenuDrawer() void Hu_MenuPageTicker(mn_page_t *page) { // Normal ticker actions first. - MNPage_Ticker(page); + page->tick(); /// @todo Move game-menu specific page tick functionality here. } @@ -4837,240 +4764,11 @@ void Hu_MenuNavigatePage(mn_page_t * /*page*/, int /*pageDelta*/) if(index != oldIndex) { S_LocalSound(SFX_MENU_NAV_RIGHT, NULL); - MNPage_SetFocus(page, page->objects + index); + page->setFocus(page->objects + index); } #endif } -static void initPageObjects(mn_page_t *page) -{ - mn_object_t *ob; - assert(page); - - page->objectsCount = 0; - - for(ob = page->objects; MNObject_Type(ob) != MN_NONE; ob++) - { - page->objectsCount += 1; - - ob->_page = page; - ob->_geometry = Rect_New(); - - ob->timer = 0; - MNObject_SetFlags(ob, FO_CLEAR, MNF_FOCUS); - - if(0 != ob->_shortcut) - { - int shortcut = ob->_shortcut; - ob->_shortcut = 0; // Clear invalid defaults. - MNObject_SetShortcut(ob, shortcut); - } - - switch(MNObject_Type(ob)) - { - case MN_TEXT: { - mndata_text_t *txt = (mndata_text_t *)ob->_typedata; - MNObject_SetFlags(ob, FO_SET, MNF_NO_FOCUS); - - if(txt->text && (PTR2INT(txt->text) > 0 && PTR2INT(txt->text) < NUMTEXT)) - { - txt->text = GET_TXT(PTR2INT(txt->text)); - } - break; } - - case MN_BUTTON: { - /*mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED);*/ - mndata_button_t *btn = (mndata_button_t *)ob->_typedata; - - if(btn->text && (PTR2INT(btn->text) > 0 && PTR2INT(btn->text) < NUMTEXT)) - { - btn->text = GET_TXT(PTR2INT(btn->text)); - /// @todo Should not be done here. - MNObject_SetShortcut(ob, btn->text[0]); - } - break; } - - case MN_EDIT: { - mndata_edit_t *edit = (mndata_edit_t *) ob->_typedata; - - if(edit->emptyString && (PTR2INT(edit->emptyString) > 0 && PTR2INT(edit->emptyString) < NUMTEXT)) - { - edit->emptyString = GET_TXT(PTR2INT(edit->emptyString)); - } - break; } - - case MN_LIST: - case MN_LISTINLINE: { - mndata_list_t *list = (mndata_list_t *) ob->_typedata; - - for(int i = 0; i < list->count; ++i) - { - mndata_listitem_t *item = &((mndata_listitem_t *)list->items)[i]; - if(item->text && (PTR2INT(item->text) > 0 && PTR2INT(item->text) < NUMTEXT)) - { - item->text = GET_TXT(PTR2INT(item->text)); - } - } - break; } - - case MN_COLORBOX: { - mndata_colorbox_t *cbox = (mndata_colorbox_t *) ob->_typedata; - - if(!cbox->rgbaMode) - cbox->a = 1.f; - if(0 >= cbox->width) - cbox->width = MNDATA_COLORBOX_WIDTH; - if(0 >= cbox->height) - cbox->height = MNDATA_COLORBOX_HEIGHT; - break; } - - case MN_MOBJPREVIEW: - MNObject_SetFlags(ob, FO_SET, MNF_NO_FOCUS); - break; - - default: break; - } - } -} - -/** - * Main task is to update objects linked to cvars. - */ -static void updatePageObjects(mn_page_t *page) -{ - DENG_ASSERT(page != 0); - - mn_object_t *ob; - for(ob = page->objects; MNObject_Type(ob) != MN_NONE; ob++) - { - switch(MNObject_Type(ob)) - { - case MN_TEXT: - case MN_MOBJPREVIEW: - MNObject_SetFlags(ob, FO_SET, MNF_NO_FOCUS); - break; - - case MN_BUTTON: { - mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); - mndata_button_t *btn = (mndata_button_t *)ob->_typedata; - - if(action && action->callback == Hu_MenuCvarButton) - { - cvarbutton_t *cvb; - if(ob->data1) - { - // This button has already been initialized. - cvb = (cvarbutton_t *) ob->data1; - cvb->active = (Con_GetByte(cvb->cvarname) & (cvb->mask? cvb->mask : ~0)) != 0; - //strcpy(obj->text, cvb->active ? cvb->yes : cvb->no); - btn->text = cvb->active ? cvb->yes : cvb->no; - continue; - } - - // Find the cvarbutton representing this one. - for(cvb = mnCVarButtons; cvb->cvarname; cvb++) - { - if(!strcmp((char const *)btn->data, cvb->cvarname) && ob->data2 == cvb->mask) - { - cvb->active = (Con_GetByte(cvb->cvarname) & (cvb->mask? cvb->mask : ~0)) != 0; - ob->data1 = (void*) cvb; - - btn->yes = cvb->yes; - btn->no = cvb->no; - btn->text = (cvb->active ? btn->yes : btn->no); - break; - } - } - cvb = 0; - } - break; } - - case MN_LIST: - case MN_LISTINLINE: { - mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); - mndata_list_t *list = (mndata_list_t *) ob->_typedata; - - if(action && action->callback == Hu_MenuCvarList) - { - MNList_SelectItemByValue(ob, MNLIST_SIF_NO_ACTION, Con_GetInteger((char const *)list->data)); - } - break; } - - case MN_EDIT: { - mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); - mndata_edit_t *edit = (mndata_edit_t *) ob->_typedata; - - if(action && action->callback == Hu_MenuCvarEdit) - { - MNEdit_SetText(ob, MNEDIT_STF_NO_ACTION, Con_GetString((char const *)edit->data1)); - } - break; } - - case MN_SLIDER: { - mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); - mndata_slider_t *sldr = (mndata_slider_t *) ob->_typedata; - if(action && action->callback == Hu_MenuCvarSlider) - { - float value; - if(sldr->floatMode) - value = Con_GetFloat((char const *)sldr->data1); - else - value = Con_GetInteger((char const *)sldr->data1); - MNSlider_SetValue(ob, MNSLIDER_SVF_NO_ACTION, value); - } - break; } - - case MN_COLORBOX: { - mndata_colorbox_t *cbox = (mndata_colorbox_t *) ob->_typedata; - mn_actioninfo_t const *action = MNObject_Action(ob, MNA_MODIFIED); - - if(action && action->callback == Hu_MenuCvarColorBox) - { - float rgba[4]; - rgba[CR] = Con_GetFloat((char const *)cbox->data1); - rgba[CG] = Con_GetFloat((char const *)cbox->data2); - rgba[CB] = Con_GetFloat((char const *)cbox->data3); - rgba[CA] = (cbox->rgbaMode? Con_GetFloat((char const *)cbox->data4) : 1.f); - MNColorBox_SetColor4fv(ob, MNCOLORBOX_SCF_NO_ACTION, rgba); - } - break; } - - default: break; - } - } -} - -static void destroyPageObjects(mn_page_t *page) -{ - mn_object_t *obj; - if(!page) return; - for(obj = page->objects; MNObject_Type(obj) != MN_NONE; obj++) - { - if(obj->_geometry) - { - Rect_Delete(obj->_geometry); - 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 initAllPages() { Hu_MenuInitColorWidgetPage(); @@ -5104,30 +4802,21 @@ static void initAllPages() static void destroyAllPages() { - 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); + qDeleteAll(pages); + pages.clear(); } static void initAllObjectsOnAllPages() { - int i; - for(i = 0; i < pageCount; ++i) + foreach(mn_page_t *page, pages) { - pagerecord_t* rec = pages + i; - initPageObjects(rec->page); + page->initObjects(); } } int Hu_MenuColorWidgetCmdResponder(mn_page_t *page, menucommand_e cmd) { - assert(page); + DENG2_ASSERT(page); switch(cmd) { case MCMD_NAV_OUT: { @@ -5166,7 +4855,7 @@ int Hu_MenuColorWidgetCmdResponder(mn_page_t *page, menucommand_e cmd) static void fallbackCommandResponder(mn_page_t *page, menucommand_e cmd) { - assert(page); + DENG2_ASSERT(page != 0); switch(cmd) { case MCMD_NAV_PAGEUP: @@ -5177,7 +4866,7 @@ static void fallbackCommandResponder(mn_page_t *page, menucommand_e cmd) case MCMD_NAV_UP: case MCMD_NAV_DOWN: { - mn_object_t *obj = MNPage_FocusObject(page); + mn_object_t *obj = page->focusObject(); // An object on this page must have focus in order to navigate. if(obj) { @@ -5186,15 +4875,15 @@ static void fallbackCommandResponder(mn_page_t *page, menucommand_e cmd) { giveFocus += (cmd == MCMD_NAV_UP? -1 : 1); if(giveFocus < 0) - giveFocus = page->objectsCount - 1; - else if(giveFocus >= page->objectsCount) + giveFocus = page->objectsCount() - 1; + else if(giveFocus >= page->objectsCount()) giveFocus = 0; - } while(++i < page->objectsCount && (MNObject_Flags(page->objects + giveFocus) & (MNF_DISABLED | MNF_NO_FOCUS | MNF_HIDDEN))); + } while(++i < page->objectsCount() && (MNObject_Flags(&page->objects()[giveFocus]) & (MNF_DISABLED | MNF_NO_FOCUS | MNF_HIDDEN))); if(giveFocus != page->focus) { S_LocalSound(cmd == MCMD_NAV_UP? SFX_MENU_NAV_UP : SFX_MENU_NAV_DOWN, NULL); - MNPage_SetFocus(page, page->objects + giveFocus); + page->setFocus(&page->objects()[giveFocus]); } } break; @@ -5211,6 +4900,7 @@ static void fallbackCommandResponder(mn_page_t *page, menucommand_e cmd) Hu_MenuSetActivePage(page->previous); } break; + default: // DEBUG_Message("Warning: fallbackCommandResponder: Command %i not processed, ignoring.\n", (int) cmd); break; @@ -5224,7 +4914,7 @@ static menucommand_e translateCommand(menucommand_e cmd) // "active" widget - interpret the command instead as "navigate out". if(menuActive && (cmd == MCMD_CLOSE || cmd == MCMD_CLOSEFAST)) { - mn_object_t *obj = MNPage_FocusObject(Hu_MenuActivePage()); + mn_object_t *obj = Hu_MenuActivePage()->focusObject(); if(obj) { switch(MNObject_Type(obj)) @@ -5248,7 +4938,7 @@ static menucommand_e translateCommand(menucommand_e cmd) void Hu_MenuCommand(menucommand_e cmd) { mn_page_t *page; - mn_object_t *obj; + mn_object_t *ob; cmd = translateCommand(cmd); @@ -5326,10 +5016,10 @@ void Hu_MenuCommand(menucommand_e cmd) } // Try the current focus object. - obj = MNPage_FocusObject(page); - if(obj && obj->cmdResponder) + ob = page->focusObject(); + if(ob && ob->cmdResponder) { - if(obj->cmdResponder(obj, cmd)) + if(ob->cmdResponder(ob, cmd)) return; } @@ -5347,7 +5037,7 @@ int Hu_MenuPrivilegedResponder(event_t* ev) { if(Hu_MenuIsActive()) { - mn_object_t *obj = MNPage_FocusObject(Hu_MenuActivePage()); + mn_object_t *obj = Hu_MenuActivePage()->focusObject(); if(obj && !(MNObject_Flags(obj) & MNF_DISABLED)) { if(obj->privilegedResponder) @@ -5363,7 +5053,7 @@ int Hu_MenuResponder(event_t* ev) { if(Hu_MenuIsActive()) { - mn_object_t *obj = MNPage_FocusObject(Hu_MenuActivePage()); + mn_object_t *obj = Hu_MenuActivePage()->focusObject(); if(obj && !(MNObject_Flags(obj) & MNF_DISABLED)) { if(obj->responder) @@ -5375,7 +5065,7 @@ int Hu_MenuResponder(event_t* ev) return false; // Not eaten. } -int Hu_MenuFallbackResponder(event_t* ev) +int Hu_MenuFallbackResponder(event_t *ev) { mn_page_t *page = Hu_MenuActivePage(); @@ -5385,16 +5075,15 @@ int Hu_MenuFallbackResponder(event_t* ev) { if(ev->type == EV_KEY && (ev->state == EVS_DOWN || ev->state == EVS_REPEAT)) { - int i; - for(i = 0; i < page->objectsCount; ++i) + for(int i = 0; i < page->objectsCount(); ++i) { - mn_object_t *obj = &page->objects[i]; + mn_object_t *obj = &page->objects()[i]; if(MNObject_Flags(obj) & (MNF_DISABLED | MNF_NO_FOCUS | MNF_HIDDEN)) continue; if(MNObject_Shortcut(obj) == ev->data1) { - MNPage_SetFocus(page, obj); + page->setFocus(obj); return true; } } @@ -5406,14 +5095,14 @@ int Hu_MenuFallbackResponder(event_t* ev) /** * User wants to load this game */ -int Hu_MenuSelectLoadSlot(mn_object_t *obj, mn_actionid_t action, void * /*context*/) +int Hu_MenuSelectLoadSlot(mn_object_t *ob, mn_actionid_t action, void * /*context*/) { - mndata_edit_t *edit = (mndata_edit_t *)obj->_typedata; + mndata_edit_t *edit = (mndata_edit_t *)ob->_typedata; if(MNA_ACTIVEOUT != action) return 1; mn_page_t *saveGamePage = Hu_MenuFindPageByName("SaveGame"); - MNPage_SetFocus(saveGamePage, MNPage_FindObject(saveGamePage, 0, obj->data2)); + saveGamePage->setFocus(saveGamePage->findObject(0, ob->data2)); G_SetGameActionLoadSession((char *)edit->data1); Hu_MenuCommand(chooseCloseMethod()); @@ -5496,12 +5185,12 @@ static void composeNotDesignedForMessage(char const *str) */ void Hu_MenuPlayerClassBackgroundTicker(mn_object_t *ob) { - DENG_ASSERT(ob != 0); + DENG2_ASSERT(ob != 0); // Determine our selection according to the current focus object. /// @todo Do not search for the focus object, flag the "random" /// state through a focus action. - if(mn_object_t *mop = MNPage_FocusObject(MNObject_Page(ob))) + if(mn_object_t *mop = MNObject_Page(ob)->focusObject()) { playerclass_t pClass = (playerclass_t) mop->data2; if(pClass == PCLASS_NONE) @@ -5527,12 +5216,12 @@ void Hu_MenuPlayerClassBackgroundTicker(mn_object_t *ob) */ void Hu_MenuPlayerClassPreviewTicker(mn_object_t *ob) { - DENG_ASSERT(ob != 0); + DENG2_ASSERT(ob != 0); // Determine our selection according to the current focus object. /// @todo Do not search for the focus object, flag the "random" /// state through a focus action. - if(mn_object_t *mop = MNPage_FocusObject(MNObject_Page(ob))) + if(mn_object_t *mop = MNObject_Page(ob)->focusObject()) { playerclass_t pClass = (playerclass_t) mop->data2; if(pClass == PCLASS_NONE) @@ -5575,8 +5264,8 @@ void Hu_MenuDrawEpisodePage(mn_page_t *page, Point2Raw const *origin) DENG2_UNUSED(origin); // Inform the user episode 6 is designed for deathmatch only. - mn_object_t *obj = MNPage_FindObject(page, 0, MNF_ID0); - if(obj && obj == MNPage_FocusObject(page)) + mn_object_t *obj = page->findObject(0, MNF_ID0); + if(obj && obj == page->focusObject()) { Point2Raw origin; @@ -5649,10 +5338,10 @@ int Hu_MenuSelectSaveSlot(mn_object_t *ob, mn_actionid_t action, void * /*contex } mn_page_t *page = Hu_MenuFindPageByName("SaveGame"); - MNPage_SetFocus(page, MN_MustFindObjectOnPage(page, 0, ob->data2)); + page->setFocus(MN_MustFindObjectOnPage(page, 0, ob->data2)); page = Hu_MenuFindPageByName("LoadGame"); - MNPage_SetFocus(page, MN_MustFindObjectOnPage(page, 0, ob->data2)); + page->setFocus(MN_MustFindObjectOnPage(page, 0, ob->data2)); Hu_MenuCommand(chooseCloseMethod()); return 0; @@ -5819,7 +5508,7 @@ int Hu_MenuActivateColorWidget(mn_object_t *ob, mn_actionid_t action, void * /*c colorWidgetActive = true; - MNPage_Initialize(colorWidgetPage); + colorWidgetPage->initialize(); colorWidgetPage->userData = ob; MNColorBox_CopyColor(cboxMix, 0, ob); @@ -5926,7 +5615,7 @@ void Hu_MenuDrawOptionsPage(mn_page_t * /*page*/, Point2Raw const *origin) void Hu_MenuDrawWeaponsPage(mn_page_t *page, Point2Raw const * /*offset*/) { // Inform the user how to change the order. - if(MNPage_FocusObject(page) == MN_MustFindObjectOnPage(page, 0, MNF_ID0)) + if(page->focusObject() == MN_MustFindObjectOnPage(page, 0, MNF_ID0)) { char const *helpText = "Use left/right to move weapon up/down"; Point2Raw origin; @@ -6285,9 +5974,9 @@ int Hu_MenuSelectPlayerClass(mn_object_t *ob, mn_actionid_t action, void * /*con switch(mnPlrClass) { - case PCLASS_FIGHTER: MNPage_SetX(skillPage, 120); break; - case PCLASS_CLERIC: MNPage_SetX(skillPage, 116); break; - case PCLASS_MAGE: MNPage_SetX(skillPage, 112); break; + case PCLASS_FIGHTER: skillPage->setX(120); break; + case PCLASS_CLERIC: skillPage->setX(116); break; + case PCLASS_MAGE: skillPage->setX(112); break; } Hu_MenuSetActivePage(skillPage); return 0; diff --git a/doomsday/plugins/common/src/m_ctrl.cpp b/doomsday/plugins/common/src/m_ctrl.cpp index 82b83537ad..aac76b85d1 100644 --- a/doomsday/plugins/common/src/m_ctrl.cpp +++ b/doomsday/plugins/common/src/m_ctrl.cpp @@ -336,10 +336,10 @@ void Hu_MenuInitControlsPage() objects[objectIdx]._type = MN_NONE; // Terminate. mn_page_t *page = Hu_MenuNewPage("ControlOptions", &pageOrigin, 0, Hu_MenuPageTicker, Hu_MenuDrawControlsPage, NULL, NULL); - page->objects = objects; - MNPage_SetTitle(page, "Controls"); - MNPage_SetPredefinedFont(page, MENU_FONT1, FID(GF_FONTA)); - MNPage_SetPreviousPage(page, Hu_MenuFindPageByName("Options")); + page->_objects = objects; + page->setTitle("Controls"); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); + page->setPreviousPage(Hu_MenuFindPageByName("Options")); } static void drawSmallText(char const *string, int x, int y, float alpha) diff --git a/doomsday/plugins/common/src/saveslots.cpp b/doomsday/plugins/common/src/saveslots.cpp index c41c2c8064..602990367a 100644 --- a/doomsday/plugins/common/src/saveslots.cpp +++ b/doomsday/plugins/common/src/saveslots.cpp @@ -91,7 +91,7 @@ DENG2_PIMPL_NOREF(SaveSlots::Slot) mn_page_t *page = Hu_MenuFindPageByName("LoadGame"); if(!page) return; // Not initialized yet? - mn_object_t *ob = MNPage_FindObject(page, 0, menuWidgetId); + mn_object_t *ob = page->findObject(0, menuWidgetId); if(!ob) { LOG_DEBUG("Failed locating menu widget with id ") << menuWidgetId;