FIRE-34884: Separate delta-mode operation from rotation changes
parent
ffd83207a6
commit
617a8f0644
|
|
@ -1131,7 +1131,7 @@ void FSFloaterPoser::onUndoLastRotation()
|
|||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
mPoserAnimator.undoLastJointRotation(avatar, *item, getUiSelectedBoneDeflectionStyle(item->jointName()));
|
||||
mPoserAnimator.undoLastJointRotation(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
enableOrDisableRedoButton();
|
||||
|
|
@ -1156,7 +1156,7 @@ void FSFloaterPoser::onUndoLastPosition()
|
|||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
mPoserAnimator.undoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle(item->jointName()));
|
||||
mPoserAnimator.undoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedPositionSliders();
|
||||
|
|
@ -1180,7 +1180,7 @@ void FSFloaterPoser::onUndoLastScale()
|
|||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
mPoserAnimator.undoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle(item->jointName()));
|
||||
mPoserAnimator.undoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedScaleSliders();
|
||||
|
|
@ -1220,7 +1220,7 @@ void FSFloaterPoser::onResetPosition()
|
|||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
mPoserAnimator.resetJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle(item->jointName()));
|
||||
mPoserAnimator.resetJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedPositionSliders();
|
||||
|
|
@ -1247,7 +1247,7 @@ void FSFloaterPoser::onResetScale()
|
|||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
mPoserAnimator.resetJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle(item->jointName()));
|
||||
mPoserAnimator.resetJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedScaleSliders();
|
||||
|
|
@ -1270,7 +1270,7 @@ void FSFloaterPoser::onRedoLastRotation()
|
|||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
mPoserAnimator.redoLastJointRotation(avatar, *item, getUiSelectedBoneDeflectionStyle(item->jointName()));
|
||||
mPoserAnimator.redoLastJointRotation(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
enableOrDisableRedoButton();
|
||||
|
|
@ -1295,7 +1295,7 @@ void FSFloaterPoser::onRedoLastPosition()
|
|||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
mPoserAnimator.redoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle(item->jointName()));
|
||||
mPoserAnimator.redoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedPositionSliders();
|
||||
|
|
@ -1319,7 +1319,7 @@ void FSFloaterPoser::onRedoLastScale()
|
|||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
mPoserAnimator.redoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle(item->jointName()));
|
||||
mPoserAnimator.redoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedScaleSliders();
|
||||
|
|
@ -1443,39 +1443,25 @@ std::vector<FSPoserAnimator::FSPoserJoint*> FSFloaterPoser::getUiSelectedPoserJo
|
|||
return joints;
|
||||
}
|
||||
|
||||
bool FSFloaterPoser::isAnyDeltaModeRotation(const E_BoneDeflectionStyles deflection)
|
||||
{
|
||||
if (mToggleDeltaModeBtn->getValue().asBoolean())
|
||||
return true;
|
||||
|
||||
switch (deflection)
|
||||
{
|
||||
case DELTAMODE:
|
||||
case SYMPATHETIC_DELTA:
|
||||
case MIRROR_DELTA:
|
||||
return true;
|
||||
|
||||
case NONE:
|
||||
case SYMPATHETIC:
|
||||
case MIRROR:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
E_BoneDeflectionStyles FSFloaterPoser::getUiSelectedBoneDeflectionStyle(const std::string& jointName) const
|
||||
E_RotationStyle FSFloaterPoser::getUiSelectedBoneRotationStyle(const std::string& jointName) const
|
||||
{
|
||||
if (jointName.empty())
|
||||
return NONE;
|
||||
return ABSOLUTE_ROT;
|
||||
|
||||
bool isDelta = mToggleDeltaModeBtn->getValue().asBoolean();
|
||||
bool hasRotationStylePreferenceParameter = hasString(XML_JOINT_DELTAROT_STRING_PREFIX + jointName);
|
||||
if (hasRotationStylePreferenceParameter)
|
||||
{
|
||||
std::string paramValue = getString(XML_JOINT_DELTAROT_STRING_PREFIX + jointName);
|
||||
if (strstr(paramValue.c_str(), "true"))
|
||||
isDelta = true;
|
||||
}
|
||||
if (!hasRotationStylePreferenceParameter)
|
||||
return ABSOLUTE_ROT;
|
||||
|
||||
std::string paramValue = getString(XML_JOINT_DELTAROT_STRING_PREFIX + jointName);
|
||||
if (strstr(paramValue.c_str(), "true"))
|
||||
return DELTAIC_ROT;
|
||||
|
||||
return ABSOLUTE_ROT;
|
||||
}
|
||||
|
||||
E_BoneDeflectionStyles FSFloaterPoser::getUiSelectedBoneDeflectionStyle() const
|
||||
{
|
||||
bool isDelta = mToggleDeltaModeBtn->getValue().asBoolean();
|
||||
|
||||
if (mToggleMirrorRotationBtn->getValue().asBoolean())
|
||||
return isDelta ? MIRROR_DELTA : MIRROR;
|
||||
|
|
@ -1746,6 +1732,7 @@ void FSFloaterPoser::setSelectedJointsPosition(F32 x, F32 y, F32 z)
|
|||
return;
|
||||
|
||||
LLVector3 vec3 = LLVector3(x, y, z);
|
||||
E_BoneDeflectionStyles defl = getUiSelectedBoneDeflectionStyle();
|
||||
|
||||
for (auto item : getUiSelectedPoserJoints())
|
||||
{
|
||||
|
|
@ -1753,7 +1740,6 @@ void FSFloaterPoser::setSelectedJointsPosition(F32 x, F32 y, F32 z)
|
|||
if (!currentlyPosingJoint)
|
||||
continue;
|
||||
|
||||
E_BoneDeflectionStyles defl = getUiSelectedBoneDeflectionStyle(item->jointName());
|
||||
mPoserAnimator.setJointPosition(avatar, item, vec3, defl);
|
||||
}
|
||||
}
|
||||
|
|
@ -1767,8 +1753,9 @@ void FSFloaterPoser::setSelectedJointsRotation(LLVector3 absoluteRot, LLVector3
|
|||
if (!mPoserAnimator.isPosingAvatar(avatar))
|
||||
return;
|
||||
|
||||
auto selectedJoints = getUiSelectedPoserJoints();
|
||||
bool savingToExternal = getWhetherToResetBaseRotationOnEdit();
|
||||
auto selectedJoints = getUiSelectedPoserJoints();
|
||||
bool savingToExternal = getWhetherToResetBaseRotationOnEdit();
|
||||
E_BoneDeflectionStyles defl = getUiSelectedBoneDeflectionStyle();
|
||||
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
|
|
@ -1786,9 +1773,9 @@ void FSFloaterPoser::setSelectedJointsRotation(LLVector3 absoluteRot, LLVector3
|
|||
continue;
|
||||
}
|
||||
|
||||
E_BoneDeflectionStyles defl = getUiSelectedBoneDeflectionStyle(item->jointName());
|
||||
mPoserAnimator.setJointRotation(avatar, item, isAnyDeltaModeRotation(defl) ? deltaRot : absoluteRot, defl,
|
||||
getJointTranslation(item->jointName()), getJointNegation(item->jointName()), savingToExternal);
|
||||
mPoserAnimator.setJointRotation(avatar, item, absoluteRot, deltaRot, defl,
|
||||
getJointTranslation(item->jointName()), getJointNegation(item->jointName()), savingToExternal,
|
||||
getUiSelectedBoneRotationStyle(item->jointName()));
|
||||
}
|
||||
|
||||
if (savingToExternal)
|
||||
|
|
@ -1804,7 +1791,8 @@ void FSFloaterPoser::setSelectedJointsScale(F32 x, F32 y, F32 z)
|
|||
if (!mPoserAnimator.isPosingAvatar(avatar))
|
||||
return;
|
||||
|
||||
LLVector3 vec3 = LLVector3(x, y, z);
|
||||
LLVector3 vec3 = LLVector3(x, y, z);
|
||||
E_BoneDeflectionStyles defl = getUiSelectedBoneDeflectionStyle();
|
||||
|
||||
for (auto item : getUiSelectedPoserJoints())
|
||||
{
|
||||
|
|
@ -1812,7 +1800,6 @@ void FSFloaterPoser::setSelectedJointsScale(F32 x, F32 y, F32 z)
|
|||
if (!currentlyPosingJoint)
|
||||
continue;
|
||||
|
||||
E_BoneDeflectionStyles defl = getUiSelectedBoneDeflectionStyle(item->jointName());
|
||||
mPoserAnimator.setJointScale(avatar, item, vec3, defl);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,16 +147,16 @@ class FSFloaterPoser : public LLFloater
|
|||
/// Gets the current bone-deflection style: encapsulates 'anything else you want to do' while you're manipulating a joint.
|
||||
/// Such as: fiddle the opposite joint too.
|
||||
/// </summary>
|
||||
/// <param name="jointName">The well-known joint name of the joint to add the row for, eg: mChest.</param>
|
||||
/// <returns>A E_BoneDeflectionStyles member.</returns>
|
||||
E_BoneDeflectionStyles getUiSelectedBoneDeflectionStyle(const std::string& jointName) const;
|
||||
E_BoneDeflectionStyles getUiSelectedBoneDeflectionStyle() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the supplied joint name should be rotated using the delta method.
|
||||
/// Gets the means by which the rotation should be applied to the supplied joint name.
|
||||
/// Such as: fiddle the opposite joint too.
|
||||
/// </summary>
|
||||
/// <param name="deflection">The deflection to consider.</param>
|
||||
/// <returns>true if the joint should be rotated by delta for any reason, otherwise false.</returns>
|
||||
bool isAnyDeltaModeRotation(const E_BoneDeflectionStyles deflection);
|
||||
/// <param name="jointName">The well-known joint name of the joint to add the row for, eg: mChest.</param>
|
||||
/// <returns>A E_RotationStyle member.</returns>
|
||||
E_RotationStyle getUiSelectedBoneRotationStyle(const std::string& jointName) const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of UUIDs for nearby avatars.
|
||||
|
|
|
|||
|
|
@ -169,13 +169,30 @@ void FSJointPose::swapRotationWith(FSJointPose* oppositeJoint)
|
|||
if (mIsCollisionVolume)
|
||||
return;
|
||||
|
||||
LLJoint* joint = mJointState->getJoint();
|
||||
if (!joint)
|
||||
auto tempRot = FSJointRotation(mRotation);
|
||||
mRotation = FSJointRotation(oppositeJoint->mRotation);
|
||||
oppositeJoint->mRotation = tempRot;
|
||||
}
|
||||
|
||||
void FSJointPose::cloneRotationFrom(FSJointPose* fromJoint)
|
||||
{
|
||||
if (!fromJoint)
|
||||
return;
|
||||
|
||||
auto tempRot = FSJointRotation(mRotation);
|
||||
mRotation = FSJointRotation(oppositeJoint->mRotation);
|
||||
oppositeJoint->mRotation = tempRot;
|
||||
mRotation = FSJointRotation(fromJoint->mRotation);
|
||||
}
|
||||
|
||||
void FSJointPose::mirrorRotationFrom(FSJointPose* fromJoint)
|
||||
{
|
||||
if (!fromJoint)
|
||||
return;
|
||||
|
||||
cloneRotationFrom(fromJoint);
|
||||
|
||||
mRotation.baseRotation = LLQuaternion(-mRotation.baseRotation.mQ[VX], mRotation.baseRotation.mQ[VY], -mRotation.baseRotation.mQ[VZ],
|
||||
mRotation.baseRotation.mQ[VW]);
|
||||
mRotation.deltaRotation = LLQuaternion(-mRotation.deltaRotation.mQ[VX], mRotation.deltaRotation.mQ[VY], -mRotation.deltaRotation.mQ[VZ],
|
||||
mRotation.deltaRotation.mQ[VW]);
|
||||
}
|
||||
|
||||
void FSJointPose::revertJointScale()
|
||||
|
|
|
|||
|
|
@ -147,6 +147,16 @@ class FSJointPose
|
|||
/// </summary>
|
||||
void swapRotationWith(FSJointPose* oppositeJoint);
|
||||
|
||||
/// <summary>
|
||||
/// Clones the rotation to this from the supplied joint.
|
||||
/// </summary>
|
||||
void cloneRotationFrom(FSJointPose* fromJoint);
|
||||
|
||||
/// <summary>
|
||||
/// Mirrors the rotation to this from the supplied joint.
|
||||
/// </summary>
|
||||
void mirrorRotationFrom(FSJointPose* fromJoint);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the beginning properties of the joint this represents.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -496,8 +496,9 @@ LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar* avatar, const FSPoserJoi
|
|||
return translateRotationFromQuaternion(translation, negation, jointPose->getRotationDelta());
|
||||
}
|
||||
|
||||
void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& rotation, E_BoneDeflectionStyles style, E_BoneAxisTranslation translation, S32 negation,
|
||||
bool resetBaseRotationToZero)
|
||||
void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& absRotation,
|
||||
const LLVector3& deltaRotation, E_BoneDeflectionStyles deflectionStyle,
|
||||
E_BoneAxisTranslation translation, S32 negation, bool resetBaseRotationToZero, E_RotationStyle rotationStyle)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
return;
|
||||
|
|
@ -515,26 +516,35 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* j
|
|||
if (resetBaseRotationToZero)
|
||||
jointPose->zeroBaseRotation();
|
||||
|
||||
LLQuaternion rot_quat = translateRotationToQuaternion(translation, negation, rotation);
|
||||
switch (style)
|
||||
LLQuaternion absRot = translateRotationToQuaternion(translation, negation, absRotation);
|
||||
LLQuaternion deltaRot = translateRotationToQuaternion(translation, negation, deltaRotation);
|
||||
switch (deflectionStyle)
|
||||
{
|
||||
case SYMPATHETIC:
|
||||
case MIRROR:
|
||||
jointPose->setRotationDelta(rot_quat);
|
||||
if (rotationStyle == DELTAIC_ROT)
|
||||
jointPose->setRotationDelta(deltaRot * jointPose->getRotationDelta());
|
||||
else
|
||||
jointPose->setRotationDelta(absRot);
|
||||
|
||||
break;
|
||||
|
||||
case SYMPATHETIC_DELTA:
|
||||
case MIRROR_DELTA:
|
||||
jointPose->setRotationDelta(rot_quat * jointPose->getRotationDelta());
|
||||
jointPose->setRotationDelta(deltaRot * jointPose->getRotationDelta());
|
||||
break;
|
||||
|
||||
case DELTAMODE:
|
||||
jointPose->setRotationDelta(rot_quat * jointPose->getRotationDelta());
|
||||
jointPose->setRotationDelta(deltaRot * jointPose->getRotationDelta());
|
||||
return;
|
||||
|
||||
case NONE:
|
||||
default:
|
||||
jointPose->setRotationDelta(rot_quat);
|
||||
if (rotationStyle == DELTAIC_ROT)
|
||||
jointPose->setRotationDelta(deltaRot * jointPose->getRotationDelta());
|
||||
else
|
||||
jointPose->setRotationDelta(absRot);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -542,27 +552,23 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* j
|
|||
if (!oppositeJointPose)
|
||||
return;
|
||||
|
||||
if (resetBaseRotationToZero)
|
||||
oppositeJointPose->zeroBaseRotation();
|
||||
|
||||
LLQuaternion inv_quat;
|
||||
switch (style)
|
||||
switch (deflectionStyle)
|
||||
{
|
||||
case SYMPATHETIC:
|
||||
oppositeJointPose->setRotationDelta(rot_quat);
|
||||
oppositeJointPose->cloneRotationFrom(jointPose);
|
||||
break;
|
||||
|
||||
case SYMPATHETIC_DELTA:
|
||||
oppositeJointPose->setRotationDelta(rot_quat * oppositeJointPose->getRotationDelta());
|
||||
oppositeJointPose->setRotationDelta(deltaRot * oppositeJointPose->getRotationDelta());
|
||||
break;
|
||||
|
||||
case MIRROR:
|
||||
inv_quat = LLQuaternion(-rot_quat.mQ[VX], rot_quat.mQ[VY], -rot_quat.mQ[VZ], rot_quat.mQ[VW]);
|
||||
oppositeJointPose->setRotationDelta(inv_quat);
|
||||
oppositeJointPose->mirrorRotationFrom(jointPose);
|
||||
break;
|
||||
|
||||
case MIRROR_DELTA:
|
||||
inv_quat = LLQuaternion(-rot_quat.mQ[VX], rot_quat.mQ[VY], -rot_quat.mQ[VZ], rot_quat.mQ[VW]);
|
||||
inv_quat = LLQuaternion(-deltaRot.mQ[VX], deltaRot.mQ[VY], -deltaRot.mQ[VZ], deltaRot.mQ[VW]);
|
||||
oppositeJointPose->setRotationDelta(inv_quat * oppositeJointPose->getRotationDelta());
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -54,10 +54,24 @@ typedef enum E_BoneDeflectionStyles
|
|||
MIRROR = 1, // change the other joint, like in a mirror, eg: one left one right
|
||||
SYMPATHETIC = 2, // change the other joint, but opposite to a mirrored way, eg: both go right or both go left
|
||||
DELTAMODE = 3, // each selected joint changes by the same supplied amount relative to their current
|
||||
MIRROR_DELTA = 4, // As MIRROR, but applied as negated delta to opposite
|
||||
SYMPATHETIC_DELTA = 5, // As SYMPATHETIC, but applied as delta
|
||||
MIRROR_DELTA = 4, // Applies a MIRROR delta, this limb and its opposite change by opposite amount
|
||||
SYMPATHETIC_DELTA = 5, // Applies a SYMPATHETIC delta, this limb and the opposite change by the same amount
|
||||
} E_BoneDeflectionStyles;
|
||||
|
||||
/// <summary>
|
||||
/// Joints may have rotations applied by applying an absolute value or a delta value.
|
||||
/// When applying a rotation as absolutes, feedback via the UI can tend to Gimbal lock control of the quaternion.
|
||||
/// For certain joints, particularly "down the centreline", absolute rotations provide the best feel.
|
||||
/// For other joints, such as hips, knees, elbows and wrists, Gimbal lock readily occurs (sitting poses particularly), and
|
||||
/// applying small angle changes directly to the quaternion (rather than going via the locked absolute) makes for
|
||||
/// a more sensible user experience.
|
||||
/// </summary>
|
||||
typedef enum E_RotationStyle
|
||||
{
|
||||
ABSOLUTE_ROT = 0, // The rotation should be applied as an absolute value because while it can Gimbal lock, it doesn't happen often.
|
||||
DELTAIC_ROT = 1, // The rotation should be applied as a delta value because it is apt to Gimbal lock.
|
||||
} E_RotationStyle;
|
||||
|
||||
/// <summary>
|
||||
/// When we're going from bone-rotation to the UI sliders, some of the axes need swapping so they make sense in UI-terms.
|
||||
/// eg: for one bone, the X-axis may mean up and down, but for another bone, the x-axis might be left-right.
|
||||
|
|
@ -457,13 +471,15 @@ public:
|
|||
/// </summary>
|
||||
/// <param name="avatar">The avatar whose joint is to be set.</param>
|
||||
/// <param name="joint">The joint to set.</param>
|
||||
/// <param name="rotation">The rotation to set the joint to.</param>
|
||||
/// <param name="absRotation">The absolute rotation to apply to the joint, if appropriate.</param>
|
||||
/// <param name="deltaRotation">The delta of rotation to apply to the joint, if appropriate.</param>
|
||||
/// <param name="style">Any ancilliary action to be taken with the change to be made.</param>
|
||||
/// <param name="translation">The axial translation form the supplied joint.</param>
|
||||
/// <param name="negation">The style of negation to apply to the set.</param>
|
||||
/// <param name="resetBaseRotationToZero">Whether to set the base rotation to zero on setting the rotation.</param>
|
||||
void setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& rotation, E_BoneDeflectionStyles style,
|
||||
E_BoneAxisTranslation translation, S32 negation, bool resetBaseRotationToZero);
|
||||
/// <param name="rotationStyle">Whether to apply the supplied rotation as a delta to the supplied joint.</param>
|
||||
void setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& absRotation, const LLVector3& deltaRotation, E_BoneDeflectionStyles style,
|
||||
E_BoneAxisTranslation translation, S32 negation, bool resetBaseRotationToZero, E_RotationStyle rotationStyle);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scale of a joint for the supplied avatar.
|
||||
|
|
|
|||
Loading…
Reference in New Issue