From 8a228daeff3e9c503ab2df03e701e3a02b1a4040 Mon Sep 17 00:00:00 2001 From: Angeldark Raymaker Date: Fri, 8 Nov 2024 16:48:44 +0000 Subject: [PATCH] FIRE-34747: Move FSJointPose to own class --- indra/newview/CMakeLists.txt | 1 + indra/newview/fsjointpose.cpp | 284 ++++++++++++++++++++++++++++++ indra/newview/fsjointpose.h | 238 +++++++++++++++++++++++++ indra/newview/fsposeranimator.cpp | 72 ++++---- indra/newview/fsposingmotion.cpp | 252 +------------------------- indra/newview/fsposingmotion.h | 193 +------------------- 6 files changed, 563 insertions(+), 477 deletions(-) create mode 100644 indra/newview/fsjointpose.cpp create mode 100644 indra/newview/fsjointpose.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 58619e6191..c1bb35f1d7 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -139,6 +139,7 @@ set(viewer_SOURCE_FILES fsfloatervramusage.cpp fsfloaterwearablefavorites.cpp fsfloaterwhitelisthelper.cpp + fsjointpose.cpp fskeywords.cpp fslslbridge.cpp fslslbridgerequest.cpp diff --git a/indra/newview/fsjointpose.cpp b/indra/newview/fsjointpose.cpp new file mode 100644 index 0000000000..9c2750590f --- /dev/null +++ b/indra/newview/fsjointpose.cpp @@ -0,0 +1,284 @@ +/** + * @file fsposingmotion.cpp + * @brief Model for posing your (and other) avatar(s). + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (c) 2024 Angeldark Raymaker @ Second Life + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include +#include +#include "fsposingmotion.h" +#include "llcharacter.h" + +constexpr size_t MaximumUndoQueueLength = 20; + +/// +/// The constant time interval, in seconds, specifying whether an 'undo' value should be added. +/// +constexpr std::chrono::duration UndoUpdateInterval = std::chrono::duration(0.3); + +FSJointPose::FSJointPose(LLJoint* joint, U32 usage, bool isCollisionVolume) +{ + mJointState = new LLJointState; + mJointState->setJoint(joint); + mJointState->setUsage(usage); + + mJointName = joint->getName(); + mIsCollisionVolume = isCollisionVolume; + + mBeginningRotation = mTargetRotation = joint->getRotation(); + mBeginningPosition = mTargetPosition = joint->getPosition(); + mBeginningScale = mTargetScale = joint->getScale(); +} + +void FSJointPose::addLastPositionToUndo() +{ + if (mUndonePositionIndex > 0) + { + for (int i = 0; i < mUndonePositionIndex; i++) + mLastSetPositions.pop_front(); + + mUndonePositionIndex = 0; + } + + mLastSetPositions.push_front(mTargetPosition); + + while (mLastSetPositions.size() > MaximumUndoQueueLength) + mLastSetPositions.pop_back(); +} + +void FSJointPose::addLastRotationToUndo() +{ + if (mUndoneRotationIndex > 0) + { + for (int i = 0; i < mUndoneRotationIndex; i++) + mLastSetRotations.pop_front(); + + mUndoneRotationIndex = 0; + } + + mLastSetRotations.push_front(mTargetRotation); + + while (mLastSetRotations.size() > MaximumUndoQueueLength) + mLastSetRotations.pop_back(); +} + +void FSJointPose::addLastScaleToUndo() +{ + if (mUndoneScaleIndex > 0) + { + for (int i = 0; i < mUndoneScaleIndex; i++) + mLastSetScales.pop_front(); + + mUndoneScaleIndex = 0; + } + + mLastSetScales.push_front(mTargetScale); + + while (mLastSetScales.size() > MaximumUndoQueueLength) + mLastSetScales.pop_back(); +} + +LLVector3 FSJointPose::getCurrentPosition() +{ + LLVector3 vec3; + LLJoint* joint = mJointState->getJoint(); + if (!joint) + return vec3; + + vec3 = joint->getPosition(); + return vec3; +} + +void FSJointPose::setTargetPosition(const LLVector3& pos) +{ + auto timeIntervalSinceLastRotationChange = std::chrono::system_clock::now() - mTimeLastUpdatedPosition; + if (timeIntervalSinceLastRotationChange > UndoUpdateInterval) + addLastPositionToUndo(); + + mTimeLastUpdatedPosition = std::chrono::system_clock::now(); + mTargetPosition.set(pos); +} + +LLQuaternion FSJointPose::getCurrentRotation() +{ + LLQuaternion quat; + LLJoint* joint = mJointState->getJoint(); + if (!joint) + return quat; + + quat = joint->getRotation(); + return quat; +} + +void FSJointPose::setTargetRotation(const LLQuaternion& rot) +{ + auto timeIntervalSinceLastRotationChange = std::chrono::system_clock::now() - mTimeLastUpdatedRotation; + if (timeIntervalSinceLastRotationChange > UndoUpdateInterval) + addLastRotationToUndo(); + + mTimeLastUpdatedRotation = std::chrono::system_clock::now(); + mTargetRotation.set(rot); +} + +void FSJointPose::applyDeltaRotation(const LLQuaternion& rot) +{ + auto timeIntervalSinceLastRotationChange = std::chrono::system_clock::now() - mTimeLastUpdatedRotation; + if (timeIntervalSinceLastRotationChange > UndoUpdateInterval) + addLastRotationToUndo(); + + mTimeLastUpdatedRotation = std::chrono::system_clock::now(); + mTargetRotation = mTargetRotation * rot; +} + +LLVector3 FSJointPose::getCurrentScale() +{ + LLVector3 vec3; + LLJoint* joint = mJointState->getJoint(); + if (!joint) + return vec3; + + vec3 = joint->getScale(); + return vec3; +} + +void FSJointPose::setTargetScale(LLVector3 scale) +{ + auto timeIntervalSinceLastScaleChange = std::chrono::system_clock::now() - mTimeLastUpdatedScale; + if (timeIntervalSinceLastScaleChange > UndoUpdateInterval) + addLastScaleToUndo(); + + mTimeLastUpdatedScale = std::chrono::system_clock::now(); + mTargetScale.set(scale); +} + +void FSJointPose::undoLastPositionSet() +{ + if (mLastSetPositions.empty()) + return; + + if (mUndonePositionIndex == 0) // at the top of the queue add the current + addLastPositionToUndo(); + + mUndonePositionIndex++; + mUndonePositionIndex = llclamp(mUndonePositionIndex, 0, mLastSetPositions.size() - 1); + mTargetPosition.set(mLastSetPositions[mUndonePositionIndex]); +} + +void FSJointPose::redoLastPositionSet() +{ + if (mLastSetPositions.empty()) + return; + + mUndonePositionIndex--; + mUndonePositionIndex = llclamp(mUndonePositionIndex, 0, mLastSetPositions.size() - 1); + + mTargetPosition.set(mLastSetPositions[mUndonePositionIndex]); + if (mUndonePositionIndex == 0) + mLastSetPositions.pop_front(); +} + +void FSJointPose::undoLastRotationSet() +{ + if (mLastSetRotations.empty()) + return; + + if (mUndoneRotationIndex == 0) // at the top of the queue add the current + addLastRotationToUndo(); + + mUndoneRotationIndex++; + mUndoneRotationIndex = llclamp(mUndoneRotationIndex, 0, mLastSetRotations.size() - 1); + mTargetRotation.set(mLastSetRotations[mUndoneRotationIndex]); +} + +void FSJointPose::redoLastRotationSet() +{ + if (mLastSetRotations.empty()) + return; + + mUndoneRotationIndex--; + mUndoneRotationIndex = llclamp(mUndoneRotationIndex, 0, mLastSetRotations.size() - 1); + + mTargetRotation.set(mLastSetRotations[mUndoneRotationIndex]); + if (mUndoneRotationIndex == 0) + mLastSetRotations.pop_front(); +} + +void FSJointPose::undoLastScaleSet() +{ + if (mLastSetScales.empty()) + return; + + if (mUndoneScaleIndex == 0) + addLastScaleToUndo(); + + mUndoneScaleIndex++; + mUndoneScaleIndex = llclamp(mUndoneScaleIndex, 0, mLastSetScales.size() - 1); + mTargetScale.set(mLastSetScales[mUndoneScaleIndex]); +} + +void FSJointPose::redoLastScaleSet() +{ + if (mLastSetScales.empty()) + return; + + mUndoneScaleIndex--; + mUndoneScaleIndex = llclamp(mUndoneScaleIndex, 0, mLastSetScales.size() - 1); + + mTargetScale.set(mLastSetScales[mUndoneScaleIndex]); + if (mUndoneScaleIndex == 0) + mLastSetScales.pop_front(); +} + +void FSJointPose::revertJointScale() +{ + LLJoint* joint = mJointState->getJoint(); + if (!joint) + return; + + joint->setScale(mBeginningScale); +} + +void FSJointPose::revertJointPosition() +{ + LLJoint* joint = mJointState->getJoint(); + if (!joint) + return; + + joint->setPosition(mBeginningPosition); +} + +void FSJointPose::revertCollisionVolume() +{ + if (!mIsCollisionVolume) + return; + + LLJoint* joint = mJointState->getJoint(); + if (!joint) + return; + + joint->setRotation(mBeginningRotation); + joint->setPosition(mBeginningPosition); + joint->setScale(mBeginningScale); +} + +void FSJointPose::setJointStartRotations(LLQuaternion quat) { mBeginningRotation = mTargetRotation = quat; } diff --git a/indra/newview/fsjointpose.h b/indra/newview/fsjointpose.h new file mode 100644 index 0000000000..16fc6f8a90 --- /dev/null +++ b/indra/newview/fsjointpose.h @@ -0,0 +1,238 @@ +/** + * @file fsjointpose.h + * @brief Container for the pose of a joint. + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (c) 2024 Angeldark Raymaker @ Second Life + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef FS_JOINTPPOSE_H +#define FS_JOINTPPOSE_H + +//----------------------------------------------------------------------------- +// Header files +//----------------------------------------------------------------------------- +#include "llmotion.h" + +//----------------------------------------------------------------------------- +// class FSJointPose +//----------------------------------------------------------------------------- +class FSJointPose +{ + public: + /// + /// A class encapsulating the positions/rotations for a joint. + /// + /// The joint this joint pose represents. + /// The default usage the joint should have in a pose. + /// Whether the supplied joint is a collision volume. + FSJointPose(LLJoint* joint, U32 usage, bool isCollisionVolume = false); + + /// + /// Gets the name of the joint. + /// + std::string jointName() const { return mJointName; } + + /// + /// Gets whether this represents a collision volume. + /// + /// true if the joint is a collision volume, otherwise false. + bool isCollisionVolume() const { return mIsCollisionVolume; } + + /// + /// Adds a last rotation to the deque. + /// + void addLastRotationToUndo(); + + /// + /// Gets whether a redo of this joints rotation may be performed. + /// + /// true if the joint can have a redo applied, otherwise false. + bool canRedoRotation() const { return mUndoneRotationIndex > 0; } + + /// + /// Gets the position the joint was in when the animation was initialized. + /// + LLVector3 getBeginningPosition() const { return mBeginningPosition; } + + /// + /// Gets the position the animator wishes the joint to be in. + /// + LLVector3 getTargetPosition() const { return mTargetPosition; } + + /// + /// Gets the position the animator wishes the joint to be in. + /// + LLVector3 getCurrentPosition(); + + /// + /// Sets the position the animator wishes the joint to be in. + /// + void setTargetPosition(const LLVector3& pos); + + /// + /// Adds a last position to the deque. + /// + void addLastPositionToUndo(); + + /// + /// Undoes the last position set, if any. + /// + void undoLastPositionSet(); + + /// + /// Undoes the last position set, if any. + /// + void redoLastPositionSet(); + + /// + /// Gets the rotation the joint was in when the animation was initialized. + /// + LLQuaternion getBeginningRotation() const { return mBeginningRotation; } + + /// + /// Gets the rotation the animator wishes the joint to be in. + /// + LLQuaternion getTargetRotation() const { return mTargetRotation; } + + /// + /// Gets the rotation of the joint. + /// + LLQuaternion getCurrentRotation(); + + /// + /// Sets the beginning and target rotations to the supplied rotation. + /// + void setJointStartRotations(LLQuaternion quat); + + /// + /// Sets the rotation the animator wishes the joint to be in. + /// + void setTargetRotation(const LLQuaternion& rot); + + /// + /// Applies a delta to the rotation the joint currently targets. + /// + void applyDeltaRotation(const LLQuaternion& rot); + + /// + /// Undoes the last rotation set, if any. + /// Ordinarily the queue does not contain the current rotation, because we rely on time to add, and not button-up. + /// When we undo, if we are at the top of the queue, we need to add the current rotation so we can redo back to it. + /// Thus when we start undoing, mUndoneRotationIndex points at the current rotation. + /// + void undoLastRotationSet(); + + /// + /// Redoes the last rotation set, if any. + /// + void redoLastRotationSet(); + + /// + /// Gets the scale the animator wishes the joint to have. + /// + LLVector3 getTargetScale() const { return mTargetScale; } + + /// + /// Gets the scale the joint has. + /// + LLVector3 getCurrentScale(); + + /// + /// Gets the scale the joint had when the animation was initialized. + /// + LLVector3 getBeginningScale() const { return mBeginningScale; } + + /// + /// Sets the scale the animator wishes the joint to have. + /// + void setTargetScale(LLVector3 scale); + + /// + /// Undoes the last scale set, if any. + /// + void undoLastScaleSet(); + + /// + /// Redoes the last scale set, if any. + /// + void redoLastScaleSet(); + + /// + /// Adds a last rotation to the deque. + /// + void addLastScaleToUndo(); + + /// + /// Restores the joint represented by this to the scale it had when this motion started. + /// + void revertJointScale(); + + /// + /// Restores the joint represented by this to the position it had when this motion started. + /// + void revertJointPosition(); + + /// + /// Collision Volumes do not 'reset' their position/rotation when the animation stops. + /// This requires special treatment to revert changes we've made this animation session. + /// + void revertCollisionVolume(); + + /// + /// Gets the pointer to the jointstate for the joint this represents. + /// + LLPointer getJointState() const { return mJointState; } + +private: + std::string mJointName = ""; // expected to be a match to LLJoint.getName() for a joint implementation. + LLPointer mJointState{ nullptr }; + + /// + /// Collision Volumes require special treatment when we stop animating an avatar, as they do not revert to their original state + /// natively. + /// + bool mIsCollisionVolume{ false }; + + LLQuaternion mTargetRotation; + LLQuaternion mBeginningRotation; + std::deque mLastSetRotations; + size_t mUndoneRotationIndex = 0; + std::chrono::system_clock::time_point mTimeLastUpdatedRotation = std::chrono::system_clock::now(); + + LLVector3 mTargetPosition; + LLVector3 mBeginningPosition; + std::deque mLastSetPositions; + size_t mUndonePositionIndex = 0; + std::chrono::system_clock::time_point mTimeLastUpdatedPosition = std::chrono::system_clock::now(); + + /// + /// Joint scales require special treatment, as they do not revert when we stop animating an avatar. + /// + LLVector3 mTargetScale; + LLVector3 mBeginningScale; + std::deque mLastSetScales; + size_t mUndoneScaleIndex = 0; + std::chrono::system_clock::time_point mTimeLastUpdatedScale = std::chrono::system_clock::now(); +}; + +#endif // FS_JOINTPPOSE_H + diff --git a/indra/newview/fsposeranimator.cpp b/indra/newview/fsposeranimator.cpp index 4f70b19a2f..a678d311ed 100644 --- a/indra/newview/fsposeranimator.cpp +++ b/indra/newview/fsposeranimator.cpp @@ -45,7 +45,7 @@ bool FSPoserAnimator::isPosingAvatarJoint(LLVOAvatar* avatar, const FSPoserJoint if (posingMotion->isStopped()) return false; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return false; @@ -68,7 +68,7 @@ void FSPoserAnimator::setPosingAvatarJoint(LLVOAvatar* avatar, const FSPoserJoin if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -90,7 +90,7 @@ void FSPoserAnimator::resetAvatarJoint(LLVOAvatar* avatar, const FSPoserJoint& j if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -110,7 +110,7 @@ void FSPoserAnimator::undoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoi if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -119,7 +119,7 @@ void FSPoserAnimator::undoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoi if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); if (!oppositeJointPose) return; @@ -138,7 +138,7 @@ void FSPoserAnimator::undoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoi if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -147,7 +147,7 @@ void FSPoserAnimator::undoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoi if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); if (!oppositeJointPose) return; @@ -166,7 +166,7 @@ void FSPoserAnimator::undoLastJointScale(LLVOAvatar* avatar, const FSPoserJoint& if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -175,7 +175,7 @@ void FSPoserAnimator::undoLastJointScale(LLVOAvatar* avatar, const FSPoserJoint& if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); if (!oppositeJointPose) return; @@ -194,7 +194,7 @@ void FSPoserAnimator::resetJointPosition(LLVOAvatar* avatar, const FSPoserJoint& if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -203,7 +203,7 @@ void FSPoserAnimator::resetJointPosition(LLVOAvatar* avatar, const FSPoserJoint& if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); if (!oppositeJointPose) return; @@ -222,7 +222,7 @@ void FSPoserAnimator::resetJointScale(LLVOAvatar* avatar, const FSPoserJoint& jo if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -231,7 +231,7 @@ void FSPoserAnimator::resetJointScale(LLVOAvatar* avatar, const FSPoserJoint& jo if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); if (!oppositeJointPose) return; @@ -250,7 +250,7 @@ bool FSPoserAnimator::canRedoJointRotation(LLVOAvatar* avatar, const FSPoserJoin if (posingMotion->isStopped()) return false; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return false; @@ -269,7 +269,7 @@ void FSPoserAnimator::redoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoi if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -278,7 +278,7 @@ void FSPoserAnimator::redoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoi if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); if (!oppositeJointPose) return; @@ -297,7 +297,7 @@ void FSPoserAnimator::redoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoi if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -306,7 +306,7 @@ void FSPoserAnimator::redoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoi if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); if (!oppositeJointPose) return; @@ -325,7 +325,7 @@ void FSPoserAnimator::redoLastJointScale(LLVOAvatar* avatar, const FSPoserJoint& if (posingMotion->isStopped()) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return; @@ -334,7 +334,7 @@ void FSPoserAnimator::redoLastJointScale(LLVOAvatar* avatar, const FSPoserJoint& if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName()); if (!oppositeJointPose) return; @@ -351,7 +351,7 @@ LLVector3 FSPoserAnimator::getJointPosition(LLVOAvatar* avatar, const FSPoserJoi if (!posingMotion) return pos; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return pos; @@ -378,7 +378,7 @@ void FSPoserAnimator::setJointPosition(LLVOAvatar* avatar, const FSPoserJoint* j if (!posingMotion) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(jn); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(jn); if (!jointPose) return; @@ -390,7 +390,7 @@ void FSPoserAnimator::setJointPosition(LLVOAvatar* avatar, const FSPoserJoint* j LLVector3 positionDelta = jointPose->getTargetPosition() - position; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); if (!oppositeJointPose) return; @@ -466,7 +466,7 @@ void FSPoserAnimator::setStartingJointRotation(LLVOAvatar* avatar, const FSPoser if (!posingMotion) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); if (!jointPose) return; @@ -484,7 +484,7 @@ LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar* avatar, const FSPoserJoi if (!posingMotion) return vec3; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return vec3; @@ -516,7 +516,7 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* j if (!posingMotion) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); if (!jointPose) return; @@ -538,7 +538,7 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* j return; } - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); if (!oppositeJointPose) return; @@ -571,11 +571,11 @@ void FSPoserAnimator::reflectJoint(LLVOAvatar* avatar, const FSPoserJoint* joint if (!posingMotion) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); if (!jointPose) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); if (!oppositeJointPose) { LLQuaternion rot_quat = jointPose->getTargetRotation(); @@ -735,7 +735,7 @@ LLVector3 FSPoserAnimator::getJointScale(LLVOAvatar* avatar, const FSPoserJoint& if (!posingMotion) return scale; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return scale; @@ -762,7 +762,7 @@ void FSPoserAnimator::setJointScale(LLVOAvatar* avatar, const FSPoserJoint* join if (!posingMotion) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(jn); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(jn); if (!jointPose) return; @@ -771,7 +771,7 @@ void FSPoserAnimator::setJointScale(LLVOAvatar* avatar, const FSPoserJoint* join if (style == NONE) return; - FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); if (!oppositeJointPose) return; @@ -790,7 +790,7 @@ bool FSPoserAnimator::tryGetJointSaveVectors(LLVOAvatar* avatar, const FSPoserJo if (!posingMotion) return false; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); if (!jointPose) return false; @@ -811,7 +811,7 @@ void FSPoserAnimator::loadJointRotation(LLVOAvatar* avatar, const FSPoserJoint* if (!posingMotion) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); if (!jointPose) return; @@ -828,7 +828,7 @@ void FSPoserAnimator::loadJointPosition(LLVOAvatar* avatar, const FSPoserJoint* if (!posingMotion) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); if (!jointPose) return; @@ -847,7 +847,7 @@ void FSPoserAnimator::loadJointScale(LLVOAvatar* avatar, const FSPoserJoint* joi if (!posingMotion) return; - FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); if (!jointPose) return; diff --git a/indra/newview/fsposingmotion.cpp b/indra/newview/fsposingmotion.cpp index f0f37a1455..07916ef9c4 100644 --- a/indra/newview/fsposingmotion.cpp +++ b/indra/newview/fsposingmotion.cpp @@ -48,7 +48,7 @@ LLMotion::LLMotionInitStatus FSPosingMotion::onInitialize(LLCharacter *character if (!targetJoint) continue; - FSJointPose jointPose = FSJointPose(targetJoint); + FSJointPose jointPose = FSJointPose(targetJoint, POSER_JOINT_STATE); mJointPoses.push_back(jointPose); addJointState(jointPose.getJointState()); @@ -213,7 +213,7 @@ void FSPosingMotion::setJointState(LLJoint* joint, U32 state) addJointState(jointPose->getJointState()); } -FSPosingMotion::FSJointPose* FSPosingMotion::getJointPoseByJointName(const std::string& name) +FSJointPose* FSPosingMotion::getJointPoseByJointName(const std::string& name) { if (mJointPoses.size() < 1) return nullptr; @@ -285,251 +285,3 @@ constexpr size_t MaximumUndoQueueLength = 20; /// The constant time interval, in seconds, specifying whether an 'undo' value should be added. /// constexpr std::chrono::duration UndoUpdateInterval = std::chrono::duration(0.3); - - -void FSPosingMotion::FSJointPose::addLastPositionToUndo() -{ - if (mUndonePositionIndex > 0) - { - for (int i = 0; i < mUndonePositionIndex; i++) - mLastSetPositions.pop_front(); - - mUndonePositionIndex = 0; - } - - mLastSetPositions.push_front(mTargetPosition); - - while (mLastSetPositions.size() > MaximumUndoQueueLength) - mLastSetPositions.pop_back(); -} - -void FSPosingMotion::FSJointPose::addLastRotationToUndo() -{ - if (mUndoneRotationIndex > 0) - { - for (int i = 0; i < mUndoneRotationIndex; i++) - mLastSetRotations.pop_front(); - - mUndoneRotationIndex = 0; - } - - mLastSetRotations.push_front(mTargetRotation); - - while (mLastSetRotations.size() > MaximumUndoQueueLength) - mLastSetRotations.pop_back(); -} - -void FSPosingMotion::FSJointPose::addLastScaleToUndo() -{ - if (mUndoneScaleIndex > 0) - { - for (int i = 0; i < mUndoneScaleIndex; i++) - mLastSetScales.pop_front(); - - mUndoneScaleIndex = 0; - } - - mLastSetScales.push_front(mTargetScale); - - while (mLastSetScales.size() > MaximumUndoQueueLength) - mLastSetScales.pop_back(); -} - -LLVector3 FSPosingMotion::FSJointPose::getCurrentPosition() -{ - LLVector3 vec3; - LLJoint* joint = mJointState->getJoint(); - if (!joint) - return vec3; - - vec3 = joint->getPosition(); - return vec3; -} - -void FSPosingMotion::FSJointPose::setTargetPosition(const LLVector3& pos) -{ - auto timeIntervalSinceLastRotationChange = std::chrono::system_clock::now() - mTimeLastUpdatedPosition; - if (timeIntervalSinceLastRotationChange > UndoUpdateInterval) - addLastPositionToUndo(); - - mTimeLastUpdatedPosition = std::chrono::system_clock::now(); - mTargetPosition.set(pos); -} - -LLQuaternion FSPosingMotion::FSJointPose::getCurrentRotation() -{ - LLQuaternion quat; - LLJoint* joint = mJointState->getJoint(); - if (!joint) - return quat; - - quat = joint->getRotation(); - return quat; -} - -void FSPosingMotion::FSJointPose::setTargetRotation(const LLQuaternion& rot) -{ - auto timeIntervalSinceLastRotationChange = std::chrono::system_clock::now() - mTimeLastUpdatedRotation; - if (timeIntervalSinceLastRotationChange > UndoUpdateInterval) - addLastRotationToUndo(); - - mTimeLastUpdatedRotation = std::chrono::system_clock::now(); - mTargetRotation.set(rot); -} - -void FSPosingMotion::FSJointPose::applyDeltaRotation(const LLQuaternion& rot) -{ - auto timeIntervalSinceLastRotationChange = std::chrono::system_clock::now() - mTimeLastUpdatedRotation; - if (timeIntervalSinceLastRotationChange > UndoUpdateInterval) - addLastRotationToUndo(); - - mTimeLastUpdatedRotation = std::chrono::system_clock::now(); - mTargetRotation = mTargetRotation * rot; -} - -LLVector3 FSPosingMotion::FSJointPose::getCurrentScale() -{ - LLVector3 vec3; - LLJoint* joint = mJointState->getJoint(); - if (!joint) - return vec3; - - vec3 = joint->getScale(); - return vec3; -} - -void FSPosingMotion::FSJointPose::setTargetScale(LLVector3 scale) -{ - auto timeIntervalSinceLastScaleChange = std::chrono::system_clock::now() - mTimeLastUpdatedScale; - if (timeIntervalSinceLastScaleChange > UndoUpdateInterval) - addLastScaleToUndo(); - - mTimeLastUpdatedScale = std::chrono::system_clock::now(); - mTargetScale.set(scale); -} - -void FSPosingMotion::FSJointPose::undoLastPositionSet() -{ - if (mLastSetPositions.empty()) - return; - - if (mUndonePositionIndex == 0) // at the top of the queue add the current - addLastPositionToUndo(); - - mUndonePositionIndex++; - mUndonePositionIndex = llclamp(mUndonePositionIndex, 0, mLastSetPositions.size() - 1); - mTargetPosition.set(mLastSetPositions[mUndonePositionIndex]); -} - -void FSPosingMotion::FSJointPose::redoLastPositionSet() -{ - if (mLastSetPositions.empty()) - return; - - mUndonePositionIndex--; - mUndonePositionIndex = llclamp(mUndonePositionIndex, 0, mLastSetPositions.size() - 1); - - mTargetPosition.set(mLastSetPositions[mUndonePositionIndex]); - if (mUndonePositionIndex == 0) - mLastSetPositions.pop_front(); -} - -void FSPosingMotion::FSJointPose::undoLastRotationSet() -{ - if (mLastSetRotations.empty()) - return; - - if (mUndoneRotationIndex == 0) // at the top of the queue add the current - addLastRotationToUndo(); - - mUndoneRotationIndex++; - mUndoneRotationIndex = llclamp(mUndoneRotationIndex, 0, mLastSetRotations.size() - 1); - mTargetRotation.set(mLastSetRotations[mUndoneRotationIndex]); -} - -void FSPosingMotion::FSJointPose::redoLastRotationSet() -{ - if (mLastSetRotations.empty()) - return; - - mUndoneRotationIndex--; - mUndoneRotationIndex = llclamp(mUndoneRotationIndex, 0, mLastSetRotations.size() - 1); - - mTargetRotation.set(mLastSetRotations[mUndoneRotationIndex]); - if (mUndoneRotationIndex == 0) - mLastSetRotations.pop_front(); -} - -void FSPosingMotion::FSJointPose::undoLastScaleSet() -{ - if (mLastSetScales.empty()) - return; - - if (mUndoneScaleIndex == 0) - addLastScaleToUndo(); - - mUndoneScaleIndex++; - mUndoneScaleIndex = llclamp(mUndoneScaleIndex, 0, mLastSetScales.size() - 1); - mTargetScale.set(mLastSetScales[mUndoneScaleIndex]); -} - -void FSPosingMotion::FSJointPose::redoLastScaleSet() -{ - if (mLastSetScales.empty()) - return; - - mUndoneScaleIndex--; - mUndoneScaleIndex = llclamp(mUndoneScaleIndex, 0, mLastSetScales.size() - 1); - - mTargetScale.set(mLastSetScales[mUndoneScaleIndex]); - if (mUndoneScaleIndex == 0) - mLastSetScales.pop_front(); -} - -void FSPosingMotion::FSJointPose::revertJointScale() -{ - LLJoint* joint = mJointState->getJoint(); - if (!joint) - return; - - joint->setScale(mBeginningScale); -} - -void FSPosingMotion::FSJointPose::revertJointPosition() -{ - LLJoint* joint = mJointState->getJoint(); - if (!joint) - return; - - joint->setPosition(mBeginningPosition); -} - -void FSPosingMotion::FSJointPose::revertCollisionVolume() -{ - if (!mIsCollisionVolume) - return; - - LLJoint* joint = mJointState->getJoint(); - if (!joint) - return; - - joint->setRotation(mBeginningRotation); - joint->setPosition(mBeginningPosition); - joint->setScale(mBeginningScale); -} - -void FSPosingMotion::FSJointPose::setJointStartRotations(LLQuaternion quat) { mBeginningRotation = mTargetRotation = quat; } - -FSPosingMotion::FSJointPose::FSJointPose(LLJoint* joint, bool isCollisionVolume) -{ - mJointState = new LLJointState; - mJointState->setJoint(joint); - mJointState->setUsage(POSER_JOINT_STATE); - - mJointName = joint->getName(); - mIsCollisionVolume = isCollisionVolume; - - mBeginningRotation = mTargetRotation = joint->getRotation(); - mBeginningPosition = mTargetPosition = joint->getPosition(); - mBeginningScale = mTargetScale = joint->getScale(); -} diff --git a/indra/newview/fsposingmotion.h b/indra/newview/fsposingmotion.h index c20f3b07c2..5c4d97c579 100644 --- a/indra/newview/fsposingmotion.h +++ b/indra/newview/fsposingmotion.h @@ -1,5 +1,5 @@ /** - * @file fsposingmotion.cpp + * @file fsposingmotion.h * @brief Model for posing your (and other) avatar(s). * * $LicenseInfo:firstyear=2024&license=viewerlgpl$ @@ -31,6 +31,7 @@ // Header files //----------------------------------------------------------------------------- #include "llmotion.h" +#include "fsjointpose.h" #define MIN_REQUIRED_PIXEL_AREA_POSING 500.f @@ -47,195 +48,6 @@ public: public: static LLMotion *create(const LLUUID &id) { return new FSPosingMotion(id); } - /// - /// A class encapsulating the positions/rotations for a joint. - /// - class FSJointPose - { - std::string mJointName = ""; // expected to be a match to LLJoint.getName() for a joint implementation. - LLPointer mJointState{ nullptr }; - - /// - /// Collision Volumes require special treatment when we stop animating an avatar, as they do not revert to their original state natively. - /// - bool mIsCollisionVolume{ false }; - - LLQuaternion mTargetRotation; - LLQuaternion mBeginningRotation; - std::deque mLastSetRotations; - size_t mUndoneRotationIndex = 0; - std::chrono::system_clock::time_point mTimeLastUpdatedRotation = std::chrono::system_clock::now(); - - LLVector3 mTargetPosition; - LLVector3 mBeginningPosition; - std::deque mLastSetPositions; - size_t mUndonePositionIndex = 0; - std::chrono::system_clock::time_point mTimeLastUpdatedPosition = std::chrono::system_clock::now(); - - /// - /// Joint scales require special treatment, as they do not revert when we stop animating an avatar. - /// - LLVector3 mTargetScale; - LLVector3 mBeginningScale; - std::deque mLastSetScales; - size_t mUndoneScaleIndex = 0; - std::chrono::system_clock::time_point mTimeLastUpdatedScale = std::chrono::system_clock::now(); - - /// - /// Adds a last position to the deque. - /// - void addLastPositionToUndo(); - - /// - /// Adds a last rotation to the deque. - /// - void addLastRotationToUndo(); - - /// - /// Adds a last rotation to the deque. - /// - void addLastScaleToUndo(); - - public: - /// - /// Gets the name of the joint. - /// - std::string jointName() const { return mJointName; } - - /// - /// Gets whether this represents a collision volume. - /// - /// - bool isCollisionVolume() const { return mIsCollisionVolume; } - - /// - /// Gets whether a redo of this joints rotation may be performed. - /// - /// - bool canRedoRotation() const { return mUndoneRotationIndex > 0; } - - /// - /// Gets the position the joint was in when the animation was initialized. - /// - LLVector3 getBeginningPosition() const { return mBeginningPosition; } - - /// - /// Gets the position the animator wishes the joint to be in. - /// - LLVector3 getTargetPosition() const { return mTargetPosition; } - - /// - /// Gets the position the animator wishes the joint to be in. - /// - LLVector3 getCurrentPosition(); - - /// - /// Sets the position the animator wishes the joint to be in. - /// - void setTargetPosition(const LLVector3& pos); - - /// - /// Gets the rotation the joint was in when the animation was initialized. - /// - LLQuaternion getBeginningRotation() const { return mBeginningRotation; } - - /// - /// Gets the rotation the animator wishes the joint to be in. - /// - LLQuaternion getTargetRotation() const { return mTargetRotation; } - - /// - /// Gets the rotation of the joint. - /// - LLQuaternion getCurrentRotation(); - - /// - /// Sets the rotation the animator wishes the joint to be in. - /// - void setTargetRotation(const LLQuaternion& rot); - - /// - /// Applies a delta to the rotation the joint currently targets. - /// - void applyDeltaRotation(const LLQuaternion& rot); - - /// - /// Gets the scale the animator wishes the joint to have. - /// - LLVector3 getTargetScale() const { return mTargetScale; } - - /// - /// Gets the scale the joint has. - /// - LLVector3 getCurrentScale(); - - /// - /// Gets the scale the joint had when the animation was initialized. - /// - LLVector3 getBeginningScale() const { return mBeginningScale; } - - /// - /// Sets the scale the animator wishes the joint to have. - /// - void setTargetScale(LLVector3 scale); - - /// - /// Undoes the last position set, if any. - /// - void undoLastPositionSet(); - - /// - /// Undoes the last position set, if any. - /// - void redoLastPositionSet(); - - /// - /// Undoes the last rotation set, if any. - /// Ordinarily the queue does not contain the current rotation, because we rely on time to add, and not button-up. - /// When we undo, if we are at the top of the queue, we need to add the current rotation so we can redo back to it. - /// Thus when we start undoing, mUndoneRotationIndex points at the current rotation. - /// - void undoLastRotationSet(); - - /// - /// Undoes the last rotation set, if any. - /// - void redoLastRotationSet(); - - void undoLastScaleSet(); - - void redoLastScaleSet(); - - /// - /// Restores the joint represented by this to the scale it had when this motion started. - /// - void revertJointScale(); - - /// - /// Restores the joint represented by this to the position it had when this motion started. - /// - void revertJointPosition(); - - /// - /// Collision Volumes do not 'reset' their position/rotation when the animation stops. - /// This requires special treatment to revert changes we've made this animation session. - /// - void revertCollisionVolume(); - - /// - /// Sets the beginning and target rotations to the supplied rotation. - /// - void setJointStartRotations(LLQuaternion quat); - - /// - /// Gets the pointer to the jointstate for the joint this represents. - /// - LLPointer getJointState() const { return mJointState; } - - FSJointPose(LLJoint* joint, bool isCollisionVolume = false); - }; - -public: virtual bool getLoop() { return true; } virtual F32 getDuration() { return 0.0; } @@ -366,4 +178,3 @@ private: }; #endif // FS_POSINGMOTION_H -