diff --git a/CHANGELOG.md b/CHANGELOG.md index 97ff01ade7..671103cd21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -133,6 +133,7 @@ Bug #7724: Guards don't help vs werewolves Bug #7733: Launcher shows incorrect data paths when there's two plugins with the same name Bug #7742: Governing attribute training limit should use the modified attribute + Bug #7753: Editor: Actors Don't Scale According to Their Race Bug #7758: Water walking is not taken into account to compute path cost on the water Bug #7761: Rain and ambient loop sounds are mutually exclusive Bug #7765: OpenMW-CS: Touch Record option is broken diff --git a/apps/opencs/model/world/actoradapter.cpp b/apps/opencs/model/world/actoradapter.cpp index 37aaf08445..acbe6b5d38 100644 --- a/apps/opencs/model/world/actoradapter.cpp +++ b/apps/opencs/model/world/actoradapter.cpp @@ -67,6 +67,11 @@ namespace CSMWorld return mMaleParts[ESM::getMeshPart(index)]; } + const osg::Vec2f& ActorAdapter::RaceData::getGenderWeightHeight(bool isFemale) + { + return isFemale ? mWeightsHeights.mFemaleWeightHeight : mWeightsHeights.mMaleWeightHeight; + } + bool ActorAdapter::RaceData::hasDependency(const ESM::RefId& id) const { return mDependencies.find(id) != mDependencies.end(); @@ -90,10 +95,11 @@ namespace CSMWorld mDependencies.emplace(id); } - void ActorAdapter::RaceData::reset_data(const ESM::RefId& id, bool isBeast) + void ActorAdapter::RaceData::reset_data(const ESM::RefId& id, const WeightsHeights& raceStats, bool isBeast) { mId = id; mIsBeast = isBeast; + mWeightsHeights = raceStats; for (auto& str : mFemaleParts) str = ESM::RefId(); for (auto& str : mMaleParts) @@ -163,6 +169,11 @@ namespace CSMWorld return it->second.first; } + const osg::Vec2f& ActorAdapter::ActorData::getRaceWeightHeight() const + { + return mRaceData->getGenderWeightHeight(isFemale()); + } + bool ActorAdapter::ActorData::hasDependency(const ESM::RefId& id) const { return mDependencies.find(id) != mDependencies.end(); @@ -504,7 +515,11 @@ namespace CSMWorld } auto& race = raceRecord.get(); - data->reset_data(id, race.mData.mFlags & ESM::Race::Beast); + + WeightsHeights scaleStats = { osg::Vec2f(race.mData.mMaleWeight, race.mData.mMaleHeight), + osg::Vec2f(race.mData.mFemaleWeight, race.mData.mFemaleHeight) }; + + data->reset_data(id, scaleStats, race.mData.mFlags & ESM::Race::Beast); // Setup body parts for (int i = 0; i < mBodyParts.getSize(); ++i) diff --git a/apps/opencs/model/world/actoradapter.hpp b/apps/opencs/model/world/actoradapter.hpp index 9747f448ae..1650fc9006 100644 --- a/apps/opencs/model/world/actoradapter.hpp +++ b/apps/opencs/model/world/actoradapter.hpp @@ -41,6 +41,12 @@ namespace CSMWorld /// Tracks unique strings using RefIdSet = std::unordered_set; + struct WeightsHeights + { + osg::Vec2f mMaleWeightHeight; + osg::Vec2f mFemaleWeightHeight; + }; + /// Contains base race data shared between actors class RaceData { @@ -57,6 +63,8 @@ namespace CSMWorld const ESM::RefId& getFemalePart(ESM::PartReferenceType index) const; /// Retrieves the associated body part const ESM::RefId& getMalePart(ESM::PartReferenceType index) const; + + const osg::Vec2f& getGenderWeightHeight(bool isFemale); /// Checks if the race has a data dependency bool hasDependency(const ESM::RefId& id) const; @@ -67,7 +75,8 @@ namespace CSMWorld /// Marks an additional dependency void addOtherDependency(const ESM::RefId& id); /// Clears parts and dependencies - void reset_data(const ESM::RefId& raceId, bool isBeast = false); + void reset_data(const ESM::RefId& raceId, + const WeightsHeights& raceStats = { osg::Vec2f(1.f, 1.f), osg::Vec2f(1.f, 1.f) }, bool isBeast = false); private: bool handles(ESM::PartReferenceType type) const; @@ -75,6 +84,7 @@ namespace CSMWorld bool mIsBeast; RacePartList mFemaleParts; RacePartList mMaleParts; + WeightsHeights mWeightsHeights; RefIdSet mDependencies; }; using RaceDataPtr = std::shared_ptr; @@ -96,6 +106,8 @@ namespace CSMWorld std::string getSkeleton() const; /// Retrieves the associated actor part ESM::RefId getPart(ESM::PartReferenceType index) const; + + const osg::Vec2f& getRaceWeightHeight() const; /// Checks if the actor has a data dependency bool hasDependency(const ESM::RefId& id) const; diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index eba09bd8b1..0cd95b0ed2 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -585,19 +585,22 @@ namespace CSMWorld void set(Record& record, const QVariant& data) override { ESXRecordT record2 = record.get(); + + float bodyAttr = std::clamp(data.toFloat(), 0.5f, 2.0f); + if (mWeight) { if (mMale) - record2.mData.mMaleWeight = data.toFloat(); + record2.mData.mMaleWeight = bodyAttr; else - record2.mData.mFemaleWeight = data.toFloat(); + record2.mData.mFemaleWeight = bodyAttr; } else { if (mMale) - record2.mData.mMaleHeight = data.toFloat(); + record2.mData.mMaleHeight = bodyAttr; else - record2.mData.mFemaleHeight = data.toFloat(); + record2.mData.mFemaleHeight = bodyAttr; } record.setModified(record2); } diff --git a/apps/opencs/view/render/actor.cpp b/apps/opencs/view/render/actor.cpp index d1bfac0ec6..8aa08e443e 100644 --- a/apps/opencs/view/render/actor.cpp +++ b/apps/opencs/view/render/actor.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,7 @@ namespace CSVRender Actor::Actor(const ESM::RefId& id, CSMWorld::Data& data) : mId(id) , mData(data) - , mBaseNode(new osg::Group()) + , mBaseNode(new osg::PositionAttitudeTransform()) , mSkeleton(nullptr) { mActorData = mData.getActorAdapter()->getActorData(mId); @@ -60,6 +61,10 @@ namespace CSVRender // Attach parts to skeleton loadBodyParts(); + + const osg::Vec2f& attributes = mActorData->getRaceWeightHeight(); + + mBaseNode->setScale(osg::Vec3d(attributes.x(), attributes.x(), attributes.y())); } else { diff --git a/apps/opencs/view/render/actor.hpp b/apps/opencs/view/render/actor.hpp index 86c7e7ff2d..a9cc34b00d 100644 --- a/apps/opencs/view/render/actor.hpp +++ b/apps/opencs/view/render/actor.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -59,7 +60,7 @@ namespace CSVRender CSMWorld::Data& mData; CSMWorld::ActorAdapter::ActorDataPtr mActorData; - osg::ref_ptr mBaseNode; + osg::ref_ptr mBaseNode; SceneUtil::Skeleton* mSkeleton; SceneUtil::NodeMapVisitor::NodeMap mNodeMap; };