FIRE-34744: Preen diff save, update recapture
parent
73ea090f99
commit
f4b515175b
|
|
@ -307,6 +307,12 @@ void FSFloaterPoser::onPoseFileSelect()
|
|||
LLStringExplicit name = LLStringExplicit(poseName);
|
||||
mPoseSaveNameEditor->setEnabled(enableButtons);
|
||||
mPoseSaveNameEditor->setText(name);
|
||||
|
||||
bool isDeltaSave = !poseFileStartsFromTeePose(name);
|
||||
if (isDeltaSave)
|
||||
mLoadPosesBtn->setLabel("Load Diff");
|
||||
else
|
||||
mLoadPosesBtn->setLabel("Load Pose");
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onClickPoseSave()
|
||||
|
|
@ -348,13 +354,13 @@ bool FSFloaterPoser::savePoseToXml(LLVOAvatar* avatar, const std::string& poseFi
|
|||
std::string fullSavePath =
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, POSE_SAVE_SUBDIRECTORY, poseFileName + POSE_INTERNAL_FORMAT_FILE_EXT);
|
||||
|
||||
bool fromZeroRot = mPoserAnimator.posingStartedFromZeroRotations(avatar);
|
||||
bool savingDiff = !mPoserAnimator.posingStartedFromZeroRotations(avatar);
|
||||
|
||||
LLSD record;
|
||||
record["version"]["value"] = (S32)4;
|
||||
record["startFromTeePose"]["value"] = fromZeroRot;
|
||||
record["startFromTeePose"]["value"] = !savingDiff;
|
||||
|
||||
LLVector3 rotation, position, scale;
|
||||
LLVector3 rotation, position, scale, zeroVector;
|
||||
|
||||
for (const FSPoserAnimator::FSPoserJoint& pj : mPoserAnimator.PoserJoints)
|
||||
{
|
||||
|
|
@ -362,8 +368,13 @@ bool FSFloaterPoser::savePoseToXml(LLVOAvatar* avatar, const std::string& poseFi
|
|||
if (!mPoserAnimator.tryGetJointSaveVectors(avatar, pj, &rotation, &position, &scale))
|
||||
continue;
|
||||
|
||||
record[bone_name] = pj.jointName();
|
||||
record[bone_name]["enabled"] = mPoserAnimator.isPosingAvatarJoint(avatar, pj);
|
||||
bool jointRotPosScaleAllZero = rotation == zeroVector && position == zeroVector && scale == zeroVector;
|
||||
bool posingThisJoint = mPoserAnimator.isPosingAvatarJoint(avatar, pj);
|
||||
if (savingDiff && (!posingThisJoint || jointRotPosScaleAllZero))
|
||||
continue;
|
||||
|
||||
record[bone_name] = bone_name;
|
||||
record[bone_name]["enabled"] = posingThisJoint;
|
||||
record[bone_name]["rotation"] = rotation.getValue();
|
||||
record[bone_name]["position"] = position.getValue();
|
||||
record[bone_name]["scale"] = scale.getValue();
|
||||
|
|
@ -494,17 +505,7 @@ void FSFloaterPoser::onClickRecaptureSelectedBones()
|
|||
if (currentlyPosing)
|
||||
continue;
|
||||
|
||||
LLVector3 newRotation = mPoserAnimator.getJointRotation(avatar, *item, getJointTranslation(item->jointName()),
|
||||
getJointNegation(item->jointName()), CURRENTROTATION);
|
||||
LLVector3 newPosition = mPoserAnimator.getJointPosition(avatar, *item, true);
|
||||
LLVector3 newScale = mPoserAnimator.getJointScale(avatar, *item, true);
|
||||
|
||||
mPoserAnimator.setPosingAvatarJoint(avatar, *item, true);
|
||||
|
||||
mPoserAnimator.setJointRotation(avatar, item, newRotation, NONE, getJointTranslation(item->jointName()),
|
||||
getJointNegation(item->jointName()));
|
||||
mPoserAnimator.setJointPosition(avatar, item, newPosition, NONE);
|
||||
mPoserAnimator.setJointScale(avatar, item, newScale, NONE);
|
||||
mPoserAnimator.recaptureJoint(avatar, *item, getJointTranslation(item->jointName()), getJointNegation(item->jointName()));
|
||||
}
|
||||
|
||||
refreshRotationSliders();
|
||||
|
|
@ -674,6 +675,51 @@ void FSFloaterPoser::onClickLoadHandPose(bool isRightHand)
|
|||
|
||||
}
|
||||
|
||||
bool FSFloaterPoser::poseFileStartsFromTeePose(const std::string& poseFileName)
|
||||
{
|
||||
std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, POSE_SAVE_SUBDIRECTORY);
|
||||
if (!gDirUtilp->fileExists(pathname))
|
||||
return false;
|
||||
|
||||
std::string fullPath =
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, POSE_SAVE_SUBDIRECTORY, poseFileName + POSE_INTERNAL_FORMAT_FILE_EXT);
|
||||
|
||||
try
|
||||
{
|
||||
LLSD pose;
|
||||
llifstream infile;
|
||||
bool startFromZeroRot = false;
|
||||
|
||||
infile.open(fullPath);
|
||||
if (!infile.is_open())
|
||||
return false;
|
||||
|
||||
S32 lineCount = LLSDSerialize::fromXML(pose, infile);
|
||||
if (lineCount == LLSDParser::PARSE_FAILURE)
|
||||
{
|
||||
LL_WARNS("Posing") << "Failed to parse file: " << poseFileName << LL_ENDL;
|
||||
return startFromZeroRot;
|
||||
}
|
||||
|
||||
for (LLSD::map_const_iterator itr = pose.beginMap(); itr != pose.endMap(); ++itr)
|
||||
{
|
||||
std::string const& name = itr->first;
|
||||
LLSD const& control_map = itr->second;
|
||||
|
||||
if (name == "startFromTeePose")
|
||||
startFromZeroRot = control_map["value"].asBoolean();
|
||||
}
|
||||
|
||||
return startFromZeroRot;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LL_WARNS("Posing") << "Unable to load or parse the pose: " << poseFileName << " exception: " << e.what() << LL_ENDL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FSFloaterPoser::loadPoseFromXml(LLVOAvatar* avatar, const std::string& poseFileName, E_LoadPoseMethods loadMethod)
|
||||
{
|
||||
std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, POSE_SAVE_SUBDIRECTORY);
|
||||
|
|
@ -732,7 +778,7 @@ void FSFloaterPoser::loadPoseFromXml(LLVOAvatar* avatar, const std::string& pose
|
|||
if (version > 3)
|
||||
loadPositionsAndScalesAsDeltas = true;
|
||||
|
||||
if (startFromZeroRot) // old save formats will always start from T-Pose, for better or worse.
|
||||
if (startFromZeroRot) // legacy saves will always start from T-Pose, for better or worse.
|
||||
{
|
||||
disableRecapture();
|
||||
mPoserAnimator.setAllAvatarStartingRotationsToZero(avatar);
|
||||
|
|
@ -772,7 +818,7 @@ void FSFloaterPoser::loadPoseFromXml(LLVOAvatar* avatar, const std::string& pose
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( const std::exception & e )
|
||||
{
|
||||
LL_WARNS("Posing") << "Everything caught fire trying to load the pose: " << poseFileName << " exception: " << e.what() << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ class FSFloaterPoser : public LLFloater
|
|||
void onClickBrowsePoseCache();
|
||||
void onPoseMenuAction(const LLSD& param);
|
||||
void loadPoseFromXml(LLVOAvatar* avatar, const std::string& poseFileName, E_LoadPoseMethods loadMethod);
|
||||
bool poseFileStartsFromTeePose(const std::string& poseFileName);
|
||||
void setPoseSaveFileTextBoxToUiSelectedAvatarSaveFileName();
|
||||
void setUiSelectedAvatarSaveFileName(const std::string& saveFileName);
|
||||
void showOrHideAdvancedSaveOptions();
|
||||
|
|
|
|||
|
|
@ -440,6 +440,40 @@ void FSPoserAnimator::setAllAvatarStartingRotationsToZero(LLVOAvatar* avatar)
|
|||
posingMotion->setAllRotationsToZero();
|
||||
}
|
||||
|
||||
void FSPoserAnimator::recaptureJoint(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation)
|
||||
{
|
||||
LLVector3 newRotation = getJointRotation(avatar, joint, translation, negation, CURRENTROTATION);
|
||||
LLVector3 newPosition = getJointPosition(avatar, joint, true);
|
||||
LLVector3 newScale = getJointScale(avatar, joint, true);
|
||||
|
||||
setPosingAvatarJoint(avatar, joint, true);
|
||||
setStartingJointRotation(avatar, &joint, newRotation, translation, negation);
|
||||
|
||||
// recapture of positions and scale does not reset starting values, since this this could result in unwanted residue deformation after posing stops.
|
||||
setJointPosition(avatar, &joint, newPosition, NONE);
|
||||
setJointScale(avatar, &joint, newScale, NONE);
|
||||
}
|
||||
|
||||
void FSPoserAnimator::setStartingJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& rotation,
|
||||
E_BoneAxisTranslation translation, S32 negation)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
return;
|
||||
if (!joint)
|
||||
return;
|
||||
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
FSPosingMotion::FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
LLQuaternion rot_quat = translateRotationToQuaternion(translation, negation, rotation);
|
||||
jointPose->setJointStartRotations(rot_quat);
|
||||
}
|
||||
|
||||
LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation, E_BoneRotationType rotType) const
|
||||
{
|
||||
LLVector3 vec3;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
/// <summary>
|
||||
/// Describes how we will cluster the joints/bones/thingos.
|
||||
/// Each joint/bone/thingo should have one of these, <see:"FSPoserAnimator.PoserJoints"/>.
|
||||
/// Each joint/bone/thingo should have one of these, FSPoserAnimator.PoserJoints.
|
||||
/// </summary>
|
||||
typedef enum E_BoneTypes
|
||||
{
|
||||
|
|
@ -446,7 +446,7 @@ public:
|
|||
/// <param name="avatar">The avatar whose joint is being queried.</param>
|
||||
/// <param name="joint">The joint to determine the rotation for.</param>
|
||||
/// <param name="translation">The joint to determine the rotation for.</param>
|
||||
/// <param name="negation">The style of negation to apply to the set.</param>
|
||||
/// <param name="negation">The style of negation to dis-apply to the get.</param>
|
||||
/// <param name="rotType">The type of rotation to get from the supplied joint for the supplied avatar.</param>
|
||||
/// <returns>The rotation of the requested joint, if determinable, otherwise a default vector.</returns>
|
||||
LLVector3 getJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation, E_BoneRotationType rotType) const;
|
||||
|
|
@ -459,6 +459,7 @@ public:
|
|||
/// <param name="rotation">The rotation to set the joint to.</param>
|
||||
/// <param name="style">Any ancilliary action to be taken with the change to be made.</param>
|
||||
/// <param name="translation">The axial translation form the supplied joint.</param>
|
||||
/// <param name="negation">The style of negation to apply to the set.</param>
|
||||
void setJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& rotation, E_BoneDeflectionStyles style,
|
||||
E_BoneAxisTranslation translation, S32 negation);
|
||||
|
||||
|
|
@ -492,6 +493,15 @@ public:
|
|||
/// <param name="avatar">The avatar whose pose should flip left-right.</param>
|
||||
void flipEntirePose(LLVOAvatar* avatar);
|
||||
|
||||
/// <summary>
|
||||
/// Recaptures the rotation, position and scale state of the supplied joint for the supplied avatar.
|
||||
/// </summary>
|
||||
/// <param name="avatar">The avatar whose joint is to be recaptured.</param>
|
||||
/// <param name="joint">The joint to recapture.</param>
|
||||
/// <param name="translation">The axial translation form the supplied joint.</param>
|
||||
/// <param name="negation">The style of negation to apply to the recapture.</param>
|
||||
void recaptureJoint(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation);
|
||||
|
||||
/// <summary>
|
||||
/// Sets all of the joint rotations of the supplied avatar to zero.
|
||||
/// </summary>
|
||||
|
|
@ -533,8 +543,8 @@ public:
|
|||
/// <param name="rotation">The rotation to load.</param>
|
||||
/// <remarks>
|
||||
/// All rotations we load are deltas to the current rotation the supplied joint has.
|
||||
/// Whether the joint already has a rotation because some animation is playing (sp possibly a non-zero rotation),
|
||||
/// or whether it is a rotation relative to zero, the result is always the same: just 'add' this rotation to the existing.
|
||||
/// Whether the joint already has a rotation because some animation is playing,
|
||||
/// or whether its rotation is zero, the result is always the same: just 'add' the supplied rotation to the existing rotation.
|
||||
/// </remarks>
|
||||
void loadJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, LLVector3 rotation);
|
||||
|
||||
|
|
@ -549,7 +559,7 @@ public:
|
|||
/// A position is saved as an absolute if the user created the pose from 'scratch' (at present the 'T-Pose').
|
||||
/// Otherwise the position is saved as a delta.
|
||||
/// The primary purpose is aesthetic: the numbers inside of a 'delta save file' have 'zeros everywhere'.
|
||||
/// A delta-save thus accurately reflects what the user changed, and not what the original creator of the modified pose specified.
|
||||
/// A delta-save thus accurately reflects what the user changed, and not what the original pose is.
|
||||
/// 'Legacy' (pre save format version-4) poses we expect to load as absolutes.
|
||||
/// </remarks>
|
||||
void loadJointPosition(LLVOAvatar* avatar, const FSPoserJoint* joint, bool loadPositionAsDelta, LLVector3 position);
|
||||
|
|
@ -612,6 +622,9 @@ public:
|
|||
/// <returns>True if the avatar is safe to manipulate, otherwise false.</returns>
|
||||
bool isAvatarSafeToUse(LLVOAvatar* avatar) const;
|
||||
|
||||
void setStartingJointRotation(LLVOAvatar* avatar, const FSPoserJoint* joint, const LLVector3& rotation,
|
||||
E_BoneAxisTranslation translation, S32 negation);
|
||||
|
||||
/// <summary>
|
||||
/// Maps the avatar's ID to the animation registered to them.
|
||||
/// Thus we start/stop the same animation, and get/set the same rotations etc.
|
||||
|
|
|
|||
|
|
@ -269,19 +269,20 @@ bool FSPosingMotion::allStartingRotationsAreZero() const
|
|||
|
||||
void FSPosingMotion::setAllRotationsToZero()
|
||||
{
|
||||
LLQuaternion zeroQuat;
|
||||
for (auto poserJoint_iter = mJointPoses.begin(); poserJoint_iter != mJointPoses.end(); ++poserJoint_iter)
|
||||
{
|
||||
if (poserJoint_iter->isCollisionVolume())
|
||||
continue;
|
||||
|
||||
poserJoint_iter->setRotationsToZero();
|
||||
poserJoint_iter->setJointStartRotations(zeroQuat);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr size_t MaximumUndoQueueLength = 20;
|
||||
|
||||
/// <summary>
|
||||
/// The constant time interval, in seconds,
|
||||
/// The constant time interval, in seconds, specifying whether an 'undo' value should be added.
|
||||
/// </summary>
|
||||
constexpr std::chrono::duration<double> UndoUpdateInterval = std::chrono::duration<double>(0.3);
|
||||
|
||||
|
|
@ -517,7 +518,7 @@ void FSPosingMotion::FSJointPose::revertCollisionVolume()
|
|||
joint->setScale(mBeginningScale);
|
||||
}
|
||||
|
||||
void FSPosingMotion::FSJointPose::setRotationsToZero() { mBeginningRotation = mTargetRotation = LLQuaternion(); }
|
||||
void FSPosingMotion::FSJointPose::setJointStartRotations(LLQuaternion quat) { mBeginningRotation = mTargetRotation = quat; }
|
||||
|
||||
FSPosingMotion::FSJointPose::FSJointPose(LLJoint* joint, bool isCollisionVolume)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -223,9 +223,9 @@ public:
|
|||
void revertCollisionVolume();
|
||||
|
||||
/// <summary>
|
||||
/// Sets all rotations to zero.
|
||||
/// Sets the beginning and target rotations to the supplied rotation.
|
||||
/// </summary>
|
||||
void setRotationsToZero();
|
||||
void setJointStartRotations(LLQuaternion quat);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the pointer to the jointstate for the joint this represents.
|
||||
|
|
|
|||
|
|
@ -654,7 +654,7 @@ width="403">
|
|||
background_visible="false"
|
||||
layout="topleft"
|
||||
visible="true"
|
||||
title="Posee"
|
||||
title="Model"
|
||||
mouse_opaque="false"
|
||||
name="avatarSelection_panel"
|
||||
top="0"
|
||||
|
|
@ -1137,7 +1137,7 @@ width="403">
|
|||
name="button_RecaptureParts"
|
||||
left_pad="1"
|
||||
top_delta="0"
|
||||
tool_tip="If the selected body part(s) is/are OFF, this Recaptures what those body parts are doing right now"
|
||||
tool_tip="If the selected body part(s) is/are OFF, this Recaptures what those body parts are doing right now. This button disables if you start from a T-Pose"
|
||||
width="45" >
|
||||
<button.commit_callback
|
||||
function="Poser.RecaptureSelectedBones"/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue