Poser: Refactor undo to one stack

Rework UI: removed 'advanced' panel. Remove yaw/pitch/roll sliders. Added Symmetrize L/R.
master
Angeldark Raymaker 2025-03-09 23:22:28 +00:00 committed by Beq
parent f9035a4b8b
commit 47a2a78089
8 changed files with 833 additions and 1312 deletions

View File

@ -55,7 +55,6 @@ constexpr char XML_LIST_TITLE_STRING_PREFIX[] = "title_";
constexpr char XML_JOINT_TRANSFORM_STRING_PREFIX[] = "joint_transform_";
constexpr char XML_JOINT_DELTAROT_STRING_PREFIX[] = "joint_delta_rotate_";
constexpr char BVH_JOINT_TRANSFORM_STRING_PREFIX[] = "bvh_joint_transform_";
constexpr std::string_view POSER_ADVANCEDWINDOWSTATE_SAVE_KEY = "FSPoserAdvancedWindowState";
constexpr std::string_view POSER_TRACKPAD_SENSITIVITY_SAVE_KEY = "FSPoserTrackpadSensitivity";
constexpr std::string_view POSER_STOPPOSINGWHENCLOSED_SAVE_KEY = "FSPoserStopPosingWhenClosed";
constexpr std::string_view POSER_RESETBASEROTONEDIT_SAVE_KEY = "FSPoserResetBaseRotationOnEdit";
@ -74,10 +73,9 @@ FSFloaterPoser::FSFloaterPoser(const LLSD& key) : LLFloater(key)
mCommitCallbackRegistrar.add("Poser.RefreshAvatars", [this](LLUICtrl*, const LLSD&) { onAvatarsRefresh(); });
mCommitCallbackRegistrar.add("Poser.StartStopAnimating", [this](LLUICtrl*, const LLSD&) { onPoseStartStop(); });
mCommitCallbackRegistrar.add("Poser.ToggleLoadSavePanel", [this](LLUICtrl*, const LLSD&) { onToggleLoadSavePanel(); });
mCommitCallbackRegistrar.add("Poser.ToggleAdvancedPanel", [this](LLUICtrl*, const LLSD&) { onToggleAdvancedPanel(); });
mCommitCallbackRegistrar.add("Poser.UndoLastRotation", [this](LLUICtrl*, const LLSD&) { onUndoLastRotation(); });
mCommitCallbackRegistrar.add("Poser.RedoLastRotation", [this](LLUICtrl*, const LLSD&) { onRedoLastRotation(); });
mCommitCallbackRegistrar.add("Poser.UndoLastRotation", [this](LLUICtrl*, const LLSD&) { onUndoLastChange(); });
mCommitCallbackRegistrar.add("Poser.RedoLastRotation", [this](LLUICtrl*, const LLSD&) { onRedoLastChange(); });
mCommitCallbackRegistrar.add("Poser.ToggleMirrorChanges", [this](LLUICtrl*, const LLSD&) { onToggleMirrorChange(); });
mCommitCallbackRegistrar.add("Poser.ToggleSympatheticChanges", [this](LLUICtrl*, const LLSD&) { onToggleSympatheticChange(); });
mCommitCallbackRegistrar.add("Poser.AdjustTrackPadSensitivity", [this](LLUICtrl*, const LLSD&) { onAdjustTrackpadSensitivity(); });
@ -87,12 +85,9 @@ FSFloaterPoser::FSFloaterPoser(const LLSD& key) : LLFloater(key)
mCommitCallbackRegistrar.add("Poser.Advanced.PositionSet", [this](LLUICtrl*, const LLSD&) { onAdvancedPositionSet(); });
mCommitCallbackRegistrar.add("Poser.Advanced.ScaleSet", [this](LLUICtrl*, const LLSD&) { onAdvancedScaleSet(); });
mCommitCallbackRegistrar.add("Poser.UndoLastPosition", [this](LLUICtrl*, const LLSD&) { onUndoLastPosition(); });
mCommitCallbackRegistrar.add("Poser.RedoLastPosition", [this](LLUICtrl*, const LLSD&) { onRedoLastPosition(); });
mCommitCallbackRegistrar.add("Poser.ResetPosition", [this](LLUICtrl*, const LLSD&) { onResetPosition(); });
mCommitCallbackRegistrar.add("Poser.ResetScale", [this](LLUICtrl*, const LLSD&) { onResetScale(); });
mCommitCallbackRegistrar.add("Poser.UndoLastScale", [this](LLUICtrl*, const LLSD&) { onUndoLastScale(); });
mCommitCallbackRegistrar.add("Poser.RedoLastScale", [this](LLUICtrl*, const LLSD&) { onRedoLastScale(); });
mCommitCallbackRegistrar.add("Poser.UndoLastPosition", [this](LLUICtrl*, const LLSD&) { onUndoLastChange(); });
mCommitCallbackRegistrar.add("Poser.RedoLastPosition", [this](LLUICtrl*, const LLSD&) { onRedoLastChange(); });
mCommitCallbackRegistrar.add("Poser.ResetJoint", [this](LLUICtrl*, const LLSD& data) { onResetJoint(data); });
mCommitCallbackRegistrar.add("Poser.Save", [this](LLUICtrl*, const LLSD&) { onClickPoseSave(); });
mCommitCallbackRegistrar.add("Pose.Menu", [this](LLUICtrl*, const LLSD& data) { onPoseMenuAction(data); });
@ -104,10 +99,9 @@ FSFloaterPoser::FSFloaterPoser(const LLSD& key) : LLFloater(key)
mCommitCallbackRegistrar.add("Poser.FlipJoint", [this](LLUICtrl*, const LLSD&) { onClickFlipSelectedJoints(); });
mCommitCallbackRegistrar.add("Poser.RecaptureSelectedBones", [this](LLUICtrl*, const LLSD&) { onClickRecaptureSelectedBones(); });
mCommitCallbackRegistrar.add("Poser.TogglePosingSelectedBones", [this](LLUICtrl*, const LLSD&) { onClickToggleSelectedBoneEnabled(); });
mCommitCallbackRegistrar.add("Poser.PoseJointsReset", [this](LLUICtrl*, const LLSD&) { onPoseJointsReset(); });
//mCommitCallbackRegistrar.add("Poser.CommitSpinner", [this](LLUICtrl* spinnerControl, const LLSD&) { onCommitSpinner(spinnerControl); });
mCommitCallbackRegistrar.add("Poser.CommitSpinner", boost::bind(&FSFloaterPoser::onCommitSpinner, this, _1, _2));
mCommitCallbackRegistrar.add("Poser.CommitSpinner", [this](LLUICtrl* spinner, const LLSD& data) { onCommitSpinner(spinner, data); });
mCommitCallbackRegistrar.add("Poser.Symmetrize", [this](LLUICtrl*, const LLSD& data) { onClickSymmetrize(data); });
}
bool FSFloaterPoser::postBuild()
@ -115,15 +109,6 @@ bool FSFloaterPoser::postBuild()
mAvatarTrackball = getChild<FSVirtualTrackpad>("limb_rotation");
mAvatarTrackball->setCommitCallback([this](LLUICtrl *, const LLSD &) { onLimbTrackballChanged(); });
mLimbYawSlider = getChild<LLSliderCtrl>("limb_yaw");
mLimbYawSlider->setCommitCallback([this](LLUICtrl *, const LLSD &) { onYawPitchRollSliderChanged(); });
mLimbPitchSlider = getChild<LLSliderCtrl>("limb_pitch");
mLimbPitchSlider->setCommitCallback([this](LLUICtrl *, const LLSD &) { onYawPitchRollSliderChanged(); });
mLimbRollSlider = getChild<LLSliderCtrl>("limb_roll");
mLimbRollSlider->setCommitCallback([this](LLUICtrl *, const LLSD &) { onYawPitchRollSliderChanged(); });
mJointsTabs = getChild<LLTabContainer>("joints_tabs");
mJointsTabs->setCommitCallback(
[this](LLUICtrl*, const LLSD&)
@ -162,10 +147,6 @@ bool FSFloaterPoser::postBuild()
mPosesScrollList->setCommitOnSelectionChange(true);
mPosesScrollList->setCommitCallback([this](LLUICtrl *, const LLSD &) { onPoseFileSelect(); });
mToggleAdvancedPanelBtn = getChild<LLButton>("toggleAdvancedPanel");
if (gSavedSettings.getBOOL(POSER_ADVANCEDWINDOWSTATE_SAVE_KEY))
mToggleAdvancedPanelBtn->setValue(true);
mTrackpadSensitivitySlider = getChild<LLSliderCtrl>("trackpad_sensitivity_slider");
mPoseSaveNameEditor = getChild<LLLineEditor>("pose_save_name");
@ -204,7 +185,6 @@ bool FSFloaterPoser::postBuild()
mSetToTposeButton = getChild<LLButton>("set_t_pose_button");
mJointsParentPnl = getChild<LLPanel>("joints_parent_panel");
mAdvancedParentPnl = getChild<LLPanel>("advanced_parent_panel");
mTrackballPnl = getChild<LLPanel>("trackball_panel");
mPositionRotationPnl = getChild<LLPanel>("positionRotation_panel");
mBodyJointsPnl = getChild<LLPanel>("body_joints_panel");
@ -220,8 +200,11 @@ bool FSFloaterPoser::postBuild()
mTrackpadSensitivitySpnr = getChild<LLUICtrl>("trackpad_sensitivity_spinner");
mYawSpnr = getChild<LLUICtrl>("limb_yaw_spinner");
mYawSpnr->setCommitCallback([this](LLUICtrl*, const LLSD&) { onYawPitchRollChanged(); });
mPitchSpnr = getChild<LLUICtrl>("limb_pitch_spinner");
mRollSpnr = getChild<LLUICtrl>("limb_roll_spinner");
mPitchSpnr->setCommitCallback([this](LLUICtrl*, const LLSD&) { onYawPitchRollChanged(); });
mRollSpnr = getChild<LLUICtrl>("limb_roll_spinner");
mRollSpnr->setCommitCallback([this](LLUICtrl*, const LLSD&) { onYawPitchRollChanged(); });
mUpDownSpnr = getChild<LLUICtrl>("av_position_updown_spinner");
mLeftRightSpnr = getChild<LLUICtrl>("av_position_leftright_spinner");
mInOutSpnr = getChild<LLUICtrl>("av_position_inout_spinner");
@ -241,7 +224,6 @@ void FSFloaterPoser::onOpen(const LLSD& key)
onAvatarsRefresh();
refreshJointScrollListMembers();
onJointTabSelect();
onOpenSetAdvancedPanel();
refreshPoseScroll(mHandPresetsScrollList, POSE_PRESETS_HANDS_SUBDIRECTORY);
startPosingSelf();
@ -250,9 +232,6 @@ void FSFloaterPoser::onOpen(const LLSD& key)
void FSFloaterPoser::onClose(bool app_quitting)
{
if (mToggleAdvancedPanelBtn)
gSavedSettings.setBOOL(POSER_ADVANCEDWINDOWSTATE_SAVE_KEY, mToggleAdvancedPanelBtn->getValue().asBoolean());
if (gSavedSettings.getBOOL(POSER_STOPPOSINGWHENCLOSED_SAVE_KEY))
stopPosingAllAvatars();
@ -582,8 +561,24 @@ void FSFloaterPoser::onClickBrowsePoseCache()
gViewerWindow->getWindow()->openFile(pathname);
}
//void FSFloaterPoser::onCommitSpinner(LLUICtrl* spinner)
// Pass in an ID as a parameter, so you can use a switch statement
void FSFloaterPoser::onClickSymmetrize(S32 ID)
{
if (notDoubleClicked())
return;
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
return;
if (!mPoserAnimator.isPosingAvatar(avatar))
return;
mPoserAnimator.symmetrizeLeftToRightOrRightToLeft(avatar, ID == 2);
refreshRotationSlidersAndSpinners();
refreshTrackpadCursor();
}
void FSFloaterPoser::onCommitSpinner(LLUICtrl* spinner, S32 id)
{
if (!spinner)
@ -597,8 +592,6 @@ void FSFloaterPoser::onCommitSpinner(LLUICtrl* spinner, S32 id)
F32 value = (F32)spinner->getValue().asReal();
// Use the ID passed in to perform a switch statment
// which should make each action take the same amount of time.
switch (id)
{
case 0: // av_position_updown_spinner
@ -624,24 +617,6 @@ void FSFloaterPoser::onCommitSpinner(LLUICtrl* spinner, S32 id)
onAdjustTrackpadSensitivity();
break;
}
case 4: // limb_pitch_spinner
{
mLimbPitchSlider->setValue(value);
onYawPitchRollSliderChanged();
break;
}
case 5: // limb_yaw_spinner
{
mLimbYawSlider->setValue(value);
onYawPitchRollSliderChanged();
break;
}
case 6: // limb_roll_spinner
{
mLimbRollSlider->setValue(value);
onYawPitchRollSliderChanged();
break;
}
case 7: // adv_posx_spinner
{
if (changingBodyPosition)
@ -690,34 +665,6 @@ void FSFloaterPoser::onCommitSpinner(LLUICtrl* spinner, S32 id)
}
}
void FSFloaterPoser::onPoseJointsReset()
{
if (notDoubleClicked())
return;
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
return;
if (!mPoserAnimator.isPosingAvatar(avatar))
return;
auto selectedJoints = getUiSelectedPoserJoints();
if (selectedJoints.size() < 1)
return;
for (auto item : selectedJoints)
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.resetAvatarJoint(avatar, *item);
}
refreshRotationSlidersAndSpinners();
refreshTrackpadCursor();
refreshAvatarPositionSlidersAndSpinners();
}
void FSFloaterPoser::onPoseMenuAction(const LLSD& param)
{
std::string loadStyle = param.asString();
@ -1018,7 +965,7 @@ void FSFloaterPoser::startPosingSelf()
void FSFloaterPoser::stopPosingAllAvatars()
{
if (!gAgentAvatarp || gAgentAvatarp.isNull())
if (!gAgentAvatarp || gAgentAvatarp.isNull() || !mAvatarSelectionScrollList)
return;
for (auto listItem : mAvatarSelectionScrollList->getAllData())
@ -1087,7 +1034,6 @@ bool FSFloaterPoser::havePermissionToAnimateAvatar(LLVOAvatar *avatar) const
void FSFloaterPoser::poseControlsEnable(bool enable)
{
mAdvancedParentPnl->setEnabled(enable);
mTrackballPnl->setEnabled(enable);
mFlipPoseBtn->setEnabled(enable);
mFlipJointBtn->setEnabled(enable);
@ -1254,7 +1200,7 @@ void FSFloaterPoser::setRotationChangeButtons(bool togglingMirror, bool toggling
refreshTrackpadCursor();
}
void FSFloaterPoser::onUndoLastRotation()
void FSFloaterPoser::onUndoLastChange()
{
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
@ -1271,59 +1217,15 @@ void FSFloaterPoser::onUndoLastRotation()
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.undoLastJointRotation(avatar, *item, getUiSelectedBoneDeflectionStyle());
mPoserAnimator.undoLastJointChange(avatar, *item, getUiSelectedBoneDeflectionStyle());
}
enableOrDisableRedoButton();
refreshRotationSlidersAndSpinners();
refreshTrackpadCursor();
}
void FSFloaterPoser::onUndoLastPosition()
{
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
return;
if (!mPoserAnimator.isPosingAvatar(avatar))
return;
auto selectedJoints = getUiSelectedPoserJoints();
if (selectedJoints.size() < 1)
return;
for (auto item : selectedJoints)
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.undoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle());
}
refreshAdvancedPositionSlidersAndSpinners();
refreshPositionSlidersAndSpinners();
refreshAvatarPositionSlidersAndSpinners();
}
void FSFloaterPoser::onUndoLastScale()
{
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
return;
if (!mPoserAnimator.isPosingAvatar(avatar))
return;
auto selectedJoints = getUiSelectedPoserJoints();
if (selectedJoints.size() < 1)
return;
for (auto item : selectedJoints)
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.undoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle());
}
refreshAdvancedScaleSlidersAndSpinners();
refreshScaleSlidersAndSpinners();
}
void FSFloaterPoser::onSetAvatarToTpose()
@ -1340,11 +1242,13 @@ void FSFloaterPoser::onSetAvatarToTpose()
refreshTextHighlightingOnJointScrollLists();
}
void FSFloaterPoser::onResetPosition()
void FSFloaterPoser::onResetJoint(const LLSD data)
{
if (notDoubleClicked())
return;
int resetType = data.asInteger();
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
return;
@ -1359,41 +1263,20 @@ void FSFloaterPoser::onResetPosition()
for (auto item : selectedJoints)
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.resetJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle());
if (!currentlyPosing)
continue;
mPoserAnimator.resetJoint(avatar, *item, getUiSelectedBoneDeflectionStyle());
}
refreshAdvancedPositionSlidersAndSpinners();
refreshRotationSlidersAndSpinners();
refreshTrackpadCursor();
refreshAvatarPositionSlidersAndSpinners();
refreshPositionSlidersAndSpinners();
refreshScaleSlidersAndSpinners();
}
void FSFloaterPoser::onResetScale()
{
if (notDoubleClicked())
return;
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
return;
if (!mPoserAnimator.isPosingAvatar(avatar))
return;
auto selectedJoints = getUiSelectedPoserJoints();
if (selectedJoints.size() < 1)
return;
for (auto item : selectedJoints)
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.resetJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle());
}
refreshAdvancedScaleSlidersAndSpinners();
}
void FSFloaterPoser::onRedoLastRotation()
void FSFloaterPoser::onRedoLastChange()
{
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
@ -1410,61 +1293,17 @@ void FSFloaterPoser::onRedoLastRotation()
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.redoLastJointRotation(avatar, *item, getUiSelectedBoneDeflectionStyle());
mPoserAnimator.redoLastJointChange(avatar, *item, getUiSelectedBoneDeflectionStyle());
}
enableOrDisableRedoButton();
refreshRotationSlidersAndSpinners();
refreshTrackpadCursor();
}
void FSFloaterPoser::onRedoLastPosition()
{
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
return;
if (!mPoserAnimator.isPosingAvatar(avatar))
return;
auto selectedJoints = getUiSelectedPoserJoints();
if (selectedJoints.size() < 1)
return;
for (auto item : selectedJoints)
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.redoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle());
}
refreshAdvancedPositionSlidersAndSpinners();
refreshScaleSlidersAndSpinners();
refreshPositionSlidersAndSpinners();
refreshAvatarPositionSlidersAndSpinners();
}
void FSFloaterPoser::onRedoLastScale()
{
LLVOAvatar* avatar = getUiSelectedAvatar();
if (!avatar)
return;
if (!mPoserAnimator.isPosingAvatar(avatar))
return;
auto selectedJoints = getUiSelectedPoserJoints();
if (selectedJoints.size() < 1)
return;
for (auto item : selectedJoints)
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
mPoserAnimator.redoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle());
}
refreshAdvancedScaleSlidersAndSpinners();
}
void FSFloaterPoser::enableOrDisableRedoButton()
{
LLVOAvatar* avatar = getUiSelectedAvatar();
@ -1483,42 +1322,12 @@ void FSFloaterPoser::enableOrDisableRedoButton()
{
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
if (currentlyPosing)
shouldEnableRedoButton |= mPoserAnimator.canRedoJointRotation(avatar, *item);
shouldEnableRedoButton |= mPoserAnimator.canRedoJointChange(avatar, *item);
}
mRedoChangeBtn->setEnabled(shouldEnableRedoButton);
}
void FSFloaterPoser::onOpenSetAdvancedPanel()
{
bool advancedPanelExpanded = mToggleAdvancedPanelBtn->getValue().asBoolean();
if (advancedPanelExpanded)
onToggleAdvancedPanel();
}
void FSFloaterPoser::onToggleAdvancedPanel()
{
if (isMinimized())
return;
bool advancedPanelExpanded = mToggleAdvancedPanelBtn->getValue().asBoolean();
mAdvancedParentPnl->setVisible(advancedPanelExpanded);
// change the height of the Poser panel
S32 currentHeight = getRect().getHeight();
S32 advancedPanelHeight = mAdvancedParentPnl->getRect().getHeight();
S32 poserFloaterHeight = advancedPanelExpanded ? currentHeight + advancedPanelHeight : currentHeight - advancedPanelHeight;
S32 poserFloaterWidth = getRect().getWidth();
if (poserFloaterHeight < 0)
return;
reshape(poserFloaterWidth, poserFloaterHeight);
onJointTabSelect();
}
std::vector<FSPoserAnimator::FSPoserJoint*> FSFloaterPoser::getUiSelectedPoserJoints() const
{
std::vector<FSPoserAnimator::FSPoserJoint*> joints;
@ -1733,7 +1542,7 @@ void FSFloaterPoser::onAvatarPositionSet()
mUpDownSpnr->setValue(posZ);
setSelectedJointsPosition(posX, posY, posZ);
refreshAdvancedPositionSlidersAndSpinners();
refreshPositionSlidersAndSpinners();
}
void FSFloaterPoser::onLimbTrackballChanged()
@ -1769,13 +1578,9 @@ void FSFloaterPoser::onLimbTrackballChanged()
// as tempting as it is to refactor the following to refreshRotationSliders(), don't.
// getRotationOfFirstSelectedJoint/setSelectedJointsRotation are
// not necessarily symmetric functions (see their remarks).
mLimbYawSlider->setValue(trackPadPos.mV[VX] *= RAD_TO_DEG);
mLimbPitchSlider->setValue(trackPadPos.mV[VY] *= RAD_TO_DEG);
mLimbRollSlider->setValue(trackPadPos.mV[VZ] *= RAD_TO_DEG);
mYawSpnr->setValue(mLimbYawSlider->getValueF32());
mPitchSpnr->setValue(mLimbPitchSlider->getValueF32());
mRollSpnr->setValue(mLimbRollSlider->getValueF32());
mYawSpnr->setValue(trackPadPos.mV[VX] *= RAD_TO_DEG);
mPitchSpnr->setValue(trackPadPos.mV[VY] *= RAD_TO_DEG);
mRollSpnr->setValue(trackPadPos.mV[VZ] *= RAD_TO_DEG);
}
F32 FSFloaterPoser::unWrapScale(F32 scale)
@ -1792,12 +1597,12 @@ F32 FSFloaterPoser::unWrapScale(F32 scale)
return result;
}
void FSFloaterPoser::onYawPitchRollSliderChanged()
void FSFloaterPoser::onYawPitchRollChanged()
{
LLVector3 absoluteRotation, deltaRotation;
absoluteRotation.mV[VX] = mLimbYawSlider->getValueF32() * DEG_TO_RAD;
absoluteRotation.mV[VY] = mLimbPitchSlider->getValueF32() * DEG_TO_RAD;
absoluteRotation.mV[VZ] = mLimbRollSlider->getValueF32() * DEG_TO_RAD;
absoluteRotation.mV[VX] = (F32)mYawSpnr->getValue().asReal() * DEG_TO_RAD;
absoluteRotation.mV[VY] = (F32)mPitchSpnr->getValue().asReal() * DEG_TO_RAD;
absoluteRotation.mV[VZ] = (F32)mRollSpnr->getValue().asReal() * DEG_TO_RAD;
deltaRotation = absoluteRotation - mLastSliderRotation;
mLastSliderRotation = absoluteRotation;
@ -1817,10 +1622,6 @@ void FSFloaterPoser::onYawPitchRollSliderChanged()
absoluteRotation.mV[VZ] /= NormalTrackpadRangeInRads;
mAvatarTrackball->setValue(absoluteRotation.getValue());
mYawSpnr->setValue(mLimbYawSlider->getValueF32());
mPitchSpnr->setValue(mLimbPitchSlider->getValueF32());
mRollSpnr->setValue(mLimbRollSlider->getValueF32());
}
void FSFloaterPoser::onAdjustTrackpadSensitivity()
@ -1830,9 +1631,9 @@ void FSFloaterPoser::onAdjustTrackpadSensitivity()
void FSFloaterPoser::refreshTrackpadCursor()
{
F32 axis1 = mLimbYawSlider->getValueF32() * DEG_TO_RAD / NormalTrackpadRangeInRads;
F32 axis2 = mLimbPitchSlider->getValueF32() * DEG_TO_RAD / NormalTrackpadRangeInRads;
F32 axis3 = mLimbRollSlider->getValueF32() * DEG_TO_RAD / NormalTrackpadRangeInRads;
F32 axis1 = (F32)mYawSpnr->getValue().asReal() * DEG_TO_RAD / NormalTrackpadRangeInRads;
F32 axis2 = (F32)mPitchSpnr->getValue().asReal() * DEG_TO_RAD / NormalTrackpadRangeInRads;
F32 axis3 = (F32)mRollSpnr->getValue().asReal() * DEG_TO_RAD / NormalTrackpadRangeInRads;
F32 trackPadSensitivity = llmax(gSavedSettings.getF32(POSER_TRACKPAD_SENSITIVITY_SAVE_KEY), 0.0001f);
axis1 /= trackPadSensitivity;
@ -1867,15 +1668,12 @@ void FSFloaterPoser::refreshRotationSlidersAndSpinners()
LLVector3 rotation = getRotationOfFirstSelectedJoint();
mLastSliderRotation = rotation;
mLimbYawSlider->setValue(rotation.mV[VX] *= RAD_TO_DEG);
mYawSpnr->setValue(rotation.mV[VX]);
mLimbPitchSlider->setValue(rotation.mV[VY] *= RAD_TO_DEG);
mPitchSpnr->setValue(rotation.mV[VY]);
mLimbRollSlider->setValue(rotation.mV[VZ] *= RAD_TO_DEG);
mRollSpnr->setValue(rotation.mV[VZ]);
mYawSpnr->setValue(rotation.mV[VX] *= RAD_TO_DEG);
mPitchSpnr->setValue(rotation.mV[VY] *= RAD_TO_DEG);
mRollSpnr->setValue(rotation.mV[VZ] *= RAD_TO_DEG);
}
void FSFloaterPoser::refreshAdvancedPositionSlidersAndSpinners()
void FSFloaterPoser::refreshPositionSlidersAndSpinners()
{
LLVector3 position = getPositionOfFirstSelectedJoint();
@ -1887,7 +1685,7 @@ void FSFloaterPoser::refreshAdvancedPositionSlidersAndSpinners()
mAdvPosZSpnr->setValue(position.mV[VZ]);
}
void FSFloaterPoser::refreshAdvancedScaleSlidersAndSpinners()
void FSFloaterPoser::refreshScaleSlidersAndSpinners()
{
LLVector3 rotation = getScaleOfFirstSelectedJoint();
@ -2041,16 +1839,12 @@ LLVector3 FSFloaterPoser::getScaleOfFirstSelectedJoint() const
void FSFloaterPoser::onJointTabSelect()
{
refreshAvatarPositionSlidersAndSpinners();
refreshRotationSlidersAndSpinners();
refreshRotationSlidersAndSpinners();
refreshTrackpadCursor();
enableOrDisableRedoButton();
refreshPositionSlidersAndSpinners();
refreshScaleSlidersAndSpinners();
onClickSetBaseRotZero();
if (mToggleAdvancedPanelBtn->getValue().asBoolean())
{
refreshAdvancedPositionSlidersAndSpinners();
refreshAdvancedScaleSlidersAndSpinners();
}
}
E_BoneAxisTranslation FSFloaterPoser::getJointTranslation(const std::string& jointName) const

View File

@ -220,25 +220,19 @@ class FSFloaterPoser : public LLFloater
void onAvatarsRefresh();
void onAvatarSelect();
void onJointTabSelect();
void onToggleAdvancedPanel();
void onToggleMirrorChange();
void onToggleSympatheticChange();
void setRotationChangeButtons(bool mirror, bool sympathetic);
void onUndoLastRotation();
void onRedoLastRotation();
void onUndoLastPosition();
void onRedoLastPosition();
void onUndoLastScale();
void onRedoLastScale();
void onResetPosition();
void onResetScale();
void onUndoLastChange();
void onRedoLastChange();
void onResetJoint(const LLSD data);
void onSetAvatarToTpose();
void enableOrDisableRedoButton();
void onPoseStartStop();
void startPosingSelf();
void stopPosingAllAvatars();
void onLimbTrackballChanged();
void onYawPitchRollSliderChanged();
void onYawPitchRollChanged();
void onAvatarPositionSet();
void onAdvancedPositionSet();
void onAdvancedScaleSet();
@ -246,22 +240,20 @@ class FSFloaterPoser : public LLFloater
void onClickRecaptureSelectedBones();
void onClickFlipPose();
void onClickFlipSelectedJoints();
void onPoseJointsReset();
void onOpenSetAdvancedPanel();
void onAdjustTrackpadSensitivity();
void onClickLoadLeftHandPose();
void onClickLoadRightHandPose();
void onClickLoadHandPose(bool isRightHand);
void onClickSetBaseRotZero();
//void onCommitSpinner(LLUICtrl* spinner);
void onCommitSpinner(LLUICtrl* spinner, S32 ID);
void onClickSymmetrize(S32 ID);
// UI Refreshments
void refreshRotationSlidersAndSpinners();
void refreshAvatarPositionSlidersAndSpinners();
void refreshTrackpadCursor();
void refreshAdvancedPositionSlidersAndSpinners();
void refreshAdvancedScaleSlidersAndSpinners();
void refreshPositionSlidersAndSpinners();
void refreshScaleSlidersAndSpinners();
/// <summary>
/// Determines if we have permission to animate the supplied avatar.
@ -447,9 +439,6 @@ class FSFloaterPoser : public LLFloater
FSVirtualTrackpad* mAvatarTrackball{ nullptr };
LLSliderCtrl* mTrackpadSensitivitySlider{ nullptr };
LLSliderCtrl* mLimbYawSlider{ nullptr };
LLSliderCtrl* mLimbPitchSlider{ nullptr }; // pointing your nose up or down
LLSliderCtrl* mLimbRollSlider{ nullptr }; // your ear touches your shoulder
LLSliderCtrl* mPosXSlider{ nullptr };
LLSliderCtrl* mPosYSlider{ nullptr };
LLSliderCtrl* mPosZSlider{ nullptr };
@ -473,7 +462,6 @@ class FSFloaterPoser : public LLFloater
LLScrollListCtrl* mPosesScrollList{ nullptr };
LLScrollListCtrl* mHandPresetsScrollList{ nullptr };
LLButton* mToggleAdvancedPanelBtn{ nullptr };
LLButton* mStartStopPosingBtn{ nullptr };
LLButton* mToggleLoadSavePanelBtn{ nullptr };
LLButton* mBrowserFolderBtn{ nullptr };
@ -491,7 +479,6 @@ class FSFloaterPoser : public LLFloater
LLLineEditor* mPoseSaveNameEditor{ nullptr };
LLPanel* mAdvancedParentPnl{ nullptr };
LLPanel* mJointsParentPnl{ nullptr };
LLPanel* mTrackballPnl{ nullptr };
LLPanel* mPositionRotationPnl{ nullptr };

View File

@ -30,7 +30,7 @@
#include "llcharacter.h"
/// <summary>
/// The maximum length of any undo queue; adding new members preens older ones.
/// The maximum length of the undo queue; adding new members preens older ones.
/// </summary>
constexpr size_t MaximumUndoQueueLength = 20;
@ -48,103 +48,87 @@ FSJointPose::FSJointPose(LLJoint* joint, U32 usage, bool isCollisionVolume)
mJointName = joint->getName();
mIsCollisionVolume = isCollisionVolume;
mRotation = FSJointRotation(joint->getRotation());
mBeginningPosition = joint->getPosition();
mBeginningScale = joint->getScale();
mCurrentState = FSJointState(joint);
mBeginningState = FSJointState(joint);
}
void FSJointPose::setPositionDelta(const LLVector3& pos)
void FSJointPose::setPublicPosition(const LLVector3& pos)
{
addToUndo(mPositionDelta, &mUndonePositionIndex, &mLastSetPositionDeltas, &mTimeLastUpdatedPosition);
mPositionDelta.set(pos);
addStateToUndo(FSJointState(mCurrentState));
mCurrentState.mPosition.set(pos);
}
void FSJointPose::setRotationDelta(const LLQuaternion& rot)
void FSJointPose::setPublicRotation(const LLQuaternion& rot)
{
addToUndo(mRotation, &mUndoneRotationIndex, &mLastSetRotationDeltas, &mTimeLastUpdatedRotation);
mRotation = FSJointRotation(mRotation.baseRotation, rot);
addStateToUndo(FSJointState(mCurrentState));
mCurrentState.mRotation.set(rot);
}
void FSJointPose::setScaleDelta(const LLVector3& scale)
void FSJointPose::setPublicScale(const LLVector3& scale)
{
addToUndo(mScaleDelta, &mUndoneScaleIndex, &mLastSetScaleDeltas, &mTimeLastUpdatedScale);
mScaleDelta.set(scale);
addStateToUndo(FSJointState(mCurrentState));
mCurrentState.mScale.set(scale);
}
void FSJointPose::undoLastPositionChange()
void FSJointPose::undoLastChange()
{
mPositionDelta.set(undoLastChange(mPositionDelta, &mUndonePositionIndex, &mLastSetPositionDeltas));
mCurrentState = undoLastStateChange(FSJointState(mCurrentState));
}
void FSJointPose::undoLastRotationChange()
void FSJointPose::redoLastChange()
{
mRotation.set(undoLastChange(mRotation, &mUndoneRotationIndex, &mLastSetRotationDeltas));
mCurrentState = redoLastStateChange(FSJointState(mCurrentState));
}
void FSJointPose::undoLastScaleChange() { mScaleDelta.set(undoLastChange(mScaleDelta, &mUndoneScaleIndex, &mLastSetScaleDeltas)); }
void FSJointPose::redoLastPositionChange()
void FSJointPose::addStateToUndo(FSJointState stateToAddToUndo)
{
mPositionDelta.set(redoLastChange(mPositionDelta, &mUndonePositionIndex, &mLastSetPositionDeltas));
}
void FSJointPose::redoLastRotationChange()
{
mRotation.set(redoLastChange(mRotation, &mUndoneRotationIndex, &mLastSetRotationDeltas));
}
void FSJointPose::redoLastScaleChange() { mScaleDelta.set(redoLastChange(mScaleDelta, &mUndoneScaleIndex, &mLastSetScaleDeltas)); }
template <typename T>
inline void FSJointPose::addToUndo(T delta, size_t* undoIndex, std::deque<T>* dequeue,
std::chrono::system_clock::time_point* timeLastUpdated)
{
auto timeIntervalSinceLastChange = std::chrono::system_clock::now() - *timeLastUpdated;
*timeLastUpdated = std::chrono::system_clock::now();
auto timeIntervalSinceLastChange = std::chrono::system_clock::now() - mTimeLastUpdatedCurrentState;
mTimeLastUpdatedCurrentState = std::chrono::system_clock::now();
if (timeIntervalSinceLastChange < UndoUpdateInterval)
return;
if (*undoIndex > 0)
if (mUndoneJointStatesIndex > 0)
{
for (size_t i = 0; i < *undoIndex; i++)
dequeue->pop_front();
for (size_t i = 0; i <= mUndoneJointStatesIndex; i++)
if (!mLastSetJointStates.empty())
mLastSetJointStates.pop_front();
*undoIndex = 0;
mUndoneJointStatesIndex = 0;
}
dequeue->push_front(delta);
mLastSetJointStates.push_front(stateToAddToUndo);
while (dequeue->size() > MaximumUndoQueueLength)
dequeue->pop_back();
while (mLastSetJointStates.size() > MaximumUndoQueueLength)
mLastSetJointStates.pop_back();
}
template <typename T> T FSJointPose::undoLastChange(T thingToSet, size_t* undoIndex, std::deque<T>* dequeue)
FSJointPose::FSJointState FSJointPose::undoLastStateChange(FSJointState thingToSet)
{
if (dequeue->empty())
if (mLastSetJointStates.empty())
return thingToSet;
if (*undoIndex == 0)
dequeue->push_front(thingToSet);
if (mUndoneJointStatesIndex == 0)
mLastSetJointStates.push_front(thingToSet);
*undoIndex += 1;
*undoIndex = llclamp(*undoIndex, 0, dequeue->size() - 1);
mUndoneJointStatesIndex += 1;
mUndoneJointStatesIndex = llclamp(mUndoneJointStatesIndex, 0, mLastSetJointStates.size() - 1);
return dequeue->at(*undoIndex);
return mLastSetJointStates.at(mUndoneJointStatesIndex);
}
template <typename T> T FSJointPose::redoLastChange(T thingToSet, size_t* undoIndex, std::deque<T>* dequeue)
FSJointPose::FSJointState FSJointPose::redoLastStateChange(FSJointState thingToSet)
{
if (dequeue->empty())
if (mLastSetJointStates.empty())
return thingToSet;
if (*undoIndex == 0)
if (mUndoneJointStatesIndex == 0)
return thingToSet;
*undoIndex -= 1;
*undoIndex = llclamp(*undoIndex, 0, dequeue->size() - 1);
T result = dequeue->at(*undoIndex);
if (*undoIndex == 0)
dequeue->pop_front();
mUndoneJointStatesIndex -= 1;
mUndoneJointStatesIndex = llclamp(mUndoneJointStatesIndex, 0, mLastSetJointStates.size() - 1);
auto result = mLastSetJointStates.at(mUndoneJointStatesIndex);
if (mUndoneJointStatesIndex == 0)
mLastSetJointStates.pop_front();
return result;
}
@ -158,8 +142,8 @@ void FSJointPose::recaptureJoint()
if (!joint)
return;
addToUndo(mRotation, &mUndoneRotationIndex, &mLastSetRotationDeltas, &mTimeLastUpdatedRotation);
mRotation = FSJointRotation(joint->getRotation());
addStateToUndo(FSJointState(mCurrentState));
mCurrentState = FSJointState(joint);
}
void FSJointPose::swapRotationWith(FSJointPose* oppositeJoint)
@ -169,9 +153,9 @@ void FSJointPose::swapRotationWith(FSJointPose* oppositeJoint)
if (mIsCollisionVolume)
return;
auto tempRot = FSJointRotation(mRotation);
mRotation = FSJointRotation(oppositeJoint->mRotation);
oppositeJoint->mRotation = tempRot;
auto tempState = FSJointState(mCurrentState);
mCurrentState.cloneRotationFrom(oppositeJoint->mCurrentState);
oppositeJoint->mCurrentState.cloneRotationFrom(tempState);
}
void FSJointPose::cloneRotationFrom(FSJointPose* fromJoint)
@ -179,8 +163,8 @@ void FSJointPose::cloneRotationFrom(FSJointPose* fromJoint)
if (!fromJoint)
return;
addToUndo(mRotation, &mUndoneRotationIndex, &mLastSetRotationDeltas, &mTimeLastUpdatedRotation);
mRotation = FSJointRotation(fromJoint->mRotation);
addStateToUndo(FSJointState(mCurrentState));
mCurrentState.cloneRotationFrom(fromJoint->mCurrentState);
}
void FSJointPose::mirrorRotationFrom(FSJointPose* fromJoint)
@ -189,11 +173,7 @@ void FSJointPose::mirrorRotationFrom(FSJointPose* 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]);
mCurrentState.reflectRotation();
}
void FSJointPose::revertJoint()
@ -202,9 +182,9 @@ void FSJointPose::revertJoint()
if (!joint)
return;
joint->setRotation(mRotation.baseRotation);
joint->setPosition(mBeginningPosition);
joint->setScale(mBeginningScale);
joint->setRotation(mBeginningState.getTargetRotation());
joint->setPosition(mBeginningState.getTargetPosition());
joint->setScale(mBeginningState.getTargetScale());
}
void FSJointPose::reflectRotation()
@ -212,7 +192,7 @@ void FSJointPose::reflectRotation()
if (mIsCollisionVolume)
return;
mRotation.reflectRotation();
mCurrentState.reflectRotation();
}
void FSJointPose::zeroBaseRotation()
@ -220,7 +200,7 @@ void FSJointPose::zeroBaseRotation()
if (mIsCollisionVolume)
return;
mRotation.baseRotation = LLQuaternion::DEFAULT;
mBeginningState.mRotation = LLQuaternion::DEFAULT;
}
bool FSJointPose::isBaseRotationZero() const
@ -228,5 +208,5 @@ bool FSJointPose::isBaseRotationZero() const
if (mIsCollisionVolume)
return true;
return mRotation.baseRotation == LLQuaternion::DEFAULT;
return mBeginningState.mRotation == LLQuaternion::DEFAULT;
}

