diff --git a/indra/newview/fsfloaterposer.cpp b/indra/newview/fsfloaterposer.cpp
index fd068a9816..adb22b6b7b 100644
--- a/indra/newview/fsfloaterposer.cpp
+++ b/indra/newview/fsfloaterposer.cpp
@@ -908,14 +908,6 @@ void FSFloaterPoser::onAvatarPositionSet()
setSelectedJointsPosition(posX, posY, posZ);
}
-///
-/// The trackball controller is not friendly to photographers (or normal people).
-/// This method could be streamlined but at the high cost of picking apart what it does.
-/// The simplest thing to do would be to reimplement the code behind the slider!
-/// TLDR: we just want the trackball to behave like a 2-axis slider.
-///
-/// BEWARE! Changes to behaviour here require their inverse to be applied on the slider-callback.
-///
void FSFloaterPoser::onLimbTrackballChanged()
{
FSVirtualTrackpad *trackBall = getChild(POSER_AVATAR_TRACKBALL_NAME);
diff --git a/indra/newview/fsposeranimator.cpp b/indra/newview/fsposeranimator.cpp
index af05a25005..c839f87668 100644
--- a/indra/newview/fsposeranimator.cpp
+++ b/indra/newview/fsposeranimator.cpp
@@ -99,7 +99,34 @@ LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar *avatar, FSPoserJoint joi
return vec3;
LLQuaternion rot = avJoint->getRotation();
- rot.getEulerAngles(&vec3.mV[VX], &vec3.mV[VZ], &vec3.mV[VY]);
+
+ return translateRotationFromQuaternion(joint.boneTranslation(), rot);
+}
+
+// from the bone to the UI; this is the 'forwards' use of the enum
+LLVector3 FSPoserAnimator::translateRotationFromQuaternion(E_BoneAxisTranslation translation, LLQuaternion rotation)
+{
+ LLVector3 vec3;
+
+ switch (translation)
+ {
+ case SWAP_YAW_AND_ROLL:
+ rotation.getEulerAngles(&vec3.mV[VY], &vec3.mV[VZ], &vec3.mV[VX]);
+ break;
+
+ case SWAP_YAW_AND_PITCH:
+ rotation.getEulerAngles(&vec3.mV[VZ], &vec3.mV[VX], &vec3.mV[VY]);
+ break;
+
+ case SWAP_ROLL_AND_PITCH:
+ rotation.getEulerAngles(&vec3.mV[VX], &vec3.mV[VY], &vec3.mV[VZ]);
+ break;
+
+ case SWAP_NOTHING:
+ default:
+ rotation.getEulerAngles(&vec3.mV[VX], &vec3.mV[VZ], &vec3.mV[VY]);
+ break;
+ }
return vec3;
}
@@ -115,10 +142,38 @@ void FSPoserAnimator::setJointRotation(LLVOAvatar *avatar, const FSPoserJoint *j
if (!avJoint)
return;
- LLMatrix3 rot_mat = LLMatrix3(rotation.mV[VX], rotation.mV[VY], rotation.mV[VZ]);
+ LLQuaternion rot_quat = translateRotationToQuaternion(joint->boneTranslation(), rotation);
+ avJoint->setRotation(rot_quat);
+}
+
+// from the UI to the bone, the inverse translation, the un-swap, the backwards
+LLQuaternion FSPoserAnimator::translateRotationToQuaternion(E_BoneAxisTranslation translation, LLVector3 rotation)
+{
+ LLMatrix3 rot_mat;
+ switch (translation)
+ {
+ case SWAP_YAW_AND_ROLL:
+ rot_mat = LLMatrix3(rotation.mV[VZ], rotation.mV[VY], -1 * rotation.mV[VX]);
+ break;
+
+ case SWAP_YAW_AND_PITCH:
+ rot_mat = LLMatrix3(rotation.mV[VY], rotation.mV[VX], rotation.mV[VZ]);
+ break;
+
+ case SWAP_ROLL_AND_PITCH:
+ rot_mat = LLMatrix3(rotation.mV[VX], rotation.mV[VZ], rotation.mV[VY]);
+ break;
+
+ case SWAP_NOTHING:
+ default:
+ rot_mat = LLMatrix3(rotation.mV[VX], rotation.mV[VY], rotation.mV[VZ]);
+ break;
+ }
+
LLQuaternion rot_quat;
rot_quat = LLQuaternion(rot_mat) * rot_quat;
- avJoint->setRotation(rot_quat);
+
+ return rot_quat;
}
LLVector3 FSPoserAnimator::getJointScale(LLVOAvatar *avatar, FSPoserJoint joint)
diff --git a/indra/newview/fsposeranimator.h b/indra/newview/fsposeranimator.h
index 51114568e1..f964c14665 100644
--- a/indra/newview/fsposeranimator.h
+++ b/indra/newview/fsposeranimator.h
@@ -58,6 +58,20 @@ typedef enum E_BoneDeflectionStyles
SYMPATHETIC = 2, // change the other joint, but opposite to a mirrored way, eg: both go right or both go left
} E_BoneDeflectionStyles;
+///
+/// When we're going from bone-rotation to the UI sliders, some of the axes need swapping so they make sense in UI-terms.
+/// eg: for one bone, the X-axis may mean up and down, but for another bone, the x-axis might be left-right.
+/// These are translations of bone-TO-UI; an inverse translation needs to happen the other way.
+/// It would be nice if these were defined in XML; but then they're not const, and I want const.
+///
+typedef enum E_BoneAxisTranslation
+{
+ SWAP_NOTHING = 0,
+ SWAP_YAW_AND_ROLL = 1,
+ SWAP_YAW_AND_PITCH = 2,
+ SWAP_ROLL_AND_PITCH = 3,
+} E_BoneAxisTranslation;
+
class FSPoserAnimator
{
public:
@@ -73,6 +87,7 @@ public:
std::string _jointName; // expected to be a match to LLJoint.getName() for a joint implementation.
std::string _mirrorJointName;
E_BoneTypes _boneList;
+ E_BoneAxisTranslation _boneTranslation;
public:
///
/// Gets the name of the joint.
@@ -89,6 +104,11 @@ public:
///
E_BoneTypes boneType() const { return _boneList; }
+ ///
+ /// Gets the E_BoneAxisTranslation of the joint.
+ ///
+ E_BoneAxisTranslation boneTranslation() const { return _boneTranslation; }
+
///
/// Creates a new instance of a PoserJoint.
///
@@ -99,11 +119,12 @@ public:
///
/// The opposite joint name, if any. Also expected to be a well-known name.
/// The
- FSPoserJoint(std::string a, std::string b, E_BoneTypes c)
+ FSPoserJoint(std::string a, std::string b, E_BoneTypes c, E_BoneAxisTranslation d = SWAP_NOTHING)
{
_jointName = a;
_mirrorJointName = b;
_boneList = c;
+ _boneTranslation = d;
}
};
@@ -122,7 +143,7 @@ public:
///
const std::vector PoserJoints {
// head, torso, legs
- {"mPelvis", "", WHOLEAVATAR}, {"mTorso", "", BODY}, {"mChest", "", BODY}, {"mNeck", "", BODY}, {"mHead", "", BODY},
+ {"mPelvis", "", WHOLEAVATAR}, {"mTorso", "", BODY, SWAP_YAW_AND_ROLL}, {"mChest", "", BODY}, {"mNeck", "", BODY}, {"mHead", "", BODY},
{"mCollarLeft", "mCollarRight", BODY}, {"mShoulderLeft", "mShoulderRight", BODY}, {"mElbowLeft", "mElbowRight", BODY}, {"mWristLeft", "mWristRight", BODY},
{"mCollarRight", "mCollarLeft", BODY}, {"mShoulderRight", "mShoulderLeft", BODY}, {"mElbowRight", "mElbowLeft", BODY}, {"mWristRight", "mWristLeft", BODY},
{"mHipLeft", "", BODY}, {"mKneeLeft", "", BODY}, {"mAnkleLeft", "", BODY},
@@ -269,6 +290,23 @@ public:
private:
bool _currentlyPosingSelf = false;
+ ///
+ /// Translates a rotation vector from the UI to a Quaternion for the bone.
+ /// This also performs the axis-swapping the UI needs for up/down/left/right to make sense.
+ ///
+ /// The axis translation to perform.
+ /// The rotation to transform to quaternion.
+ /// The rotation quaternion.
+ LLQuaternion translateRotationToQuaternion(E_BoneAxisTranslation translation, LLVector3 rotation);
+
+ ///
+ /// Translates a bone-rotation quaternion to a vector usable easily on the UI.
+ ///
+ /// The axis translation to perform.
+ /// The rotation to transform to matrix.
+ /// The rotation vector.
+ LLVector3 translateRotationFromQuaternion(E_BoneAxisTranslation translation, LLQuaternion rotation);
+
// public:
// static LLMotion *create(const LLUUID &id) { return new FSPoserAnimator(id); }
diff --git a/indra/newview/fsvirtualtrackpad.h b/indra/newview/fsvirtualtrackpad.h
index c12b097936..648b8ff169 100644
--- a/indra/newview/fsvirtualtrackpad.h
+++ b/indra/newview/fsvirtualtrackpad.h
@@ -43,7 +43,6 @@ public:
Optional border;
Optional image_moon_back, image_moon_front, image_sphere, image_sun_back, image_sun_front;
Optional pinch_mode;
- Optional allow_drag_outside;
Params();
};
diff --git a/indra/newview/skins/default/xui/en/floater_poser.xml b/indra/newview/skins/default/xui/en/floater_poser.xml
index add6511759..2d5a0b60e8 100644
--- a/indra/newview/skins/default/xui/en/floater_poser.xml
+++ b/indra/newview/skins/default/xui/en/floater_poser.xml
@@ -594,10 +594,10 @@ width="565">
left_delta="0"
top_pad="2"
width="200">Up/Down:
-
left_delta="-5"
top_pad="0"
width="200">Left/Right:
-
left_delta="-5"
top_pad="-1"
width="200">Roll:
-