FIRE-35794: Cleanup and fix reloading

master
Angeldark Raymaker 2025-09-28 10:13:33 +01:00
parent d1dbdd0ae1
commit 713029a3f2
5 changed files with 85 additions and 55 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -734,6 +734,17 @@ public:
/// <param name="jointsRecaptured">The joints which were recaptured.</param>
void updatePosingState(LLVOAvatar* avatar, std::vector<FSPoserAnimator::FSPoserJoint*> jointsRecaptured);
/// <summary>
/// Add a new posing state, or updates the matching posing state with the supplied data.
/// </summary>
/// <param name="avatar">The avatar the posing state is intended for.</param>
/// <param name="animId">The ID of the animation.</param>
/// <param name="updateTime">The frame-time of the animation.</param>
/// <param name="jointNames">The names of the joints, if any, the animation should specifically be applied to.</param>
/// <param name="captureOrder">The capture order.</param>
/// <returns>True if the posing state was added or changed by the update data, otherwise false.</returns>
bool addOrUpdatePosingState(LLVOAvatar* avatar, LLUUID animId, F32 updateTime, std::string jointNames, int captureOrder);
/// <summary>
/// Traverses the joints and applies reversals to the base rotations if needed.
/// </summary>

View File

@ -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<fsMotionState>::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)

View File

@ -41,9 +41,6 @@ public:
/// Captures the current animations posing the supplied avatar and how long they have been playing.
/// </summary>
/// <param name="avatar">The avatar whose animations are to be captured.</param>
/// <remarks>
/// Only animations owned by the supplied avatar are documented.
/// </remarks>
void captureMotionStates(LLVOAvatar* avatar);
/// <summary>
@ -54,6 +51,17 @@ public:
/// <param name="jointNamesRecaptured">The names of the joints being recaptured.</param>
void updateMotionStates(LLVOAvatar* avatar, FSPosingMotion* posingMotion, std::string jointNamesRecaptured);
/// <summary>
/// Add a new posing state, or updates the matching posing state with the supplied data.
/// </summary>
/// <param name="avatar">The avatar the posing state is intended for.</param>
/// <param name="animId">The ID of the animation.</param>
/// <param name="updateTime">The frame-time of the animation.</param>
/// <param name="jointNames">The names of the joints, if any, the animation should specifically be applied to.</param>
/// <param name="captureOrder">The capture order.</param>
/// <returns>True if the posing state was added or changed by the update data, otherwise false.</returns>
bool addOrUpdatePosingMotionState(LLVOAvatar* avatar, LLUUID animId, F32 updateTime, std::string jointNames, int captureOrder);
/// <summary>
/// Removes all current animation states for the supplied avatar.
/// </summary>
@ -98,11 +106,6 @@ private:
class fsMotionState
{
public:
/// <summary>
/// The avatar ID this record is associated with.
/// </summary>
LLUUID avatarId;
/// <summary>
/// The motion ID recorded animating the avatar ID.
/// </summary>