Visual Poser v1.1 (with UI refactor)
This merges in the V1.0 poser + changes since the last beta * a UI refactor (from angeldark raymaker) * unified undo/redo history (angeldark raymaker) * toggle to allow enable/disable of visual manipulator (beq) * undo/redo keyboard accelerator support (ctrl-z/ctrl-y) * improved focus loss/gain handing TODO: when another tool is used (edit tools) the floater still thinks visuals are active, toggling it fixes this but it can be handled bettermaster
commit
95dcbfb8c1
|
|
@ -146,6 +146,7 @@ set(viewer_SOURCE_FILES
|
|||
fslslbridgerequest.cpp
|
||||
fslslpreproc.cpp
|
||||
fslslpreprocviewer.cpp
|
||||
fsmaniprotatejoint.cpp
|
||||
fsmoneytracker.cpp
|
||||
fsnamelistavatarmenu.cpp
|
||||
fsnearbychatbarlistener.cpp
|
||||
|
|
@ -960,6 +961,7 @@ set(viewer_HEADER_FILES
|
|||
fslslpreproc.h
|
||||
fslslpreprocviewer.h
|
||||
fsmoneytracker.h
|
||||
fsmaniprotatejoint.h
|
||||
fsnamelistavatarmenu.h
|
||||
fsnearbychatbarlistener.h
|
||||
fsnearbychatcontrol.h
|
||||
|
|
|
|||
|
|
@ -26198,5 +26198,16 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>FSManipRotateJointUseNaturalDirection</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>use the natural bone direction instead of world rotation</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
</map>
|
||||
</llsd>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "fsfloaterposer.h"
|
||||
#include "fsposeranimator.h"
|
||||
#include "fsvirtualtrackpad.h"
|
||||
#include "v4color.h"
|
||||
#include "llagent.h"
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
|
|
@ -42,6 +43,7 @@
|
|||
#include "llwindow.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "lltoolcomp.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -55,7 +57,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 +75,10 @@ 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.ToggleVisualManipulators", [this](LLUICtrl*, const LLSD&) { onToggleVisualManipulators(); });
|
||||
|
||||
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 +88,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 +102,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,22 +112,13 @@ 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&)
|
||||
{
|
||||
onJointTabSelect();
|
||||
setRotationChangeButtons(false, false);
|
||||
});
|
||||
});
|
||||
|
||||
mAvatarSelectionScrollList = getChild<LLScrollListCtrl>("avatarSelection_scroll");
|
||||
mAvatarSelectionScrollList->setCommitOnSelectionChange(true);
|
||||
|
|
@ -162,9 +150,8 @@ 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);
|
||||
mToggleVisualManipulators = getChild<LLButton>("toggleVisualManipulators");
|
||||
mToggleVisualManipulators->setToggleState(true);
|
||||
|
||||
mTrackpadSensitivitySlider = getChild<LLSliderCtrl>("trackpad_sensitivity_slider");
|
||||
|
||||
|
|
@ -204,7 +191,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 +206,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");
|
||||
|
|
@ -232,6 +221,8 @@ bool FSFloaterPoser::postBuild()
|
|||
mScaleYSpnr = getChild<LLUICtrl>("adv_scaley_spinner");
|
||||
mScaleZSpnr = getChild<LLUICtrl>("adv_scalez_spinner");
|
||||
|
||||
mBtnJointRotate = getChild<LLButton>("button_joint_rotate_tool");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -241,21 +232,54 @@ void FSFloaterPoser::onOpen(const LLSD& key)
|
|||
onAvatarsRefresh();
|
||||
refreshJointScrollListMembers();
|
||||
onJointTabSelect();
|
||||
onOpenSetAdvancedPanel();
|
||||
refreshPoseScroll(mHandPresetsScrollList, POSE_PRESETS_HANDS_SUBDIRECTORY);
|
||||
startPosingSelf();
|
||||
|
||||
enableVisualManipulators();
|
||||
LLFloater::onOpen(key);
|
||||
}
|
||||
|
||||
|
||||
void FSFloaterPoser::onFocusReceived()
|
||||
{
|
||||
LLEditMenuHandler::gEditMenuHandler = this;
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onFocusLost()
|
||||
{
|
||||
if( LLEditMenuHandler::gEditMenuHandler == this )
|
||||
{
|
||||
LLEditMenuHandler::gEditMenuHandler = nullptr;
|
||||
}
|
||||
}
|
||||
void FSFloaterPoser::enableVisualManipulators()
|
||||
{
|
||||
if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset)
|
||||
{
|
||||
mLastToolset = LLToolMgr::getInstance()->getCurrentToolset();
|
||||
}
|
||||
LLToolMgr::getInstance()->setCurrentToolset(gPoserToolset);
|
||||
LLToolMgr::getInstance()->getCurrentToolset()->selectTool(FSToolCompPose::getInstance());
|
||||
FSToolCompPose::getInstance()->setAvatar( gAgentAvatarp);
|
||||
}
|
||||
|
||||
void FSFloaterPoser::disableVisualManipulators()
|
||||
{
|
||||
if (mLastToolset)
|
||||
{
|
||||
LLToolMgr::getInstance()->setCurrentToolset(mLastToolset);
|
||||
}
|
||||
FSToolCompPose::getInstance()->setAvatar(nullptr);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
disableVisualManipulators();
|
||||
LLFloater::onClose(app_quitting);
|
||||
}
|
||||
|
||||
|
|
@ -411,7 +435,7 @@ bool FSFloaterPoser::savePoseToXml(LLVOAvatar* avatar, const std::string& poseFi
|
|||
{
|
||||
bool savingDiff = !mPoserAnimator.allBaseRotationsAreZero(avatar);
|
||||
LLSD record;
|
||||
record["version"]["value"] = (S32)5;
|
||||
record["version"]["value"] = (S32)6;
|
||||
record["startFromTeePose"]["value"] = !savingDiff;
|
||||
|
||||
LLVector3 rotation, position, scale, zeroVector;
|
||||
|
|
@ -573,6 +597,33 @@ void FSFloaterPoser::onClickRecaptureSelectedBones()
|
|||
refreshTrackpadCursor();
|
||||
refreshTextHighlightingOnJointScrollLists();
|
||||
}
|
||||
void FSFloaterPoser::updatePosedBones()
|
||||
{
|
||||
auto selectedJoints = getUiSelectedPoserJoints();
|
||||
if (selectedJoints.size() < 1)
|
||||
return;
|
||||
|
||||
LLVOAvatar *avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
return;
|
||||
|
||||
if (!mPoserAnimator.isPosingAvatar(avatar))
|
||||
return;
|
||||
|
||||
for (auto item : selectedJoints)
|
||||
{
|
||||
bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item);
|
||||
if (!currentlyPosing)
|
||||
continue;
|
||||
|
||||
mPoserAnimator.recaptureJointAsDelta(avatar, *item, getJointTranslation(item->jointName()), getJointNegation(item->jointName()));
|
||||
}
|
||||
|
||||
setSavePosesButtonText(true);
|
||||
refreshRotationSlidersAndSpinners();
|
||||
refreshTrackpadCursor();
|
||||
refreshTextHighlightingOnJointScrollLists();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onClickBrowsePoseCache()
|
||||
{
|
||||
|
|
@ -582,8 +633,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 +664,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 +689,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 +737,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();
|
||||
|
|
@ -757,7 +776,7 @@ void FSFloaterPoser::onPoseMenuAction(const LLSD& param)
|
|||
loadPoseFromXml(avatar, poseName, loadType);
|
||||
onJointTabSelect();
|
||||
refreshJointScrollListMembers();
|
||||
setSavePosesButtonText(mPoserAnimator.allBaseRotationsAreZero(avatar));
|
||||
setSavePosesButtonText(!mPoserAnimator.allBaseRotationsAreZero(avatar));
|
||||
}
|
||||
|
||||
bool FSFloaterPoser::notDoubleClicked()
|
||||
|
|
@ -946,6 +965,9 @@ void FSFloaterPoser::loadPoseFromXml(LLVOAvatar* avatar, const std::string& pose
|
|||
version = (S32)control_map["value"].asInteger();
|
||||
}
|
||||
|
||||
if (version > 5 && startFromZeroRot)
|
||||
mPoserAnimator.setAllAvatarStartingRotationsToZero(avatar);
|
||||
|
||||
bool loadPositionsAndScalesAsDeltas = false;
|
||||
if (version > 3)
|
||||
loadPositionsAndScalesAsDeltas = true;
|
||||
|
|
@ -1018,7 +1040,7 @@ void FSFloaterPoser::startPosingSelf()
|
|||
|
||||
void FSFloaterPoser::stopPosingAllAvatars()
|
||||
{
|
||||
if (!gAgentAvatarp || gAgentAvatarp.isNull())
|
||||
if (!gAgentAvatarp || gAgentAvatarp.isNull() || !mAvatarSelectionScrollList)
|
||||
return;
|
||||
|
||||
for (auto listItem : mAvatarSelectionScrollList->getAllData())
|
||||
|
|
@ -1087,7 +1109,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 +1275,7 @@ void FSFloaterPoser::setRotationChangeButtons(bool togglingMirror, bool toggling
|
|||
refreshTrackpadCursor();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onUndoLastRotation()
|
||||
void FSFloaterPoser::onUndoLastChange()
|
||||
{
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if (!avatar)
|
||||
|
|
@ -1271,59 +1292,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 +1317,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 +1338,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 +1368,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 +1397,113 @@ 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()
|
||||
void FSFloaterPoser::onToggleVisualManipulators()
|
||||
{
|
||||
bool advancedPanelExpanded = mToggleAdvancedPanelBtn->getValue().asBoolean();
|
||||
if (advancedPanelExpanded)
|
||||
onToggleAdvancedPanel();
|
||||
bool tools_enabled = mToggleVisualManipulators->getValue().asBoolean();
|
||||
|
||||
if (tools_enabled)
|
||||
{
|
||||
enableVisualManipulators();
|
||||
}
|
||||
else
|
||||
{
|
||||
disableVisualManipulators();
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onToggleAdvancedPanel()
|
||||
void FSFloaterPoser::selectJointByName(const std::string& jointName)
|
||||
{
|
||||
if (isMinimized())
|
||||
return;
|
||||
LLTabContainer* tabContainer = mJointsTabs;
|
||||
std::vector<LLPanel*> panels = {
|
||||
mPositionRotationPnl,
|
||||
mBodyJointsPnl,
|
||||
mFaceJointsPnl,
|
||||
mHandsTabs,
|
||||
mMiscJointsPnl,
|
||||
mCollisionVolumesPnl
|
||||
};
|
||||
|
||||
std::vector<LLScrollListCtrl*> scrollLists = {
|
||||
mEntireAvJointScroll,
|
||||
mBodyJointsScrollList,
|
||||
mFaceJointsScrollList,
|
||||
mHandJointsScrollList,
|
||||
mMiscJointsScrollList,
|
||||
mCollisionVolumesScrollList
|
||||
};
|
||||
|
||||
bool advancedPanelExpanded = mToggleAdvancedPanelBtn->getValue().asBoolean();
|
||||
bool found = false;
|
||||
for (S32 i = 0; i < tabContainer->getTabCount(); ++i)
|
||||
{
|
||||
LLPanel* panel = tabContainer->getPanelByIndex(i);
|
||||
tabContainer->selectTabPanel(panel);
|
||||
|
||||
mAdvancedParentPnl->setVisible(advancedPanelExpanded);
|
||||
// Special handling for Hands tab
|
||||
if (panel == mHandsTabs)
|
||||
{
|
||||
mHandsTabs->selectTabPanel(mHandsJointsPnl);
|
||||
}
|
||||
|
||||
// change the height of the Poser panel
|
||||
S32 currentHeight = getRect().getHeight();
|
||||
S32 advancedPanelHeight = mAdvancedParentPnl->getRect().getHeight();
|
||||
for (auto scrollList : scrollLists)
|
||||
{
|
||||
scrollList->deselectAllItems();
|
||||
}
|
||||
|
||||
S32 poserFloaterHeight = advancedPanelExpanded ? currentHeight + advancedPanelHeight : currentHeight - advancedPanelHeight;
|
||||
S32 poserFloaterWidth = getRect().getWidth();
|
||||
auto scrollList = getScrollListForTab(panel);
|
||||
|
||||
if (poserFloaterHeight < 0)
|
||||
return;
|
||||
|
||||
reshape(poserFloaterWidth, poserFloaterHeight);
|
||||
onJointTabSelect();
|
||||
std::vector<LLScrollListItem*> items = scrollList->getAllData();
|
||||
for (auto item : items)
|
||||
{
|
||||
auto* userData = static_cast<FSPoserAnimator::FSPoserJoint*>(item->getUserdata());
|
||||
if (userData && userData->jointName() == jointName)
|
||||
{
|
||||
tabContainer->selectTab(i);
|
||||
scrollList->selectNthItem(scrollList->getItemIndex(item));
|
||||
scrollList->scrollToShowSelected();
|
||||
getUiSelectedPoserJoints();
|
||||
return; // Exit the loop once we've found and selected the joint
|
||||
}
|
||||
}
|
||||
}
|
||||
LL_WARNS() << "Joint not found: " << jointName << LL_ENDL;
|
||||
}
|
||||
|
||||
LLScrollListCtrl* FSFloaterPoser::getScrollListForTab(LLPanel * tabPanel) const
|
||||
{
|
||||
if (tabPanel == mPositionRotationPnl)
|
||||
{
|
||||
return mEntireAvJointScroll;
|
||||
}
|
||||
else if (tabPanel == mBodyJointsPnl)
|
||||
{
|
||||
return mBodyJointsScrollList;
|
||||
}
|
||||
else if (tabPanel == mFaceJointsPnl)
|
||||
{
|
||||
return mFaceJointsScrollList;
|
||||
}
|
||||
else if (tabPanel == mHandsTabs)
|
||||
{
|
||||
return mHandJointsScrollList;
|
||||
}
|
||||
else if (tabPanel == mMiscJointsPnl)
|
||||
{
|
||||
return mMiscJointsScrollList;
|
||||
}
|
||||
else if (tabPanel == mCollisionVolumesPnl)
|
||||
{
|
||||
return mCollisionVolumesScrollList;
|
||||
}
|
||||
|
||||
LL_WARNS() << "Unknown tab panel: " << tabPanel << LL_ENDL;
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<FSPoserAnimator::FSPoserJoint*> FSFloaterPoser::getUiSelectedPoserJoints() const
|
||||
{
|
||||
std::vector<FSPoserAnimator::FSPoserJoint*> joints;
|
||||
|
|
@ -1530,42 +1515,20 @@ std::vector<FSPoserAnimator::FSPoserJoint*> FSFloaterPoser::getUiSelectedPoserJo
|
|||
}
|
||||
|
||||
LLScrollListCtrl* scrollList{ nullptr };
|
||||
|
||||
|
||||
scrollList = getScrollListForTab(activeTab);
|
||||
if (activeTab == mPositionRotationPnl)
|
||||
{
|
||||
mEntireAvJointScroll->selectFirstItem();
|
||||
scrollList = mEntireAvJointScroll;
|
||||
}
|
||||
else if (activeTab == mBodyJointsPnl)
|
||||
{
|
||||
scrollList = mBodyJointsScrollList;
|
||||
}
|
||||
else if (activeTab == mFaceJointsPnl)
|
||||
{
|
||||
scrollList = mFaceJointsScrollList;
|
||||
}
|
||||
else if (activeTab == mHandsTabs)
|
||||
else if (activeTab == mHandsTabs )
|
||||
{
|
||||
auto activeHandsSubTab = mHandsTabs->getCurrentPanel();
|
||||
if (!activeHandsSubTab)
|
||||
{
|
||||
return joints;
|
||||
}
|
||||
|
||||
if (activeHandsSubTab == mHandsJointsPnl)
|
||||
{
|
||||
scrollList = mHandJointsScrollList;
|
||||
}
|
||||
}
|
||||
else if (activeTab == mMiscJointsPnl)
|
||||
{
|
||||
scrollList = mMiscJointsScrollList;
|
||||
}
|
||||
else if (activeTab == mCollisionVolumesPnl)
|
||||
{
|
||||
scrollList = mCollisionVolumesScrollList;
|
||||
}
|
||||
|
||||
if (!scrollList)
|
||||
{
|
||||
return joints;
|
||||
|
|
@ -1579,7 +1542,18 @@ std::vector<FSPoserAnimator::FSPoserJoint*> FSFloaterPoser::getUiSelectedPoserJo
|
|||
joints.push_back(userData);
|
||||
}
|
||||
}
|
||||
|
||||
auto avatarp = getUiSelectedAvatar();
|
||||
if (avatarp)
|
||||
{
|
||||
if(joints.size() >= 1)
|
||||
{
|
||||
FSToolCompPose::getInstance()->setJoint( gAgentAvatarp->getJoint( JointKey::construct(joints[0]->jointName())) );
|
||||
}
|
||||
else
|
||||
{
|
||||
FSToolCompPose::getInstance()->setJoint( nullptr );
|
||||
}
|
||||
}
|
||||
return joints;
|
||||
}
|
||||
|
||||
|
|
@ -1733,7 +1707,7 @@ void FSFloaterPoser::onAvatarPositionSet()
|
|||
mUpDownSpnr->setValue(posZ);
|
||||
|
||||
setSelectedJointsPosition(posX, posY, posZ);
|
||||
refreshAdvancedPositionSlidersAndSpinners();
|
||||
refreshPositionSlidersAndSpinners();
|
||||
}
|
||||
|
||||
void FSFloaterPoser::onLimbTrackballChanged()
|
||||
|
|
@ -1769,13 +1743,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 +1762,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 +1787,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 +1796,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 +1833,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 +1850,7 @@ void FSFloaterPoser::refreshAdvancedPositionSlidersAndSpinners()
|
|||
mAdvPosZSpnr->setValue(position.mV[VZ]);
|
||||
}
|
||||
|
||||
void FSFloaterPoser::refreshAdvancedScaleSlidersAndSpinners()
|
||||
void FSFloaterPoser::refreshScaleSlidersAndSpinners()
|
||||
{
|
||||
LLVector3 rotation = getScaleOfFirstSelectedJoint();
|
||||
|
||||
|
|
@ -2041,16 +2004,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
|
||||
|
|
@ -2110,6 +2069,10 @@ S32 FSFloaterPoser::getJointNegation(const std::string& jointName) const
|
|||
void FSFloaterPoser::onAvatarSelect()
|
||||
{
|
||||
LLVOAvatar* avatar = getUiSelectedAvatar();
|
||||
if(avatar)
|
||||
{
|
||||
FSToolCompPose::getInstance()->setAvatar(avatar);
|
||||
}
|
||||
mStartStopPosingBtn->setEnabled(couldAnimateAvatar(avatar));
|
||||
|
||||
bool arePosingSelected = mPoserAnimator.isPosingAvatar(avatar);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#define FS_FLOATER_POSER_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lltoolmgr.h"
|
||||
#include "fsposeranimator.h"
|
||||
|
||||
class FSVirtualTrackpad;
|
||||
|
|
@ -73,16 +74,23 @@ typedef enum E_Columns
|
|||
/// A class containing the UI fiddling for the Poser Floater.
|
||||
/// Please don't do LLJoint stuff here, fsposingmotion (the LLMotion derivative) is the class for that.
|
||||
/// </summary>
|
||||
class FSFloaterPoser : public LLFloater
|
||||
class FSFloaterPoser : public LLFloater, public LLEditMenuHandler
|
||||
{
|
||||
friend class LLFloaterReg;
|
||||
FSFloaterPoser(const LLSD &key);
|
||||
|
||||
public:
|
||||
void updatePosedBones();
|
||||
void selectJointByName(const std::string& jointName);
|
||||
void undo() override { onUndoLastChange(); };
|
||||
bool canUndo() const override { return true; }
|
||||
void redo() override { onRedoLastChange(); };
|
||||
bool canRedo() const override { return true; }
|
||||
private:
|
||||
bool postBuild() override;
|
||||
void onOpen(const LLSD& key) override;
|
||||
void onClose(bool app_quitting) override;
|
||||
|
||||
void onFocusReceived() override;
|
||||
void onFocusLost() override;
|
||||
/// <summary>
|
||||
/// Refreshes the supplied pose list from the supplued subdirectory.
|
||||
/// </summary>
|
||||
|
|
@ -176,7 +184,7 @@ class FSFloaterPoser : public LLFloater
|
|||
/// <param name="toFind">The avatar UUID to find on the avatars scroll list.</param>
|
||||
/// <returns>The scroll-list index for the supplied avatar, if found, otherwise -1.</returns>
|
||||
S32 getAvatarListIndexForUuid(const LLUUID& toFind) const;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// There are several control-callbacks manipulating rotations etc, they all devolve to these.
|
||||
/// In these are the appeals to the posing business layer.
|
||||
|
|
@ -185,11 +193,10 @@ class FSFloaterPoser : public LLFloater
|
|||
/// Using a set, then a get does not guarantee the value you just set.
|
||||
/// There may be +/- PI difference two axes, because harmonics.
|
||||
/// Thus keep your UI synced with less gets.
|
||||
/// </remarks>
|
||||
/// </remarks>
|
||||
void setSelectedJointsRotation(const LLVector3& absoluteRot, const LLVector3& deltaRot);
|
||||
void setSelectedJointsPosition(F32 x, F32 y, F32 z);
|
||||
void setSelectedJointsScale(F32 x, F32 y, F32 z);
|
||||
|
||||
/// <summary>
|
||||
/// Yeilds the rotation of the first selected joint (one may multi-select).
|
||||
/// </summary>
|
||||
|
|
@ -202,6 +209,7 @@ class FSFloaterPoser : public LLFloater
|
|||
LLVector3 getPositionOfFirstSelectedJoint() const;
|
||||
LLVector3 getScaleOfFirstSelectedJoint() const;
|
||||
|
||||
LLScrollListCtrl* getScrollListForTab(LLPanel * tabPanel) const;
|
||||
// Pose load/save
|
||||
void createUserPoseDirectoryIfNeeded();
|
||||
void onToggleLoadSavePanel();
|
||||
|
|
@ -215,30 +223,28 @@ class FSFloaterPoser : public LLFloater
|
|||
bool poseFileStartsFromTeePose(const std::string& poseFileName);
|
||||
void setPoseSaveFileTextBoxToUiSelectedAvatarSaveFileName();
|
||||
void setUiSelectedAvatarSaveFileName(const std::string& saveFileName);
|
||||
// visual manipulators control
|
||||
void enableVisualManipulators();
|
||||
void disableVisualManipulators();
|
||||
|
||||
// UI Event Handlers:
|
||||
void onAvatarsRefresh();
|
||||
void onAvatarSelect();
|
||||
void onJointTabSelect();
|
||||
void onToggleAdvancedPanel();
|
||||
void onToggleMirrorChange();
|
||||
void onToggleSympatheticChange();
|
||||
void onToggleVisualManipulators();
|
||||
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 +252,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.
|
||||
|
|
@ -443,13 +447,14 @@ class FSFloaterPoser : public LLFloater
|
|||
/// </remarks>
|
||||
static F32 unWrapScale(F32 scale);
|
||||
|
||||
LLToolset* mLastToolset{ nullptr };
|
||||
LLTool* mJointRotTool{ nullptr };
|
||||
|
||||
LLVector3 mLastSliderRotation;
|
||||
|
||||
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 +478,7 @@ class FSFloaterPoser : public LLFloater
|
|||
LLScrollListCtrl* mPosesScrollList{ nullptr };
|
||||
LLScrollListCtrl* mHandPresetsScrollList{ nullptr };
|
||||
|
||||
LLButton* mToggleAdvancedPanelBtn{ nullptr };
|
||||
LLButton* mToggleVisualManipulators{ nullptr };
|
||||
LLButton* mStartStopPosingBtn{ nullptr };
|
||||
LLButton* mToggleLoadSavePanelBtn{ nullptr };
|
||||
LLButton* mBrowserFolderBtn{ nullptr };
|
||||
|
|
@ -488,10 +493,10 @@ class FSFloaterPoser : public LLFloater
|
|||
LLButton* mToggleDeltaModeBtn{ nullptr };
|
||||
LLButton* mRedoChangeBtn{ nullptr };
|
||||
LLButton* mSetToTposeButton{ nullptr };
|
||||
LLButton* mBtnJointRotate{ nullptr };
|
||||
|
||||
LLLineEditor* mPoseSaveNameEditor{ nullptr };
|
||||
|
||||
LLPanel* mAdvancedParentPnl{ nullptr };
|
||||
LLPanel* mJointsParentPnl{ nullptr };
|
||||
LLPanel* mTrackballPnl{ nullptr };
|
||||
LLPanel* mPositionRotationPnl{ nullptr };
|
||||
|
|
|
|||
|
|
@ -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,86 @@ 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);
|
||||
}
|
||||
|
||||
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 +141,24 @@ void FSJointPose::recaptureJoint()
|
|||
if (!joint)
|
||||
return;
|
||||
|
||||
addToUndo(mRotation, &mUndoneRotationIndex, &mLastSetRotationDeltas, &mTimeLastUpdatedRotation);
|
||||
mRotation = FSJointRotation(joint->getRotation());
|
||||
addStateToUndo(FSJointState(mCurrentState));
|
||||
mCurrentState = FSJointState(joint);
|
||||
}
|
||||
void FSJointPose::recaptureJointAsDelta()
|
||||
{
|
||||
if (mIsCollisionVolume)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLJoint* joint = mJointState->getJoint();
|
||||
if (!joint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
addStateToUndo(mCurrentState);
|
||||
mCurrentState = FSJointState(joint);
|
||||
}
|
||||
|
||||
void FSJointPose::swapRotationWith(FSJointPose* oppositeJoint)
|
||||
|
|
@ -169,9 +168,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 +178,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,22 +188,12 @@ 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()
|
||||
{
|
||||
LLJoint* joint = mJointState->getJoint();
|
||||
if (!joint)
|
||||
return;
|
||||
|
||||
joint->setRotation(mRotation.baseRotation);
|
||||
joint->setPosition(mBeginningPosition);
|
||||
joint->setScale(mBeginningScale);
|
||||
mCurrentState.revertJointToBase(mJointState->getJoint());
|
||||
}
|
||||
|
||||
void FSJointPose::reflectRotation()
|
||||
|
|
@ -212,7 +201,7 @@ void FSJointPose::reflectRotation()
|
|||
if (mIsCollisionVolume)
|
||||
return;
|
||||
|
||||
mRotation.reflectRotation();
|
||||
mCurrentState.reflectRotation();
|
||||
}
|
||||
|
||||
void FSJointPose::zeroBaseRotation()
|
||||
|
|
@ -220,7 +209,7 @@ void FSJointPose::zeroBaseRotation()
|
|||
if (mIsCollisionVolume)
|
||||
return;
|
||||
|
||||
mRotation.baseRotation = LLQuaternion::DEFAULT;
|
||||
mCurrentState.zeroBaseRotation();
|
||||
}
|
||||
|
||||
bool FSJointPose::isBaseRotationZero() const
|
||||
|
|
@ -228,5 +217,5 @@ bool FSJointPose::isBaseRotationZero() const
|
|||
if (mIsCollisionVolume)
|
||||
return true;
|
||||
|
||||
return mRotation.baseRotation == LLQuaternion::DEFAULT;
|
||||
return mCurrentState.baseRotationIsZero();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -161,6 +143,11 @@ class FSJointPose
|
|||
/// Resets the beginning properties of the joint this represents.
|
||||
/// </summary>
|
||||
void recaptureJoint();
|
||||
/// <summary>
|
||||
/// Recalculates the delta reltive to the base for a new rotation.
|
||||
/// </summary>
|
||||
void recaptureJointAsDelta();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reverts the position/rotation/scale to their values when the animation begun.
|
||||
|
|
@ -168,52 +155,90 @@ 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;
|
||||
|
||||
LLQuaternion baseRotation;
|
||||
LLQuaternion deltaRotation;
|
||||
LLQuaternion getTargetRotation() const { return deltaRotation * baseRotation; }
|
||||
FSJointState() = default;
|
||||
LLQuaternion mDeltaRotation;
|
||||
LLQuaternion getTargetRotation() const { return mRotation * mBaseRotation; }
|
||||
LLVector3 getTargetPosition() const { return mPosition + mBasePosition; }
|
||||
LLVector3 getTargetScale() const { return mScale + mBaseScale; }
|
||||
void updateRotation(const LLQuaternion& newRotation)
|
||||
{
|
||||
auto inv_base = mBaseRotation;
|
||||
inv_base.conjugate();
|
||||
mDeltaRotation = newRotation * inv_base;
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool baseRotationIsZero() const { return mBaseRotation == LLQuaternion::DEFAULT; }
|
||||
|
||||
void zeroBaseRotation() { mBaseRotation = LLQuaternion::DEFAULT; }
|
||||
|
||||
void revertJointToBase(LLJoint* joint) const
|
||||
{
|
||||
if (!joint)
|
||||
return;
|
||||
|
||||
joint->setRotation(mBaseRotation);
|
||||
joint->setPosition(mBasePosition);
|
||||
joint->setScale(mBaseScale);
|
||||
}
|
||||
|
||||
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 +248,15 @@ 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;
|
||||
|
||||
/// <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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
#include "fsjointrotatetool.h"
|
||||
#include "llviewerobject.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
FSJointRotateTool::FSJointRotateTool() : LLTool(std::string("Rotate Joint"))
|
||||
{
|
||||
}
|
||||
|
||||
void FSJointRotateTool::handleSelect()
|
||||
{
|
||||
LL_INFOS() << "Rotate tool selected" << LL_ENDL;
|
||||
}
|
||||
|
||||
void FSJointRotateTool::handleDeselect()
|
||||
{
|
||||
LL_INFOS() << "Rotate tool deselected" << LL_ENDL;
|
||||
}
|
||||
|
||||
bool FSJointRotateTool::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if (findSelectedManipulator(x, y))
|
||||
{
|
||||
LLVOAvatar* avatar = gAgentAvatarp; // Assume the avatar is the agent avatar
|
||||
if (avatar)
|
||||
{
|
||||
rotateJoint(avatar);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FSJointRotateTool::handleHover(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
return findSelectedManipulator(x, y);
|
||||
}
|
||||
|
||||
void FSJointRotateTool::render()
|
||||
{
|
||||
computeManipulatorSize();
|
||||
renderManipulators();
|
||||
}
|
||||
|
||||
void FSJointRotateTool::rotateJoint(LLVOAvatar* avatar)
|
||||
{
|
||||
// Use joint rotation APIs, perhaps from FSPoserAnimator
|
||||
LL_INFOS() << "Rotating joint" << LL_ENDL;
|
||||
}
|
||||
|
||||
bool FSJointRotateTool::findSelectedManipulator(S32 x, S32 y)
|
||||
{
|
||||
// Implement logic to detect user selection of a manipulator
|
||||
return false;
|
||||
}
|
||||
|
||||
void FSJointRotateTool::computeManipulatorSize()
|
||||
{
|
||||
mManipulatorSize = 5.0f; // Example size
|
||||
}
|
||||
|
||||
void FSJointRotateTool::renderManipulators()
|
||||
{
|
||||
// Render manipulators (axes or rotation handles) using OpenGL
|
||||
gGL.color4f(0.5f, 0.5f, 0.5f, 0.5f); // Example color
|
||||
gGL.flush();
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef FS_JOINTROTATETOOL_H
|
||||
#define FS_JOINTROTATETOOL_H
|
||||
|
||||
#include "lltool.h"
|
||||
#include "llbbox.h"
|
||||
#include "llvoavatar.h"
|
||||
|
||||
class FSJointRotateTool : public LLTool, public LLSingleton<FSJointRotateTool>
|
||||
{
|
||||
LLSINGLETON(FSJointRotateTool);
|
||||
|
||||
public:
|
||||
void handleSelect() override;
|
||||
void handleDeselect() override;
|
||||
bool handleMouseDown(S32 x, S32 y, MASK mask) override;
|
||||
bool handleHover(S32 x, S32 y, MASK mask) override;
|
||||
void render() override;
|
||||
|
||||
private:
|
||||
void rotateJoint(LLVOAvatar* avatar);
|
||||
bool findSelectedManipulator(S32 x, S32 y);
|
||||
void computeManipulatorSize();
|
||||
void renderManipulators();
|
||||
|
||||
LLBBox mBBox;
|
||||
F32 mManipulatorSize;
|
||||
S32 mHighlightedAxis;
|
||||
F32 mHighlightedDirection;
|
||||
bool mForce;
|
||||
};
|
||||
|
||||
#endif // FS_JOINTROTATETOOL_H
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,119 @@
|
|||
// File: fsmaniprotatejoint.h
|
||||
|
||||
#ifndef FS_MANIP_ROTATE_JOINT_H
|
||||
#define FS_MANIP_ROTATE_JOINT_H
|
||||
#include "llselectmgr.h"
|
||||
#include "llmaniprotate.h"
|
||||
class LLJoint;
|
||||
class LLVOAvatar; // or LLVOAvatarSelf, etc.
|
||||
namespace {
|
||||
const F32 AXIS_ONTO_CAM_TOLERANCE = cos( 80.f * DEG_TO_RAD ); // cos() is not constexpr til c++26
|
||||
constexpr F32 RADIUS_PIXELS = 100.f; // size in screen space
|
||||
constexpr S32 CIRCLE_STEPS = 100;
|
||||
constexpr F32 CIRCLE_STEP_SIZE = 2.0f * F_PI / CIRCLE_STEPS;
|
||||
constexpr F32 SQ_RADIUS = RADIUS_PIXELS * RADIUS_PIXELS;
|
||||
constexpr F32 WIDTH_PIXELS = 8;
|
||||
constexpr F32 MAX_MANIP_SELECT_DISTANCE = 100.f;
|
||||
constexpr F32 SNAP_ANGLE_INCREMENT = 5.625f;
|
||||
constexpr F32 SNAP_ANGLE_DETENTE = SNAP_ANGLE_INCREMENT;
|
||||
constexpr F32 SNAP_GUIDE_RADIUS_1 = 2.8f;
|
||||
constexpr F32 SNAP_GUIDE_RADIUS_2 = 2.4f;
|
||||
constexpr F32 SNAP_GUIDE_RADIUS_3 = 2.2f;
|
||||
constexpr F32 SNAP_GUIDE_RADIUS_4 = 2.1f;
|
||||
constexpr F32 SNAP_GUIDE_RADIUS_5 = 2.05f;
|
||||
constexpr F32 SNAP_GUIDE_INNER_RADIUS = 2.f;
|
||||
constexpr F32 SELECTED_MANIPULATOR_SCALE = 1.05f;
|
||||
constexpr F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
|
||||
constexpr S32 VERTICAL_OFFSET = 100;
|
||||
|
||||
}
|
||||
class FSManipRotateJoint : public LLManipRotate
|
||||
{
|
||||
// Used for overriding the natural "up" direction of a joint.
|
||||
// if no override is set then the world up direction is used unless the joint is vertical in which case we pick an arbitrary normal
|
||||
static std::unordered_map<std::string, LLVector3> sReferenceUpVectors;
|
||||
|
||||
struct BoneAxes
|
||||
{
|
||||
LLVector3 naturalX;
|
||||
LLVector3 naturalY;
|
||||
LLVector3 naturalZ;
|
||||
};
|
||||
LLQuaternion computeAlignmentQuat( const BoneAxes& boneAxes ) const;
|
||||
BoneAxes computeBoneAxes() const;
|
||||
public:
|
||||
FSManipRotateJoint(LLToolComposite* composite);
|
||||
virtual ~FSManipRotateJoint() {}
|
||||
static std::string getManipPartString(EManipPart part);
|
||||
// Called to designate which joint we are going to manipulate.
|
||||
void setJoint(LLJoint* joint);
|
||||
|
||||
void setAvatar(LLVOAvatar* avatar);
|
||||
|
||||
// Overrides
|
||||
void handleSelect() override;
|
||||
bool updateVisiblity();
|
||||
void render() override;
|
||||
void renderNameXYZ(const LLVector3 &vec);
|
||||
bool handleMouseDown(S32 x, S32 y, MASK mask) override;
|
||||
bool handleMouseUp(S32 x, S32 y, MASK mask) override;
|
||||
bool handleHover(S32 x, S32 y, MASK mask) override;
|
||||
void drag(S32 x, S32 y) override;
|
||||
bool isAlwaysRendered() override { return true; }
|
||||
void highlightManipulators(S32 x, S32 y) override;
|
||||
bool handleMouseDownOnPart(S32 x, S32 y, MASK mask) override;
|
||||
void highlightHoverSpheres(S32 mouseX, S32 mouseY);
|
||||
protected:
|
||||
// void renderNameXYZ(const std::string name, const LLVector3 &vec);
|
||||
LLQuaternion dragUnconstrained( S32 x, S32 y );
|
||||
LLQuaternion dragConstrained( S32 x, S32 y );
|
||||
LLVector3 getConstraintAxis() const { return mConstraintAxis; };
|
||||
LLVector3 setConstraintAxis();
|
||||
bool computeMouseIntersectionOnSphere(S32 x, S32 y,
|
||||
const LLVector3d& sphere_center_global,
|
||||
F32 sphere_radius,
|
||||
LLVector3& outIntersection);
|
||||
|
||||
// Instead of selecting an LLViewerObject, we have a single joint
|
||||
LLJoint* mJoint = nullptr;
|
||||
BoneAxes mBoneAxes;
|
||||
LLQuaternion mNaturalAlignmentQuat;
|
||||
LLVOAvatar* mAvatar = nullptr;
|
||||
// We'll store the joint's original rotation for reference
|
||||
LLQuaternion mSavedJointRot;
|
||||
LLJoint * mHighlightedJoint = nullptr;
|
||||
F32 mHighlightedPartDistance = 0.f;
|
||||
LLVector3 mInitialIntersection; // The initial point on the manipulator’s sphere (in agent space)
|
||||
const std::vector<std::string_view> getSelectableJoints(){ return sSelectableJoints; };
|
||||
private:
|
||||
static const std::vector<std::string_view> sSelectableJoints;
|
||||
|
||||
// Structure holding parameters needed to render one manipulator ring.
|
||||
struct RingRenderParams
|
||||
{
|
||||
EManipPart part; // e.g. LL_ROT_Z, LL_ROT_Y, LL_ROT_X, etc.
|
||||
LLVector4 targetScale; // Target scale for mManipulatorScales for this part.
|
||||
float extraRotateAngle; // Extra rotation angle (in degrees) to apply.
|
||||
LLVector3 extraRotateAxis; // Axis for the extra rotation.
|
||||
LLColor4 primaryColor; // Primary ring color.
|
||||
LLColor4 secondaryColor; // Secondary ring color.
|
||||
int scaleIndex; // Which component of mManipulatorScales to use (0: X, 1: Y, 2: Z, 3: Roll).
|
||||
};
|
||||
|
||||
static const std::unordered_map<EManipPart, RingRenderParams> sRingParams;
|
||||
void updateManipulatorScale(EManipPart part, LLVector4& scales);
|
||||
void renderActiveRing( F32 radius, F32 width, const LLColor4& front_color, const LLColor4& back_color);
|
||||
void renderManipulatorRings(const LLVector3& center, const LLQuaternion& finalAlignment);
|
||||
|
||||
void renderCenterCircle(const F32 radius, const LLColor4 normal_color=LLColor4(0.7f,0.7,0.7f,0.2), const LLColor4 highlight_color=LLColor4(0.8f,0.8f,0.8f,0.3));
|
||||
void renderCenterSphere(const F32 radius, const LLColor4 normal_color=LLColor4(0.7f,0.7,0.7f,0.2), const LLColor4 highlight_color=LLColor4(0.8f,0.8f,0.8f,0.3));
|
||||
void renderDetailedRings(float width_meters);
|
||||
void renderRingPass(const RingRenderParams& params, float radius, float width, int pass);
|
||||
void renderAxes(const LLVector3& center, F32 size, const LLQuaternion& rotation);
|
||||
|
||||
float mLastAngle = 0.f;
|
||||
LLVector3 mConstraintAxis;
|
||||
|
||||
};
|
||||
|
||||
#endif // FS_MANIP_ROTATE_JOINT_H
|
||||
|
|
@ -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:
|
||||
|
|
@ -478,6 +322,22 @@ void FSPoserAnimator::recaptureJoint(LLVOAvatar* avatar, const FSPoserJoint& joi
|
|||
jointPose->recaptureJoint();
|
||||
setPosingAvatarJoint(avatar, joint, true);
|
||||
}
|
||||
void FSPoserAnimator::recaptureJointAsDelta(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation)
|
||||
{
|
||||
if (!isAvatarSafeToUse(avatar))
|
||||
return;
|
||||
|
||||
FSPosingMotion* posingMotion = getPosingMotion(avatar);
|
||||
if (!posingMotion)
|
||||
return;
|
||||
|
||||
FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName());
|
||||
if (!jointPose)
|
||||
return;
|
||||
|
||||
jointPose->recaptureJointAsDelta();
|
||||
setPosingAvatarJoint(avatar, joint, true);
|
||||
}
|
||||
|
||||
LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation) const
|
||||
{
|
||||
|
|
@ -493,7 +353,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 +383,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 +420,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 +429,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 +463,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 +649,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 +671,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 +682,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 +709,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 +735,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 +752,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 +771,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)
|
||||
|
|
|
|||
|
|
@ -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,14 +500,23 @@ 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.
|
||||
/// AsDelta variant retians the original base and creates a delta relative to it.
|
||||
/// </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);
|
||||
void recaptureJointAsDelta(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation);
|
||||
|
||||
/// <summary>
|
||||
/// Sets all of the joint rotations of the supplied avatar to zero.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -771,7 +771,7 @@ LLAppViewer::LLAppViewer()
|
|||
// static_debug_info.log file
|
||||
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
|
||||
// <FS:Beq> Improve Bugsplat tracking by using attributes
|
||||
BugSplatAttributes::setCrashContextFileName(logdir + "crash-context.xml");
|
||||
BugSplatAttributes::setCrashContextFileName(logdir + "CrashContext.xml");
|
||||
// </FS:Beq>
|
||||
# else // ! LL_BUGSPLAT
|
||||
// write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class LLColor4;
|
|||
|
||||
class LLManipRotate : public LLManip
|
||||
{
|
||||
friend class FSManipRotateJoint;
|
||||
public:
|
||||
class ManipulatorHandle
|
||||
{
|
||||
|
|
@ -67,13 +68,13 @@ public:
|
|||
private:
|
||||
void updateHoverView();
|
||||
|
||||
void drag( S32 x, S32 y );
|
||||
virtual void drag( S32 x, S32 y );
|
||||
LLVector3 projectToSphere( F32 x, F32 y, bool* on_sphere );
|
||||
|
||||
void renderSnapGuides();
|
||||
void renderActiveRing(F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color);
|
||||
|
||||
bool updateVisiblity();
|
||||
virtual bool updateVisiblity();
|
||||
LLVector3 findNearestPointOnRing( S32 x, S32 y, const LLVector3& center, const LLVector3& axis );
|
||||
|
||||
LLQuaternion dragUnconstrained( S32 x, S32 y );
|
||||
|
|
|
|||
|
|
@ -899,3 +899,165 @@ bool LLToolCompGun::handleScrollWheel(S32 x, S32 y, S32 clicks)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#include "llviewerwindow.h" // for gViewerWindow->pickAsync()
|
||||
#include "llselectmgr.h" // for LLSelectMgr
|
||||
#include "llfloaterreg.h" // for LLFloaterReg::showInstance()
|
||||
#include "llviewermenu.h" // for LLEditMenuHandler::gEditMenuHandler
|
||||
#include "fsfloaterposer.h"
|
||||
|
||||
// If you want a standard static instance approach:
|
||||
FSToolCompPose* FSToolCompPose::getInstance()
|
||||
{
|
||||
// Meyers singleton pattern
|
||||
static FSToolCompPose instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// Constructor
|
||||
FSToolCompPose::FSToolCompPose()
|
||||
: LLToolComposite(std::string("Pose"))
|
||||
{
|
||||
// Create a joint manipulator
|
||||
mManip = new FSManipRotateJoint(this);
|
||||
|
||||
// Possibly create a selection rectangle tool if you want
|
||||
// to be able to box-select joints or objects
|
||||
// (same usage as LLToolCompRotate does)
|
||||
// mSelectRect = new LLToolSelectRect(this);
|
||||
|
||||
// Set the default and current subtool
|
||||
mCur = mManip;
|
||||
mDefault = mManip;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// Destructor
|
||||
FSToolCompPose::~FSToolCompPose()
|
||||
{
|
||||
delete mManip;
|
||||
mManip = nullptr;
|
||||
|
||||
delete mSelectRect;
|
||||
mSelectRect = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// Handle Hover
|
||||
bool FSToolCompPose::handleHover(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
// If the current subtool hasn't captured the mouse,
|
||||
// switch to your manip subtool (like LLToolCompRotate).
|
||||
if (!mCur->hasMouseCapture())
|
||||
{
|
||||
setCurrentTool(mManip);
|
||||
}
|
||||
return mCur->handleHover(x, y, mask);
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// Handle MouseDown
|
||||
bool FSToolCompPose::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
mMouseDown = true;
|
||||
|
||||
// Kick off an async pick, which calls pickCallback when complete
|
||||
// so we can see if user clicked on a manip ring or not
|
||||
gViewerWindow->pickAsync(x, y, mask, pickCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// The pickCallback
|
||||
void FSToolCompPose::pickCallback(const LLPickInfo& pick_info)
|
||||
{
|
||||
FSToolCompPose* self = FSToolCompPose::getInstance();
|
||||
FSManipRotateJoint* manip = self->mManip;
|
||||
|
||||
if (!manip) return; // No manipulator available, exit
|
||||
|
||||
// Highlight the manipulator based on the mouse position
|
||||
manip->highlightManipulators(pick_info.mMousePt.mX, pick_info.mMousePt.mY);
|
||||
|
||||
if (!self->mMouseDown)
|
||||
{
|
||||
// No action needed if mouse is up; interaction is handled by highlight logic
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if a manipulator ring is highlighted
|
||||
if (manip->getHighlightedPart() != LLManip::LL_NO_PART)
|
||||
{
|
||||
// Switch to the manipulator tool for dragging
|
||||
self->setCurrentTool(manip);
|
||||
manip->handleMouseDownOnPart(pick_info.mMousePt.mX, pick_info.mMousePt.mY, pick_info.mKeyMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no ring is highlighted, reset interaction or do nothing
|
||||
LL_DEBUGS("FSToolCompPose") << "No manipulator ring selected" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------
|
||||
// Handle MouseUp
|
||||
bool FSToolCompPose::handleMouseUp(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
mMouseDown = false;
|
||||
// The base LLToolComposite sets mCur->handleMouseUp(...)
|
||||
// and does other management
|
||||
return LLToolComposite::handleMouseUp(x, y, mask);
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// getOverrideTool
|
||||
// If you want SHIFT+CTRL combos to do something else
|
||||
LLTool* FSToolCompPose::getOverrideTool(MASK mask)
|
||||
{
|
||||
// Example from LLToolCompRotate that calls scale if SHIFT+CTRL
|
||||
if (mask == (MASK_CONTROL | MASK_SHIFT))
|
||||
{
|
||||
// If you have a scale tool, return that. Or else remove
|
||||
// this if you don't want an override.
|
||||
return LLToolCompScale::getInstance();
|
||||
}
|
||||
// Otherwise fallback
|
||||
return LLToolComposite::getOverrideTool(mask);
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// Handle DoubleClick
|
||||
bool FSToolCompPose::handleDoubleClick(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if (!mManip->getSelection()->isEmpty() &&
|
||||
mManip->getHighlightedPart() == LLManip::LL_NO_PART)
|
||||
{
|
||||
// Possibly show some pose properties or open the pose floater
|
||||
mPoser = dynamic_cast<FSFloaterPoser*>(LLFloaterReg::showInstance("fs_poser"));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If nothing selected, try a mouse down again
|
||||
return handleMouseDown(x, y, mask);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// render
|
||||
void FSToolCompPose::render()
|
||||
{
|
||||
// Render the current subtool
|
||||
mCur->render();
|
||||
|
||||
// If the current subtool is not the manip, we can still
|
||||
// optionally draw manip guidelines in the background
|
||||
if (mCur != mManip)
|
||||
{
|
||||
mManip->renderGuidelines(); // or something similar if your manip has it
|
||||
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,5 +252,44 @@ protected:
|
|||
LLTool* mNull;
|
||||
};
|
||||
|
||||
// Subclass of LLToolComposite
|
||||
#include "fsmaniprotatejoint.h" // For FSManipRotateJoint
|
||||
#include "fsfloaterposer.h"
|
||||
class FSToolCompPose : public LLToolComposite
|
||||
{
|
||||
public:
|
||||
// Typical pattern: pass a name like "Pose"
|
||||
FSToolCompPose();
|
||||
virtual ~FSToolCompPose();
|
||||
|
||||
// For some viewer patterns, we create a static singleton:
|
||||
static FSToolCompPose* getInstance();
|
||||
|
||||
// Overriding base events:
|
||||
virtual bool handleHover(S32 x, S32 y, MASK mask) override;
|
||||
virtual bool handleMouseDown(S32 x, S32 y, MASK mask) override;
|
||||
virtual bool handleMouseUp(S32 x, S32 y, MASK mask) override;
|
||||
virtual bool handleDoubleClick(S32 x, S32 y, MASK mask) override;
|
||||
virtual void render() override;
|
||||
void setAvatar(LLVOAvatar* avatar) { mManip->setAvatar(avatar); };
|
||||
void setJoint( LLJoint * joint ) { mManip->setJoint( joint ); };
|
||||
|
||||
// Optional override if you have SHIFT/CTRL combos
|
||||
virtual LLTool* getOverrideTool(MASK mask) override;
|
||||
|
||||
// The pick callback invoked on async pick
|
||||
static void pickCallback(const LLPickInfo& pick_info);
|
||||
void setPoserFloater(FSFloaterPoser* poser){ mPoser = poser; };
|
||||
FSFloaterPoser* getPoserFloater(){ return mPoser; };
|
||||
protected:
|
||||
// Tools within this composite
|
||||
FSManipRotateJoint* mManip = nullptr;
|
||||
LLToolSelectRect* mSelectRect= nullptr;
|
||||
FSFloaterPoser* mPoser = nullptr;
|
||||
|
||||
// Track mouse state similarly to LLToolCompRotate
|
||||
bool mMouseDown = false;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_TOOLCOMP_H
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ LLToolset* gCameraToolset = NULL;
|
|||
//LLToolset* gLandToolset = NULL;
|
||||
LLToolset* gMouselookToolset = NULL;
|
||||
LLToolset* gFaceEditToolset = NULL;
|
||||
LLToolset* gPoserToolset = nullptr;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// LLToolMgr
|
||||
|
|
@ -99,6 +100,8 @@ LLToolMgr::LLToolMgr()
|
|||
// gLandToolset = new LLToolset();
|
||||
gMouselookToolset = new LLToolset();
|
||||
gFaceEditToolset = new LLToolset();
|
||||
gPoserToolset = new LLToolset();
|
||||
gPoserToolset->setShowFloaterTools(false);
|
||||
gMouselookToolset->setShowFloaterTools(false);
|
||||
gFaceEditToolset->setShowFloaterTools(false);
|
||||
}
|
||||
|
|
@ -121,6 +124,7 @@ void LLToolMgr::initTools()
|
|||
gMouselookToolset->addTool( LLToolCompGun::getInstance() );
|
||||
gBasicToolset->addTool( LLToolCompInspect::getInstance() );
|
||||
gFaceEditToolset->addTool( LLToolCamera::getInstance() );
|
||||
gPoserToolset->addTool( FSToolCompPose::getInstance() );
|
||||
|
||||
// On startup, use "select" tool
|
||||
setCurrentToolset(gBasicToolset);
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ extern LLToolset *gCameraToolset;
|
|||
//extern LLToolset *gLandToolset;
|
||||
extern LLToolset* gMouselookToolset;
|
||||
extern LLToolset* gFaceEditToolset;
|
||||
extern LLToolset* gPoserToolset;
|
||||
|
||||
extern LLTool* gToolNull;
|
||||
|
||||
|
|
|
|||
|
|
@ -5096,6 +5096,13 @@ void LLViewerWindow::renderSelections( bool for_gl_pick, bool pick_parcel_walls,
|
|||
// Call this once and only once
|
||||
LLSelectMgr::getInstance()->updateSilhouettes();
|
||||
}
|
||||
// <FS:Beq> render the poser manipulator guides
|
||||
// if we have something selected those toosl should override
|
||||
if ( (!for_hud) && (selection->isEmpty()) && (LLToolMgr::getInstance()->getCurrentTool() == FSToolCompPose::getInstance()) )
|
||||
{
|
||||
FSToolCompPose::getInstance()->render();
|
||||
}
|
||||
// </FS:Beq>
|
||||
|
||||
// Draw fence around land selections
|
||||
if (for_gl_pick)
|
||||
|
|
|
|||
|
|
@ -1934,6 +1934,227 @@ void LLVOAvatar::renderBones(const std::string &selected_joint)
|
|||
}
|
||||
}
|
||||
|
||||
void LLVOAvatar::renderOnlySelectedBones(const std::vector<std::string> &selected_joints)
|
||||
{
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
|
||||
avatar_joint_list_t::iterator iter = mSkeleton.begin();
|
||||
avatar_joint_list_t::iterator end = mSkeleton.end();
|
||||
|
||||
// For selected joints
|
||||
static LLVector3 SELECTED_COLOR_OCCLUDED(1.0f, 1.0f, 0.0f);
|
||||
static LLVector3 SELECTED_COLOR_VISIBLE(0.5f, 0.5f, 0.5f);
|
||||
// For bones with position overrides defined
|
||||
static LLVector3 OVERRIDE_COLOR_OCCLUDED(1.0f, 0.0f, 0.0f);
|
||||
static LLVector3 OVERRIDE_COLOR_VISIBLE(0.5f, 0.5f, 0.5f);
|
||||
// For bones which are rigged to by at least one attachment
|
||||
static LLVector3 RIGGED_COLOR_OCCLUDED(0.0f, 1.0f, 1.0f);
|
||||
static LLVector3 RIGGED_COLOR_VISIBLE(0.5f, 0.5f, 0.5f);
|
||||
// For bones not otherwise colored
|
||||
static LLVector3 OTHER_COLOR_OCCLUDED(0.0f, 1.0f, 0.0f);
|
||||
static LLVector3 OTHER_COLOR_VISIBLE(0.5f, 0.5f, 0.5f);
|
||||
|
||||
static F32 SPHERE_SCALEF = 0.001f;
|
||||
|
||||
for (; iter != end; ++iter)
|
||||
{
|
||||
LLJoint* jointp = *iter;
|
||||
if (!jointp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (std::find(selected_joints.begin(), selected_joints.end(), jointp->getName()) == selected_joints.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
jointp->updateWorldMatrix();
|
||||
|
||||
LLVector3 occ_color, visible_color;
|
||||
|
||||
occ_color = SELECTED_COLOR_OCCLUDED;
|
||||
visible_color = SELECTED_COLOR_VISIBLE;
|
||||
|
||||
gGL.pushMatrix();
|
||||
gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] );
|
||||
|
||||
gGL.diffuseColor3f( 1.f, 0.f, 1.f );
|
||||
|
||||
gGL.begin(LLRender::LINES);
|
||||
|
||||
LLVector3 v[] =
|
||||
{
|
||||
LLVector3(1,0,0),
|
||||
LLVector3(-1,0,0),
|
||||
LLVector3(0,1,0),
|
||||
LLVector3(0,-1,0),
|
||||
|
||||
LLVector3(0,0,-1),
|
||||
LLVector3(0,0,1),
|
||||
};
|
||||
|
||||
//sides
|
||||
gGL.vertex3fv(v[0].mV);
|
||||
gGL.vertex3fv(v[2].mV);
|
||||
|
||||
gGL.vertex3fv(v[0].mV);
|
||||
gGL.vertex3fv(v[3].mV);
|
||||
|
||||
gGL.vertex3fv(v[1].mV);
|
||||
gGL.vertex3fv(v[2].mV);
|
||||
|
||||
gGL.vertex3fv(v[1].mV);
|
||||
gGL.vertex3fv(v[3].mV);
|
||||
|
||||
|
||||
//top
|
||||
gGL.vertex3fv(v[0].mV);
|
||||
gGL.vertex3fv(v[4].mV);
|
||||
|
||||
gGL.vertex3fv(v[1].mV);
|
||||
gGL.vertex3fv(v[4].mV);
|
||||
|
||||
gGL.vertex3fv(v[2].mV);
|
||||
gGL.vertex3fv(v[4].mV);
|
||||
|
||||
gGL.vertex3fv(v[3].mV);
|
||||
gGL.vertex3fv(v[4].mV);
|
||||
|
||||
|
||||
//bottom
|
||||
gGL.vertex3fv(v[0].mV);
|
||||
gGL.vertex3fv(v[5].mV);
|
||||
|
||||
gGL.vertex3fv(v[1].mV);
|
||||
gGL.vertex3fv(v[5].mV);
|
||||
|
||||
gGL.vertex3fv(v[2].mV);
|
||||
gGL.vertex3fv(v[5].mV);
|
||||
|
||||
gGL.vertex3fv(v[3].mV);
|
||||
gGL.vertex3fv(v[5].mV);
|
||||
|
||||
gGL.end();
|
||||
|
||||
gGL.popMatrix();
|
||||
|
||||
|
||||
// renderBoxAroundJointAttachments( jointp );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// // draw joint space bounding boxes of rigged attachments in yellow
|
||||
// gGL.color3f(1.f, 1.f, 0.f);
|
||||
// for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++)
|
||||
// {
|
||||
// LLJoint* joint = getJoint(joint_num);
|
||||
// LLJointRiggingInfo* rig_info = NULL;
|
||||
// if (joint_num < mJointRiggingInfoTab.size())
|
||||
// {
|
||||
// rig_info = &mJointRiggingInfoTab[joint_num];
|
||||
// }
|
||||
|
||||
// if (joint && rig_info && rig_info->isRiggedTo())
|
||||
// {
|
||||
// LLViewerJointAttachment* as_joint_attach = dynamic_cast<LLViewerJointAttachment*>(joint);
|
||||
// if (as_joint_attach && as_joint_attach->getIsHUDAttachment())
|
||||
// {
|
||||
// // Ignore bounding box of HUD joints
|
||||
// continue;
|
||||
// }
|
||||
// gGL.pushMatrix();
|
||||
// gGL.multMatrix(&joint->getXform()->getWorldMatrix().mMatrix[0][0]);
|
||||
|
||||
// LLVector4a pos;
|
||||
// LLVector4a size;
|
||||
|
||||
// const LLVector4a* extents = rig_info->getRiggedExtents();
|
||||
|
||||
// pos.setAdd(extents[0], extents[1]);
|
||||
// pos.mul(0.5f);
|
||||
// size.setSub(extents[1], extents[0]);
|
||||
// size.mul(0.5f);
|
||||
|
||||
// drawBoxOutline(pos, size);
|
||||
|
||||
// gGL.popMatrix();
|
||||
// }
|
||||
// }
|
||||
|
||||
// draw world space attachment rigged bounding boxes in cyan
|
||||
// gGL.color3f(0.f, 1.f, 1.f);
|
||||
// for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
|
||||
// iter != mAttachmentPoints.end();
|
||||
// ++iter)
|
||||
// {
|
||||
// LLViewerJointAttachment* attachment = iter->second;
|
||||
|
||||
// if (attachment->getValid())
|
||||
// {
|
||||
// for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
// attachment_iter != attachment->mAttachedObjects.end();
|
||||
// ++attachment_iter)
|
||||
// {
|
||||
// LLViewerObject* attached_object = attachment_iter->get();
|
||||
// if (attached_object && !attached_object->isHUDAttachment())
|
||||
// {
|
||||
// LLDrawable* drawable = attached_object->mDrawable;
|
||||
// if (drawable && drawable->isState(LLDrawable::RIGGED | LLDrawable::RIGGED_CHILD))
|
||||
// {
|
||||
// // get face rigged extents
|
||||
// for (S32 i = 0; i < drawable->getNumFaces(); ++i)
|
||||
// {
|
||||
// LLFace* facep = drawable->getFace(i);
|
||||
// if (facep && facep->isState(LLFace::RIGGED))
|
||||
// {
|
||||
// LLVector4a center, size;
|
||||
|
||||
// LLVector4a* extents = facep->mRiggedExtents;
|
||||
|
||||
// center.setAdd(extents[0], extents[1]);
|
||||
// center.mul(0.5f);
|
||||
// size.setSub(extents[1], extents[0]);
|
||||
// size.mul(0.5f);
|
||||
// drawBoxOutline(center, size);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
void LLVOAvatar::renderBoxAroundJointAttachments(LLJoint * joint)
|
||||
{
|
||||
LLJointRiggingInfo* rig_info = NULL;
|
||||
|
||||
if (joint->getJointNum() < mJointRiggingInfoTab.size())
|
||||
{
|
||||
rig_info = &mJointRiggingInfoTab[joint->getJointNum()];
|
||||
}
|
||||
|
||||
if (joint && rig_info && rig_info->isRiggedTo())
|
||||
{
|
||||
LLViewerJointAttachment* as_joint_attach = dynamic_cast<LLViewerJointAttachment*>(joint);
|
||||
gGL.pushMatrix();
|
||||
gGL.multMatrix(&joint->getXform()->getWorldMatrix().mMatrix[0][0]);
|
||||
|
||||
LLVector4a pos;
|
||||
LLVector4a size;
|
||||
|
||||
const LLVector4a* extents = rig_info->getRiggedExtents();
|
||||
|
||||
pos.setAdd(extents[0], extents[1]);
|
||||
pos.mul(0.5f);
|
||||
size.setSub(extents[1], extents[0]);
|
||||
size.mul(0.5f);
|
||||
|
||||
drawBoxOutline(pos, size);
|
||||
|
||||
gGL.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLVOAvatar::renderJoints()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -568,6 +568,9 @@ public:
|
|||
U32 renderTransparent(bool first_pass);
|
||||
void renderCollisionVolumes();
|
||||
void renderBones(const std::string &selected_joint = std::string());
|
||||
void renderOnlySelectedBones(const std::vector<std::string> &selected_joints);
|
||||
void renderBoxAroundJointAttachments(LLJoint * joint);
|
||||
|
||||
void renderJoints();
|
||||
static void deleteCachedImages(bool clearAll=true);
|
||||
static void destroyGL();
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
|
|
@ -593,6 +593,11 @@ with the same filename but different name
|
|||
<texture name="Pathfinding_Dirty_Light" file_name="icons/Pathfinding_Dirty_Light.png" preload="false" />
|
||||
<texture name="Pathfinding_Disabled_Light" file_name="icons/Pathfinding_Disabled_Light.png" preload="false" />
|
||||
|
||||
<!-- FS:Beq: Poser icons -->
|
||||
<texture name="Poser_Visual_On" file_name="icons/visual_pose_enabled.png" />
|
||||
<texture name="Poser_Visual_Off" file_name="icons/visual_pose_disabled.png" />
|
||||
|
||||
|
||||
<!-- FS:Ansariel: Icon for script errors in V1 status bar -->
|
||||
<texture name="Statusbar_Script_Error" file_name="icons/status_script_debug.tga" preload="false" />
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue