From 16aa13721a54bb0faccb40eb2d6cdfb293d48374 Mon Sep 17 00:00:00 2001 From: Jan Borsodi Date: Fri, 22 Oct 2010 22:53:34 +0200 Subject: [PATCH] Updated all dialogs to use a garbage list for postponed cleanup, this list is cleared in update() which is called for each frame. Fixed incorrect code in onCreateClassDialogBack, should use set class from pickClassDialog. Add private method setGuiMode() which calls the input manager, updated all gui-mode changes in WindowManager to use that. --- apps/openmw/mwgui/window_manager.cpp | 278 ++++++++++++++++++--------- apps/openmw/mwgui/window_manager.hpp | 30 +++ apps/openmw/mwinput/inputmanager.cpp | 8 + 3 files changed, 225 insertions(+), 91 deletions(-) diff --git a/apps/openmw/mwgui/window_manager.cpp b/apps/openmw/mwgui/window_manager.cpp index 327020aa71..ca8d2e140d 100644 --- a/apps/openmw/mwgui/window_manager.cpp +++ b/apps/openmw/mwgui/window_manager.cpp @@ -36,6 +36,8 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment , reviewNext(false) , gui(_gui) , mode(GM_Game) + , nextMode(GM_Game) + , needModeChange(false) , shown(GW_ALL) , allowed(newGame ? GW_None : GW_ALL) { @@ -93,6 +95,37 @@ WindowManager::~WindowManager() delete reviewDialog; } +void WindowManager::update() +{ + // Delete any dialogs which no longer in use + if (!garbageDialogs.empty()) + { + for (std::vector::iterator it = garbageDialogs.begin(); it != garbageDialogs.end(); ++it) + { + delete *it; + } + garbageDialogs.clear(); + } + + if (needModeChange) + { + needModeChange = false; + environment.mInputManager->setGuiMode(nextMode); + nextMode = GM_Game; + } +} + +void WindowManager::setNextMode(GuiMode newMode) +{ + nextMode = newMode; + needModeChange = true; +} + +void WindowManager::setGuiMode(GuiMode newMode) +{ + environment.mInputManager->setGuiMode(newMode); +} + void WindowManager::updateVisible() { // Start out by hiding everything except the HUD @@ -128,9 +161,12 @@ void WindowManager::updateVisible() if (mode == GM_Name) { - if (!nameDialog) - nameDialog = new TextInputDialog(environment, gui->getViewSize()); - + if (nameDialog) + { + nameDialog->setVisible(false); + garbageDialogs.push_back(nameDialog); + } + nameDialog = new TextInputDialog(environment, gui->getViewSize()); std::string sName = getGameSettingString("sName", "Name"); nameDialog->setTextLabel(sName); nameDialog->setNextButtonShow(nameChosen); @@ -141,8 +177,12 @@ void WindowManager::updateVisible() if (mode == GM_Race) { - if (!raceDialog) - raceDialog = new RaceDialog(environment, gui->getViewSize()); + if (raceDialog) + { + raceDialog->setVisible(false); + garbageDialogs.push_back(raceDialog); + } + raceDialog = new RaceDialog(environment, gui->getViewSize()); raceDialog->setNextButtonShow(raceChosen); raceDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onRaceDialogDone); raceDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onRaceDialogBack); @@ -153,7 +193,10 @@ void WindowManager::updateVisible() if (mode == GM_Class) { if (classChoiceDialog) - delete classChoiceDialog; + { + classChoiceDialog->setVisible(false); + garbageDialogs.push_back(classChoiceDialog); + } classChoiceDialog = new ClassChoiceDialog(environment); classChoiceDialog->eventButtonSelected = MyGUI::newDelegate(this, &WindowManager::onClassChoice); return; @@ -168,8 +211,12 @@ void WindowManager::updateVisible() if (mode == GM_ClassPick) { - if (!pickClassDialog) - pickClassDialog = new PickClassDialog(environment, gui->getViewSize()); + if (pickClassDialog) + { + pickClassDialog->setVisible(false); + garbageDialogs.push_back(pickClassDialog); + } + pickClassDialog = new PickClassDialog(environment, gui->getViewSize()); pickClassDialog->setNextButtonShow(classChosen); pickClassDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onPickClassDialogDone); pickClassDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onPickClassDialogBack); @@ -180,7 +227,10 @@ void WindowManager::updateVisible() if (mode == GM_ClassCreate) { if (createClassDialog) - delete createClassDialog; + { + createClassDialog->setVisible(false); + garbageDialogs.push_back(createClassDialog); + } createClassDialog = new CreateClassDialog(environment, gui->getViewSize()); createClassDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onCreateClassDialogDone); createClassDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onCreateClassDialogBack); @@ -190,9 +240,14 @@ void WindowManager::updateVisible() if (mode == GM_Birth) { - if (!birthSignDialog) - birthSignDialog = new BirthDialog(environment, gui->getViewSize()); + if (birthSignDialog) + { + birthSignDialog->setVisible(false); + garbageDialogs.push_back(birthSignDialog); + } + birthSignDialog = new BirthDialog(environment, gui->getViewSize()); birthSignDialog->setNextButtonShow(birthSignChosen); + birthSignDialog->setBirthId(playerBirthSignId); birthSignDialog->eventDone = MyGUI::newDelegate(this, &WindowManager::onBirthSignDialogDone); birthSignDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onBirthSignDialogBack); birthSignDialog->open(); @@ -202,9 +257,12 @@ void WindowManager::updateVisible() if (mode == GM_Review) { reviewNext = false; - if (!reviewDialog) - reviewDialog = new ReviewDialog(environment, gui->getViewSize()); - + if (reviewDialog) + { + reviewDialog->setVisible(false); + garbageDialogs.push_back(reviewDialog); + } + reviewDialog = new ReviewDialog(environment, gui->getViewSize()); reviewDialog->setPlayerName(playerName); reviewDialog->setRace(playerRaceId); reviewDialog->setClass(playerClass); @@ -259,7 +317,7 @@ void WindowManager::updateVisible() // Unsupported mode, switch back to game // Note: The call will eventually end up this method again but // will stop at the check if(mode == GM_Game) above. - environment.mInputManager->setGuiMode(GM_Game); + setGuiMode(GM_Game); } void WindowManager::setValue (const std::string& id, const MWMechanics::Stat& value) @@ -434,81 +492,91 @@ void WindowManager::updateCharacterGeneration() void WindowManager::onNameDialogDone() { - nameDialog->eventDone = MWGui::TextInputDialog::EventHandle_Void(); + if (nameDialog) + { + environment.mMechanicsManager->setPlayerName(nameDialog->getTextInput()); + nameDialog->eventDone = MWGui::TextInputDialog::EventHandle_Void(); + nameDialog->setVisible(false); + garbageDialogs.push_back(nameDialog); + nameDialog = nullptr; + } bool goNext = nameChosen; // Go to next dialog if name was previously chosen nameChosen = true; - if (nameDialog) - { - nameDialog->setVisible(false); - environment.mMechanicsManager->setPlayerName(nameDialog->getTextInput()); - } updateCharacterGeneration(); if (reviewNext) - environment.mInputManager->setGuiMode(GM_Review); + setGuiMode(GM_Review); else if (goNext) - environment.mInputManager->setGuiMode(GM_Race); + setGuiMode(GM_Race); else - environment.mInputManager->setGuiMode(GM_Game); + setGuiMode(GM_Game); } void WindowManager::onRaceDialogDone() { - raceDialog->eventDone = MWGui::RaceDialog::EventHandle_Void(); + if (raceDialog) + { + environment.mMechanicsManager->setPlayerRace(raceDialog->getRaceId(), raceDialog->getGender() == RaceDialog::GM_Male); + raceDialog->eventDone = MWGui::RaceDialog::EventHandle_Void(); + raceDialog->setVisible(false); + garbageDialogs.push_back(raceDialog); + raceDialog = nullptr; + } bool goNext = raceChosen; // Go to next dialog if race was previously chosen raceChosen = true; - if (raceDialog) - { - raceDialog->setVisible(false); - environment.mMechanicsManager->setPlayerRace(raceDialog->getRaceId(), raceDialog->getGender() == RaceDialog::GM_Male); - } updateCharacterGeneration(); if (reviewNext) - environment.mInputManager->setGuiMode(GM_Review); + setGuiMode(GM_Review); else if (goNext) - environment.mInputManager->setGuiMode(GM_Class); + setGuiMode(GM_Class); else - environment.mInputManager->setGuiMode(GM_Game); + setGuiMode(GM_Game); } void WindowManager::onRaceDialogBack() { if (raceDialog) { - raceDialog->setVisible(false); environment.mMechanicsManager->setPlayerRace(raceDialog->getRaceId(), raceDialog->getGender() == RaceDialog::GM_Male); + raceDialog->setVisible(false); + garbageDialogs.push_back(raceDialog); + raceDialog = nullptr; } updateCharacterGeneration(); - environment.mInputManager->setGuiMode(GM_Name); + setGuiMode(GM_Name); } void WindowManager::onClassChoice(MyGUI::WidgetPtr, int _index) { - classChoiceDialog->setVisible(false); -// classChoiceDialog = nullptr; + if (classChoiceDialog) + { + classChoiceDialog->setVisible(false); + garbageDialogs.push_back(classChoiceDialog); + classChoiceDialog = nullptr; + } if (_index == ClassChoiceDialog::Class_Generate) { - environment.mInputManager->setGuiMode(GM_ClassGenerate); + setGuiMode(GM_ClassGenerate); } else if (_index == ClassChoiceDialog::Class_Pick) { - environment.mInputManager->setGuiMode(GM_ClassPick); + setGuiMode(GM_ClassPick); } else if (_index == ClassChoiceDialog::Class_Create) { - environment.mInputManager->setGuiMode(GM_ClassCreate); + setGuiMode(GM_ClassCreate); } else if (_index == ClassChoiceDialog::Class_Back) { - environment.mInputManager->setGuiMode(GM_Race); + setGuiMode(GM_Race); } } @@ -538,7 +606,10 @@ void WindowManager::showClassQuestionDialog() generateClass = "acrobat"; if (generateClassResultDialog) - delete generateClassResultDialog; + { + generateClassResultDialog->setVisible(false); + garbageDialogs.push_back(generateClassResultDialog); + } generateClassResultDialog = new GenerateClassResultDialog(environment); generateClassResultDialog->setClassId(generateClass); generateClassResultDialog->eventBack = MyGUI::newDelegate(this, &WindowManager::onGenerateClassBack); @@ -549,12 +620,16 @@ void WindowManager::showClassQuestionDialog() if (generateClassStep > steps.size()) { - environment.mInputManager->setGuiMode(GM_Class); + setGuiMode(GM_Class); return; } - if (!generateClassQuestionDialog) - generateClassQuestionDialog = new InfoBoxDialog(environment); + if (generateClassQuestionDialog) + { + generateClassQuestionDialog->setVisible(false); + garbageDialogs.push_back(generateClassQuestionDialog); + } + generateClassQuestionDialog = new InfoBoxDialog(environment); InfoBoxDialog::ButtonList buttons; generateClassQuestionDialog->setText(steps[generateClassStep].text); @@ -569,10 +644,15 @@ void WindowManager::showClassQuestionDialog() void WindowManager::onClassQuestionChosen(MyGUI::Widget* _sender, int _index) { - generateClassQuestionDialog->setVisible(false); + if (generateClassQuestionDialog) + { + generateClassQuestionDialog->setVisible(false); + garbageDialogs.push_back(generateClassQuestionDialog); + generateClassQuestionDialog = nullptr; + } if (_index < 0 || _index >= 3) { - environment.mInputManager->setGuiMode(GM_Class); + setGuiMode(GM_Class); return; } @@ -588,12 +668,14 @@ void WindowManager::onGenerateClassBack() if (generateClassResultDialog) { generateClassResultDialog->setVisible(false); + garbageDialogs.push_back(generateClassResultDialog); + generateClassResultDialog = nullptr; } environment.mMechanicsManager->setPlayerClass(generateClass); updateCharacterGeneration(); - environment.mInputManager->setGuiMode(GM_Class); + setGuiMode(GM_Class); } void WindowManager::onGenerateClassDone() @@ -604,65 +686,65 @@ void WindowManager::onGenerateClassDone() if (generateClassResultDialog) { generateClassResultDialog->setVisible(false); + garbageDialogs.push_back(generateClassResultDialog); + generateClassResultDialog = nullptr; } environment.mMechanicsManager->setPlayerClass(generateClass); updateCharacterGeneration(); if (reviewNext) - environment.mInputManager->setGuiMode(GM_Review); + setGuiMode(GM_Review); else if (goNext) - environment.mInputManager->setGuiMode(GM_Birth); + setGuiMode(GM_Birth); else - environment.mInputManager->setGuiMode(GM_Game); + setGuiMode(GM_Game); } void WindowManager::onPickClassDialogDone() { - pickClassDialog->eventDone = MWGui::PickClassDialog::EventHandle_Void(); + if (pickClassDialog) + { + environment.mMechanicsManager->setPlayerClass(pickClassDialog->getClassId()); + pickClassDialog->eventDone = MWGui::PickClassDialog::EventHandle_Void(); + pickClassDialog->setVisible(false); + garbageDialogs.push_back(pickClassDialog); + pickClassDialog = nullptr; + } bool goNext = classChosen; // Go to next dialog if class was previously chosen classChosen = true; - if (pickClassDialog) - { - pickClassDialog->setVisible(false); - environment.mMechanicsManager->setPlayerClass(pickClassDialog->getClassId()); - } updateCharacterGeneration(); if (reviewNext) - environment.mInputManager->setGuiMode(GM_Review); + setGuiMode(GM_Review); else if (goNext) - environment.mInputManager->setGuiMode(GM_Birth); + setGuiMode(GM_Birth); else - environment.mInputManager->setGuiMode(GM_Game); + setGuiMode(GM_Game); } void WindowManager::onPickClassDialogBack() { if (pickClassDialog) { - pickClassDialog->setVisible(false); environment.mMechanicsManager->setPlayerClass(pickClassDialog->getClassId()); + pickClassDialog->setVisible(false); + garbageDialogs.push_back(pickClassDialog); + pickClassDialog = nullptr; } updateCharacterGeneration(); - environment.mInputManager->setGuiMode(GM_Class); + setGuiMode(GM_Class); } void WindowManager::onCreateClassDialogDone() { - createClassDialog->eventDone = MWGui::CreateClassDialog::EventHandle_Void(); - - bool goNext = classChosen; // Go to next dialog if class was previously chosen - classChosen = true; if (createClassDialog) { - createClassDialog->setVisible(false); - // TODO: The ESM::Class should have methods to set these values to ensure correct data is assigned ESM::Class klass; klass.name = createClassDialog->getName(); @@ -685,77 +767,90 @@ void WindowManager::onCreateClassDialogDone() klass.data.skills[i][0] = minorSkills[i]; } environment.mMechanicsManager->setPlayerClass(klass); + + createClassDialog->eventDone = MWGui::CreateClassDialog::EventHandle_Void(); + createClassDialog->setVisible(false); + garbageDialogs.push_back(createClassDialog); + createClassDialog = nullptr; } + bool goNext = classChosen; // Go to next dialog if class was previously chosen + classChosen = true; + updateCharacterGeneration(); if (reviewNext) - environment.mInputManager->setGuiMode(GM_Review); + setGuiMode(GM_Review); else if (goNext) - environment.mInputManager->setGuiMode(GM_Birth); + setGuiMode(GM_Birth); else - environment.mInputManager->setGuiMode(GM_Game); + setGuiMode(GM_Game); } void WindowManager::onCreateClassDialogBack() { - if (pickClassDialog) + if (createClassDialog) { - pickClassDialog->setVisible(false); - environment.mMechanicsManager->setPlayerClass(pickClassDialog->getClassId()); + createClassDialog->setVisible(false); + garbageDialogs.push_back(createClassDialog); + createClassDialog = nullptr; } updateCharacterGeneration(); - environment.mInputManager->setGuiMode(GM_Class); + setGuiMode(GM_Class); } void WindowManager::onBirthSignDialogDone() { - birthSignDialog->eventDone = MWGui::BirthDialog::EventHandle_Void(); + if (birthSignDialog) + { + environment.mMechanicsManager->setPlayerBirthsign(birthSignDialog->getBirthId()); + birthSignDialog->eventDone = MWGui::BirthDialog::EventHandle_Void(); + birthSignDialog->setVisible(false); + garbageDialogs.push_back(birthSignDialog); + birthSignDialog = nullptr; + } bool goNext = birthSignChosen; // Go to next dialog if birth sign was previously chosen birthSignChosen = true; - if (birthSignDialog) - { - birthSignDialog->setVisible(false); - environment.mMechanicsManager->setPlayerBirthsign(birthSignDialog->getBirthId()); - } updateCharacterGeneration(); if (reviewNext || goNext) - environment.mInputManager->setGuiMode(GM_Review); + setGuiMode(GM_Review); else - environment.mInputManager->setGuiMode(GM_Game); + setGuiMode(GM_Game); } void WindowManager::onBirthSignDialogBack() { if (birthSignDialog) { - birthSignDialog->setVisible(false); environment.mMechanicsManager->setPlayerBirthsign(birthSignDialog->getBirthId()); + birthSignDialog->setVisible(false); + garbageDialogs.push_back(birthSignDialog); + birthSignDialog = nullptr; } updateCharacterGeneration(); - environment.mInputManager->setGuiMode(GM_Class); + setGuiMode(GM_Class); } void WindowManager::onReviewDialogDone() { - reviewDialog->eventDone = MWGui::BirthDialog::EventHandle_Void(); - if (reviewDialog) { + reviewDialog->eventDone = MWGui::BirthDialog::EventHandle_Void(); reviewDialog->setVisible(false); - //environment.mMechanicsManager->setPlayerBirthsign(reviewDialog->getBirthId()); + garbageDialogs.push_back(reviewDialog); + reviewDialog = nullptr; } updateCharacterGeneration(); - environment.mInputManager->setGuiMode(GM_Game); + setGuiMode(GM_Game); } void WindowManager::onReviewDialogBack() @@ -763,10 +858,11 @@ void WindowManager::onReviewDialogBack() if (reviewDialog) { reviewDialog->setVisible(false); - //environment.mMechanicsManager->setPlayerBirthsign(reviewDialog->getBirthId()); + garbageDialogs.push_back(reviewDialog); + reviewDialog = nullptr; } updateCharacterGeneration(); - environment.mInputManager->setGuiMode(GM_Birth); + setGuiMode(GM_Birth); } diff --git a/apps/openmw/mwgui/window_manager.hpp b/apps/openmw/mwgui/window_manager.hpp index ee4326b2e8..c646a841b1 100644 --- a/apps/openmw/mwgui/window_manager.hpp +++ b/apps/openmw/mwgui/window_manager.hpp @@ -34,6 +34,14 @@ namespace MWWorld class Environment; } +namespace OEngine +{ + namespace GUI + { + class Layout; + } +} + namespace MWGui { class HUD; @@ -109,6 +117,18 @@ namespace MWGui // Current gui mode GuiMode mode; + /** + * Next mode to activate in update(). + */ + GuiMode nextMode; + /** + * Whether a mode change is needed in update(). + * Will use @a nextMode as the new mode. + */ + bool needModeChange; + + std::vector garbageDialogs; + // Currently shown windows in inventory mode GuiWindow shown; @@ -126,12 +146,21 @@ namespace MWGui // allowed settings. void updateVisible(); + void setGuiMode(GuiMode newMode); + public: /// The constructor needs the main Gui object WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment, const Compiler::Extensions& extensions, bool newGame); virtual ~WindowManager(); + /** + * Should be called each frame to update windows/gui elements. + * This could mean updating sizes of gui elements or opening + * new dialogs. + */ + void update(); + void setMode(GuiMode newMode) { if (newMode==GM_Inventory && allowed==GW_None) @@ -140,6 +169,7 @@ namespace MWGui mode = newMode; updateVisible(); } + void setNextMode(GuiMode newMode); GuiMode getMode() const { return mode; } diff --git a/apps/openmw/mwinput/inputmanager.cpp b/apps/openmw/mwinput/inputmanager.cpp index 8dba12b7a6..0544df6f0f 100644 --- a/apps/openmw/mwinput/inputmanager.cpp +++ b/apps/openmw/mwinput/inputmanager.cpp @@ -225,6 +225,14 @@ namespace MWInput // Tell OIS to handle all input events input.capture(); + // Update windows/gui as a result of input events + // For instance this could mean opening a new window/dialog, + // by doing this after the input events are handled we + // ensure that window/gui changes appear quickly while + // avoiding that window/gui changes does not happen in + // event callbacks (which may crash) + windows.update(); + // Disable movement in Gui mode if(windows.isGuiMode()) return true;