View File

@ -58,34 +58,39 @@ class FSJointPose
bool isCollisionVolume() const { return mIsCollisionVolume; }
/// <summary>
/// Gets the position change the animator wishes the joint to have.
/// Gets the 'public' position of the joint.
/// </summary>
LLVector3 getPositionDelta() const { return mPositionDelta; }
LLVector3 getPublicPosition() const { return mCurrentState.mPosition; }
/// <summary>
/// Sets the position the animator wishes the joint to be in.
/// Sets the 'public' position of the joint.
/// </summary>
void setPositionDelta(const LLVector3& pos);
void setPublicPosition(const LLVector3& pos);
/// <summary>
/// Undoes the last position set, if any.
/// </summary>
void undoLastPositionChange();
void undoLastChange();
/// <summary>
/// Undoes the last position set, if any.
/// </summary>
void redoLastPositionChange();
void redoLastChange();
/// <summary>
/// Gets the rotation the animator wishes the joint to be in.
/// Gets the 'public' rotation of the joint.
/// </summary>
LLQuaternion getRotationDelta() const { return mRotation.deltaRotation; }
LLQuaternion getPublicRotation() const { return mCurrentState.mRotation; }
/// <summary>
/// Sets the rotation the animator wishes the joint to be in.
/// Sets the 'public' rotation of the joint.
/// </summary>
void setRotationDelta(const LLQuaternion& rot);
/// <remarks>
/// 'Public rotation' is the amount of rotation the user has added to the initial state.
/// Public rotation is what a user may save to an external format (such as BVH).
/// This distinguishes 'private' rotation, which is the state inherited from something like a pose in-world.
/// </remarks>
void setPublicRotation(const LLQuaternion& rot);
/// <summary>
/// Reflects the base and delta rotation of the represented joint left-right.
@ -93,7 +98,7 @@ class FSJointPose
void reflectRotation();
/// <summary>
/// Sets the base rotation of the represented joint to zero.
/// Sets the private rotation of the represented joint to zero.
/// </summary>
void zeroBaseRotation();
@ -104,43 +109,20 @@ class FSJointPose
bool isBaseRotationZero() const;
/// <summary>
/// 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.
/// Gets whether a redo of this joint may be performed.
/// </summary>
void undoLastRotationChange();
/// <returns>true if the joint may have a redo applied, otherwise false.</returns>
bool canPerformRedo() const { return mUndoneJointStatesIndex > 0; }
/// <summary>
/// Redoes the last rotation set, if any.
/// Gets the 'public' scale of the joint.
/// </summary>
void redoLastRotationChange();
LLVector3 getPublicScale() const { return mCurrentState.mScale; }
/// <summary>
/// Gets whether a redo of this joints rotation may be performed.
/// Sets the 'public' scale of the joint.
/// </summary>
/// <returns>true if the joint can have a redo applied, otherwise false.</returns>
bool canRedoRotation() const { return mUndoneRotationIndex > 0; }
/// <summary>
/// Gets the scale the animator wishes the joint to have.
/// </summary>
LLVector3 getScaleDelta() const { return mScaleDelta; }
/// <summary>
/// Sets the scale the animator wishes the joint to have.
/// </summary>
void setScaleDelta(const LLVector3& scale);
/// <summary>
/// Undoes the last scale set, if any.
/// </summary>
void undoLastScaleChange();
/// <summary>
/// Redoes the last scale set, if any.
/// </summary>
void redoLastScaleChange();
void setPublicScale(const LLVector3& scale);
/// <summary>
/// Exchanges the rotations between two joints.
@ -168,52 +150,69 @@ class FSJointPose
/// </summary>
void revertJoint();
LLVector3 getTargetPosition() const { return mPositionDelta + mBeginningPosition; }
LLQuaternion getTargetRotation() const { return mRotation.getTargetRotation(); }
LLVector3 getTargetScale() const { return mScaleDelta + mBeginningScale; }
LLQuaternion getTargetRotation() const { return mCurrentState.getTargetRotation(); }
LLVector3 getTargetPosition() const { return mCurrentState.getTargetPosition(); }
LLVector3 getTargetScale() const { return mCurrentState.getTargetScale(); }
/// <summary>
/// Gets the pointer to the jointstate for the joint this represents.
/// </summary>
LLPointer<LLJointState> getJointState() const { return mJointState; }
/// <summary>
/// A class wrapping base and delta rotation, attempting to keep baseRotation as secret as possible.
/// Among other things, facilitates easy undo/redo through the joint-recapture process.
/// </summary>
class FSJointRotation
class FSJointState
{
public:
FSJointRotation(LLQuaternion base) { baseRotation.set(base); }
FSJointRotation(LLQuaternion base, LLQuaternion delta)
FSJointState(LLJoint* joint)
{
baseRotation.set(base);
deltaRotation.set(delta);
mBaseRotation.set(joint->getRotation());
mBasePosition.set(joint->getPosition());
mBaseScale.set(joint->getScale());
}
FSJointRotation() = default;
FSJointState() = default;
LLQuaternion baseRotation;
LLQuaternion deltaRotation;
LLQuaternion getTargetRotation() const { return deltaRotation * baseRotation; }
LLQuaternion getTargetRotation() const { return mRotation * mBaseRotation; }
LLVector3 getTargetPosition() const { return mPosition + mBasePosition; }
LLVector3 getTargetScale() const { return mScale + mBaseScale; }
void reflectRotation()
{
baseRotation.mQ[VX] *= -1;
baseRotation.mQ[VZ] *= -1;
deltaRotation.mQ[VX] *= -1;
deltaRotation.mQ[VZ] *= -1;
mBaseRotation.mQ[VX] *= -1;
mBaseRotation.mQ[VZ] *= -1;
mRotation.mQ[VX] *= -1;
mRotation.mQ[VZ] *= -1;
}
void set(const FSJointRotation& jRot)
void cloneRotationFrom(FSJointState otherState)
{
baseRotation.set(jRot.baseRotation);
deltaRotation.set(jRot.deltaRotation);
mBaseRotation.set(otherState.mBaseRotation);
mRotation.set(otherState.mRotation);
}
private:
FSJointState(FSJointState* state)
{
mBaseRotation.set(state->mBaseRotation);
mBasePosition.set(state->mBasePosition);
mBaseScale.set(state->mBaseScale);
mRotation.set(state->mRotation);
mPosition.set(state->mPosition);
mScale.set(state->mScale);
}
public:
LLQuaternion mRotation;
LLVector3 mPosition;
LLVector3 mScale;
private:
LLQuaternion mBaseRotation;
LLVector3 mBasePosition;
LLVector3 mBaseScale;
};
private:
private:
std::string mJointName = ""; // expected to be a match to LLJoint.getName() for a joint implementation.
LLPointer<LLJointState> mJointState{ nullptr };
@ -223,32 +222,16 @@ private:
/// </summary>
bool mIsCollisionVolume{ false };
FSJointRotation mRotation;
std::deque<FSJointRotation> mLastSetRotationDeltas;
size_t mUndoneRotationIndex = 0;
std::chrono::system_clock::time_point mTimeLastUpdatedRotation = std::chrono::system_clock::now();
std::deque<FSJointState> mLastSetJointStates;
size_t mUndoneJointStatesIndex = 0;
std::chrono::system_clock::time_point mTimeLastUpdatedCurrentState = std::chrono::system_clock::now();
LLVector3 mPositionDelta;
LLVector3 mBeginningPosition;
std::deque<LLVector3> mLastSetPositionDeltas;
size_t mUndonePositionIndex = 0;
std::chrono::system_clock::time_point mTimeLastUpdatedPosition = std::chrono::system_clock::now();
FSJointState mCurrentState;
FSJointState mBeginningState;
/// <summary>
/// Joint scales require special treatment, as they do not revert when we stop animating an avatar.
/// </summary>
LLVector3 mScaleDelta;
LLVector3 mBeginningScale;
std::deque<LLVector3> mLastSetScaleDeltas;
size_t mUndoneScaleIndex = 0;
std::chrono::system_clock::time_point mTimeLastUpdatedScale = std::chrono::system_clock::now();
template <typename T>
void addToUndo(T delta, size_t* undoIndex, std::deque<T>* dequeue, std::chrono::system_clock::time_point* timeLastUpdated);
template <typename T> T undoLastChange(T thingToSet, size_t* undoIndex, std::deque<T>* dequeue);
template <typename T> T redoLastChange(T thingToSet, size_t* undoIndex, std::deque<T>* dequeue);
void addStateToUndo(FSJointState stateToAddToUndo);
FSJointState undoLastStateChange(FSJointState currentState);
FSJointState redoLastStateChange(FSJointState currentState);
};
#endif // FS_JOINTPPOSE_H

