FIRE-30873: Rework undo, add redo
Now affected by mirror/symp, undo is now joint specific, and has undo-depth of last 20 changesmaster
parent
da998c838e
commit
542dc37c97
|
|
@ -69,6 +69,7 @@ static const std::string POSER_AVATAR_SLIDER_ROLL_NAME = "limb_roll"; // your ea
|
|||
static const std::string POSER_AVATAR_TOGGLEBUTTON_TRACKPADSENSITIVITY = "button_toggleTrackPadSensitivity";
|
||||
static const std::string POSER_AVATAR_TOGGLEBUTTON_MIRROR = "button_toggleMirrorRotation";
|
||||
static const std::string POSER_AVATAR_TOGGLEBUTTON_SYMPATH = "button_toggleSympatheticRotation";
|
||||
static const std::string POSER_AVATAR_BUTTON_REDO = "button_redo_change";
|
||||
static const std::string POSER_AVATAR_SLIDER_POSX_NAME = "av_position_inout";
|
||||
static const std::string POSER_AVATAR_SLIDER_POSY_NAME = "av_position_leftright";
|
||||
static const std::string POSER_AVATAR_SLIDER_POSZ_NAME = "av_position_updown";
|
||||
|
|
@ -118,6 +119,7 @@ FSFloaterPoser::FSFloaterPoser(const LLSD& key) : LLFloater(key)
|
|||
mCommitCallbackRegistrar.add("Poser.ToggleAdvancedPanel", boost::bind(&FSFloaterPoser::onToggleAdvancedPanel, this));
|
||||
|
||||
mCommitCallbackRegistrar.add("Poser.UndoLastRotation", boost::bind(&FSFloaterPoser::onUndoLastRotation, this));
|
||||
mCommitCallbackRegistrar.add("Poser.RedoLastRotation", boost::bind(&FSFloaterPoser::onRedoLastRotation, this));
|
||||
mCommitCallbackRegistrar.add("Poser.ToggleMirrorChanges", boost::bind(&FSFloaterPoser::onToggleMirrorChange, this));
|
||||
mCommitCallbackRegistrar.add("Poser.ToggleSympatheticChanges", boost::bind(&FSFloaterPoser::onToggleSympatheticChange, this));
|
||||
mCommitCallbackRegistrar.add("Poser.ToggleTrackPadSensitivity", boost::bind(&FSFloaterPoser::refreshTrackpadCursor, this));
|
||||
|
|
@ -936,12 +938,67 @@ void FSFloaterPoser::setRotationChangeButtons(bool togglingMirror, bool toggling
|
|||
|
||||
void FSFloaterPoser::onUndoLastRotation()
|
||||
{
|
||||
FSVirtualTrackpad *trackBall = getChild<FSVirtualTrackpad>(POSER_AVATAR_TRACKBALL_NAME);
|
||||
if (!trackBall)
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
return;
|
||||
|
||||
trackBall->undoLastValue();
|
||||
onLimbTrackballChanged();
|
||||
if (!_poserAnimator.isPosingAvatar(avatar))
|
||||
return;
|
||||
|
||||
auto selectedJoints = getUiSelectedPoserJoints();
|
||||
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(shouldEnableRedoButton);
|
||||
refreshRotationSliders();
|
||||
refreshTrackpadCursor();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onRedoLastRotation()
|
||||
{
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
return;
|
||||
|
||||
if (!_poserAnimator.isPosingAvatar(avatar))
|
||||
return;
|
||||
|
||||
auto selectedJoints = getUiSelectedPoserJoints();
|
||||
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(shouldEnableRedoButton);
|
||||
refreshRotationSliders();
|
||||
refreshTrackpadCursor();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::enableOrDisableRedoButton(bool shouldEnable)
|
||||
{
|
||||
LLButton* redoButton = getChild<LLButton>(POSER_AVATAR_BUTTON_REDO);
|
||||
if (!redoButton)
|
||||
return;
|
||||
|
||||
redoButton->setEnabled(shouldEnable);
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onOpenSetAdvancedPanel()
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@ class FSFloaterPoser : public LLFloater
|
|||
void onToggleSympatheticChange();
|
||||
void setRotationChangeButtons(bool mirror, bool sympathetic);
|
||||
void onUndoLastRotation();
|
||||
void onRedoLastRotation();
|
||||
void enableOrDisableRedoButton(bool shouldEnable);
|
||||
void onPoseStartStop();
|
||||
void onLimbTrackballChanged();
|
||||
void onLimbYawPitchRollChanged();
|
||||
|
|
|
|||
|
|
@ -92,11 +92,87 @@ void FSPoserAnimator::resetAvatarJoint(LLVOAvatar *avatar, FSPoserJoint joint)
|
|||
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
jointPose->setTargetPosition(jointPose->getBeginningPosition());
|
||||
jointPose->setTargetRotation(jointPose->getBeginningRotation());
|
||||
}
|
||||
|
||||
void FSPoserAnimator::undoLastJointRotation(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->undoLastRotationSet();
|
||||
|
||||
if (style == NONE)
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
|
||||
if (!oppositeJointPose)
|
||||
return;
|
||||
|
||||
oppositeJointPose->undoLastRotationSet();
|
||||
}
|
||||
|
||||
bool FSPoserAnimator::canRedoJointRotation(LLVOAvatar* avatar, FSPoserJoint joint)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
return false;
|
||||
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return false;
|
||||
|
||||
if (posingMotion->isStopped())
|
||||
return false;
|
||||
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
|
||||
if (!jointPose)
|
||||
return false;
|
||||
|
||||
return jointPose->canRedo();
|
||||
}
|
||||
|
||||
void FSPoserAnimator::redoLastJointRotation(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->redoLastRotationSet();
|
||||
|
||||
if (style == NONE)
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint.mirrorJointName());
|
||||
if (!oppositeJointPose)
|
||||
return;
|
||||
|
||||
oppositeJointPose->redoLastRotationSet();
|
||||
}
|
||||
|
||||
LLVector3 FSPoserAnimator::getJointPosition(LLVOAvatar *avatar, FSPoserJoint joint)
|
||||
{
|
||||
LLVector3 pos;
|
||||
|
|
|
|||
|
|
@ -252,6 +252,28 @@ public:
|
|||
/// <param name="joint">The joint to be reset.</param>
|
||||
void resetAvatarJoint(LLVOAvatar *avatar, 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, FSPoserJoint joint, E_BoneDeflectionStyles style);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a redo action is currently permitted for the supplied joint.
|
||||
/// </summary>
|
||||
/// <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, FSPoserJoint joint);
|
||||
|
||||
/// <summary>
|
||||
/// Re-does the last undone 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 redo.</param>
|
||||
void redoLastJointRotation(LLVOAvatar* avatar, FSPoserJoint joint, E_BoneDeflectionStyles style);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position of a joint for the supplied avatar.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ bool FSPosingMotion::onUpdate(F32 time, U8* joint_mask)
|
|||
LLQuaternion currentRotation;
|
||||
LLVector3 currentPosition;
|
||||
LLVector3 targetPosition;
|
||||
F32 poseTransitionAmount = 0.0f; // when we change from one position/rotation to another, we do so over time; this documents the amount of transition.
|
||||
|
||||
for (FSJointPose jointPose : _jointPoses)
|
||||
{
|
||||
|
|
@ -76,7 +75,6 @@ bool FSPosingMotion::onUpdate(F32 time, U8* joint_mask)
|
|||
targetRotation = jointPose.getTargetRotation();
|
||||
targetPosition = jointPose.getTargetPosition();
|
||||
|
||||
poseTransitionAmount = llclamp(_interpolationTimer.getElapsedTimeF32() / _interpolationTime, 0.0f, 1.0f);
|
||||
if (currentPosition != targetPosition)
|
||||
{
|
||||
currentPosition = lerp(currentPosition, targetPosition, _interpolationTime);
|
||||
|
|
@ -90,9 +88,6 @@ bool FSPosingMotion::onUpdate(F32 time, U8* joint_mask)
|
|||
}
|
||||
}
|
||||
|
||||
if (_interpolationTimer.getStarted() && poseTransitionAmount >= 1.0f)
|
||||
_interpolationTimer.stop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_FSPOSINGMOTION_H
|
||||
#define LL_FSPOSINGMOTION_H
|
||||
#ifndef FS_POSINGMOTION_H
|
||||
#define FS_POSINGMOTION_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Header files
|
||||
|
|
@ -52,12 +52,65 @@ public:
|
|||
/// </summary>
|
||||
class FSJointPose
|
||||
{
|
||||
std::string _jointName = ""; // expected to be a match to LLJoint.getName() for a joint implementation.
|
||||
LLQuaternion _beginningRotation;
|
||||
LLQuaternion _targetRotation;
|
||||
const size_t MaximumUndoQueueLength = 20;
|
||||
|
||||
/// <summary>
|
||||
/// The constant time interval, in seconds,
|
||||
/// </summary>
|
||||
std::chrono::duration<double> const _undoUpdateInterval = std::chrono::duration<double>(0.3);
|
||||
|
||||
std::string _jointName = ""; // expected to be a match to LLJoint.getName() for a joint implementation.
|
||||
LLPointer<LLJointState> _jointState;
|
||||
|
||||
LLQuaternion _targetRotation;
|
||||
LLQuaternion _beginningRotation;
|
||||
std::deque<LLQuaternion> _lastSetRotations;
|
||||
size_t _undoneRotationIndex = 0;
|
||||
std::chrono::system_clock::time_point _timeLastUpdatedRotation = std::chrono::system_clock::now();
|
||||
|
||||
LLVector3 _targetPosition;
|
||||
LLVector3 _beginningPosition;
|
||||
LLPointer<LLJointState> _jointState;
|
||||
std::deque<LLVector3> _lastSetPositions;
|
||||
size_t _undonePositionIndex = 0;
|
||||
std::chrono::system_clock::time_point _timeLastUpdatedPosition = std::chrono::system_clock::now();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a last position to the deque.
|
||||
/// </summary>
|
||||
void addLastPositionToUndo()
|
||||
{
|
||||
if (_undonePositionIndex > 0)
|
||||
{
|
||||
for (int i = 0; i < _undonePositionIndex; i++)
|
||||
_lastSetPositions.pop_front();
|
||||
|
||||
_undonePositionIndex = 0;
|
||||
}
|
||||
|
||||
_lastSetPositions.push_front(_targetPosition);
|
||||
|
||||
while (_lastSetPositions.size() > MaximumUndoQueueLength)
|
||||
_lastSetPositions.pop_back();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a last rotation to the deque.
|
||||
/// </summary>
|
||||
void addLastRotationToUndo()
|
||||
{
|
||||
if (_undoneRotationIndex > 0)
|
||||
{
|
||||
for (int i = 0; i < _undoneRotationIndex; i++)
|
||||
_lastSetRotations.pop_front();
|
||||
|
||||
_undoneRotationIndex = 0;
|
||||
}
|
||||
|
||||
_lastSetRotations.push_front(_targetRotation);
|
||||
|
||||
while (_lastSetRotations.size() > MaximumUndoQueueLength)
|
||||
_lastSetRotations.pop_back();
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
|
@ -65,6 +118,8 @@ public:
|
|||
/// </summary>
|
||||
std::string jointName() const { return _jointName; }
|
||||
|
||||
bool canRedo() const { return _undoneRotationIndex > 0; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the position the joint was in when the animation was initialized.
|
||||
/// </summary>
|
||||
|
|
@ -78,7 +133,15 @@ public:
|
|||
/// <summary>
|
||||
/// Sets the position the animator wishes the joint to be in.
|
||||
/// </summary>
|
||||
void setTargetPosition(const LLVector3& pos) { _targetPosition.set(pos) ; }
|
||||
void setTargetPosition(const LLVector3& pos)
|
||||
{
|
||||
auto timeIntervalSinceLastRotationChange = std::chrono::system_clock::now() - _timeLastUpdatedPosition;
|
||||
if (timeIntervalSinceLastRotationChange > _undoUpdateInterval)
|
||||
addLastPositionToUndo();
|
||||
|
||||
_timeLastUpdatedPosition = std::chrono::system_clock::now();
|
||||
_targetPosition.set(pos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the rotation the joint was in when the animation was initialized.
|
||||
|
|
@ -93,7 +156,82 @@ public:
|
|||
/// <summary>
|
||||
/// Sets the rotation the animator wishes the joint to be in.
|
||||
/// </summary>
|
||||
void setTargetRotation(const LLQuaternion& rot) { _targetRotation.set(rot); }
|
||||
void setTargetRotation(const LLQuaternion& rot)
|
||||
{
|
||||
auto timeIntervalSinceLastRotationChange = std::chrono::system_clock::now() - _timeLastUpdatedRotation;
|
||||
if (timeIntervalSinceLastRotationChange > _undoUpdateInterval)
|
||||
addLastRotationToUndo();
|
||||
|
||||
_timeLastUpdatedRotation = std::chrono::system_clock::now();
|
||||
_targetRotation.set(rot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Undoes the last position set, if any.
|
||||
/// </summary>
|
||||
void undoLastPositionSet()
|
||||
{
|
||||
if (_lastSetPositions.empty())
|
||||
return;
|
||||
|
||||
if (_undonePositionIndex == 0) // at the top of the queue add the current
|
||||
addLastPositionToUndo();
|
||||
|
||||
_undonePositionIndex++;
|
||||
_undonePositionIndex = llclamp(_undonePositionIndex, 0, _lastSetPositions.size() - 1);
|
||||
_targetPosition.set(_lastSetPositions[_undonePositionIndex]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Undoes the last position set, if any.
|
||||
/// </summary>
|
||||
void redoLastPositionSet()
|
||||
{
|
||||
if (_lastSetPositions.empty())
|
||||
return;
|
||||
|
||||
_undonePositionIndex--;
|
||||
_undonePositionIndex = llclamp(_undonePositionIndex, 0, _lastSetPositions.size() - 1);
|
||||
|
||||
_targetPosition.set(_lastSetPositions[_undonePositionIndex]);
|
||||
if (_undonePositionIndex == 0)
|
||||
_lastSetRotations.pop_front();
|
||||
}
|
||||
|
||||
/// <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, _undoneRotationIndex points at the current rotation.
|
||||
/// </summary>
|
||||
void undoLastRotationSet()
|
||||
{
|
||||
if (_lastSetRotations.empty())
|
||||
return;
|
||||
|
||||
if (_undoneRotationIndex == 0) // at the top of the queue add the current
|
||||
addLastRotationToUndo();
|
||||
|
||||
_undoneRotationIndex++;
|
||||
_undoneRotationIndex = llclamp(_undoneRotationIndex, 0, _lastSetRotations.size() - 1);
|
||||
_targetRotation.set(_lastSetRotations[_undoneRotationIndex]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Undoes the last rotation set, if any.
|
||||
/// </summary>
|
||||
void redoLastRotationSet()
|
||||
{
|
||||
if (_lastSetRotations.empty())
|
||||
return;
|
||||
|
||||
_undoneRotationIndex--;
|
||||
_undoneRotationIndex = llclamp(_undoneRotationIndex, 0, _lastSetRotations.size() - 1);
|
||||
|
||||
_targetRotation.set(_lastSetRotations[_undoneRotationIndex]);
|
||||
if (_undoneRotationIndex == 0)
|
||||
_lastSetRotations.pop_front();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pointer to the jointstate for the joint this represents.
|
||||
|
|
@ -193,19 +331,16 @@ private:
|
|||
/// <summary>
|
||||
/// The amount of time, in seconds, we use for transitioning between one animation-state to another; this affects the 'fluidity'
|
||||
/// of motion between changed to a joint.
|
||||
/// Use caution making this larger than the perceptual amount of time between adjusting a joint and then choosing to use 'undo'.
|
||||
/// Undo-function waits this amount of time after the last user-incited joint change to add a 'restore point'.
|
||||
/// </summary>
|
||||
const F32 _interpolationTime = 0.25f;
|
||||
|
||||
/// <summary>
|
||||
/// The timer used to smoothly transition from one joint position or rotation to another.
|
||||
/// </summary>
|
||||
LLFrameTimer _interpolationTimer;
|
||||
|
||||
/// <summary>
|
||||
/// The collection of joint poses this motion uses to pose the joints of the character this is animating.
|
||||
/// </summary>
|
||||
std::vector<FSJointPose> _jointPoses;
|
||||
};
|
||||
|
||||
#endif // LL_LLKEYFRAMEMOTION_H
|
||||
#endif // FS_POSINGMOTION_H
|
||||
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ FSVirtualTrackpad::FSVirtualTrackpad(const FSVirtualTrackpad::Params &p)
|
|||
mInfiniteScrollMode(p.infinite_scroll_mode)
|
||||
{
|
||||
LLRect border_rect = getLocalRect();
|
||||
_valueX = _lastValueX = _pinchValueX = _lastPinchValueX = border_rect.getCenterX();
|
||||
_valueY = _lastValueY = _pinchValueY = _lastPinchValueY = border_rect.getCenterY();
|
||||
_valueX = _pinchValueX = border_rect.getCenterX();
|
||||
_valueY = _pinchValueY = border_rect.getCenterY();
|
||||
_thumbClickOffsetX = _thumbClickOffsetY = _pinchThumbClickOffsetX = _pinchThumbClickOffsetY = 0;
|
||||
_valueWheelClicks = _pinchValueWheelClicks = 0;
|
||||
|
||||
|
|
@ -246,10 +246,6 @@ void FSVirtualTrackpad::setValue(F32 x, F32 y) { convertNormalizedToPixelPos(x,
|
|||
|
||||
void FSVirtualTrackpad::setPinchValue(F32 x, F32 y) { convertNormalizedToPixelPos(x, y, &_pinchValueX, &_pinchValueY); }
|
||||
|
||||
void FSVirtualTrackpad::undoLastValue() { setValueAndCommit(_lastValueX, _lastValueY); }
|
||||
|
||||
void FSVirtualTrackpad::undoLastSetPinchValue() { setPinchValueAndCommit(_lastPinchValueX, _lastPinchValueY); }
|
||||
|
||||
void FSVirtualTrackpad::setValueAndCommit(const S32 x, const S32 y)
|
||||
{
|
||||
_valueX = x;
|
||||
|
|
@ -405,8 +401,6 @@ bool FSVirtualTrackpad::handleMouseDown(S32 x, S32 y, MASK mask)
|
|||
determineThumbClickError(x, y);
|
||||
updateClickErrorIfInfiniteScrolling();
|
||||
_valueWheelClicks = 0;
|
||||
_lastValueX = _valueX;
|
||||
_lastValueY = _valueY;
|
||||
_wheelClicksSinceMouseDown = 0;
|
||||
gFocusMgr.setMouseCapture(this);
|
||||
|
||||
|
|
@ -440,8 +434,6 @@ bool FSVirtualTrackpad::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
|||
determineThumbClickErrorForPinch(x, y);
|
||||
updateClickErrorIfInfiniteScrollingForPinch();
|
||||
_pinchValueWheelClicks = 0;
|
||||
_lastPinchValueX = _pinchValueX;
|
||||
_lastPinchValueY = _pinchValueY;
|
||||
_wheelClicksSinceMouseDown = 0;
|
||||
doingPinchMode = true;
|
||||
gFocusMgr.setMouseCapture(this);
|
||||
|
|
|
|||
|
|
@ -70,9 +70,6 @@ public:
|
|||
/// <param name="y">The y-axis (top/bottom) position to set; expected range 1..-1; top = 1</param>
|
||||
void setValue(F32 x, F32 y);
|
||||
|
||||
void undoLastValue();
|
||||
void undoLastSetPinchValue();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position of the second cursor.
|
||||
/// </summary>
|
||||
|
|
@ -140,14 +137,10 @@ private:
|
|||
S32 _valueX;
|
||||
S32 _valueY;
|
||||
S32 _valueWheelClicks;
|
||||
S32 _lastValueX;
|
||||
S32 _lastValueY;
|
||||
|
||||
S32 _pinchValueX;
|
||||
S32 _pinchValueY;
|
||||
S32 _pinchValueWheelClicks;
|
||||
S32 _lastPinchValueX;
|
||||
S32 _lastPinchValueY;
|
||||
|
||||
/// <summary>
|
||||
/// Rolling the wheel is pioneering a 'delta' mode: where changes are handled by the control-owner in a relative way.
|
||||
|
|
|
|||
|
|
@ -612,16 +612,47 @@ width="565">
|
|||
follows="top|left"
|
||||
layout="topleft"
|
||||
label=""
|
||||
image_overlay="Refresh_Off"
|
||||
image_overlay="Script_Undo"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="refresh_avatars"
|
||||
name="undo_change"
|
||||
tool_tip="Undo the last rotation change"
|
||||
width="20"
|
||||
width="18"
|
||||
top_pad="0"
|
||||
left="4">
|
||||
<button.commit_callback
|
||||
function="Poser.UndoLastRotation"/>
|
||||
</button>
|
||||
<button
|
||||
height="21"
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
label=""
|
||||
image_overlay="Script_Redo"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="button_redo_change"
|
||||
tool_tip="Re-do the last Undo change"
|
||||
enabled="false"
|
||||
width="18"
|
||||
top_delta="0"
|
||||
left_pad="1">
|
||||
<button.commit_callback
|
||||
function="Poser.RedoLastRotation"/>
|
||||
</button>
|
||||
<button
|
||||
height="21"
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
label=""
|
||||
image_overlay="Inv_TrashOpen"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="refresh_avatars"
|
||||
tool_tip="Double click to reset all selected body parts to when you first started posing"
|
||||
width="18"
|
||||
top_delta="0"
|
||||
left_pad="1">
|
||||
<button.commit_callback
|
||||
function="Pose.PoseJointsReset"/>
|
||||
</button>
|
||||
<button
|
||||
follows="left|top"
|
||||
height="21"
|
||||
|
|
@ -640,31 +671,16 @@ width="565">
|
|||
tool_tip="Make smaller changes when using the trackball."
|
||||
left_pad="1"
|
||||
top_delta="0"
|
||||
width="20" >
|
||||
width="18" >
|
||||
<button.commit_callback
|
||||
function="Poser.ToggleTrackPadSensitivity"/>
|
||||
</button>
|
||||
<button
|
||||
height="21"
|
||||
follows="top|left"
|
||||
layout="topleft"
|
||||
label=""
|
||||
image_overlay="Inv_TrashOpen"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
name="refresh_avatars"
|
||||
tool_tip="Double click to reset all selected body parts to when you first started posing"
|
||||
width="20"
|
||||
top_delta="0"
|
||||
left_pad="1">
|
||||
<button.commit_callback
|
||||
function="Pose.PoseJointsReset"/>
|
||||
</button>
|
||||
<button
|
||||
follows="left|top"
|
||||
height="21"
|
||||
is_toggle="true"
|
||||
layout="topleft"
|
||||
label="Mirror"
|
||||
label="Mirr."
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
|
|
@ -676,7 +692,7 @@ width="565">
|
|||
tool_tip="Change the opposite joint, like in a mirror."
|
||||
left_pad="1"
|
||||
top_delta="0"
|
||||
width="45" >
|
||||
width="38" >
|
||||
<button.commit_callback
|
||||
function="Poser.ToggleMirrorChanges"/>
|
||||
</button>
|
||||
|
|
@ -685,7 +701,7 @@ width="565">
|
|||
height="21"
|
||||
is_toggle="true"
|
||||
layout="topleft"
|
||||
label="Symp."
|
||||
label="Sym."
|
||||
image_hover_unselected="Toolbar_Middle_Over"
|
||||
image_selected="Toolbar_Middle_Selected"
|
||||
image_unselected="Toolbar_Middle_Off"
|
||||
|
|
@ -697,7 +713,7 @@ width="565">
|
|||
tool_tip="Change the opposite joint, but in the same way."
|
||||
left_pad="1"
|
||||
top_delta="0"
|
||||
width="45" >
|
||||
width="38" >
|
||||
<button.commit_callback
|
||||
function="Poser.ToggleSympatheticChanges"/>
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in New Issue