From 04d7781424e3d80d4dfc444fdf8e93d38ea5d422 Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 3 Mar 2023 16:00:16 +0100 Subject: [PATCH] Support not only StringRefId for checking first person body part --- apps/opencs/model/world/actoradapter.cpp | 8 +------- apps/opencs/model/world/actoradapter.hpp | 1 - apps/openmw/mwgui/race.cpp | 4 +--- apps/openmw/mwrender/npcanimation.cpp | 11 ++--------- apps/openmw/mwrender/npcanimation.hpp | 1 - components/esm/refid.cpp | 18 ++++++++++++++++++ components/esm/refid.hpp | 4 ++++ components/esm/stringrefid.cpp | 5 +++++ components/esm/stringrefid.hpp | 2 ++ components/esm3/loadbody.cpp | 5 +++++ components/esm3/loadbody.hpp | 2 ++ 11 files changed, 40 insertions(+), 21 deletions(-) diff --git a/apps/opencs/model/world/actoradapter.cpp b/apps/opencs/model/world/actoradapter.cpp index 1a50a51010..e57ad648ba 100644 --- a/apps/opencs/model/world/actoradapter.cpp +++ b/apps/opencs/model/world/actoradapter.cpp @@ -425,11 +425,6 @@ namespace CSMWorld return index; } - bool ActorAdapter::is1stPersonPart(const std::string& name) const - { - return name.size() >= 4 && name.find(".1st", name.size() - 4) != std::string::npos; - } - ActorAdapter::RaceDataPtr ActorAdapter::getRaceData(const ESM::RefId& id) { // Return cached race data if it exists @@ -519,8 +514,7 @@ namespace CSMWorld } auto& part = partRecord.get(); - if (part.mRace == id && part.mData.mType == ESM::BodyPart::MT_Skin - && !is1stPersonPart(part.mId.getRefIdString())) + if (part.mRace == id && part.mData.mType == ESM::BodyPart::MT_Skin && !ESM::isFirstPersonBodyPart(part)) { auto type = (ESM::BodyPart::MeshPart)part.mData.mPart; bool female = part.mData.mFlags & ESM::BodyPart::BPF_Female; diff --git a/apps/opencs/model/world/actoradapter.hpp b/apps/opencs/model/world/actoradapter.hpp index 8d703a6bae..9747f448ae 100644 --- a/apps/opencs/model/world/actoradapter.hpp +++ b/apps/opencs/model/world/actoradapter.hpp @@ -149,7 +149,6 @@ namespace CSMWorld ActorAdapter& operator=(const ActorAdapter&) = delete; QModelIndex getHighestIndex(QModelIndex) const; - bool is1stPersonPart(const std::string& id) const; RaceDataPtr getRaceData(const ESM::RefId& raceId); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index adc6d9d614..5d21cb00bd 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -321,7 +321,6 @@ namespace MWGui for (const ESM::BodyPart& bodypart : store) { - const std::string& idString = bodypart.mId.getRefIdString(); if (bodypart.mData.mFlags & ESM::BodyPart::BPF_NotPlayable) continue; if (bodypart.mData.mType != ESM::BodyPart::MT_Skin) @@ -330,8 +329,7 @@ namespace MWGui continue; if (mGenderIndex != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female)) continue; - bool firstPerson = Misc::StringUtils::ciEndsWith(idString, "1st"); - if (firstPerson) + if (ESM::isFirstPersonBodyPart(bodypart)) continue; if (bodypart.mRace == mCurrentRaceId) out.push_back(bodypart.mId); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 1025c21621..9e98b2e6ff 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -85,7 +85,6 @@ namespace namespace MWRender { - class HeadAnimationTime : public SceneUtil::ControllerSource { private: @@ -761,12 +760,6 @@ namespace MWRender } } - bool NpcAnimation::isFirstPersonPart(const ESM::BodyPart* bodypart) - { - std::string_view partName = bodypart->mId.getRefIdString(); - return partName.size() >= 3 && partName.substr(partName.size() - 3, 3) == "1st"; - } - bool NpcAnimation::isFemalePart(const ESM::BodyPart* bodypart) { return bodypart->mData.mFlags & ESM::BodyPart::BPF_Female; @@ -1220,7 +1213,7 @@ namespace MWRender if (!(bodypart.mRace == race)) continue; - bool partFirstPerson = isFirstPersonPart(&bodypart); + const bool partFirstPerson = ESM::isFirstPersonBodyPart(bodypart); bool isHand = bodypart.mData.mPart == ESM::BodyPart::MP_Hand || bodypart.mData.mPart == ESM::BodyPart::MP_Wrist @@ -1277,7 +1270,7 @@ namespace MWRender parts[bIt->second] = &bodypart; // If we have 3d person fallback bodypart for hand and 1st person fallback found (2) - else if (isHand && !isFirstPersonPart(parts[bIt->second]) && partFirstPerson) + else if (isHand && !ESM::isFirstPersonBodyPart(*parts[bIt->second]) && partFirstPerson) parts[bIt->second] = &bodypart; ++bIt; diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 5468e785d9..a03ee28f3a 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -99,7 +99,6 @@ namespace MWRender osg::ref_ptr mFirstPersonNeckController; - static bool isFirstPersonPart(const ESM::BodyPart* bodypart); static bool isFemalePart(const ESM::BodyPart* bodypart); static NpcType getNpcType(const MWWorld::Ptr& ptr); diff --git a/components/esm/refid.cpp b/components/esm/refid.cpp index 849efee96b..e6bdaa2df0 100644 --- a/components/esm/refid.cpp +++ b/components/esm/refid.cpp @@ -77,6 +77,19 @@ namespace ESM } }; + struct EndsWith + { + const std::string_view mSuffix; + + bool operator()(StringRefId v) const { return v.endsWith(mSuffix); } + + template + bool operator()(const T& /*v*/) const + { + return false; + } + }; + struct Contains { const std::string_view mSubString; @@ -155,6 +168,11 @@ namespace ESM return std::visit(StartsWith{ prefix }, mValue); } + bool RefId::endsWith(std::string_view suffix) const + { + return std::visit(EndsWith{ suffix }, mValue); + } + bool RefId::contains(std::string_view subString) const { return std::visit(Contains{ subString }, mValue); diff --git a/components/esm/refid.hpp b/components/esm/refid.hpp index 7c7d9e03fd..351a7630e5 100644 --- a/components/esm/refid.hpp +++ b/components/esm/refid.hpp @@ -104,6 +104,10 @@ namespace ESM // Otherwise returns false. bool startsWith(std::string_view prefix) const; + // Returns true if underlying value is StringRefId and its underlying std::string ends with given suffix. + // Otherwise returns false. + bool endsWith(std::string_view suffix) const; + // Returns true if underlying value is StringRefId and its underlying std::string contains given subString. // Otherwise returns false. bool contains(std::string_view subString) const; diff --git a/components/esm/stringrefid.cpp b/components/esm/stringrefid.cpp index e619cd0ebe..22cf045a32 100644 --- a/components/esm/stringrefid.cpp +++ b/components/esm/stringrefid.cpp @@ -81,6 +81,11 @@ namespace ESM return Misc::StringUtils::ciStartsWith(*mValue, prefix); } + bool StringRefId::endsWith(std::string_view suffix) const + { + return Misc::StringUtils::ciEndsWith(*mValue, suffix); + } + bool StringRefId::contains(std::string_view subString) const { return Misc::StringUtils::ciFind(*mValue, subString) != std::string_view::npos; diff --git a/components/esm/stringrefid.hpp b/components/esm/stringrefid.hpp index 989d487346..6679763d55 100644 --- a/components/esm/stringrefid.hpp +++ b/components/esm/stringrefid.hpp @@ -27,6 +27,8 @@ namespace ESM bool startsWith(std::string_view prefix) const; + bool endsWith(std::string_view suffix) const; + bool contains(std::string_view subString) const; bool operator==(StringRefId rhs) const noexcept { return mValue == rhs.mValue; } diff --git a/components/esm3/loadbody.cpp b/components/esm3/loadbody.cpp index 89d7e3f051..8468fc5c90 100644 --- a/components/esm3/loadbody.cpp +++ b/components/esm3/loadbody.cpp @@ -73,4 +73,9 @@ namespace ESM mModel.clear(); mRace = ESM::RefId(); } + + bool isFirstPersonBodyPart(const BodyPart& value) + { + return value.mId.endsWith("1st"); + } } diff --git a/components/esm3/loadbody.hpp b/components/esm3/loadbody.hpp index d0ee5488af..0fadf190df 100644 --- a/components/esm3/loadbody.hpp +++ b/components/esm3/loadbody.hpp @@ -72,5 +72,7 @@ namespace ESM void blank(); ///< Set record to default state (does not touch the ID). }; + + bool isFirstPersonBodyPart(const BodyPart& value); } #endif