Merge branch 'master' into FIRE-35081

master
minerjr 2025-03-17 23:22:17 -03:00
commit ddca8a3d62
53 changed files with 3876 additions and 2058 deletions

View File

@ -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

View File

@ -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>

View File

@ -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);
}
@ -324,9 +348,9 @@ void FSFloaterPoser::onPoseFileSelect()
bool isDeltaSave = !poseFileStartsFromTeePose(name);
if (isDeltaSave)
mLoadPosesBtn->setLabel("Load Diff");
mLoadPosesBtn->setLabel(getString("LoadDiffLabel"));
else
mLoadPosesBtn->setLabel("Load Pose");
mLoadPosesBtn->setLabel(getString("LoadPoseLabel"));
}
void FSFloaterPoser::onClickPoseSave()
@ -382,7 +406,7 @@ void FSFloaterPoser::createUserPoseDirectoryIfNeeded()
return;
auto posesToCopy = gDirUtilp->getFilesInDir(sourcePresetPath);
for (auto pose : posesToCopy)
for (const auto& pose : posesToCopy)
{
std::string source = sourcePresetPath + gDirUtilp->getDirDelimiter() + pose;
std::string destination = userHandPresetsPath + gDirUtilp->getDirDelimiter() + pose;
@ -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);

View File

@ -1,5 +1,5 @@
/**
* @file fsfloaterposer.cpp
* @file fsfloaterposer.h
* @brief View Model for posing your (and other) avatar(s).
*
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
@ -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 };

View File

@ -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();
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -0,0 +1,144 @@
/**
* @file fsmaniproatejoint.h
* @brief custom manipulator for rotating joints
*
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (c) 2025 Beq Janus @ Second Life
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
* http://www.firestormviewer.org
* $/LicenseInfo$
*/
#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();
// 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 manipulators 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 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

View File

@ -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)

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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 );

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);

View File

@ -129,6 +129,7 @@ extern LLToolset *gCameraToolset;
//extern LLToolset *gLandToolset;
extern LLToolset* gMouselookToolset;
extern LLToolset* gFaceEditToolset;
extern LLToolset* gPoserToolset;
extern LLTool* gToolNull;

View File

@ -475,7 +475,7 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
if (gResizeShadowTexture)
{ //skip render on frames where window has been resized
gPipeline.resizeShadowTexture();
gResizeShadowTexture = false;
// gResizeShadowTexture = false; // <FS:Beq/> This prevents the deferred resize from working properly.
}
gSnapshot = for_snapshot;

View File

@ -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)

View File

@ -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()
{

View File

@ -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();

View File

@ -789,6 +789,12 @@ void LLPipeline::requestResizeShadowTexture()
void LLPipeline::resizeShadowTexture()
{
// <FS:Beq> [FIRE-33200] changing shadowres requires reload - original fix by William Weaver (paperwork)
if(mRT->width == 0 || mRT->height == 0)
{
return;
}
// </FS:Beq>
releaseSunShadowTargets();
releaseSpotShadowTargets();
allocateShadowBuffer(mRT->width, mRT->height);
@ -2302,9 +2308,9 @@ F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size,
//shrink dist by dist/16.
if (dist < 16.f)
{
dist /= 16.f;
dist *= dist;
dist *= 16.f;
dist /= 16.f;
dist *= dist;
dist *= 16.f;
}
//get area of circle around node
@ -8082,7 +8088,7 @@ bool LLPipeline::renderSnapshotFrame(LLRenderTarget* src, LLRenderTarget* dst)
{
float frame_width = w;
float frame_height = frame_width / snapshot_aspect;
// Centre this box in [0..1]<EFBFBD>[0..1]
// Centre this box in [0..1]x[0..1]
float y_offset = 0.5f * (h - frame_height);
left = 0.f;
top = y_offset / h;
@ -8093,7 +8099,7 @@ bool LLPipeline::renderSnapshotFrame(LLRenderTarget* src, LLRenderTarget* dst)
{
float frame_height = h;
float frame_width = h * snapshot_aspect;
// Centre this box in [0..1]<EFBFBD>[0..1]
// Centre this box in [0..1]x[0..1]
float x_offset = 0.5f * (w - frame_width);
left = x_offset / w;
top = 0.f;
@ -8796,14 +8802,20 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale);
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, (GLfloat)RenderSSAOMaxScale);
// <FS:WW> Compute scale factor to match AO appearance between view and snapshot.
F32 screen_to_target_scale_factor = (F32)gViewerWindow->getWindowHeightRaw() / deferred_target->getHeight();
//shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale);
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale / screen_to_target_scale_factor);
//shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, (GLfloat)RenderSSAOMaxScale);
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale / screen_to_target_scale_factor);
// </FS:WW>
F32 ssao_factor = RenderSSAOFactor;
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor);
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0f/ssao_factor);
LLVector3 ssao_effect = RenderSSAOEffect;
F32 matrix_diag = (ssao_effect[0] + 2.0f*ssao_effect[1])/3.0f;
F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0f;
// This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -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" />

View File

