FIRE-30873: Add redo buttons to advanced areas
parent
d0465c9e6e
commit
aebd67f10d
|
|
@ -130,8 +130,11 @@ FSFloaterPoser::FSFloaterPoser(const LLSD& key) : LLFloater(key)
|
|||
mCommitCallbackRegistrar.add("Poser.Advanced.RotationSet", boost::bind(&FSFloaterPoser::onAdvancedRotationSet, this));
|
||||
mCommitCallbackRegistrar.add("Poser.Advanced.ScaleSet", boost::bind(&FSFloaterPoser::onAdvancedScaleSet, this));
|
||||
mCommitCallbackRegistrar.add("Poser.UndoLastPosition", boost::bind(&FSFloaterPoser::onUndoLastPosition, this));
|
||||
mCommitCallbackRegistrar.add("Poser.RedoLastPosition", boost::bind(&FSFloaterPoser::onRedoLastPosition, this));
|
||||
mCommitCallbackRegistrar.add("Poser.ResetPosition", boost::bind(&FSFloaterPoser::onResetPosition, this));
|
||||
mCommitCallbackRegistrar.add("Poser.ResetScale", boost::bind(&FSFloaterPoser::onResetScale, this));
|
||||
mCommitCallbackRegistrar.add("Poser.UndoLastScale", boost::bind(&FSFloaterPoser::onUndoLastScale, this));
|
||||
mCommitCallbackRegistrar.add("Poser.RedoLastScale", boost::bind(&FSFloaterPoser::onRedoLastScale, this));
|
||||
|
||||
mCommitCallbackRegistrar.add("Poser.Save", boost::bind(&FSFloaterPoser::onClickPoseSave, this));
|
||||
mCommitCallbackRegistrar.add("Pose.Menu", boost::bind(&FSFloaterPoser::onPoseMenuAction, this, _2));
|
||||
|
|
@ -979,14 +982,11 @@ void FSFloaterPoser::onUndoLastRotation()
|
|||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
bool shouldEnableRedoButton = false;
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = _poserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
_poserAnimator.undoLastJointRotation(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
|
||||
shouldEnableRedoButton |= _poserAnimator.canRedoJointRotation(avatar, *item);
|
||||
}
|
||||
|
||||
enableOrDisableRedoButton();
|
||||
|
|
@ -1007,7 +1007,6 @@ void FSFloaterPoser::onUndoLastPosition()
|
|||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
bool shouldEnableRedoButton = false;
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = _poserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
|
|
@ -1016,9 +1015,10 @@ void FSFloaterPoser::onUndoLastPosition()
|
|||
}
|
||||
|
||||
refreshAdvancedPositionSliders();
|
||||
refreshAvatarPositionSliders();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onResetPosition()
|
||||
void FSFloaterPoser::onUndoLastScale()
|
||||
{
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
|
|
@ -1031,7 +1031,35 @@ void FSFloaterPoser::onResetPosition()
|
|||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
bool shouldEnableRedoButton = false;
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = _poserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
_poserAnimator.undoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedScaleSliders();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onResetPosition()
|
||||
{
|
||||
// This is a double-click function: it needs to run twice within some amount of time to complete.
|
||||
auto timeIntervalSinceLastClick = std::chrono::system_clock::now() - _timeLastClickedJointReset;
|
||||
_timeLastClickedJointReset = std::chrono::system_clock::now();
|
||||
if (timeIntervalSinceLastClick > _doubleClickInterval)
|
||||
return;
|
||||
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
return;
|
||||
|
||||
if (!_poserAnimator.isPosingAvatar(avatar))
|
||||
return;
|
||||
|
||||
auto selectedJoints = getUiSelectedPoserJoints();
|
||||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = _poserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
|
|
@ -1040,10 +1068,17 @@ void FSFloaterPoser::onResetPosition()
|
|||
}
|
||||
|
||||
refreshAdvancedPositionSliders();
|
||||
refreshAvatarPositionSliders();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onResetScale()
|
||||
{
|
||||
// This is a double-click function: it needs to run twice within some amount of time to complete.
|
||||
auto timeIntervalSinceLastClick = std::chrono::system_clock::now() - _timeLastClickedJointReset;
|
||||
_timeLastClickedJointReset = std::chrono::system_clock::now();
|
||||
if (timeIntervalSinceLastClick > _doubleClickInterval)
|
||||
return;
|
||||
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
return;
|
||||
|
|
@ -1055,7 +1090,6 @@ void FSFloaterPoser::onResetScale()
|
|||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
bool shouldEnableRedoButton = false;
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = _poserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
|
|
@ -1079,14 +1113,11 @@ void FSFloaterPoser::onRedoLastRotation()
|
|||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
bool shouldEnableRedoButton = false;
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = _poserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
_poserAnimator.redoLastJointRotation(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
|
||||
shouldEnableRedoButton |= _poserAnimator.canRedoJointRotation(avatar, *item);
|
||||
}
|
||||
|
||||
enableOrDisableRedoButton();
|
||||
|
|
@ -1094,6 +1125,53 @@ void FSFloaterPoser::onRedoLastRotation()
|
|||
refreshTrackpadCursor();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onRedoLastPosition()
|
||||
{
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
return;
|
||||
|
||||
if (!_poserAnimator.isPosingAvatar(avatar))
|
||||
return;
|
||||
|
||||
auto selectedJoints = getUiSelectedPoserJoints();
|
||||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = _poserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
_poserAnimator.redoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedPositionSliders();
|
||||
refreshAvatarPositionSliders();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onRedoLastScale()
|
||||
{
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
return;
|
||||
|
||||
if (!_poserAnimator.isPosingAvatar(avatar))
|
||||
return;
|
||||
|
||||
auto selectedJoints = getUiSelectedPoserJoints();
|
||||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = _poserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (currentlyPosing)
|
||||
_poserAnimator.redoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle());
|
||||
}
|
||||
|
||||
refreshAdvancedScaleSliders();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::enableOrDisableRedoButton()
|
||||
{
|
||||
LLButton* redoButton = getChild<LLButton>(POSER_AVATAR_BUTTON_REDO);
|
||||
|
|
|
|||
|
|
@ -215,6 +215,9 @@ class FSFloaterPoser : public LLFloater
|
|||
void onUndoLastRotation();
|
||||
void onRedoLastRotation();
|
||||
void onUndoLastPosition();
|
||||
void onRedoLastPosition();
|
||||
void onUndoLastScale();
|
||||
void onRedoLastScale();
|
||||
void onResetPosition();
|
||||
void onResetScale();
|
||||
void enableOrDisableRedoButton();
|
||||
|
|
|
|||
|
|
@ -154,6 +154,34 @@ void FSPoserAnimator::undoLastJointPosition(LLVOAvatar* avatar, FSPoserJoint joi
|
|||
oppositeJointPose->undoLastPositionSet();
|
||||
}
|
||||
|
||||
void FSPoserAnimator::undoLastJointScale(LLVOAvatar* avatar, FSPoserJoint joint, E_BoneDeflectionStyles style)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
return;
|
||||
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
if (posingMotion->isStopped())
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
jointPose->undoLastScaleSet();
|
||||
|
||||
if (style == NONE)
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
|
||||
if (!oppositeJointPose)
|
||||
return;
|
||||
|
||||
oppositeJointPose->undoLastScaleSet();
|
||||
}
|
||||
|
||||
void FSPoserAnimator::resetJointPosition(LLVOAvatar* avatar, FSPoserJoint joint, E_BoneDeflectionStyles style)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
|
|
@ -257,6 +285,62 @@ void FSPoserAnimator::redoLastJointRotation(LLVOAvatar* avatar, FSPoserJoint joi
|
|||
oppositeJointPose->redoLastRotationSet();
|
||||
}
|
||||
|
||||
void FSPoserAnimator::redoLastJointPosition(LLVOAvatar* avatar, FSPoserJoint joint, E_BoneDeflectionStyles style)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
return;
|
||||
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
if (posingMotion->isStopped())
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
jointPose->redoLastPositionSet();
|
||||
|
||||
if (style == NONE)
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
|
||||
if (!oppositeJointPose)
|
||||
return;
|
||||
|
||||
oppositeJointPose->redoLastPositionSet();
|
||||
}
|
||||
|
||||
void FSPoserAnimator::redoLastJointScale(LLVOAvatar* avatar, FSPoserJoint joint, E_BoneDeflectionStyles style)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
return;
|
||||
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
if (posingMotion->isStopped())
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
jointPose->redoLastScaleSet();
|
||||
|
||||
if (style == NONE)
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
|
||||
if (!oppositeJointPose)
|
||||
return;
|
||||
|
||||
oppositeJointPose->redoLastScaleSet();
|
||||
}
|
||||
|
||||
LLVector3 FSPoserAnimator::getJointPosition(LLVOAvatar *avatar, FSPoserJoint joint)
|
||||
{
|
||||
LLVector3 pos;
|
||||
|
|
|
|||
|
|
@ -270,6 +270,13 @@ public:
|
|||
/// <param name="joint">The joint with the position to undo.</param>
|
||||
void undoLastJointPosition(LLVOAvatar* avatar, 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, FSPoserJoint joint, E_BoneDeflectionStyles style);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the position of the supplied PoserJoint.
|
||||
/// </summary>
|
||||
|
|
@ -299,6 +306,20 @@ public:
|
|||
/// <param name="joint">The joint with the rotation to redo.</param>
|
||||
void redoLastJointRotation(LLVOAvatar* avatar, 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, 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, FSPoserJoint joint, E_BoneDeflectionStyles style);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of a joint for the supplied avatar.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ public:
|
|||
LLVector3 _targetScale;
|
||||
LLVector3 _beginningScale;
|
||||
std::deque<LLVector3> _lastSetScales;
|
||||
size_t _undoneScaleIndex = 0;
|
||||
std::chrono::system_clock::time_point _timeLastUpdatedScale = std::chrono::system_clock::now();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a last position to the deque.
|
||||
|
|
@ -124,6 +126,34 @@ public:
|
|||
_lastSetRotations.pop_back();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a last rotation to the deque.
|
||||
/// </summary>
|
||||
void addLastScaleToUndo()
|
||||
{
|
||||
if (_undoneScaleIndex > 0)
|
||||
{
|
||||
for (int i = 0; i < _undoneScaleIndex; i++)
|
||||
_lastSetScales.pop_front();
|
||||
|
||||
_undoneScaleIndex = 0;
|
||||
}
|
||||
|
||||
_lastSetScales.push_front(_targetScale);
|
||||
|
||||
while (_lastSetScales.size() > MaximumUndoQueueLength)
|
||||
_lastSetScales.pop_back();
|
||||
}
|
||||
|
||||
void setScale(LLVector3 scale)
|
||||
{
|
||||
LLJoint* joint = _jointState->getJoint();
|
||||
if (!joint)
|
||||
return;
|
||||
|
||||
joint->setScale(scale);
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the name of the joint.
|
||||
|
|
@ -217,7 +247,7 @@ public:
|
|||
|
||||
_targetPosition.set(_lastSetPositions[_undonePositionIndex]);
|
||||
if (_undonePositionIndex == 0)
|
||||
_lastSetRotations.pop_front();
|
||||
_lastSetPositions.pop_front();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -276,12 +306,44 @@ public:
|
|||
LLVector3 getJointScale() const { return _targetScale; }
|
||||
void setJointScale(LLVector3 scale)
|
||||
{
|
||||
auto timeIntervalSinceLastScaleChange = std::chrono::system_clock::now() - _timeLastUpdatedScale;
|
||||
if (timeIntervalSinceLastScaleChange > _undoUpdateInterval)
|
||||
addLastScaleToUndo();
|
||||
|
||||
_timeLastUpdatedScale = std::chrono::system_clock::now();
|
||||
|
||||
_targetScale.set(scale);
|
||||
LLJoint* joint = _jointState->getJoint();
|
||||
if (!joint)
|
||||
setScale(_targetScale);
|
||||
}
|
||||
|
||||
void undoLastScaleSet()
|
||||
{
|
||||
if (_lastSetScales.empty())
|
||||
return;
|
||||
|
||||
joint->setScale(_targetScale);
|
||||
if (_undoneScaleIndex == 0) // at the top of the queue add the current
|
||||
addLastScaleToUndo();
|
||||
|
||||
_undoneScaleIndex++;
|
||||
_undoneScaleIndex = llclamp(_undoneScaleIndex, 0, _lastSetScales.size() - 1);
|
||||
_targetScale.set(_lastSetScales[_undoneScaleIndex]);
|
||||
|
||||
setScale(_targetScale);
|
||||
}
|
||||
|
||||
void redoLastScaleSet()
|
||||
{
|
||||
if (_lastSetScales.empty())
|
||||
return;
|
||||
|
||||
_undoneScaleIndex--;
|
||||
_undoneScaleIndex = llclamp(_undoneScaleIndex, 0, _lastSetScales.size() - 1);
|
||||
|
||||
_targetScale.set(_lastSetScales[_undoneScaleIndex]);
|
||||
if (_undoneScaleIndex == 0)
|
||||
_lastSetScales.pop_front();
|
||||
|
||||
setScale(_targetScale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -289,12 +351,8 @@ public:
|
|||
/// </summary>
|
||||
void revertJointScale()
|
||||
{
|
||||
LLJoint* joint = _jointState->getJoint();
|
||||
if (!joint)
|
||||
return;
|
||||
|
||||
_targetScale = _beginningScale;
|
||||
joint->setScale(_beginningScale);
|
||||
_targetScale.set(_beginningScale);
|
||||
setScale(_beginningScale);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1229,12 +1229,28 @@ width="565">
|
|||
height="21"
|
||||
follows="left|top"
|
||||
layout="topleft"
|
||||
label="Redo Position"
|
||||
image_overlay="Script_Redo"
|
||||
image_overlay_alignment="left"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="redo_position_change"
|
||||
tool_tip="Redo the last position change"
|
||||
width="110"
|
||||
top_delta="0"
|
||||
left_pad="4">
|
||||
<button.commit_callback
|
||||
function="Poser.RedoLastPosition"/>
|
||||
</button>
|
||||
<button
|
||||
height="21"
|
||||
follows="left|top"
|
||||
layout="topleft"
|
||||
label="Reset Position"
|
||||
image_overlay="Inv_TrashOpen"
|
||||
image_overlay_alignment="left"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="undo_position_change"
|
||||
tool_tip="Reset position back to original"
|
||||
tool_tip="Double click to reset position back to original"
|
||||
width="110"
|
||||
top_delta="0"
|
||||
left_pad="4">
|
||||
|
|
@ -1316,15 +1332,47 @@ width="565">
|
|||
height="21"
|
||||
follows="left|top"
|
||||
layout="topleft"
|
||||
label="Reset Scale Change"
|
||||
image_overlay="Inv_TrashOpen"
|
||||
label="Undo Scale Change"
|
||||
image_overlay="Script_Undo"
|
||||
image_overlay_alignment="left"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="reset_scale_change"
|
||||
tool_tip="Reset the scale of the selected body part(s) to normal"
|
||||
name="undo_position_change"
|
||||
tool_tip="Undo the last scale change"
|
||||
width="150"
|
||||
top_pad="2"
|
||||
left_delta="0">
|
||||
<button.commit_callback
|
||||
function="Poser.UndoLastScale"/>
|
||||
</button>
|
||||
<button
|
||||
height="21"
|
||||
follows="left|top"
|
||||
layout="topleft"
|
||||
label="Redo Scale"
|
||||
image_overlay="Script_Redo"
|
||||
image_overlay_alignment="left"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="redo_scale_change"
|
||||
tool_tip="Redo the last scale change"
|
||||
width="110"
|
||||
top_delta="0"
|
||||
left_pad="4">
|
||||
<button.commit_callback
|
||||
function="Poser.RedoLastScale"/>
|
||||
</button>
|
||||
<button
|
||||
height="21"
|
||||
follows="left|top"
|
||||
layout="topleft"
|
||||
label="Reset Scale"
|
||||
image_overlay="Inv_TrashOpen"
|
||||
image_overlay_alignment="left"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="undo_scale_change"
|
||||
tool_tip="Double click to reset scale back to original"
|
||||
width="110"
|
||||
top_delta="0"
|
||||
left_pad="4">
|
||||
<button.commit_callback
|
||||
function="Poser.ResetScale"/>
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in New Issue