From 2ddc77138a9c1a9620e3eb97e8e8fe2f7db9e1cd Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 18 Sep 2024 23:52:20 +0200 Subject: [PATCH 01/13] Use normalized path in ESM4 reader --- components/esm4/reader.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index 2d9a929bb2..505922601d 100644 --- a/components/esm4/reader.cpp +++ b/components/esm4/reader.cpp @@ -320,16 +320,18 @@ namespace ESM4 std::filesystem::path path = strings / (prefix + language + suffix); if (mVFS != nullptr) { - std::string vfsPath = Files::pathToUnicodeString(path); - if (!mVFS->exists(vfsPath)) + VFS::Path::Normalized vfsPath(Files::pathToUnicodeString(path)); + Files::IStreamPtr stream = mVFS->find(vfsPath); + + if (stream == nullptr) { path = strings / (prefix + altLanguage + suffix); - vfsPath = Files::pathToUnicodeString(path); + vfsPath = VFS::Path::Normalized(Files::pathToUnicodeString(path)); + stream = mVFS->find(vfsPath); } - if (mVFS->exists(vfsPath)) + if (stream != nullptr) { - const Files::IStreamPtr stream = mVFS->get(vfsPath); buildLStringIndex(stringType, *stream); return; } From 597d1853eebef71fd410111de63ba81ebce22661 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 18 Sep 2024 23:52:44 +0200 Subject: [PATCH 02/13] Use normalized path in ESM LuaScripts --- components/esm/luascripts.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esm/luascripts.cpp b/components/esm/luascripts.cpp index 71e2ce6dc1..81cc867aff 100644 --- a/components/esm/luascripts.cpp +++ b/components/esm/luascripts.cpp @@ -56,7 +56,7 @@ void ESM::LuaScriptsCfg::load(ESMReader& esm) { mScripts.emplace_back(); ESM::LuaScriptCfg& script = mScripts.back(); - script.mScriptPath = esm.getHString(); + script.mScriptPath = VFS::Path::Normalized(esm.getHString()); esm.getSubNameIs("LUAF"); esm.getSubHeader(); @@ -161,7 +161,7 @@ void ESM::LuaScripts::load(ESMReader& esm) { while (esm.isNextSub("LUAS")) { - std::string name = esm.getHString(); + VFS::Path::Normalized name(esm.getHString()); std::string data = loadLuaBinaryData(esm); std::vector timers; while (esm.isNextSub("LUAT")) From 85edc49f2f843b613760d4e836de769f5a671579 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 18 Sep 2024 23:53:04 +0200 Subject: [PATCH 03/13] Remove unused argument --- components/misc/resourcehelpers.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/misc/resourcehelpers.cpp b/components/misc/resourcehelpers.cpp index 5ed0bcc972..1728e51c7a 100644 --- a/components/misc/resourcehelpers.cpp +++ b/components/misc/resourcehelpers.cpp @@ -228,7 +228,7 @@ bool Misc::ResourceHelpers::isHiddenMarker(const ESM::RefId& id) namespace { - std::string getLODMeshNameImpl(std::string resPath, const VFS::Manager* vfs, std::string_view pattern) + std::string getLODMeshNameImpl(std::string resPath, std::string_view pattern) { if (auto w = Misc::findExtension(resPath); w != std::string::npos) resPath.insert(w, pattern); @@ -237,7 +237,7 @@ namespace std::string getBestLODMeshName(std::string const& resPath, const VFS::Manager* vfs, std::string_view pattern) { - if (const auto& result = getLODMeshNameImpl(resPath, vfs, pattern); vfs->exists(result)) + if (std::string result = getLODMeshNameImpl(resPath, pattern); vfs->exists(result)) return result; return resPath; } From a78f5182e48443054ab54eff27345add1cf85c77 Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 18 Sep 2024 23:53:17 +0200 Subject: [PATCH 04/13] Replace toNormalized by Normalized fname type cannot be changed because it's part of mygui library interface. --- components/myguiplatform/myguitexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/myguiplatform/myguitexture.cpp b/components/myguiplatform/myguitexture.cpp index fe2b700049..9d865e1296 100644 --- a/components/myguiplatform/myguitexture.cpp +++ b/components/myguiplatform/myguitexture.cpp @@ -95,7 +95,7 @@ namespace osgMyGUI if (!mImageManager) throw std::runtime_error("No imagemanager set"); - osg::ref_ptr image(mImageManager->getImage(VFS::Path::toNormalized(fname))); + osg::ref_ptr image(mImageManager->getImage(VFS::Path::Normalized(fname))); mTexture = new osg::Texture2D(image); mTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); mTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); From f1533c215dce038592bfefeda549b190d989f99a Mon Sep 17 00:00:00 2001 From: elsid Date: Wed, 18 Sep 2024 23:56:03 +0200 Subject: [PATCH 05/13] Use normalized path in ActorAnimation::attach --- apps/openmw/mwrender/actoranimation.cpp | 5 ++--- apps/openmw/mwrender/actoranimation.hpp | 4 +++- apps/openmw/mwrender/creatureanimation.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/actoranimation.cpp b/apps/openmw/mwrender/actoranimation.cpp index 35ff81a9ca..df712b43b0 100644 --- a/apps/openmw/mwrender/actoranimation.cpp +++ b/apps/openmw/mwrender/actoranimation.cpp @@ -88,10 +88,9 @@ namespace MWRender } osg::ref_ptr ActorAnimation::attach( - const std::string& model, std::string_view bonename, std::string_view bonefilter, bool isLight) + VFS::Path::NormalizedView model, std::string_view bonename, std::string_view bonefilter, bool isLight) { - osg::ref_ptr templateNode - = mResourceSystem->getSceneManager()->getTemplate(VFS::Path::toNormalized(model)); + osg::ref_ptr templateNode = mResourceSystem->getSceneManager()->getTemplate(model); const NodeMap& nodeMap = getNodeMap(); auto found = nodeMap.find(bonename); diff --git a/apps/openmw/mwrender/actoranimation.hpp b/apps/openmw/mwrender/actoranimation.hpp index b6586d4eab..5a28c41b6c 100644 --- a/apps/openmw/mwrender/actoranimation.hpp +++ b/apps/openmw/mwrender/actoranimation.hpp @@ -5,6 +5,8 @@ #include +#include + #include "../mwworld/containerstore.hpp" #include "animation.hpp" @@ -59,7 +61,7 @@ namespace MWRender return attachMesh(model, bonename, false, &stubColor); } osg::ref_ptr attach( - const std::string& model, std::string_view bonename, std::string_view bonefilter, bool isLight); + VFS::Path::NormalizedView model, std::string_view bonename, std::string_view bonefilter, bool isLight); PartHolderPtr mScabbard; PartHolderPtr mHolsteredShield; diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index b6cc823d28..f84e58e4bc 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -111,7 +111,7 @@ namespace MWRender MWWorld::ConstPtr item = *it; std::string_view bonename; - std::string itemModel = item.getClass().getCorrectedModel(item); + VFS::Path::Normalized itemModel = item.getClass().getCorrectedModel(item); if (slot == MWWorld::InventoryStore::Slot_CarriedRight) { if (item.getType() == ESM::Weapon::sRecordId) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 08dfcb667c..c8fc36e18a 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -681,11 +681,11 @@ namespace MWRender PartHolderPtr NpcAnimation::insertBoundedPart(const std::string& model, std::string_view bonename, std::string_view bonefilter, bool enchantedGlow, osg::Vec4f* glowColor, bool isLight) { - osg::ref_ptr attached = attach(model, bonename, bonefilter, isLight); + osg::ref_ptr attached = attach(VFS::Path::toNormalized(model), bonename, bonefilter, isLight); if (enchantedGlow) mGlowUpdater = SceneUtil::addEnchantedGlow(attached, mResourceSystem, *glowColor); - return std::make_unique(attached); + return std::make_unique(std::move(attached)); } osg::Vec3f NpcAnimation::runAnimation(float timepassed) From d7e99f988b6e8633f0bb21f12e08978b72f02760 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 19 Sep 2024 00:07:36 +0200 Subject: [PATCH 06/13] Use normalized path in ActorAnimation::attachMesh --- apps/openmw/mwrender/actoranimation.cpp | 25 +++++++++++++------------ apps/openmw/mwrender/actoranimation.hpp | 9 ++++++--- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwrender/actoranimation.cpp b/apps/openmw/mwrender/actoranimation.cpp index df712b43b0..123090209f 100644 --- a/apps/openmw/mwrender/actoranimation.cpp +++ b/apps/openmw/mwrender/actoranimation.cpp @@ -67,14 +67,13 @@ namespace MWRender } PartHolderPtr ActorAnimation::attachMesh( - const std::string& model, std::string_view bonename, bool enchantedGlow, osg::Vec4f* glowColor) + VFS::Path::NormalizedView model, std::string_view bonename, bool enchantedGlow, osg::Vec4f* glowColor) { osg::Group* parent = getBoneByName(bonename); if (!parent) return nullptr; - osg::ref_ptr instance - = mResourceSystem->getSceneManager()->getInstance(VFS::Path::toNormalized(model), parent); + osg::ref_ptr instance = mResourceSystem->getSceneManager()->getInstance(model, parent); const NodeMap& nodeMap = getNodeMap(); NodeMap::const_iterator found = nodeMap.find(bonename); @@ -217,13 +216,13 @@ namespace MWRender return; } - std::string mesh = getSheathedShieldMesh(*shield); + const VFS::Path::Normalized mesh = getSheathedShieldMesh(*shield); if (mesh.empty()) return; - std::string_view boneName = "Bip01 AttachShield"; + constexpr std::string_view boneName = "Bip01 AttachShield"; osg::Vec4f glowColor = shield->getClass().getEnchantmentColor(*shield); - const std::string holsteredName = addSuffixBeforeExtension(mesh, "_sh"); + const VFS::Path::Normalized holsteredName = addSuffixBeforeExtension(mesh, "_sh"); bool isEnchanted = !shield->getClass().getEnchantment(*shield).empty(); // If we have no dedicated sheath model, use basic shield model as fallback. @@ -244,8 +243,7 @@ namespace MWRender // file. if (shieldNode && !shieldNode->getNumChildren()) { - osg::ref_ptr fallbackNode - = mResourceSystem->getSceneManager()->getInstance(VFS::Path::toNormalized(mesh), shieldNode); + osg::ref_ptr fallbackNode = mResourceSystem->getSceneManager()->getInstance(mesh, shieldNode); if (isEnchanted) SceneUtil::addEnchantedGlow(shieldNode, mResourceSystem, glowColor); } @@ -340,13 +338,16 @@ namespace MWRender if (MWMechanics::getWeaponType(type)->mWeaponClass == ESM::WeaponType::Thrown) showHolsteredWeapons = false; - std::string mesh = weapon->getClass().getCorrectedModel(*weapon); - std::string_view boneName = getHolsteredWeaponBoneName(*weapon); - if (mesh.empty() || boneName.empty()) + const VFS::Path::Normalized mesh = weapon->getClass().getCorrectedModel(*weapon); + if (mesh.empty()) + return; + + const std::string_view boneName = getHolsteredWeaponBoneName(*weapon); + if (boneName.empty()) return; // If the scabbard is not found, use the weapon mesh as fallback. - const std::string scabbardName = addSuffixBeforeExtension(mesh, "_sh"); + const VFS::Path::Normalized scabbardName = addSuffixBeforeExtension(mesh, "_sh"); bool isEnchanted = !weapon->getClass().getEnchantment(*weapon).empty(); if (!mResourceSystem->getVFS()->exists(scabbardName)) { diff --git a/apps/openmw/mwrender/actoranimation.hpp b/apps/openmw/mwrender/actoranimation.hpp index 5a28c41b6c..ba10c4fc16 100644 --- a/apps/openmw/mwrender/actoranimation.hpp +++ b/apps/openmw/mwrender/actoranimation.hpp @@ -53,13 +53,16 @@ namespace MWRender std::string getShieldMesh(const MWWorld::ConstPtr& shield, bool female) const; virtual std::string getSheathedShieldMesh(const MWWorld::ConstPtr& shield) const; virtual std::string_view getHolsteredWeaponBoneName(const MWWorld::ConstPtr& weapon); - virtual PartHolderPtr attachMesh( - const std::string& model, std::string_view bonename, bool enchantedGlow, osg::Vec4f* glowColor); - virtual PartHolderPtr attachMesh(const std::string& model, std::string_view bonename) + + PartHolderPtr attachMesh( + VFS::Path::NormalizedView model, std::string_view bonename, bool enchantedGlow, osg::Vec4f* glowColor); + + PartHolderPtr attachMesh(VFS::Path::NormalizedView model, std::string_view bonename) { osg::Vec4f stubColor = osg::Vec4f(0, 0, 0, 0); return attachMesh(model, bonename, false, &stubColor); } + osg::ref_ptr attach( VFS::Path::NormalizedView model, std::string_view bonename, std::string_view bonefilter, bool isLight); From 8ba4ff99468d88d054c581262b19b3668f49a709 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 19 Sep 2024 00:13:41 +0200 Subject: [PATCH 07/13] Remove redundant bool argument from ActorAnimation::attachMesh --- apps/openmw/mwrender/actoranimation.cpp | 19 ++++++++++--------- apps/openmw/mwrender/actoranimation.hpp | 8 +------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwrender/actoranimation.cpp b/apps/openmw/mwrender/actoranimation.cpp index 123090209f..96141c9ebf 100644 --- a/apps/openmw/mwrender/actoranimation.cpp +++ b/apps/openmw/mwrender/actoranimation.cpp @@ -67,7 +67,7 @@ namespace MWRender } PartHolderPtr ActorAnimation::attachMesh( - VFS::Path::NormalizedView model, std::string_view bonename, bool enchantedGlow, osg::Vec4f* glowColor) + VFS::Path::NormalizedView model, std::string_view bonename, const osg::Vec4f* glowColor) { osg::Group* parent = getBoneByName(bonename); if (!parent) @@ -80,7 +80,7 @@ namespace MWRender if (found == nodeMap.end()) return {}; - if (enchantedGlow) + if (glowColor != nullptr) mGlowUpdater = SceneUtil::addEnchantedGlow(instance, mResourceSystem, *glowColor); return std::make_unique(instance); @@ -221,15 +221,15 @@ namespace MWRender return; constexpr std::string_view boneName = "Bip01 AttachShield"; - osg::Vec4f glowColor = shield->getClass().getEnchantmentColor(*shield); + const bool isEnchanted = !shield->getClass().getEnchantment(*shield).empty(); + const osg::Vec4f glowColor = isEnchanted ? shield->getClass().getEnchantmentColor(*shield) : osg::Vec4f(); const VFS::Path::Normalized holsteredName = addSuffixBeforeExtension(mesh, "_sh"); - bool isEnchanted = !shield->getClass().getEnchantment(*shield).empty(); // If we have no dedicated sheath model, use basic shield model as fallback. if (!mResourceSystem->getVFS()->exists(holsteredName)) - mHolsteredShield = attachMesh(mesh, boneName, isEnchanted, &glowColor); + mHolsteredShield = attachMesh(mesh, boneName, isEnchanted ? &glowColor : nullptr); else - mHolsteredShield = attachMesh(holsteredName, boneName, isEnchanted, &glowColor); + mHolsteredShield = attachMesh(holsteredName, boneName, isEnchanted ? &glowColor : nullptr); if (!mHolsteredShield) return; @@ -348,13 +348,14 @@ namespace MWRender // If the scabbard is not found, use the weapon mesh as fallback. const VFS::Path::Normalized scabbardName = addSuffixBeforeExtension(mesh, "_sh"); - bool isEnchanted = !weapon->getClass().getEnchantment(*weapon).empty(); + const bool isEnchanted = !weapon->getClass().getEnchantment(*weapon).empty(); if (!mResourceSystem->getVFS()->exists(scabbardName)) { if (showHolsteredWeapons) { - osg::Vec4f glowColor = weapon->getClass().getEnchantmentColor(*weapon); - mScabbard = attachMesh(mesh, boneName, isEnchanted, &glowColor); + const osg::Vec4f glowColor + = isEnchanted ? weapon->getClass().getEnchantmentColor(*weapon) : osg::Vec4f(); + mScabbard = attachMesh(mesh, boneName, isEnchanted ? &glowColor : nullptr); if (mScabbard) resetControllers(mScabbard->getNode()); } diff --git a/apps/openmw/mwrender/actoranimation.hpp b/apps/openmw/mwrender/actoranimation.hpp index ba10c4fc16..04a7ada323 100644 --- a/apps/openmw/mwrender/actoranimation.hpp +++ b/apps/openmw/mwrender/actoranimation.hpp @@ -55,13 +55,7 @@ namespace MWRender virtual std::string_view getHolsteredWeaponBoneName(const MWWorld::ConstPtr& weapon); PartHolderPtr attachMesh( - VFS::Path::NormalizedView model, std::string_view bonename, bool enchantedGlow, osg::Vec4f* glowColor); - - PartHolderPtr attachMesh(VFS::Path::NormalizedView model, std::string_view bonename) - { - osg::Vec4f stubColor = osg::Vec4f(0, 0, 0, 0); - return attachMesh(model, bonename, false, &stubColor); - } + VFS::Path::NormalizedView model, std::string_view bonename, const osg::Vec4f* glowColor = nullptr); osg::ref_ptr attach( VFS::Path::NormalizedView model, std::string_view bonename, std::string_view bonefilter, bool isLight); From 320d376b95c224216ddc942ac48483040f6c8953 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 19 Sep 2024 00:17:44 +0200 Subject: [PATCH 08/13] Remove unused virtual specifier --- apps/openmw/mwrender/actoranimation.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/actoranimation.hpp b/apps/openmw/mwrender/actoranimation.hpp index 04a7ada323..0182df9370 100644 --- a/apps/openmw/mwrender/actoranimation.hpp +++ b/apps/openmw/mwrender/actoranimation.hpp @@ -47,12 +47,12 @@ namespace MWRender protected: osg::Group* getBoneByName(std::string_view boneName) const; - virtual void updateHolsteredWeapon(bool showHolsteredWeapons); - virtual void updateHolsteredShield(bool showCarriedLeft); - virtual void updateQuiver(); + void updateHolsteredWeapon(bool showHolsteredWeapons); + void updateHolsteredShield(bool showCarriedLeft); + void updateQuiver(); std::string getShieldMesh(const MWWorld::ConstPtr& shield, bool female) const; virtual std::string getSheathedShieldMesh(const MWWorld::ConstPtr& shield) const; - virtual std::string_view getHolsteredWeaponBoneName(const MWWorld::ConstPtr& weapon); + std::string_view getHolsteredWeaponBoneName(const MWWorld::ConstPtr& weapon); PartHolderPtr attachMesh( VFS::Path::NormalizedView model, std::string_view bonename, const osg::Vec4f* glowColor = nullptr); From 3475a166e50ae6e0991b953e1bb534056ae0d390 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 19 Sep 2024 00:31:16 +0200 Subject: [PATCH 09/13] Use normalized path for World::spawnEffect --- apps/openmw/mwbase/world.hpp | 4 ++-- apps/openmw/mwlua/animationbindings.cpp | 6 +++--- apps/openmw/mwmechanics/actors.cpp | 5 +++-- apps/openmw/mwmechanics/spellcasting.cpp | 10 ++++++---- apps/openmw/mwworld/worldimp.cpp | 6 +++--- apps/openmw/mwworld/worldimp.hpp | 5 +++-- 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 6ab5ab64fa..904b96c463 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -4,13 +4,13 @@ #include "rotationflags.hpp" #include -#include #include #include #include #include #include +#include #include "../mwworld/doorstate.hpp" #include "../mwworld/globalvariablename.hpp" @@ -515,7 +515,7 @@ namespace MWBase /// Spawn a blood effect for \a ptr at \a worldPosition virtual void spawnBloodEffect(const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0; - virtual void spawnEffect(const std::string& model, const std::string& textureOverride, + virtual void spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride, const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true) = 0; diff --git a/apps/openmw/mwlua/animationbindings.cpp b/apps/openmw/mwlua/animationbindings.cpp index 95294f46cb..b74a3e51c3 100644 --- a/apps/openmw/mwlua/animationbindings.cpp +++ b/apps/openmw/mwlua/animationbindings.cpp @@ -319,14 +319,14 @@ namespace MWLua std::string texture = options->get_or("particleTextureOverride", ""); float scale = options->get_or("scale", 1.f); context.mLuaManager->addAction( - [world, model = std::string(model), texture = std::move(texture), worldPos, scale, + [world, model = VFS::Path::Normalized(model), texture = std::move(texture), worldPos, scale, magicVfx]() { world->spawnEffect(model, texture, worldPos, scale, magicVfx); }, "openmw.vfx.spawn"); } else { - context.mLuaManager->addAction( - [world, model = std::string(model), worldPos]() { world->spawnEffect(model, "", worldPos); }, + context.mLuaManager->addAction([world, model = VFS::Path::Normalized(model), + worldPos]() { world->spawnEffect(model, "", worldPos); }, "openmw.vfx.spawn"); } }; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 3f2a9b46bb..401ba0ae86 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -214,7 +214,7 @@ namespace const ESM::Static* const fx = world->getStore().get().search(ESM::RefId::stringRefId("VFX_Soul_Trap")); if (fx != nullptr) - world->spawnEffect(Misc::ResourceHelpers::correctMeshPath(fx->mModel), "", + world->spawnEffect(VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(fx->mModel)), "", creature.getRefData().getPosition().asVec3()); MWBase::Environment::get().getSoundManager()->playSound3D( @@ -1806,7 +1806,8 @@ namespace MWMechanics ESM::RefId::stringRefId("VFX_Summon_End")); if (fx) MWBase::Environment::get().getWorld()->spawnEffect( - Misc::ResourceHelpers::correctMeshPath(fx->mModel), "", ptr.getRefData().getPosition().asVec3()); + VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(fx->mModel)), "", + ptr.getRefData().getPosition().asVec3()); // Remove the summoned creature's summoned creatures as well MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index d22b6c4837..1d847a4129 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -72,12 +72,13 @@ namespace MWMechanics { if (effectInfo.mData.mRange == ESM::RT_Target) world->spawnEffect( - Misc::ResourceHelpers::correctMeshPath(areaStatic->mModel), texture, mHitPosition, 1.0f); + VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(areaStatic->mModel)), texture, + mHitPosition, 1.0f); continue; } else - world->spawnEffect(Misc::ResourceHelpers::correctMeshPath(areaStatic->mModel), texture, mHitPosition, - static_cast(effectInfo.mData.mArea * 2)); + world->spawnEffect(VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(areaStatic->mModel)), + texture, mHitPosition, static_cast(effectInfo.mData.mArea * 2)); // Play explosion sound (make sure to use NoTrack, since we will delete the projectile now) { @@ -539,7 +540,8 @@ namespace MWMechanics } scale = std::max(scale, 1.f); MWBase::Environment::get().getWorld()->spawnEffect( - Misc::ResourceHelpers::correctMeshPath(castStatic->mModel), effect->mParticle, pos, scale); + VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(castStatic->mModel)), + effect->mParticle, pos, scale); } if (animation && !mCaster.getClass().isActor()) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b52d59d5e7..07da51b4f3 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3644,10 +3644,10 @@ namespace MWWorld mRendering->spawnEffect(model, texture, worldPosition, 1.0f, false); } - void World::spawnEffect(const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos, - float scale, bool isMagicVFX) + void World::spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride, + const osg::Vec3f& worldPos, float scale, bool isMagicVFX) { - mRendering->spawnEffect(VFS::Path::toNormalized(model), textureOverride, worldPos, scale, isMagicVFX); + mRendering->spawnEffect(model, textureOverride, worldPos, scale, isMagicVFX); } struct ResetActorsVisitor diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f4c22e94d3..9e00118533 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "../mwbase/world.hpp" @@ -603,8 +604,8 @@ namespace MWWorld /// Spawn a blood effect for \a ptr at \a worldPosition void spawnBloodEffect(const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) override; - void spawnEffect(const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos, - float scale = 1.f, bool isMagicVFX = true) override; + void spawnEffect(VFS::Path::NormalizedView model, const std::string& textureOverride, + const osg::Vec3f& worldPos, float scale = 1.f, bool isMagicVFX = true) override; /// @see MWWorld::WeatherManager::isInStorm bool isInStorm() const override; From 28faae69b0ba88270003786a8dfa942175f4f497 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 19 Sep 2024 00:36:45 +0200 Subject: [PATCH 10/13] Use normalized path in TextureManager --- components/terrain/defs.hpp | 6 +++--- components/terrain/texturemanager.cpp | 22 ++++++++++------------ components/terrain/texturemanager.hpp | 5 ++--- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/components/terrain/defs.hpp b/components/terrain/defs.hpp index c2342c50d2..48e4813e65 100644 --- a/components/terrain/defs.hpp +++ b/components/terrain/defs.hpp @@ -1,7 +1,7 @@ #ifndef COMPONENTS_TERRAIN_DEFS_HPP #define COMPONENTS_TERRAIN_DEFS_HPP -#include +#include namespace Terrain { @@ -16,8 +16,8 @@ namespace Terrain struct LayerInfo { - std::string mDiffuseMap; - std::string mNormalMap; + VFS::Path::Normalized mDiffuseMap; + VFS::Path::Normalized mNormalMap; bool mParallax; // Height info in normal map alpha channel? bool mSpecular; // Specular info in diffuse map alpha channel? diff --git a/components/terrain/texturemanager.cpp b/components/terrain/texturemanager.cpp index 8df880fab0..06f3243330 100644 --- a/components/terrain/texturemanager.cpp +++ b/components/terrain/texturemanager.cpp @@ -35,23 +35,21 @@ namespace Terrain mCache->call(f); } - osg::ref_ptr TextureManager::getTexture(const std::string& name) + osg::ref_ptr TextureManager::getTexture(VFS::Path::NormalizedView name) { // don't bother with case folding, since there is only one way of referring to terrain textures we can assume // the case is always the same osg::ref_ptr obj = mCache->getRefFromObjectCache(name); - if (obj) + + if (obj != nullptr) return static_cast(obj.get()); - else - { - osg::ref_ptr texture( - new osg::Texture2D(mSceneManager->getImageManager()->getImage(VFS::Path::toNormalized(name)))); - texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); - texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); - mSceneManager->applyFilterSettings(texture); - mCache->addEntryToObjectCache(name, texture.get()); - return texture; - } + + osg::ref_ptr texture(new osg::Texture2D(mSceneManager->getImageManager()->getImage(name))); + texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + mSceneManager->applyFilterSettings(texture); + mCache->addEntryToObjectCache(name.value(), texture.get()); + return texture; } void TextureManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const diff --git a/components/terrain/texturemanager.hpp b/components/terrain/texturemanager.hpp index 96fb43abfa..a79ef53b88 100644 --- a/components/terrain/texturemanager.hpp +++ b/components/terrain/texturemanager.hpp @@ -1,9 +1,8 @@ #ifndef OPENMW_COMPONENTS_TERRAIN_TEXTUREMANAGER_H #define OPENMW_COMPONENTS_TERRAIN_TEXTUREMANAGER_H -#include - #include +#include namespace Resource { @@ -25,7 +24,7 @@ namespace Terrain void updateTextureFiltering(); - osg::ref_ptr getTexture(const std::string& name); + osg::ref_ptr getTexture(VFS::Path::NormalizedView name); void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; From 5f2582fe6856db5028a8f626e11e9f83daa88767 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 19 Sep 2024 00:47:51 +0200 Subject: [PATCH 11/13] Use normalized path in SceneManager::checkLoaded --- apps/openmw/mwworld/scene.cpp | 24 ++++++++++++------------ components/resource/scenemanager.cpp | 4 ++-- components/resource/scenemanager.hpp | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 66aa027a89..c42a786936 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -1126,19 +1126,19 @@ namespace MWWorld void Scene::preload(const std::string& mesh, bool useAnim) { - std::string meshPath = mesh; - if (useAnim) - meshPath = Misc::ResourceHelpers::correctActorModelPath(meshPath, mRendering.getResourceSystem()->getVFS()); + const VFS::Path::Normalized meshPath = useAnim + ? Misc::ResourceHelpers::correctActorModelPath(mesh, mRendering.getResourceSystem()->getVFS()) + : mesh; - if (!mRendering.getResourceSystem()->getSceneManager()->checkLoaded(meshPath, mRendering.getReferenceTime())) - { - osg::ref_ptr item(new PreloadMeshItem( - VFS::Path::toNormalized(meshPath), mRendering.getResourceSystem()->getSceneManager())); - mRendering.getWorkQueue()->addWorkItem(item); - const auto isDone = [](const osg::ref_ptr& v) { return v->isDone(); }; - mWorkItems.erase(std::remove_if(mWorkItems.begin(), mWorkItems.end(), isDone), mWorkItems.end()); - mWorkItems.emplace_back(std::move(item)); - } + if (mRendering.getResourceSystem()->getSceneManager()->checkLoaded(meshPath, mRendering.getReferenceTime())) + return; + + osg::ref_ptr item( + new PreloadMeshItem(meshPath, mRendering.getResourceSystem()->getSceneManager())); + mRendering.getWorkQueue()->addWorkItem(item); + const auto isDone = [](const osg::ref_ptr& v) { return v->isDone(); }; + mWorkItems.erase(std::remove_if(mWorkItems.begin(), mWorkItems.end(), isDone), mWorkItems.end()); + mWorkItems.emplace_back(std::move(item)); } void Scene::preloadCells(float dt) diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 9feab669a9..82a77ccc0a 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -597,9 +597,9 @@ namespace Resource mShaderManager->setShaderPath(path); } - bool SceneManager::checkLoaded(const std::string& name, double timeStamp) + bool SceneManager::checkLoaded(VFS::Path::NormalizedView name, double timeStamp) { - return mCache->checkInObjectCache(VFS::Path::normalizeFilename(name), timeStamp); + return mCache->checkInObjectCache(name, timeStamp); } void SceneManager::setUpNormalsRTForStateSet(osg::StateSet* stateset, bool enabled) diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index 6ea94233e7..ecd94e257c 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -152,7 +152,7 @@ namespace Resource void setShaderPath(const std::filesystem::path& path); /// Check if a given scene is loaded and if so, update its usage timestamp to prevent it from being unloaded - bool checkLoaded(const std::string& name, double referenceTime); + bool checkLoaded(VFS::Path::NormalizedView name, double referenceTime); /// Get a read-only copy of this scene "template" /// @note If the given filename does not exist or fails to load, an error marker mesh will be used instead. From 7e453d491a573de3429238c218bda8dc4cd4529b Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 19 Sep 2024 00:53:27 +0200 Subject: [PATCH 12/13] Remove redundant toNormalized --- apps/openmw/mwrender/animation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 5b7d1db78a..64e961e22e 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1508,10 +1508,10 @@ namespace MWRender } animationPath.replace(animationPath.size() - 4, 4, "/"); - for (const auto& name : resourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath)) + for (const VFS::Path::Normalized& name : resourceSystem->getVFS()->getRecursiveDirectoryIterator(animationPath)) { if (Misc::getFileExtension(name) == "nif") - loadBonesFromFile(node, VFS::Path::toNormalized(name), resourceSystem); + loadBonesFromFile(node, name, resourceSystem); } } From 2ef5a8486d417312ff3c8b97f0d75d2ec61298d1 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 19 Sep 2024 01:05:10 +0200 Subject: [PATCH 13/13] Use normalized path in ObjectPaging::createChunk --- apps/openmw/mwrender/objectpaging.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 6e39d99404..8040790bd7 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -639,7 +640,7 @@ namespace MWRender continue; const int type = store.findStatic(ref.mRefId); - std::string model = getModel(type, ref.mRefId, store); + VFS::Path::Normalized model = getModel(type, ref.mRefId, store); if (model.empty()) continue; model = Misc::ResourceHelpers::correctMeshPath(model); @@ -647,10 +648,10 @@ namespace MWRender if (activeGrid && type != ESM::REC_STAT) { model = Misc::ResourceHelpers::correctActorModelPath(model, mSceneManager->getVFS()); - std::string kfname = Misc::StringUtils::lowerCase(model); - if (kfname.size() > 4 && kfname.ends_with(".nif")) + if (Misc::getFileExtension(model) == "nif") { - kfname.replace(kfname.size() - 4, 4, ".kf"); + VFS::Path::Normalized kfname = model; + kfname.changeExtension("kf"); if (mSceneManager->getVFS()->exists(kfname)) continue; } @@ -671,7 +672,7 @@ namespace MWRender ->second; } - osg::ref_ptr cnode = mSceneManager->getTemplate(VFS::Path::toNormalized(model), false); + osg::ref_ptr cnode = mSceneManager->getTemplate(model, false); if (activeGrid) {