From 6e97deb3f7a584822672477e1eea40d8d9b3c5cb Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 3 May 2024 01:07:47 +0200 Subject: [PATCH 1/4] Use normalized path for text key files --- components/resource/keyframemanager.cpp | 36 +++++++++---------------- components/resource/keyframemanager.hpp | 6 ++--- components/vfs/manager.cpp | 23 ++++++++++++---- components/vfs/manager.hpp | 5 ++++ 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/components/resource/keyframemanager.cpp b/components/resource/keyframemanager.cpp index c4d3da2938..beef689e85 100644 --- a/components/resource/keyframemanager.cpp +++ b/components/resource/keyframemanager.cpp @@ -30,9 +30,10 @@ namespace Resource : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) , mTarget(target) , mAnimationManager(std::move(animationManager)) - , mNormalized(normalized) + , mPath(normalized) , mVFS(vfs) { + mPath.changeExtension("txt"); } bool RetrieveAnimationsVisitor::belongsToLeftUpperExtremity(const std::string& name) @@ -142,18 +143,22 @@ namespace Resource // InventoryWeaponOneHand, PickProbe, Slash, Thrust, Chop... even "Slash Small Follow" osgAnimation formats // should have a .txt file with the same name, each line holding a textkey and whitespace separated time // value e.g. idle: start 0.0333 - try + if (const Files::IStreamPtr textKeysFile = mVFS->find(mPath)) { - Files::IStreamPtr textKeysFile = mVFS->get(changeFileExtension(mNormalized, "txt")); - std::string line; - while (getline(*textKeysFile, line)) + try { - mTarget.mTextKeys.emplace(parseTimeSignature(line), parseTextKey(line)); + std::string line; + while (getline(*textKeysFile, line)) + mTarget.mTextKeys.emplace(parseTimeSignature(line), parseTextKey(line)); + } + catch (const std::exception& e) + { + Log(Debug::Warning) << "Failed to read text key file \"" << mPath << "\": " << e.what(); } } - catch (const std::exception& e) + else { - Log(Debug::Warning) << "Failed to use textkey file " << mNormalized << ": " << e.what(); + Log(Debug::Warning) << "Text key file is not found: " << mPath; } callback->setEmulatedAnimations(emulatedAnimations); @@ -191,21 +196,6 @@ namespace Resource return time; } - std::string RetrieveAnimationsVisitor::changeFileExtension(const std::string& file, const std::string& ext) - { - size_t extPos = file.find_last_of('.'); - if (extPos != std::string::npos && extPos + 1 < file.size()) - { - return file.substr(0, extPos + 1) + ext; - } - return file; - } - -} - -namespace Resource -{ - KeyframeManager::KeyframeManager(const VFS::Manager* vfs, SceneManager* sceneManager, double expiryDelay, const ToUTF8::StatelessUtf8Encoder* encoder) : ResourceManager(vfs, expiryDelay) diff --git a/components/resource/keyframemanager.hpp b/components/resource/keyframemanager.hpp index ed8d4a04ab..e5dc1af1cc 100644 --- a/components/resource/keyframemanager.hpp +++ b/components/resource/keyframemanager.hpp @@ -1,9 +1,10 @@ #ifndef OPENMW_COMPONENTS_KEYFRAMEMANAGER_H #define OPENMW_COMPONENTS_KEYFRAMEMANAGER_H +#include + #include #include -#include #include @@ -32,13 +33,12 @@ namespace Resource virtual void apply(osg::Node& node) override; private: - std::string changeFileExtension(const std::string& file, const std::string& ext); std::string parseTextKey(const std::string& line); double parseTimeSignature(const std::string& line); SceneUtil::KeyframeHolder& mTarget; osg::ref_ptr mAnimationManager; - std::string mNormalized; + VFS::Path::Normalized mPath; const VFS::Manager* mVFS; }; } diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index dfbde8299f..12ef378017 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -1,6 +1,5 @@ #include "manager.hpp" -#include #include #include @@ -38,6 +37,11 @@ namespace VFS archive->listResources(mIndex); } + Files::IStreamPtr Manager::find(Path::NormalizedView name) const + { + return findNormalized(name.value()); + } + Files::IStreamPtr Manager::get(const Path::Normalized& name) const { return getNormalized(name); @@ -51,10 +55,10 @@ namespace VFS Files::IStreamPtr Manager::getNormalized(std::string_view normalizedName) const { assert(Path::isNormalized(normalizedName)); - const auto found = mIndex.find(normalizedName); - if (found == mIndex.end()) - throw std::runtime_error("Resource '" + std::string(normalizedName) + "' is not found"); - return found->second->open(); + auto ptr = findNormalized(normalizedName); + if (ptr == nullptr) + throw std::runtime_error("Resource '" + std::string(normalizedName) + "' not found"); + return ptr; } bool Manager::exists(const Path::Normalized& name) const @@ -116,4 +120,13 @@ namespace VFS { return { mIndex.begin(), mIndex.end() }; } + + Files::IStreamPtr Manager::findNormalized(std::string_view normalizedPath) const + { + assert(Path::isNormalized(normalizedPath)); + const auto it = mIndex.find(normalizedPath); + if (it == mIndex.end()) + return nullptr; + return it->second->open(); + } } diff --git a/components/vfs/manager.hpp b/components/vfs/manager.hpp index d64be1d1d1..b6a9d796cc 100644 --- a/components/vfs/manager.hpp +++ b/components/vfs/manager.hpp @@ -45,6 +45,9 @@ namespace VFS bool exists(Path::NormalizedView name) const; + // Returns open file if exists or nullptr. + Files::IStreamPtr find(Path::NormalizedView name) const; + /// Retrieve a file by name. /// @note Throws an exception if the file can not be found. /// @note May be called from any thread once the index has been built. @@ -78,6 +81,8 @@ namespace VFS std::vector> mArchives; FileMap mIndex; + + inline Files::IStreamPtr findNormalized(std::string_view normalizedPath) const; }; } From 616b033c36b19f02918cce3ce982d05c2b2b6a5a Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 3 May 2024 01:11:51 +0200 Subject: [PATCH 2/4] Move parseTextKey and parseTimeSignature to unnamed namespace --- components/resource/keyframemanager.cpp | 36 +++++++++++++------------ components/resource/keyframemanager.hpp | 3 --- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/components/resource/keyframemanager.cpp b/components/resource/keyframemanager.cpp index beef689e85..88b37be0fc 100644 --- a/components/resource/keyframemanager.cpp +++ b/components/resource/keyframemanager.cpp @@ -23,6 +23,25 @@ namespace Resource { + namespace + { + std::string parseTextKey(const std::string& line) + { + const std::size_t spacePos = line.find_last_of(' '); + if (spacePos != std::string::npos) + return line.substr(0, spacePos); + return {}; + } + + double parseTimeSignature(std::string_view line) + { + size_t spacePos = line.find_last_of(' '); + double time = 0.0; + if (spacePos != std::string::npos && spacePos + 1 < line.size()) + time = Misc::StringUtils::toNumeric(line.substr(spacePos + 1), time); + return time; + } + } RetrieveAnimationsVisitor::RetrieveAnimationsVisitor(SceneUtil::KeyframeHolder& target, osg::ref_ptr animationManager, const std::string& normalized, @@ -179,23 +198,6 @@ namespace Resource traverse(node); } - std::string RetrieveAnimationsVisitor::parseTextKey(const std::string& line) - { - size_t spacePos = line.find_last_of(' '); - if (spacePos != std::string::npos) - return line.substr(0, spacePos); - return ""; - } - - double RetrieveAnimationsVisitor::parseTimeSignature(const std::string& line) - { - size_t spacePos = line.find_last_of(' '); - double time = 0.0; - if (spacePos != std::string::npos && spacePos + 1 < line.size()) - time = Misc::StringUtils::toNumeric(line.substr(spacePos + 1), time); - return time; - } - KeyframeManager::KeyframeManager(const VFS::Manager* vfs, SceneManager* sceneManager, double expiryDelay, const ToUTF8::StatelessUtf8Encoder* encoder) : ResourceManager(vfs, expiryDelay) diff --git a/components/resource/keyframemanager.hpp b/components/resource/keyframemanager.hpp index e5dc1af1cc..9dac730042 100644 --- a/components/resource/keyframemanager.hpp +++ b/components/resource/keyframemanager.hpp @@ -33,9 +33,6 @@ namespace Resource virtual void apply(osg::Node& node) override; private: - std::string parseTextKey(const std::string& line); - double parseTimeSignature(const std::string& line); - SceneUtil::KeyframeHolder& mTarget; osg::ref_ptr mAnimationManager; VFS::Path::Normalized mPath; From 7e1ecfc0ee999d52526367aa16db8ac0f1c1f54b Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 3 May 2024 01:28:09 +0200 Subject: [PATCH 3/4] Pass normalized path to RetrieveAnimationsVisitor --- components/resource/keyframemanager.cpp | 18 +++++++++--------- components/resource/keyframemanager.hpp | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/components/resource/keyframemanager.cpp b/components/resource/keyframemanager.cpp index 88b37be0fc..a272d89dd1 100644 --- a/components/resource/keyframemanager.cpp +++ b/components/resource/keyframemanager.cpp @@ -35,22 +35,22 @@ namespace Resource double parseTimeSignature(std::string_view line) { - size_t spacePos = line.find_last_of(' '); + const std::size_t spacePos = line.find_last_of(' '); double time = 0.0; - if (spacePos != std::string::npos && spacePos + 1 < line.size()) + if (spacePos != std::string_view::npos && spacePos + 1 < line.size()) time = Misc::StringUtils::toNumeric(line.substr(spacePos + 1), time); return time; } } RetrieveAnimationsVisitor::RetrieveAnimationsVisitor(SceneUtil::KeyframeHolder& target, - osg::ref_ptr animationManager, const std::string& normalized, - const VFS::Manager* vfs) + osg::ref_ptr animationManager, VFS::Path::NormalizedView path, + const VFS::Manager& vfs) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) , mTarget(target) , mAnimationManager(std::move(animationManager)) - , mPath(normalized) - , mVFS(vfs) + , mPath(path) + , mVFS(&vfs) { mPath.changeExtension("txt"); } @@ -208,7 +208,7 @@ namespace Resource osg::ref_ptr KeyframeManager::get(const std::string& name) { - const std::string normalized = VFS::Path::normalizeFilename(name); + const VFS::Path::Normalized normalized(name); osg::ref_ptr obj = mCache->getRefFromObjectCache(normalized); if (obj) @@ -220,7 +220,7 @@ namespace Resource { auto file = std::make_shared(normalized); Nif::Reader reader(*file, mEncoder); - reader.parse(mVFS->getNormalized(normalized)); + reader.parse(mVFS->get(normalized)); NifOsg::Loader::loadKf(*file, *loaded.get()); } else @@ -230,7 +230,7 @@ namespace Resource = dynamic_cast(scene->getUpdateCallback()); if (bam) { - Resource::RetrieveAnimationsVisitor rav(*loaded.get(), std::move(bam), normalized, mVFS); + Resource::RetrieveAnimationsVisitor rav(*loaded.get(), std::move(bam), normalized, *mVFS); scene->accept(rav); } } diff --git a/components/resource/keyframemanager.hpp b/components/resource/keyframemanager.hpp index 9dac730042..2f5aa875d0 100644 --- a/components/resource/keyframemanager.hpp +++ b/components/resource/keyframemanager.hpp @@ -21,9 +21,9 @@ namespace Resource class RetrieveAnimationsVisitor : public osg::NodeVisitor { public: - RetrieveAnimationsVisitor(SceneUtil::KeyframeHolder& target, - osg::ref_ptr animationManager, const std::string& normalized, - const VFS::Manager* vfs); + explicit RetrieveAnimationsVisitor(SceneUtil::KeyframeHolder& target, + osg::ref_ptr animationManager, VFS::Path::NormalizedView path, + const VFS::Manager& vfs); bool belongsToLeftUpperExtremity(const std::string& name); bool belongsToRightUpperExtremity(const std::string& name); From 8cc744997fe72650a43ae543109dc44a84478648 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 3 May 2024 01:28:38 +0200 Subject: [PATCH 4/4] Make path helpers constexpr and noexcept --- components/misc/pathhelpers.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/components/misc/pathhelpers.hpp b/components/misc/pathhelpers.hpp index 5a6d3feb55..5dc814e20d 100644 --- a/components/misc/pathhelpers.hpp +++ b/components/misc/pathhelpers.hpp @@ -1,18 +1,18 @@ #ifndef OPENMW_COMPONENTS_MISC_PATHHELPERS_H #define OPENMW_COMPONENTS_MISC_PATHHELPERS_H -#include +#include namespace Misc { - inline size_t findExtension(std::string_view file) + inline constexpr std::size_t findExtension(std::string_view file) noexcept { return file.find_last_of('.'); } - inline std::string_view getFileExtension(std::string_view file) + inline constexpr std::string_view getFileExtension(std::string_view file) noexcept { - if (auto extPos = findExtension(file); extPos != std::string::npos) + if (auto extPos = findExtension(file); extPos != std::string_view::npos) { file.remove_prefix(extPos + 1); return file; @@ -20,9 +20,9 @@ namespace Misc return {}; } - inline std::string_view getFileName(std::string_view path) + inline constexpr std::string_view getFileName(std::string_view path) noexcept { - if (auto namePos = path.find_last_of("/\\"); namePos != std::string::npos) + if (auto namePos = path.find_last_of("/\\"); namePos != std::string_view::npos) { path.remove_prefix(namePos + 1); } @@ -30,11 +30,11 @@ namespace Misc return path; } - inline std::string_view stemFile(std::string_view path) + inline constexpr std::string_view stemFile(std::string_view path) noexcept { path = getFileName(path); - if (auto extPos = path.find_last_of("."); extPos != std::string::npos) + if (auto extPos = path.find_last_of('.'); extPos != std::string_view::npos) { path.remove_suffix(path.size() - extPos); }