From 713029a3f2150ef8b6b50f2eddd2526518b58ba2 Mon Sep 17 00:00:00 2001 From: Angeldark Raymaker Date: Sun, 28 Sep 2025 10:13:33 +0100 Subject: [PATCH] FIRE-35794: Cleanup and fix reloading --- indra/newview/fsfloaterposer.cpp | 42 +++++++++++++---------- indra/newview/fsfloaterposer.h | 9 +++-- indra/newview/fsposeranimator.h | 11 ++++++ indra/newview/fsposestate.cpp | 59 ++++++++++++++++++-------------- indra/newview/fsposestate.h | 19 +++++----- 5 files changed, 85 insertions(+), 55 deletions(-) diff --git a/indra/newview/fsfloaterposer.cpp b/indra/newview/fsfloaterposer.cpp index f5104ea2d5..0ccd53c6c0 100644 --- a/indra/newview/fsfloaterposer.cpp +++ b/indra/newview/fsfloaterposer.cpp @@ -915,15 +915,14 @@ void FSFloaterPoser::timedReload() if (loadPoseFromXml(avatar, mLoadPoseTimer->getPosePath(), mLoadPoseTimer->getLoadMethod())) { - setLoadingProgress(false); + mLoadPoseTimer->completeLoading(); onJointTabSelect(); refreshJointScrollListMembers(); setSavePosesButtonText(!mPoserAnimator.allBaseRotationsAreZero(avatar)); } - else - { - setLoadingProgress(true); - } + + if (mLoadPoseTimer->loadCompleteOrFailed()) + setLoadingProgress(false); } void FSFloaterPoser::setLoadingProgress(bool started) @@ -1145,22 +1144,25 @@ bool FSFloaterPoser::loadPoseFromXml(LLVOAvatar* avatar, const std::string& pose setJointBaseRotationToZero = startFromZeroRot; if (loadPositions && control_map.has("position")) - { vec3.setValue(control_map["position"]); - mPoserAnimator.loadJointPosition(avatar, poserJoint, loadPositionsAndScalesAsDeltas, vec3); - } + else + vec3.clear(); + + mPoserAnimator.loadJointPosition(avatar, poserJoint, loadPositionsAndScalesAsDeltas, vec3); if (loadRotations && control_map.has("rotation")) - { vec3.setValue(control_map["rotation"]); - mPoserAnimator.loadJointRotation(avatar, poserJoint, setJointBaseRotationToZero, vec3); - } + else + vec3.clear(); + + mPoserAnimator.loadJointRotation(avatar, poserJoint, setJointBaseRotationToZero, vec3); if (loadScales && control_map.has("scale")) - { vec3.setValue(control_map["scale"]); - mPoserAnimator.loadJointScale(avatar, poserJoint, loadPositionsAndScalesAsDeltas, vec3); - } + else + vec3.clear(); + + mPoserAnimator.loadJointScale(avatar, poserJoint, loadPositionsAndScalesAsDeltas, vec3); worldLocked = control_map.has("worldLocked") ? control_map["worldLocked"].asBoolean() : false; mPoserAnimator.setRotationIsWorldLocked(avatar, *poserJoint, worldLocked); @@ -1823,6 +1825,9 @@ void FSFloaterPoser::setUiSelectedAvatarSaveFileName(const std::string& saveFile LLVOAvatar* FSFloaterPoser::getAvatarByUuid(const LLUUID& avatarToFind) const { + if (avatarToFind.isNull()) + return nullptr; + for (LLCharacter* character : LLCharacter::sInstances) { if (avatarToFind != character->getID()) @@ -2775,15 +2780,14 @@ bool FSLoadPoseTimer::tick() { if (!mAttemptLoading) return false; - - if (mLoadAttempts > 5) - return false; - if (mCallback.empty()) return false; - mCallback(); + if (mLoadAttempts >= mMaxLoadAttempts) + mAttemptLoading = false; + mLoadAttempts++; + mCallback(); return false; } diff --git a/indra/newview/fsfloaterposer.h b/indra/newview/fsfloaterposer.h index 79830826b5..a88f690a4b 100644 --- a/indra/newview/fsfloaterposer.h +++ b/indra/newview/fsfloaterposer.h @@ -542,9 +542,11 @@ public: FSLoadPoseTimer(callback_t callback); /*virtual*/ bool tick(); - void tryLoading(std::string filePath, E_LoadPoseMethods loadMethod); - std::string getPosePath() { return mPoseFullPath; }; - E_LoadPoseMethods getLoadMethod() { return mLoadType; }; + void tryLoading(std::string filePath, E_LoadPoseMethods loadMethod); + bool loadCompleteOrFailed() const { return !mAttemptLoading && mLoadAttempts > 0; } + void completeLoading() { mAttemptLoading = false; } + std::string getPosePath() { return mPoseFullPath; }; + E_LoadPoseMethods getLoadMethod() const { return mLoadType; }; private: callback_t mCallback; @@ -552,6 +554,7 @@ private: E_LoadPoseMethods mLoadType = ROT_POS_AND_SCALES; std::string mPoseFullPath; int mLoadAttempts = 0; + const int mMaxLoadAttempts = 5; }; #endif diff --git a/indra/newview/fsposeranimator.h b/indra/newview/fsposeranimator.h index 387e60da12..880997a750 100644 --- a/indra/newview/fsposeranimator.h +++ b/indra/newview/fsposeranimator.h @@ -734,6 +734,17 @@ public: /// The joints which were recaptured. void updatePosingState(LLVOAvatar* avatar, std::vector jointsRecaptured); + /// + /// Add a new posing state, or updates the matching posing state with the supplied data. + /// + /// The avatar the posing state is intended for. + /// The ID of the animation. + /// The frame-time of the animation. + /// The names of the joints, if any, the animation should specifically be applied to. + /// The capture order. + /// True if the posing state was added or changed by the update data, otherwise false. + bool addOrUpdatePosingState(LLVOAvatar* avatar, LLUUID animId, F32 updateTime, std::string jointNames, int captureOrder); + /// /// Traverses the joints and applies reversals to the base rotations if needed. /// diff --git a/indra/newview/fsposestate.cpp b/indra/newview/fsposestate.cpp index 8d0f679fa0..ea94565d7d 100644 --- a/indra/newview/fsposestate.cpp +++ b/indra/newview/fsposestate.cpp @@ -18,7 +18,6 @@ void FSPoseState::captureMotionStates(LLVOAvatar* avatar) continue; fsMotionState newState; - newState.avatarId = avatar->getID(); newState.motionId = anim_it->first; newState.lastUpdateTime = motion->getLastUpdateTime(); newState.captureOrder = 0; @@ -39,11 +38,10 @@ void FSPoseState::updateMotionStates(LLVOAvatar* avatar, FSPosingMotion* posingM // this happens on second/subsequent recaptures; the first recapture is no longer needed for (auto it = sMotionStates[avatar->getID()].begin(); it != sMotionStates[avatar->getID()].end();) { - bool avatarMatches = (*it).avatarId == avatar->getID(); std::string joints = (*it).jointNamesAnimated; bool recaptureMatches = !joints.empty() && !jointNamesRecaptured.empty() && jointNamesRecaptured.find(joints) != std::string::npos; - if (avatarMatches && recaptureMatches) + if (recaptureMatches) it = sMotionStates[avatar->getID()].erase(it); else it++; @@ -61,11 +59,10 @@ void FSPoseState::updateMotionStates(LLVOAvatar* avatar, FSPosingMotion* posingM bool foundMatch = false; for (auto it = sMotionStates[avatar->getID()].begin(); it != sMotionStates[avatar->getID()].end(); it++) { - bool avatarMatches = (*it).avatarId == avatar->getID(); bool motionIdMatches = (*it).motionId == anim_it->first; bool updateTimesMatch = (*it).lastUpdateTime == motion->getLastUpdateTime(); // consider when recapturing the same animation at different times for a subset of bones - foundMatch = avatarMatches && motionIdMatches && updateTimesMatch; + foundMatch = motionIdMatches && updateTimesMatch; if (foundMatch) break; } @@ -74,7 +71,6 @@ void FSPoseState::updateMotionStates(LLVOAvatar* avatar, FSPosingMotion* posingM continue; fsMotionState newState; - newState.avatarId = avatar->getID(); newState.motionId = anim_it->first; newState.lastUpdateTime = motion->getLastUpdateTime(); newState.jointNamesAnimated = jointNamesRecaptured; @@ -85,19 +81,41 @@ void FSPoseState::updateMotionStates(LLVOAvatar* avatar, FSPosingMotion* posingM } } +bool FSPoseState::addOrUpdatePosingMotionState(LLVOAvatar* avatar, LLUUID animId, F32 updateTime, std::string jointNames, int captureOrder) +{ + if (!avatar) + return false; + + bool foundMatch = false; + for (auto it = sMotionStates[avatar->getID()].begin(); it != sMotionStates[avatar->getID()].end(); it++) + { + bool motionIdMatches = (*it).motionId == animId; + bool updateTimesMatch = (*it).lastUpdateTime == updateTime; + bool jointNamesMatch = (*it).jointNamesAnimated == jointNames; + bool captureOrdersMatch = (*it).captureOrder == captureOrder; + + foundMatch = motionIdMatches && updateTimesMatch && jointNamesMatch && captureOrdersMatch; + if (foundMatch) + return false; + } + + fsMotionState newState; + newState.motionId = animId; + newState.lastUpdateTime = updateTime; + newState.jointNamesAnimated = jointNames; + newState.captureOrder = captureOrder; + newState.avatarOwnsPose = false; + + sMotionStates[avatar->getID()].push_back(newState); + return true; +} + void FSPoseState::purgeMotionStates(LLVOAvatar* avatar) { if (!avatar) return; - std::vector::iterator it; - for (it = sMotionStates[avatar->getID()].begin(); it != sMotionStates[avatar->getID()].end();) - { - if ((*it).avatarId == avatar->getID()) - it = sMotionStates[avatar->getID()].erase(it); - else - it++; - } + sMotionStates[avatar->getID()].clear(); } void FSPoseState::writeMotionStates(LLVOAvatar* avatar, LLSD* saveRecord) @@ -108,8 +126,6 @@ void FSPoseState::writeMotionStates(LLVOAvatar* avatar, LLSD* saveRecord) int animNumber = 0; for (auto it = sMotionStates[avatar->getID()].begin(); it != sMotionStates[avatar->getID()].end(); ++it) { - if (it->avatarId != avatar->getID()) - continue; if (!it->avatarOwnsPose) continue; @@ -118,7 +134,6 @@ void FSPoseState::writeMotionStates(LLVOAvatar* avatar, LLSD* saveRecord) (*saveRecord)[uniqueAnimId]["lastUpdateTime"] = it->lastUpdateTime; (*saveRecord)[uniqueAnimId]["jointNamesAnimated"] = it->jointNamesAnimated; (*saveRecord)[uniqueAnimId]["captureOrder"] = it->captureOrder; - (*saveRecord)[uniqueAnimId]["playOrder"] = animNumber; } } @@ -131,14 +146,13 @@ void FSPoseState::restoreMotionStates(LLVOAvatar* avatar, LLSD pose) for (auto itr = pose.beginMap(); itr != pose.endMap(); ++itr) { - std::string const& name = itr->first; - LLSD const& control_map = itr->second; + std::string const& name = itr->first; + LLSD const& control_map = itr->second; if (!name.starts_with("poseState")) continue; fsMotionState newState; - newState.avatarId = avatar->getID(); newState.avatarOwnsPose = true; if (control_map.has("animationId")) @@ -178,9 +192,6 @@ bool FSPoseState::applyMotionStatesToPosingMotion(LLVOAvatar* avatar, FSPosingMo bool needPriorityReset = false; for (auto it = sMotionStates[avatar->getID()].begin(); it != sMotionStates[avatar->getID()].end(); it++) { - if (it->avatarId != avatar->getID()) - continue; - needPriorityReset = it->captureOrder > lastCaptureOrder; if (it->motionApplied) @@ -216,8 +227,6 @@ void FSPoseState::resetPriorityForCaptureOrder(LLVOAvatar* avatar, FSPosingMotio { if (it->jointNamesAnimated.empty()) continue; - if (it->avatarId != avatar->getID()) - continue; if (it->motionApplied) continue; if (it->captureOrder != captureOrder) diff --git a/indra/newview/fsposestate.h b/indra/newview/fsposestate.h index 233258565c..e941e28d70 100644 --- a/indra/newview/fsposestate.h +++ b/indra/newview/fsposestate.h @@ -41,9 +41,6 @@ public: /// Captures the current animations posing the supplied avatar and how long they have been playing. /// /// The avatar whose animations are to be captured. - /// - /// Only animations owned by the supplied avatar are documented. - /// void captureMotionStates(LLVOAvatar* avatar); /// @@ -54,6 +51,17 @@ public: /// The names of the joints being recaptured. void updateMotionStates(LLVOAvatar* avatar, FSPosingMotion* posingMotion, std::string jointNamesRecaptured); + /// + /// Add a new posing state, or updates the matching posing state with the supplied data. + /// + /// The avatar the posing state is intended for. + /// The ID of the animation. + /// The frame-time of the animation. + /// The names of the joints, if any, the animation should specifically be applied to. + /// The capture order. + /// True if the posing state was added or changed by the update data, otherwise false. + bool addOrUpdatePosingMotionState(LLVOAvatar* avatar, LLUUID animId, F32 updateTime, std::string jointNames, int captureOrder); + /// /// Removes all current animation states for the supplied avatar. /// @@ -98,11 +106,6 @@ private: class fsMotionState { public: - /// - /// The avatar ID this record is associated with. - /// - LLUUID avatarId; - /// /// The motion ID recorded animating the avatar ID. ///