From f1b52c964a2da506aefdc7b404bd00fee766b273 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 13 Jul 2015 18:00:41 +0200 Subject: [PATCH 1/9] Select the current resolution in resolution list on game start (Fixes #2768) --- apps/openmw/mwgui/settingswindow.cpp | 21 +++++++++++++++++++++ apps/openmw/mwgui/settingswindow.hpp | 1 + 2 files changed, 22 insertions(+) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index df5aa1a40..3ab2a6ce3 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -233,6 +233,7 @@ namespace MWGui if (mResolutionList->findItemIndexWith(str) == MyGUI::ITEM_NONE) mResolutionList->addItem(str); } + highlightCurrentResolution(); std::string tf = Settings::Manager::getString("texture filtering", "General"); mTextureFilteringButton->setCaption(textureFilteringToStr(tf)); @@ -299,8 +300,28 @@ namespace MWGui } void SettingsWindow::onResolutionCancel() + { + highlightCurrentResolution(); + } + + void SettingsWindow::highlightCurrentResolution() { mResolutionList->setIndexSelected(MyGUI::ITEM_NONE); + + int currentX = Settings::Manager::getInt("resolution x", "Video"); + int currentY = Settings::Manager::getInt("resolution y", "Video"); + + for (size_t i=0; igetItemCount(); ++i) + { + int resX, resY; + parseResolution (resX, resY, mResolutionList->getItemNameAt(i)); + + if (resX == currentX && resY == currentY) + { + mResolutionList->setIndexSelected(i); + break; + } + } } void SettingsWindow::onShadowTextureSizeChanged(MyGUI::ComboBox *_sender, size_t pos) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 45d489284..79487c54b 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -59,6 +59,7 @@ namespace MWGui void onResolutionSelected(MyGUI::ListBox* _sender, size_t index); void onResolutionAccept(); void onResolutionCancel(); + void highlightCurrentResolution(); void onShadowTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos); From dca4704b4b665f0853917150f7902e0c29607e58 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 13 Jul 2015 18:40:05 +0200 Subject: [PATCH 2/9] Print exceptions in CharacterCreation::spawnDialog --- apps/openmw/mwgui/charactercreation.cpp | 241 ++++++++++++------------ 1 file changed, 124 insertions(+), 117 deletions(-) diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 73b950a6a..d0a050526 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -132,134 +132,141 @@ namespace MWGui void CharacterCreation::spawnDialog(const char id) { - switch (id) + try { - case GM_Name: - MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog); - mNameDialog = 0; - mNameDialog = new TextInputDialog(); - mNameDialog->setTextLabel(MWBase::Environment::get().getWindowManager()->getGameSettingString("sName", "Name")); - mNameDialog->setTextInput(mPlayerName); - mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen); - mNameDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone); - mNameDialog->setVisible(true); - break; + switch (id) + { + case GM_Name: + MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog); + mNameDialog = 0; + mNameDialog = new TextInputDialog(); + mNameDialog->setTextLabel(MWBase::Environment::get().getWindowManager()->getGameSettingString("sName", "Name")); + mNameDialog->setTextInput(mPlayerName); + mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen); + mNameDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone); + mNameDialog->setVisible(true); + break; - case GM_Race: - MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog); - mRaceDialog = 0; - mRaceDialog = new RaceDialog(mViewer, mResourceSystem); - mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen); - mRaceDialog->setRaceId(mPlayerRaceId); - mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone); - mRaceDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack); - mRaceDialog->setVisible(true); - if (mCreationStage < CSE_NameChosen) - mCreationStage = CSE_NameChosen; - break; + case GM_Race: + MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog); + mRaceDialog = 0; + mRaceDialog = new RaceDialog(mViewer, mResourceSystem); + mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen); + mRaceDialog->setRaceId(mPlayerRaceId); + mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone); + mRaceDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack); + mRaceDialog->setVisible(true); + if (mCreationStage < CSE_NameChosen) + mCreationStage = CSE_NameChosen; + break; - case GM_Class: - MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog); - mClassChoiceDialog = 0; - mClassChoiceDialog = new ClassChoiceDialog(); - mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice); - mClassChoiceDialog->setVisible(true); - if (mCreationStage < CSE_RaceChosen) - mCreationStage = CSE_RaceChosen; - break; + case GM_Class: + MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog); + mClassChoiceDialog = 0; + mClassChoiceDialog = new ClassChoiceDialog(); + mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice); + mClassChoiceDialog->setVisible(true); + if (mCreationStage < CSE_RaceChosen) + mCreationStage = CSE_RaceChosen; + break; - case GM_ClassPick: - MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog); - mPickClassDialog = 0; - mPickClassDialog = new PickClassDialog(); - mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); - mPickClassDialog->setClassId(mPlayerClass.mName); - mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone); - mPickClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack); - mPickClassDialog->setVisible(true); - if (mCreationStage < CSE_RaceChosen) - mCreationStage = CSE_RaceChosen; - break; + case GM_ClassPick: + MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog); + mPickClassDialog = 0; + mPickClassDialog = new PickClassDialog(); + mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); + mPickClassDialog->setClassId(mPlayerClass.mName); + mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone); + mPickClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack); + mPickClassDialog->setVisible(true); + if (mCreationStage < CSE_RaceChosen) + mCreationStage = CSE_RaceChosen; + break; - case GM_Birth: - MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog); - mBirthSignDialog = 0; - mBirthSignDialog = new BirthDialog(); - mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen); - mBirthSignDialog->setBirthId(mPlayerBirthSignId); - mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone); - mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack); - mBirthSignDialog->setVisible(true); - if (mCreationStage < CSE_ClassChosen) - mCreationStage = CSE_ClassChosen; - break; + case GM_Birth: + MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog); + mBirthSignDialog = 0; + mBirthSignDialog = new BirthDialog(); + mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen); + mBirthSignDialog->setBirthId(mPlayerBirthSignId); + mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone); + mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack); + mBirthSignDialog->setVisible(true); + if (mCreationStage < CSE_ClassChosen) + mCreationStage = CSE_ClassChosen; + break; - case GM_ClassCreate: - if (!mCreateClassDialog) - { - mCreateClassDialog = new CreateClassDialog(); - mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone); - mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack); - } - mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); - mCreateClassDialog->setVisible(true); - if (mCreationStage < CSE_RaceChosen) - mCreationStage = CSE_RaceChosen; - break; - case GM_ClassGenerate: - mGenerateClassStep = 0; - mGenerateClass = ""; - mGenerateClassSpecializations[0] = 0; - mGenerateClassSpecializations[1] = 0; - mGenerateClassSpecializations[2] = 0; - showClassQuestionDialog(); - if (mCreationStage < CSE_RaceChosen) - mCreationStage = CSE_RaceChosen; - break; - case GM_Review: - MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); - mReviewDialog = 0; - mReviewDialog = new ReviewDialog(); - mReviewDialog->setPlayerName(mPlayerName); - mReviewDialog->setRace(mPlayerRaceId); - mReviewDialog->setClass(mPlayerClass); - mReviewDialog->setBirthSign(mPlayerBirthSignId); - - { - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - const MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); - - mReviewDialog->setHealth ( stats.getHealth() ); - mReviewDialog->setMagicka( stats.getMagicka() ); - mReviewDialog->setFatigue( stats.getFatigue() ); - } - - { - std::map attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues(); - for (std::map::iterator it = attributes.begin(); - it != attributes.end(); ++it) + case GM_ClassCreate: + if (!mCreateClassDialog) { - mReviewDialog->setAttribute(static_cast (it->first), it->second); + mCreateClassDialog = new CreateClassDialog(); + mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone); + mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack); } - } + mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen); + mCreateClassDialog->setVisible(true); + if (mCreationStage < CSE_RaceChosen) + mCreationStage = CSE_RaceChosen; + break; + case GM_ClassGenerate: + mGenerateClassStep = 0; + mGenerateClass = ""; + mGenerateClassSpecializations[0] = 0; + mGenerateClassSpecializations[1] = 0; + mGenerateClassSpecializations[2] = 0; + showClassQuestionDialog(); + if (mCreationStage < CSE_RaceChosen) + mCreationStage = CSE_RaceChosen; + break; + case GM_Review: + MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog); + mReviewDialog = 0; + mReviewDialog = new ReviewDialog(); + mReviewDialog->setPlayerName(mPlayerName); + mReviewDialog->setRace(mPlayerRaceId); + mReviewDialog->setClass(mPlayerClass); + mReviewDialog->setBirthSign(mPlayerBirthSignId); - { - std::map skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues(); - for (std::map::iterator it = skills.begin(); - it != skills.end(); ++it) { - mReviewDialog->setSkillValue(static_cast (it->first), it->second); - } - mReviewDialog->configureSkills(MWBase::Environment::get().getWindowManager()->getPlayerMajorSkills(), MWBase::Environment::get().getWindowManager()->getPlayerMinorSkills()); - } + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + const MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player); - mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone); - mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack); - mReviewDialog->eventActivateDialog += MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog); - mReviewDialog->setVisible(true); - if (mCreationStage < CSE_BirthSignChosen) - mCreationStage = CSE_BirthSignChosen; - break; + mReviewDialog->setHealth ( stats.getHealth() ); + mReviewDialog->setMagicka( stats.getMagicka() ); + mReviewDialog->setFatigue( stats.getFatigue() ); + } + + { + std::map attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues(); + for (std::map::iterator it = attributes.begin(); + it != attributes.end(); ++it) + { + mReviewDialog->setAttribute(static_cast (it->first), it->second); + } + } + + { + std::map skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues(); + for (std::map::iterator it = skills.begin(); + it != skills.end(); ++it) + { + mReviewDialog->setSkillValue(static_cast (it->first), it->second); + } + mReviewDialog->configureSkills(MWBase::Environment::get().getWindowManager()->getPlayerMajorSkills(), MWBase::Environment::get().getWindowManager()->getPlayerMinorSkills()); + } + + mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone); + mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack); + mReviewDialog->eventActivateDialog += MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog); + mReviewDialog->setVisible(true); + if (mCreationStage < CSE_BirthSignChosen) + mCreationStage = CSE_BirthSignChosen; + break; + } + } + catch (std::exception& e) + { + std::cerr << "Failed to create chargen window: " << e.what() << std::endl; } } From c4866bdfc63e28ceff2573dabb643fafc4283360 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 13 Jul 2015 19:13:26 +0200 Subject: [PATCH 3/9] Disable mipmaps for GUI textures For some reason, the mipmap generator seems to be broken on Linux Intel graphics (works on Nvidia). This was breaking the scrollbar arrows, which are minified enough to show using a mipmap. --- components/myguiplatform/myguitexture.cpp | 2 ++ components/resource/texturemanager.cpp | 25 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/components/myguiplatform/myguitexture.cpp b/components/myguiplatform/myguitexture.cpp index 0a846b227..50ac5c1f3 100644 --- a/components/myguiplatform/myguitexture.cpp +++ b/components/myguiplatform/myguitexture.cpp @@ -87,6 +87,8 @@ namespace osgMyGUI throw std::runtime_error("No texturemanager set"); mTexture = mTextureManager->getTexture2D(fname, osg::Texture2D::CLAMP_TO_EDGE, osg::Texture2D::CLAMP_TO_EDGE); + // disable mip-maps + mTexture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); // FIXME mFormat = MyGUI::PixelFormat::R8G8B8; diff --git a/components/resource/texturemanager.cpp b/components/resource/texturemanager.cpp index 62cbd6bb3..ae8d16102 100644 --- a/components/resource/texturemanager.cpp +++ b/components/resource/texturemanager.cpp @@ -64,7 +64,30 @@ namespace Resource for (std::map >::iterator it = mTextures.begin(); it != mTextures.end(); ++it) { osg::ref_ptr tex = it->second; - tex->setFilter(osg::Texture::MIN_FILTER, mMinFilter); + + // Keep mip-mapping disabled if the texture creator explicitely requested it. + osg::Texture::FilterMode oldMin = tex->getFilter(osg::Texture::MIN_FILTER); + if (oldMin == osg::Texture::LINEAR || oldMin == osg::Texture::NEAREST) + { + osg::Texture::FilterMode newMin = osg::Texture::LINEAR; + switch (mMinFilter) + { + case osg::Texture::LINEAR: + case osg::Texture::LINEAR_MIPMAP_LINEAR: + case osg::Texture::LINEAR_MIPMAP_NEAREST: + newMin = osg::Texture::LINEAR; + break; + case osg::Texture::NEAREST: + case osg::Texture::NEAREST_MIPMAP_LINEAR: + case osg::Texture::NEAREST_MIPMAP_NEAREST: + newMin = osg::Texture::NEAREST; + break; + } + tex->setFilter(osg::Texture::MIN_FILTER, newMin); + } + else + tex->setFilter(osg::Texture::MIN_FILTER, mMinFilter); + tex->setFilter(osg::Texture::MAG_FILTER, mMagFilter); tex->setMaxAnisotropy(static_cast(mMaxAnisotropy)); } From 992b7703155300f6a0c83b47f78f6513561f0a66 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 15 Jul 2015 18:52:23 +0200 Subject: [PATCH 4/9] Don't set OnPcEquip for items that failed to equip (Fixes #2776) --- apps/openmw/mwgui/inventorywindow.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 392a4a84a..39f476403 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -436,6 +436,20 @@ namespace MWGui { const std::string& script = ptr.getClass().getScript(ptr); + MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); + + // early-out for items that need to be equipped, but can't be equipped: we don't want to set OnPcEquip in that case + if (!ptr.getClass().getEquipmentSlots(ptr).first.empty()) + { + std::pair canEquip = ptr.getClass().canBeEquipped(ptr, player); + if (canEquip.first == 0) + { + MWBase::Environment::get().getWindowManager()->messageBox(canEquip.second); + updateItemView(); + return; + } + } + // If the item has a script, set its OnPcEquip to 1 if (!script.empty() // Another morrowind oddity: when an item has skipped equipping and pcskipequip is reset to 0 afterwards, @@ -455,7 +469,7 @@ namespace MWGui { boost::shared_ptr action = ptr.getClass().use(ptr); - action->execute (MWBase::Environment::get().getWorld()->getPlayerPtr()); + action->execute (player); mSkippedToEquip = MWWorld::Ptr(); } From f8d360190d7443337e5a1d48d8b0505491c5fd73 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 15 Jul 2015 19:10:09 +0200 Subject: [PATCH 5/9] Remove an unneeded virtual --- apps/openmw/mwgui/windowbase.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/windowbase.hpp b/apps/openmw/mwgui/windowbase.hpp index 195b6c384..43fb8901e 100644 --- a/apps/openmw/mwgui/windowbase.hpp +++ b/apps/openmw/mwgui/windowbase.hpp @@ -21,16 +21,16 @@ namespace MWGui // Events typedef MyGUI::delegates::CMultiDelegate1 EventHandle_WindowBase; - ///Unhides the window + /// Notify that window has been made visible virtual void open() {} - ///Hides the window + /// Notify that window has been hidden virtual void close () {} - ///Gracefully exits the window + /// Gracefully exits the window virtual void exit() {} - ///Sets the visibility of the window + /// Sets the visibility of the window virtual void setVisible(bool visible); - ///Returns the visibility state of the window - virtual bool isVisible(); + /// Returns the visibility state of the window + bool isVisible(); void center(); }; From 9a115fedbc724ce29e3cae8da6a19d24c28a0fa3 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 16 Jul 2015 20:11:33 +0200 Subject: [PATCH 6/9] Add ability to copy&paste the version label in the main menu --- files/mygui/openmw_mainmenu.layout | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/files/mygui/openmw_mainmenu.layout b/files/mygui/openmw_mainmenu.layout index f4c7142ce..c4d88ff85 100644 --- a/files/mygui/openmw_mainmenu.layout +++ b/files/mygui/openmw_mainmenu.layout @@ -3,10 +3,12 @@ - + + + From 91d71d0fcd690559a47dec6a889ca189ee09a199 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 17 Jul 2015 03:39:09 +0200 Subject: [PATCH 7/9] Disable MyGUI's scrollbar autorepeat (Fixes #2779) We are currently using a custom implementation so as to support MyGUI version 3.2.1. When compiled with 3.2.2 or later, we need to disable MyGUI's autorepeat so that it doesn't interfere with ours. --- apps/openmw/mwgui/widgets.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwgui/widgets.cpp b/apps/openmw/mwgui/widgets.cpp index 158d5fd5e..481ffaade 100644 --- a/apps/openmw/mwgui/widgets.cpp +++ b/apps/openmw/mwgui/widgets.cpp @@ -539,6 +539,9 @@ namespace MWGui , mRepeatStepTime(0.1f) , mIsIncreasing(true) { +#if MYGUI_VERSION >= MYGUI_DEFINE_VERSION(3,2,2) + ScrollBar::setRepeatEnabled(false); +#endif } MWScrollBar::~MWScrollBar() From 41bed4c7d9c2a1dc4a7f3e4444433a0d50df4a16 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 17 Jul 2015 20:49:10 +0200 Subject: [PATCH 8/9] Use multimap to speed up custom map marker code --- apps/openmw/mwgui/mapwindow.cpp | 118 ++++++++++++++----------- apps/openmw/mwgui/mapwindow.hpp | 12 ++- apps/openmw/mwgui/windowmanagerimp.cpp | 4 +- components/esm/cellid.cpp | 23 +++++ components/esm/cellid.hpp | 1 + 5 files changed, 100 insertions(+), 58 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 442fbeb08..7778569d2 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -92,31 +92,41 @@ namespace MWGui void CustomMarkerCollection::addMarker(const ESM::CustomMarker &marker, bool triggerEvent) { - mMarkers.push_back(marker); + mMarkers.insert(std::make_pair(marker.mCell, marker)); if (triggerEvent) eventMarkersChanged(); } void CustomMarkerCollection::deleteMarker(const ESM::CustomMarker &marker) { - std::vector::iterator it = std::find(mMarkers.begin(), mMarkers.end(), marker); - if (it != mMarkers.end()) - mMarkers.erase(it); - else - throw std::runtime_error("can't find marker to delete"); + std::pair range = mMarkers.equal_range(marker.mCell); - eventMarkersChanged(); + for (ContainerType::iterator it = range.first; it != range.second; ++it) + { + if (it->second == marker) + { + mMarkers.erase(it); + eventMarkersChanged(); + return; + } + } + throw std::runtime_error("can't find marker to delete"); } void CustomMarkerCollection::updateMarker(const ESM::CustomMarker &marker, const std::string &newNote) { - std::vector::iterator it = std::find(mMarkers.begin(), mMarkers.end(), marker); - if (it != mMarkers.end()) - it->mNote = newNote; - else - throw std::runtime_error("can't find marker to update"); + std::pair range = mMarkers.equal_range(marker.mCell); - eventMarkersChanged(); + for (ContainerType::iterator it = range.first; it != range.second; ++it) + { + if (it->second == marker) + { + it->second.mNote = newNote; + eventMarkersChanged(); + return; + } + } + throw std::runtime_error("can't find marker to update"); } void CustomMarkerCollection::clear() @@ -125,16 +135,21 @@ namespace MWGui eventMarkersChanged(); } - std::vector::const_iterator CustomMarkerCollection::begin() const + CustomMarkerCollection::ContainerType::const_iterator CustomMarkerCollection::begin() const { return mMarkers.begin(); } - std::vector::const_iterator CustomMarkerCollection::end() const + CustomMarkerCollection::ContainerType::const_iterator CustomMarkerCollection::end() const { return mMarkers.end(); } + CustomMarkerCollection::RangeType CustomMarkerCollection::getMarkers(const ESM::CellId &cellId) const + { + return mMarkers.equal_range(cellId); + } + size_t CustomMarkerCollection::size() const { return mMarkers.size(); @@ -299,44 +314,43 @@ namespace MWGui MyGUI::Gui::getInstance().destroyWidget(*it); mCustomMarkerWidgets.clear(); - for (std::vector::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) + for (int dX = -1; dX <= 1; ++dX) { - const ESM::CustomMarker& marker = *it; - - if (marker.mCell.mPaged != !mInterior) - continue; - if (mInterior) + for (int dY =-1; dY <= 1; ++dY) { - if (marker.mCell.mWorldspace != mPrefix) - continue; - } - else - { - if (std::abs(marker.mCell.mIndex.mX - mCurX) > 1) - continue; - if (std::abs(marker.mCell.mIndex.mY - mCurY) > 1) - continue; - } + ESM::CellId cellId; + cellId.mPaged = !mInterior; + cellId.mWorldspace = (mInterior ? mPrefix : "sys::default"); + cellId.mIndex.mX = mCurX+dX; + cellId.mIndex.mY = mCurY+dY; - MarkerUserData markerPos (mLocalMapRender); - MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos); + CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(cellId); + for (CustomMarkerCollection::ContainerType::const_iterator it = markers.first; it != markers.second; ++it) + { + const ESM::CustomMarker& marker = it->second; - MyGUI::IntCoord widgetCoord(widgetPos.left - 8, - widgetPos.top - 8, - 16, 16); - MarkerWidget* markerWidget = mLocalMap->createWidget("CustomMarkerButton", - widgetCoord, MyGUI::Align::Default); - markerWidget->setDepth(Local_MarkerAboveFogLayer); - markerWidget->setUserString("ToolTipType", "Layout"); - markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); - markerWidget->setUserString("Caption_TextOneLine", MyGUI::TextIterator::toTagsString(marker.mNote)); - markerWidget->setNormalColour(MyGUI::Colour(0.6f, 0.6f, 0.6f)); - markerWidget->setHoverColour(MyGUI::Colour(1.0f, 1.0f, 1.0f)); - markerWidget->setUserData(marker); - markerWidget->setNeedMouseFocus(true); - customMarkerCreated(markerWidget); - mCustomMarkerWidgets.push_back(markerWidget); + MarkerUserData markerPos (mLocalMapRender); + MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos); + + MyGUI::IntCoord widgetCoord(widgetPos.left - 8, + widgetPos.top - 8, + 16, 16); + MarkerWidget* markerWidget = mLocalMap->createWidget("CustomMarkerButton", + widgetCoord, MyGUI::Align::Default); + markerWidget->setDepth(Local_MarkerAboveFogLayer); + markerWidget->setUserString("ToolTipType", "Layout"); + markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); + markerWidget->setUserString("Caption_TextOneLine", MyGUI::TextIterator::toTagsString(marker.mNote)); + markerWidget->setNormalColour(MyGUI::Colour(0.6f, 0.6f, 0.6f)); + markerWidget->setHoverColour(MyGUI::Colour(1.0f, 1.0f, 1.0f)); + markerWidget->setUserData(marker); + markerWidget->setNeedMouseFocus(true); + customMarkerCreated(markerWidget); + mCustomMarkerWidgets.push_back(markerWidget); + } + } } + redraw(); } @@ -411,11 +425,9 @@ namespace MWGui MWBase::World::DoorMarker marker = *it; std::vector destNotes; - for (std::vector::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) - { - if (it->mCell == marker.dest) - destNotes.push_back(it->mNote); - } + CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(marker.dest); + for (CustomMarkerCollection::ContainerType::const_iterator it = markers.first; it != markers.second; ++it) + destNotes.push_back(it->second.mNote); MarkerUserData data (mLocalMapRender); data.notes = destNotes; diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 388103b5d..ec4298786 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -42,14 +42,20 @@ namespace MWGui size_t size() const; - std::vector::const_iterator begin() const; - std::vector::const_iterator end() const; + typedef std::multimap ContainerType; + + typedef std::pair RangeType; + + ContainerType::const_iterator begin() const; + ContainerType::const_iterator end() const; + + RangeType getMarkers(const ESM::CellId& cellId) const; typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; EventHandle_Void eventMarkersChanged; private: - std::vector mMarkers; + ContainerType mMarkers; }; class LocalMapBase diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 582519b19..4dbef8a74 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1672,10 +1672,10 @@ namespace MWGui writer.endRecord(ESM::REC_ASPL); } - for (std::vector::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) + for (CustomMarkerCollection::ContainerType::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) { writer.startRecord(ESM::REC_MARK); - (*it).save(writer); + it->second.save(writer); writer.endRecord(ESM::REC_MARK); } } diff --git a/components/esm/cellid.cpp b/components/esm/cellid.cpp index 3c6e23ffd..c77b27b22 100644 --- a/components/esm/cellid.cpp +++ b/components/esm/cellid.cpp @@ -35,3 +35,26 @@ bool ESM::operator!= (const CellId& left, const CellId& right) { return !(left==right); } + +bool ESM::operator < (const CellId& left, const CellId& right) +{ + if (left.mPaged < right.mPaged) + return true; + if (left.mPaged > right.mPaged) + return false; + + if (left.mPaged) + { + if (left.mIndex.mX < right.mIndex.mX) + return true; + if (left.mIndex.mX > right.mIndex.mX) + return false; + + if (left.mIndex.mY < right.mIndex.mY) + return true; + if (left.mIndex.mY > right.mIndex.mY) + return false; + } + + return left.mWorldspace < right.mWorldspace; +} diff --git a/components/esm/cellid.hpp b/components/esm/cellid.hpp index 44a1b387a..56d5a674e 100644 --- a/components/esm/cellid.hpp +++ b/components/esm/cellid.hpp @@ -26,6 +26,7 @@ namespace ESM bool operator== (const CellId& left, const CellId& right); bool operator!= (const CellId& left, const CellId& right); + bool operator< (const CellId& left, const CellId& right); } #endif From 6e493500c9099a646598ae92984cd66f54aa6ca7 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 18 Jul 2015 00:14:11 +0200 Subject: [PATCH 9/9] Show custom map markers on the tooltip of the world map marker (Fixes #2711) --- apps/openmw/mwgui/mapwindow.cpp | 57 +++++++++++++++++++++++++++++---- apps/openmw/mwgui/mapwindow.hpp | 7 ++-- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 7778569d2..2485f3c94 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -783,15 +783,19 @@ namespace MWGui MyGUI::Widget* markerWidget = mGlobalMap->createWidget("MarkerButton", widgetCoord, MyGUI::Align::Default); + + markerWidget->setUserString("Caption_TextOneLine", name); + + setGlobalMapMarkerTooltip(markerWidget, x, y); + + markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); + markerWidget->setNeedMouseFocus(true); markerWidget->setColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}"))); - markerWidget->setUserString("ToolTipType", "Layout"); - markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); - markerWidget->setUserString("Caption_TextOneLine", name); markerWidget->setDepth(Global_MarkerLayer); markerWidget->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag); markerWidget->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart); - mGlobalMapMarkers.push_back(markerWidget); + mGlobalMapMarkers[std::make_pair(x,y)] = markerWidget; } } @@ -816,6 +820,45 @@ namespace MWGui NoDrop::onFrame(dt); } + void MapWindow::setGlobalMapMarkerTooltip(MyGUI::Widget* markerWidget, int x, int y) + { + ESM::CellId cellId; + cellId.mIndex.mX = x; + cellId.mIndex.mY = y; + cellId.mWorldspace = "sys::default"; + cellId.mPaged = true; + CustomMarkerCollection::RangeType markers = mCustomMarkers.getMarkers(cellId); + std::vector destNotes; + for (CustomMarkerCollection::ContainerType::const_iterator it = markers.first; it != markers.second; ++it) + destNotes.push_back(it->second.mNote); + + if (!destNotes.empty()) + { + MarkerUserData data (NULL); + data.notes = destNotes; + data.caption = markerWidget->getUserString("Caption_TextOneLine"); + markerWidget->setUserData(data); + markerWidget->setUserString("ToolTipType", "MapMarker"); + } + else + { + markerWidget->setUserString("ToolTipType", "Layout"); + } + } + + void MapWindow::updateCustomMarkers() + { + LocalMapBase::updateCustomMarkers(); + + for (std::map, MyGUI::Widget*>::iterator widgetIt = mGlobalMapMarkers.begin(); widgetIt != mGlobalMapMarkers.end(); ++widgetIt) + { + int x = widgetIt->first.first; + int y = widgetIt->first.second; + MyGUI::Widget* markerWidget = widgetIt->second; + setGlobalMapMarkerTooltip(markerWidget, x, y); + } + } + void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id) { if (_id!=MyGUI::MouseButton::Left) return; @@ -913,8 +956,8 @@ namespace MWGui mGlobalMapRender->clear(); mChanged = true; - for (std::vector::iterator it = mGlobalMapMarkers.begin(); it != mGlobalMapMarkers.end(); ++it) - MyGUI::Gui::getInstance().destroyWidget(*it); + for (std::map, MyGUI::Widget*>::iterator it = mGlobalMapMarkers.begin(); it != mGlobalMapMarkers.end(); ++it) + MyGUI::Gui::getInstance().destroyWidget(it->second); mGlobalMapMarkers.clear(); } @@ -1034,6 +1077,8 @@ namespace MWGui bool LocalMapBase::MarkerUserData::isPositionExplored() const { + if (!mLocalMapRender) + return true; return mLocalMapRender->isPositionExplored(nX, nY, cellX, cellY, interior); } diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index ec4298786..a5594bee8 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -126,7 +126,7 @@ namespace MWGui std::vector mMagicMarkerWidgets; std::vector mCustomMarkerWidgets; - void updateCustomMarkers(); + virtual void updateCustomMarkers(); void applyFogOfWar(); @@ -203,6 +203,8 @@ namespace MWGui void onFrame(float dt); + virtual void updateCustomMarkers(); + /// Clear all savegame-specific data void clear(); @@ -221,6 +223,7 @@ namespace MWGui void onNoteDoubleClicked(MyGUI::Widget* sender); void onChangeScrollWindowCoord(MyGUI::Widget* sender); void globalMapUpdatePlayer(); + void setGlobalMapMarkerTooltip(MyGUI::Widget* widget, int x, int y); MyGUI::ScrollView* mGlobalMap; std::auto_ptr mGlobalMapTexture; @@ -248,7 +251,7 @@ namespace MWGui MWRender::GlobalMap* mGlobalMapRender; - std::vector mGlobalMapMarkers; + std::map, MyGUI::Widget*> mGlobalMapMarkers; EditNoteDialog mEditNoteDialog; ESM::CustomMarker mEditingMarker;