diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 8118752bfc..b8799c2570 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -169,6 +169,16 @@ public: S32 mJointNum; + // [FIRE-30873]: Poser + LLQuaternion mNextRotation; + LLQuaternion mTargetRotation; + LLQuaternion mLastRotation; + LLVector3 mNextPosition; + LLVector3 mTargetPosition; + LLVector3 mLastPosition; + bool mHasPosition; + // + // child joints typedef std::vector joints_t; joints_t mChildren; @@ -284,6 +294,29 @@ public: const LLVector3& getScale(); void setScale( const LLVector3& scale, bool apply_attachment_overrides = false ); + // [FIRE-30873]: Poser + void setTargetPosition(const LLVector3 &pos) { mTargetPosition = pos; } + LLVector3 getTargetPosition() const { return mTargetPosition; } + + void setTargetRotation(const LLQuaternion &rot) { mTargetRotation = rot; } + LLQuaternion getTargetRotation() const { return mTargetRotation; } + + void setLastPosition(const LLVector3 &pos) { mLastPosition = pos; } + LLVector3 getLastPosition() const { return mLastPosition; } + + void setLastRotation(const LLQuaternion &rot) { mLastRotation = rot; } + LLQuaternion getLastRotation() const { return mLastRotation; } + + void setCanReposition(const bool can_reposition) { mHasPosition = can_reposition; } + bool canReposition() const { return mHasPosition; } + + void setNextPosition(const LLVector3 &pos) { mNextPosition = pos; } + LLVector3 getNextPosition() const { return mNextPosition; } + + void setNextRotation(const LLQuaternion &rot) { mNextRotation = rot; } + LLQuaternion getNextRotation() const { return mNextRotation; } + // + // get/set world matrix const LLMatrix4 &getWorldMatrix(); void setWorldMatrix( const LLMatrix4& mat ); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 5a50e75b1f..b7bd154964 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -91,6 +91,7 @@ set(viewer_SOURCE_FILES ao.cpp aoengine.cpp aoset.cpp + bdposingmotion.cpp chatbar_as_cmdline.cpp daeexport.cpp dialogstack.cpp diff --git a/indra/newview/bdposingmotion.cpp b/indra/newview/bdposingmotion.cpp new file mode 100644 index 0000000000..618113ad04 --- /dev/null +++ b/indra/newview/bdposingmotion.cpp @@ -0,0 +1,220 @@ +/** +* +* Copyright (C) 2018, NiranV Dean +* +* 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. +* +*/ + +#include "linden_common.h" +#include "llviewerprecompiledheaders.h" +#include "bdposingmotion.h" +#include "llcharacter.h" +#include "llviewercontrol.h" + +BDPosingMotion::BDPosingMotion(const LLUUID &id) : +LLMotion(id), + mCharacter(NULL), + mTargetJoint(NULL) +{ + mName = "custom_pose"; + //BD - Use slight spherical linear interpolation by default. + mInterpolationTime = 0.25f; + mInterpolationType = 2; + + for (auto& entry : mJointState) + entry = new LLJointState; +} + +BDPosingMotion::~BDPosingMotion() {} + +LLMotion::LLMotionInitStatus BDPosingMotion::onInitialize(LLCharacter *character) +{ + // save character for future use + mCharacter = character; + + for (S32 i = 0; (mTargetJoint = mCharacter->getCharacterJoint(i)); ++i) // this seems poorly constrained + { + mJointState[i]->setJoint(mTargetJoint); + mJointState[i]->setUsage(LLJointState::POS | LLJointState::ROT /* | LLJointState::SCALE*/); + + addJointState(mJointState[i]); + } + + return STATUS_SUCCESS; +} + +bool BDPosingMotion::onActivate() +{ + for (auto joint_state : mJointState) + { + LLJoint* joint = joint_state->getJoint(); + if (!joint) + continue; + + joint->setTargetRotation(joint->getRotation()); + joint->setTargetPosition(joint->getPosition()); + } + + return true; +} + +bool BDPosingMotion::onUpdate(F32 time, U8* joint_mask) +{ + LLQuaternion target_quat; + LLQuaternion joint_quat; + LLQuaternion last_quat; + LLQuaternion next_quat; + LLVector3 joint_pos; + LLVector3 last_pos; + LLVector3 target_pos; + LLVector3 next_pos; + F32 perc = 0.0f; + + for (auto joint_state : mJointState) + { + LLJoint* joint = joint_state->getJoint(); + if (!joint) + continue; + + target_quat = joint->getTargetRotation(); + joint_quat = joint->getRotation(); + last_quat = joint->getLastRotation(); + + //BD - Merge these two together? + perc = llclamp(mInterpolationTimer.getElapsedTimeF32() / mInterpolationTime, 0.0f, 1.0f); + //BD - All bones support positions now. + joint_pos = joint->getPosition(); + target_pos = joint->getTargetPosition(); + last_pos = joint->getLastPosition(); + if (target_pos != joint_pos) + { + if (mInterpolationType == 2) + { + //BD - Do spherical linear interpolation. + // We emulate the spherical linear interpolation here because + // slerp() does not support LLVector3. mInterpolationTime is always + // in a range between 0.00 and 1.00 which makes it perfect to use + // as percentage directly. + // We use the current joint position rather than the original like + // in linear interpolation to take a fraction of the fraction, this + // re-creates spherical linear interpolation's behavior. + joint_pos = lerp(joint_pos, target_pos, mInterpolationTime); + } + else if (mInterpolationType == 3) + { + next_pos = joint->getNextPosition(); + //BD - Do curve interpolation. + // This is a special kind of interpolation where we interpolate towards + // a "middle" pose to a given degree while on our way to the actual final + // pose. + joint_pos = lerp(joint_pos, next_pos, perc); + joint_pos = lerp(joint_pos, target_pos, 0.5f - abs(0.5f - perc)); + } + else + { + if (perc >= 1.0f) + { + //BD - Can be used to do no interpolation too. + joint_pos = target_pos; + last_pos = joint_pos; + } + else + { + //BD - Do linear interpolation. + joint_pos = lerp(last_pos, target_pos, perc); + } + } + joint_state->setPosition(joint_pos); + } + + if (target_quat != joint_quat) + { + if (mInterpolationType == 2) + { + //BD - Do spherical linear interpolation. + joint_quat = slerp(mInterpolationTime, joint_quat, target_quat); + } + else if (mInterpolationType == 3) + { + next_pos = joint->getNextPosition(); + //BD - Do curve interpolation. + // This is a special kind of interpolation where we interpolate towards + // a "middle" pose to a given degree while on our way to the actual final + // pose. + joint_quat = lerp(perc, joint_quat, next_quat); + joint_quat = lerp(0.5f - abs(0.5f - perc), joint_quat, target_quat); + } + else + { + if (perc >= 1.0f) + { + //BD - Can be used to do no interpolation too. + joint_quat = target_quat; + last_quat = joint_quat; + } + else + { + //BD - Do linear interpolation. + joint_quat = lerp(perc, last_quat, target_quat); + } + } + joint_state->setRotation(joint_quat); + } + } + + if (perc >= 1.0f && mInterpolationTimer.getStarted() + && (last_quat == joint_quat + && (last_pos == joint_pos))) + { + mInterpolationTimer.stop(); + } + + return true; +} + +void BDPosingMotion::onDeactivate() {} + +/// +/// Adds the supplied joint to the current animation. +/// +void BDPosingMotion::addJointToState(LLJoint *joint) { setJointState(joint, LLJointState::POS | LLJointState::ROT); } + +void BDPosingMotion::removeJointFromState(LLJoint *joint) { setJointState(joint, 0); } + +void BDPosingMotion::setJointState(LLJoint *joint, U32 state) +{ + if (!joint) + return; + + S32 jointNumber = joint->getJointNum(); + if (jointNumber < 0 || jointNumber >= _numberOfBonesApropoOfNothing) + return; + + mJointState[jointNumber]->setJoint(joint); + mJointState[jointNumber]->setUsage(state); + + addJointState(mJointState[jointNumber]); +} + +bool BDPosingMotion::currentlyPosingJoint(LLJoint* joint) +{ + if (!joint) + return false; + + S32 jointNumber = joint->getJointNum(); + if (jointNumber < 0 || jointNumber >= _numberOfBonesApropoOfNothing) + return false; + + U32 state = mJointState[jointNumber]->getUsage(); + + return (state & LLJointState::POS) && (state & LLJointState::ROT); +} diff --git a/indra/newview/bdposingmotion.h b/indra/newview/bdposingmotion.h new file mode 100644 index 0000000000..eb95304317 --- /dev/null +++ b/indra/newview/bdposingmotion.h @@ -0,0 +1,128 @@ +/** +* +* Copyright (C) 2018, NiranV Dean +* +* 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. +* +*/ + +#ifndef LL_BDPOSINGMOTION_H +#define LL_BDPOSINGMOTION_H + +//----------------------------------------------------------------------------- +// Header files +//----------------------------------------------------------------------------- +#include "llmotion.h" +#include "lljointsolverrp3.h" +#include "v3dmath.h" + +#define MIN_REQUIRED_PIXEL_AREA_POSING 500.f + +//----------------------------------------------------------------------------- +// class BDPosingMotion +//----------------------------------------------------------------------------- +class BDPosingMotion : + public LLMotion +{ +public: + /// + /// Unsure why it is special. Perhaps its a low-priority animation? Perhaps it just needs to be unique? + /// + const LLUUID ANIM_BD_POSING_MOTION = LLUUID("fd29b117-9429-09c4-10cb-933d0b2ab653"); + + BDPosingMotion(const LLUUID &id); + virtual ~BDPosingMotion(); + +public: + //------------------------------------------------------------------------- + // functions to support MotionController and MotionRegistry + //------------------------------------------------------------------------- + + // static constructor + // all subclasses must implement such a function and register it + static LLMotion *create(const LLUUID &id) { return new BDPosingMotion(id); } + +public: + virtual bool getLoop() { return TRUE; } + + virtual F32 getDuration() { return 0.0; } + + virtual F32 getEaseInDuration() { return 0.0f; } + + virtual F32 getEaseOutDuration() { return 0.5f; } + + // motions must report their priority + virtual LLJoint::JointPriority getPriority() { return LLJoint::ADDITIVE_PRIORITY; } + + virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; } + + // called to determine when a motion should be activated/deactivated based on avatar pixel coverage + virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_POSING; } + + // run-time (post constructor) initialization, + // called after parameters have been set + // must return true to indicate success and be available for activation + virtual LLMotionInitStatus onInitialize(LLCharacter *character); + + // called when a motion is activated + // must return TRUE to indicate success, or else + // it will be deactivated + virtual bool onActivate(); + + // called per time step + // must return TRUE while it is active, and + // must return FALSE when the motion is completed. + virtual bool onUpdate(F32 time, U8 *joint_mask); + + // called when a motion is deactivated + virtual void onDeactivate(); + + /// + /// Adds the supplied joint to the current animation-state. + /// + /// The joint to animate. + void addJointToState(LLJoint *joint); + + /// + /// Removes the supplied joint to the current animation-state. + /// + /// The joint to stop animating. + void removeJointFromState(LLJoint *joint); + + void setJointState(LLJoint *joint, U32 state); + + /// + /// Queries whether the supplied joint is being animated. + /// + /// The joint to query. + bool currentlyPosingJoint(LLJoint *joint); + +private: + static const S32 _numberOfBonesApropoOfNothing = 134; + + // BD - functions to set/get our interpolation type + // 0 = None, + // 1 = Linear Interpolatioon, + // 2 = Spherical Linear Interpolation, + // 3 = Curve + S32 mInterpolationType; + F32 mInterpolationTime; + LLFrameTimer mInterpolationTimer; + + LLCharacter *mCharacter; + + LLPointer mJointState[_numberOfBonesApropoOfNothing]; + + LLJoint *mTargetJoint; +}; + +#endif // LL_LLKEYFRAMEMOTION_H + diff --git a/indra/newview/fsfloaterposer.cpp b/indra/newview/fsfloaterposer.cpp index 9ed9cc8452..656f00a703 100644 --- a/indra/newview/fsfloaterposer.cpp +++ b/indra/newview/fsfloaterposer.cpp @@ -334,7 +334,7 @@ bool FSFloaterPoser::savePoseToXml(std::string poseFileName) { std::string bone_name = pj.jointName(); - LLVector3 vec3 = _poserAnimator.getJointRotation(avatar, pj, getJointTranslation(bone_name), getJointNegation(bone_name)); + LLVector3 vec3 = _poserAnimator.getJointRotation(avatar, pj, SWAP_NOTHING, NEGATE_NOTHING); // no swap, it might load into BD; though BD likes interpolation numbers record[bone_name] = pj.jointName(); record[bone_name]["rotation"] = vec3.getValue(); @@ -556,7 +556,7 @@ void FSFloaterPoser::loadPoseFromXml(std::string poseFileName, E_LoadPoseMethods if (loadRotations && control_map.has("rotation")) { vec3.setValue(control_map["rotation"]); - _poserAnimator.setJointRotation(avatar, poserJoint, vec3, NONE, getJointTranslation(name), getJointNegation(name)); // I think if we keep defaults it will load BD poses + _poserAnimator.setJointRotation(avatar, poserJoint, vec3, NONE, SWAP_NOTHING, NEGATE_NOTHING); // If we keep defaults it will load BD poses } if (loadPositions && control_map.has("position")) diff --git a/indra/newview/fsfloaterposer.h b/indra/newview/fsfloaterposer.h index efc1e20082..3d332bc680 100644 --- a/indra/newview/fsfloaterposer.h +++ b/indra/newview/fsfloaterposer.h @@ -144,6 +144,11 @@ class FSFloaterPoser : public LLFloater /// There are several control-callbacks manipulating rotations etc, they all devolve to these. /// In these are the appeals to the posing business layer. /// + /// + /// Using a set, then a get does not guarantee the value you just set. + /// There may be +/- PI difference two axes, because harmonics. + /// Thus keep your UI synced with less gets. + /// void setSelectedJointsRotation(F32 yawInRadians, F32 pitchInRadians, F32 rollInRadians); void setSelectedJointsPosition(F32 x, F32 y, F32 z); void setSelectedJointsScale(F32 x, F32 y, F32 z); @@ -151,6 +156,11 @@ class FSFloaterPoser : public LLFloater /// /// Yeilds the rotation of the first selected joint (one may multi-select). /// + /// + /// Using a set, then a get does not guarantee the value you just set. + /// There may be +/- PI difference two axes, because harmonics. + /// Thus keep your UI synced with less gets. + /// LLVector3 getRotationOfFirstSelectedJoint(); LLVector3 getPositionOfFirstSelectedJoint(); LLVector3 getScaleOfFirstSelectedJoint(); @@ -179,6 +189,9 @@ class FSFloaterPoser : public LLFloater void onAdvancedPositionSet(); void onAdvancedRotationSet(); void onAdvancedScaleSet(); + void onClickToggleSelectedBoneEnabled(); + void onClickRecaptureSelectedBones(); + void onPoseResetMenuAction(const LLSD ¶m); // UI Refreshments void refreshRotationSliders(); diff --git a/indra/newview/fsposeranimator.cpp b/indra/newview/fsposeranimator.cpp index a0cff54a1f..ff39666652 100644 --- a/indra/newview/fsposeranimator.cpp +++ b/indra/newview/fsposeranimator.cpp @@ -33,6 +33,11 @@ #include "llvoavatarself.h" #include +#include "bdposingmotion.h" // BD - Use Black Dragon posing piece + +/// +/// This has turned into a shim-class rather than the business of posing. *shrug* +/// FSPoserAnimator::FSPoserAnimator() {} FSPoserAnimator::~FSPoserAnimator() {} @@ -41,7 +46,15 @@ bool FSPoserAnimator::isPosingAvatarJoint(LLVOAvatar *avatar, FSPoserJoint joint if (!avatar || avatar->isDead()) return false; - return _currentlyPosingSelf; + BDPosingMotion *motion = (BDPosingMotion *) avatar->findMotion(ANIM_BD_POSING_MOTION); + if (!motion || motion->isStopped()) + return false; + + LLJoint *avJoint = gAgentAvatarp->getJoint(JointKey::construct(joint.jointName())); + if (!avJoint) + return false; + + return motion->currentlyPosingJoint(avJoint); } void FSPoserAnimator::setPosingAvatarJoint(LLVOAvatar *avatar, FSPoserJoint joint, bool shouldPose) @@ -49,7 +62,38 @@ void FSPoserAnimator::setPosingAvatarJoint(LLVOAvatar *avatar, FSPoserJoint join if (!avatar || avatar->isDead()) return; - // TODO: Bust a move. Or don't. + bool arePosing = isPosingAvatarJoint(avatar, joint); + if (arePosing && shouldPose || !arePosing && !shouldPose) // could !XOR, but this is readable + return; + + BDPosingMotion *motion = (BDPosingMotion *) avatar->findMotion(ANIM_BD_POSING_MOTION); + if (!motion || motion->isStopped()) + return; + + LLJoint *avJoint = gAgentAvatarp->getJoint(JointKey::construct(joint.jointName())); + if (!avJoint) + return; + + if (shouldPose) + motion->addJointToState(avJoint); + else + motion->removeJointFromState(avJoint); +} + +void FSPoserAnimator::resetAvatarJoint(LLVOAvatar *avatar, FSPoserJoint joint) +{ + if (!avatar || avatar->isDead()) + return; + + BDPosingMotion *motion = (BDPosingMotion *) avatar->findMotion(ANIM_BD_POSING_MOTION); + if (!motion || motion->isStopped()) + return; + + LLJoint *avJoint = gAgentAvatarp->getJoint(JointKey::construct(joint.jointName())); + if (!avJoint) + return; + + // this or something? motion->resetJointState(avJoint); } LLVector3 FSPoserAnimator::getJointPosition(LLVOAvatar *avatar, FSPoserJoint joint) @@ -62,7 +106,7 @@ LLVector3 FSPoserAnimator::getJointPosition(LLVOAvatar *avatar, FSPoserJoint joi if (!avJoint) return pos; - pos = avJoint->getPosition(); + pos = avJoint->getTargetPosition(); return pos; } @@ -82,14 +126,12 @@ void FSPoserAnimator::setJointPosition(LLVOAvatar *avatar, const FSPoserJoint *j LLJoint *avJoint = avatar->getJoint(key); if (!avJoint) return; + + avJoint->setTargetPosition(position); } LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar *avatar, FSPoserJoint joint, E_BoneAxisTranslation translation, S32 negation, bool forRecapture) { - // this needs to do this, to be compatible in some part with BD poses - // LLQuaternion rot = _poserAnimator.getJointRotation(avatar, pj); - // rot.getEulerAngles(&vec3.mV[VX], &vec3.mV[VZ], &vec3.mV[VY]); - LLVector3 vec3; if (!avatar || avatar->isDead()) return vec3; @@ -98,7 +140,7 @@ LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar *avatar, FSPoserJoint joi if (!avJoint) return vec3; - LLQuaternion rot = avJoint->getRotation(); + LLQuaternion rot = forRecapture ? avJoint->getRotation() : avJoint->getTargetRotation(); return translateRotationFromQuaternion(translation, negation, rot); } @@ -116,7 +158,30 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar *avatar, const FSPoserJoint *j return; LLQuaternion rot_quat = translateRotationToQuaternion(translation, negation, rotation); - avJoint->setRotation(rot_quat); + avJoint->setTargetRotation(rot_quat); + + if (style == NONE) + return; + + LLJoint *oppositeJoint = avatar->getJoint(JointKey::construct(joint->mirrorJointName())); + if (!oppositeJoint) + return; + + LLQuaternion inv_quat; + switch (style) + { + case SYMPATHETIC: + oppositeJoint->setTargetRotation(rot_quat); + break; + + case MIRROR: + inv_quat = LLQuaternion(-rot_quat.mQ[VX], rot_quat.mQ[VY], -rot_quat.mQ[VZ], rot_quat.mQ[VW]); + oppositeJoint->setTargetRotation(inv_quat); + break; + + default: + break; + } } // from the UI to the bone, the inverse translation, the un-swap, the backwards @@ -229,6 +294,13 @@ LLVector3 FSPoserAnimator::translateRotationFromQuaternion(E_BoneAxisTranslation LLVector3 FSPoserAnimator::getJointScale(LLVOAvatar *avatar, FSPoserJoint joint) { LLVector3 vec3; + + LLJoint *avJoint = avatar->getJoint(JointKey::construct(joint.jointName())); + if (!avJoint) + return vec3; + + vec3 = avJoint->getScale(); + return vec3; } @@ -238,6 +310,12 @@ void FSPoserAnimator::setJointScale(LLVOAvatar *avatar, const FSPoserJoint *join return; if (!joint) return; + + LLJoint *avJoint = avatar->getJoint(JointKey::construct(joint->jointName())); + if (!avJoint) + return; + + avJoint->setScale(scale); } const FSPoserAnimator::FSPoserJoint* FSPoserAnimator::getPoserJointByName(std::string jointName) @@ -256,24 +334,35 @@ bool FSPoserAnimator::tryPosingAvatar(LLVOAvatar *avatar) if (!avatar || avatar->isDead()) return false; - LLMotion *motion = avatar->findMotion(ANIM_AGENT_TARGET); - gAgent.stopFidget(); - avatar->startDefaultMotions(); - _currentlyPosingSelf = avatar->startMotion(ANIM_AGENT_TARGET); + if (avatar->getPosing()) + return false; - return _currentlyPosingSelf; + BDPosingMotion *motion = (BDPosingMotion *) avatar->findMotion(ANIM_BD_POSING_MOTION); + if (!motion || motion->isStopped()) + { + avatar->setPosing(); + + if (avatar->isSelf()) + gAgent.stopFidget(); + + avatar->startDefaultMotions(); + avatar->startMotion(ANIM_BD_POSING_MOTION); + + // TODO: scrape motion state prior to edit, facilitating reset + + return true; + } + + return false; } void FSPoserAnimator::stopPosingAvatar(LLVOAvatar *avatar) { - if (!_currentlyPosingSelf) - return; if (!avatar || avatar->isDead()) return; - bool result = avatar->stopMotion(ANIM_AGENT_TARGET); - - _currentlyPosingSelf = false; + avatar->clearPosing(); + avatar->stopMotion(ANIM_BD_POSING_MOTION); } bool FSPoserAnimator::isPosingAvatar(LLVOAvatar* avatar) @@ -281,9 +370,13 @@ bool FSPoserAnimator::isPosingAvatar(LLVOAvatar* avatar) if (!avatar || avatar->isDead()) return false; - if (avatar->isSelf()) - return _currentlyPosingSelf; + if (!avatar->getPosing()) + return false; - return false; + BDPosingMotion *motion = (BDPosingMotion *) avatar->findMotion(ANIM_BD_POSING_MOTION); + if (!motion) + return false; + + return !motion->isStopped(); } diff --git a/indra/newview/fsposeranimator.h b/indra/newview/fsposeranimator.h index 6f1fd40ae8..6a09763ca9 100644 --- a/indra/newview/fsposeranimator.h +++ b/indra/newview/fsposeranimator.h @@ -143,8 +143,8 @@ public: {"mPelvis", "", WHOLEAVATAR}, {"mTorso", "", BODY}, {"mChest", "", BODY}, {"mNeck", "", BODY}, {"mHead", "", BODY}, {"mCollarLeft", "mCollarRight", BODY}, {"mShoulderLeft", "mShoulderRight", BODY}, {"mElbowLeft", "mElbowRight", BODY}, {"mWristLeft", "mWristRight", BODY}, {"mCollarRight", "mCollarLeft", BODY}, {"mShoulderRight", "mShoulderLeft", BODY}, {"mElbowRight", "mElbowLeft", BODY}, {"mWristRight", "mWristLeft", BODY}, - {"mHipLeft", "", BODY}, {"mKneeLeft", "", BODY}, {"mAnkleLeft", "", BODY}, - {"mHipRight", "", BODY}, {"mKneeRight", "", BODY}, {"mAnkleRight", "", BODY}, + {"mHipLeft", "mHipRight", BODY}, {"mKneeLeft", "mKneeRight", BODY}, {"mAnkleLeft", "mAnkleRight", BODY}, + {"mHipRight", "mHipLeft", BODY}, {"mKneeRight", "mKneeLeft", BODY}, {"mAnkleRight", "mAnkleLeft", BODY}, // face {"mFaceForeheadLeft", "mFaceForeheadRight", FACE}, {"mFaceForeheadCenter", "", FACE}, {"mFaceForeheadRight", "mFaceForeheadLeft", FACE}, @@ -298,8 +298,6 @@ public: void setJointScale(LLVOAvatar *avatar, const FSPoserJoint *joint, LLVector3 scale, E_BoneDeflectionStyles style); private: - bool _currentlyPosingSelf = false; - /// /// Translates a rotation vector from the UI to a Quaternion for the bone. /// This also performs the axis-swapping the UI needs for up/down/left/right to make sense. diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index c7b2711e89..a9dfe15e0d 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -412,6 +412,8 @@ private: LLUUID mLastChatterID; F32 mNearChatRadius; + bool mIsPosing; // [FIRE-30873]: Poser + //-------------------------------------------------------------------- // Typing //-------------------------------------------------------------------- @@ -425,6 +427,13 @@ public: private: LLFrameTimer mTypingTimer; +// [FIRE-30873]: Poser +public: + void setPosing() { mIsPosing = true; } + void clearPosing() { mIsPosing = false; } + bool getPosing() const { return mIsPosing; } +// [FIRE-30873]: Poser + //-------------------------------------------------------------------- // AFK //-------------------------------------------------------------------- diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b2d6d6e141..38ac664307 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -138,6 +138,10 @@ #include "fsdiscordconnect.h" // tapping a place that happens on landing in world to start up discord +// [FIRE-30873]: Poser +#include "bdposingmotion.h" +// + extern F32 SPEED_ADJUST_MAX; extern F32 SPEED_ADJUST_MAX_SEC; extern F32 ANIM_SPEED_MAX; @@ -173,6 +177,7 @@ const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust" const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"physics_motion" +const LLUUID ANIM_BD_POSING_MOTION = LLUUID("fd29b117-9429-09c4-10cb-933d0b2ab653"); // [FIRE-30873]: Poser: "custom_motion" //----------------------------------------------------------------------------- // Constants @@ -1254,6 +1259,7 @@ void LLVOAvatar::initClass() gAnimLibrary.animStateSetString(ANIM_AGENT_PELVIS_FIX,"pelvis_fix"); gAnimLibrary.animStateSetString(ANIM_AGENT_TARGET,"target"); gAnimLibrary.animStateSetString(ANIM_AGENT_WALK_ADJUST,"walk_adjust"); + gAnimLibrary.animStateSetString(ANIM_BD_POSING_MOTION, "custom_pose"); // [FIRE-30873]: Poser // Where should this be set initially? LLJoint::setDebugJointNames(gSavedSettings.getString("DebugAvatarJoints")); @@ -1376,6 +1382,8 @@ void LLVOAvatar::initInstance() registerMotion( ANIM_AGENT_SIT_FEMALE, LLKeyframeMotion::create ); registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create ); registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create ); + + registerMotion(ANIM_BD_POSING_MOTION, BDPosingMotion::create); // [FIRE-30873]: Poser } LLAvatarAppearance::initInstance(); @@ -2289,6 +2297,15 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) return; } + // [FIRE-30873]: Poser: BD - We need to clear posing here otherwise we'll crash. + LLMotion *pose_motion = findMotion(ANIM_BD_POSING_MOTION); + if (pose_motion) + { + gAgent.clearPosing(); + removeMotion(ANIM_BD_POSING_MOTION); + } + // + // Save mPelvis state //LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); //LLQuaternion pelvis_rot = getJoint("mPelvis")->getRotation(); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 19cb28502e..1c7626857a 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -67,6 +67,8 @@ extern const LLUUID ANIM_AGENT_PELVIS_FIX; extern const LLUUID ANIM_AGENT_TARGET; extern const LLUUID ANIM_AGENT_WALK_ADJUST; +extern const LLUUID ANIM_BD_POSING_MOTION; // [FIRE-30873]: Poser + class LLViewerWearable; class LLVoiceVisualizer; class LLHUDNameTag; @@ -1270,6 +1272,7 @@ private: std::string mDebugText; std::string mBakedTextureDebugText; + bool mIsPosing = false; // [FIRE-30873]: Poser: Custom Posing //-------------------------------------------------------------------- // Avatar Rez Metrics @@ -1298,6 +1301,13 @@ public: ** ** *******************************************************************************/ +// [FIRE-30873]: Poser: Custom Posing + public: + void setPosing() { mIsPosing = true; } + void clearPosing() { mIsPosing = false; } + bool getPosing() const { return mIsPosing; } +// [FIRE - 30873] : Poser + /******************************************************************************** ** ** ** SUPPORT CLASSES