From d649c197906a35b28a30e601bc8a82a9ab746eb2 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 13 Aug 2014 16:00:32 +0200 Subject: [PATCH 01/16] Cache ActorId in AiFollow::getTarget (Fixes #1804) --- apps/openmw/mwmechanics/aifollow.cpp | 33 +++++++++++++++++++--------- apps/openmw/mwmechanics/aifollow.hpp | 5 +++-- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 623306411..44d2552be 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -16,24 +16,28 @@ #include "steering.hpp" MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mCommanded(false), mRemainingDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId("") +: mAlwaysFollow(false), mCommanded(false), mRemainingDuration(duration), mX(x), mY(y), mZ(z) +, mActorRefId(actorId), mCellId(""), mActorId(-1) { } MWMechanics::AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) -: mAlwaysFollow(false), mCommanded(false), mRemainingDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId), mCellId(cellId) +: mAlwaysFollow(false), mCommanded(false), mRemainingDuration(duration), mX(x), mY(y), mZ(z) +, mActorRefId(actorId), mCellId(cellId), mActorId(-1) { } MWMechanics::AiFollow::AiFollow(const std::string &actorId, bool commanded) -: mAlwaysFollow(true), mCommanded(commanded), mRemainingDuration(0), mX(0), mY(0), mZ(0), mActorId(actorId), mCellId("") +: mAlwaysFollow(true), mCommanded(commanded), mRemainingDuration(0), mX(0), mY(0), mZ(0) +, mActorRefId(actorId), mCellId(""), mActorId(-1) { } bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) { - const MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mActorId, false); //The target to follow + MWWorld::Ptr target = getTarget(); - if(target == MWWorld::Ptr()) return true; //Target doesn't exist + if (target.isEmpty()) + return true; //Target doesn't exist actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); @@ -86,7 +90,7 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) std::string MWMechanics::AiFollow::getFollowedActor() { - return mActorId; + return mActorRefId; } MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const @@ -110,7 +114,7 @@ void MWMechanics::AiFollow::writeState(ESM::AiSequence::AiSequence &sequence) co follow->mData.mX = mX; follow->mData.mY = mY; follow->mData.mZ = mZ; - follow->mTargetId = mActorId; + follow->mTargetId = mActorRefId; follow->mRemainingDuration = mRemainingDuration; follow->mCellId = mCellId; follow->mAlwaysFollow = mAlwaysFollow; @@ -125,13 +129,22 @@ void MWMechanics::AiFollow::writeState(ESM::AiSequence::AiSequence &sequence) co MWMechanics::AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow) : mAlwaysFollow(follow->mAlwaysFollow), mRemainingDuration(follow->mRemainingDuration) , mX(follow->mData.mX), mY(follow->mData.mY), mZ(follow->mData.mZ) - , mActorId(follow->mTargetId), mCellId(follow->mCellId) + , mActorRefId(follow->mTargetId), mCellId(follow->mCellId) , mCommanded(follow->mCommanded) { } -MWWorld::Ptr MWMechanics::AiFollow::getTarget() const +MWWorld::Ptr MWMechanics::AiFollow::getTarget() { - return MWBase::Environment::get().getWorld()->searchPtr(mActorId, false); + if (mActorId == -1) + { + MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mActorRefId, false); + mActorId = target.getClass().getCreatureStats(target).getActorId(); + } + + if (mActorId != -1) + return MWBase::Environment::get().getWorld()->searchPtrViaActorId(mActorId); + else + return MWWorld::Ptr(); } diff --git a/apps/openmw/mwmechanics/aifollow.hpp b/apps/openmw/mwmechanics/aifollow.hpp index c0eef8008..483901b69 100644 --- a/apps/openmw/mwmechanics/aifollow.hpp +++ b/apps/openmw/mwmechanics/aifollow.hpp @@ -31,7 +31,7 @@ namespace MWMechanics AiFollow(const ESM::AiSequence::AiFollow* follow); - MWWorld::Ptr getTarget() const; + MWWorld::Ptr getTarget(); virtual AiFollow *clone() const; @@ -55,7 +55,8 @@ namespace MWMechanics float mX; float mY; float mZ; - std::string mActorId; + std::string mActorRefId; + int mActorId; std::string mCellId; }; } From 09f27d142a604c744114eb2fa87ba39ba910279e Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 13 Aug 2014 16:23:34 +0200 Subject: [PATCH 02/16] Clear movement queue when changing to a new cell (Fixes #1802) --- apps/openmw/mwworld/physicssystem.cpp | 7 +++++++ apps/openmw/mwworld/physicssystem.hpp | 4 ++++ apps/openmw/mwworld/worldimp.cpp | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 3c0e67729..0d6cef565 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -784,6 +784,13 @@ namespace MWWorld mMovementQueue.push_back(std::make_pair(ptr, movement)); } + void PhysicsSystem::clearQueuedMovement() + { + mMovementQueue.clear(); + mCollisions.clear(); + mStandingCollisions.clear(); + } + const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt) { // Collision events are only tracked for a single frame, so reset first diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index f0522426d..e66c179b0 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -85,8 +85,12 @@ namespace MWWorld /// be overwritten. Valid until the next call to applyQueuedMovement. void queueObjectMovement(const Ptr &ptr, const Ogre::Vector3 &velocity); + /// Apply all queued movements, then clear the list. const PtrVelocityList& applyQueuedMovement(float dt); + /// Clear the queued movements list without applying. + void clearQueuedMovement(); + /// Return true if \a actor has been standing on \a object in this frame /// This will trigger whenever the object is directly below the actor. /// It doesn't matter if the actor is stationary or moving. diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index a84e4781d..4deed671e 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -840,6 +840,8 @@ namespace MWWorld void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) { + mPhysics->clearQueuedMovement(); + if (mCurrentWorldSpace != cellName) { // changed worldspace @@ -855,6 +857,8 @@ namespace MWWorld void World::changeToExteriorCell (const ESM::Position& position) { + mPhysics->clearQueuedMovement(); + if (mCurrentWorldSpace != "sys::default") // FIXME { // changed worldspace From 28e61c983465655930e5ebf0330844a667ecbe8a Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 13 Aug 2014 17:32:52 +0200 Subject: [PATCH 03/16] Add default values for fDifficultyMult and sDifficulty (Fixes #1742) Also added values for some other GMSTs added in a Morrowind patch or Tribunal/BM --- apps/openmw/mwworld/worldimp.cpp | 77 +++++++++++++++++++++----------- components/esm/variant.cpp | 24 ++++++++++ components/esm/variant.hpp | 6 ++- 3 files changed, 79 insertions(+), 28 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 4deed671e..881f01285 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -350,36 +350,59 @@ namespace MWWorld void World::ensureNeededRecords() { - if (!mStore.get().search("sCompanionShare")) + std::map gmst; + // Companion (tribunal) + gmst["sCompanionShare"] = ESM::Variant("Companion Share"); + gmst["sCompanionWarningMessage"] = ESM::Variant("Warning message"); + gmst["sCompanionWarningButtonOne"] = ESM::Variant("Button 1"); + gmst["sCompanionWarningButtonTwo"] = ESM::Variant("Button 2"); + gmst["sCompanionShare"] = ESM::Variant("Companion Share"); + gmst["sProfitValue"] = ESM::Variant("Profit Value"); + gmst["sTeleportDisabled"] = ESM::Variant("Teleport disabled"); + gmst["sLevitateDisabled"] = ESM::Variant("Levitate disabled"); + + // Missing in unpatched MW 1.0 + gmst["sDifficulty"] = ESM::Variant("Difficulty"); + gmst["fDifficultyMult"] = ESM::Variant(5.f); + gmst["sAuto_Run"] = ESM::Variant("Auto Run"); + gmst["sServiceRefusal"] = ESM::Variant("Service Refusal"); + gmst["sNeedOneSkill"] = ESM::Variant("Need one skill"); + gmst["sNeedTwoSkills"] = ESM::Variant("Need two skills"); + gmst["sEasy"] = ESM::Variant("Easy"); + gmst["sHard"] = ESM::Variant("Hard"); + gmst["sDeleteNote"] = ESM::Variant("Delete Note"); + gmst["sEditNote"] = ESM::Variant("Edit Note"); + + // Werewolf (BM) + gmst["fWereWolfRunMult"] = ESM::Variant(1.f); + gmst["fWereWolfSilverWeaponDamageMult"] = ESM::Variant(1.f); + + + std::map globals; + // vanilla Morrowind does not define dayspassed. + globals["dayspassed"] = ESM::Variant(1); // but the addons start counting at 1 :( + globals["WerewolfClawMult"] = ESM::Variant(1.f); + + for (std::map::iterator it = gmst.begin(); it != gmst.end(); ++it) { - ESM::GameSetting sCompanionShare; - sCompanionShare.mId = "sCompanionShare"; - ESM::Variant value; - value.setType(ESM::VT_String); - value.setString("Companion Share"); - sCompanionShare.mValue = value; - mStore.insertStatic(sCompanionShare); + if (!mStore.get().search(it->first)) + { + ESM::GameSetting setting; + setting.mId = it->first; + setting.mValue = it->second; + mStore.insertStatic(setting); + } } - if (!mStore.get().search("dayspassed")) + + for (std::map::iterator it = globals.begin(); it != globals.end(); ++it) { - // vanilla Morrowind does not define dayspassed. - ESM::Global dayspassed; - dayspassed.mId = "dayspassed"; - ESM::Variant value; - value.setType(ESM::VT_Long); - value.setInteger(1); // but the addons start counting at 1 :( - dayspassed.mValue = value; - mStore.insertStatic(dayspassed); - } - if (!mStore.get().search("fWereWolfRunMult")) - { - ESM::GameSetting fWereWolfRunMult; - fWereWolfRunMult.mId = "fWereWolfRunMult"; - ESM::Variant value; - value.setType(ESM::VT_Float); - value.setFloat(1.f); - fWereWolfRunMult.mValue = value; - mStore.insertStatic(fWereWolfRunMult); + if (!mStore.get().search(it->first)) + { + ESM::Global setting; + setting.mId = it->first; + setting.mValue = it->second; + mStore.insertStatic(setting); + } } } diff --git a/components/esm/variant.cpp b/components/esm/variant.cpp index 217ec4407..4127a9d62 100644 --- a/components/esm/variant.cpp +++ b/components/esm/variant.cpp @@ -17,6 +17,30 @@ namespace ESM::Variant::Variant() : mType (VT_None), mData (0) {} +ESM::Variant::Variant(const std::string &value) +{ + mData = 0; + mType = VT_None; + setType(VT_String); + setString(value); +} + +ESM::Variant::Variant(int value) +{ + mData = 0; + mType = VT_None; + setType(VT_Long); + setInteger(value); +} + +ESM::Variant::Variant(float value) +{ + mData = 0; + mType = VT_None; + setType(VT_Float); + setFloat(value); +} + ESM::Variant::~Variant() { delete mData; diff --git a/components/esm/variant.hpp b/components/esm/variant.hpp index 8ba9bb34f..d6c1a5489 100644 --- a/components/esm/variant.hpp +++ b/components/esm/variant.hpp @@ -38,6 +38,10 @@ namespace ESM Variant(); + Variant (const std::string& value); + Variant (int value); + Variant (float value); + ~Variant(); Variant& operator= (const Variant& variant); @@ -83,4 +87,4 @@ namespace ESM bool operator!= (const Variant& left, const Variant& right); } -#endif \ No newline at end of file +#endif From 94c2517d6713982c008801bd728b6ce062f7bf5f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 13 Aug 2014 19:30:46 +0200 Subject: [PATCH 04/16] Fix race preview crash (Fixes #1808) --- apps/openmw/mwgui/race.cpp | 19 ++++++++++++++----- apps/openmw/mwgui/race.hpp | 2 +- apps/openmw/mwrender/characterpreview.cpp | 3 +++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 499c1e191..a51250c9d 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -32,7 +32,6 @@ namespace MWGui , mHairIndex(0) , mCurrentAngle(0) , mPreviewDirty(true) - , mPreview(NULL) { // Centre dialog center(); @@ -115,7 +114,14 @@ namespace MWGui updateSkills(); updateSpellPowers(); - mPreview = new MWRender::RaceSelectionPreview(); + mPreview.reset(NULL); + + mPreviewImage->setImageTexture(""); + + const std::string textureName = "CharacterHeadPreview"; + MyGUI::RenderManager::getInstance().destroyTexture(MyGUI::RenderManager::getInstance().getTexture(textureName)); + + mPreview.reset(new MWRender::RaceSelectionPreview()); mPreview->setup(); mPreview->update (0); @@ -129,7 +135,7 @@ namespace MWGui index = proto.mHair.substr(proto.mHair.size() - 2, 2); mHairIndex = boost::lexical_cast(index) - 1; - mPreviewImage->setImageTexture ("CharacterHeadPreview"); + mPreviewImage->setImageTexture (textureName); mPreviewDirty = true; } @@ -157,8 +163,7 @@ namespace MWGui void RaceDialog::close() { - delete mPreview; - mPreview = 0; + mPreview.reset(NULL); } // widget controls @@ -306,6 +311,10 @@ namespace MWGui void RaceDialog::doRenderUpdate() { + if (!mPreview.get()) + return; + + mPreview->onFrame(); if (mPreviewDirty) { mPreview->render(); diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index 340dcfa27..46c4c5ef4 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -100,7 +100,7 @@ namespace MWGui float mCurrentAngle; - MWRender::RaceSelectionPreview* mPreview; + std::auto_ptr mPreview; bool mPreviewDirty; }; diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index fd07f1a19..1af11996e 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -298,6 +298,9 @@ namespace MWRender void RaceSelectionPreview::render() { mTexture->load(); + + if (!mRenderTarget) + setupRenderTarget(); mRenderTarget->update(); } From f8010c09fe35fcc8ca6ea2d200979d1cae79a1b6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Aug 2014 01:08:09 +0200 Subject: [PATCH 05/16] Adjust combat engagement of following actors (Fixes #1810) --- apps/openmw/mwmechanics/actors.cpp | 45 ++++++++++++++++++++-------- apps/openmw/mwmechanics/aifollow.cpp | 11 ++++++- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 92879fe37..dfec007d7 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -301,20 +301,31 @@ namespace MWMechanics } } - // start combat if we are in combat with any followers of this actor - const std::list& followers = getActorsFollowing(actor2); + // start combat if target actor is in combat with one of our followers + const std::list& followers = getActorsFollowing(actor1); + const CreatureStats& creatureStats2 = actor2.getClass().getCreatureStats(actor2); for (std::list::const_iterator it = followers.begin(); it != followers.end(); ++it) { - if (creatureStats.getAiSequence().isInCombat(*it)) + // need to check both ways since player doesn't use AI packages + if (creatureStats2.getAiSequence().isInCombat(*it) + || it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(actor2)) aggressive = true; } - // start combat if we are in combat with someone this actor is following - const CreatureStats& creatureStats2 = actor2.getClass().getCreatureStats(actor2); - for (std::list::const_iterator it = creatureStats2.getAiSequence().begin(); it != creatureStats2.getAiSequence().end(); ++it) + + // start combat if target actor is in combat with someone we are following + for (std::list::const_iterator it = creatureStats.getAiSequence().begin(); it != creatureStats.getAiSequence().end(); ++it) { - if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow && - creatureStats.getAiSequence().isInCombat(dynamic_cast(*it)->getTarget())) - aggressive = true; + if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow) + { + MWWorld::Ptr followTarget = dynamic_cast(*it)->getTarget(); + if (followTarget.isEmpty()) + continue; + + // need to check both ways since player doesn't use AI packages + if (creatureStats2.getAiSequence().isInCombat(followTarget) + || followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2)) + aggressive = true; + } } if(aggressive) @@ -1374,11 +1385,19 @@ namespace MWMechanics { const MWWorld::Class &cls = iter->first.getClass(); CreatureStats &stats = cls.getCreatureStats(iter->first); - if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow) + if (stats.isDead()) + continue; + + for (std::list::const_iterator it = stats.getAiSequence().begin(); it != stats.getAiSequence().end(); ++it) { - MWMechanics::AiFollow* package = static_cast(stats.getAiSequence().getActivePackage()); - if(package->getFollowedActor() == actor.getCellRef().getRefId()) - list.push_front(iter->first); + if ((*it)->getTypeId() == MWMechanics::AiPackage::TypeIdFollow) + { + MWWorld::Ptr followTarget = dynamic_cast(*it)->getTarget(); + if (followTarget.isEmpty()) + continue; + if (followTarget == actor) + list.push_back(iter->first); + } } } return list; diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 44d2552be..d8b16b366 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -137,10 +137,19 @@ MWMechanics::AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow) MWWorld::Ptr MWMechanics::AiFollow::getTarget() { + if (mActorId == -2) + return MWWorld::Ptr(); + if (mActorId == -1) { MWWorld::Ptr target = MWBase::Environment::get().getWorld()->searchPtr(mActorRefId, false); - mActorId = target.getClass().getCreatureStats(target).getActorId(); + if (target.isEmpty()) + { + mActorId = -2; + return target; + } + else + mActorId = target.getClass().getCreatureStats(target).getActorId(); } if (mActorId != -1) From 061c7813f6362b8ed16d6c79c016e6d5be18fdef Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Aug 2014 01:20:12 +0200 Subject: [PATCH 06/16] AiFollow: return from execute() if target is not player (Fixes #1637) --- apps/openmw/mwmechanics/aifollow.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index d8b16b366..fb24946a5 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -39,6 +39,11 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration) if (target.isEmpty()) return true; //Target doesn't exist + // Only the player can be actively followed. AiFollow packages with targets other than the player + // are only used for defining combat alliances, since NPCs will defend whoever they are following or being followed by. + if (target != MWBase::Environment::get().getWorld()->getPlayerPtr()) + return false; + actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); ESM::Position pos = actor.getRefData().getPosition(); //position of the actor From 1bb82c710c1081d99c3b53467124973bd0f1a4f5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Aug 2014 18:55:54 +0200 Subject: [PATCH 07/16] Fix use of uninitialized memory in AiWander::init --- apps/openmw/mwmechanics/aiwander.cpp | 20 +++++++++++--------- apps/openmw/mwmechanics/aiwander.hpp | 3 ++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 3b093d6f6..6b73c9eb4 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -35,6 +35,8 @@ namespace MWMechanics void AiWander::init() { + // NOTE: mDistance and mDuration must be set already + mCellX = std::numeric_limits::max(); mCellY = std::numeric_limits::max(); mXCell = 0; @@ -47,7 +49,7 @@ namespace MWMechanics mRotate = false; mTargetAngle = 0; mSaidGreeting = Greet_None; - greetingTimer = 0; + mGreetingTimer = 0; mHasReturnPosition = false; mReturnPosition = Ogre::Vector3(0,0,0); @@ -430,19 +432,19 @@ namespace MWMechanics { if ((playerDistSqr <= helloDistance*helloDistance) && MWBase::Environment::get().getWorld()->getLOS(player, actor) && MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, actor)) - greetingTimer++; + mGreetingTimer++; - if (greetingTimer >= GREETING_SHOULD_START) + if (mGreetingTimer >= GREETING_SHOULD_START) { mSaidGreeting = Greet_InProgress; MWBase::Environment::get().getDialogueManager()->say(actor, "hello"); - greetingTimer = 0; + mGreetingTimer = 0; } } if(mSaidGreeting == Greet_InProgress) { - greetingTimer++; + mGreetingTimer++; if(mWalking) { @@ -470,10 +472,10 @@ namespace MWMechanics } } - if (greetingTimer >= GREETING_SHOULD_END) + if (mGreetingTimer >= GREETING_SHOULD_END) { mSaidGreeting = Greet_Done; - greetingTimer = 0; + mGreetingTimer = 0; } } @@ -680,8 +682,6 @@ namespace MWMechanics AiWander::AiWander (const ESM::AiSequence::AiWander* wander) { - init(); - mDistance = wander->mData.mDistance; mDuration = wander->mData.mDuration; mStartTime = MWWorld::TimeStamp(wander->mStartTime); @@ -690,6 +690,8 @@ namespace MWMechanics mIdle.push_back(wander->mData.mIdle[i]); mRepeat = wander->mData.mShouldRepeat; + + init(); } } diff --git a/apps/openmw/mwmechanics/aiwander.hpp b/apps/openmw/mwmechanics/aiwander.hpp index 9b579b24a..59a51446e 100644 --- a/apps/openmw/mwmechanics/aiwander.hpp +++ b/apps/openmw/mwmechanics/aiwander.hpp @@ -36,6 +36,7 @@ namespace MWMechanics AiWander (const ESM::AiSequence::AiWander* wander); + // NOTE: mDistance and mDuration must be set already void init(); virtual AiPackage *clone() const; @@ -68,7 +69,7 @@ namespace MWMechanics Greet_Done }; GreetingState mSaidGreeting; - int greetingTimer; + int mGreetingTimer; bool mHasReturnPosition; // NOTE: Could be removed if mReturnPosition was initialized to actor position, // if we had the actor in the AiWander constructor... From c065a4b203ec53906477aa77e0e205351d83523e Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Aug 2014 19:01:03 +0200 Subject: [PATCH 08/16] Add ManualResourceLoader for global map overlay (Fixes #1736) --- apps/openmw/mwgui/mapwindow.cpp | 8 +--- apps/openmw/mwrender/globalmap.cpp | 70 ++++++++++++++++++++---------- apps/openmw/mwrender/globalmap.hpp | 6 ++- apps/openmw/mwrender/localmap.cpp | 1 + 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 39df4d03e..1f2794be3 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -544,15 +544,9 @@ namespace MWGui void MapWindow::open() { - // force markers to foreground - for (unsigned int i=0; igetChildCount (); ++i) - { - if (mGlobalMapOverlay->getChildAt (i)->getName().substr(0,4) == "Door") - mGlobalMapOverlay->getChildAt (i)->castType()->setImageResource("DoorMarker"); - } - globalMapUpdatePlayer(); + mPlayerArrowGlobal->setImageTexture (""); mPlayerArrowGlobal->setImageTexture ("textures\\compass.dds"); } diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 1ccfd9527..d543308ff 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -31,6 +31,10 @@ namespace MWRender { } + GlobalMap::~GlobalMap() + { + Ogre::TextureManager::getSingleton().remove(mOverlayTexture->getName()); + } void GlobalMap::render (Loading::Listener* loadingListener) { @@ -168,9 +172,8 @@ namespace MWRender tex->load(); - mOverlayTexture = Ogre::TextureManager::getSingleton().createManual("GlobalMapOverlay", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_A8B8G8R8, Ogre::TU_DYNAMIC_WRITE_ONLY); + Ogre::TEX_TYPE_2D, mWidth, mHeight, 0, Ogre::PF_A8B8G8R8, Ogre::TU_DYNAMIC, this); clear(); @@ -194,9 +197,11 @@ namespace MWRender void GlobalMap::exploreCell(int cellX, int cellY) { - float originX = (cellX - mMinX) * 24; + const int size = 24; + + float originX = (cellX - mMinX) * size; // NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is - float originY = mHeight - (cellY+1 - mMinY) * 24; + float originY = mHeight - (cellY+1 - mMinY) * size; if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY) return; @@ -204,31 +209,47 @@ namespace MWRender Ogre::TexturePtr localMapTexture = Ogre::TextureManager::getSingleton().getByName("Cell_" + boost::lexical_cast(cellX) + "_" + boost::lexical_cast(cellY)); - // mipmap version - can't get ogre to generate automips.. - /*if (!localMapTexture.isNull()) - { - assert(localMapTexture->getBuffer(0, 4)->getWidth() == 64); // 1024 / 2^4 - - mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(0, 4), Ogre::Image::Box(0,0,64, 64), - Ogre::Image::Box(originX,originY,originX+24,originY+24)); - }*/ - if (!localMapTexture.isNull()) { + mOverlayTexture->load(); mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,512,512), - Ogre::Image::Box(originX,originY,originX+24,originY+24)); + Ogre::Image::Box(originX,originY,originX+size,originY+size)); + + Ogre::Image backup; + std::vector data; + data.resize(size*size*4, 0); + backup.loadDynamicImage(&data[0], size, size, Ogre::PF_A8B8G8R8); + + localMapTexture->getBuffer()->blitToMemory(Ogre::Image::Box(0,0,512,512), backup.getPixelBox()); + + for (int x=0; x buffer; - // initialize to (0,0,0,0) - buffer.resize(mWidth * mHeight, 0); + Ogre::uchar* buffer = OGRE_ALLOC_T(Ogre::uchar, mWidth * mHeight * 4, Ogre::MEMCATEGORY_GENERAL); + memset(buffer, 0, mWidth * mHeight * 4); - Ogre::PixelBox pb(mWidth, mHeight, 1, Ogre::PF_A8B8G8R8, &buffer[0]); + mOverlayImage.loadDynamicImage(&buffer[0], mWidth, mHeight, 1, Ogre::PF_A8B8G8R8, true); // pass ownership of buffer to image - mOverlayTexture->getBuffer()->blitFromMemory(pb); + mOverlayTexture->load(); + } + + void GlobalMap::loadResource(Ogre::Resource *resource) + { + Ogre::Texture* tex = dynamic_cast(resource); + Ogre::ConstImagePtrList list; + list.push_back(&mOverlayImage); + tex->_loadImages(list); } void GlobalMap::write(ESM::GlobalMap& map) @@ -238,9 +259,7 @@ namespace MWRender map.mBounds.mMinY = mMinY; map.mBounds.mMaxY = mMaxY; - Ogre::Image image; - mOverlayTexture->convertToImage(image); - Ogre::DataStreamPtr encoded = image.encode("png"); + Ogre::DataStreamPtr encoded = mOverlayImage.encode("png"); map.mImageData.resize(encoded->size()); encoded->read(&map.mImageData[0], encoded->size()); } @@ -303,8 +322,15 @@ namespace MWRender image.getHeight(), 0, Ogre::PF_A8B8G8R8); tex->loadImage(image); + mOverlayTexture->load(); mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox); + if (srcBox.left == destBox.left && srcBox.right == destBox.right + && srcBox.top == destBox.top && srcBox.bottom == destBox.bottom) + mOverlayImage = image; + else + mOverlayTexture->convertToImage(mOverlayImage); + Ogre::TextureManager::getSingleton().remove("@temp"); } } diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index 6075d042e..050da8e7f 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -18,10 +18,11 @@ namespace ESM namespace MWRender { - class GlobalMap + class GlobalMap : public Ogre::ManualResourceLoader { public: GlobalMap(const std::string& cacheDir); + ~GlobalMap(); void render(Loading::Listener* loadingListener); @@ -36,6 +37,8 @@ namespace MWRender void exploreCell (int cellX, int cellY); + virtual void loadResource(Ogre::Resource* resource); + /// Clears the overlay void clear(); @@ -48,6 +51,7 @@ namespace MWRender std::vector< std::pair > mExploredCells; Ogre::TexturePtr mOverlayTexture; + Ogre::Image mOverlayImage; // Backup in system memory int mWidth; int mHeight; diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 50dec8950..ace105b2d 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -324,6 +324,7 @@ void LocalMap::createFogOfWar(const std::string& texturePrefix) buffer.resize(sFogOfWarResolution*sFogOfWarResolution, 0xFF000000); // upload to the texture + tex->load(); memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4); tex->getBuffer()->unlock(); From c62d53ae8491081db8eec459cc53e880290dde06 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Aug 2014 19:09:33 +0200 Subject: [PATCH 09/16] Remove no longer needed comments about coordinate system --- apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwrender/globalmap.hpp | 2 -- apps/openmw/mwrender/localmap.hpp | 4 +--- apps/openmw/mwworld/worldimp.hpp | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index a3a127d63..bf64ee44e 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -143,7 +143,7 @@ namespace MWBase virtual bool isCellQuasiExterior() const = 0; virtual Ogre::Vector2 getNorthVector (MWWorld::CellStore* cell) = 0; - ///< get north vector (OGRE coordinates) for given interior cell + ///< get north vector for given interior cell virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector& out) = 0; ///< get a list of teleport door markers for a given cell, to be displayed on the local map diff --git a/apps/openmw/mwrender/globalmap.hpp b/apps/openmw/mwrender/globalmap.hpp index 050da8e7f..66fe89f73 100644 --- a/apps/openmw/mwrender/globalmap.hpp +++ b/apps/openmw/mwrender/globalmap.hpp @@ -30,8 +30,6 @@ namespace MWRender int getHeight() { return mHeight; } void worldPosToImageSpace(float x, float z, float& imageX, float& imageY); - ///< @param x x ogre coords - /// @param z z ogre coords void cellTopLeftCornerToImageSpace(int x, int y, float& imageX, float& imageY); diff --git a/apps/openmw/mwrender/localmap.hpp b/apps/openmw/mwrender/localmap.hpp index 1572800e5..aed7e0637 100644 --- a/apps/openmw/mwrender/localmap.hpp +++ b/apps/openmw/mwrender/localmap.hpp @@ -61,8 +61,6 @@ namespace MWRender * Set the position & direction of the player. * @remarks This is used to draw a "fog of war" effect * to hide areas on the map the player has not discovered yet. - * @param position (OGRE coordinates) - * @param camera orientation (OGRE coordinates) */ void updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation); @@ -74,7 +72,7 @@ namespace MWRender /** * Get the interior map texture index and normalized position - * on this texture, given a world position (in ogre coordinates) + * on this texture, given a world position */ void getInteriorMapPosition (Ogre::Vector2 pos, float& nX, float& nY, int& x, int& y); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index fad3dfd97..ad166c91a 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -205,7 +205,7 @@ namespace MWWorld virtual bool isCellQuasiExterior() const; virtual Ogre::Vector2 getNorthVector (CellStore* cell); - ///< get north vector (OGRE coordinates) for given interior cell + ///< get north vector for given interior cell virtual void getDoorMarkers (MWWorld::CellStore* cell, std::vector& out); ///< get a list of teleport door markers for a given cell, to be displayed on the local map From 77a4e38c49297f11b04fdf70b58008d80b5d1354 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Aug 2014 19:18:30 +0200 Subject: [PATCH 10/16] Remove -Wno-ignored-qualifiers and fix caused warnings --- CMakeLists.txt | 3 --- components/esm/esmreader.hpp | 2 +- components/settings/settings.cpp | 8 ++++---- components/settings/settings.hpp | 8 ++++---- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d380aea0..368fe5364 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -362,9 +362,6 @@ endif() if (CMAKE_COMPILER_IS_GNUCC) SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}") - # Silence warnings in OGRE headers. Remove once OGRE got fixed! - SET(CMAKE_CXX_FLAGS "-Wno-ignored-qualifiers ${CMAKE_CXX_FLAGS}") - execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) diff --git a/components/esm/esmreader.hpp b/components/esm/esmreader.hpp index 6b0bb9a27..730bdd8c7 100644 --- a/components/esm/esmreader.hpp +++ b/components/esm/esmreader.hpp @@ -83,7 +83,7 @@ public: // indirectly to the load() method. int mIdx; void setIndex(const int index) {mIdx = index; mCtx.index = index;} - const int getIndex() {return mIdx;} + int getIndex() {return mIdx;} void setGlobalReaderList(std::vector *list) {mGlobalReaderList = list;} std::vector *getGlobalReaderList() {return mGlobalReaderList;} diff --git a/components/settings/settings.cpp b/components/settings/settings.cpp index 0def0afdb..5fc2ca3c1 100644 --- a/components/settings/settings.cpp +++ b/components/settings/settings.cpp @@ -79,7 +79,7 @@ void Manager::saveUser(const std::string& file) fout.close(); } -const std::string Manager::getString (const std::string& setting, const std::string& category) +std::string Manager::getString (const std::string& setting, const std::string& category) { if (mNewSettings.find(std::make_pair(category, setting)) != mNewSettings.end()) return mNewSettings[std::make_pair(category, setting)]; @@ -92,17 +92,17 @@ const std::string Manager::getString (const std::string& setting, const std::str return val; } -const float Manager::getFloat (const std::string& setting, const std::string& category) +float Manager::getFloat (const std::string& setting, const std::string& category) { return Ogre::StringConverter::parseReal( getString(setting, category) ); } -const int Manager::getInt (const std::string& setting, const std::string& category) +int Manager::getInt (const std::string& setting, const std::string& category) { return Ogre::StringConverter::parseInt( getString(setting, category) ); } -const bool Manager::getBool (const std::string& setting, const std::string& category) +bool Manager::getBool (const std::string& setting, const std::string& category) { return Ogre::StringConverter::parseBool( getString(setting, category) ); } diff --git a/components/settings/settings.hpp b/components/settings/settings.hpp index b7c7d59a9..03b0b517c 100644 --- a/components/settings/settings.hpp +++ b/components/settings/settings.hpp @@ -36,10 +36,10 @@ namespace Settings static const CategorySettingVector apply(); ///< returns the list of changed settings and then clears it - static const int getInt (const std::string& setting, const std::string& category); - static const float getFloat (const std::string& setting, const std::string& category); - static const std::string getString (const std::string& setting, const std::string& category); - static const bool getBool (const std::string& setting, const std::string& category); + static int getInt (const std::string& setting, const std::string& category); + static float getFloat (const std::string& setting, const std::string& category); + static std::string getString (const std::string& setting, const std::string& category); + static bool getBool (const std::string& setting, const std::string& category); static void setInt (const std::string& setting, const std::string& category, const int value); static void setFloat (const std::string& setting, const std::string& category, const float value); From 7f807f31d01ae527175eb3e964026b3961600a1e Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 14 Aug 2014 19:49:03 +0200 Subject: [PATCH 11/16] Remove comment Doing some testing with extended journals, doesn't appear to be a performance issue. --- apps/openmw/mwgui/journalwindow.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 3e2006e57..057e12414 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -201,10 +201,6 @@ namespace setBookMode (); - /// \todo Wiping the whole book layout each time the journal is opened is probably too costly for a large journal (eg 300+ pages). - /// There should be a way to keep the existing layout and append new entries to the end of it. - /// However, that still leaves the problem of having to add links to previously unknown, but now known topics, so - /// we maybe need to find another way to speed things up. Book journalBook; if (mModel->isEmpty ()) journalBook = createEmptyJournalBook (); From 084cc857d4a8af8e8de1983a5ab0a3cf232c020a Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 15 Aug 2014 01:13:38 +0200 Subject: [PATCH 12/16] Update magic effects when changing equipment (Fixes #1646) --- apps/openmw/mwgui/inventorywindow.cpp | 3 +++ apps/openmw/mwmechanics/actors.cpp | 6 ++++++ apps/openmw/mwmechanics/actors.hpp | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index e2048a34b..93c598d28 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -543,6 +543,9 @@ namespace MWGui if (MWBase::Environment::get().getWindowManager()->getSpellWindow()) MWBase::Environment::get().getWindowManager()->getSpellWindow()->updateSpells(); + MWBase::Environment::get().getMechanicsManager()->updateMagicEffects( + MWBase::Environment::get().getWorld()->getPlayerPtr()); + mPreviewDirty = true; } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index dfec007d7..be3a90e0c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1458,4 +1458,10 @@ namespace MWMechanics mActors.clear(); mDeathCount.clear(); } + + void Actors::updateMagicEffects(const MWWorld::Ptr &ptr) + { + adjustMagicEffects(ptr); + calculateCreatureStatModifiers(ptr, 0.f); + } } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 4b5d77a7f..f893f7596 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -56,7 +56,7 @@ namespace MWMechanics /// Update magic effects for an actor. Usually done automatically once per frame, but if we're currently /// paused we may want to do it manually (after equipping permanent enchantment) - void updateMagicEffects (const MWWorld::Ptr& ptr) { adjustMagicEffects(ptr); } + void updateMagicEffects (const MWWorld::Ptr& ptr); void addActor (const MWWorld::Ptr& ptr, bool updateImmediately=false); ///< Register an actor for stats management From ddba9e58542748c49fe5ef719d06eb222d5acb1c Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 15 Aug 2014 18:42:33 +0200 Subject: [PATCH 13/16] Improve performance of ItemView resize (reposition widgets instead of recreate) --- apps/openmw/mwgui/itemview.cpp | 66 +++++++++++++++++++++------------- apps/openmw/mwgui/itemview.hpp | 2 ++ 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/apps/openmw/mwgui/itemview.cpp b/apps/openmw/mwgui/itemview.cpp index c4c6c6545..bb838e340 100644 --- a/apps/openmw/mwgui/itemview.cpp +++ b/apps/openmw/mwgui/itemview.cpp @@ -56,6 +56,43 @@ void ItemView::initialiseOverride() mScrollView->setCanvasAlign(MyGUI::Align::Left | MyGUI::Align::Top); } +void ItemView::layoutWidgets() +{ + if (!mScrollView->getChildCount()) + return; + + int x = 0; + int y = 0; + int maxHeight = mScrollView->getSize().height - 58; + + MyGUI::Widget* dragArea = mScrollView->getChildAt(0); + + for (unsigned int i=0; igetChildCount(); ++i) + { + MyGUI::Widget* w = dragArea->getChildAt(i); + + w->setPosition(x, y); + + y += 42; + if (y > maxHeight) + { + x += 42; + y = 0; + } + } + x += 42; + + MyGUI::IntSize size = MyGUI::IntSize(std::max(mScrollView->getSize().width, x), mScrollView->getSize().height); + + // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden + mScrollView->setVisibleVScroll(false); + mScrollView->setVisibleHScroll(false); + mScrollView->setCanvasSize(size); + mScrollView->setVisibleVScroll(true); + mScrollView->setVisibleHScroll(true); + dragArea->setSize(size); +} + void ItemView::update() { while (mScrollView->getChildCount()) @@ -64,10 +101,6 @@ void ItemView::update() if (!mModel) return; - int x = 0; - int y = 0; - int maxHeight = mScrollView->getSize().height - 58; - mModel->update(); MyGUI::Widget* dragArea = mScrollView->createWidget("",0,0,mScrollView->getWidth(),mScrollView->getHeight(), @@ -80,9 +113,8 @@ void ItemView::update() { const ItemStack& item = mModel->getItem(i); - /// \todo performance improvement: don't create/destroy all the widgets everytime the container window changes size, only reposition them ItemWidget* itemWidget = dragArea->createWidget("MW_ItemIcon", - MyGUI::IntCoord(x, y, 42, 42), MyGUI::Align::Default); + MyGUI::IntCoord(0, 0, 42, 42), MyGUI::Align::Default); itemWidget->setUserString("ToolTipType", "ItemModelIndex"); itemWidget->setUserData(std::make_pair(i, mModel)); ItemWidget::ItemState state = ItemWidget::None; @@ -104,25 +136,9 @@ void ItemView::update() text->setTextShadow(true); text->setTextShadowColour(MyGUI::Colour(0,0,0)); text->setCaption(getCountString(item.mCount)); - - y += 42; - if (y > maxHeight) - { - x += 42; - y = 0; - } - } - x += 42; - MyGUI::IntSize size = MyGUI::IntSize(std::max(mScrollView->getSize().width, x), mScrollView->getSize().height); - // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden - mScrollView->setVisibleVScroll(false); - mScrollView->setVisibleHScroll(false); - mScrollView->setCanvasSize(size); - mScrollView->setVisibleVScroll(true); - mScrollView->setVisibleHScroll(true); - dragArea->setSize(size); + layoutWidgets(); } void ItemView::onSelectedItem(MyGUI::Widget *sender) @@ -149,7 +165,7 @@ void ItemView::setSize(const MyGUI::IntSize &_value) bool changed = (_value.width != getWidth() || _value.height != getHeight()); Base::setSize(_value); if (changed) - update(); + layoutWidgets(); } void ItemView::setSize(int _width, int _height) @@ -162,7 +178,7 @@ void ItemView::setCoord(const MyGUI::IntCoord &_value) bool changed = (_value.width != getWidth() || _value.height != getHeight()); Base::setCoord(_value); if (changed) - update(); + layoutWidgets(); } void ItemView::setCoord(int _left, int _top, int _width, int _height) diff --git a/apps/openmw/mwgui/itemview.hpp b/apps/openmw/mwgui/itemview.hpp index 74bc66ea0..68704d219 100644 --- a/apps/openmw/mwgui/itemview.hpp +++ b/apps/openmw/mwgui/itemview.hpp @@ -35,6 +35,8 @@ namespace MWGui private: virtual void initialiseOverride(); + void layoutWidgets(); + virtual void setSize(const MyGUI::IntSize& _value); virtual void setCoord(const MyGUI::IntCoord& _value); void setSize(int _width, int _height); From 6c6b3bd8903a6504e506aa87cedcdb99e171ccfa Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 15 Aug 2014 22:46:48 +0200 Subject: [PATCH 14/16] Remove extra setVisibilityFlags on SkelBase SkelBase is already contained in mEntities. --- components/nifogre/ogrenifloader.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index be362e6ac..495dd1f16 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -118,9 +118,6 @@ ObjectScene::~ObjectScene() void ObjectScene::setVisibilityFlags (unsigned int flags) { - if (mSkelBase) - mSkelBase->setVisibilityFlags (flags); - for (std::vector::iterator iter (mEntities.begin()); iter!=mEntities.end(); ++iter) (*iter)->setVisibilityFlags (flags); From 7432771ac7373069da5e8e26b3ab1bb6b0748971 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 16 Aug 2014 00:51:02 +0200 Subject: [PATCH 15/16] For non-active torches set the particle system speed factor to zero instead of destroying it (Fixes #1811) --- apps/openmw/mwrender/animation.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 7a5a45832..0547051a7 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1430,9 +1430,12 @@ void ObjectAnimation::removeParticles() { for (unsigned int i=0; imParticles.size(); ++i) { - mObjectRoot->mSceneMgr->destroyParticleSystem(mObjectRoot->mParticles[i]); + // Don't destroyParticleSystem, the ParticleSystemController is still holding a pointer to it. + // Don't setVisible, this could conflict with a VisController. + // The following will remove all spawned particles, then set the speed factor to zero so that no new ones will be spawned. + mObjectRoot->mParticles[i]->setSpeedFactor(0.f); + mObjectRoot->mParticles[i]->clear(); } - mObjectRoot->mParticles.clear(); } From c4ae07f48aed4b68f3c3fb07d90e15a04d17845f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 16 Aug 2014 02:01:39 +0200 Subject: [PATCH 16/16] Remove partially broken sound pausing in main menu (Fixes #1707) --- apps/openmw/mwgui/dialogue.cpp | 1 - apps/openmw/mwgui/mainmenu.cpp | 1 - apps/openmw/mwinput/inputmanagerimp.cpp | 2 -- 3 files changed, 4 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 23098bf42..94b2c4b0e 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -276,7 +276,6 @@ namespace MWGui { // in choice, not allowed to escape, but give access to main menu to allow loading other saves MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); - MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx); } else MWBase::Environment::get().getDialogueManager()->goodbyeSelected(); diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index ca7e877cc..7c60353d2 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -92,7 +92,6 @@ namespace MWGui MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f); if (name == "return") { - MWBase::Environment::get().getSoundManager ()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu); } else if (name == "options") diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index f60c89681..c07b4760d 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -689,12 +689,10 @@ namespace MWInput if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) //No open GUIs, open up the MainMenu { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); - MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx); } else //Close current GUI { MWBase::Environment::get().getWindowManager()->exitCurrentGuiMode(); - MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); } }