@ -72,8 +72,7 @@
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
Səma [INDEX]
[ALTITUDE]m
Səma [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt1">
Naməlum
@ -82,8 +81,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
Səma [INDEX]
[ALTITUDE]m
Səma [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt2">
Naməlum
@ -92,8 +90,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
Səma [INDEX]
[ALTITUDE]m
Səma [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt3">
Naməlum

View File

@ -1,153 +1,151 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="floater_poser" title="Poser für Avatar und Animesh">
<!-- A matching bone name with the 'header_' prefix produces a sub-heading with the supplied name -->
<string name="header_mHead">Körper</string>
<string name="header_mFaceForeheadLeft">Stirn/Augenbrauen</string>
<string name="header_mEyeLeft">Augen/Augenlider</string>
<string name="header_mFaceCheekUpperLeft">Wangen/Lippen</string>
<string name="header_mHandThumb1Left">Linke Hand</string>
<string name="header_mCollarLeft">Linker Arm</string>
<string name="header_mHandThumb1Right">Rechte Hand</string>
<string name="header_mCollarRight">Rechter Arm</string>
<string name="header_mHipLeft">Beine</string>
<string name="header_mTail1">Schwanz</string>
<string name="header_mHindLimbsRoot">Hintere Glieder</string>
<string name="header_mWingsRoot">Flügel</string>
<string name="header_mFaceEar1Left">Ohren/Nase</string>
<string name="header_mHead">Körper</string>
<string name="header_mFaceForeheadLeft">Stirn/Augenbrauen</string>
<string name="header_mEyeLeft">Augen/Augenlider</string>
<string name="header_mFaceCheekUpperLeft">Wangen/Lippen</string>
<string name="header_mHandThumb1Left">Linke Hand</string>
<string name="header_mCollarLeft">Linker Arm</string>
<string name="header_mHandThumb1Right">Rechte Hand</string>
<string name="header_mCollarRight">Rechter Arm</string>
<string name="header_mHipLeft">Beine</string>
<string name="header_mTail1">Schwanz</string>
<string name="header_mHindLimbsRoot">Hintere Glieder</string>
<string name="header_mWingsRoot">Flügel</string>
<string name="header_mFaceEar1Left">Ohren/Nase</string>
<!-- These are names to appear on the UI for the joints/bones/thingos -->
<string name="title_mPelvis">Ganzer Avatar</string>
<string name="title_mTorso">Oberkörper</string>
<string name="title_mChest">Brust</string>
<string name="title_mNeck">Hals</string>
<string name="title_mHead">Kopf</string>
<string name="title_mEyeRight">Rechtes Auge</string>
<string name="title_mEyeLeft">Linkes Auge</string>
<string name="title_mFaceForeheadLeft">Linker Stirnwinkel</string>
<string name="title_mFaceForeheadRight">Rechter Stirnwinkel</string>
<string name="title_mFaceEyebrowOuterLeft">Äuß. linke Augenbraue</string>
<string name="title_mFaceEyebrowCenterLeft">Mit. linke Augenbraue</string>
<string name="title_mFaceEyebrowInnerLeft">In. linke Augenbraue</string>
<string name="title_mFaceEyebrowOuterRight">Äuß. rechte Augenbraue</string>
<string name="title_mFaceEyebrowCenterRight">Mit. rechte Augenbraue</string>
<string name="title_mFaceEyebrowInnerRight">In. rechte Augenbraue</string>
<string name="title_mFaceEyeLidUpperLeft">Linkes oberes Augenlid</string>
<string name="title_mFaceEyeLidLowerLeft">Linkes unteres Augenlid</string>
<string name="title_mFaceEyeLidUpperRight">Rechtes oberes Augenlid</string>
<string name="title_mFaceEyeLidLowerRight">Rechtes unteres Augenlid</string>
<string name="title_mFaceEar1Left">Linkes oberes Ohr</string>
<string name="title_mFaceEar2Left">Linkes unteres Ohr</string>
<string name="title_mFaceEar1Right">Rechtes oberes Ohr</string>
<string name="title_mFaceEar2Right">Rechtes unteres Ohr</string>
<string name="title_mFaceNoseLeft">Nase links</string>
<string name="title_mFaceNoseCenter">Nase Mitte</string>
<string name="title_mFaceNoseRight">Nase rechts</string>
<string name="title_mFaceCheekLowerLeft">Linke obere Wange</string>
<string name="title_mFaceCheekUpperLeft">Linke untere Wange</string>
<string name="title_mFaceCheekLowerRight">Rechte oberes Wange</string>
<string name="title_mFaceCheekUpperRight">Rechte untere Wange</string>
<string name="title_mFaceJaw">Kiefer</string>
<string name="title_mFaceTeethLower">Zähne unten</string>
<string name="title_mFaceLipLowerLeft">Linke untere Lippe</string>
<string name="title_mFaceLipLowerRight">Rechte untere Lippe</string>
<string name="title_mFaceLipLowerCenter">Mittlere untere Lippe</string>
<string name="title_mFaceTongueBase">Zunge Basis</string>
<string name="title_mFaceTongueTip">Zungenspite</string>
<string name="title_mFaceJawShaper">Kieferform</string>
<string name="title_mFaceForeheadCenter">Stirn Mitte</string>
<string name="title_mFaceNoseBase">Nase Basis</string>
<string name="title_mFaceTeethUpper">Obere Zähne</string>
<string name="title_mFaceLipUpperLeft">Linke obere Lippe</string>
<string name="title_mFaceLipUpperRight">Rechte obere Lippe</string>
<string name="title_mFaceLipCornerLeft">Linker Mundwinkel</string>
<string name="title_mFaceLipCornerRight">Rechter Mundwinkel</string>
<string name="title_mFaceLipUpperCenter">Mittlere obere Lippe</string>
<string name="title_mFaceEyecornerInnerLeft">In. linker Augenwinkel</string>
<string name="title_mFaceEyecornerInnerRight">In. rechter Augenwinkel</string>
<string name="title_mFaceNoseBridge">Nasenbrücke</string>
<string name="title_mCollarLeft">Kragen</string>
<string name="title_mShoulderLeft">Ganzer Arm</string>
<string name="title_mElbowLeft">Unterarm</string>
<string name="title_mWristLeft">Handgelenk</string>
<string name="title_mHandMiddle1Left">Basis Mittelfinger</string>
<string name="title_mHandMiddle2Left">Mitte Mittelfinger</string>
<string name="title_mHandMiddle3Left">Spitze Mittelfinger</string>
<string name="title_mHandIndex1Left">Basis Zeigefinger</string>
<string name="title_mHandIndex2Left">Mitte Zeigefinger</string>
<string name="title_mHandIndex3Left">Spitze Zeigefinger</string>
<string name="title_mHandRing1Left">Basis Ringfinger</string>
<string name="title_mHandRing2Left">Mitte Ringfinger</string>
<string name="title_mHandRing3Left">Spitze Ringfinger</string>
<string name="title_mHandPinky1Left">Basis kleiner Finger</string>
<string name="title_mHandPinky2Left">Mitte kleiner Finger</string>
<string name="title_mHandPinky3Left">Spitze kleiner Finger</string>
<string name="title_mHandThumb1Left">Basis Daumen</string>
<string name="title_mHandThumb2Left">Mitte Daumen</string>
<string name="title_mHandThumb3Left">Spitze Daumen</string>
<string name="title_mCollarRight">Kragen</string>
<string name="title_mShoulderRight">Ganzer Arm</string>
<string name="title_mElbowRight">Unterarm</string>
<string name="title_mWristRight">Handgelenk</string>
<string name="title_mHandMiddle1Right">Basis Mittelfinger</string>
<string name="title_mHandMiddle2Right">Mitte Mittelfinger</string>
<string name="title_mHandMiddle3Right">Spitze Mittelfinger</string>
<string name="title_mHandIndex1Right">Basis Zeigefinger</string>
<string name="title_mHandIndex2Right">Mitte Zeigefinger</string>
<string name="title_mHandIndex3Right">Spitze Zeigefinger</string>
<string name="title_mHandRing1Right">Basis Ringfinger</string>
<string name="title_mHandRing2Right">Mitte Ringfinger</string>
<string name="title_mHandRing3Right">Spitze Ringfinger</string>
<string name="title_mHandPinky1Right">Basis kleiner Finger</string>
<string name="title_mHandPinky2Right">Mitte kleiner Finger</string>
<string name="title_mHandPinky3Right">Spitze kleiner Finger</string>
<string name="title_mHandThumb1Right">Basis Daumen</string>
<string name="title_mHandThumb2Right">Mitte Daumen</string>
<string name="title_mHandThumb3Right">Spitze Daumen</string>
<string name="title_mWingsRoot">Wurzel</string>
<string name="title_mWing1Left">Links 1</string>
<string name="title_mWing2Left">Links 2</string>
<string name="title_mWing3Left">Links 3</string>
<string name="title_mWing4Left">Links 4</string>
<string name="title_mWing4FanLeft">Linker Fächer</string>
<string name="title_mWing1Right">Rechts 1</string>
<string name="title_mWing2Right">Rechts 2</string>
<string name="title_mWing3Right">Rechts 3</string>
<string name="title_mWing4Right">Rechts 4</string>
<string name="title_mWing4FanRight">Rechter Fächer</string>
<string name="title_mHipRight">Rechtes Bein</string>
<string name="title_mKneeRight">Rechtes Knie</string>
<string name="title_mAnkleRight">Rechter Knöchel</string>
<string name="title_mFootRight">Rechter Fuß</string>
<string name="title_mToeRight">Rechter Zeh</string>
<string name="title_mHipLeft">Linkes Bein</string>
<string name="title_mKneeLeft">Linkes Knie</string>
<string name="title_mAnkleLeft">Linker Knöchel</string>
<string name="title_mFootLeft">Linker Fuß</string>
<string name="title_mToeLeft">Linker Zeh</string>
<string name="title_mTail1">Basis Schwanz</string>
<string name="title_mTail2">Schwanz 2</string>
<string name="title_mTail3">Schwanz 3</string>
<string name="title_mTail4">Schwanz 4</string>
<string name="title_mTail5">Schwanz 5</string>
<string name="title_mTail6">Schwanz-Spitze</string>
<string name="title_mGroin">Leiste</string>
<string name="title_mHindLimbsRoot">Wurzel</string>
<string name="title_mHindLimb1Left">Linke Basis</string>
<string name="title_mHindLimb2Left">Links 2</string>
<string name="title_mHindLimb3Left">Links 3</string>
<string name="title_mHindLimb4Left">Links 4</string>
<string name="title_mHindLimb1Right">Rechte Basis</string>
<string name="title_mHindLimb2Right">Rechts 2</string>
<string name="title_mHindLimb3Right">Rechts 3</string>
<string name="title_mHindLimb4Right">Rechts 4</string>
<string name="title_BUTT">Hintern</string>
<string name="title_BELLY">Bauch</string>
<string name="title_LEFT_PEC">Linke Brustmuskeln</string>
<string name="title_RIGHT_PEC">Rechte Brustmuskeln</string>
<string name="title_mFaceEar1Left">Linke Basis</string>
<string name="title_mFaceEar1Right">Rechte Basis</string>
<string name="title_mFaceEar2Left">Linke Spitze</string>
<string name="title_mFaceEar2Right">Rechte Spitze</string>
<string name="title_mPelvis">Ganzer Avatar</string>
<string name="title_mTorso">Oberkörper</string>
<string name="title_mChest">Brust</string>
<string name="title_mNeck">Hals</string>
<string name="title_mHead">Kopf</string>
<string name="title_mEyeRight">Rechtes Auge</string>
<string name="title_mEyeLeft">Linkes Auge</string>
<string name="title_mFaceForeheadLeft">Linker Stirnwinkel</string>
<string name="title_mFaceForeheadRight">Rechter Stirnwinkel</string>
<string name="title_mFaceEyebrowOuterLeft">Äuß. linke Augenbraue</string>
<string name="title_mFaceEyebrowCenterLeft">Mit. linke Augenbraue</string>
<string name="title_mFaceEyebrowInnerLeft">In. linke Augenbraue</string>
<string name="title_mFaceEyebrowOuterRight">Äuß. rechte Augenbraue</string>
<string name="title_mFaceEyebrowCenterRight">Mit. rechte Augenbraue</string>
<string name="title_mFaceEyebrowInnerRight">In. rechte Augenbraue</string>
<string name="title_mFaceEyeLidUpperLeft">Linkes oberes Augenlid</string>
<string name="title_mFaceEyeLidLowerLeft">Linkes unteres Augenlid</string>
<string name="title_mFaceEyeLidUpperRight">Rechtes oberes Augenlid</string>
<string name="title_mFaceEyeLidLowerRight">Rechtes unteres Augenlid</string>
<string name="title_mFaceEar1Left">Linkes oberes Ohr</string>
<string name="title_mFaceEar2Left">Linkes unteres Ohr</string>
<string name="title_mFaceEar1Right">Rechtes oberes Ohr</string>
<string name="title_mFaceEar2Right">Rechtes unteres Ohr</string>
<string name="title_mFaceNoseLeft">Nase links</string>
<string name="title_mFaceNoseCenter">Nase Mitte</string>
<string name="title_mFaceNoseRight">Nase rechts</string>
<string name="title_mFaceCheekLowerLeft">Linke obere Wange</string>
<string name="title_mFaceCheekUpperLeft">Linke untere Wange</string>
<string name="title_mFaceCheekLowerRight">Rechte oberes Wange</string>
<string name="title_mFaceCheekUpperRight">Rechte untere Wange</string>
<string name="title_mFaceJaw">Kiefer</string>
<string name="title_mFaceTeethLower">Zähne unten</string>
<string name="title_mFaceLipLowerLeft">Linke untere Lippe</string>
<string name="title_mFaceLipLowerRight">Rechte untere Lippe</string>
<string name="title_mFaceLipLowerCenter">Mittlere untere Lippe</string>
<string name="title_mFaceTongueBase">Zunge Basis</string>
<string name="title_mFaceTongueTip">Zungenspite</string>
<string name="title_mFaceJawShaper">Kieferform</string>
<string name="title_mFaceForeheadCenter">Stirn Mitte</string>
<string name="title_mFaceNoseBase">Nase Basis</string>
<string name="title_mFaceTeethUpper">Obere Zähne</string>
<string name="title_mFaceLipUpperLeft">Linke obere Lippe</string>
<string name="title_mFaceLipUpperRight">Rechte obere Lippe</string>
<string name="title_mFaceLipCornerLeft">Linker Mundwinkel</string>
<string name="title_mFaceLipCornerRight">Rechter Mundwinkel</string>
<string name="title_mFaceLipUpperCenter">Mittlere obere Lippe</string>
<string name="title_mFaceEyecornerInnerLeft">In. linker Augenwinkel</string>
<string name="title_mFaceEyecornerInnerRight">In. rechter Augenwinkel</string>
<string name="title_mFaceNoseBridge">Nasenbrücke</string>
<string name="title_mCollarLeft">Kragen</string>
<string name="title_mShoulderLeft">Ganzer Arm</string>
<string name="title_mElbowLeft">Unterarm</string>
<string name="title_mWristLeft">Handgelenk</string>
<string name="title_mHandMiddle1Left">Basis Mittelfinger</string>
<string name="title_mHandMiddle2Left">Mitte Mittelfinger</string>
<string name="title_mHandMiddle3Left">Spitze Mittelfinger</string>
<string name="title_mHandIndex1Left">Basis Zeigefinger</string>
<string name="title_mHandIndex2Left">Mitte Zeigefinger</string>
<string name="title_mHandIndex3Left">Spitze Zeigefinger</string>
<string name="title_mHandRing1Left">Basis Ringfinger</string>
<string name="title_mHandRing2Left">Mitte Ringfinger</string>
<string name="title_mHandRing3Left">Spitze Ringfinger</string>
<string name="title_mHandPinky1Left">Basis kleiner Finger</string>
<string name="title_mHandPinky2Left">Mitte kleiner Finger</string>
<string name="title_mHandPinky3Left">Spitze kleiner Finger</string>
<string name="title_mHandThumb1Left">Basis Daumen</string>
<string name="title_mHandThumb2Left">Mitte Daumen</string>
<string name="title_mHandThumb3Left">Spitze Daumen</string>
<string name="title_mCollarRight">Kragen</string>
<string name="title_mShoulderRight">Ganzer Arm</string>
<string name="title_mElbowRight">Unterarm</string>
<string name="title_mWristRight">Handgelenk</string>
<string name="title_mHandMiddle1Right">Basis Mittelfinger</string>
<string name="title_mHandMiddle2Right">Mitte Mittelfinger</string>
<string name="title_mHandMiddle3Right">Spitze Mittelfinger</string>
<string name="title_mHandIndex1Right">Basis Zeigefinger</string>
<string name="title_mHandIndex2Right">Mitte Zeigefinger</string>
<string name="title_mHandIndex3Right">Spitze Zeigefinger</string>
<string name="title_mHandRing1Right">Basis Ringfinger</string>
<string name="title_mHandRing2Right">Mitte Ringfinger</string>
<string name="title_mHandRing3Right">Spitze Ringfinger</string>
<string name="title_mHandPinky1Right">Basis kleiner Finger</string>
<string name="title_mHandPinky2Right">Mitte kleiner Finger</string>
<string name="title_mHandPinky3Right">Spitze kleiner Finger</string>
<string name="title_mHandThumb1Right">Basis Daumen</string>
<string name="title_mHandThumb2Right">Mitte Daumen</string>
<string name="title_mHandThumb3Right">Spitze Daumen</string>
<string name="title_mWingsRoot">Wurzel</string>
<string name="title_mWing1Left">Links 1</string>
<string name="title_mWing2Left">Links 2</string>
<string name="title_mWing3Left">Links 3</string>
<string name="title_mWing4Left">Links 4</string>
<string name="title_mWing4FanLeft">Linker Fächer</string>
<string name="title_mWing1Right">Rechts 1</string>
<string name="title_mWing2Right">Rechts 2</string>
<string name="title_mWing3Right">Rechts 3</string>
<string name="title_mWing4Right">Rechts 4</string>
<string name="title_mWing4FanRight">Rechter Fächer</string>
<string name="title_mHipRight">Rechtes Bein</string>
<string name="title_mKneeRight">Rechtes Knie</string>
<string name="title_mAnkleRight">Rechter Knöchel</string>
<string name="title_mFootRight">Rechter Fuß</string>
<string name="title_mToeRight">Rechter Zeh</string>
<string name="title_mHipLeft">Linkes Bein</string>
<string name="title_mKneeLeft">Linkes Knie</string>
<string name="title_mAnkleLeft">Linker Knöchel</string>
<string name="title_mFootLeft">Linker Fuß</string>
<string name="title_mToeLeft">Linker Zeh</string>
<string name="title_mTail1">Basis Schwanz</string>
<string name="title_mTail2">Schwanz 2</string>
<string name="title_mTail3">Schwanz 3</string>
<string name="title_mTail4">Schwanz 4</string>
<string name="title_mTail5">Schwanz 5</string>
<string name="title_mTail6">Schwanz-Spitze</string>
<string name="title_mGroin">Leiste</string>
<string name="title_mHindLimbsRoot">Wurzel</string>
<string name="title_mHindLimb1Left">Linke Basis</string>
<string name="title_mHindLimb2Left">Links 2</string>
<string name="title_mHindLimb3Left">Links 3</string>
<string name="title_mHindLimb4Left">Links 4</string>
<string name="title_mHindLimb1Right">Rechte Basis</string>
<string name="title_mHindLimb2Right">Rechts 2</string>
<string name="title_mHindLimb3Right">Rechts 3</string>
<string name="title_mHindLimb4Right">Rechts 4</string>
<string name="title_BUTT">Hintern</string>
<string name="title_BELLY">Bauch</string>
<string name="title_LEFT_PEC">Linke Brustmuskeln</string>
<string name="title_RIGHT_PEC">Rechte Brustmuskeln</string>
<string name="LoadPoseLabel">Pose laden</string>
<string name="LoadDiffLabel">Diff. laden</string>
<!-- The layout is a vertical stack of 3 rows, and each row a horizontal stack of panels -->
<layout_stack name="poser_stack">
@ -221,34 +219,59 @@
Steuerkugel-Sensitivität:
</text>
<slider name="trackpad_sensitivity_slider" tool_tip="Stellt die Sensitivität der Steuerkugel ein"/>
<check_box name="natural_direction_checkbox" label="Natürl. Ausrichtung verw." tool_tip="Das Skelett besitzt standardmäßig unnatürliche Gelenk-Rotationen, was das Posieren erschwert. Falls aktiviert, werden die Gelenke in eine natürlichere Rotation versetzt."/>
<check_box name="stop_posing_on_close_checkbox" label="Beim Schließen stoppen" tool_tip="Die Pose beim Schließen nicht zu stoppen kann hilfreich sein, um die bisher getätigte Arbeit nicht zu verlieren."/>
<check_box name="reset_base_rotation_on_edit_checkbox" label="Basis-Rot. beim Edit. zurück." tool_tip="Wenn das erste Mal eine Pose bearbeitet wird, diese auf Null zurücksetzen. Hierdurch eine eine komplette Pose und nicht nur die Differenz gespeichert werden. Ein grüner Haken erscheint neben jedem Gelenk, dass auf Null-basierend exportiert wurde."/>
<check_box name="also_save_bvh_checkbox" label="BHV beim Speichern erst." tool_tip="Wenn die Pose gespeichert wird, wird ebenfalls eine BHV-Datei erstellt, die via Bauen > Hochladen > Animation hochgeladen und zum Posieren vom eigenen Avatar oder anderen Avataren verwendet werden kann. Hierzu muss die Basis der Gelenke auf Null gesetzt werden, da BHV nicht von anderen Posen abgeleitet wird."/>
</panel>
</tab_container>
<button name="toggleVisualManipulators" tool_tip="Visuelle Manipulatoren an-/ausschalten" />
</panel>
<panel name="trackball_panel">
<text name="rotation_label">
Rotation:
</text>
<fs_virtual_trackpad name="limb_rotation" tool_tip="Ändert die Rotation der aktuell ausgewählten Körperteile. STRG gedrückt halten, um langsam zu ändern. Mausrad drehen, um 3. Achse zu justieren. Umschalten oder Alt benutzen, um zwischen Rotationsachsen zu wechseln."/>
<panel name="joint_manipulation_panel">
<tab_container name="modifier_tabs">
<panel label="Rotation" name="trackball_panel">
<fs_virtual_trackpad name="limb_rotation" tool_tip="Ändert die Rotation der aktuell ausgewählten Körperteile. STRG gedrückt halten, um langsam zu ändern. Mausrad drehen, um 3. Achse zu justieren. Umschalten oder Alt benutzen, um zwischen Rotationsachsen zu wechseln."/>
<text name="limb_pitch_label">
Auf/Ab:
</text>
<text name="limb_yaw_label">
Links/Re.:
</text>
<text name="limb_roll_label">
Rollen:
</text>
</panel>
<panel title="Pos. / Skal." name="position_panel">
<text name="pos_x_label">
Position X:
</text>
<text name="pos_y_label">
Position Y:
</text>
<text name="pos_z_label">
Position Z:
</text>
<text name="scale_x_label">
Skala X:
</text>
<text name="scale_y_label">
Skala Y:
</text>
<text name="scale_z_label">
Skala Z:
</text>
</panel>
</tab_container>
<panel name="trackball_button_panel">
<button name="undo_change" tool_tip="Letzte Rotationsänderung rückgängig machen"/>
<button name="undo_change" tool_tip="Letzte Änderung rückgängig machen"/>
<button name="button_redo_change" tool_tip="Letzte Rotationsänderung wiederherstellen"/>
<button name="poser_joint_reset" tool_tip="Doppelklicken, um alle ausgewählten Körperteile auf die Ursprungswerte zurückzusetzen."/>
<button name="delta_mode_toggle" tool_tip="Falls mehrere Gelenke geändert werden, diese um denselben Wert ändern anstatt in dieselbe Rotation zu versetzen. Wird auch zur Verhinderung von Gimbal Lock verwendet."/>
<button label="Spieg." name="button_toggleMirrorRotation" tool_tip="Änderungen an gegenüberliegendem Gelenk spiegeln."/>
<button label="Sym." name="button_toggleSympatheticRotation" tool_tip="Gegenüberliegendes Gelenk gleichermaßen anpassen."/>
<button label="Kopie L &gt; P" name="button_symmetrize_left_to_right" tool_tip="Doppelklicken, um Änderung von linker Seite zur rechten Seite zu kopieren." />
<button label="Kopie P &gt; L" name="button_symmetrize_right_to_left" tool_tip="Doppelklicken, um Änderung von rechter Seite zur linken Seite zu kopieren." />
</panel>
<text name="limb_pitch_label">
Hoch/Runter:
</text>
<text name="limb_yaw_label">
Links/Rechts:
</text>
<text name="limb_roll_label">
Rollen:
</text>
</panel>
<panel name="poses_loadSave">
<scroll_list tool_tip="Pose für ausgewählten Avatar laden." name="poses_scroll">
@ -259,7 +282,6 @@
</layout_panel>
<layout_panel name="button_controls_layout">
<panel name="button_controls_panel">
<button name="toggleAdvancedPanel" tool_tip="Erweiterte Einstellungen aktivieren/deaktivieren"/>
<button name="FlipPose_avatar" tool_tip="Komplette Pose links/rechts umschalten"/>
<button name="FlipJoint_avatar" tool_tip="Ausgewählte Körperteile links/rechts spiegeln"/>
<button label="Ausw." name="button_RecaptureParts" tool_tip="Falls ausgewählte Körperteile nicht posiert werden, werden die Werte der aktuellen Pose erfasst."/>
@ -270,27 +292,5 @@
<button label="Diff. speich." tool_tip="Speichert die Differenz zu einer bestehenden Pose. Aus einer T-Pose heraus starten, um ein neues Werk zu beginnen." name="save_poses_button"/>
</panel>
</layout_panel>
<layout_panel name="advanced_controls_layout">
<panel name="advanced_parent_panel">
<tab_container name="modifier_tabs">
<panel title="Körperteil-Position" name="position_panel">
<slider label="Position X:" name="Advanced_Position_X"/>
<slider label="Position Y:" name="Advanced_Position_Y"/>
<slider label="Position Z:" name="Advanced_Position_Z"/>
<button label="Positionsänd. zurücks." name="undo_position_change" tool_tip="Macht die letzte Positionsänderung rückgängig"/>
<button label="Pos. wiederh." name="redo_position_change" tool_tip="Stellt die letzte Positionsänderung wieder her"/>
<button label="Pos. zurücks." name="reset_positions" tool_tip="Doppelklicken, um Position auf Originalwert zurückzusetzen"/>
</panel>
<panel title="Körperteil-Skalierung" name="scale_panel">
<slider label="Skalierung X:" name="Advanced_Scale_X"/>
<slider label="Skalierung Y:" name="Advanced_Scale_Y"/>
<slider label="Skalierung Z:" name="Advanced_Scale_Z"/>
<button label="Skal.-Änd. zurücks." name="undo_scale_change" tool_tip="Macht die letzte Änderung der Skalierung rückgängig"/>
<button label="Skal. wiederh." name="redo_scale_change" tool_tip="Stellt die letzte Änderung der Skalierung wieder her"/>
<button label="Skal. zurücks." name="reset_scales" tool_tip="Doppelklicken, um Skalierung auf Originalwert zurückzusetzen"/>
</panel>
</tab_container>
</panel>
</layout_panel>
</layout_stack>
</floater>

View File

@ -80,8 +80,7 @@
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
Himmel [INDEX]
[ALTITUDE]m
Himmel [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt1">
Unbekannt
@ -90,8 +89,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
Himmel [INDEX]
[ALTITUDE]m
Himmel [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt2">
Unbekannt
@ -100,8 +98,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
Himmel [INDEX]
[ALTITUDE]m
Himmel [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt3">
Unbekannt

File diff suppressed because it is too large Load Diff

View File

@ -272,8 +272,7 @@
top_pad="1"
halign="right"
name="txt_alt1">
Sky [INDEX]
[ALTITUDE]m
Sky [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor
follows="left|top"
@ -318,8 +317,7 @@
top_pad="1"
halign="right"
name="txt_alt2">
Sky [INDEX]
[ALTITUDE]m
Sky [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor
follows="left|top"
@ -364,8 +362,7 @@
top_pad="1"
halign="right"
name="txt_alt3">
Sky [INDEX]
[ALTITUDE]m
Sky [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor
follows="left|top"

View File

@ -32,20 +32,17 @@
</layout_panel>
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">Cielo [INDEX]
[ALTITUDE]m</text>
<text name="txt_alt1">Cielo [INDEX]&#xA;[ALTITUDE]m</text>
<line_editor name="edt_invname_alt1">Desconocido</line_editor>
<settings_drop_target name="sdt_alt1" tool_tip="Mover un parámetro desde el Inventario hasta este recuadro para seleccionarlo como cielo actual."/>
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">Cielo [INDEX]
[ALTITUDE]m</text>
<text name="txt_alt2">Cielo [INDEX]&#xA;[ALTITUDE]m</text>
<line_editor name="edt_invname_alt2">Desconocido</line_editor>
<settings_drop_target name="sdt_alt2" tool_tip="Mover un parámetro desde el Inventario hasta este recuadro para seleccionarlo como cielo actual."/>
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">Cielo [INDEX]
[ALTITUDE]m</text>
<text name="txt_alt3">Cielo [INDEX]&#xA;[ALTITUDE]m</text>
<line_editor name="edt_invname_alt3">Desconocido</line_editor>
<settings_drop_target name="sdt_alt3" tool_tip="Mover un parámetro desde el Inventario hasta este recuadro para seleccionarlo como cielo actual."/>
</panel>

View File

@ -141,10 +141,6 @@
<string name="title_BELLY">Ventre</string>
<string name="title_LEFT_PEC">Sein gauche</string>
<string name="title_RIGHT_PEC">Sein droit</string>
<string name="title_mFaceEar1Left">Base gauche</string>
<string name="title_mFaceEar1Right">Base droite</string>
<string name="title_mFaceEar2Left">Pointe gauche</string>
<string name="title_mFaceEar2Right">Pointe droite</string>
<layout_stack name="poser_stack">
<layout_panel name="regular_controls_layout">
<panel name="joints_parent_panel">
@ -212,34 +208,59 @@
Sensibilité du trackpad :
</text>
<slider name="trackpad_sensitivity_slider" tool_tip="Règle la sensibilité du trackpad"/>
<check_box name="natural_direction_checkbox" label="Utiliser l'alignement naturel" tool_tip="Le squelette a des rotations d'articulations non naturelles par défaut. Cela complique la pose. Si cette option est cochée, les articulations tourneront de manière plus naturelle."/>
<check_box name="stop_posing_on_close_checkbox" label="Arrêt pose si fermeture" tool_tip="Ne pas arrêter votre pose peut être utile si vous travaillez beaucoup et que vous ne voulez pas la perdre accidentellement."/>
<check_box name="reset_base_rotation_on_edit_checkbox" label="Réinitialisation de la rotation" tool_tip="Lorsque vous modifiez une rotation pour la première fois, la remet à zéro. Cela signifie que votre travail peut enregistrer une pose (et non une différence - voir charger/enregistrer). Une coche verte apparaît à côté de chaque articulation dont l'exportation a été remise à zéro."/>
<check_box name="also_save_bvh_checkbox" label="Ajouter BVH en enregistrant**" tool_tip="Lorsque vous enregistrez votre pose, écrivez également un fichier BVH, qui peut être téléchargé via 'Construire > Charger > Animation' pour poser vous-même ou d'autres personnes dans le monde. Pour ce faire, les articulations doivent remettre leur « base » à zéro, car le BVH nécessite que l'on travaille sur l'original."/>
<check_box name="also_save_bvh_checkbox" label="Ajouter BVH à l'enregis.**" tool_tip="Lorsque vous enregistrez votre pose, écrivez également un fichier BVH, qui peut être téléchargé via 'Construire > Charger > Animation' pour poser vous-même ou d'autres personnes dans le monde. Pour ce faire, les articulations doivent remettre leur « base » à zéro, car le BVH nécessite que l'on travaille sur l'original."/>
</panel>
</tab_container>
<button name="toggleVisualManipulators" tool_tip="Activer et désactiver les manipulateurs visuels"/>
</panel>
<panel name="trackball_panel">
<text name="rotation_label">
Rotation :
</text>
<fs_virtual_trackpad name="limb_rotation" tool_tip="Modifie la rotation de la partie du corps sélectionnée. Maintenir la touche Ctrl enfoncée pour se déplacer lentement. Tournez la roue pour ajuster le troisième axe. Utilisez Shift ou Alt pour échanger les changements de rotation." />
<panel name="joint_manipulation_panel">
<tab_container name="modifier_tabs">
<panel label="Rotation" name="trackball_panel">
<fs_virtual_trackpad name="limb_rotation" tool_tip="Modifie la rotation de la ou des parties du corps actuellement sélectionnées. Maintenez la touche Ctrl enfoncée pour un déplacement lent. Faites rouler la roue pour ajuster le troisième axe. Utilisez Shift ou Alt pour permuter les rotations qui changent."/>
<text name="limb_pitch_label">
Haut/Bas :
</text>
<text name="limb_yaw_label">
Gche/drte :
</text>
<text name="limb_roll_label">
Roulement :
</text>
</panel>
<panel title="Dépl. / Éch." name="position_panel">
<text name="pos_x_label">
Position X :
</text>
<text name="pos_y_label">
Position Y :
</text>
<text name="pos_z_label">
Position Z :
</text>
<text name="scale_x_label">
Échelle X :
</text>
<text name="scale_y_label">
Échelle Y :
</text>
<text name="scale_z_label">
Échelle Z :
</text>
</panel>
</tab_container>
<panel name="trackball_button_panel">
<button name="undo_change" tool_tip="Annuler la dernière rotation" />
<button name="undo_change" tool_tip="Annuler la dernière modification" />
<button name="button_redo_change" tool_tip="Rétablir la dernière modification annulée" />
<button name="poser_joint_reset" tool_tip="Double-cliquez pour remettre toutes les parties du corps sélectionnées dans l'état où elles se trouvaient lorsque vous avez commencé à poser." />
<button name="delta_mode_toggle" tool_tip="Si vous modifiez plusieurs articulations, chacune d'entre elles sera modifiée de la même manière, au lieu de toutes les modifier du même coup. Sert également à déverrouiller le Gimbal Lock." />
<button label="Miroir" name="button_toggleMirrorRotation" tool_tip="Changer l'articulation opposée, comme dans un miroir." />
<button label="Sym." name="button_toggleSympatheticRotation" tool_tip="Modifier l'articulation opposée, mais de la même manière." />
<button label="Sym." name="button_toggleSympatheticRotation" tool_tip="Copier les modifications sur l'articulation opposée." />
<button label="Cop. G &gt; D" name="button_symmetrize_left_to_right" tool_tip="Double-cliquez pour copier la modification du côté gauche vers le côté droit."/>
<button label="Cop. D &gt; G" name="button_symmetrize_right_to_left" tool_tip="Double-cliquez pour copier la modification du côté droit vers le côté gauche."/>
</panel>
<text name="limb_pitch_label">
Haut/Bas :
</text>
<text name="limb_yaw_label">
Gauche/droite :
</text>
<text name="limb_roll_label">
Roulement :
</text>
</panel>
<panel name="poses_loadSave">
<scroll_list tool_tip="Charge une pose pour le personnage animé." name="poses_scroll">
@ -250,7 +271,6 @@
</layout_panel>
<layout_panel name="button_controls_layout">
<panel name="button_controls_panel">
<button name="toggleAdvancedPanel" tool_tip="Passer à la section des paramètres avancés"/>
<button name="FlipPose_avatar" tool_tip="Inverser toute la pose vers la gauche/droite" />
<button name="FlipJoint_avatar" tool_tip="Miroir des parties du corps sélectionnées gauche/droite" />
<button label="Capter" name="button_RecaptureParts" tool_tip="Si les parties du corps sélectionnées sont désactivées, cette option permet de capturer à nouveau ce que ces parties du corps font actuellement."/>
@ -261,27 +281,5 @@
<button label="Enr. diff." tool_tip="Un diff est simplement une modification apportée à une pose existante. Commencez à partir d'une pose T pour sauvegarder un nouveau travail." name="save_poses_button" />
</panel>
</layout_panel>
<layout_panel name="advanced_controls_layout">
<panel name="advanced_parent_panel">
<tab_container name="modifier_tabs">
<panel title="Pos. des parties du corps" name="position_panel">
<slider label="Point X :" name="Advanced_Position_X" />
<slider label="Point Y :" name="Advanced_Position_Y" />
<slider label="Point Z :" name="Advanced_Position_Z" />
<button label="Annuler pos." name="undo_position_change" tool_tip="Annuler le dernier changement de position" />
<button label="Repositionner" name="redo_position_change" tool_tip="Refaire le dernier changement de position" />
<button label="Réinit. position" name="reset_positions" tool_tip="Double-cliquez pour rétablir la position d'origine" />
</panel>
<panel title="Échelle des parties du corps" name="scale_panel">
<slider label="Échelle X :" name="Advanced_Scale_X" />
<slider label="Échelle Y :" name="Advanced_Scale_Y" />
<slider label="Échelle Z :" name="Advanced_Scale_Z" />
<button label="Annuler échelle" name="undo_scale_change" tool_tip="Annuler le dernier changement d'échelle" />
<button label="À l'échelle" name="redo_scale_change" tool_tip="Refaire le dernier changement d'échelle" />
<button label="Réinit. échelle" name="reset_scales" tool_tip="Double-cliquez pour rétablir l'échelle d'origine" />
</panel>
</tab_container>
</panel>
</layout_panel>
</layout_stack>
</floater>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="prefs_graphics_advanced" title="PRÉFÉRENCES GRAPHIQUES AVANCÉES">
<floater name="prefs_graphics_advanced" title="Préférences graphiques avancées">
<text name="GeneralText">
Général
</text>
@ -13,6 +13,10 @@
Faible
</text>
<slider label="Max. lumières proches :" name="MaxLights"/>
<text name="MaxTextureResolutionLabel">
Résolution maximale du LOD :
</text>
<combo_box name="MaxTextureResolution" tool_tip="Résolution maximale pour les textures « niveau de détail »."/>
<check_box label="Activer VSync" name="vsync" tool_tip="Synchronise la fréquence d'images avec la fréquence de rafraîchissement du moniteur, ce qui peut entraîner une augmentation du lag et des images saccadées."/>
<text name="AvatarText">
Avatar
@ -62,7 +66,7 @@
<combo_box.item label="SMAA" name="SMAA"/>
</combo_box>
<text name="antialiasing quality label">
Qualité de l'anti-crénelage :
Qualité anti-crénelage :
</text>
<combo_box label="Anti-crénelage" name="fsaa quality">
<combo_box.item label="Faible" name="Low"/>
@ -168,7 +172,7 @@
<combo_box.item label="Toutes les 3 images" name="2"/>
<combo_box.item label="Toutes les 4 images" name="3"/>
</combo_box>
<slider label="Sharpening :" name="RenderSharpness"/>
<slider label="Netteté :" name="RenderSharpness"/>
<text name="TonemapTypeText">
Mappage de tons :
</text>

View File

@ -29,6 +29,7 @@
<check_box label="Afficher le guide de cadrage" tool_tip="Affiche le guide de cadrage (règle des tiers) à l'intérieur du cadre de la photo." name="show_guides"/>
<check_box label="Figer l'écran (plein écran)" name="freeze_frame_check"/>
<check_box label="Actualisation automatique" name="auto_snapshot_check"/>
<check_box label="Pas de post-traitement" name="no_post_check"/>
<text name="filter_list_label">Filtre :</text>
<combo_box name="filters_combobox" tool_tip="Filtres pour l'image">
<combo_box.item label="Pas de filtre" name="NoFilter"/>

View File

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<menu_bar name="Login Menu">
<menu label="Viewer" name="File">
<menu label="Visionneuse" name="File">
<menu_item_call label="Préférences..." name="Preferences..."/>
<menu_item_call label="Quitter [APP_NAME]" name="Quit"/>
</menu>
<menu label="Aide" name="Help">
<menu_item_call label="Wiki Firestorm" name="Firestorm Wiki"/>
<menu_item_call label="Dépannage" name="Troubleshooting"/>
<menu_item_call label="Guide" name="How To"/>
<menu_item_call label="Signaler un problème" name="Report Bug"/>
<menu_item_call label="À propos de [APP_NAME]" name="About Second Life"/>
<menu_item_call label="Aide [CURRENT_GRID]" name="current_grid_help_login"/>
@ -15,6 +16,7 @@
<menu_item_check label="Afficher le menu débogage" name="Show Debug Menu"/>
<menu label="Débogage" name="Debug">
<menu_item_call label="Afficher les paramètres de débogage" name="Debug Settings"/>
<menu_item_call label="Afficher les paramètres de couleur" name="Color Settings"/>
<menu_item_call label="Outil de prévisualisation XUI" name="UI Preview Tool"/>
<menu label="Polices" name="Fonts">
<menu_item_call label="Afficher le test de police" name="Show Font Test"/>

View File

@ -287,7 +287,6 @@
<menu_item_call label="Wiki" name="Wiki"/>
<menu_item_call label="Forums communautaires" name="Community Forums"/>
<menu_item_call label="Portail d'assistance" name="Support portal"/>
<menu_item_call label="Nouvelles de [SECOND_LIFE]" name="Second Life News"/>
<menu_item_call label="Blogs de [SECOND_LIFE]" name="Second Life Blogs"/>-->
<menu_item_call name="whitelist_folders" label="Conseils de liste blanche"/>
<menu_item_check label="Consulter l'état de la grille" name="Grid Status"/>

View File

@ -155,10 +155,10 @@ Si vous ne comprenez pas la distinction, ne vous souciez pas de ce contrôle."/>
<check_box label="Limiter les images par secondes" name="FSLimitFramerate" tool_tip="Limite le taux de rafraîchissement à une valeur définie par l'utilisateur. Peut réduire la consommation d'énergie et la chaleur du GPU/CPU."/>
<check_box label="Limiter le taux de rafraîchissement à la fréquence du moniteur (VSync)" name="vsync" tool_tip="Synchronise la fréquence d'images avec la fréquence de rafraîchissement du moniteur, ce qui peut entraîner une augmentation du lag et des images saccadées."/>
<text name="Texture Rendering">Rendu des textures :</text>
<check_box width="270" label="Limiter le résolution maximale des textures à :" tool_tip="Activée, cette option limite la résomution maximale d'affichage des textures dans Second Life. Cela permet d'afficher plus de textures avant de dépasser la limite de mémoire disponible et évite de voir des textures floues." name="FSRestrictMaxTextureSize"/>
<text name="FSRestrictMaxTextureSizeRestartText">
(Redémarrage requis)
<text name="FSRestrictMaxTextureSize">
Limiter le résolution maximale des textures à :
</text>
<combo_box tool_tip="Définit la résolution maximale d'affichage des textures dans le monde. Cela permet d'afficher plus de textures avant de dépasser la mémoire de texture disponible et obtenir des textures floues." name="FSRestrictMaxTexturePixels"/>
<text name="TextureDetailLabel">
Qualité max. des textures :
</text>
@ -168,9 +168,9 @@ Si vous ne comprenez pas la distinction, ne vous souciez pas de ce contrôle."/>
<combo_box.item label="Basse" name="4"/>
<combo_box.item label="Pas de textures" name="5"/>
</combo_box>
<text name="Alpha Mask Rendering">Rendu des masques alphas :</text>
<check_box label="Activer les masques alpha" tool_tip="Si cette option est cochée, le rendu des masques Alpha (bits transparents) est correct." name="RenderAutoMaskAlphaDeferred"/>
<text name="Miscellaneous Rendering">Divers :</text>
<check_box label="HDR et émissivité" tool_tip="Permet des fonctionnalités supplémentaires du pipeline de rendu sur les machines plus récentes, telles que le HDR et les textures émissives sur le contenu PBR." name="VintageMode"/>
<check_box label="Activer les masques alpha" tool_tip="Si cette option est cochée, le rendu des masques Alpha (bits transparents) est correct." name="RenderAutoMaskAlphaDeferred"/>
<check_box label="Éclat lumineux" tool_tip="Activer l'éclat lumineux. Noter que la force doit être définie sur 0 pour désactiver l'éclat lumineux lorsque les ombres sont activées." name="RenderGlow"/>
<slider label="Force :" tool_tip="Force de l'éclat lumineux. Une valeur plus élevée le rends plus diffus et plus doux (2 par défaut)" name="glow_strength"/>
<check_box label="Afficher les avatars qui n'ont pas fini de charger" name="RenderUnloadedAvatars"/>

View File

@ -73,8 +73,7 @@
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
Ciel [INDEX]
[ALTITUDE]m
Ciel [INDEX]&#xA;[ALTITUDE] m
</text>
<line_editor name="edt_invname_alt1">
Inconnu
@ -83,8 +82,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
Ciel [INDEX]
[ALTITUDE]m
Ciel [INDEX]&#xA;[ALTITUDE] m
</text>
<line_editor name="edt_invname_alt2">
Inconnu
@ -93,8 +91,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
Ciel [INDEX]
[ALTITUDE]m
Ciel [INDEX]&#xA;[ALTITUDE] m
</text>
<line_editor name="edt_invname_alt3">
Inconnu

View File

@ -141,10 +141,6 @@
<string name="title_BELLY">Pancia</string>
<string name="title_LEFT_PEC">Pettorale sinistro</string>
<string name="title_RIGHT_PEC">Pettorale destro</string>
<string name="title_mFaceEar1Left">Orecchio sx: superiore</string> <!-- duplicate -->
<string name="title_mFaceEar1Right">Orecchio dx: superiore</string> <!-- duplicate -->
<string name="title_mFaceEar2Left">Orecchio sx: inferiore</string> <!-- duplicate -->
<string name="title_mFaceEar2Right">Orecchio dx: inferiore</string> <!-- duplicate -->
<layout_stack name="poser_stack">
<layout_panel name="regular_controls_layout">
<panel name="joints_parent_panel">

View File

@ -70,8 +70,7 @@
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
Cielo [INDEX]
[ALTITUDE]m
Cielo [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt1">
Sconosciuto
@ -80,8 +79,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
Cielo [INDEX]
[ALTITUDE]m
Cielo [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt2">
Sconosciuto
@ -90,8 +88,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
Cielo [INDEX]
[ALTITUDE]m
Cielo [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt3">
Sconosciuto

View File

@ -71,8 +71,7 @@
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
空 [INDEX]
[ALTITUDE]m
空 [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt1">
不明
@ -81,8 +80,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
空 [INDEX]
[ALTITUDE]m
空 [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt2">
不明
@ -91,8 +89,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
空 [INDEX]
[ALTITUDE]m
空 [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt3">
不明

View File

@ -141,10 +141,8 @@
<string name="title_BELLY">Brzuch</string>
<string name="title_LEFT_PEC">Lewa pierś</string>
<string name="title_RIGHT_PEC">Prawa pierś</string>
<string name="title_mFaceEar1Left">Lewa podstawa</string>
<string name="title_mFaceEar1Right">Prawa podstawa</string>
<string name="title_mFaceEar2Left">Lewy czubek</string>
<string name="title_mFaceEar2Right">Prawy czubek</string>
<string name="LoadPoseLabel">Ładuj pozę</string>
<string name="LoadDiffLabel">Ładuj różn.</string>
<layout_stack name="poser_stack">
<layout_panel name="regular_controls_layout">
<panel name="joints_parent_panel">
@ -213,34 +211,59 @@
<panel title="Inne" name="settings_panel">
<text name="trackpad_sensitivity_label">Czułość trackpada:</text>
<slider name="trackpad_sensitivity_slider" tool_tip="Dostosowuje czułość trackballa / kółka" />
<check_box name="natural_direction_checkbox" label="Naturalne wyrównanie" tool_tip="Szkielet ma domyślnie nienaturalne rotacje stawów. To utrudnia pozowanie. Po zaznaczeniu stawy będą się obracać w bardziej naturalny sposób." />
<check_box name="stop_posing_on_close_checkbox" label="Stop pozy po zamknięciu" tool_tip="Brak zatrzymywania pozy może być pomocny, jeśli nie chcesz jej przypadkowo stracić." />
<check_box name="reset_base_rotation_on_edit_checkbox" label="Reset bazy rotacji na edycji" tool_tip="Gdy po raz pierwszy edytujesz obrót, zresetuj go do zera. Oznacza to, że Twoja praca może zapisać pozę (a nie różnicę, patrz ładowanie / zapisywanie). Zielony 'ptaszek' pojawia się obok każdego wyzerowanego tak, wyeksportowanego stawu." />
<check_box name="also_save_bvh_checkbox" label="Twórz BVH podczas zapisu**" tool_tip="Podczas zapisywania pozy twórz również plik BVH, który można przesłać za pomocą 'Buduj > Prześlij > Animację', aby móc ustawiać siebie lub innych w świecie. Należy zresetować 'bazę' stawów do zera, ponieważ BVH wymaga oryginalnej pracy." />
</panel>
</tab_container>
<button name="toggleVisualManipulators" tool_tip="Włącz / wyłącz manipulatory wizualne." />
</panel>
<panel name="trackball_panel">
<text name="rotation_label">
Obrót:
</text>
<fs_virtual_trackpad name="limb_rotation" tool_tip="Zmień obrót aktualnie wybranej części ciała. Przytrzymaj Ctrl, aby poruszać powoli. Obróć kółkiem, aby dostosować trzecią oś. Użyj Shift lub Alt, aby zamienić, które obroty się zmieniają" />
<panel name="joint_manipulation_panel">
<tab_container name="modifier_tabs">
<panel label="Obrót" name="trackball_panel">
<fs_virtual_trackpad name="limb_rotation" tool_tip="Zmień obrót aktualnie wybranej części ciała. Przytrzymaj Ctrl, aby poruszać powoli. Obróć kółkiem, aby dostosować trzecią oś. Użyj Shift lub Alt, aby zamienić, które obroty się zmieniają" />
<text name="limb_pitch_label">
Góra/Dół:
</text>
<text name="limb_yaw_label">
Lewo/Prawo:
</text>
<text name="limb_roll_label">
Zawijanie:
</text>
</panel>
<panel title="Ruch / Rozmiar" name="position_panel">
<text name="pos_x_label">
Pozycja X:
</text>
<text name="pos_y_label">
Pozycja Y:
</text>
<text name="pos_z_label">
Pozycja Z:
</text>
<text name="scale_x_label">
Skala X:
</text>
<text name="scale_y_label">
Skala Y:
</text>
<text name="scale_z_label">
Skala Z:
</text>
</panel>
</tab_container>
<panel name="trackball_button_panel">
<button name="undo_change" tool_tip="Cofnij ostatnią zmianę obrotu" />
<button name="undo_change" tool_tip="Cofnij ostatnią zmianę" />
<button name="button_redo_change" tool_tip="Ponów ostatnią cofniętą zmianę" />
<button name="poser_joint_reset" tool_tip="Kliknij dwukrotnie, aby zresetować wszystkie wybrane części ciała do stanu z momentu, w którym po raz pierwszy zacząłeś/aś pozować" />
<button name="delta_mode_toggle" tool_tip="Jeśli zmienisz wiele stawów, każdy z nich zmieni się o tę samą wartość, zamiast wszystkie o taki sam obrót. Stosowany również do pozbywania się blokady Gimbala." />
<button label="Odbij" name="button_toggleMirrorRotation" tool_tip="Zmień przeciwległy staw, jak w lustrze." />
<button label="Sym." name="button_toggleSympatheticRotation" tool_tip="Zmień przeciwległy staw, ale w ten sam sposób." />
<button label="Kopia L &gt; P" name="button_symmetrize_left_to_right" tool_tip="Kliknij dwukrotnie, aby skopiować zmiany z lewej strony na prawą." />
<button label="Kopia P &gt; L" name="button_symmetrize_right_to_left" tool_tip="Kliknij dwukrotnie, aby skopiować zmiany z prawej strony na lewą." />
</panel>
<text name="limb_pitch_label">
Góra/Dół:
</text>
<text name="limb_yaw_label">
Lewo/Prawo:
</text>
<text name="limb_roll_label">
Rolowanie:
</text>
</panel>
<panel name="poses_loadSave">
<scroll_list tool_tip="Załaduj pozę dla animowanej postaci." name="poses_scroll">
@ -251,38 +274,15 @@
</layout_panel>
<layout_panel name="button_controls_layout">
<panel name="button_controls_panel">
<button name="toggleAdvancedPanel" tool_tip="Przełącz obszar ustawień zaawansowanych" />
<button name="FlipPose_avatar" tool_tip="Przerzuć całą pozę na lewo/prawo" />
<button name="FlipJoint_avatar" tool_tip="Odbij lustrzanie wybrane części ciała w lewo/prawo" />
<button label="Złap" name="button_RecaptureParts" tool_tip="Jeśli wybrane części ciała są WYŁĄCZONE, to ta opcja ponownie przechwytuje to, co te części ciała robią teraz." />
<button label="Wł/Wył część" name="toggle_PosingSelectedBones" tool_tip="Włącz lub wyłącz Pozer dla wybranych części ciała. Po wyłączeniu ta część ciała animuje się jak zwykle (jak z AO lub z kulką itp.)" />
<button label="Wł/Wył część" name="toggle_PosingSelectedBones" tool_tip="Włącz lub wyłącz Pozera dla wybranych części ciała. Po wyłączeniu ta część ciała animuje się jak zwykle (jak z AO lub z kulką itp.)" />
<button label="Moje pozy" name="toggleLoadSavePanel" tool_tip="Wczytaj, zapisz i zarządzaj pozami, które tworzysz" />
<button tool_tip="Zarządzaj katalogiem poz" name="open_poseDir_button" />
<menu_button label="Wczytaj pozę" tool_tip="Wczytaj aktualnie wybraną pozę." name="load_poses_button" />
<button label="Zapis różnic" tool_tip="Zapisz Twoje zmiany w istniejącej Pozie. Zacznij od T-Pozy, aby zapisać nową pracę." name="save_poses_button" />
</panel>
</layout_panel>
<layout_panel name="advanced_controls_layout">
<panel name="advanced_parent_panel">
<tab_container name="modifier_tabs">
<panel title="Pozycja części ciała" name="position_panel">
<slider label="Pozycja X:" name="Advanced_Position_X" />
<slider label="Pozycja Y:" name="Advanced_Position_Y" />
<slider label="Pozycja Z:" name="Advanced_Position_Z" />
<button label="Cofnij pozycję" name="undo_position_change" tool_tip="Cofnij ostatnią zmianę pozycji" />
<button label="Ponów pozycję" name="redo_position_change" tool_tip="Ponownie wykonaj ostatnią zmianę pozycji" />
<button label="Reset pozycji" name="reset_positions" tool_tip="Kliknij dwukrotnie, aby przywrócić pierwotną pozycję" />
</panel>
<panel title="Skala części ciała" name="scale_panel">
<slider label="Skala X:" name="Advanced_Scale_X" />
<slider label="Skala Y:" name="Advanced_Scale_Y" />
<slider label="Skala Z:" name="Advanced_Scale_Z" />
<button label="Cofnij skalę" name="undo_scale_change" tool_tip="Cofnij ostatnią zmianę skali" />
<button label="Ponów skalę" name="redo_scale_change" tool_tip="Ponownie wykonaj ostatnią zmianę skali" />
<button label="Reset skali" name="reset_scales" tool_tip="Kliknij dwukrotnie, aby przywrócić pierwotną skalę" />
</panel>
</tab_container>
</panel>
</layout_panel>
</layout_stack>
</floater>

View File

@ -30,7 +30,7 @@
<button name="Noon" label="Południe" tool_tip="Dostosuj oświetlenie tak, aby symulowało jasność południa." />
<button name="Sunset" label="Zachód" tool_tip="Zastosuj oświetlenie zachodzącego słońca, aby uzyskać ciepłe, złote odcienie." />
<button name="Midnight" label="Północ" tool_tip="Przełącz na ustawienia nocne w przypadku miejsc o słabym oświetleniu." />
<button name="Revert to Region Default" label="Otoczenie współdzielone" tool_tip="Przywróć ustawienia współdzielonego środowiska regionu." />
<button name="Revert to Region Default" label="Otocz. współdzielone" tool_tip="Przywróć ustawienia współdzielonego środowiska regionu." />
</panel>
<panel name="P_WL_Presets">
<text name="T_WL_Presets">
@ -107,7 +107,7 @@
<combo_box.item label="Słońce/Księżyc + inne źródła" name="2"/>
</combo_box>
<text name="local lights_label" tool_tip="Definiuje, ile lokalnych źródeł światła jest renderowanych jednocześnie. Ustawienie tej wartości na 0 powoduje wyłączenie wszystkich lokalnych świateł. Wyższe wartości mogą mieć wpływ na wydajność w złożonych scenach.">
Oświetl. punktowe (restart)
Światła (restart)
</text>
<combo_box name="LocalLightsDetail">
<combo_box.item label="Pełne (domyślne)" name="3" />
@ -146,7 +146,7 @@
</text>
<button name="FOV_Cutoff_Reset" tool_tip="Kliknij tutaj, aby zresetować ustawienia do domyślnych."/>
<text name="T_Spot_Cutoff" tool_tip="Dostosowuje przesunięcie cieni rzucanych przez reflektory, aby zminimalizować artefakty lub niepożądane linie na powierzchniach.">
Przesun. pnkt.
Przesn. pnkt.
</text>
<button name="Spot_Cutoff_Reset" tool_tip="Kliknij tutaj, aby zresetować ustawienia do domyślnych."/>
<text name="T_Shd_Bias" tool_tip="Steruje korekcją głębi stosowaną do cieni, aby zapobiec artefaktom związanym z samocieniem (tzw. 'shadow acne'). Niższe wartości tworzą dokładniejsze cienie, podczas gdy nieco wyższe wartości mogą pomóc zmniejszyć migotanie lub problemy z nakładaniem się cieni. Dostosowanie tego ustawienia może również pomóc w korygowaniu cieni, które wydają się unosić nad powierzchniami lub nie dotykają prawidłowo krawędzi obiektów. Reguluj stopniowo, aby zrównoważyć dokładność cieni i zapobieganie artefaktom.">

View File

@ -67,8 +67,7 @@
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
Niebo [INDEX]
[ALTITUDE]m
Niebo [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt1">
Nieznane
@ -77,8 +76,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
Niebo [INDEX]
[ALTITUDE]m
Niebo [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt2">
Nieznane
@ -87,8 +85,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
Niebo [INDEX]
[ALTITUDE]m
Niebo [INDEX]&#xA;[ALTITUDE]m
</text>
<line_editor name="edt_invname_alt3">
Nieznane

View File

@ -32,20 +32,17 @@
</layout_panel>
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">Céu [INDEX]
[ALTITUDE]m</text>
<text name="txt_alt1">Céu [INDEX]&#xA;[ALTITUDE]m</text>
<line_editor name="edt_invname_alt1">Desconhecido</line_editor>
<settings_drop_target name="sdt_alt1" tool_tip="Arraste uma configuração do Inventário para a caixa alvo para selecionar como o céu atual."/>
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">Céu [INDEX]
[ALTITUDE]m</text>
<text name="txt_alt2">Céu [INDEX]&#xA;[ALTITUDE]m</text>
<line_editor name="edt_invname_alt2">Desconhecido</line_editor>
<settings_drop_target name="sdt_alt2" tool_tip="Arraste uma configuração do Inventário para a caixa alvo para selecionar como o céu atual."/>
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">Céu [INDEX]
[ALTITUDE]m</text>
<text name="txt_alt3">Céu [INDEX]&#xA;[ALTITUDE]m</text>
<line_editor name="edt_invname_alt3">Desconhecido</line_editor>
<settings_drop_target name="sdt_alt3" tool_tip="Arraste uma configuração do Inventário para a caixa alvo para selecionar como o céu atual."/>
</panel>

View File

@ -142,10 +142,6 @@
<string name="title_BELLY">Живот</string>
<string name="title_LEFT_PEC">Левая грудь</string>
<string name="title_RIGHT_PEC">Правая грудь</string>
<string name="title_mFaceEar1Left">Левая основа</string>
<string name="title_mFaceEar1Right">Правая основа</string>
<string name="title_mFaceEar2Left">Левый кончик</string>
<string name="title_mFaceEar2Right">Правый кончик</string>
<layout_stack name="poser_stack">
<layout_panel name="regular_controls_layout">

View File

@ -72,8 +72,7 @@
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
Небо [INDEX]
[ALTITUDE]м
Небо [INDEX]&#xA;[ALTITUDE]м
</text>
<line_editor name="edt_invname_alt1">
Неизвестно
@ -82,8 +81,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
Небо [INDEX]
[ALTITUDE]м
Небо [INDEX]&#xA;[ALTITUDE]м
</text>
<line_editor name="edt_invname_alt2">
Неизвестно
@ -92,8 +90,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
Небо [INDEX]
[ALTITUDE]м
Небо [INDEX]&#xA;[ALTITUDE]м
</text>
<line_editor name="edt_invname_alt3">
Неизвестно

View File

@ -57,8 +57,7 @@
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
Gökyüzü [INDEX]
[ALTITUDE] m
Gökyüzü [INDEX]&#xA;[ALTITUDE] m
</text>
<line_editor name="edt_invname_alt1">
Bilinmiyor
@ -67,8 +66,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
Gökyüzü [INDEX]
[ALTITUDE] m
Gökyüzü [INDEX]&#xA;[ALTITUDE] m
</text>
<line_editor name="edt_invname_alt2">
Bilinmiyor
@ -77,8 +75,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
Gökyüzü [INDEX]
[ALTITUDE] m
Gökyüzü [INDEX]&#xA;[ALTITUDE] m
</text>
<line_editor name="edt_invname_alt3">
Bilinmiyor

View File

@ -1,26 +1,23 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater name="floater_poser" title="化身與動畫模型的姿勢">
<!-- A matching bone name with the 'header_' prefix produces a sub-heading with the supplied name -->
<string name="header_mHead">身體</string>
<string name="header_mFaceForeheadLeft">額頭/眉毛</string>
<string name="header_mEyeLeft">眼睛/眼瞼</string>
<string name="header_mFaceCheekUpperLeft">臉頰/嘴唇</string>
<string name="header_mHandThumb1Left">左手</string>
<string name="header_mCollarLeft">左臂</string>
<string name="header_mHandThumb1Right">右手</string>
<string name="header_mCollarRight">右臂</string>
<string name="header_mHipLeft"></string>
<string name="header_mTail1">尾巴</string>
<string name="header_mHindLimbsRoot">後肢</string>
<string name="header_mWingsRoot"></string>
<string name="header_mFaceEar1Left">耳朵/鼻子</string>
<!-- These are names to appear on the UI for the joints/bones/thingos -->
<string name="title_mPelvis">化身整體</string>
<string name="title_mTorso">軀幹</string>
<string name="title_mChest">胸部</string>
<string name="title_mNeck">頸部</string>
<string name="title_mHead">頭顱</string>
<string name="header_mHead">身體</string>
<string name="header_mFaceForeheadLeft">額頭/眉毛</string>
<string name="header_mEyeLeft">眼睛/眼瞼</string>
<string name="header_mFaceCheekUpperLeft">臉頰/嘴唇</string>
<string name="header_mHandThumb1Left">左手</string>
<string name="header_mCollarLeft">左臂</string>
<string name="header_mHandThumb1Right">右手</string>
<string name="header_mCollarRight">右臂</string>
<string name="header_mHipLeft"></string>
<string name="header_mTail1">尾巴</string>
<string name="header_mHindLimbsRoot">後肢</string>
<string name="header_mWingsRoot"></string>
<string name="header_mFaceEar1Left">耳朵/鼻子</string>
<string name="title_mPelvis">化身整體</string>
<string name="title_mTorso">軀幹</string>
<string name="title_mChest">胸部</string>
<string name="title_mNeck">頸部</string>
<string name="title_mHead">頭顱</string>
<string name="title_mEyeRight">右眼</string>
<string name="title_mEyeLeft">左眼</string>
<string name="title_mFaceForeheadLeft">左額頭角</string>
@ -144,12 +141,8 @@
<string name="title_BELLY">腹部</string>
<string name="title_LEFT_PEC">左胸肌</string>
<string name="title_RIGHT_PEC">右胸肌</string>
<string name="title_mFaceEar1Left">左耳根</string>
<string name="title_mFaceEar1Right">右耳根</string>
<string name="title_mFaceEar2Left">左耳尖</string>
<string name="title_mFaceEar2Right">右耳尖</string>
<!-- The layout is a vertical stack of 3 rows, and each row a horizontal stack of panels -->
<string name="LoadPoseLabel">載入姿勢</string>
<string name="LoadDiffLabel">載入差異</string>
<layout_stack name="poser_stack">
<layout_panel name="regular_controls_layout">
<panel name="joints_parent_panel">
@ -165,7 +158,7 @@
</text>
<slider name="av_position_leftright" tool_tip="左右移動選中的化身"/>
<text name="av_position_inout_label">
進/出
前/後
</text>
<slider name="av_position_inout" tool_tip="前後移動選中的化身"/>
<scroll_list name="entireAv_joint_scroll">
@ -208,10 +201,10 @@
</scroll_list>
</panel>
<panel title="模型" name="avatarSelection_panel">
<scroll_list tool_tip="選擇要動畫的角色或動漫角色。" name="avatarSelection_scroll">
<scroll_list tool_tip="選擇要製作姿勢的化身或動畫物件。" name="avatarSelection_scroll">
<scroll_list.columns label="選擇..." name="name"/>
</scroll_list>
<button name="refresh_avatars" tool_tip="更新頭像和動漫角色的列表"/>
<button name="refresh_avatars" tool_tip="更新化身和動畫物件的列表"/>
<button label="開始姿勢" label_selected="停止姿勢" tool_tip="若有許可權,開始/停止選定的化身或動畫物件的姿勢" name="start_stop_posing_button"/>
<button label="設為T姿勢" tool_tip="雙擊將選定的化身設為T姿勢" name="set_t_pose_button"/>
</panel>
@ -220,34 +213,59 @@
觸控板敏感度:
</text>
<slider name="trackpad_sensitivity_slider" tool_tip="設定觸控板的敏感度"/>
<check_box name="natural_direction_checkbox" label="使用自然對齊" tool_tip="骨骼預設具有不自然的關節旋轉,這可能會讓姿勢調整變得更複雜。選取此選項後,關節將以更自然的方式旋轉。" />
<check_box name="stop_posing_on_close_checkbox" label="關閉時停止" tool_tip="關閉時不停止姿勢可有助於保留目前工作。"/>
<check_box name="also_save_bvh_checkbox" label="儲存時也儲存BHV" tool_tip="當姿勢被儲存時將同時創建一個BHV檔案該檔案可以透過建造 > 上傳 > 動畫上傳並用於自己或其他化身的姿勢。為了實現此功能關節的基礎位置必須設為零因為BHV無法從其他姿勢推導出來。"/>
<check_box name="reset_base_rotation_on_edit_checkbox" label="編輯時重設基礎旋轉" tool_tip="首次編輯旋轉時,將其重設為零。這意味著可以保存完整的姿勢(而不僅僅是差異,請參閱載入/保存)。每個以零為基準匯出的關節旁都會顯示綠色勾選標誌。" />
</panel>
</tab_container>
<button name="toggleVisualManipulators" tool_tip="啟用 / 停用可視操控器。" />
</panel>
<panel name="trackball_panel">
<text name="rotation_label">
旋轉:
</text>
<fs_virtual_trackpad name="limb_rotation" tool_tip="改變目前選定身體部位的旋轉。按住CTRL緩慢改變。滾動滑鼠滾輪調整第三軸。切換或使用ALT以切換旋轉軸。"/>
<panel name="joint_manipulation_panel">
<tab_container name="modifier_tabs">
<panel label="旋轉" name="trackball_panel">
<fs_virtual_trackpad name="limb_rotation" tool_tip="調整當前選取的身體部位旋轉。按住 Ctrl 以緩慢移動,滾動滑鼠滾輪可調整三軸。使用 Shift 或 Alt 切換旋轉軸的調整方式。" />
<text name="limb_pitch_label">
上/下:
</text>
<text name="limb_yaw_label">
左/右:
</text>
<text name="limb_roll_label">
旋轉:
</text>
</panel>
<panel title="移動 / 縮放" name="position_panel">
<text name="pos_x_label">
位置 X
</text>
<text name="pos_y_label">
位置 Y
</text>
<text name="pos_z_label">
位置 Z
</text>
<text name="scale_x_label">
縮放 X
</text>
<text name="scale_y_label">
縮放 Y
</text>
<text name="scale_z_label">
縮放 Z
</text>
</panel>
</tab_container>
<panel name="trackball_button_panel">
<button name="undo_change" tool_tip="撤銷最後一次旋轉變化"/>
<button name="button_redo_change" tool_tip="重做最後一次旋轉變化"/>
<button name="poser_joint_reset" tool_tip="雙擊將所有選定身體部位重設為原始值。"/>
<button name="undo_change" tool_tip="撤銷上一次變更" />
<button name="button_redo_change" tool_tip="重做上一次變更"/>
<button name="poser_joint_reset" tool_tip="雙擊以將選取的身體部位重設為最初開始調整姿勢時的狀態。"/>
<button name="delta_mode_toggle" tool_tip="如果改變多個關節,則改變它們相同的值而不是相同的角度。這也用於解決萬向節鎖定的問題。"/>
<button label="映象" name="button_toggleMirrorRotation" tool_tip="映象對稱關節的變化。"/>
<button label="同步" name="button_toggleSympatheticRotation" tool_tip="同步調整對稱關節。"/>
<button label="鏡像" name="button_toggleMirrorRotation" tool_tip="將變更鏡像到對側關節。"/>
<button label="複製" name="button_toggleSympatheticRotation" tool_tip="將變更複製到對側關節。"/>
<button label="複製左側&gt;右" name="button_symmetrize_left_to_right" tool_tip="雙擊以將變更從左側複製到右側。" />
<button label="複製右側&gt;左" name="button_symmetrize_right_to_left" tool_tip="雙擊以將變更從右側複製到左側。" />
</panel>
<text name="limb_pitch_label">
上/下:
</text>
<text name="limb_yaw_label">
左/右:
</text>
<text name="limb_roll_label">
滾轉:
</text>
</panel>
<panel name="poses_loadSave">
<scroll_list tool_tip="為選定的化身載入姿勢。" name="poses_scroll">
@ -258,9 +276,8 @@
</layout_panel>
<layout_panel name="button_controls_layout">
<panel name="button_controls_panel">
<button name="toggleAdvancedPanel" tool_tip="啟用/禁用高級設定"/>
<button name="FlipPose_avatar" tool_tip="左右翻轉整個姿勢"/>
<button name="FlipJoint_avatar" tool_tip="映象翻轉選定的身體部位"/>
<button name="FlipJoint_avatar" tool_tip="鏡像翻轉選定的身體部位"/>
<button label="重捕" name="button_RecaptureParts" tool_tip="如果選擇的身體部位已關閉,這將重新捕捉這些身體部位當前的姿勢。"/>
<button label="啟用/禁用部位" name="toggle_PosingSelectedBones" tool_tip="啟用或禁用選定身體部位的姿勢。如果禁用,這些部位將正常動畫化。"/>
<button label="自定義姿勢" name="toggleLoadSavePanel" tool_tip="載入、儲存並管理自定義建立的姿勢"/>
@ -269,27 +286,5 @@
<button label="儲存差異" tool_tip="儲存與現有姿勢的差異。從T姿勢開始以建立新作品。" name="save_poses_button"/>
</panel>
</layout_panel>
<layout_panel name="advanced_controls_layout">
<panel name="advanced_parent_panel">
<tab_container name="modifier_tabs">
<panel title="身體部位位置" name="position_panel">
<slider label="位置 X" name="Advanced_Position_X"/>
<slider label="位置 Y" name="Advanced_Position_Y"/>
<slider label="位置 Z" name="Advanced_Position_Z"/>
<button label="撤銷位置" name="undo_position_change" tool_tip="撤銷最後一次位置變化"/>
<button label="重做位置" name="redo_position_change" tool_tip="重做最後一次位置變化"/>
<button label="重設位置" name="reset_positions" tool_tip="雙擊重設位置為原始值"/>
</panel>
<panel title="身體部位縮放" name="scale_panel">
<slider label="縮放 X" name="Advanced_Scale_X"/>
<slider label="縮放 Y" name="Advanced_Scale_Y"/>
<slider label="縮放 Z" name="Advanced_Scale_Z"/>
<button label="撤銷縮放" name="undo_scale_change" tool_tip="撤銷最後一次縮放變化"/>
<button label="重做縮放" name="redo_scale_change" tool_tip="重做最後一次縮放變化"/>
<button label="重設縮放" name="reset_scales" tool_tip="雙擊重設縮放為原始值"/>
</panel>
</tab_container>
</panel>
</layout_panel>
</layout_stack>
</floater>

View File

@ -511,7 +511,7 @@
<menu_item_check label="自動Alpha遮罩延遲" name="Automatic Alpha Masks (deferred)" />
<menu_item_check label="動畫紋理" name="Animation Textures" />
<menu_item_check label="禁用紋理" name="Disable Textures" />
<menu_item_call label="不顯示動畫" name="Derender Animesh" />
<menu_item_call label="禁用所有的動畫物件" name="Derender Animesh" />
<menu_item_check label="全解析度紋理(有風險)" name="Full Res Textures" />
<menu_item_check label="彩現附著的燈光" name="Render Attached Lights" />
<menu_item_check label="彩現附著的粒子" name="Render Attached Particles" />

View File

@ -7,7 +7,7 @@
<layout_stack name="vertical_centering2">
<layout_panel name="panel_icons">
<text name="logos_lbl">
正在使用Second Life
Second Life 使用
</text>
</layout_panel>
</layout_stack>

View File

@ -10,7 +10,7 @@
天空 [INDEX]([ALTITUDE]m)
</string>
<string name="str_no_parcel">
未選擇地塊。 環境設定已停用。
未選擇地塊。環境設定已停用。
</string>
<string name="str_cross_region">
跨越區域不提供環境設定。
@ -74,14 +74,12 @@
[HH]:[MM][AP] ([PRC]%)
</text>
</layout_panel>
<layout_panel name="pnl_environment_buttons" />
</layout_stack>
</layout_panel>
<layout_panel name="pnl_environment_altitudes">
<panel name="pnl_alt1">
<text name="txt_alt1">
天空[INDEX]
[ALTITUDE]米
天空[INDEX]&#xA;[ALTITUDE]米
</text>
<line_editor name="edt_invname_alt1">
未知
@ -90,8 +88,7 @@
</panel>
<panel name="pnl_alt2">
<text name="txt_alt2">
天空[INDEX]
[ALTITUDE]米
天空[INDEX]&#xA;[ALTITUDE]米
</text>
<line_editor name="edt_invname_alt2">
未知
@ -100,8 +97,7 @@
</panel>
<panel name="pnl_alt3">
<text name="txt_alt3">
天空[INDEX]
[ALTITUDE]米
天空[INDEX]&#xA;[ALTITUDE]米
</text>
<line_editor name="edt_invname_alt3">
未知
@ -111,11 +107,6 @@
<text name="sky_altitudes_label">
天空高度
</text>
<multi_slider initial_value="0" name="sld_altitudes">
<slider name="sld1" value="1000" />
<slider name="sld2" value="2000" />
<slider name="sld3" value="3000" />
</multi_slider>
<panel name="pnl_ground">
<text name="txt_ground">
地面