diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 87c1ee8e1f..76002c2885 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -16,3 +16,5 @@ e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 # ignore some of the merges of ws silliness to restore blame reporting 5f1a19af725b90737d50a42a51a7bc1db12c7d13 a17fd2352a9746dd3116f956dcc554f95f17e770 +# ignore beq's formatting derp +f8204c43e89d65d981a52aebf033ead5b4b3495a diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 75d88248d2..1e9e9f695a 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -107,7 +107,7 @@ if (WINDOWS) /Oy- /Oi /Ot - /fp:fast + /fp:precise /MP /permissive- ) diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index acdad15642..7d8039a64e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -641,6 +641,11 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve if(discard_level > 0) { mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level); + // [FIRE-35361] RenderMaxTextureResolution caps texture resolution lower than intended + // 2K textures could set the mMaxDiscardLevel above MAX_DISCARD_LEVEL, which would + // cause them to not be down-scaled so they would get stuck at 0 discard all the time. + mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)MAX_DISCARD_LEVEL); + // [FIRE-35361] } } else diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index eb9dc2f27f..01f1b8eb9a 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1249,7 +1249,7 @@ void LLUrlEntryParcel::processParcelInfo(const LLParcelData& parcel_data) // LLUrlEntryPlace::LLUrlEntryPlace() { - mPattern = boost::regex("((hop://[-\\w\\.\\:\\@]+/)|((x-grid-location-info://[-\\w\\.]+/region/)|(secondlife://)))\\S+/?(\\d+/\\d+/\\d+|\\d+/\\d+)/?", // + mPattern = boost::regex("((hop://[-\\w\\.\\:\\@]+/)|((x-grid-location-info://[-\\w\\.]+/region/)|(secondlife://)))\\S+(?:/?(-?\\d+/-?\\d+/-?\\d+|-?\\d+/-?\\d+)/?)?", // boost::regex::perl|boost::regex::icase); mMenuName = "menu_url_slurl.xml"; mTooltip = LLTrans::getString("TooltipSLURL"); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 00c754ed5c..55066dba15 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8080,17 +8080,6 @@ Value 0 - FSPoserAdvancedWindowState - - Comment - Whether the 'advanced' pane is shown when opening the Avatar/Animesh Poser. - Persist - 1 - Type - Boolean - Value - 0 - FSPoserSaveExternalFileAlso Comment @@ -8113,6 +8102,17 @@ Value 0 + FSPoserOnSaveConfirmOverwrite + + Comment + Whether to confirm overwriting a save file. + Persist + 1 + Type + Boolean + Value + 0 + FSPoserStopPosingWhenClosed Comment diff --git a/indra/newview/fsfloaterposer.cpp b/indra/newview/fsfloaterposer.cpp index 9a54e1d7bf..5a5f04c7e6 100644 --- a/indra/newview/fsfloaterposer.cpp +++ b/indra/newview/fsfloaterposer.cpp @@ -61,6 +61,7 @@ constexpr std::string_view POSER_TRACKPAD_SENSITIVITY_SAVE_KEY = "FSPoserTrackpa constexpr std::string_view POSER_STOPPOSINGWHENCLOSED_SAVE_KEY = "FSPoserStopPosingWhenClosed"; constexpr std::string_view POSER_RESETBASEROTONEDIT_SAVE_KEY = "FSPoserResetBaseRotationOnEdit"; constexpr std::string_view POSER_SAVEEXTERNALFORMAT_SAVE_KEY = "FSPoserSaveExternalFileAlso"; +constexpr std::string_view POSER_SAVECONFIRMREQUIRED_SAVE_KEY = "FSPoserOnSaveConfirmOverwrite"; } // namespace /// @@ -83,11 +84,10 @@ FSFloaterPoser::FSFloaterPoser(const LLSD& key) : LLFloater(key) mCommitCallbackRegistrar.add("Poser.ToggleSympatheticChanges", [this](LLUICtrl*, const LLSD&) { onToggleSympatheticChange(); }); mCommitCallbackRegistrar.add("Poser.AdjustTrackPadSensitivity", [this](LLUICtrl*, const LLSD&) { onAdjustTrackpadSensitivity(); }); - mCommitCallbackRegistrar.add("Poser.PositionSet", [this](LLUICtrl*, const LLSD&) { onAvatarPositionSet(); }); + mCommitCallbackRegistrar.add("Poser.PositionSet", [this](LLUICtrl*, const LLSD&) { onPositionSet(); }); mCommitCallbackRegistrar.add("Poser.SetToTPose", [this](LLUICtrl*, const LLSD&) { onSetAvatarToTpose(); }); - mCommitCallbackRegistrar.add("Poser.Advanced.PositionSet", [this](LLUICtrl*, const LLSD&) { onAdvancedPositionSet(); }); - mCommitCallbackRegistrar.add("Poser.Advanced.ScaleSet", [this](LLUICtrl*, const LLSD&) { onAdvancedScaleSet(); }); + mCommitCallbackRegistrar.add("Poser.Advanced.ScaleSet", [this](LLUICtrl*, const LLSD&) { onScaleSet(); }); 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); }); @@ -104,13 +104,14 @@ FSFloaterPoser::FSFloaterPoser(const LLSD& key) : LLFloater(key) mCommitCallbackRegistrar.add("Poser.TogglePosingSelectedBones", [this](LLUICtrl*, const LLSD&) { onClickToggleSelectedBoneEnabled(); }); mCommitCallbackRegistrar.add("Poser.CommitSpinner", [this](LLUICtrl* spinner, const LLSD& data) { onCommitSpinner(spinner, data); }); + mCommitCallbackRegistrar.add("Poser.CommitSlider", [this](LLUICtrl* slider, const LLSD& data) { onCommitSlider(slider, data); }); mCommitCallbackRegistrar.add("Poser.Symmetrize", [this](LLUICtrl*, const LLSD& data) { onClickSymmetrize(data); }); } bool FSFloaterPoser::postBuild() { mAvatarTrackball = getChild("limb_rotation"); - mAvatarTrackball->setCommitCallback([this](LLUICtrl *, const LLSD &) { onLimbTrackballChanged(); }); + mAvatarTrackball->setCommitCallback([this](LLUICtrl *, const LLSD &) { onTrackballChanged(); }); mJointsTabs = getChild("joints_tabs"); mJointsTabs->setCommitCallback( @@ -164,6 +165,10 @@ bool FSFloaterPoser::postBuild() mPosYSlider = getChild("av_position_leftright"); mPosZSlider = getChild("av_position_updown"); + mAdvRotXSlider = getChild("limb_pitch_slider"); + mAdvRotYSlider = getChild("limb_yaw_slider"); + mAdvRotZSlider = getChild("limb_roll_slider"); + mAdvPosXSlider = getChild("Advanced_Position_X"); mAdvPosYSlider = getChild("Advanced_Position_Y"); mAdvPosZSlider = getChild("Advanced_Position_Z"); @@ -178,6 +183,7 @@ bool FSFloaterPoser::postBuild() mBrowserFolderBtn = getChild("open_poseDir_button"); mLoadPosesBtn = getChild("load_poses_button"); mSavePosesBtn = getChild("save_poses_button"); + mSavePosesBtn->setMouseLeaveCallback([this](LLUICtrl*, const LLSD&) { onMouseLeaveSavePoseBtn(); }); mFlipPoseBtn = getChild("FlipPose_avatar"); mFlipJointBtn = getChild("FlipJoint_avatar"); @@ -188,6 +194,7 @@ bool FSFloaterPoser::postBuild() mToggleSympatheticRotationBtn = getChild("button_toggleSympatheticRotation"); mToggleDeltaModeBtn = getChild("delta_mode_toggle"); mRedoChangeBtn = getChild("button_redo_change"); + mUndoChangeBtn = getChild("undo_change"); mSetToTposeButton = getChild("set_t_pose_button"); mJointsParentPnl = getChild("joints_parent_panel"); @@ -252,15 +259,23 @@ void FSFloaterPoser::onFocusLost() LLEditMenuHandler::gEditMenuHandler = nullptr; } } + void FSFloaterPoser::enableVisualManipulators() { + if (!gAgentAvatarp || gAgentAvatarp.isNull()) + { + mToggleVisualManipulators->setToggleState(false); + return; + } + if (LLToolMgr::getInstance()->getCurrentToolset() != gCameraToolset) { mLastToolset = LLToolMgr::getInstance()->getCurrentToolset(); } + LLToolMgr::getInstance()->setCurrentToolset(gPoserToolset); LLToolMgr::getInstance()->getCurrentToolset()->selectTool(FSToolCompPose::getInstance()); - FSToolCompPose::getInstance()->setAvatar( gAgentAvatarp); + FSToolCompPose::getInstance()->setAvatar(gAgentAvatarp); } void FSFloaterPoser::disableVisualManipulators() @@ -347,16 +362,22 @@ void FSFloaterPoser::onPoseFileSelect() mPoseSaveNameEditor->setText(name); bool isDeltaSave = !poseFileStartsFromTeePose(name); - if (isDeltaSave) + if (isDeltaSave && hasString("LoadDiffLabel")) mLoadPosesBtn->setLabel(getString("LoadDiffLabel")); - else + else if (hasString("LoadPoseLabel")) mLoadPosesBtn->setLabel(getString("LoadPoseLabel")); } void FSFloaterPoser::onClickPoseSave() { std::string filename = mPoseSaveNameEditor->getValue().asString(); - if (filename.empty()) + if (filename.empty() && hasString("icon_save_failed_button")) + { + mSavePosesBtn->setImageOverlay(getString("icon_save_failed_button"), mSavePosesBtn->getImageOverlayHAlign()); + return; + } + + if (confirmFileOverwrite(filename)) return; LLVOAvatar* avatar = getUiSelectedAvatar(); @@ -372,8 +393,55 @@ void FSFloaterPoser::onClickPoseSave() if (getSavingToBvh()) savePoseToBvh(avatar, filename); - // TODO: provide feedback for save + if (hasString("icon_rotation_is_own_work")) + mSavePosesBtn->setImageOverlay(getString("icon_rotation_is_own_work"), mSavePosesBtn->getImageOverlayHAlign()); + + setSavePosesButtonText(!mPoserAnimator.allBaseRotationsAreZero(avatar)); } + else + { + if (hasString("icon_save_failed_button")) + mSavePosesBtn->setImageOverlay(getString("icon_save_failed_button"), mSavePosesBtn->getImageOverlayHAlign()); + } +} + +bool FSFloaterPoser::confirmFileOverwrite(std::string fileName) +{ + if (fileName.empty()) + return false; + + if (!gSavedSettings.getBOOL(POSER_SAVECONFIRMREQUIRED_SAVE_KEY)) + return false; + + if (!hasString("icon_save_query")) + return false; + + if (mSavePosesBtn->getImageOverlay().notNull() && mSavePosesBtn->getImageOverlay()->getName() == getString("icon_save_query")) + return false; + + std::string fullSavePath = + gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, POSE_SAVE_SUBDIRECTORY, fileName + POSE_INTERNAL_FORMAT_FILE_EXT); + + if (!gDirUtilp->fileExists(fullSavePath)) + return false; + + mSavePosesBtn->setImageOverlay(getString("icon_save_query"), mSavePosesBtn->getImageOverlayHAlign()); + if (hasString("OverWriteLabel")) + mSavePosesBtn->setLabel(getString("OverWriteLabel")); + + return true; +} + +void FSFloaterPoser::onMouseLeaveSavePoseBtn() +{ + if (hasString("icon_save_button")) + mSavePosesBtn->setImageOverlay(getString("icon_save_button"), mSavePosesBtn->getImageOverlayHAlign()); + + LLVOAvatar* avatar = getUiSelectedAvatar(); + if (!avatar) + return; + + setSavePosesButtonText(!mPoserAnimator.allBaseRotationsAreZero(avatar)); } void FSFloaterPoser::createUserPoseDirectoryIfNeeded() @@ -552,6 +620,7 @@ void FSFloaterPoser::onClickFlipSelectedJoints() } refreshRotationSlidersAndSpinners(); + enableOrDisableRedoAndUndoButton(); refreshTrackpadCursor(); } @@ -596,13 +665,11 @@ void FSFloaterPoser::onClickRecaptureSelectedBones() refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); refreshTextHighlightingOnJointScrollLists(); + enableOrDisableRedoAndUndoButton(); } -void FSFloaterPoser::updatePosedBones() -{ - auto selectedJoints = getUiSelectedPoserJoints(); - if (selectedJoints.size() < 1) - return; +void FSFloaterPoser::updatePosedBones(const std::string& jointName) +{ LLVOAvatar *avatar = getUiSelectedAvatar(); if (!avatar) return; @@ -610,18 +677,17 @@ void FSFloaterPoser::updatePosedBones() if (!mPoserAnimator.isPosingAvatar(avatar)) return; - for (auto item : selectedJoints) - { - bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item); - if (!currentlyPosing) - continue; + const FSPoserAnimator::FSPoserJoint* poserJoint = mPoserAnimator.getPoserJointByName(jointName); + if (!poserJoint) + return; - mPoserAnimator.recaptureJointAsDelta(avatar, *item, getJointTranslation(item->jointName()), getJointNegation(item->jointName())); - } + mPoserAnimator.recaptureJointAsDelta(avatar, poserJoint, getUiSelectedBoneDeflectionStyle()); - setSavePosesButtonText(true); refreshRotationSlidersAndSpinners(); + refreshPositionSlidersAndSpinners(); + refreshScaleSlidersAndSpinners(); refreshTrackpadCursor(); + enableOrDisableRedoAndUndoButton(); refreshTextHighlightingOnJointScrollLists(); } @@ -633,11 +699,8 @@ void FSFloaterPoser::onClickBrowsePoseCache() gViewerWindow->getWindow()->openFile(pathname); } -void FSFloaterPoser::onClickSymmetrize(S32 ID) +void FSFloaterPoser::onClickSymmetrize(const S32 ID) { - if (notDoubleClicked()) - return; - LLVOAvatar* avatar = getUiSelectedAvatar(); if (!avatar) return; @@ -648,40 +711,35 @@ void FSFloaterPoser::onClickSymmetrize(S32 ID) mPoserAnimator.symmetrizeLeftToRightOrRightToLeft(avatar, ID == 2); refreshRotationSlidersAndSpinners(); + enableOrDisableRedoAndUndoButton(); refreshTrackpadCursor(); } -void FSFloaterPoser::onCommitSpinner(LLUICtrl* spinner, S32 id) +void FSFloaterPoser::onCommitSpinner(const LLUICtrl* spinner, const S32 id) { if (!spinner) return; - auto activeTab = mJointsTabs->getCurrentPanel(); - if (!activeTab) - return; - - bool changingBodyPosition = activeTab == mPositionRotationPnl; - F32 value = (F32)spinner->getValue().asReal(); switch (id) { case 0: // av_position_updown_spinner { - mPosZSlider->setValue(value); - onAvatarPositionSet(); + mAdvPosZSpnr->setValue(value); + onPositionSet(); break; } case 1: // av_position_leftright { - mPosYSlider->setValue(value); - onAvatarPositionSet(); + mAdvPosYSpnr->setValue(value); + onPositionSet(); break; } case 2: // av_position_inout_spinner { - mPosXSlider->setValue(value); - onAvatarPositionSet(); + mAdvPosXSpnr->setValue(value); + onPositionSet(); break; } case 3: // trackpad_sensitivity_spinner @@ -690,50 +748,100 @@ void FSFloaterPoser::onCommitSpinner(LLUICtrl* spinner, S32 id) break; } case 7: // adv_posx_spinner - { - if (changingBodyPosition) - mPosXSlider->setValue(value); - - mAdvPosXSlider->setValue(value); - onAdvancedPositionSet(); - break; - } case 8: // adv_posy_spinner - { - if (changingBodyPosition) - mPosYSlider->setValue(value); - - mAdvPosYSlider->setValue(value); - onAdvancedPositionSet(); - break; - } case 9: // adv_posz_spinner { - if (changingBodyPosition) - mPosZSlider->setValue(value); - - mAdvPosZSlider->setValue(value); - onAdvancedPositionSet(); + onPositionSet(); break; } case 10: // adv_scalex_spinner - { - mAdvScaleXSlider->setValue(value); - onAdvancedScaleSet(); - break; - } case 11: // adv_scaley_spinner - { - mAdvScaleYSlider->setValue(value); - onAdvancedScaleSet(); - break; - } case 12: // adv_scalez_spinner { - mAdvScaleZSlider->setValue(value); - onAdvancedScaleSet(); + onScaleSet(); break; } + + default: + LL_WARNS("Posing") << "onCommitSpinner passed invalid parameter: " << id << LL_ENDL; + break; + } +} + +void FSFloaterPoser::onCommitSlider(const LLUICtrl* slider, const S32 id) +{ + if (!slider) + return; + + F32 value = (F32)slider->getValue().asReal(); + + switch (id) + { + case 0: // av_position_updown + case 9: // Advanced_Position_Z + { + mAdvPosZSpnr->setValue(value); + onPositionSet(); + break; + } + + case 1: // av_position_leftright + case 8: // Advanced_Position_Y + { + mAdvPosYSpnr->setValue(value); + onPositionSet(); + break; + } + + case 2: // av_position_inout + case 7: // Advanced_Position_X + { + mAdvPosXSpnr->setValue(value); + onPositionSet(); + break; + } + + case 4: // limb_pitch_slider + { + mPitchSpnr->setValue(value); + onYawPitchRollChanged(); + break; + } + case 5: // limb_yaw_slider + { + mYawSpnr->setValue(value); + onYawPitchRollChanged(); + break; + } + case 6: // limb_roll_slider + { + mRollSpnr->setValue(value); + onYawPitchRollChanged(); + break; + } + + case 10: // Advanced_Scale_X + { + mScaleXSpnr->setValue(value); + onScaleSet(); + break; + } + case 11: // Advanced_Scale_Y + { + mScaleYSpnr->setValue(value); + onScaleSet(); + break; + } + case 12: // Advanced_Scale_Z + { + mScaleZSpnr->setValue(value); + onScaleSet(); + break; + } + + default: + LL_WARNS("Posing") << "onCommitSlider passed invalid parameter: " << id << LL_ENDL; + break; } } @@ -779,27 +887,13 @@ void FSFloaterPoser::onPoseMenuAction(const LLSD& param) setSavePosesButtonText(!mPoserAnimator.allBaseRotationsAreZero(avatar)); } -bool FSFloaterPoser::notDoubleClicked() -{ - auto timeIntervalSinceLastExecution = std::chrono::system_clock::now() - mTimeLastExecutedDoubleClickMethod; - mTimeLastExecutedDoubleClickMethod = std::chrono::system_clock::now(); - - return timeIntervalSinceLastExecution > mDoubleClickInterval; -} - void FSFloaterPoser::onClickLoadLeftHandPose() { - if (notDoubleClicked()) - return; - onClickLoadHandPose(false); } void FSFloaterPoser::onClickLoadRightHandPose() { - if (notDoubleClicked()) - return; - onClickLoadHandPose(true); } @@ -1295,19 +1389,15 @@ void FSFloaterPoser::onUndoLastChange() mPoserAnimator.undoLastJointChange(avatar, *item, getUiSelectedBoneDeflectionStyle()); } - enableOrDisableRedoButton(); + enableOrDisableRedoAndUndoButton(); refreshRotationSlidersAndSpinners(); - refreshTrackpadCursor(); refreshPositionSlidersAndSpinners(); - refreshAvatarPositionSlidersAndSpinners(); refreshScaleSlidersAndSpinners(); + refreshTrackpadCursor(); } void FSFloaterPoser::onSetAvatarToTpose() { - if (notDoubleClicked()) - return; - LLVOAvatar* avatar = getUiSelectedAvatar(); if (!avatar) return; @@ -1315,13 +1405,11 @@ void FSFloaterPoser::onSetAvatarToTpose() setSavePosesButtonText(false); mPoserAnimator.setAllAvatarStartingRotationsToZero(avatar); refreshTextHighlightingOnJointScrollLists(); + enableOrDisableRedoAndUndoButton(); } void FSFloaterPoser::onResetJoint(const LLSD data) { - if (notDoubleClicked()) - return; - int resetType = data.asInteger(); LLVOAvatar* avatar = getUiSelectedAvatar(); @@ -1345,10 +1433,10 @@ void FSFloaterPoser::onResetJoint(const LLSD data) } refreshRotationSlidersAndSpinners(); - refreshTrackpadCursor(); - refreshAvatarPositionSlidersAndSpinners(); refreshPositionSlidersAndSpinners(); refreshScaleSlidersAndSpinners(); + refreshTrackpadCursor(); + enableOrDisableRedoAndUndoButton(); } void FSFloaterPoser::onRedoLastChange() @@ -1371,16 +1459,18 @@ void FSFloaterPoser::onRedoLastChange() mPoserAnimator.redoLastJointChange(avatar, *item, getUiSelectedBoneDeflectionStyle()); } - enableOrDisableRedoButton(); + enableOrDisableRedoAndUndoButton(); refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); refreshScaleSlidersAndSpinners(); refreshPositionSlidersAndSpinners(); - refreshAvatarPositionSlidersAndSpinners(); } -void FSFloaterPoser::enableOrDisableRedoButton() +void FSFloaterPoser::enableOrDisableRedoAndUndoButton() { + mRedoChangeBtn->setEnabled(false); + mUndoChangeBtn->setEnabled(false); + LLVOAvatar* avatar = getUiSelectedAvatar(); if (!avatar) return; @@ -1393,14 +1483,20 @@ void FSFloaterPoser::enableOrDisableRedoButton() return; bool shouldEnableRedoButton = false; + bool shouldEnableUndoButton = false; + for (auto item : selectedJoints) { bool currentlyPosing = mPoserAnimator.isPosingAvatarJoint(avatar, *item); - if (currentlyPosing) - shouldEnableRedoButton |= mPoserAnimator.canRedoJointChange(avatar, *item); + if (!currentlyPosing) + continue; + + shouldEnableRedoButton |= mPoserAnimator.canRedoOrUndoJointChange(avatar, *item); + shouldEnableUndoButton |= mPoserAnimator.canRedoOrUndoJointChange(avatar, *item, true); } mRedoChangeBtn->setEnabled(shouldEnableRedoButton); + mUndoChangeBtn->setEnabled(shouldEnableUndoButton); } void FSFloaterPoser::onToggleVisualManipulators() @@ -1504,6 +1600,7 @@ LLScrollListCtrl* FSFloaterPoser::getScrollListForTab(LLPanel * tabPanel) const LL_WARNS() << "Unknown tab panel: " << tabPanel << LL_ENDL; return nullptr; } + std::vector FSFloaterPoser::getUiSelectedPoserJoints() const { std::vector joints; @@ -1542,21 +1639,23 @@ std::vector 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 ); - } - } + + updateManipWithFirstSelectedJoint(joints); + return joints; } +void FSFloaterPoser::updateManipWithFirstSelectedJoint(std::vector joints) +{ + if (!gAgentAvatarp || gAgentAvatarp.isNull()) + return; + + if (joints.size() >= 1) + FSToolCompPose::getInstance()->setJoint(gAgentAvatarp->getJoint(JointKey::construct(joints[0]->jointName()))); + else + FSToolCompPose::getInstance()->setJoint(nullptr); +} + E_RotationStyle FSFloaterPoser::getUiSelectedBoneRotationStyle(const std::string& jointName) const { if (jointName.empty()) @@ -1663,130 +1762,100 @@ LLVOAvatar* FSFloaterPoser::getAvatarByUuid(const LLUUID& avatarToFind) const return nullptr; } -void FSFloaterPoser::onAdvancedPositionSet() +void FSFloaterPoser::onPositionSet() { - F32 posX = mAdvPosXSlider->getValueF32(); - F32 posY = mAdvPosYSlider->getValueF32(); - F32 posZ = mAdvPosZSlider->getValueF32(); - - mAdvPosXSpnr->setValue(posX); + F32 posX = (F32)mAdvPosXSpnr->getValue().asReal(); + F32 posY = (F32)mAdvPosYSpnr->getValue().asReal(); + F32 posZ = (F32)mAdvPosZSpnr->getValue().asReal(); + mInOutSpnr->setValue(posX); - mAdvPosYSpnr->setValue(posY); mLeftRightSpnr->setValue(posY); - mAdvPosZSpnr->setValue(posZ); - mUpDownSpnr->setValue(posZ); - - setSelectedJointsPosition(posX, posY, posZ); - refreshAvatarPositionSlidersAndSpinners(); -} - -void FSFloaterPoser::onAdvancedScaleSet() -{ - F32 scX = mAdvScaleXSlider->getValueF32(); - F32 scY = mAdvScaleYSlider->getValueF32(); - F32 scZ = mAdvScaleZSlider->getValueF32(); - - mScaleXSpnr->setValue(scX); - mScaleYSpnr->setValue(scY); - mScaleZSpnr->setValue(scZ); - - setSelectedJointsScale(scX, scY, scZ); -} - -void FSFloaterPoser::onAvatarPositionSet() -{ - F32 posX = mPosXSlider->getValueF32(); - F32 posY = mPosYSlider->getValueF32(); - F32 posZ = mPosZSlider->getValueF32(); - - mAdvPosXSpnr->setValue(posX); - mInOutSpnr->setValue(posX); - mAdvPosYSpnr->setValue(posY); - mLeftRightSpnr->setValue(posY); - mAdvPosZSpnr->setValue(posZ); mUpDownSpnr->setValue(posZ); + mAdvPosXSlider->setValue(posX); + mAdvPosYSlider->setValue(posY); + mAdvPosZSlider->setValue(posZ); + mPosXSlider->setValue(posX); + mPosYSlider->setValue(posY); + mPosZSlider->setValue(posZ); setSelectedJointsPosition(posX, posY, posZ); refreshPositionSlidersAndSpinners(); + enableOrDisableRedoAndUndoButton(); } -void FSFloaterPoser::onLimbTrackballChanged() +void FSFloaterPoser::onScaleSet() { - LLVector3 trackPadPos, trackPadDeltaPos; - LLSD position = mAvatarTrackball->getValue(); + F32 scX = (F32)mScaleXSpnr->getValue().asReal(); + F32 scY = (F32)mScaleYSpnr->getValue().asReal(); + F32 scZ = (F32)mScaleZSpnr->getValue().asReal(); + + mAdvScaleXSlider->setValue(scX); + mAdvScaleYSlider->setValue(scY); + mAdvScaleZSlider->setValue(scZ); + + setSelectedJointsScale(scX, scY, scZ); + refreshScaleSlidersAndSpinners(); + enableOrDisableRedoAndUndoButton(); +} + +void FSFloaterPoser::onTrackballChanged() +{ + LLVector3 trackPadDeltaPos; LLSD deltaPosition = mAvatarTrackball->getValueDelta(); - if (position.isArray() && position.size() == 3 && deltaPosition.isArray() && deltaPosition.size() == 3) - { - trackPadPos.setValue(position); + if (deltaPosition.isArray() && deltaPosition.size() == 3) trackPadDeltaPos.setValue(deltaPosition); - } else return; F32 trackPadSensitivity = llmax(gSavedSettings.getF32(POSER_TRACKPAD_SENSITIVITY_SAVE_KEY), 0.0001f); - trackPadPos.mV[VX] *= trackPadSensitivity; - trackPadPos.mV[VY] *= trackPadSensitivity; + trackPadDeltaPos[VX] *= NormalTrackpadRangeInRads * trackPadSensitivity * RAD_TO_DEG; + trackPadDeltaPos[VY] *= NormalTrackpadRangeInRads * trackPadSensitivity * RAD_TO_DEG; + trackPadDeltaPos[VZ] *= NormalTrackpadRangeInRads * RAD_TO_DEG; - trackPadPos.mV[VX] = unWrapScale(trackPadPos.mV[VX]) * NormalTrackpadRangeInRads; - trackPadPos.mV[VY] = unWrapScale(trackPadPos.mV[VY]) * NormalTrackpadRangeInRads; - trackPadPos.mV[VZ] = unWrapScale(trackPadPos.mV[VZ]) * NormalTrackpadRangeInRads; + F32 axis1 = clipRange((F32)mYawSpnr->getValue().asReal() + trackPadDeltaPos[VX]); + F32 axis2 = (F32)mPitchSpnr->getValue().asReal() + trackPadDeltaPos[VY]; + F32 axis3 = (F32)mRollSpnr->getValue().asReal() + trackPadDeltaPos[VZ]; - trackPadDeltaPos[VX] *= NormalTrackpadRangeInRads * trackPadSensitivity; - trackPadDeltaPos[VY] *= NormalTrackpadRangeInRads * trackPadSensitivity; - trackPadDeltaPos[VZ] *= NormalTrackpadRangeInRads; + mYawSpnr->setValue(axis1); + mPitchSpnr->setValue(axis2); + mRollSpnr->setValue(axis3); - setSelectedJointsRotation(trackPadPos, trackPadDeltaPos); - - // WARNING! - // as tempting as it is to refactor the following to refreshRotationSliders(), don't. - // getRotationOfFirstSelectedJoint/setSelectedJointsRotation are - // not necessarily symmetric functions (see their remarks). - mYawSpnr->setValue(trackPadPos.mV[VX] *= RAD_TO_DEG); - mPitchSpnr->setValue(trackPadPos.mV[VY] *= RAD_TO_DEG); - mRollSpnr->setValue(trackPadPos.mV[VZ] *= RAD_TO_DEG); + onYawPitchRollChanged(true); } -F32 FSFloaterPoser::unWrapScale(F32 scale) +F32 FSFloaterPoser::clipRange(F32 value) { - if (scale > -1.f && scale < 1.f) - return scale; - - F32 result = fmodf(scale, 100.f); // to avoid time consuming while loops - while (result > 1) - result -= 2; - while (result < -1) - result += 2; + F32 result = fmodf(value, 3600.f); // to avoid time consuming while loops + while (result > 180.f) + result -= 360.f; + while (result < -180.f) + result += 360.f; return result; } -void FSFloaterPoser::onYawPitchRollChanged() +void FSFloaterPoser::onYawPitchRollChanged(bool skipUpdateTrackpad) { LLVector3 absoluteRotation, deltaRotation; - 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; + absoluteRotation.mV[VX] = (F32)mYawSpnr->getValue().asReal(); + absoluteRotation.mV[VY] = (F32)mPitchSpnr->getValue().asReal(); + absoluteRotation.mV[VZ] = (F32)mRollSpnr->getValue().asReal(); + mAdvRotXSlider->setValue(absoluteRotation.mV[VY]); + mAdvRotYSlider->setValue(absoluteRotation.mV[VX]); + mAdvRotZSlider->setValue(absoluteRotation.mV[VZ]); + + absoluteRotation *= DEG_TO_RAD; deltaRotation = absoluteRotation - mLastSliderRotation; mLastSliderRotation = absoluteRotation; setSelectedJointsRotation(absoluteRotation, deltaRotation); + enableOrDisableRedoAndUndoButton(); - // WARNING! - // as tempting as it is to refactor the following to refreshTrackpadCursor(), don't. - // getRotationOfFirstSelectedJoint/setSelectedJointsRotation are - // not necessarily symmetric functions (see their remarks). - F32 trackPadSensitivity = llmax(gSavedSettings.getF32(POSER_TRACKPAD_SENSITIVITY_SAVE_KEY), 0.0001f); - absoluteRotation.mV[VX] /= trackPadSensitivity; - absoluteRotation.mV[VY] /= trackPadSensitivity; - - absoluteRotation.mV[VX] /= NormalTrackpadRangeInRads; - absoluteRotation.mV[VY] /= NormalTrackpadRangeInRads; - absoluteRotation.mV[VZ] /= NormalTrackpadRangeInRads; - - mAvatarTrackball->setValue(absoluteRotation.getValue()); + if (!skipUpdateTrackpad) + refreshTrackpadCursor(); } void FSFloaterPoser::onAdjustTrackpadSensitivity() @@ -1796,38 +1865,14 @@ void FSFloaterPoser::onAdjustTrackpadSensitivity() void FSFloaterPoser::refreshTrackpadCursor() { - F32 axis1 = (F32)mYawSpnr->getValue().asReal() * DEG_TO_RAD / NormalTrackpadRangeInRads; - F32 axis2 = (F32)mPitchSpnr->getValue().asReal() * DEG_TO_RAD / NormalTrackpadRangeInRads; + F32 trackPadSensitivity = llmax(gSavedSettings.getF32(POSER_TRACKPAD_SENSITIVITY_SAVE_KEY), 0.0001f); + F32 axis1 = (F32)mYawSpnr->getValue().asReal() * DEG_TO_RAD / NormalTrackpadRangeInRads / trackPadSensitivity; + F32 axis2 = (F32)mPitchSpnr->getValue().asReal() * DEG_TO_RAD / NormalTrackpadRangeInRads / trackPadSensitivity; F32 axis3 = (F32)mRollSpnr->getValue().asReal() * DEG_TO_RAD / NormalTrackpadRangeInRads; - F32 trackPadSensitivity = llmax(gSavedSettings.getF32(POSER_TRACKPAD_SENSITIVITY_SAVE_KEY), 0.0001f); - axis1 /= trackPadSensitivity; - axis2 /= trackPadSensitivity; - mAvatarTrackball->setValue(axis1, axis2, axis3); } -/// -/// This only sets the position sliders of the 'basic' view (not the advanced sliders). -/// -void FSFloaterPoser::refreshAvatarPositionSlidersAndSpinners() -{ - auto activeTab = mJointsTabs->getCurrentPanel(); - if (!activeTab) - return; - - if (activeTab != mPositionRotationPnl) - return; // if the active tab isn't the av position one, don't set anything. - - LLVector3 position = getPositionOfFirstSelectedJoint(); - mPosXSlider->setValue(position.mV[VX]); - mInOutSpnr->setValue(position.mV[VX]); - mPosYSlider->setValue(position.mV[VY]); - mLeftRightSpnr->setValue(position.mV[VY]); - mPosZSlider->setValue(position.mV[VZ]); - mUpDownSpnr->setValue(position.mV[VZ]); -} - void FSFloaterPoser::refreshRotationSlidersAndSpinners() { LLVector3 rotation = getRotationOfFirstSelectedJoint(); @@ -1836,6 +1881,9 @@ void FSFloaterPoser::refreshRotationSlidersAndSpinners() mYawSpnr->setValue(rotation.mV[VX] *= RAD_TO_DEG); mPitchSpnr->setValue(rotation.mV[VY] *= RAD_TO_DEG); mRollSpnr->setValue(rotation.mV[VZ] *= RAD_TO_DEG); + mAdvRotXSlider->setValue(rotation.mV[VY]); + mAdvRotYSlider->setValue(rotation.mV[VX]); + mAdvRotZSlider->setValue(rotation.mV[VZ]); } void FSFloaterPoser::refreshPositionSlidersAndSpinners() @@ -1848,6 +1896,20 @@ void FSFloaterPoser::refreshPositionSlidersAndSpinners() mAdvPosYSpnr->setValue(position.mV[VY]); mAdvPosZSlider->setValue(position.mV[VZ]); mAdvPosZSpnr->setValue(position.mV[VZ]); + + auto activeTab = mJointsTabs->getCurrentPanel(); + if (!activeTab) + return; + + if (activeTab != mPositionRotationPnl) + return; // if the active tab isn't the av position one, don't set anything. + + mPosXSlider->setValue(position.mV[VX]); + mInOutSpnr->setValue(position.mV[VX]); + mPosYSlider->setValue(position.mV[VY]); + mLeftRightSpnr->setValue(position.mV[VY]); + mPosZSlider->setValue(position.mV[VZ]); + mUpDownSpnr->setValue(position.mV[VZ]); } void FSFloaterPoser::refreshScaleSlidersAndSpinners() @@ -2003,11 +2065,10 @@ LLVector3 FSFloaterPoser::getScaleOfFirstSelectedJoint() const void FSFloaterPoser::onJointTabSelect() { - refreshAvatarPositionSlidersAndSpinners(); + refreshPositionSlidersAndSpinners(); refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); - enableOrDisableRedoButton(); - refreshPositionSlidersAndSpinners(); + enableOrDisableRedoAndUndoButton(); refreshScaleSlidersAndSpinners(); onClickSetBaseRotZero(); } @@ -2276,7 +2337,8 @@ void FSFloaterPoser::refreshTextHighlightingOnJointScrollLists() void FSFloaterPoser::setSavePosesButtonText(bool setAsSaveDiff) { - setAsSaveDiff ? mSavePosesBtn->setLabel("Save Diff") : mSavePosesBtn->setLabel("Save Pose"); + if (hasString("SavePoseLabel") && hasString("SaveDiffLabel")) + setAsSaveDiff ? mSavePosesBtn->setLabel(getString("SaveDiffLabel")) : mSavePosesBtn->setLabel(getString("SavePoseLabel")); } void FSFloaterPoser::addBoldToScrollList(LLScrollListCtrl* list, LLVOAvatar* avatar) @@ -2571,8 +2633,8 @@ S32 FSFloaterPoser::getBvhJointNegation(const std::string& jointName) const return result; } - bool FSFloaterPoser::getWhetherToResetBaseRotationOnEdit() { return gSavedSettings.getBOOL(POSER_RESETBASEROTONEDIT_SAVE_KEY); } + void FSFloaterPoser::onClickSetBaseRotZero() { mAlsoSaveBvhCbx->setEnabled(getWhetherToResetBaseRotationOnEdit()); } bool FSFloaterPoser::getSavingToBvh() diff --git a/indra/newview/fsfloaterposer.h b/indra/newview/fsfloaterposer.h index 3d21953b05..622577b0de 100644 --- a/indra/newview/fsfloaterposer.h +++ b/indra/newview/fsfloaterposer.h @@ -78,13 +78,13 @@ class FSFloaterPoser : public LLFloater, public LLEditMenuHandler { friend class LLFloaterReg; FSFloaterPoser(const LLSD &key); -public: - void updatePosedBones(); +public: + void updatePosedBones(const std::string& jointName); 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; } + 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; @@ -132,6 +132,12 @@ public: /// The selected joints std::vector getUiSelectedPoserJoints() const; + /// + /// Updates the visual with the first selected joint from the supplied collection, if any. + /// + /// The collection of selected joints. + static void updateManipWithFirstSelectedJoint(std::vector joints); + /// /// Gets a detectable avatar by its UUID. /// @@ -214,6 +220,7 @@ public: void createUserPoseDirectoryIfNeeded(); void onToggleLoadSavePanel(); void onClickPoseSave(); + void onMouseLeaveSavePoseBtn(); void onPoseFileSelect(); bool savePoseToXml(LLVOAvatar* avatar, const std::string& posePath); bool savePoseToBvh(LLVOAvatar* avatar, const std::string& posePath); @@ -223,31 +230,30 @@ public: bool poseFileStartsFromTeePose(const std::string& poseFileName); void setPoseSaveFileTextBoxToUiSelectedAvatarSaveFileName(); void setUiSelectedAvatarSaveFileName(const std::string& saveFileName); + bool confirmFileOverwrite(std::string fileName); + void startPosingSelf(); + void stopPosingAllAvatars(); // visual manipulators control void enableVisualManipulators(); void disableVisualManipulators(); - // UI Event Handlers: + // UI Event Handlers void onAvatarsRefresh(); void onAvatarSelect(); void onJointTabSelect(); void onToggleMirrorChange(); void onToggleSympatheticChange(); - void onToggleVisualManipulators(); + void onToggleVisualManipulators(); void setRotationChangeButtons(bool mirror, bool sympathetic); void onUndoLastChange(); void onRedoLastChange(); void onResetJoint(const LLSD data); void onSetAvatarToTpose(); - void enableOrDisableRedoButton(); void onPoseStartStop(); - void startPosingSelf(); - void stopPosingAllAvatars(); - void onLimbTrackballChanged(); - void onYawPitchRollChanged(); - void onAvatarPositionSet(); - void onAdvancedPositionSet(); - void onAdvancedScaleSet(); + void onTrackballChanged(); + void onYawPitchRollChanged(bool skipUpdateTrackpad = false); + void onPositionSet(); + void onScaleSet(); void onClickToggleSelectedBoneEnabled(); void onClickRecaptureSelectedBones(); void onClickFlipPose(); @@ -257,15 +263,16 @@ public: void onClickLoadRightHandPose(); void onClickLoadHandPose(bool isRightHand); void onClickSetBaseRotZero(); - void onCommitSpinner(LLUICtrl* spinner, S32 ID); - void onClickSymmetrize(S32 ID); + void onCommitSpinner(const LLUICtrl* spinner, const S32 ID); + void onCommitSlider(const LLUICtrl* slider, const S32 id); + void onClickSymmetrize(const S32 ID); // UI Refreshments void refreshRotationSlidersAndSpinners(); - void refreshAvatarPositionSlidersAndSpinners(); - void refreshTrackpadCursor(); void refreshPositionSlidersAndSpinners(); void refreshScaleSlidersAndSpinners(); + void refreshTrackpadCursor(); + void enableOrDisableRedoAndUndoButton(); /// /// Determines if we have permission to animate the supplied avatar. @@ -341,12 +348,6 @@ public: /// The avatar to whom the list is relevant. void addBoldToScrollList(LLScrollListCtrl* list, LLVOAvatar* avatar); - /// - /// Determines if the user has run this method twice within mDoubleClickInterval. - /// - /// true if this method has executed since mDoubleClickInterval seconds ago, otherwise false. - bool notDoubleClicked(); - /// /// Gets whether the user wishes to reset the base-rotation to zero when they start editing a joint. /// @@ -426,26 +427,15 @@ public: std::string static vec3ToXYZString(const LLVector3& val); /// - /// The time when the last click of a button was made. - /// Utilized for controls needing a 'double click do' function. + /// Performs an angle module of the supplied value to between -180 & 180 (degrees). /// - std::chrono::system_clock::time_point mTimeLastExecutedDoubleClickMethod = std::chrono::system_clock::now(); - - /// - /// The constant time interval, in seconds, a user must execute the notDoubleClicked twice to successfully 'double-click' a button. - /// - std::chrono::duration const mDoubleClickInterval = std::chrono::duration(0.3); - - /// - /// Unwraps a normalized value from the trackball to a slider value. - /// - /// The scale value from the trackball. - /// A value appropriate for fitting a slider. + /// The value to modulo. + /// The modulo value. /// - /// If the trackpad is in 'infinite scroll' mode, it can produce normalized-values outside the range of the sliders. - /// This method ensures whatever value the trackpad produces, they work with the sliders. + /// If the trackpad is in 'infinite scroll' mode, it can produce normalized-values outside the range of the spinners. + /// This method ensures whatever value the trackpad produces, they work with the spinners. /// - static F32 unWrapScale(F32 scale); + static F32 clipRange(F32 value); LLToolset* mLastToolset{ nullptr }; LLTool* mJointRotTool{ nullptr }; @@ -458,6 +448,9 @@ public: LLSliderCtrl* mPosXSlider{ nullptr }; LLSliderCtrl* mPosYSlider{ nullptr }; LLSliderCtrl* mPosZSlider{ nullptr }; + LLSliderCtrl* mAdvRotXSlider{ nullptr }; + LLSliderCtrl* mAdvRotYSlider{ nullptr }; + LLSliderCtrl* mAdvRotZSlider{ nullptr }; LLSliderCtrl* mAdvPosXSlider{ nullptr }; LLSliderCtrl* mAdvPosYSlider{ nullptr }; LLSliderCtrl* mAdvPosZSlider{ nullptr }; @@ -492,6 +485,7 @@ public: LLButton* mToggleSympatheticRotationBtn{ nullptr }; LLButton* mToggleDeltaModeBtn{ nullptr }; LLButton* mRedoChangeBtn{ nullptr }; + LLButton* mUndoChangeBtn{ nullptr }; LLButton* mSetToTposeButton{ nullptr }; LLButton* mBtnJointRotate{ nullptr }; diff --git a/indra/newview/fsjointpose.cpp b/indra/newview/fsjointpose.cpp index 53a6b2869e..608e737aba 100644 --- a/indra/newview/fsjointpose.cpp +++ b/indra/newview/fsjointpose.cpp @@ -144,21 +144,15 @@ void FSJointPose::recaptureJoint() addStateToUndo(FSJointState(mCurrentState)); mCurrentState = FSJointState(joint); } + void FSJointPose::recaptureJointAsDelta() { - if (mIsCollisionVolume) - { - return; - } - LLJoint* joint = mJointState->getJoint(); if (!joint) - { return; - } - - addStateToUndo(mCurrentState); - mCurrentState = FSJointState(joint); + + addStateToUndo(FSJointState(mCurrentState)); + mCurrentState.updateFromJoint(joint); } void FSJointPose::swapRotationWith(FSJointPose* oppositeJoint) @@ -209,6 +203,9 @@ void FSJointPose::zeroBaseRotation() if (mIsCollisionVolume) return; + if (!isBaseRotationZero()) + purgeUndoQueue(); + mCurrentState.zeroBaseRotation(); } @@ -219,3 +216,22 @@ bool FSJointPose::isBaseRotationZero() const return mCurrentState.baseRotationIsZero(); } + +void FSJointPose::purgeUndoQueue() +{ + mUndoneJointStatesIndex = 0; + mLastSetJointStates.clear(); +} + +bool FSJointPose::canPerformUndo() const +{ + switch (mLastSetJointStates.size()) + { + case 0: // nothing to undo + return false; + case 1: // there is only one change + return true; + default: // current state is not the bottom of the deque + return mUndoneJointStatesIndex != (mLastSetJointStates.size() - 1); + } +} diff --git a/indra/newview/fsjointpose.h b/indra/newview/fsjointpose.h index fe2d200bd1..05c96475ff 100644 --- a/indra/newview/fsjointpose.h +++ b/indra/newview/fsjointpose.h @@ -108,6 +108,12 @@ class FSJointPose /// True if the represented joint is zero, otherwise false. bool isBaseRotationZero() const; + /// + /// Gets whether an undo of this joint may be performed. + /// + /// true if the joint may have a undo applied, otherwise false. + bool canPerformUndo() const; + /// /// Gets whether a redo of this joint may be performed. /// @@ -143,11 +149,16 @@ class FSJointPose /// Resets the beginning properties of the joint this represents. /// void recaptureJoint(); + /// /// Recalculates the delta reltive to the base for a new rotation. /// void recaptureJointAsDelta(); + /// + /// Clears the undo/redo deque. + /// + void purgeUndoQueue(); /// /// Reverts the position/rotation/scale to their values when the animation begun. @@ -185,7 +196,6 @@ class FSJointPose inv_base.conjugate(); mDeltaRotation = newRotation * inv_base; }; - void reflectRotation() { @@ -215,6 +225,18 @@ class FSJointPose joint->setScale(mBaseScale); } + void updateFromJoint(LLJoint* joint) + { + if (!joint) + return; + + LLQuaternion invRot = mBaseRotation; + invRot.conjugate(); + mRotation = joint->getRotation() * invRot; + mPosition.set(joint->getPosition() - mBasePosition); + mScale.set(joint->getScale() - mBaseScale); + } + private: FSJointState(FSJointState* state) { diff --git a/indra/newview/fsmaniprotatejoint.cpp b/indra/newview/fsmaniprotatejoint.cpp index 8e5c4466da..da1bd33a90 100644 --- a/indra/newview/fsmaniprotatejoint.cpp +++ b/indra/newview/fsmaniprotatejoint.cpp @@ -1012,9 +1012,9 @@ bool FSManipRotateJoint::handleMouseUp(S32 x, S32 y, MASK mask) if (hasMouseCapture()) { // Update the UI, by causing it to read back the position of the selected joints and aply those relative to the base rot - if (poser) + if (poser && mJoint) { - poser->updatePosedBones(); + poser->updatePosedBones(mJoint->getName()); } // Release mouse diff --git a/indra/newview/fspanelface.cpp b/indra/newview/fspanelface.cpp index ea4558d355..8ff008372c 100644 --- a/indra/newview/fspanelface.cpp +++ b/indra/newview/fspanelface.cpp @@ -220,10 +220,10 @@ void getSelectedGLTFMaterialMaxRepeats(LLGLTFMaterial::TextureInfo channel, F32& // // local preview of material changes -class LLRenderMaterialFunctor : public LLSelectedTEFunctor +class FSRenderMaterialFunctor : public LLSelectedTEFunctor { public: - LLRenderMaterialFunctor(const LLUUID &id) + FSRenderMaterialFunctor(const LLUUID &id) : mMatId(id) { } @@ -243,21 +243,23 @@ private: }; // -// keep LLRenderMaterialOverrideFunctor in sync with llmaterialeditor.cpp just take -// out the reverting functionality as it makes no real sense with all the texture -// controls visible for the material at all times. +// keep LLRenderMaterialOverrideFunctor in sync with llmaterialeditor.cpp just take out the +// reverting functionality of non texture and color related GLTF settings as it makes no +// real sense with all the texture controls visible for the material at all times. // TODO: look at how to handle local textures, especially when saving materials // - Would be nice if we had this in its own file so we could include it from both sides ... -Zi // -class LLRenderMaterialOverrideFunctor : public LLSelectedNodeFunctor +class FSRenderMaterialOverrideFunctor : public LLSelectedNodeFunctor { public: - LLRenderMaterialOverrideFunctor( + FSRenderMaterialOverrideFunctor( LLGLTFMaterial* material_to_apply, - U32 unsaved_changes + U32 unsaved_changes, + U32 reverted_changes ) : mMaterialToApply(material_to_apply) , mUnsavedChanges(unsaved_changes) + , mRevertedChanges(reverted_changes) { } @@ -314,12 +316,32 @@ public: material = new LLGLTFMaterial(*material); } + LLPointer revert_mat; + if (nodep->mSavedGLTFOverrideMaterials.size() > te) + { + if (nodep->mSavedGLTFOverrideMaterials[te].notNull()) + { + revert_mat = nodep->mSavedGLTFOverrideMaterials[te]; + } + else + { + // mSavedGLTFOverrideMaterials[te] being present but null + // means we need to use a default value + revert_mat = new LLGLTFMaterial(); + } + } + // else can not revert at all + // Override object's values with values from editor where appropriate if (mUnsavedChanges & MATERIAL_BASE_COLOR_DIRTY) { LL_DEBUGS("APPLY_GLTF_CHANGES") << "applying MATERIAL_BASE_COLOR_DIRTY" << LL_ENDL; material->setBaseColorFactor(mMaterialToApply->mBaseColor, true); } + else if ((mRevertedChanges & MATERIAL_BASE_COLOR_DIRTY) && revert_mat.notNull()) + { + material->setBaseColorFactor(revert_mat->mBaseColor, false); + } if (mUnsavedChanges & MATERIAL_BASE_COLOR_TEX_DIRTY) { @@ -333,6 +355,17 @@ public: } */ } + else if ((mRevertedChanges & MATERIAL_BASE_COLOR_TEX_DIRTY) && revert_mat.notNull()) + { + material->setBaseColorId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR], false); + /* + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_BASE_COLOR_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } + */ + } if (mUnsavedChanges & MATERIAL_NORMAL_TEX_DIRTY) { @@ -346,6 +379,17 @@ public: } */ } + else if ((mRevertedChanges & MATERIAL_NORMAL_TEX_DIRTY) && revert_mat.notNull()) + { + material->setNormalId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL], false); + /* + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_NORMAL_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } + */ + } if (mUnsavedChanges & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) { @@ -359,6 +403,17 @@ public: } */ } + else if ((mRevertedChanges & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) && revert_mat.notNull()) + { + material->setOcclusionRoughnessMetallicId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS], false); + /* + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } + */ + } if (mUnsavedChanges & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY) { @@ -377,6 +432,10 @@ public: LL_DEBUGS("APPLY_GLTF_CHANGES") << "applying MATERIAL_EMISIVE_COLOR_DIRTY" << LL_ENDL; material->setEmissiveColorFactor(LLColor3(mMaterialToApply->mEmissiveColor), true); } + else if ((mRevertedChanges & MATERIAL_EMISIVE_COLOR_DIRTY) && revert_mat.notNull()) + { + material->setEmissiveColorFactor(revert_mat->mEmissiveColor, false); + } if (mUnsavedChanges & MATERIAL_EMISIVE_TEX_DIRTY) { @@ -390,6 +449,17 @@ public: } */ } + else if ((mRevertedChanges & MATERIAL_EMISIVE_TEX_DIRTY) && revert_mat.notNull()) + { + material->setEmissiveId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE], false); + /* + LLUUID tracking_id = mEditor->getLocalTextureTrackingIdFromFlag(MATERIAL_EMISIVE_TEX_DIRTY); + if (tracking_id.notNull()) + { + LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(tracking_id, material); + } + */ + } if (mUnsavedChanges & MATERIAL_DOUBLE_SIDED_DIRTY) { @@ -418,6 +488,7 @@ public: private: LLGLTFMaterial* mMaterialToApply; U32 mUnsavedChanges; + U32 mRevertedChanges; }; // @@ -621,6 +692,7 @@ FSPanelFace::FSPanelFace() : LLPanel(), mNeedMediaTitle(true), mUnsavedChanges(0), + mRevertedChanges(0), mExcludeWater(false) { // register callbacks before buildFromFile() or they won't work! @@ -660,9 +732,6 @@ void FSPanelFace::onMatTabChange() static S32 last_mat = -1; if( auto curr_mat = getCurrentMaterialType(); curr_mat != last_mat ) { - // Fixes some UI desync - updateUI(true); - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); LLViewerObject* objectp = node ? node->getObject() : NULL; if(objectp) @@ -688,6 +757,16 @@ void FSPanelFace::onMatTabChange() } } } + + // Since we allow both PBR and BP textures to be applied at the same time, + // we need to hide or show the GLTF material only locally based on the current tab. + if (curr_mat != MATMEDIA_PBR) + LLSelectMgr::getInstance()->hideGLTFMaterial(); + else + LLSelectMgr::getInstance()->showGLTFMaterial(); + + // Fixes some UI desync + updateUI(true); } } @@ -1092,7 +1171,7 @@ void FSPanelFace::draw() // not sure if there isn't a better place for this, but for the time being this seems to work, // and trying other places always failed in some way or other -Zi static U64MicrosecondsImplicit next_update_time = 0LL; - if (mUnsavedChanges && gFrameTime > next_update_time) + if ((mUnsavedChanges || mRevertedChanges) && gFrameTime > next_update_time) { LL_DEBUGS("APPLY_GLTF_CHANGES") << "detected unsaved changes: " << mUnsavedChanges << LL_ENDL; @@ -1100,12 +1179,13 @@ void FSPanelFace::draw() getGLTFMaterial(mat); LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection(); - LLRenderMaterialOverrideFunctor override_func(mat, mUnsavedChanges); + FSRenderMaterialOverrideFunctor override_func(mat, mUnsavedChanges, mRevertedChanges); selected_objects->applyToNodes(&override_func); LLGLTFMaterialList::flushUpdates(); mUnsavedChanges = 0; + mRevertedChanges = 0; next_update_time = gFrameTime + 100000LL; // 100 ms @@ -3790,12 +3870,114 @@ void FSPanelFace::updatePBROverrideDisplay() void FSPanelFace::onCancelPbr(const LLUICtrl* map_ctrl) { - // TODO -Zi + if (map_ctrl == mBaseTexturePBR) + { + mRevertedChanges |= MATERIAL_BASE_COLOR_TEX_DIRTY; + } + else if (map_ctrl == mNormalTexturePBR) + { + mRevertedChanges |= MATERIAL_NORMAL_TEX_DIRTY; + } + else if (map_ctrl == mEmissiveTexturePBR) + { + mRevertedChanges |= MATERIAL_EMISIVE_TEX_DIRTY; + } + else if (map_ctrl == mORMTexturePBR) + { + mRevertedChanges |= MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY; + } + else if (map_ctrl == mBaseTintPBR) + { + mRevertedChanges |= MATERIAL_BASE_COLOR_DIRTY; + } + else if (map_ctrl == mEmissiveTintPBR) + { + mRevertedChanges |= MATERIAL_EMISIVE_COLOR_DIRTY; + } } void FSPanelFace::onSelectPbr(const LLUICtrl* map_ctrl) { onCommitPbr(map_ctrl); + + struct f : public LLSelectedNodeFunctor + { + f(const LLUICtrl* ctrl, S32 dirty_flag) : mCtrl(ctrl), mDirtyFlag(dirty_flag) + { + } + + virtual bool apply(LLSelectNode* nodep) + { + LLViewerObject* objectp = nodep->getObject(); + if (!objectp) + { + return false; + } + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); // avatars have TEs but no faces + for (S32 te = 0; te < num_tes; ++te) + { + if (nodep->isTESelected(te) && nodep->mSavedGLTFOverrideMaterials.size() > te) + { + if (nodep->mSavedGLTFOverrideMaterials[te].isNull()) + { + // populate with default values, default values basically mean 'not in use' + nodep->mSavedGLTFOverrideMaterials[te] = new LLGLTFMaterial(); + } + + switch (mDirtyFlag) + { + //Textures + case MATERIAL_BASE_COLOR_TEX_DIRTY: + { + nodep->mSavedGLTFOverrideMaterials[te]->setBaseColorId(mCtrl->getValue().asUUID(), true); + //update_local_texture(mCtrl, nodep->mSavedGLTFOverrideMaterials[te].get()); + break; + } + case MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY: + { + nodep->mSavedGLTFOverrideMaterials[te]->setOcclusionRoughnessMetallicId(mCtrl->getValue().asUUID(), true); + //update_local_texture(mCtrl, nodep->mSavedGLTFOverrideMaterials[te].get()); + break; + } + case MATERIAL_EMISIVE_TEX_DIRTY: + { + nodep->mSavedGLTFOverrideMaterials[te]->setEmissiveId(mCtrl->getValue().asUUID(), true); + //update_local_texture(mCtrl, nodep->mSavedGLTFOverrideMaterials[te].get()); + break; + } + case MATERIAL_NORMAL_TEX_DIRTY: + { + nodep->mSavedGLTFOverrideMaterials[te]->setNormalId(mCtrl->getValue().asUUID(), true); + //update_local_texture(mCtrl, nodep->mSavedGLTFOverrideMaterials[te].get()); + break; + } + // Colors + case MATERIAL_BASE_COLOR_DIRTY: + { + LLColor4 ret = linearColor4(LLColor4(mCtrl->getValue())); + // except transparency + ret.mV[3] = nodep->mSavedGLTFOverrideMaterials[te]->mBaseColor.mV[3]; + nodep->mSavedGLTFOverrideMaterials[te]->setBaseColorFactor(ret, true); + break; + } + case MATERIAL_EMISIVE_COLOR_DIRTY: + { + nodep->mSavedGLTFOverrideMaterials[te]->setEmissiveColorFactor(LLColor3(mCtrl->getValue()), true); + break; + } + default: + break; + } + } + } + return true; + } + + const LLUICtrl* mCtrl; + S32 mDirtyFlag; + } func(map_ctrl, mUnsavedChanges); + + LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func); } bool FSPanelFace::onDragTexture(const LLUICtrl* texture_ctrl, LLInventoryItem* item) diff --git a/indra/newview/fspanelface.h b/indra/newview/fspanelface.h index f053f20442..d4d226f872 100644 --- a/indra/newview/fspanelface.h +++ b/indra/newview/fspanelface.h @@ -485,6 +485,7 @@ private: // Dirty flags - taken from llmaterialeditor.cpp ... LL please put this in a .h! -Zi U32 mUnsavedChanges; // flags to indicate individual changed parameters + U32 mRevertedChanges; // flags to indicate individual reverted parameters // Hey look everyone, a type-safe alternative to copy and paste! :) // diff --git a/indra/newview/fsposeranimator.cpp b/indra/newview/fsposeranimator.cpp index 39938d4490..62d9030c85 100644 --- a/indra/newview/fsposeranimator.cpp +++ b/indra/newview/fsposeranimator.cpp @@ -138,7 +138,7 @@ void FSPoserAnimator::resetJoint(LLVOAvatar* avatar, const FSPoserJoint& joint, oppositeJointPose->setPublicScale(LLVector3()); } -bool FSPoserAnimator::canRedoJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint) +bool FSPoserAnimator::canRedoOrUndoJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint, bool canUndo) { if (!isAvatarSafeToUse(avatar)) return false; @@ -154,6 +154,9 @@ bool FSPoserAnimator::canRedoJointChange(LLVOAvatar* avatar, const FSPoserJoint& if (!jointPose) return false; + if (canUndo) + return jointPose->canPerformUndo(); + return jointPose->canPerformRedo(); } @@ -303,7 +306,7 @@ void FSPoserAnimator::setAllAvatarStartingRotationsToZero(LLVOAvatar* avatar) if (!posingMotion) return; - posingMotion->setAllRotationsToZero(); + posingMotion->setAllRotationsToZeroAndClearUndo(); } void FSPoserAnimator::recaptureJoint(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation) @@ -322,7 +325,8 @@ 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) + +void FSPoserAnimator::recaptureJointAsDelta(LLVOAvatar* avatar, const FSPoserJoint* joint, E_BoneDeflectionStyles style) { if (!isAvatarSafeToUse(avatar)) return; @@ -331,12 +335,34 @@ void FSPoserAnimator::recaptureJointAsDelta(LLVOAvatar* avatar, const FSPoserJoi if (!posingMotion) return; - FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint.jointName()); + FSJointPose* jointPose = posingMotion->getJointPoseByJointName(joint->jointName()); if (!jointPose) return; jointPose->recaptureJointAsDelta(); - setPosingAvatarJoint(avatar, joint, true); + + if (style == NONE || style == DELTAMODE) + return; + + FSJointPose* oppositeJointPose = posingMotion->getJointPoseByJointName(joint->mirrorJointName()); + if (!oppositeJointPose) + return; + + switch (style) + { + case SYMPATHETIC: + case SYMPATHETIC_DELTA: + oppositeJointPose->cloneRotationFrom(jointPose); + break; + + case MIRROR: + case MIRROR_DELTA: + oppositeJointPose->mirrorRotationFrom(jointPose); + break; + + default: + break; + } } LLVector3 FSPoserAnimator::getJointRotation(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation) const diff --git a/indra/newview/fsposeranimator.h b/indra/newview/fsposeranimator.h index 045558288a..8056ba7785 100644 --- a/indra/newview/fsposeranimator.h +++ b/indra/newview/fsposeranimator.h @@ -417,8 +417,9 @@ public: /// /// The avatar having the joint to which we refer. /// The joint to query. - /// True if a redo action is available, otherwise false. - bool canRedoJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint); + /// Supply true to query if we can perform an Undo, otherwise query redo. + /// True if an undo or redo action is available, otherwise false. + bool canRedoOrUndoJointChange(LLVOAvatar* avatar, const FSPoserJoint& joint, bool canUndo = false); /// /// Re-does the last undone change (rotation, position or scale) to the supplied PoserJoint. @@ -503,20 +504,27 @@ public: /// /// Symmetrizes the rotations of the joints from one side of the supplied avatar to the other. /// - /// The avatar whose joints to symmetrizet. + /// The avatar to symmetrize. /// Whether to symmetrize rotations from right to left, otherwise symmetrize left to right. void symmetrizeLeftToRightOrRightToLeft(LLVOAvatar* avatar, bool rightToLeft); /// /// 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. + /// AsDelta variant retains the original base and creates a delta relative to it. /// /// The avatar whose joint is to be recaptured. /// The joint to recapture. /// The axial translation form the supplied joint. /// The style of negation to apply to the recapture. void recaptureJoint(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation); - void recaptureJointAsDelta(LLVOAvatar* avatar, const FSPoserJoint& joint, E_BoneAxisTranslation translation, S32 negation); + + /// + /// Recaptures any change in joint state. + /// + /// The avatar whose joint is to be recaptured. + /// The joint to recapture. + /// Any ancilliary action to be taken with the change to be made. + void recaptureJointAsDelta(LLVOAvatar* avatar, const FSPoserJoint* joint, E_BoneDeflectionStyles style); /// /// Sets all of the joint rotations of the supplied avatar to zero. @@ -525,14 +533,11 @@ public: void setAllAvatarStartingRotationsToZero(LLVOAvatar* avatar); /// - /// Determines if the kind of save to perform should be a 'delta' save, or a complete save. + /// Determines if the supplied joint has a base rotation of zero. /// - /// The avatar whose pose-rotations are being considered for saving. - /// True if the save should save only 'deltas' to the rotation, otherwise false. - /// - /// A save of the rotation 'deltas' facilitates a user saving their changes to an existing animation. - /// Thus the save represents 'nothing other than the changes the user made', to some other pose which they may have limited rights to. - /// + /// The avatar owning the supplied joint. + /// The joint to query. + /// True if the supplied joint has a 'base' rotation of zero (thus user-supplied change only), otherwise false. bool baseRotationIsZero(LLVOAvatar* avatar, const FSPoserJoint& joint) const; /// diff --git a/indra/newview/fsposingmotion.cpp b/indra/newview/fsposingmotion.cpp index fc418dd911..841ab3a452 100644 --- a/indra/newview/fsposingmotion.cpp +++ b/indra/newview/fsposingmotion.cpp @@ -255,7 +255,7 @@ bool FSPosingMotion::allStartingRotationsAreZero() const return true; } -void FSPosingMotion::setAllRotationsToZero() +void FSPosingMotion::setAllRotationsToZeroAndClearUndo() { for (auto poserJoint_iter = mJointPoses.begin(); poserJoint_iter != mJointPoses.end(); ++poserJoint_iter) { diff --git a/indra/newview/fsposingmotion.h b/indra/newview/fsposingmotion.h index 71c7d41063..9d862ffbef 100644 --- a/indra/newview/fsposingmotion.h +++ b/indra/newview/fsposingmotion.h @@ -119,9 +119,9 @@ public: bool allStartingRotationsAreZero() const; /// - /// Sets all of the non-Collision Volume rotations to zero. + /// Sets all of the non-Collision Volume base-and-delta rotations to zero, and clears the undo/redo queue. /// - void setAllRotationsToZero(); + void setAllRotationsToZeroAndClearUndo(); private: /// diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index bc3c2faa6c..ca997ff7aa 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1462,13 +1462,6 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, // LLMaterial* mat = tep->getMaterialParams().get(); LLMaterial* mat = tep ? tep->getMaterialParams().get() : 0; // - // show legacy when editing the fallback materials. - static LLCachedControl showSelectedinBP(gSavedSettings, "FSShowSelectedInBlinnPhong"); - if( gltf_mat && getViewerObject()->isSelected() && showSelectedinBP ) - { - gltf_mat = nullptr; - } - // F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 258c59122f..bae3b9fb18 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -57,6 +57,8 @@ #include "llnotificationsutil.h" #include "llregionhandle.h" #include "llscrolllistctrl.h" +#include "llviewernetwork.h" // Access to GridManager +#include "lfsimfeaturehandler.h" // hyperGridURL() #include "llslurl.h" #include "lltextbox.h" #include "lltoolbarview.h" @@ -77,6 +79,7 @@ #include "llmapimagetype.h" #include "llweb.h" #include "llsliderctrl.h" +#include "llspinctrl.h" // setMinValue #include "message.h" #include "llwindow.h" // copyTextToClipboard() #include @@ -396,9 +399,16 @@ bool LLFloaterWorldMap::postBuild() mLandmarkIcon = getChild("landmark_icon"); mLocationIcon = getChild("location_icon"); + // [FIRE-35333] OpenSim needs to be able to adjust the minValue + /* mTeleportCoordSpinX = getChild("teleport_coordinate_x"); mTeleportCoordSpinY = getChild("teleport_coordinate_y"); mTeleportCoordSpinZ = getChild("teleport_coordinate_z"); + */ + mTeleportCoordSpinX = getChild("teleport_coordinate_x"); + mTeleportCoordSpinY = getChild("teleport_coordinate_y"); + mTeleportCoordSpinZ = getChild("teleport_coordinate_z"); + // LLComboBox *avatar_combo = getChild("friend combo"); avatar_combo->selectFirstItem(); @@ -521,6 +531,15 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) { centerOnTarget(false); } + + // [FIRE-35333] OpenSim allows Z coordinates to be negative based on MinSimHeight + if (!LLGridManager::getInstance()->isInSecondLife()) + { + LLViewerRegion* regionp = gAgent.getRegion(); + F32 min_sim_height = regionp ? regionp->getMinSimHeight() : 0.f; + mTeleportCoordSpinZ->setMinValue(min_sim_height); + } + // } // static @@ -1006,7 +1025,12 @@ void LLFloaterWorldMap::updateLocation() // Set the current SLURL // Aurora-sim var region teleports //mSLURL = LLSLURL(agent_sim_name, gAgent.getPositionGlobal()); - mSLURL = LLSLURL(agent_sim_name, gAgent.getPositionAgent()); + // [FIRE-35268] OpenSim support for when on other grids + if (LLGridManager::getInstance()->isInSecondLife()) + mSLURL = LLSLURL(agent_sim_name, gAgent.getPositionAgent()); + else + mSLURL = LLSLURL(LFSimFeatureHandler::instance().hyperGridURL(), agent_sim_name, gAgent.getPositionAgent()); + // // } } @@ -1059,7 +1083,12 @@ void LLFloaterWorldMap::updateLocation() // if ( gotSimName ) { // mSLURL = LLSLURL(sim_name, pos_global); - mSLURL = LLSLURL(sim_info->getName(), sim_info->getGlobalOrigin(), pos_global); + // [FIRE-35268] OpenSim support for when on other grids + if (LLGridManager::getInstance()->isInSecondLife()) + mSLURL = LLSLURL(sim_info->getName(), gAgent.getPositionAgent()); + else + mSLURL = LLSLURL(LFSimFeatureHandler::instance().hyperGridURL(), sim_info->getName(), gAgent.getPositionAgent()); + // } // else @@ -1082,7 +1111,18 @@ void LLFloaterWorldMap::updateLocation() void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S32 y_coord, S32 z_coord) { LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromName(region_name); - z_coord = llclamp(z_coord, 0, 4096); + // [FIRE-35333] OpenSim allows Z coordinates to be negative based on MinSimHeight + if (!LLGridManager::getInstance()->isInSecondLife()) + { + LLViewerRegion* regionp = gAgent.getRegion(); + F32 min_sim_height = regionp ? regionp->getMinSimHeight() : 0.f; + z_coord = llclamp(z_coord, min_sim_height, 4096); + } + else + { + z_coord = llclamp(z_coord, 0, 4096); + } + // if (sim_info) { LLVector3 local_pos; diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 6a6f0e898a..d71ae9e88c 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -245,9 +245,16 @@ private: LLUICtrl* mLocationIcon = nullptr; LLSearchEditor* mLocationEditor = nullptr; + // [FIRE-35333] OpenSim needs to be able to adjust the minValue + /* LLUICtrl* mTeleportCoordSpinX = nullptr; LLUICtrl* mTeleportCoordSpinY = nullptr; LLUICtrl* mTeleportCoordSpinZ = nullptr; + */ + LLSpinCtrl* mTeleportCoordSpinX = nullptr; + LLSpinCtrl* mTeleportCoordSpinY = nullptr; + LLSpinCtrl* mTeleportCoordSpinZ = nullptr; + // LLSliderCtrl* mZoomSlider = nullptr; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index ed1e92670e..551dd63728 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6236,6 +6236,13 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data // might need to be moved to LLGLTFMaterialOverrideDispatchHandler node->saveGLTFMaterials(material_ids, override_materials); } + + // [FIRE-35138] Show or hide the GLTF Material based on showSelectedinBP + static LLCachedControl showSelectedinBP(gSavedSettings, "FSShowSelectedInBlinnPhong"); + if (showSelectedinBP) + LLSelectMgr::instance().hideGLTFMaterial(); + else + LLSelectMgr::instance().showGLTFMaterial(); } node->mValid = true; @@ -9074,6 +9081,88 @@ bool LLSelectMgr::selectGetNoIndividual() } // +// [FIRE-35138] Hide the GLTF Material since we are currently in BP +void LLSelectMgr::hideGLTFMaterial() +{ + struct f : public LLSelectedObjectFunctor + { + f() {} + bool apply(LLViewerObject* objectp) + { + if (!objectp || !objectp->permModify()) + { + return false; + } + + // Save the current GLTF materials so they can be restored later + objectp->saveGLTFMaterials(); + + for (S32 te = 0; te < objectp->getNumTEs(); ++te) + { + // Blank out most override data on the object and don't send to server + objectp->setRenderMaterialID(te, LLUUID(), false); + } + + return true; + } + }; + f setfunc; + getSelection()->applyToObjects(&setfunc); +} +// + +// [FIRE-35138] Show the GLTF Material since we are no longer in BP +void LLSelectMgr::showGLTFMaterial() +{ + struct f : public LLSelectedObjectFunctor + { + f() {} + bool apply(LLViewerObject* objectp) + { + if (!objectp || !objectp->permModify()) + { + return false; + } + + const uuid_vec_t& saved_gltf_material_ids = objectp->getSavedGLTFMaterialIds(); + const gltf_materials_vec_t& saved_gltf_override_materials = objectp->getSavedGLTFOverrideMaterials(); + + if (saved_gltf_material_ids.empty()) + { + return false; + } + + for (S32 te = 0; te < objectp->getNumTEs(); ++te) + { + if (te >= saved_gltf_material_ids.size()) + { + LL_WARNS("FS") << "TE index out of bounds for saved GLTF materials" << LL_ENDL; + break; + } + + // Restore gltf material + LLUUID asset_id = saved_gltf_material_ids[te]; + LLGLTFMaterial* material = saved_gltf_override_materials[te]; + + // Update material locally + objectp->setRenderMaterialID(te, asset_id, false); + if (material) + { + material = new LLGLTFMaterial(*material); + objectp->setTEGLTFMaterialOverride(te, material); + } + + // Do not enqueue update to server + } + + objectp->clearSavedGLTFMaterials(); + return true; + } + } setfunc; + getSelection()->applyToObjects(&setfunc); +} +// + template<> bool LLCheckIdenticalFunctor::same(const F32& a, const F32& b, const F32& tolerance) { diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 0ce33d597f..6a8c3d255c 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -1024,6 +1024,8 @@ public: // (edit linked parts, select face) bool selectGetNoIndividual(); // + void showGLTFMaterial(); // [FIRE-35138] Show the GLTF Material since we are no longer in BP + void hideGLTFMaterial(); // [FIRE-35138] Hide the GLTF Material since we are currently in BP }; // *DEPRECATED: For callbacks or observers, use diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index 3d3554ae17..13fa9137e8 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -546,7 +546,12 @@ void LLTracker::drawBeacon(LLVector3 pos_agent, std::string direction, LLColor4 height = pos_agent.mV[2]; } - nRows = (U32)ceil((BEACON_ROWS * height) / MAX_HEIGHT); + // [FIRE-35333] OpenSim allows Z coordinates to be negative based on MinSimHeight + if (height < 0.f) + nRows = 0; + else + nRows = (U32)ceil((BEACON_ROWS * height) / MAX_HEIGHT); + // if(nRows<2) nRows=2; rowHeight = height / nRows; @@ -557,7 +562,10 @@ void LLTracker::drawBeacon(LLVector3 pos_agent, std::string direction, LLColor4 F32 x = x_axis.mV[0]; F32 y = x_axis.mV[1]; - F32 z = 0.f; + // [FIRE-35333] OpenSim allows Z coordinates to be negative based on MinSimHeight + //F32 z = 0.f; + F32 z = llmin(height, 0.f); + // F32 z_next; F32 a,an; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 8528f28faa..869c744983 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7887,6 +7887,39 @@ void LLViewerObject::setRenderMaterialIDs(const LLUUID& id) setRenderMaterialID(-1, id); } +// [FIRE-35138] Helpers for GLTF Materials since we support PBR and BP at same time +void LLViewerObject::saveGLTFMaterials() +{ + if (!mSavedGLTFMaterialIds.empty()) + { + // Already saved, no need to do it again + return; + } + + for (S32 te = 0; te < getNumTEs(); ++te) + { + mSavedGLTFMaterialIds.emplace_back(getRenderMaterialID(te)); + + LLPointer old_override = getTE(te)->getGLTFMaterialOverride(); + if (old_override.notNull()) + { + LLGLTFMaterial* copy = new LLGLTFMaterial(*old_override); + mSavedGLTFOverrideMaterials.emplace_back(copy); + } + else + { + mSavedGLTFOverrideMaterials.emplace_back(nullptr); + } + } +} + +void LLViewerObject::clearSavedGLTFMaterials() +{ + mSavedGLTFMaterialIds.clear(); + mSavedGLTFOverrideMaterials.clear(); +} +// + void LLViewerObject::setRenderMaterialIDs(const LLRenderMaterialParams* material_params, bool local_origin) { if (!local_origin) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 515aca63f2..9adfbd0c73 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -100,6 +100,8 @@ typedef void (*inventory_callback)(LLViewerObject*, S32 serial_num, void*); +typedef std::vector > gltf_materials_vec_t; // [FIRE-35138] typedef for saved GLTF override materials + // for exporting textured materials from SL struct LLMaterialExportInfo { @@ -135,6 +137,10 @@ protected: LLNetworkData *data; }; std::unordered_map mExtraParameterList; + // [FIRE-35138] Saved GLTF materials to be restored when needed + uuid_vec_t mSavedGLTFMaterialIds; + gltf_materials_vec_t mSavedGLTFOverrideMaterials; + // public: typedef std::list > child_list_t; @@ -204,6 +210,13 @@ public: void setRenderMaterialID(S32 te, const LLUUID& id, bool update_server = true, bool local_origin = true); void setRenderMaterialIDs(const LLUUID& id); + // [FIRE-35138] Helpers for GLTF Materials since we support PBR and BP at same time + const uuid_vec_t& getSavedGLTFMaterialIds() const { return mSavedGLTFMaterialIds; }; + const gltf_materials_vec_t& getSavedGLTFOverrideMaterials() const { return mSavedGLTFOverrideMaterials; }; + void saveGLTFMaterials(); + void clearSavedGLTFMaterials(); + // + virtual bool isHUDAttachment() const { return false; } virtual bool isTempAttachment() const; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index bba0895e08..0a460152d5 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -3142,25 +3142,25 @@ void LLViewerLODTexture::processTextureStats() F32 min_discard = 0.f; */ + // Use a S32 instead of a float + S32 min_discard = 0; + if (mFullWidth > max_tex_res || mFullHeight > max_tex_res) + min_discard = 1; + // Use a S32 value for the discard level - S32 discard_level = 0; - // Find the best discard that covers the entire mMaxVirtualSize of the on screen texture - for (; discard_level <= MAX_DISCARD_LEVEL; discard_level++) + S32 discard_level = min_discard; + // Find the best discard that covers the entire mMaxVirtualSize of the on screen texture (Use MAX_DISCARD_LEVEL as a max discard instead of MAX_DISCARD_LEVEL+1) + for (; discard_level < MAX_DISCARD_LEVEL; discard_level++) // [FIRE-35361] RenderMaxTextureResolution caps texture resolution lower than intended { - // If the max virtual size is greater then the current discard level, then break out of the loop and use the current discard level - if (mMaxVirtualSize > getWidth(discard_level) * getHeight(discard_level)) + // If the max virtual size is greater then or equal to the current discard level, then break out of the loop and use the current discard level + if (mMaxVirtualSize >= getWidth(discard_level) * getHeight(discard_level)) // [FIRE-35361] RenderMaxTextureResolution caps texture resolution lower than intended { break; } } - // Use a S32 instead of a float - S32 min_discard = 0; - if (mFullWidth > max_tex_res || mFullHeight > max_tex_res) - min_discard = 1; //discard_level = llclamp(discard_level, min_discard, (F32)MAX_DISCARD_LEVEL); - discard_level = llclamp(discard_level, min_discard, MAX_DISCARD_LEVEL); // Don't convert to float and back again // [FIRE-35081] // Can't go higher than the max discard level diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 632a37bae3..362f2f61a2 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -391,6 +391,7 @@ void LLViewerTextureList::dump() std::array image_counts{0}; // Double the size for higher discards from textures < 1024 (2048 can make a 7 and 4096 could make an 8) std::array size_counts{0}; // Track the 12 possible sizes (1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048) std::array discard_counts{0}; // Also need to an 1 additional as -1 is a valid discard level (not loaded by reported as a 1x1 texture) + std::array boost_counts{0}; // Track the # of textures at boost levels by 12 possible sizes // Don't Init the buffers with 0's like it's the the 1980's... // [FIRE-35081] @@ -432,7 +433,9 @@ void LLViewerTextureList::dump() S32 y_index = (S32)log2(image->getHeight()); // Convert the height into a 0 based index by taking the Log2 of the size to get the exponent of the size. (1 = 2^0, 2 = 2^1, 4 = 2^2...) size_counts[x_index + y_index * 12] += 1; // Add this texture's dimensions to the size count // Onlyuse the largest size for the texture's discard level(for non-square textures) - discard_counts[(image->getDiscardLevel() + 1) + (y_index > x_index ? y_index : x_index) * (MAX_DISCARD_LEVEL * 2 + 2)] += 1; + S32 max_dimension = (y_index > x_index ? y_index : x_index); + discard_counts[(image->getDiscardLevel() + 1) + max_dimension * (MAX_DISCARD_LEVEL * 2 + 2)] += 1; + boost_counts[image->getBoostLevel() + max_dimension * (LLViewerTexture::BOOST_MAX_LEVEL)] += 1; texture_count++; textures_close_to_camera += S32(image->getCloseToCamera()); // [FIRE-35081] @@ -510,6 +513,12 @@ void LLViewerTextureList::dump() } } + header_break = ""; + for (S32 x = 0; x < header.length(); x++) + { + header_break += "-"; + } + LL_INFOS() << header_break << LL_ENDL; LL_INFOS() << header << LL_ENDL; // Discard Level Vs Size counts header LL_INFOS() << header_break << LL_ENDL; @@ -538,6 +547,54 @@ void LLViewerTextureList::dump() LL_INFOS() << header_break << LL_ENDL; LL_INFOS() << header << LL_ENDL; // Discard Level Vs Size counts footer LL_INFOS() << header_break << LL_ENDL; + + // This is the Boost Level Vs Size counts table + header = "Boost: "; + for (S32 x = 0; x < LLViewerTexture::BOOST_MAX_LEVEL; x++) + { + std::string newValue = std::to_string(x); + header += newValue; + for (S32 tab = 0; tab <= 8 - newValue.length(); tab++) + { + header += " "; + } + } + + header_break = ""; + for (S32 x = 0; x < header.length(); x++) + { + header_break += "-"; + } + + LL_INFOS() << header_break << LL_ENDL; + LL_INFOS() << header << LL_ENDL; // Boost Level Vs Size counts header + LL_INFOS() << header_break << LL_ENDL; + + // Y Axis is the current possible max dimension of the textures (X or Y, which ever is larger is used) + for (S32 y = 0; y < 12; y++) + { + std::string newValue = std::to_string((S32)pow(2, y)); + std::string boost_count_string = "" + newValue; + for (S32 tab = 0; tab <= 8 - newValue.length(); tab++) + { + boost_count_string += " "; + } + // X Axis is the boost level starging from BOOST_NONE up to BOOST_MAX_LEVEL + for (S32 x = 0; x < (LLViewerTexture::BOOST_MAX_LEVEL); x++) + { + std::string newValue = std::to_string(boost_counts[x + y * (LLViewerTexture::BOOST_MAX_LEVEL)]); + boost_count_string += newValue; + for (S32 tab = 0; tab <= 8 - newValue.length(); tab++) + { + boost_count_string += " "; + } + } + LL_INFOS() << boost_count_string << LL_ENDL; + } + LL_INFOS() << header_break << LL_ENDL; + LL_INFOS() << header << LL_ENDL; // Boost Level Vs Size counts footer + LL_INFOS() << header_break << LL_ENDL; + // [FIRE-35081] } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index de3444ba0c..abe5b3567d 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -851,8 +851,12 @@ public: ypos += y_inc; } // disable use of glReadPixels which messes up nVidia nSight graphics debugging - static LLCachedControl debug_show_color(gSavedSettings, "DebugShowColor", false); - if (debug_show_color() && !LLRender::sNsightDebugSupport) + // + //static LLCachedControl debug_show_color(gSavedSettings, "DebugShowColor", false); + //if (debug_show_color() && !LLRender::sNsightDebugSupport) + static LLCachedControl debug_show_color(gSavedSettings, "DebugShowColor", 0); // The value is stored as a S32 and not a Bool + if (debug_show_color == 1 && !LLRender::sNsightDebugSupport) // Which causes an exception when in RelWithDebug + // { U8 color[4]; LLCoordGL coord = gViewerWindow->getCurrentMouse(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a6f4deb688..5144f95101 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5663,14 +5663,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, auto* gltf_mat = (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial(); llassert(gltf_mat == nullptr || dynamic_cast(te->getGLTFRenderMaterial()) != nullptr); - // show legacy when editing the fallback materials. - static LLCachedControl showSelectedinBP(gSavedSettings, "FSShowSelectedInBlinnPhong"); - if( gltf_mat && facep->getViewerObject()->isSelected() && showSelectedinBP ) - { - gltf_mat = nullptr; - } - // - if (gltf_mat != nullptr) { mat_id = gltf_mat->getHash(); // TODO: cache this hash @@ -6881,14 +6873,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace const LLTextureEntry* te = facep->getTextureEntry(); LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial(); - // show legacy when editing the fallback materials. - static LLCachedControl showSelectedinBP(gSavedSettings, "FSShowSelectedInBlinnPhong"); - if( gltf_mat && facep->getViewerObject()->isSelected() && showSelectedinBP ) - { - gltf_mat = nullptr; - } - // - if (hud_group && gltf_mat == nullptr) { //all hud attachments are fullbright fullbright = true; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1f95600e9a..ea8237a575 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1042,7 +1042,7 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY) // create an independent preview screen target {LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("PreviewScreenBuffer"); - mPreviewScreen.allocate(MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT, GL_RGBA); + mPreviewScreen.allocate(MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT, GL_RGBA, true); } // {LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("BakeMapBuffer");// create an independent preview screen target mBakeMap.allocate(LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH, LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT, GL_RGBA); diff --git a/indra/newview/skins/default/xui/az/floater_avatar_textures.xml b/indra/newview/skins/default/xui/az/floater_avatar_textures.xml index 28f1cf1f44..3810683448 100644 --- a/indra/newview/skins/default/xui/az/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/az/floater_avatar_textures.xml @@ -14,7 +14,7 @@ Teksturlar Teksturlar