From 5415ca6a6311215b5b3aab84526d7044f7c6280f Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Apr 2014 13:04:09 +0200 Subject: [PATCH 1/9] Fix exception when shift+click on empty space in save dialog --- apps/openmw/mwgui/savegamedialog.cpp | 2 +- apps/openmw/mwgui/statswindow.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 74ccc82f4c..a77c625f90 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -53,7 +53,7 @@ namespace MWGui { onSlotSelected(sender, pos); - if (MyGUI::InputManager::getInstance().isShiftPressed()) + if (pos != MyGUI::ITEM_NONE && MyGUI::InputManager::getInstance().isShiftPressed()) { ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); dialog->open("#{sMessage3}"); diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 3d4c741a3e..31a3b6fdd0 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -475,7 +475,7 @@ namespace MWGui text += std::string("#DDC79E") + faction->mName; if (expelled.find(it->first) != expelled.end()) - text += "\n#{sExpelled}"; + text += "\n#BF9959#{sExpelled}"; else { text += std::string("\n#BF9959") + faction->mRanks[it->second]; From f99eda1a543c79bad59e23e9ed5a0fcd9215644d Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 Apr 2014 13:34:06 +0200 Subject: [PATCH 2/9] Fixes #1302: Do not attempt to set OnPcAdd before the script has been added --- apps/openmw/mwworld/containerstore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index b1cbcc9c26..eb6760d14c 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -231,6 +231,8 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr { CellStore *cell; + MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); + if(&(MWWorld::Class::get (player).getContainerStore (player)) == this) { cell = 0; // Items in player's inventory have cell set to 0, so their scripts will never be removed @@ -243,7 +245,6 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr item.mCell = cell; item.mContainerStore = 0; - MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); } return it; From 6f7fbc867f6e4ba8acb9fe03d7169c819cfecf91 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 30 Apr 2014 21:15:14 +0200 Subject: [PATCH 3/9] Fix several leaks --- apps/openmw/mwgui/inventorywindow.cpp | 10 +++++----- apps/openmw/mwgui/inventorywindow.hpp | 4 ++-- apps/openmw/mwrender/characterpreview.hpp | 4 ++++ apps/openmw/mwrender/ripplesimulation.cpp | 5 ++++- components/ogreinit/ogreinit.cpp | 1 + components/terrain/world.cpp | 2 ++ files/mygui/openmw_text.skin.xml | 16 ---------------- 7 files changed, 18 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e9efe75e7f..2bea088e32 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -35,7 +35,7 @@ namespace MWGui , mTrading(false) , mLastXSize(0) , mLastYSize(0) - , mPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr()) + , mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())) , mPreviewDirty(true) , mDragAndDrop(dragAndDrop) , mSelectedItem(-1) @@ -91,8 +91,8 @@ namespace MWGui mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr()); mSortModel = new SortFilterItemModel(mTradeModel); mItemView->setModel(mSortModel); - mPreview = MWRender::InventoryPreview(mPtr); - mPreview.setup(); + mPreview.reset(new MWRender::InventoryPreview(mPtr)); + mPreview->setup(); } void InventoryWindow::setGuiMode(GuiMode mode) @@ -444,7 +444,7 @@ namespace MWGui MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y) { - int slot = mPreview.getSlotSelected (x, y); + int slot = mPreview->getSlotSelected (x, y); if (slot == -1) return MWWorld::Ptr(); @@ -493,7 +493,7 @@ namespace MWGui mPreviewDirty = false; MyGUI::IntSize size = mAvatarImage->getSize(); - mPreview.update (size.width, size.height); + mPreview->update (size.width, size.height); mAvatarImage->setImageTexture("CharacterPreview"); mAvatarImage->setImageCoord(MyGUI::IntCoord(0, 0, std::min(512, size.width), std::min(1024, size.height))); diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index 7ef168e988..c23a74efad 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -34,7 +34,7 @@ namespace MWGui MWWorld::Ptr getAvatarSelectedItem(int x, int y); void rebuildAvatar() { - mPreview.rebuild(); + mPreview->rebuild(); } TradeItemModel* getTradeModel(); @@ -81,7 +81,7 @@ namespace MWGui int mLastXSize; int mLastYSize; - MWRender::InventoryPreview mPreview; + std::auto_ptr mPreview; bool mTrading; diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index 16e6ab017d..60312455ff 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -34,6 +34,10 @@ namespace MWRender virtual void rebuild(); + private: + CharacterPreview(const CharacterPreview&); + CharacterPreview& operator=(const CharacterPreview&); + protected: virtual bool renderHeadOnly() { return false; } diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index f52deedcc6..74216c1de4 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -28,7 +28,9 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) mRippleAreaLength(1000), mImpulseSize(20), mTexelOffset(0,0), - mFirstUpdate(true) + mFirstUpdate(true), + mRectangle(NULL), + mImpulse(NULL) { Ogre::AxisAlignedBox aabInf; aabInf.setInfinite(); @@ -105,6 +107,7 @@ RippleSimulation::RippleSimulation(Ogre::SceneManager* mainSceneManager) RippleSimulation::~RippleSimulation() { delete mRectangle; + delete mImpulse; Ogre::Root::getSingleton().destroySceneManager(mSceneMgr); } diff --git a/components/ogreinit/ogreinit.cpp b/components/ogreinit/ogreinit.cpp index 1b9a899a0b..01b8764c2b 100644 --- a/components/ogreinit/ogreinit.cpp +++ b/components/ogreinit/ogreinit.cpp @@ -62,6 +62,7 @@ namespace OgreInit OgreInit::~OgreInit() { delete mRoot; + delete Ogre::LogManager::getSingletonPtr(); std::vector::iterator ei; for(ei = mEmitterFactories.begin();ei != mEmitterFactories.end();++ei) diff --git a/components/terrain/world.cpp b/components/terrain/world.cpp index 844144d7c4..3d968470f3 100644 --- a/components/terrain/world.cpp +++ b/components/terrain/world.cpp @@ -337,6 +337,8 @@ namespace Terrain it->mTarget->loadLayers(*it); } + delete data; + mRootNode->loadMaterials(); mLayerLoadPending = false; diff --git a/files/mygui/openmw_text.skin.xml b/files/mygui/openmw_text.skin.xml index b80859ea1a..d4c72c75b4 100644 --- a/files/mygui/openmw_text.skin.xml +++ b/files/mygui/openmw_text.skin.xml @@ -49,22 +49,6 @@ - - - - - - - - - - - - - - - - From 64a30ad182bdb4caec160b6fd1d53b0caab9e8b5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 1 May 2014 12:44:31 +0200 Subject: [PATCH 4/9] Fix another leak --- apps/openmw/mwgui/fontloader.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/fontloader.cpp b/apps/openmw/mwgui/fontloader.cpp index 7a6317c163..59c2e7ca68 100644 --- a/apps/openmw/mwgui/fontloader.cpp +++ b/apps/openmw/mwgui/fontloader.cpp @@ -196,6 +196,16 @@ namespace MWGui bitmapFile->read(&textureData[0], width*height*4); bitmapFile->close(); + std::string resourceName; + if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic")) + resourceName = "Magic Cards"; + else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "century")) + resourceName = "Century Gothic"; + else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric")) + resourceName = "Daedric"; + else + return; // no point in loading it, since there is no way of using additional fonts + std::string textureName = name; Ogre::Image image; image.loadDynamicImage(&textureData[0], width, height, Ogre::PF_BYTE_RGBA); @@ -208,18 +218,11 @@ namespace MWGui // Register the font with MyGUI MyGUI::ResourceManualFont* font = static_cast( MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceManualFont")); + // We need to emulate loading from XML because the data members are private as of mygui 3.2.0 MyGUI::xml::Document xmlDocument; MyGUI::xml::ElementPtr root = xmlDocument.createRoot("ResourceManualFont"); - - if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic")) - root->addAttribute("name", "Magic Cards"); - else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "century")) - root->addAttribute("name", "Century Gothic"); - else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric")) - root->addAttribute("name", "Daedric"); - else - return; // no point in loading it, since there is no way of using additional fonts + root->addAttribute("name", resourceName); MyGUI::xml::ElementPtr defaultHeight = root->createChild("Property"); defaultHeight->addAttribute("key", "DefaultHeight"); @@ -285,6 +288,7 @@ namespace MWGui font->deserialization(root, MyGUI::Version(3,2,0)); + MyGUI::ResourceManager::getInstance().removeByName(font->getResourceName()); MyGUI::ResourceManager::getInstance().addResource(font); } From fc7e79027af9df32276211b9f8306c73cb51f1e4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 1 May 2014 16:44:39 +0200 Subject: [PATCH 5/9] Fixes #1144: Don't refreshCurrentAnims when adding already dead actors --- apps/openmw/mwmechanics/character.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 8ad2b4a67e..280639f714 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -489,12 +489,13 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim mIdleState = CharState_Idle; } - refreshCurrentAnims(mIdleState, mMovementState, true); if(mDeathState != CharState_None) { playRandomDeath(1.0f); } + else + refreshCurrentAnims(mIdleState, mMovementState, true); } CharacterController::~CharacterController() From 17bb8d7f9a84fbe5106ab97fbe4407f327b34097 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 1 May 2014 21:16:32 +0200 Subject: [PATCH 6/9] Fixes #1252: Add item/magic keybindings to savegame --- apps/openmw/mwbase/windowmanager.hpp | 1 + apps/openmw/mwgui/quickkeysmenu.cpp | 119 +++++++++++++++++++++++- apps/openmw/mwgui/quickkeysmenu.hpp | 5 + apps/openmw/mwgui/windowmanagerimp.cpp | 15 ++- apps/openmw/mwgui/windowmanagerimp.hpp | 1 + apps/openmw/mwstate/statemanagerimp.cpp | 4 +- components/esm/defs.hpp | 7 ++ 7 files changed, 144 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 4287e466bd..c78902a60a 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -305,6 +305,7 @@ namespace MWBase virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0; + virtual int countSavedGameRecords() const = 0; }; } diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index dc72269099..fb41b3b679 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -55,6 +55,14 @@ namespace MWGui } } + void QuickKeysMenu::clear() + { + for (int i=0; i<10; ++i) + { + unassign(mQuickKeyButtons[i], i); + } + } + QuickKeysMenu::~QuickKeysMenu() { delete mAssignDialog; @@ -154,8 +162,6 @@ namespace MWGui frame->setUserString ("ToolTipType", "ItemPtr"); frame->setUserData(item); frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked); - - MyGUI::ImageBox* image = frame->createWidget("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default); std::string path = std::string("icons\\"); path += MWWorld::Class::get(item).getInventoryIcon(item); @@ -165,7 +171,8 @@ namespace MWGui image->setImageTexture (path); image->setNeedMouseFocus (false); - mItemSelectionDialog->setVisible(false); + if (mItemSelectionDialog) + mItemSelectionDialog->setVisible(false); } void QuickKeysMenu::onAssignItemCancel() @@ -198,7 +205,8 @@ namespace MWGui image->setImageTexture (path); image->setNeedMouseFocus (false); - mMagicSelectionDialog->setVisible(false); + if (mMagicSelectionDialog) + mMagicSelectionDialog->setVisible(false); } void QuickKeysMenu::onAssignMagic (const std::string& spellId) @@ -239,7 +247,8 @@ namespace MWGui image->setImageTexture (path); image->setNeedMouseFocus (false); - mMagicSelectionDialog->setVisible(false); + if (mMagicSelectionDialog) + mMagicSelectionDialog->setVisible(false); } void QuickKeysMenu::onAssignMagicCancel () @@ -374,6 +383,106 @@ namespace MWGui center(); } + void QuickKeysMenu::write(ESM::ESMWriter &writer) + { + const std::string recKey = "KEY_"; + writer.startRecord(ESM::REC_KEYS); + + for (int i=0; i<10; ++i) + { + writer.startSubRecord(recKey); + + MyGUI::Button* button = mQuickKeyButtons[i]; + + int type = *button->getUserData(); + writer.writeHNT("TYPE", type); + + switch (type) + { + case Type_Unassigned: + writer.writeHNString("ID__", ""); + break; + case Type_Item: + case Type_MagicItem: + { + MWWorld::Ptr item = *button->getChildAt(0)->getUserData(); + writer.writeHNString("ID__", item.getCellRef().mRefID); + break; + } + case Type_Magic: + std::string spellId = button->getChildAt(0)->getUserString("Spell"); + writer.writeHNString("ID__", spellId); + break; + } + + writer.endRecord(recKey); + } + + writer.endRecord(ESM::REC_KEYS); + } + + void QuickKeysMenu::readRecord(ESM::ESMReader &reader, int32_t type) + { + if (type != ESM::REC_KEYS) + return; + + int i=0; + while (reader.isNextSub("KEY_")) + { + reader.getSubHeader(); + int keyType; + reader.getHNT(keyType, "TYPE"); + std::string id; + id = reader.getHNString("ID__"); + + mSelectedIndex = i; + + MyGUI::Button* button = mQuickKeyButtons[i]; + + switch (keyType) + { + case Type_Magic: + onAssignMagic(id); + break; + case Type_Item: + case Type_MagicItem: + { + // Find the item by id + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player); + MWWorld::Ptr item; + for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it) + { + if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, id)) + { + if (item.isEmpty() || + // Prefer the stack with the lowest remaining uses + (it->getCellRef().mCharge != -1 && (item.getCellRef().mCharge == -1 || it->getCellRef().mCharge < item.getCellRef().mCharge) )) + { + item = *it; + } + } + } + + if (item.isEmpty()) + unassign(button, i); + else + { + if (keyType == Type_Item) + onAssignItem(item); + else if (keyType == Type_MagicItem) + onAssignMagicItem(item); + } + + break; + } + case Type_Unassigned: + unassign(button, i); + break; + } + ++i; + } + } // --------------------------------------------------------------------------------------------------------- diff --git a/apps/openmw/mwgui/quickkeysmenu.hpp b/apps/openmw/mwgui/quickkeysmenu.hpp index 058519ece4..c0e25a517c 100644 --- a/apps/openmw/mwgui/quickkeysmenu.hpp +++ b/apps/openmw/mwgui/quickkeysmenu.hpp @@ -41,6 +41,11 @@ namespace MWGui }; + void write (ESM::ESMWriter& writer); + void readRecord (ESM::ESMReader& reader, int32_t type); + void clear(); + + private: MyGUI::EditBox* mInstructionLabel; MyGUI::Button* mOkButton; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index e2e4e157c1..1b4145e5c3 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1405,16 +1405,29 @@ namespace MWGui void WindowManager::clear() { mMap->clear(); + mQuickKeysMenu->clear(); } void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress) { mMap->write(writer, progress); + + mQuickKeysMenu->write(writer); + progress.increaseProgress(); } void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type) { - mMap->readRecord(reader, type); + if (type == ESM::REC_GMAP) + mMap->readRecord(reader, type); + else if (type == ESM::REC_KEYS) + mQuickKeysMenu->readRecord(reader, type); + } + + int WindowManager::countSavedGameRecords() const + { + return 1 // Global map + + 1; // QuickKeysMenu } void WindowManager::playVideo(const std::string &name, bool allowSkipping) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 064ca89bac..44bc566546 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -293,6 +293,7 @@ namespace MWGui virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress); virtual void readRecord (ESM::ESMReader& reader, int32_t type); + virtual int countSavedGameRecords() const; private: bool mConsoleOnlyScripts; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 33f2dce7c3..48d12f0a6d 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -201,7 +201,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot +MWBase::Environment::get().getWorld()->countSavedGameRecords() +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords() +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords() - +1; // global map + +MWBase::Environment::get().getWindowManager()->countSavedGameRecords(); writer.setRecordCount (recordCount); writer.save (stream); @@ -323,7 +323,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl break; case ESM::REC_GMAP: - + case ESM::REC_KEYS: MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val); break; diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 4d5b36c740..b2a1637f11 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -34,6 +34,12 @@ struct Position }; #pragma pack(pop) +template +struct FourCC +{ + static const unsigned int value = (((((d << 8) | c) << 8) | b) << 8) | a; +}; + enum RecNameInts { // format 0 / legacy @@ -93,6 +99,7 @@ enum RecNameInts REC_GMAP = 0x50414d47, REC_DIAS = 0x53414944, REC_WTHR = 0x52485457, + REC_KEYS = FourCC<'K','E','Y','S'>::value, // format 1 REC_FILT = 0x544C4946 From 6381b1e9381436a22c8a3af212bd4b4145607529 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 11:20:43 +0200 Subject: [PATCH 7/9] Fixes #1309: Do not allow saving while dialogs are opened, just like vanilla This limitation could be removed post-1.0 by serializing the state of open windows. --- apps/openmw/mwbase/windowmanager.hpp | 3 +++ apps/openmw/mwgui/mainmenu.cpp | 3 ++- apps/openmw/mwgui/referenceinterface.hpp | 2 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 20 ++++++++++++++++++++ apps/openmw/mwgui/windowmanagerimp.hpp | 3 +++ apps/openmw/mwstate/statemanagerimp.cpp | 5 +++-- 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index c78902a60a..9e5230af62 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -306,6 +306,9 @@ namespace MWBase virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) = 0; virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0; virtual int countSavedGameRecords() const = 0; + + /// Does the current stack of GUI-windows permit saving? + virtual bool isSavingAllowed() const = 0; }; } diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index df9c53ea87..8b44af2ef3 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -170,7 +170,8 @@ namespace MWGui buttons.push_back("loadgame"); if (state==MWBase::StateManager::State_Running && - MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1) + MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1 && + MWBase::Environment::get().getWindowManager()->isSavingAllowed()) buttons.push_back("savegame"); buttons.push_back("options"); diff --git a/apps/openmw/mwgui/referenceinterface.hpp b/apps/openmw/mwgui/referenceinterface.hpp index 39574d0f7a..df53a42b70 100644 --- a/apps/openmw/mwgui/referenceinterface.hpp +++ b/apps/openmw/mwgui/referenceinterface.hpp @@ -17,6 +17,8 @@ namespace MWGui void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable + void resetReference() { mPtr = MWWorld::Ptr(); mCurrentPlayerCell = NULL; } + protected: virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 1b4145e5c3..d2a31e8d15 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1406,6 +1406,19 @@ namespace MWGui { mMap->clear(); mQuickKeysMenu->clear(); + + mTrainingWindow->resetReference(); + mDialogueWindow->resetReference(); + mTradeWindow->resetReference(); + mSpellBuyingWindow->resetReference(); + mSpellCreationDialog->resetReference(); + mEnchantingDialog->resetReference(); + mContainerWindow->resetReference(); + mCompanionWindow->resetReference(); + mConsole->resetReference(); + + mGuiModes.clear(); + updateVisible(); } void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress) @@ -1430,6 +1443,13 @@ namespace MWGui + 1; // QuickKeysMenu } + bool WindowManager::isSavingAllowed() const + { + return !MyGUI::InputManager::getInstance().isModalAny() + // TODO: remove this, once we have properly serialized the state of open windows + && (!isGuiMode() || (mGuiModes.size() == 1 && getMode() == GM_MainMenu)); + } + void WindowManager::playVideo(const std::string &name, bool allowSkipping) { mVideoWidget->playVideo("video\\" + name, allowSkipping); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 44bc566546..e31013b451 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -295,6 +295,9 @@ namespace MWGui virtual void readRecord (ESM::ESMReader& reader, int32_t type); virtual int countSavedGameRecords() const; + /// Does the current stack of GUI-windows permit saving? + virtual bool isSavingAllowed() const; + private: bool mConsoleOnlyScripts; diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 48d12f0a6d..c718eeced7 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -235,8 +235,9 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot void MWState::StateManager::quickSave (std::string name) { - if (mState!=State_Running || - MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")!=-1) // char gen + if (!(mState==State_Running && + MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1 // char gen + && MWBase::Environment::get().getWindowManager()->isSavingAllowed())) { //You can not save your game right now MWBase::Environment::get().getWindowManager()->messageBox("#{sSaveGameDenied}"); From f8cc328b5e63e2eed325cde7b97bc7ee1d8bacb7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 11:26:05 +0200 Subject: [PATCH 8/9] Slightly prettier backdrop when loading game from main menu. --- apps/openmw/mwgui/savegamedialog.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index a77c625f90..c0daa2c0ea 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -206,6 +206,13 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage65}"); return; } + } + + setVisible(false); + MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu); + + if (mSaving) + { MWBase::Environment::get().getStateManager()->saveGame (mSaveNameEdit->getCaption(), mCurrentSlot); } else @@ -213,12 +220,9 @@ namespace MWGui if (mCurrentCharacter && mCurrentSlot) { MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot); - MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu); } } - setVisible(false); - if (MWBase::Environment::get().getStateManager()->getState()== MWBase::StateManager::State_NoGame) { From 8560b43464a9af526e34ce23b17423ed9a577fe1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 2 May 2014 12:47:28 +0200 Subject: [PATCH 9/9] Move to esm component --- apps/openmw/mwgui/quickkeysmenu.cpp | 36 ++++++++++++++---------- components/CMakeLists.txt | 2 +- components/esm/quickkeys.cpp | 43 +++++++++++++++++++++++++++++ components/esm/quickkeys.hpp | 28 +++++++++++++++++++ 4 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 components/esm/quickkeys.cpp create mode 100644 components/esm/quickkeys.hpp diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp index fb41b3b679..51e24e29c8 100644 --- a/apps/openmw/mwgui/quickkeysmenu.cpp +++ b/apps/openmw/mwgui/quickkeysmenu.cpp @@ -2,6 +2,8 @@ #include +#include + #include "../mwworld/inventorystore.hpp" #include "../mwworld/class.hpp" @@ -385,39 +387,41 @@ namespace MWGui void QuickKeysMenu::write(ESM::ESMWriter &writer) { - const std::string recKey = "KEY_"; writer.startRecord(ESM::REC_KEYS); + ESM::QuickKeys keys; + for (int i=0; i<10; ++i) { - writer.startSubRecord(recKey); - MyGUI::Button* button = mQuickKeyButtons[i]; int type = *button->getUserData(); - writer.writeHNT("TYPE", type); + + ESM::QuickKeys::QuickKey key; + key.mType = type; switch (type) { case Type_Unassigned: - writer.writeHNString("ID__", ""); break; case Type_Item: case Type_MagicItem: { MWWorld::Ptr item = *button->getChildAt(0)->getUserData(); - writer.writeHNString("ID__", item.getCellRef().mRefID); + key.mId = item.getCellRef().mRefID; break; } case Type_Magic: std::string spellId = button->getChildAt(0)->getUserString("Spell"); - writer.writeHNString("ID__", spellId); + key.mId = spellId; break; } - writer.endRecord(recKey); + keys.mKeys.push_back(key); } + keys.save(writer); + writer.endRecord(ESM::REC_KEYS); } @@ -426,17 +430,18 @@ namespace MWGui if (type != ESM::REC_KEYS) return; + ESM::QuickKeys keys; + keys.load(reader); + int i=0; - while (reader.isNextSub("KEY_")) + for (std::vector::const_iterator it = keys.mKeys.begin(); it != keys.mKeys.end(); ++it) { - reader.getSubHeader(); - int keyType; - reader.getHNT(keyType, "TYPE"); - std::string id; - id = reader.getHNString("ID__"); + if (i >= 10) + return; mSelectedIndex = i; - + int keyType = it->mType; + std::string id = it->mId; MyGUI::Button* button = mQuickKeyButtons[i]; switch (keyType) @@ -480,6 +485,7 @@ namespace MWGui unassign(button, i); break; } + ++i; } } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 38be5b11a6..1c60dfb831 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -45,7 +45,7 @@ add_component_dir (esm loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate - npcstats creaturestats weatherstate + npcstats creaturestats weatherstate quickkeys ) add_component_dir (misc diff --git a/components/esm/quickkeys.cpp b/components/esm/quickkeys.cpp new file mode 100644 index 0000000000..ad2b671aab --- /dev/null +++ b/components/esm/quickkeys.cpp @@ -0,0 +1,43 @@ +#include "quickkeys.hpp" + +#include "esmwriter.hpp" +#include "esmreader.hpp" + +namespace ESM +{ + + void QuickKeys::load(ESMReader &esm) + { + while (esm.isNextSub("KEY_")) + { + esm.getSubHeader(); + int keyType; + esm.getHNT(keyType, "TYPE"); + std::string id; + id = esm.getHNString("ID__"); + + QuickKey key; + key.mType = keyType; + key.mId = id; + + mKeys.push_back(key); + } + } + + void QuickKeys::save(ESMWriter &esm) const + { + const std::string recKey = "KEY_"; + + for (std::vector::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it) + { + esm.startSubRecord(recKey); + + esm.writeHNT("TYPE", it->mType); + esm.writeHNString("ID__", it->mId); + + esm.endRecord(recKey); + } + } + + +} diff --git a/components/esm/quickkeys.hpp b/components/esm/quickkeys.hpp new file mode 100644 index 0000000000..c52466b13e --- /dev/null +++ b/components/esm/quickkeys.hpp @@ -0,0 +1,28 @@ +#ifndef OPENMW_COMPONENTS_ESM_QUICKKEYS_H +#define OPENMW_COMPONENTS_ESM_QUICKKEYS_H + +#include +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; + + struct QuickKeys + { + struct QuickKey + { + int mType; + std::string mId; // Spell or Item ID + }; + + std::vector mKeys; + + void load (ESMReader &esm); + void save (ESMWriter &esm) const; + }; + +} + +#endif