From 6ff14e19d18fe19ff474e2de1f21d05391bde51d Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 14 Jan 2024 16:41:55 +0100 Subject: [PATCH] Make cell models preloading a const operation --- apps/openmw/mwclass/creature.cpp | 11 ++-- apps/openmw/mwclass/creature.hpp | 4 +- apps/openmw/mwclass/creaturelevlist.cpp | 19 ------ apps/openmw/mwclass/creaturelevlist.hpp | 4 -- apps/openmw/mwclass/npc.cpp | 79 +++++++++++++------------ apps/openmw/mwclass/npc.hpp | 4 +- apps/openmw/mwworld/cellpreloader.cpp | 13 +--- apps/openmw/mwworld/cellstore.hpp | 12 ++-- apps/openmw/mwworld/class.cpp | 4 +- apps/openmw/mwworld/class.hpp | 4 +- 10 files changed, 63 insertions(+), 91 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index bb9c1bc277..fbe232093a 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -183,16 +183,17 @@ namespace MWClass return getClassModel(ptr); } - void Creature::getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const + void Creature::getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector& models) const { std::string model = getModel(ptr); if (!model.empty()) models.push_back(model); - // FIXME: use const version of InventoryStore functions once they are available - if (hasInventoryStore(ptr)) + const MWWorld::CustomData* customData = ptr.getRefData().getCustomData(); + if (customData && hasInventoryStore(ptr)) { - const MWWorld::InventoryStore& invStore = getInventoryStore(ptr); + const auto& invStore + = static_cast(*customData->asCreatureCustomData().mContainerStore); for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) { MWWorld::ConstContainerStoreIterator equipped = invStore.getSlot(slot); @@ -513,7 +514,7 @@ namespace MWClass throw std::runtime_error("this creature has no inventory store"); } - bool Creature::hasInventoryStore(const MWWorld::Ptr& ptr) const + bool Creature::hasInventoryStore(const MWWorld::ConstPtr& ptr) const { return isFlagBitSet(ptr, ESM::Creature::Weapon); } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index b407852242..38b7bb0ec1 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -79,7 +79,7 @@ namespace MWClass MWWorld::InventoryStore& getInventoryStore(const MWWorld::Ptr& ptr) const override; ///< Return inventory store - bool hasInventoryStore(const MWWorld::Ptr& ptr) const override; + bool hasInventoryStore(const MWWorld::ConstPtr& ptr) const override; ESM::RefId getScript(const MWWorld::ConstPtr& ptr) const override; ///< Return name of the script attached to ptr @@ -107,7 +107,7 @@ namespace MWClass std::string getModel(const MWWorld::ConstPtr& ptr) const override; - void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const override; + void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector& models) const override; ///< Get a list of models to preload that this object may use (directly or indirectly). default implementation: ///< list getModel(). diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index fbae54737c..f16601531d 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -99,25 +99,6 @@ namespace MWClass customData.mSpawn = true; } - void CreatureLevList::getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const - { - // disable for now, too many false positives - /* - const MWWorld::LiveCellRef *ref = ptr.get(); - for (std::vector::const_iterator it = ref->mBase->mList.begin(); it != - ref->mBase->mList.end(); ++it) - { - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - if (it->mLevel > player.getClass().getCreatureStats(player).getLevel()) - continue; - - const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore(); - MWWorld::ManualRef ref(store, it->mId); - ref.getPtr().getClass().getModelsToPreload(ref.getPtr(), models); - } - */ - } - void CreatureLevList::insertObjectRendering( const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const { diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index d689d1770e..ded8f77de5 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -20,10 +20,6 @@ namespace MWClass bool hasToolTip(const MWWorld::ConstPtr& ptr) const override; ///< @return true if this object has a tooltip when focused (default implementation: true) - void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const override; - ///< Get a list of models to preload that this object may use (directly or indirectly). default implementation: - ///< list getModel(). - void insertObjectRendering(const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const override; ///< Add reference into a cell for rendering diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 4f295f7b35..7ff26fbdb6 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -436,10 +436,11 @@ namespace MWClass return model; } - void Npc::getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const + void Npc::getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector& models) const { const MWWorld::LiveCellRef* npc = ptr.get(); - const ESM::Race* race = MWBase::Environment::get().getESMStore()->get().search(npc->mBase->mRace); + const auto& esmStore = MWBase::Environment::get().getESMStore(); + const ESM::Race* race = esmStore->get().search(npc->mBase->mRace); if (race && race->mData.mFlags & ESM::Race::Beast) models.push_back(Settings::models().mBaseanimkna); @@ -453,56 +454,57 @@ namespace MWClass if (!npc->mBase->mHead.empty()) { - const ESM::BodyPart* head - = MWBase::Environment::get().getESMStore()->get().search(npc->mBase->mHead); + const ESM::BodyPart* head = esmStore->get().search(npc->mBase->mHead); if (head) models.push_back(Misc::ResourceHelpers::correctMeshPath(head->mModel)); } if (!npc->mBase->mHair.empty()) { - const ESM::BodyPart* hair - = MWBase::Environment::get().getESMStore()->get().search(npc->mBase->mHair); + const ESM::BodyPart* hair = esmStore->get().search(npc->mBase->mHair); if (hair) models.push_back(Misc::ResourceHelpers::correctMeshPath(hair->mModel)); } bool female = (npc->mBase->mFlags & ESM::NPC::Female); - // FIXME: use const version of InventoryStore functions once they are available - // preload equipped items - const MWWorld::InventoryStore& invStore = getInventoryStore(ptr); - for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) + const MWWorld::CustomData* customData = ptr.getRefData().getCustomData(); + if (customData) { - MWWorld::ConstContainerStoreIterator equipped = invStore.getSlot(slot); - if (equipped != invStore.end()) + const MWWorld::InventoryStore& invStore = customData->asNpcCustomData().mInventoryStore; + for (int slot = 0; slot < MWWorld::InventoryStore::Slots; ++slot) { - std::vector parts; - if (equipped->getType() == ESM::Clothing::sRecordId) + MWWorld::ConstContainerStoreIterator equipped = invStore.getSlot(slot); + if (equipped != invStore.end()) { - const ESM::Clothing* clothes = equipped->get()->mBase; - parts = clothes->mParts.mParts; - } - else if (equipped->getType() == ESM::Armor::sRecordId) - { - const ESM::Armor* armor = equipped->get()->mBase; - parts = armor->mParts.mParts; - } - else - { - std::string model = equipped->getClass().getModel(*equipped); - if (!model.empty()) - models.push_back(model); - } + const auto addParts = [&](const std::vector& parts) { + for (const ESM::PartReference& partRef : parts) + { + const ESM::RefId& partname + = (female && !partRef.mFemale.empty()) || (!female && partRef.mMale.empty()) + ? partRef.mFemale + : partRef.mMale; - for (std::vector::const_iterator it = parts.begin(); it != parts.end(); ++it) - { - const ESM::RefId& partname - = (female && !it->mFemale.empty()) || (!female && it->mMale.empty()) ? it->mFemale : it->mMale; - - const ESM::BodyPart* part - = MWBase::Environment::get().getESMStore()->get().search(partname); - if (part && !part->mModel.empty()) - models.push_back(Misc::ResourceHelpers::correctMeshPath(part->mModel)); + const ESM::BodyPart* part = esmStore->get().search(partname); + if (part && !part->mModel.empty()) + models.push_back(Misc::ResourceHelpers::correctMeshPath(part->mModel)); + } + }; + if (equipped->getType() == ESM::Clothing::sRecordId) + { + const ESM::Clothing* clothes = equipped->get()->mBase; + addParts(clothes->mParts.mParts); + } + else if (equipped->getType() == ESM::Armor::sRecordId) + { + const ESM::Armor* armor = equipped->get()->mBase; + addParts(armor->mParts.mParts); + } + else + { + std::string model = equipped->getClass().getModel(*equipped); + if (!model.empty()) + models.push_back(model); + } } } } @@ -512,9 +514,8 @@ namespace MWClass { const std::vector& parts = MWRender::NpcAnimation::getBodyParts(race->mId, female, false, false); - for (std::vector::const_iterator it = parts.begin(); it != parts.end(); ++it) + for (const ESM::BodyPart* part : parts) { - const ESM::BodyPart* part = *it; if (part && !part->mModel.empty()) models.push_back(Misc::ResourceHelpers::correctMeshPath(part->mModel)); } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index ca0d0ac95d..95245bb994 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -74,7 +74,7 @@ namespace MWClass MWWorld::InventoryStore& getInventoryStore(const MWWorld::Ptr& ptr) const override; ///< Return inventory store - bool hasInventoryStore(const MWWorld::Ptr& ptr) const override { return true; } + bool hasInventoryStore(const MWWorld::ConstPtr& ptr) const override { return true; } bool evaluateHit(const MWWorld::Ptr& ptr, MWWorld::Ptr& victim, osg::Vec3f& hitPosition) const override; @@ -85,7 +85,7 @@ namespace MWClass const MWWorld::Ptr& attacker, const osg::Vec3f& hitPosition, bool successful, const MWMechanics::DamageSourceType sourceType) const override; - void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const override; + void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector& models) const override; ///< Get a list of models to preload that this object may use (directly or indirectly). default implementation: ///< list getModel(). diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index 7da5e8f848..fe14856364 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -52,20 +52,13 @@ namespace MWWorld struct ListModelsVisitor { - ListModelsVisitor(std::vector& out) - : mOut(out) - { - } - - virtual bool operator()(const MWWorld::Ptr& ptr) + bool operator()(const MWWorld::ConstPtr& ptr) { ptr.getClass().getModelsToPreload(ptr, mOut); return true; } - virtual ~ListModelsVisitor() = default; - std::vector& mOut; }; @@ -90,8 +83,8 @@ namespace MWWorld { mTerrainView = mTerrain->createView(); - ListModelsVisitor visitor(mMeshes); - cell->forEach(visitor); + ListModelsVisitor visitor{ mMeshes }; + cell->forEachConst(visitor); } void abort() override { mAbort = true; } diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index 0c6527ce22..a8f296045a 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -224,12 +224,12 @@ namespace MWWorld mHasState = true; - for (unsigned int i = 0; i < mMergedRefs.size(); ++i) + for (LiveCellRefBase* mergedRef : mMergedRefs) { - if (!isAccessible(mMergedRefs[i]->mData, mMergedRefs[i]->mRef)) + if (!isAccessible(mergedRef->mData, mergedRef->mRef)) continue; - if (!visitor(MWWorld::Ptr(mMergedRefs[i], this))) + if (!visitor(MWWorld::Ptr(mergedRef, this))) return false; } return true; @@ -249,12 +249,12 @@ namespace MWWorld if (mMergedRefsNeedsUpdate) updateMergedRefs(); - for (unsigned int i = 0; i < mMergedRefs.size(); ++i) + for (const LiveCellRefBase* mergedRef : mMergedRefs) { - if (!isAccessible(mMergedRefs[i]->mData, mMergedRefs[i]->mRef)) + if (!isAccessible(mergedRef->mData, mergedRef->mRef)) continue; - if (!visitor(MWWorld::ConstPtr(mMergedRefs[i], this))) + if (!visitor(MWWorld::ConstPtr(mergedRef, this))) return false; } return true; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index d5062d6add..c8ba337cee 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -149,7 +149,7 @@ namespace MWWorld throw std::runtime_error("class does not have an inventory store"); } - bool Class::hasInventoryStore(const Ptr& ptr) const + bool Class::hasInventoryStore(const ConstPtr& ptr) const { return false; } @@ -320,7 +320,7 @@ namespace MWWorld return false; } - void Class::getModelsToPreload(const Ptr& ptr, std::vector& models) const + void Class::getModelsToPreload(const ConstPtr& ptr, std::vector& models) const { std::string model = getModel(ptr); if (!model.empty()) diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 87e70b3198..694a40cb32 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -170,7 +170,7 @@ namespace MWWorld ///< Return inventory store or throw an exception, if class does not have a /// inventory store (default implementation: throw an exception) - virtual bool hasInventoryStore(const Ptr& ptr) const; + virtual bool hasInventoryStore(const ConstPtr& ptr) const; ///< Does this object have an inventory store, i.e. equipment slots? (default implementation: false) virtual bool canLock(const ConstPtr& ptr) const; @@ -284,7 +284,7 @@ namespace MWWorld virtual bool useAnim() const; ///< Whether or not to use animated variant of model (default false) - virtual void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const; + virtual void getModelsToPreload(const MWWorld::ConstPtr& ptr, std::vector& models) const; ///< Get a list of models to preload that this object may use (directly or indirectly). default implementation: ///< list getModel().