View File

@ -78,7 +78,7 @@ void FSPoserAnimator::setPosingAvatarJoint(LLVOAvatar* avatar, const FSPoserJoin
posingMotion->removeJointFromState(jointPose);
}
void FSPoserAnimator::resetAvatarJoint(LLVOAvatar* avatar, const FSPoserJoint& joint)
void FSPoserAnimator::undoLastJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
@ -94,27 +94,7 @@ void FSPoserAnimator::resetAvatarJoint(LLVOAvatar* avatar, const FSPoserJoint& j
if (!jointPose)
return;
jointPose->setPositionDelta(LLVector3());
jointPose->setRotationDelta(LLQuaternion());
}
void FSPoserAnimator::undoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
FSPosingMotion* posingMotion = getPosingMotion(avatar);
if (!posingMotion)
return;
if (posingMotion->isStopped())
return;
FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
if (!jointPose)
return;
jointPose->undoLastRotationChange();
jointPose->undoLastChange();
if (style == NONE || style == DELTAMODE)
return;
@ -123,10 +103,10 @@ void FSPoserAnimator::undoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoi
if (!oppositeJointPose)
return;
oppositeJointPose->undoLastRotationChange();
oppositeJointPose->undoLastChange();
}
void FSPoserAnimator::undoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
void FSPoserAnimator::resetJoint(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
@ -142,7 +122,9 @@ void FSPoserAnimator::undoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoi
if (!jointPose)
return;
jointPose->undoLastPositionChange();
jointPose->setPublicRotation(LLQuaternion());
jointPose->setPublicPosition(LLVector3());
jointPose->setPublicScale(LLVector3());
if (style == NONE || style == DELTAMODE)
return;
@ -151,94 +133,12 @@ void FSPoserAnimator::undoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoi
if (!oppositeJointPose)
return;
oppositeJointPose->undoLastPositionChange();
oppositeJointPose->setPublicRotation(LLQuaternion());
oppositeJointPose->setPublicPosition(LLVector3());
oppositeJointPose->setPublicScale(LLVector3());
}
void FSPoserAnimator::undoLastJointScale(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
FSPosingMotion* posingMotion = getPosingMotion(avatar);
if (!posingMotion)
return;
if (posingMotion->isStopped())
return;
FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
if (!jointPose)
return;
jointPose->undoLastScaleChange();
if (style == NONE || style == DELTAMODE)
return;
FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
if (!oppositeJointPose)
return;
oppositeJointPose->undoLastScaleChange();
}
void FSPoserAnimator::resetJointPosition(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
FSPosingMotion* posingMotion = getPosingMotion(avatar);
if (!posingMotion)
return;
if (posingMotion->isStopped())
return;
FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
if (!jointPose)
return;
jointPose->setPositionDelta(LLVector3());
if (style == NONE || style == DELTAMODE)
return;
FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
if (!oppositeJointPose)
return;
oppositeJointPose->setPositionDelta(LLVector3());
}
void FSPoserAnimator::resetJointScale(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
FSPosingMotion* posingMotion = getPosingMotion(avatar);
if (!posingMotion)
return;
if (posingMotion->isStopped())
return;
FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
if (!jointPose)
return;
jointPose->setScaleDelta(LLVector3());
if (style == NONE || style == DELTAMODE)
return;
FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
if (!oppositeJointPose)
return;
oppositeJointPose->setScaleDelta(LLVector3());
}
bool FSPoserAnimator::canRedoJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint)
bool FSPoserAnimator::canRedoJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint)
{
if (!isAvatarSafeToUse(avatar))
return false;
@ -254,10 +154,10 @@ bool FSPoserAnimator::canRedoJointRotation(LLVOAvatar* avatar, const FSPoserJoin
if (!jointPose)
return false;
return jointPose->canRedoRotation();
return jointPose->canPerformRedo();
}
void FSPoserAnimator::redoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
void FSPoserAnimator::redoLastJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
@ -273,7 +173,7 @@ void FSPoserAnimator::redoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoi
if (!jointPose)
return;
jointPose->redoLastRotationChange();
jointPose->redoLastChange();
if (style == NONE || style == DELTAMODE)
return;
@ -282,63 +182,7 @@ void FSPoserAnimator::redoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoi
if (!oppositeJointPose)
return;
oppositeJointPose->redoLastRotationChange();
}
void FSPoserAnimator::redoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
FSPosingMotion* posingMotion = getPosingMotion(avatar);
if (!posingMotion)
return;
if (posingMotion->isStopped())
return;
FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
if (!jointPose)
return;
jointPose->redoLastPositionChange();
if (style == NONE || style == DELTAMODE)
return;
FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
if (!oppositeJointPose)
return;
oppositeJointPose->redoLastPositionChange();
}
void FSPoserAnimator::redoLastJointScale(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style)
{
if (!isAvatarSafeToUse(avatar))
return;
FSPosingMotion* posingMotion = getPosingMotion(avatar);
if (!posingMotion)
return;
if (posingMotion->isStopped())
return;
FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
if (!jointPose)
return;
jointPose->redoLastScaleChange();
if (style == NONE || style == DELTAMODE)
return;
FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
if (!oppositeJointPose)
return;
oppositeJointPose->redoLastScaleChange();
oppositeJointPose->redoLastChange();
}
LLVector3 FSPoserAnimator::getJointPosition(LLVOAvatar* avatar, const FSPoserJoint& joint) const
@ -355,7 +199,7 @@ LLVector3 FSPoserAnimator::getJointPosition(LLVOAvatar* avatar, const FSPoserJoi
if (!jointPose)
return pos;
return jointPose->getPositionDelta();
return jointPose->getPublicPosition();
}
void FSPoserAnimator::setJointPosition(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& position, E_BoneDeflectionStyles style)
@ -377,7 +221,7 @@ void FSPoserAnimator::setJointPosition(LLVOAvatar* avatar, const FSPoserJoint* j
if (!jointPose)
return;
LLVector3 positionDelta = jointPose->getPositionDelta() - position;
LLVector3 positionDelta = jointPose->getPublicPosition() - position;
switch (style)
{
@ -385,13 +229,13 @@ void FSPoserAnimator::setJointPosition(LLVOAvatar* avatar, const FSPoserJoint* j
case MIRROR_DELTA:
case SYMPATHETIC_DELTA:
case SYMPATHETIC:
jointPose->setPositionDelta(position);
jointPose->setPublicPosition(position);
break;
case DELTAMODE:
case NONE:
default:
jointPose->setPositionDelta(position);
jointPose->setPublicPosition(position);
return;
}
@ -399,18 +243,18 @@ void FSPoserAnimator::setJointPosition(LLVOAvatar* avatar, const FSPoserJoint* j
if (!oppositeJointPose)
return;
LLVector3 oppositeJointPosition = oppositeJointPose->getPositionDelta();
LLVector3 oppositeJointPosition = oppositeJointPose->getPublicPosition();
switch (style)
{
case MIRROR:
case MIRROR_DELTA:
oppositeJointPose->setPositionDelta(oppositeJointPosition + positionDelta);
oppositeJointPose->setPublicPosition(oppositeJointPosition + positionDelta);
break;
case SYMPATHETIC_DELTA:
case SYMPATHETIC:
oppositeJointPose->setPositionDelta(oppositeJointPosition - positionDelta);
oppositeJointPose->setPublicPosition(oppositeJointPosition - positionDelta);
break;
default:
@ -493,7 +337,7 @@ LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar* avatar, const FSPoserJoi
if (!jointPose)
return vec3;
return translateRotationFromQuaternion(translation, negation, jointPose->getRotationDelta());
return translateRotationFromQuaternion(translation, negation, jointPose->getPublicRotation());
}
void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& absRotation,
@ -523,27 +367,27 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* j
case SYMPATHETIC:
case MIRROR:
if (rotationStyle == DELTAIC_ROT)
jointPose->setRotationDelta(deltaRot * jointPose->getRotationDelta());
jointPose->setPublicRotation(deltaRot * jointPose->getPublicRotation());
else
jointPose->setRotationDelta(absRot);
jointPose->setPublicRotation(absRot);
break;
case SYMPATHETIC_DELTA:
case MIRROR_DELTA:
jointPose->setRotationDelta(deltaRot * jointPose->getRotationDelta());
jointPose->setPublicRotation(deltaRot * jointPose->getPublicRotation());
break;
case DELTAMODE:
jointPose->setRotationDelta(deltaRot * jointPose->getRotationDelta());
jointPose->setPublicRotation(deltaRot * jointPose->getPublicRotation());
return;
case NONE:
default:
if (rotationStyle == DELTAIC_ROT)
jointPose->setRotationDelta(deltaRot * jointPose->getRotationDelta());
jointPose->setPublicRotation(deltaRot * jointPose->getPublicRotation());
else
jointPose->setRotationDelta(absRot);
jointPose->setPublicRotation(absRot);
return;
}
@ -560,7 +404,7 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* j
break;
case SYMPATHETIC_DELTA:
oppositeJointPose->setRotationDelta(deltaRot * oppositeJointPose->getRotationDelta());
oppositeJointPose->setPublicRotation(deltaRot * oppositeJointPose->getPublicRotation());
break;
case MIRROR:
@ -569,7 +413,7 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* j
case MIRROR_DELTA:
inv_quat = LLQuaternion(-deltaRot.mQ[VX], deltaRot.mQ[VY], -deltaRot.mQ[VZ], deltaRot.mQ[VW]);
oppositeJointPose->setRotationDelta(inv_quat * oppositeJointPose->getRotationDelta());
oppositeJointPose->setPublicRotation(inv_quat * oppositeJointPose->getPublicRotation());
break;
default:
@ -603,6 +447,45 @@ void FSPoserAnimator::reflectJoint(LLVOAvatar* avatar, const FSPoserJoint* joint
}
}
void FSPoserAnimator::symmetrizeLeftToRightOrRightToLeft(LLVOAvatar* avatar, bool rightToLeft)
{
if (!isAvatarSafeToUse(avatar))
return;
FSPosingMotion* posingMotion = getPosingMotion(avatar);
if (!posingMotion)
return;
for (size_t index = 0; index != PoserJoints.size(); ++index)
{
if (!PoserJoints[index].dontFlipOnMirror())
continue;
bool currentlyPosing = isPosingAvatarJoint(avatar, PoserJoints[index]);
if (!currentlyPosing)
continue;
auto oppositeJoint = getPoserJointByName(PoserJoints[index].mirrorJointName());
if (!oppositeJoint)
continue;
bool currentlyPosingOppositeJoint = isPosingAvatarJoint(avatar, *oppositeJoint);
if (!currentlyPosingOppositeJoint)
continue;
FSJointPose* rightJointPose = posingMotion->getJointPoseByJointName(PoserJoints[index].jointName());
FSJointPose* leftJointPose = posingMotion->getJointPoseByJointName(oppositeJoint->jointName());
if (!leftJointPose || !rightJointPose)
return;
if (rightToLeft)
leftJointPose->mirrorRotationFrom(rightJointPose);
else
rightJointPose->mirrorRotationFrom(leftJointPose);
}
}
void FSPoserAnimator::flipEntirePose(LLVOAvatar* avatar)
{
if (!isAvatarSafeToUse(avatar))
@ -750,7 +633,7 @@ LLVector3 FSPoserAnimator::getJointScale(LLVOAvatar* avatar, const FSPoserJoint&
if (!jointPose)
return scale;
return jointPose->getScaleDelta();
return jointPose->getPublicScale();
}
void FSPoserAnimator::setJointScale(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& scale, E_BoneDeflectionStyles style)
@ -772,7 +655,7 @@ void FSPoserAnimator::setJointScale(LLVOAvatar* avatar, const FSPoserJoint* join
if (!jointPose)
return;
jointPose->setScaleDelta(scale);
jointPose->setPublicScale(scale);
FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName());
if (!oppositeJointPose)
return;
@ -783,7 +666,7 @@ void FSPoserAnimator::setJointScale(LLVOAvatar* avatar, const FSPoserJoint* join
case MIRROR:
case SYMPATHETIC_DELTA:
case MIRROR_DELTA:
oppositeJointPose->setScaleDelta(scale);
oppositeJointPose->setPublicScale(scale);
break;
case DELTAMODE:
@ -810,10 +693,10 @@ bool FSPoserAnimator::tryGetJointSaveVectors(LLVOAvatar* avatar, const FSPoserJo
if (!jointPose)
return false;
LLQuaternion rotationDelta = jointPose->getRotationDelta();
LLQuaternion rotationDelta = jointPose->getPublicRotation();
rotationDelta.getEulerAngles(&rot->mV[VX], &rot->mV[VY], &rot->mV[VZ]);
pos->set(jointPose->getPositionDelta());
scale->set(jointPose->getScaleDelta());
pos->set(jointPose->getPublicPosition());
scale->set(jointPose->getPublicScale());
*baseRotationIsZero = jointPose->isBaseRotationZero();
return true;
@ -836,7 +719,7 @@ void FSPoserAnimator::loadJointRotation(LLVOAvatar* avatar, const FSPoserJoint*
jointPose->zeroBaseRotation();
LLQuaternion rot = translateRotationToQuaternion(SWAP_NOTHING, NEGATE_NOTHING, rotation);
jointPose->setRotationDelta(rot);
jointPose->setPublicRotation(rot);
}
void FSPoserAnimator::loadJointPosition(LLVOAvatar* avatar, const FSPoserJoint* joint, bool loadPositionAsDelta, LLVector3 position)
@ -853,9 +736,9 @@ void FSPoserAnimator::loadJointPosition(LLVOAvatar* avatar, const FSPoserJoint*
return;
if (loadPositionAsDelta)
jointPose->setPositionDelta(position);
jointPose->setPublicPosition(position);
else
jointPose->setPositionDelta(position);
jointPose->setPublicPosition(position);
}
void FSPoserAnimator::loadJointScale(LLVOAvatar* avatar, const FSPoserJoint* joint, bool loadScaleAsDelta, LLVector3 scale)
@ -872,9 +755,9 @@ void FSPoserAnimator::loadJointScale(LLVOAvatar* avatar, const FSPoserJoint* joi
return;
if (loadScaleAsDelta)
jointPose->setScaleDelta(scale);
jointPose->setPublicScale(scale);
else
jointPose->setScaleDelta(scale);
jointPose->setPublicScale(scale);
}
const FSPoserAnimator::FSPoserJoint* FSPoserAnimator::getPoserJointByName(const std::string& jointName)

View File

@ -398,46 +398,19 @@ public:
void setPosingAvatarJoint(LLVOAvatar* avatar, const FSPoserJoint& joint, bool shouldPose);
/// <summary>
/// Resets the supplied PoserJoint to its position/rotation/scale it was when poser was started.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint to be reset.</param>
void resetAvatarJoint(LLVOAvatar* avatar, const FSPoserJoint& joint);
/// <summary>
/// Undoes the last applied rotation to the supplied PoserJoint.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint with the rotation to undo.</param>
void undoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <summary>
/// Undoes the last applied position to the supplied PoserJoint.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint with the position to undo.</param>
void undoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <summary>
/// Undoes the last applied scale to the supplied PoserJoint.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint with the scale to undo.</param>
void undoLastJointScale(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <summary>
/// Resets the position of the supplied PoserJoint.
/// Resets the supplied PoserJoint to the position it had when poser was started.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint with the position to reset.</param>
void resetJointPosition(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <param name="style">The style to apply the reset with; if a style that support more than one joint, more that one joint will be reset.</param>
void resetJoint(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <summary>
/// Resets the scale of the supplied joint to initial values.
/// Undoes the last applied change (rotation, position or scale) to the supplied PoserJoint.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint with the scale to reset.</param>
void resetJointScale(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <param name="joint">The joint with the rotation to undo.</param>
void undoLastJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <summary>
/// Determines if a redo action is currently permitted for the supplied joint.
@ -445,28 +418,14 @@ public:
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint to query.</param>
/// <returns>True if a redo action is available, otherwise false.</returns>
bool canRedoJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint);
bool canRedoJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint);
/// <summary>
/// Re-does the last undone rotation to the supplied PoserJoint.
/// Re-does the last undone change (rotation, position or scale) to the supplied PoserJoint.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint with the rotation to redo.</param>
void redoLastJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <summary>
/// Re-does the last undone position to the supplied PoserJoint.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint with the position to redo.</param>
void redoLastJointPosition(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <summary>
/// Re-does the last undone scale to the supplied PoserJoint.
/// </summary>
/// <param name="avatar">The avatar having the joint to which we refer.</param>
/// <param name="joint">The joint with the scale to redo.</param>
void redoLastJointScale(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
void redoLastJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneDeflectionStyles style);
/// <summary>
/// Gets the position of a joint for the supplied avatar.
@ -541,6 +500,13 @@ public:
/// <param name="avatar">The avatar whose pose should flip left-right.</param>
void flipEntirePose(LLVOAvatar* avatar);
/// <summary>
/// Symmetrizes the rotations of the joints from one side of the supplied avatar to the other.
/// </summary>
/// <param name="avatar">The avatar whose joints to symmetrizet.</param>
/// <param name="rightToLeft">Whether to symmetrize rotations from right to left, otherwise symmetrize left to right.</param>
void symmetrizeLeftToRightOrRightToLeft(LLVOAvatar* avatar, bool rightToLeft);
/// <summary>
/// Recaptures the rotation, position and scale state of the supplied joint for the supplied avatar.
/// </summary>

View File

@ -260,7 +260,7 @@ void FSPosingMotion::setAllRotationsToZero()
for (auto poserJoint_iter = mJointPoses.begin(); poserJoint_iter != mJointPoses.end(); ++poserJoint_iter)
{
poserJoint_iter->zeroBaseRotation();
poserJoint_iter->setRotationDelta(LLQuaternion::DEFAULT);
poserJoint_iter->setPublicRotation(LLQuaternion::DEFAULT);
}
}

File diff suppressed because it is too large Load Diff