From 5f42f82433516de62aa6704d55824f042eb6e699 Mon Sep 17 00:00:00 2001 From: Andre Taulien Date: Mon, 2 Jan 2017 00:57:49 +0100 Subject: [PATCH] Implemented better menu behavior, linked save/load menu --- src/logic/PlayerController.cpp | 43 +++++++------- src/logic/PlayerController.h | 10 ++++ src/ui/Hud.cpp | 100 +++++++++++++++------------------ src/ui/Hud.h | 34 +++++++---- src/ui/Menu.cpp | 14 ++--- src/ui/Menu.h | 8 +++ src/ui/Menu_Main.cpp | 20 ++++--- src/ui/Menu_Save.cpp | 13 ----- 8 files changed, 127 insertions(+), 115 deletions(-) diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index b3dc9667..ae6f0bbc 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -1860,7 +1860,12 @@ void PlayerController::setupKeyBindings() Engine::Input::RegisterAction(Engine::ActionType::OpenStatusMenu, [this](bool triggered, float) { if(triggered) - m_World.getEngine()->getHud().getStatusMenu().setHidden(!m_World.getEngine()->getHud().getStatusMenu().isHidden()); + { + UI::Menu_Status& statsScreen = m_World.getEngine()->getHud().pushMenu(); + + // Update the players status menu once + updateStatusScreen(statsScreen); + } }); Engine::Input::RegisterAction(Engine::ActionType::OpenConsole, [this](bool triggered, float) { @@ -2358,24 +2363,6 @@ void PlayerController::onUpdateForPlayer(float deltaTime) hud.setMana(stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_MANA] / (float)stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_MANAMAX]); - // Status screen - UI::Menu_Status& statsScreen = hud.getStatusMenu(); - if(!statsScreen.isHidden()) - { - statsScreen.setAttribute(UI::Menu_Status::A_STR, stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_STRENGTH]); - statsScreen.setAttribute(UI::Menu_Status::A_DEX, stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_STRENGTH]); - - statsScreen.setAttribute(UI::Menu_Status::A_MANA, stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_MANA], - stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_MANAMAX]); - statsScreen.setAttribute(UI::Menu_Status::A_HEALTH, stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_HITPOINTS], - stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_HITPOINTSMAX]); - - statsScreen.setGuild(getGuildName()); - statsScreen.setLevel(stats.level); - statsScreen.setExperience(stats.exp); - statsScreen.setExperienceNext(stats.exp_next); - statsScreen.setLearnPoints(stats.lp); - } } std::string PlayerController::getGuildName() @@ -2387,9 +2374,21 @@ std::string PlayerController::getGuildName() return *adr; } +void PlayerController::updateStatusScreen(UI::Menu_Status& statsScreen) +{ + auto& stats = getScriptInstance(); + statsScreen.setAttribute(UI::Menu_Status::A_STR, stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_STRENGTH]); + statsScreen.setAttribute(UI::Menu_Status::A_DEX, stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_STRENGTH]); + statsScreen.setAttribute(UI::Menu_Status::A_MANA, stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_MANA], + stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_MANAMAX]); + statsScreen.setAttribute(UI::Menu_Status::A_HEALTH, stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_HITPOINTS], + stats.attribute[Daedalus::GEngineClasses::C_Npc::EATR_HITPOINTSMAX]); - - - + statsScreen.setGuild(getGuildName()); + statsScreen.setLevel(stats.level); + statsScreen.setExperience(stats.exp); + statsScreen.setExperienceNext(stats.exp_next); + statsScreen.setLearnPoints(stats.lp); +} diff --git a/src/logic/PlayerController.h b/src/logic/PlayerController.h index a95bd156..744252b6 100755 --- a/src/logic/PlayerController.h +++ b/src/logic/PlayerController.h @@ -7,6 +7,11 @@ #include "LogicDef.h" #include "NpcScriptState.h" +namespace UI +{ + class Menu_Status; +} + namespace Logic { class ModelVisual; @@ -351,6 +356,11 @@ namespace Logic */ void setupKeyBindings(); + /** + * Updates the given status-screen once with the current attributes + */ + void updateStatusScreen(UI::Menu_Status& statsScreen); + /** * @return Item this NPC is currently interacting with */ diff --git a/src/ui/Hud.cpp b/src/ui/Hud.cpp index 0a48a827..58aa291e 100644 --- a/src/ui/Hud.cpp +++ b/src/ui/Hud.cpp @@ -26,30 +26,6 @@ UI::Hud::Hud(Engine::BaseEngine& e) : View(e) m_pDialogBox = new DialogBox(m_Engine); m_pDialogBox->setHidden(true); - // Menus - m_pStatusMenu = Menu_Status::create(m_Engine); - m_RegisteredMenus.push_back(m_pStatusMenu); - m_pStatusMenu->setHidden(true); - - m_pMainMenu = Menu_Main::create(m_Engine); - m_RegisteredMenus.push_back(m_pMainMenu); - m_pMainMenu->setHidden(true); - - m_pMenuLoad = Menu_Load::create(m_Engine); - m_RegisteredMenus.push_back(m_pMenuLoad ); - m_pMenuLoad->setHidden(true); - - m_pMenuSave = Menu_Save::create(m_Engine); - m_RegisteredMenus.push_back(m_pMenuSave); - m_pMenuSave->setHidden(false); - - m_pMenuSettings = Menu_Settings::create(m_Engine); - m_RegisteredMenus.push_back(m_pMenuSettings); - m_pMenuSettings->setHidden(true); - - for(Menu* m : m_RegisteredMenus) - addChild(m); - addChild(m_pHealthBar); addChild(m_pManaBar); addChild(m_pEnemyHealthBar); @@ -113,11 +89,8 @@ UI::Hud::~Hud() removeChild(m_pClock); removeChild(m_pDialogBox); - for(Menu* m : m_RegisteredMenus) - { - removeChild(m); - delete m; - } + while(!m_MenuChain.empty()) + popMenu(); delete m_pManaBar; delete m_pHealthBar; @@ -128,6 +101,18 @@ UI::Hud::~Hud() void UI::Hud::update(double dt, Engine::Input::MouseState& mstate, Render::RenderConfig& config) { + // Free old menus + cleanMenus(); + + // Only draw last menu in the menu-chain + if(!m_MenuChain.empty()) + { + for(Menu* m : m_MenuChain) + m->setHidden(true); + + m_MenuChain.back()->setHidden(false); + } + View::update(dt, mstate, config); } @@ -153,36 +138,22 @@ void UI::Hud::setTimeOfDay(const std::string& timeStr) void UI::Hud::onInputAction(UI::EInputAction action) { - // Close console, in case it's open - if(action == IA_Close) + // Notify last menu in chain + if(!m_MenuChain.empty()) { - m_Console.setOpen(false); - - // FIXME: Menu-bindings need to be reworked! - if(m_pDialogBox->isHidden() && m_pStatusMenu->isHidden() ) - { - m_pMainMenu->setHidden(!m_pMainMenu->isHidden()); - } + m_MenuChain.back()->onInputAction(action); } - // Notify all menus - // TODO: Do this in a loop - if(!m_pStatusMenu->isHidden()) - m_pStatusMenu->onInputAction(action); - - if(!m_pMenuLoad->isHidden()) - m_pMenuLoad->onInputAction(action); - - if(!m_pMenuSave->isHidden()) - m_pMenuSave->onInputAction(action); - - if(!m_pMenuSettings->isHidden()) - m_pMenuSettings->onInputAction(action); - if(!m_pDialogBox->isHidden()) - m_pDialogBox->onInputAction(action); - - if(!m_pMainMenu->isHidden() && action != IA_Close) - m_pMainMenu->onInputAction(action); + // Close console or last menu, in case it's open + if(action == IA_Close) + { + if(m_Console.isOpen()) + m_Console.setOpen(false); + else if(!m_MenuChain.empty()) + popMenu(); + else // Nothing is open right now. Show main-menu + pushMenu(); + } } void UI::Hud::setGameplayHudVisible(bool value) @@ -190,3 +161,20 @@ void UI::Hud::setGameplayHudVisible(bool value) for(View* v : m_GameplayHudElements) v->setHidden(!value); } + +void UI::Hud::popMenu() +{ + // Move to other list to delete in the next frame. This makes it possible for menus to close themselfes. + m_MenusToDelete.push_back(m_MenuChain.back()); + + removeChild(m_MenuChain.back()); + m_MenuChain.pop_back(); +} + +void UI::Hud::cleanMenus() +{ + for(Menu* m : m_MenusToDelete) + delete m; + + m_MenusToDelete.clear(); +} diff --git a/src/ui/Hud.h b/src/ui/Hud.h index fa91f222..c49852ce 100644 --- a/src/ui/Hud.h +++ b/src/ui/Hud.h @@ -65,16 +65,6 @@ namespace UI */ void onInputAction(EInputAction action); - /** - * @return Access to the menus - */ - Menu_Status& getStatusMenu(){ return *m_pStatusMenu; } - Menu_Load& getLoadMenu(){ return *m_pMenuLoad; } - Menu_Save& getSaveMenu(){ return *m_pMenuSave; } - Menu_Settings& getSettingsMenu(){ return *m_pMenuSettings; } - Menu_Main& getMainMenu(){ return *m_pMainMenu; } - - /** * @return Games console */ @@ -89,8 +79,26 @@ namespace UI * Controls visibility of gameplay-hud */ void setGameplayHudVisible(bool value); + + /** + * Appends a menu to the current menu-chain. + * @tparam T Type of menu to append. Must have a static 'create' function! + */ + template + T& pushMenu() { m_MenuChain.push_back(T::create(m_Engine)); addChild((View*)m_MenuChain.back()); return *(T*)m_MenuChain.back(); } + + /** + * Pops the last menu from the chain and frees its memory. + */ + void popMenu(); + protected: + /** + * Deletes all menus stored in the m_MenusToDelete-list + */ + void cleanMenus(); + /** * All views qualifying as used while normal gameplay */ @@ -116,6 +124,12 @@ namespace UI Menu_Save* m_pMenuSave; Menu_Settings* m_pMenuSettings; + /** + * Chain of opened menus. Only the last one will be rendered and processed + */ + std::list m_MenuChain; + std::list m_MenusToDelete; // Menus to be deleted next frame + /** * All menus registered here */ diff --git a/src/ui/Menu.cpp b/src/ui/Menu.cpp index 39382ce8..ed7b9d7e 100644 --- a/src/ui/Menu.cpp +++ b/src/ui/Menu.cpp @@ -11,6 +11,7 @@ #include #include "ImageView.h" #include "TextView.h" +#include "Hud.h" UI::Menu::Menu(Engine::BaseEngine& e) : View(e), m_pVM(nullptr) { @@ -282,13 +283,8 @@ void UI::Menu::performSelectAction(Daedalus::GameState::MenuItemHandle item) switch(iData->getSelectionEvent(0)) { - case SEL_EVENT_CLOSE: - setHidden(true); - break; - - case SEL_EVENT_EXECUTE: - { - } + case SEL_ACTION_BACK: + m_Engine.getHud().popMenu(); break; default: @@ -300,4 +296,8 @@ void UI::Menu::performSelectAction(Daedalus::GameState::MenuItemHandle item) if(!customFn.empty()) onCustomAction(customFn); } +UI::Hud& UI::Menu::getHud() +{ + return m_Engine.getHud(); +} diff --git a/src/ui/Menu.h b/src/ui/Menu.h index 14e3ba34..5058a46f 100644 --- a/src/ui/Menu.h +++ b/src/ui/Menu.h @@ -19,6 +19,7 @@ namespace UI class MenuItem; class ImageView; class TextView; + class Hud; class Menu : public View { public: @@ -58,6 +59,13 @@ namespace UI * @param action Input action */ virtual void onInputAction(EInputAction action); + + + /** + * @return Underlaying HUD + */ + Hud& getHud(); + protected: /** diff --git a/src/ui/Menu_Main.cpp b/src/ui/Menu_Main.cpp index 2442f685..cecb3f4c 100644 --- a/src/ui/Menu_Main.cpp +++ b/src/ui/Menu_Main.cpp @@ -2,6 +2,10 @@ #include #include "Menu_Main.h" #include +#include "Hud.h" +#include "Menu_Load.h" +#include "Menu_Save.h" +#include "Menu_Settings.h" using namespace UI; @@ -30,7 +34,7 @@ void Menu_Main::onInputAction(EInputAction action) case IA_Down:break; case IA_Left:break; case IA_Right:break; - case IA_Close: setHidden(true); break; + case IA_Close: getHud().popMenu(); break; case IA_Accept:break; } } @@ -40,19 +44,21 @@ void Menu_Main::onCustomAction(const std::string& action) { if(action == "NEW_GAME") { + getHud().popMenu(); + LogInfo() << "Starting new game..."; m_Engine.loadWorld(m_Engine.getEngineArgs().startupZEN); }else if(action == "MENU_SAVEGAME_LOAD") { - + getHud().pushMenu(); }else if(action == "MENU_SAVEGAME_SAVE") { - - }else if(action == "") + getHud().pushMenu(); + }else if(action == "MENU_OPTIONS") { - - }else if(action == "") + getHud().pushMenu(); + }else if(action == "MENU_LEAVE_GAME") { - + exit(0); // TODO: May want to exit properly at some point. } } diff --git a/src/ui/Menu_Save.cpp b/src/ui/Menu_Save.cpp index a16a04b7..d32569a8 100644 --- a/src/ui/Menu_Save.cpp +++ b/src/ui/Menu_Save.cpp @@ -28,18 +28,5 @@ void Menu_Save::performSelectAction(Daedalus::GameState::MenuItemHandle item) using namespace Daedalus::GEngineClasses::MenuConstants; - switch(iData->getSelectionEvent(0)) - { - case SEL_ACTION_BACK: - setHidden(true); - - // Open Main-Menu again - m_Engine.getHud().getMainMenu().setHidden(false); - return; - - default: - break; - } - Menu::performSelectAction(item); }