parent
6fd345d0b7
commit
3fca86bed9
|
|
@ -160,6 +160,7 @@ set(viewer_SOURCE_FILES
|
|||
fsparticipantlist.cpp
|
||||
fspose.cpp
|
||||
fsposeranimator.cpp
|
||||
fsposingmotion.cpp
|
||||
fsradar.cpp
|
||||
fsradarentry.cpp
|
||||
fsradarlistctrl.cpp
|
||||
|
|
|
|||
|
|
@ -32,10 +32,9 @@
|
|||
#include "llagent.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include <llanimationstates.h>
|
||||
#include "llkeyframemotion.h"
|
||||
#include "fsposingmotion.h"
|
||||
|
||||
/// <summary>
|
||||
/// This has turned into a shim-class rather than the business of posing. *shrug*
|
||||
/// </summary>
|
||||
FSPoserAnimator::FSPoserAnimator() {}
|
||||
FSPoserAnimator::~FSPoserAnimator() {}
|
||||
|
||||
|
|
@ -44,14 +43,18 @@ bool FSPoserAnimator::isPosingAvatarJoint(LLVOAvatar *avatar, FSPoserJoint joint
|
|||
if (!isAvatarSafeToUse(avatar))
|
||||
return false;
|
||||
|
||||
if (!motion || motion->isStopped())
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return false;
|
||||
|
||||
if (posingMotion->isStopped())
|
||||
return false;
|
||||
|
||||
LLJoint* avJoint = avatar->getJoint(JointKey::construct(joint.jointName()));
|
||||
if (!avJoint)
|
||||
return false;
|
||||
|
||||
return motion->currentlyPosingJoint(avJoint);
|
||||
return posingMotion->currentlyPosingJoint(avJoint);
|
||||
}
|
||||
|
||||
void FSPoserAnimator::setPosingAvatarJoint(LLVOAvatar *avatar, FSPoserJoint joint, bool shouldPose)
|
||||
|
|
@ -63,7 +66,11 @@ void FSPoserAnimator::setPosingAvatarJoint(LLVOAvatar *avatar, FSPoserJoint join
|
|||
if (arePosing && shouldPose || !arePosing && !shouldPose) // could !XOR, but this is readable
|
||||
return;
|
||||
|
||||
if (!motion || motion->isStopped())
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
if (posingMotion->isStopped())
|
||||
return;
|
||||
|
||||
LLJoint* avJoint = avatar->getJoint(JointKey::construct(joint.jointName()));
|
||||
|
|
@ -71,9 +78,9 @@ void FSPoserAnimator::setPosingAvatarJoint(LLVOAvatar *avatar, FSPoserJoint join
|
|||
return;
|
||||
|
||||
if (shouldPose)
|
||||
motion->addJointToState(avJoint);
|
||||
posingMotion->addJointToState(avJoint);
|
||||
else
|
||||
motion->removeJointFromState(avJoint);
|
||||
posingMotion->removeJointFromState(avJoint);
|
||||
}
|
||||
|
||||
void FSPoserAnimator::resetAvatarJoint(LLVOAvatar *avatar, FSPoserJoint joint)
|
||||
|
|
@ -81,7 +88,11 @@ void FSPoserAnimator::resetAvatarJoint(LLVOAvatar *avatar, FSPoserJoint joint)
|
|||
if (!isAvatarSafeToUse(avatar))
|
||||
return;
|
||||
|
||||
if (!motion || motion->isStopped())
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
if (posingMotion->isStopped())
|
||||
return;
|
||||
|
||||
LLJoint* avJoint = avatar->getJoint(JointKey::construct(joint.jointName()));
|
||||
|
|
@ -97,11 +108,15 @@ LLVector3 FSPoserAnimator::getJointPosition(LLVOAvatar *avatar, FSPoserJoint joi
|
|||
if (!isAvatarSafeToUse(avatar))
|
||||
return pos;
|
||||
|
||||
LLJoint* avJoint = avatar->getJoint(JointKey::construct(joint.jointName()));
|
||||
if (!avJoint)
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return pos;
|
||||
|
||||
pos = avJoint->getTargetPosition();
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
|
||||
if (!jointPose)
|
||||
return pos;
|
||||
|
||||
pos = jointPose->getTargetPosition();
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
|
@ -117,12 +132,15 @@ void FSPoserAnimator::setJointPosition(LLVOAvatar *avatar, const FSPoserJoint *j
|
|||
if (jn.empty())
|
||||
return;
|
||||
|
||||
JointKey key = JointKey::construct(jn);
|
||||
LLJoint *avJoint = avatar->getJoint(key);
|
||||
if (!avJoint)
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
avJoint->setTargetPosition(position);
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(jn);
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
jointPose->setTargetPosition(position);
|
||||
}
|
||||
|
||||
LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar *avatar, FSPoserJoint joint, E_BoneAxisTranslation translation, S32 negation, bool forRecapture)
|
||||
|
|
@ -131,11 +149,27 @@ LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar *avatar, FSPoserJoint joi
|
|||
if (!isAvatarSafeToUse(avatar))
|
||||
return vec3;
|
||||
|
||||
LLJoint *avJoint = avatar->getJoint(JointKey::construct(joint.jointName()));
|
||||
if (!avJoint)
|
||||
return vec3;
|
||||
LLQuaternion rot;
|
||||
if (forRecapture)
|
||||
{
|
||||
LLJoint* avJoint = avatar->getJoint(JointKey::construct(joint.jointName()));
|
||||
if (!avJoint)
|
||||
return vec3;
|
||||
|
||||
LLQuaternion rot = forRecapture ? avJoint->getRotation() : avJoint->getTargetRotation();
|
||||
rot = avJoint->getRotation();
|
||||
}
|
||||
else
|
||||
{
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return vec3;
|
||||
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
|
||||
if (!jointPose)
|
||||
return vec3;
|
||||
|
||||
rot = jointPose->getTargetRotation();
|
||||
}
|
||||
|
||||
return translateRotationFromQuaternion(translation, negation, rot);
|
||||
}
|
||||
|
|
@ -148,30 +182,34 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar *avatar, const FSPoserJoint *j
|
|||
if (!joint)
|
||||
return;
|
||||
|
||||
LLJoint *avJoint = avatar->getJoint(JointKey::construct(joint->jointName()));
|
||||
if (!avJoint)
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
LLQuaternion rot_quat = translateRotationToQuaternion(translation, negation, rotation);
|
||||
avJoint->setTargetRotation(rot_quat);
|
||||
jointPose->setTargetRotation(rot_quat);
|
||||
|
||||
if (style == NONE)
|
||||
return;
|
||||
|
||||
LLJoint *oppositeJoint = avatar->getJoint(JointKey::construct(joint->mirrorJointName()));
|
||||
if (!oppositeJoint)
|
||||
FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName());
|
||||
if (!oppositeJointPose)
|
||||
return;
|
||||
|
||||
LLQuaternion inv_quat;
|
||||
switch (style)
|
||||
{
|
||||
case SYMPATHETIC:
|
||||
oppositeJoint->setTargetRotation(rot_quat);
|
||||
oppositeJointPose->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);
|
||||
oppositeJointPose->setTargetRotation(inv_quat);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -187,26 +225,32 @@ void FSPoserAnimator::reflectJoint(LLVOAvatar *avatar, const FSPoserJoint *joint
|
|||
if (!joint)
|
||||
return;
|
||||
|
||||
LLJoint *avJoint = avatar->getJoint(JointKey::construct(joint->jointName()));
|
||||
if (!avJoint)
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
LLJoint *oppositeJoint = avatar->getJoint(JointKey::construct(joint->mirrorJointName()));
|
||||
if (!oppositeJoint)
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName());
|
||||
if (!oppositeJointPose)
|
||||
return;
|
||||
if (!oppositeJointPose)
|
||||
{
|
||||
LLQuaternion rot_quat = avJoint->getTargetRotation();
|
||||
LLQuaternion rot_quat = jointPose->getTargetRotation();
|
||||
LLQuaternion inv_quat = LLQuaternion(-rot_quat.mQ[VX], rot_quat.mQ[VY], -rot_quat.mQ[VZ], rot_quat.mQ[VW]);
|
||||
|
||||
avJoint->setTargetRotation(inv_quat);
|
||||
jointPose->setTargetRotation(inv_quat);
|
||||
return;
|
||||
}
|
||||
|
||||
LLQuaternion first_quat = avJoint->getTargetRotation();
|
||||
LLQuaternion first_quat = jointPose->getTargetRotation();
|
||||
LLQuaternion first_inv = LLQuaternion(-first_quat.mQ[VX], first_quat.mQ[VY], -first_quat.mQ[VZ], first_quat.mQ[VW]);
|
||||
LLQuaternion second_quat = oppositeJoint->getTargetRotation();
|
||||
LLQuaternion second_quat = oppositeJointPose->getTargetRotation();
|
||||
LLQuaternion second_inv = LLQuaternion(-second_quat.mQ[VX], second_quat.mQ[VY], -second_quat.mQ[VZ], second_quat.mQ[VW]);
|
||||
avJoint->setTargetRotation(second_inv);
|
||||
oppositeJoint->setTargetRotation(first_inv);
|
||||
jointPose->setTargetRotation(second_inv);
|
||||
oppositeJointPose->setTargetRotation(first_inv);
|
||||
}
|
||||
|
||||
void FSPoserAnimator::flipEntirePose(LLVOAvatar *avatar)
|
||||
|
|
@ -385,12 +429,17 @@ bool FSPoserAnimator::tryPosingAvatar(LLVOAvatar *avatar)
|
|||
if (!isAvatarSafeToUse(avatar))
|
||||
return false;
|
||||
|
||||
if (!motion || motion->isStopped())
|
||||
FSPosingMotion* posingMotion = createPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return false;
|
||||
|
||||
if (posingMotion->isStopped())
|
||||
{
|
||||
if (avatar->isSelf())
|
||||
gAgent.stopFidget();
|
||||
|
||||
avatar->startDefaultMotions();
|
||||
avatar->startMotion(posingMotion->motionId());
|
||||
|
||||
// TODO: scrape motion state prior to edit, facilitating reset
|
||||
|
||||
|
|
@ -405,6 +454,11 @@ void FSPoserAnimator::stopPosingAvatar(LLVOAvatar *avatar)
|
|||
if (!avatar || avatar->isDead())
|
||||
return;
|
||||
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
avatar->stopMotion(posingMotion->motionId());
|
||||
}
|
||||
|
||||
bool FSPoserAnimator::isPosingAvatar(LLVOAvatar* avatar)
|
||||
|
|
@ -412,10 +466,41 @@ bool FSPoserAnimator::isPosingAvatar(LLVOAvatar* avatar)
|
|||
if (!isAvatarSafeToUse(avatar))
|
||||
return false;
|
||||
|
||||
if (!motion)
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return false;
|
||||
|
||||
return !motion->isStopped();
|
||||
return !posingMotion->isStopped();
|
||||
}
|
||||
|
||||
FSPosingMotion* FSPoserAnimator::getPosingMotion(LLVOAvatar* avatar)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
return nullptr;
|
||||
|
||||
if (_avatarIdToRegisteredAnimationId.find(avatar->getID()) == _avatarIdToRegisteredAnimationId.end())
|
||||
return nullptr;
|
||||
|
||||
return dynamic_cast<FSPosingMotion*>(avatar->findMotion(_avatarIdToRegisteredAnimationId[avatar->getID()]));
|
||||
}
|
||||
|
||||
FSPosingMotion* FSPoserAnimator::createPosingMotion(LLVOAvatar* avatar)
|
||||
{
|
||||
FSPosingMotion* motion = getPosingMotion(avatar);
|
||||
|
||||
if (!motion)
|
||||
{
|
||||
LLTransactionID mTransactionID;
|
||||
mTransactionID.generate();
|
||||
LLAssetID animationAssetId = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
|
||||
|
||||
if (avatar->registerMotion(animationAssetId, FSPosingMotion::create))
|
||||
_avatarIdToRegisteredAnimationId[avatar->getID()] = animationAssetId;
|
||||
|
||||
return dynamic_cast<FSPosingMotion*>(avatar->createMotion(animationAssetId));
|
||||
}
|
||||
|
||||
return motion;
|
||||
}
|
||||
|
||||
bool FSPoserAnimator::isAvatarSafeToUse(LLVOAvatar *avatar)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "lljointsolverrp3.h"
|
||||
#include "v3dmath.h"
|
||||
#include "llcontrolavatar.h"
|
||||
#include "fsposingMotion.h"
|
||||
|
||||
/// <summary>
|
||||
/// Describes how we will cluster the joints/bones/thingos.
|
||||
|
|
@ -342,12 +343,37 @@ public:
|
|||
/// <returns>The rotation vector.</returns>
|
||||
LLVector3 translateRotationFromQuaternion(E_BoneAxisTranslation translation, S32 negation, LLQuaternion rotation);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a posing motion for the supplied avatar.
|
||||
/// </summary>
|
||||
/// <param name="avatar">The avatar to create the posing motion for.</param>
|
||||
/// <returns>The posing motion, if created, otherwise nullptr.</returns>
|
||||
/// <remarks>
|
||||
/// When a pose is created for the avatar, it is 'registered' with their character for use later on.
|
||||
/// Thus we start & stop posing the same animation.
|
||||
/// </remarks>
|
||||
FSPosingMotion* createPosingMotion(LLVOAvatar* avatar);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the poser posing-motion for the supplied avatar.
|
||||
/// </summary>
|
||||
/// <param name="avatar">The avatar to get the posing motion for.</param>
|
||||
/// <returns>The posing motion if found, otherwise nullptr.</returns>
|
||||
FSPosingMotion* getPosingMotion(LLVOAvatar* avatar);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the avatar can be used.
|
||||
/// </summary>
|
||||
/// <param name="avatar">The avatar to test if it is safe to animate.</param>
|
||||
/// <returns>True if the avatar is safe to manipulate, otherwise false.</returns>
|
||||
bool isAvatarSafeToUse(LLVOAvatar *avatar);
|
||||
|
||||
/// <summary>
|
||||
/// Maps the avatar's ID to the animation registered to them.
|
||||
/// Thus we start/stop the same animation.
|
||||
/// An avatar's animation exists so long as their session does, and there is consideration for renewal (like if they relog/crash).
|
||||
/// </summary>
|
||||
std::map<LLUUID, LLAssetID> _avatarIdToRegisteredAnimationId;
|
||||
};
|
||||
|
||||
#endif // LL_FSPoserAnimator_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
* @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 "fsposingMotion.h"
|
||||
#include "llcharacter.h"
|
||||
#include "llagent.h"
|
||||
|
||||
FSPosingMotion::FSPosingMotion(const LLUUID &id) : LLMotion(id), _character(NULL)
|
||||
{
|
||||
mName = "fs_poser_pose";
|
||||
_motionID = id;
|
||||
}
|
||||
|
||||
LLMotion::LLMotionInitStatus FSPosingMotion::onInitialize(LLCharacter *character)
|
||||
{
|
||||
if (!character)
|
||||
return STATUS_FAILURE;
|
||||
|
||||
_character = character;
|
||||
_jointPoses.clear();
|
||||
|
||||
LLJoint* targetJoint;
|
||||
for (S32 i = 0; (targetJoint = character->getCharacterJoint(i)); ++i) // this seems poorly constrained
|
||||
{
|
||||
if (!targetJoint)
|
||||
continue;
|
||||
|
||||
FSJointPose jointPose = FSJointPose(targetJoint);
|
||||
_jointPoses.push_back(jointPose);
|
||||
|
||||
addJointState(jointPose.getJointState());
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bool FSPosingMotion::onActivate() { return true; }
|
||||
|
||||
bool FSPosingMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
{
|
||||
LLQuaternion targetRotation;
|
||||
LLQuaternion currentRotation;
|
||||
LLVector3 currentPosition;
|
||||
LLVector3 targetPosition;
|
||||
F32 poseTransitionAmount = 0.0f; // when we change from one position/rotation to another, we do so over time; this documents the amount of transition.
|
||||
|
||||
for (FSJointPose jointPose : _jointPoses)
|
||||
{
|
||||
LLJoint* joint = jointPose.getJointState()->getJoint();
|
||||
if (!joint)
|
||||
continue;
|
||||
|
||||
currentRotation = joint->getRotation();
|
||||
currentPosition = joint->getPosition();
|
||||
targetRotation = jointPose.getTargetRotation();
|
||||
targetPosition = jointPose.getTargetPosition();
|
||||
|
||||
poseTransitionAmount = llclamp(_interpolationTimer.getElapsedTimeF32() / _interpolationTime, 0.0f, 1.0f);
|
||||
if (currentPosition != targetPosition)
|
||||
{
|
||||
currentPosition = lerp(currentPosition, targetPosition, _interpolationTime);
|
||||
jointPose.getJointState()->setPosition(currentPosition);
|
||||
}
|
||||
|
||||
if (currentRotation != targetRotation)
|
||||
{
|
||||
currentRotation = slerp(_interpolationTime, currentRotation, targetRotation);
|
||||
jointPose.getJointState()->setRotation(currentRotation);
|
||||
}
|
||||
}
|
||||
|
||||
if (_interpolationTimer.getStarted() && poseTransitionAmount >= 1.0f)
|
||||
_interpolationTimer.stop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FSPosingMotion::onDeactivate() {}
|
||||
|
||||
void FSPosingMotion::addJointToState(LLJoint* joint) { setJointState(joint, POSER_JOINT_STATE); }
|
||||
|
||||
void FSPosingMotion::removeJointFromState(LLJoint *joint) { setJointState(joint, 0); }
|
||||
|
||||
void FSPosingMotion::setJointState(LLJoint *joint, U32 state)
|
||||
{
|
||||
if (_jointPoses.size() < 1)
|
||||
return;
|
||||
if (!joint)
|
||||
return;
|
||||
|
||||
LLPose* pose = this->getPose();
|
||||
if (!pose)
|
||||
return;
|
||||
|
||||
LLPointer<LLJointState> jointState = pose->findJointState(joint);
|
||||
if (jointState.isNull())
|
||||
return;
|
||||
|
||||
pose->removeJointState(jointState);
|
||||
FSJointPose *jointPose = getJointPoseByJointName(joint->getName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
jointPose->getJointState()->setUsage(state);
|
||||
addJointState(jointPose->getJointState());
|
||||
}
|
||||
|
||||
FSPosingMotion::FSJointPose* FSPosingMotion::getJointPoseByJointName(std::string name)
|
||||
{
|
||||
if (_jointPoses.size() < 1)
|
||||
return nullptr;
|
||||
|
||||
std::vector<FSPosingMotion::FSJointPose>::iterator poserJoint_iter;
|
||||
for (poserJoint_iter = _jointPoses.begin(); poserJoint_iter != _jointPoses.end(); ++poserJoint_iter)
|
||||
{
|
||||
if (!boost::iequals(poserJoint_iter->jointName(), name))
|
||||
continue;
|
||||
|
||||
return &*poserJoint_iter;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool FSPosingMotion::currentlyPosingJoint(LLJoint* joint)
|
||||
{
|
||||
if (_jointPoses.size() < 1)
|
||||
return false;
|
||||
|
||||
if (!joint)
|
||||
return false;
|
||||
|
||||
LLPose* pose = this->getPose();
|
||||
if (!pose)
|
||||
return false;
|
||||
|
||||
LLPointer<LLJointState> jointState = pose->findJointState(joint);
|
||||
if (jointState.isNull())
|
||||
return false;
|
||||
|
||||
U32 state = jointState->getUsage();
|
||||
return (state & POSER_JOINT_STATE);
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
* @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$
|
||||
*/
|
||||
|
||||
#ifndef LL_FSPOSINGMOTION_H
|
||||
#define LL_FSPOSINGMOTION_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Header files
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "llmotion.h"
|
||||
#include "lljointsolverrp3.h"
|
||||
#include "v3dmath.h"
|
||||
|
||||
#define MIN_REQUIRED_PIXEL_AREA_POSING 500.f
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class FSPosingMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class FSPosingMotion :
|
||||
public LLMotion
|
||||
{
|
||||
public:
|
||||
FSPosingMotion(const LLUUID &id);
|
||||
virtual ~FSPosingMotion(){};
|
||||
|
||||
public:
|
||||
static LLMotion *create(const LLUUID &id) { return new FSPosingMotion(id); }
|
||||
|
||||
/// <summary>
|
||||
/// A class encapsulating the positions/rotations for a joint.
|
||||
/// </summary>
|
||||
class FSJointPose
|
||||
{
|
||||
std::string _jointName = ""; // expected to be a match to LLJoint.getName() for a joint implementation.
|
||||
LLQuaternion _targetRotation;
|
||||
LLVector3 _targetPosition;
|
||||
LLPointer<LLJointState> _jointState;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the name of the joint.
|
||||
/// </summary>
|
||||
std::string jointName() const { return _jointName; }
|
||||
|
||||
LLVector3 getTargetPosition() const { return _targetPosition; }
|
||||
void setTargetPosition(const LLVector3& pos) { _targetPosition.set(pos) ; }
|
||||
|
||||
LLQuaternion getTargetRotation() const { return _targetRotation; }
|
||||
void setTargetRotation(const LLQuaternion& rot) { _targetRotation.set(rot); }
|
||||
|
||||
LLPointer<LLJointState> getJointState() const { return _jointState; }
|
||||
|
||||
FSJointPose(LLJoint* joint)
|
||||
{
|
||||
_jointState = new LLJointState;
|
||||
_jointState->setJoint(joint);
|
||||
_jointState->setUsage(POSER_JOINT_STATE);
|
||||
|
||||
_jointName = joint->getName();
|
||||
|
||||
_targetRotation = joint->getRotation();
|
||||
_targetPosition = joint->getPosition();
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
virtual bool getLoop() { return TRUE; }
|
||||
|
||||
virtual F32 getDuration() { return 0.0; }
|
||||
|
||||
virtual F32 getEaseInDuration() { return 0.0f; }
|
||||
|
||||
virtual F32 getEaseOutDuration() { return 0.5f; }
|
||||
|
||||
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();
|
||||
|
||||
/// <summary>
|
||||
/// Adds the supplied joint to the current animation-state.
|
||||
/// </summary>
|
||||
/// <param name="joint">The joint to animate.</param>
|
||||
void addJointToState(LLJoint *joint);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the supplied joint to the current animation-state.
|
||||
/// </summary>
|
||||
/// <param name="joint">The joint to stop animating.</param>
|
||||
void removeJointFromState(LLJoint *joint);
|
||||
|
||||
/// <summary>
|
||||
/// Queries whether the supplied joint is being animated.
|
||||
/// </summary>
|
||||
/// <param name="joint">The joint to query.</param>
|
||||
bool currentlyPosingJoint(LLJoint *joint);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the current joint state, and adds a new one.
|
||||
/// </summary>
|
||||
void setJointState(LLJoint* joint, U32 state);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the joint pose by name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the joint to get the pose for.</param>
|
||||
/// <returns>The matching joint pose, if found, otherwise null.</returns>
|
||||
FSJointPose* getJointPoseByJointName(std::string name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the motion identity for this animation.
|
||||
/// </summary>
|
||||
/// <returns>The unique, per-session motion identity.</returns>
|
||||
LLAssetID motionId() const { return _motionID; }
|
||||
|
||||
private:
|
||||
static const U32 POSER_JOINT_STATE = LLJointState::POS | LLJointState::ROT /* | LLJointState::SCALE*/;
|
||||
LLAssetID _motionID;
|
||||
|
||||
const F32 _interpolationTime = 0.25f;
|
||||
|
||||
LLFrameTimer _interpolationTimer;
|
||||
LLCharacter *_character;
|
||||
std::vector<FSJointPose> _jointPoses;
|
||||
};
|
||||
|
||||
#endif // LL_LLKEYFRAMEMOTION_H
|
||||
|
||||
Loading…
Reference in New Issue