diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index fb35157e8..3e957ef14 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -240,9 +240,11 @@ namespace MWBase /** No guarentee of actually closing the window **/ virtual void exitCurrentGuiMode() = 0; - virtual void messageBox (const std::string& message, const std::vector& buttons = std::vector(), enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) = 0; + virtual void messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) = 0; virtual void staticMessageBox(const std::string& message) = 0; virtual void removeStaticMessageBox() = 0; + virtual void interactiveMessageBox (const std::string& message, + const std::vector& buttons = std::vector(), bool block=false) = 0; /// returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) virtual int readPressedButton() = 0; diff --git a/apps/openmw/mwdialogue/journalimp.cpp b/apps/openmw/mwdialogue/journalimp.cpp index 9497347e3..e8d5375e1 100644 --- a/apps/openmw/mwdialogue/journalimp.cpp +++ b/apps/openmw/mwdialogue/journalimp.cpp @@ -92,9 +92,7 @@ namespace MWDialogue quest.addEntry (entry); // we are doing slicing on purpose here - std::vector empty; - std::string notification = "#{sJournalEntry}"; - MWBase::Environment::get().getWindowManager()->messageBox (notification, empty); + MWBase::Environment::get().getWindowManager()->messageBox ("#{sJournalEntry}"); } void Journal::setJournalIndex (const std::string& id, int index) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index c45136eb3..9cb778ea2 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -146,10 +146,11 @@ namespace MWGui return false; } - int MessageBoxManager::readPressedButton () + int MessageBoxManager::readPressedButton (bool reset) { int pressed = mLastButtonPressed; - mLastButtonPressed = -1; + if (reset) + mLastButtonPressed = -1; return pressed; } diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 59804e097..48a92c844 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -33,7 +33,8 @@ namespace MWGui bool removeMessageBox (MessageBox *msgbox); - int readPressedButton (); + /// @param reset Reset the pressed button to -1 after reading it. + int readPressedButton (bool reset=true); typedef MyGUI::delegates::CMultiDelegate1 EventHandle_Int; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 5d737ec41..077ca4fe3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -607,7 +607,7 @@ namespace MWGui // GM_Loading uses a texture of the last rendered frame so everything previously visible will be rendered. mHud->setVisible(false); mToolTips->setVisible(false); - setCursorVisible(false); + setCursorVisible(mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox()); break; default: // Unsupported mode, switch back to game @@ -805,19 +805,31 @@ namespace MWGui } } - void WindowManager::messageBox (const std::string& message, const std::vector& buttons, enum MWGui::ShowInDialogueMode showInDialogueMode) + void WindowManager::interactiveMessageBox(const std::string &message, const std::vector &buttons, bool block) { - if (buttons.empty()) { - /* If there are no buttons, and there is a dialogue window open, messagebox goes to the dialogue window */ - if (getMode() == GM_Dialogue && showInDialogueMode != MWGui::ShowInDialogueMode_Never) { - mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(message)); - } else if (showInDialogueMode != MWGui::ShowInDialogueMode_Only) { - mMessageBoxManager->createMessageBox(message); + mMessageBoxManager->createInteractiveMessageBox(message, buttons); + MWBase::Environment::get().getInputManager()->changeInputMode(isGuiMode()); + updateVisible(); + + if (block) + { + while (mMessageBoxManager->readPressedButton(false) == -1 + && !MWBase::Environment::get().getStateManager()->hasQuitRequest()) + { + mMessageBoxManager->onFrame(0.f); + MWBase::Environment::get().getInputManager()->update(0, true, false); + + mRendering->getWindow()->update(); } - } else { - mMessageBoxManager->createInteractiveMessageBox(message, buttons); - MWBase::Environment::get().getInputManager()->changeInputMode(isGuiMode()); - updateVisible(); + } + } + + void WindowManager::messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode) + { + if (getMode() == GM_Dialogue && showInDialogueMode != MWGui::ShowInDialogueMode_Never) { + mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(message)); + } else if (showInDialogueMode != MWGui::ShowInDialogueMode_Only) { + mMessageBoxManager->createMessageBox(message); } } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 015f200d5..44d5819c2 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -238,9 +238,12 @@ namespace MWGui ///Gracefully attempts to exit the topmost GUI mode virtual void exitCurrentGuiMode(); - virtual void messageBox (const std::string& message, const std::vector& buttons = std::vector(), enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible); + virtual void messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible); virtual void staticMessageBox(const std::string& message); virtual void removeStaticMessageBox(); + virtual void interactiveMessageBox (const std::string& message, + const std::vector& buttons = std::vector(), bool block=false); + virtual int readPressedButton (); ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox) virtual void onFrame (float frameDuration); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index ece189c75..846cce6a2 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -743,8 +743,7 @@ namespace MWInput { mEngine.screenshot(); - std::vector empty; - MWBase::Environment::get().getWindowManager()->messageBox ("Screenshot saved", empty); + MWBase::Environment::get().getWindowManager()->messageBox ("Screenshot saved"); } void InputManager::toggleInventory() diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index ec7b232a2..ba01caf95 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -257,18 +257,16 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas /// \todo check if character is the player, if levelling is ever implemented for NPCs MWBase::Environment::get().getSoundManager ()->playSound ("skillraise", 1, 1); - std::vector noButtons; - std::stringstream message; message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", "")) % std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}") % static_cast (base); - MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), noButtons, MWGui::ShowInDialogueMode_Never); + MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), MWGui::ShowInDialogueMode_Never); if (mLevelProgress >= gmst.find("iLevelUpTotal")->getInt()) { // levelup is possible now - MWBase::Environment::get().getWindowManager ()->messageBox ("#{sLevelUpMsg}", noButtons, MWGui::ShowInDialogueMode_Never); + MWBase::Environment::get().getWindowManager ()->messageBox ("#{sLevelUpMsg}", MWGui::ShowInDialogueMode_Never); } getSkill (skillIndex).setBase (base); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index ea40721cb..bf161442e 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -169,6 +169,9 @@ struct AddGlow instance->setProperty("env_map", sh::makeProperty(new sh::BooleanValue(true))); instance->setProperty("env_map_color", sh::makeProperty(new sh::Vector3(mColor->x, mColor->y, mColor->z))); + // Workaround for crash in Ogre (https://bitbucket.org/sinbad/ogre/pull-request/447/fix-shadows-crash-for-textureunitstates/diff) + // Remove when the fix is merged + instance->getMaterial()->setShadowCasterMaterial("openmw_shadowcaster_noalpha"); } }; diff --git a/apps/openmw/mwscript/containerextensions.cpp b/apps/openmw/mwscript/containerextensions.cpp index 96e30e396..58b1b375b 100644 --- a/apps/openmw/mwscript/containerextensions.cpp +++ b/apps/openmw/mwscript/containerextensions.cpp @@ -71,8 +71,7 @@ namespace MWScript msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}"); msgBox = boost::str(boost::format(msgBox) % count % itemName); } - std::vector noButtons; - MWBase::Environment::get().getWindowManager()->messageBox(msgBox, noButtons, MWGui::ShowInDialogueMode_Only); + MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only); } } }; @@ -143,8 +142,7 @@ namespace MWScript msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}"); msgBox = boost::str (boost::format(msgBox) % itemName); } - std::vector noButtons; - MWBase::Environment::get().getWindowManager()->messageBox(msgBox, noButtons, MWGui::ShowInDialogueMode_Only); + MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only); } } }; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 5d52033a8..5cc4d69b6 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -200,7 +200,10 @@ namespace MWScript void InterpreterContext::messageBox (const std::string& message, const std::vector& buttons) { - MWBase::Environment::get().getWindowManager()->messageBox (message, buttons); + if (buttons.empty()) + MWBase::Environment::get().getWindowManager()->messageBox (message); + else + MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons); } void InterpreterContext::report (const std::string& message) diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 94b1ab4dc..f756ee42a 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -118,7 +118,7 @@ void MWState::StateManager::askLoadRecent() std::string message = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLoadLastSaveMsg", tag); size_t pos = message.find(tag); message.replace(pos, tag.length(), lastSave.mProfile.mDescription); - MWBase::Environment::get().getWindowManager()->messageBox(message, buttons); + MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons); mAskLoadRecent = true; } } @@ -259,7 +259,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot std::vector buttons; buttons.push_back("#{sOk}"); - MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons); + MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error.str(), buttons); // If no file was written, clean up the slot if (slot && !boost::filesystem::exists(slot->mPath)) @@ -353,6 +353,12 @@ void MWState::StateManager::loadGame (const Character *character, const std::str { ESM::SavedGame profile; profile.load(reader); + if (!verifyProfile(profile)) + { + cleanup (true); + MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); + return; + } mTimePlayed = profile.mTimePlayed; } break; @@ -459,7 +465,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str std::vector buttons; buttons.push_back("#{sOk}"); - MWBase::Environment::get().getWindowManager()->messageBox(error.str(), buttons); + MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error.str(), buttons); } } @@ -517,3 +523,30 @@ void MWState::StateManager::update (float duration) } } } + +bool MWState::StateManager::verifyProfile(const ESM::SavedGame& profile) const +{ + const std::vector& selectedContentFiles = MWBase::Environment::get().getWorld()->getContentFiles(); + bool notFound = false; + for (std::vector::const_iterator it = profile.mContentFiles.begin(); + it != profile.mContentFiles.end(); ++it) + { + if (std::find(selectedContentFiles.begin(), selectedContentFiles.end(), *it) + == selectedContentFiles.end()) + { + notFound = true; + break; + } + } + if (notFound) + { + std::vector buttons; + buttons.push_back("#{sYes}"); + buttons.push_back("#{sNo}"); + MWBase::Environment::get().getWindowManager()->interactiveMessageBox("#{sMissingMastersMsg}", buttons, true); + int selectedButton = MWBase::Environment::get().getWindowManager()->readPressedButton(); + if (selectedButton == 1 || selectedButton == -1) + return false; + } + return true; +} diff --git a/apps/openmw/mwstate/statemanagerimp.hpp b/apps/openmw/mwstate/statemanagerimp.hpp index 956a2d73c..37f38f8df 100644 --- a/apps/openmw/mwstate/statemanagerimp.hpp +++ b/apps/openmw/mwstate/statemanagerimp.hpp @@ -23,6 +23,8 @@ namespace MWState void cleanup (bool force = false); + bool verifyProfile (const ESM::SavedGame& profile) const; + std::map buildContentFileIndexMap (const ESM::ESMReader& reader) const; public: diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 7dfd41408..5461e8405 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3047,7 +3047,7 @@ namespace MWWorld std::vector buttons; buttons.push_back("#{sOk}"); - MWBase::Environment::get().getWindowManager()->messageBox(message, buttons); + MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons); } } diff --git a/files/mygui/openmw_interactive_messagebox.layout b/files/mygui/openmw_interactive_messagebox.layout index a1dbc5aa8..a72bebf3a 100644 --- a/files/mygui/openmw_interactive_messagebox.layout +++ b/files/mygui/openmw_interactive_messagebox.layout @@ -1,7 +1,7 @@ - + diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index 38a98d133..50f83aaa2 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -11,6 +11,7 @@ +