diff --git a/.github/workflows/deploy_only.yml b/.github/workflows/deploy_only.yml index 0923484f1d..47243942f8 100644 --- a/.github/workflows/deploy_only.yml +++ b/.github/workflows/deploy_only.yml @@ -45,7 +45,7 @@ jobs: run: pip install discord-webhook - name: Download Build Artifacts - uses: dawidd6/action-download-artifact@v7 + uses: dawidd6/action-download-artifact@v8 id: download with: workflow: build_viewer.yml diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index 6d98335165..6cf2b30f3f 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -41,7 +41,7 @@ jobs: setup_files: ${{ steps.get-files.outputs.setup_files }} steps: - name: Download Build Artifacts - uses: dawidd6/action-download-artifact@v7 + uses: dawidd6/action-download-artifact@v8 id: download with: workflow: build_viewer.yml diff --git a/.github/workflows/tag-fs-build.yml b/.github/workflows/tag-fs-build.yml index 3a3c6a0f5c..2760619cba 100644 --- a/.github/workflows/tag-fs-build.yml +++ b/.github/workflows/tag-fs-build.yml @@ -71,7 +71,7 @@ jobs: echo "build_run_number=${{ github.event.inputs.build_run_number }}" >> "$GITHUB_OUTPUT" fi - name: Download Build Artifacts - uses: dawidd6/action-download-artifact@v7 + uses: dawidd6/action-download-artifact@v8 id: download_build_info with: workflow: build_viewer.yml diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 9ae5dd1ceb..a32537357f 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1509,6 +1509,14 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("areaTex"); mReservedUniforms.push_back("searchTex"); mReservedUniforms.push_back("blendTex"); + // reserved uniforms for snapshot frame + mReservedUniforms.push_back("border_color"); + mReservedUniforms.push_back("border_thickness"); + mReservedUniforms.push_back("guide_color"); + mReservedUniforms.push_back("guide_thickness"); + mReservedUniforms.push_back("guide_style"); + mReservedUniforms.push_back("frame_rect"); + // llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 0fb67ff3df..e672b07068 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -351,6 +351,14 @@ public: SMAA_SEARCH_TEX, // "searchTex" SMAA_BLEND_TEX, // "blendTex" + // Uniforms for snapshot frame + SNAPSHOT_BORDER_COLOR, // "border_color" + SNAPSHOT_BORDER_THICKNESS, // "border_thickness" + SNAPSHOT_GUIDE_COLOR, // "guide_color" + SNAPSHOT_GUIDE_THICKNESS, // "guide_thickness" + SNAPSHOT_GUIDE_STYLE, // "guide_style" + SNAPSHOT_FRAME_RECT, // "frame_rect" + // END_RESERVED_UNIFORMS } eGLSLReservedUniforms; // clang-format on diff --git a/indra/newview/ao.cpp b/indra/newview/ao.cpp index 92c9c813e7..f0fb99875f 100644 --- a/indra/newview/ao.cpp +++ b/indra/newview/ao.cpp @@ -282,6 +282,10 @@ bool FloaterAO::postBuild() mPreviousButtonSmall->setCommitCallback(boost::bind(&FloaterAO::onClickPrevious, this)); mNextButtonSmall->setCommitCallback(boost::bind(&FloaterAO::onClickNext, this)); +// Double click on animation in AO + mAnimationList->setDoubleClickCallback(boost::bind(&FloaterAO::onDoubleClick, this)); +// + updateSmart(); AOEngine::instance().setReloadCallback(boost::bind(&FloaterAO::updateList, this)); @@ -780,6 +784,40 @@ void FloaterAO::onClickNext() AOEngine::instance().cycle(AOEngine::CycleNext); } +// Double click on animation in AO +void FloaterAO::onDoubleClick() +{ + LLScrollListItem* item = mAnimationList->getFirstSelected(); + if (!item) + { + return; + } + LLUUID* animUUID = (LLUUID*)item->getUserdata(); + if (!animUUID) + { + return; + } + + // do nothing if animation is for a different state than the active state + if (mSelectedState != AOEngine::instance().getCurrentState()) + { + return; + } + + // activate AO set if necessary + if (AOEngine::instance().getCurrentSet() != mSelectedSet) + { + // sync small set selector with main set selector + mSetSelectorSmall->selectNthItem(mSetSelector->getCurrentIndex()); + + LL_DEBUGS("AOEngine") << "Set activated: " << mSetSelector->getSelectedItemLabel() << LL_ENDL; + AOEngine::instance().selectSet(mSelectedSet); + } + + AOEngine::instance().playAnimation(*animUUID); +} +// + void FloaterAO::onClickMore() { LLRect fullSize = gSavedPerAccountSettings.getRect("floater_rect_animation_overrider_full"); diff --git a/indra/newview/ao.h b/indra/newview/ao.h index 1ef283d9c0..cadde5088c 100644 --- a/indra/newview/ao.h +++ b/indra/newview/ao.h @@ -91,6 +91,10 @@ class FloaterAO void onClickMore(); void onClickLess(); +// Double click on animation in AO + void onDoubleClick(); +// + void onAnimationChanged(const LLUUID& animation); void reloading(bool reload); diff --git a/indra/newview/aoengine.cpp b/indra/newview/aoengine.cpp index 62141ef422..33f91d556a 100644 --- a/indra/newview/aoengine.cpp +++ b/indra/newview/aoengine.cpp @@ -960,6 +960,115 @@ void AOEngine::cycle(eCycleMode cycleMode) } } +// Double click on animation in AO +void AOEngine::playAnimation(const LLUUID& animation) +{ + if (!mEnabled) + { + return; + } + + if (!mCurrentSet) + { + LL_DEBUGS("AOEngine") << "cycle without set." << LL_ENDL; + return; + } + + // do not cycle if we're sitting and sit-override is off + if (mLastMotion == ANIM_AGENT_SIT && !mCurrentSet->getSitOverride()) + { + return; + } + // do not cycle if we're standing and mouselook stand override is disabled while being in mouselook + else if (mLastMotion == ANIM_AGENT_STAND && mCurrentSet->getMouselookStandDisable() && mInMouselook) + { + return; + } + + AOSet::AOState* state = mCurrentSet->getStateByRemapID(mLastMotion); + if (!state) + { + LL_DEBUGS("AOEngine") << "cycle without state." << LL_ENDL; + return; + } + + if (!state->mAnimations.size()) + { + LL_DEBUGS("AOEngine") << "cycle without animations in state." << LL_ENDL; + return; + } + + LLViewerInventoryItem* item = gInventory.getItem(animation); + AOSet::AOAnimation anim; + anim.mName = item->LLInventoryItem::getName(); + anim.mInventoryUUID = item->getUUID(); + anim.mOriginalUUID = item->getLinkedUUID(); + anim.mAssetUUID = LLUUID::null; + + // if we can find the original animation already right here, save its asset ID, otherwise this will + // be tried again in AOSet::getAnimationForState() and/or AOEngine::cycle() + if (item->getLinkedItem()) + { + anim.mAssetUUID = item->getAssetUUID(); + } + + LLUUID newAnimation = anim.mAssetUUID; + LLUUID oldAnimation = state->mCurrentAnimationID; + + // don't do anything if the animation didn't change + if (newAnimation == oldAnimation) + { + return; + } + + mAnimationChangedSignal(LLUUID::null); + + // Searches for the index of the animation + U32 idx = -1; + for (U32 i = 0; i < state->mAnimations.size(); i++) + { + if (state->mAnimations[i].mAssetUUID == newAnimation) + { + idx = i; + break; + } + } + if (idx < 0) + { + idx = 0; + } + + state->mCurrentAnimation = idx; + state->mCurrentAnimationID = newAnimation; + if (newAnimation.notNull()) + { + LL_DEBUGS("AOEngine") << "requesting animation start for motion " << gAnimLibrary.animationName(mLastMotion) << ": " << newAnimation << LL_ENDL; + gAgent.sendAnimationRequest(newAnimation, ANIM_REQUEST_START); + mAnimationChangedSignal(state->mAnimations[state->mCurrentAnimation].mInventoryUUID); + } + else + { + LL_DEBUGS("AOEngine") << "overrider came back with NULL animation for motion " << gAnimLibrary.animationName(mLastMotion) << "." << LL_ENDL; + } + + if (oldAnimation.notNull()) + { + LL_DEBUGS("AOEngine") << "Cycling state " << state->mName << " - stopping animation " << oldAnimation << LL_ENDL; + gAgent.sendAnimationRequest(oldAnimation, ANIM_REQUEST_STOP); + gAgentAvatarp->LLCharacter::stopMotion(oldAnimation); + } +} + +const AOSet* AOEngine::getCurrentSet() const +{ + return mCurrentSet; +} +const AOSet::AOState* AOEngine::getCurrentState() const +{ + return mCurrentSet->getStateByRemapID(mLastMotion); +} +// + void AOEngine::updateSortOrder(AOSet::AOState* state) { for (U32 index = 0; index < state->mAnimations.size(); ++index) diff --git a/indra/newview/aoengine.h b/indra/newview/aoengine.h index a381d00dd3..438fe217b9 100644 --- a/indra/newview/aoengine.h +++ b/indra/newview/aoengine.h @@ -123,6 +123,12 @@ class AOEngine void cycleTimeout(const AOSet* set); void cycle(eCycleMode cycleMode); +// Double click on animation in AO + void playAnimation(const LLUUID& animation); + const AOSet* getCurrentSet() const; + const AOSet::AOState* getCurrentState() const; +// + void inMouselook(bool mouselook); void selectSet(AOSet* set); AOSet* selectSetByName(const std::string& name); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 71b5918270..fb7f6a124b 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -26124,5 +26124,68 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 + FSSnapshotShowCaptureFrame + + Comment + If enabled, masks the main screen according to the capture frame. + Persist + 1 + Type + Boolean + Value + 0 + + FSSnapshotFrameBorderColor + + Comment + The color of the border for the Snapshot frame + Persist + 1 + Type + Color3 + Value + + 0.0 + 0.0 + 0.0 + + + FSSnapshotFrameGuideColor + + Comment + The color of the Snapshot composition guides + Persist + 1 + Type + Color3 + Value + + 1.0 + 1.0 + 0.0 + + + FSSnapshotFrameBorderWidth + + Comment + The thickness of the line drawn around the snapshot frame + Persist + 1 + Type + F32 + Value + 2.0 + + FSSnapshotFrameGuideWidth + + Comment + The thickness of the lines drawn for the composition guides + Persist + 1 + Type + F32 + Value + 1.0 + diff --git a/indra/newview/app_settings/shaders/class1/post/snapshotFrameF.glsl b/indra/newview/app_settings/shaders/class1/post/snapshotFrameF.glsl new file mode 100644 index 0000000000..3f76193610 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/post/snapshotFrameF.glsl @@ -0,0 +1,78 @@ +#extension GL_ARB_texture_rectangle : enable + +out vec4 frag_color; + +uniform sampler2D diffuseRect; +uniform vec2 screen_res; +uniform vec4 frame_rect; // x, y, width, height (normalized 0->1) +uniform vec3 border_color; +uniform float border_thickness; // in pixels +uniform vec3 guide_color; +uniform float guide_thickness; // in pixels +uniform float guide_style; // 0: no guide, 1: rule of thirds, 2: golden spiral + +in vec2 vary_fragcoord; + +void main() +{ + vec4 diff = texture(diffuseRect, vary_fragcoord); + vec2 tc = vary_fragcoord * screen_res; + + // Convert normalized frame_rect to pixel values + vec4 frame_rect_px = vec4(frame_rect.x * screen_res.x, frame_rect.y * screen_res.y, frame_rect.z * screen_res.x, frame_rect.w * screen_res.y); + vec4 border_rect_px = vec4( + (frame_rect.x * screen_res.x) - border_thickness, + (frame_rect.y * screen_res.y) - border_thickness, + (frame_rect.z * screen_res.x) + border_thickness, + (frame_rect.w * screen_res.y) + border_thickness); + + // Desaturate fragments outside the snapshot frame + if (tc.x < border_rect_px.x || tc.x > border_rect_px.z || + tc.y < border_rect_px.y || tc.y > border_rect_px.w) + { + // Simple box blur + vec3 blur_color = vec3(0.0); + float blur_size = 2; + int blur_samples = 9; + + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + vec2 offset = vec2(x, y) * blur_size / screen_res; + blur_color += texture(diffuseRect, vary_fragcoord + offset).rgb; + } + } + + blur_color /= float(blur_samples); + float gray = dot(blur_color, vec3(0.299, 0.587, 0.114)); + diff.rgb = vec3(gray); + } + else + { + // Draw border around the snapshot frame + if ((tc.x >= border_rect_px.x && tc.x < frame_rect_px.x) || + (tc.x <= border_rect_px.z && tc.x > frame_rect_px.z) || + (tc.y >= border_rect_px.y && tc.y < frame_rect_px.y) || + (tc.y <= border_rect_px.w && tc.y > frame_rect_px.w)) + { + diff.rgb = mix(diff.rgb, border_color, 0.5); + } + + // Draw guide based on guide_style + if (guide_style == 1) + { + // Draw rule of thirds guide + float third_x = (frame_rect_px.z - frame_rect_px.x) / 3.0; + float third_y = (frame_rect_px.w - frame_rect_px.y) / 3.0; + if ((tc.x > frame_rect_px.x + third_x - guide_thickness && tc.x < frame_rect_px.x + third_x + guide_thickness) || + (tc.x > frame_rect_px.x + 2.0 * third_x - guide_thickness && tc.x < frame_rect_px.x + 2.0 * third_x + guide_thickness) || + (tc.y > frame_rect_px.y + third_y - guide_thickness && tc.y < frame_rect_px.y + third_y + guide_thickness) || + (tc.y > frame_rect_px.y + 2.0 * third_y - guide_thickness && tc.y < frame_rect_px.y + 2.0 * third_y + guide_thickness)) + { + diff.rgb = mix(diff.rgb, guide_color, 0.05); + } + } + } + frag_color = diff; +} \ No newline at end of file diff --git a/indra/newview/fsfloaterposer.cpp b/indra/newview/fsfloaterposer.cpp index b90705a31d..eba653938d 100644 --- a/indra/newview/fsfloaterposer.cpp +++ b/indra/newview/fsfloaterposer.cpp @@ -105,6 +105,9 @@ FSFloaterPoser::FSFloaterPoser(const LLSD& key) : LLFloater(key) 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)); } bool FSFloaterPoser::postBuild() @@ -164,7 +167,6 @@ bool FSFloaterPoser::postBuild() mToggleAdvancedPanelBtn->setValue(true); mTrackpadSensitivitySlider = getChild("trackpad_sensitivity_slider"); - mTrackpadSensitivitySlider->setValue(gSavedSettings.getF32(POSER_TRACKPAD_SENSITIVITY_SAVE_KEY)); mPoseSaveNameEditor = getChild("pose_save_name"); mPoseSaveNameEditor->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); @@ -216,6 +218,20 @@ bool FSFloaterPoser::postBuild() mResetBaseRotCbx = getChild("reset_base_rotation_on_edit_checkbox"); mResetBaseRotCbx->setCommitCallback([this](LLUICtrl*, const LLSD&) { onClickSetBaseRotZero(); }); + mTrackpadSensitivitySpnr = getChild("trackpad_sensitivity_spinner"); + mYawSpnr = getChild("limb_yaw_spinner"); + mPitchSpnr = getChild("limb_pitch_spinner"); + mRollSpnr = getChild("limb_roll_spinner"); + mUpDownSpnr = getChild("av_position_updown_spinner"); + mLeftRightSpnr = getChild("av_position_leftright_spinner"); + mInOutSpnr = getChild("av_position_inout_spinner"); + mAdvPosXSpnr = getChild("adv_posx_spinner"); + mAdvPosYSpnr = getChild("adv_posy_spinner"); + mAdvPosZSpnr = getChild("adv_posz_spinner"); + mScaleXSpnr = getChild("adv_scalex_spinner"); + mScaleYSpnr = getChild("adv_scaley_spinner"); + mScaleZSpnr = getChild("adv_scalez_spinner"); + return true; } @@ -238,7 +254,7 @@ void FSFloaterPoser::onClose(bool app_quitting) gSavedSettings.setBOOL(POSER_ADVANCEDWINDOWSTATE_SAVE_KEY, mToggleAdvancedPanelBtn->getValue().asBoolean()); if (gSavedSettings.getBOOL(POSER_STOPPOSINGWHENCLOSED_SAVE_KEY)) - stopPosingSelf(); + stopPosingAllAvatars(); LLFloater::onClose(app_quitting); } @@ -467,7 +483,7 @@ void FSFloaterPoser::onClickToggleSelectedBoneEnabled() mPoserAnimator.setPosingAvatarJoint(avatar, *item, !currentlyPosing); } - refreshRotationSliders(); + refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); refreshTextHighlightingOnJointScrollLists(); } @@ -511,7 +527,7 @@ void FSFloaterPoser::onClickFlipSelectedJoints() mPoserAnimator.reflectJoint(avatar, item); } - refreshRotationSliders(); + refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); } @@ -526,7 +542,7 @@ void FSFloaterPoser::onClickFlipPose() mPoserAnimator.flipEntirePose(avatar); - refreshRotationSliders(); + refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); } @@ -553,7 +569,7 @@ void FSFloaterPoser::onClickRecaptureSelectedBones() } setSavePosesButtonText(true); - refreshRotationSliders(); + refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); refreshTextHighlightingOnJointScrollLists(); } @@ -566,6 +582,114 @@ 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::onCommitSpinner(LLUICtrl* spinner, S32 id) +{ + if (!spinner) + return; + + auto activeTab = mJointsTabs->getCurrentPanel(); + if (!activeTab) + return; + + bool changingBodyPosition = activeTab == mPositionRotationPnl; + + 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 + { + mPosZSlider->setValue(value); + onAvatarPositionSet(); + break; + } + case 1: // av_position_leftright + { + mPosYSlider->setValue(value); + onAvatarPositionSet(); + break; + } + case 2: // av_position_inout_spinner + { + mPosXSlider->setValue(value); + onAvatarPositionSet(); + break; + } + case 3: // trackpad_sensitivity_spinner + { + 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) + 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(); + 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(); + break; + } + } +} + void FSFloaterPoser::onPoseJointsReset() { if (notDoubleClicked()) @@ -589,9 +713,9 @@ void FSFloaterPoser::onPoseJointsReset() mPoserAnimator.resetAvatarJoint(avatar, *item); } - refreshRotationSliders(); + refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); - refreshAvatarPositionSliders(); + refreshAvatarPositionSlidersAndSpinners(); } void FSFloaterPoser::onPoseMenuAction(const LLSD& param) @@ -892,20 +1016,24 @@ void FSFloaterPoser::startPosingSelf() onAvatarSelect(); } -void FSFloaterPoser::stopPosingSelf() +void FSFloaterPoser::stopPosingAllAvatars() { if (!gAgentAvatarp || gAgentAvatarp.isNull()) return; - LLVOAvatar* avatar = getAvatarByUuid(gAgentAvatarp->getID()); - if (!avatar) - return; + for (auto listItem : mAvatarSelectionScrollList->getAllData()) + { + LLScrollListCell* cell = listItem->getColumn(COL_UUID); + if (!cell) + continue; - bool arePosingSelected = mPoserAnimator.isPosingAvatar(avatar); - if (!arePosingSelected) - return; + LLUUID selectedAvatarId = cell->getValue().asUUID(); + LLVOAvatar* listAvatar = getAvatarByUuid(selectedAvatarId); + + if (mPoserAnimator.isPosingAvatar(listAvatar)) + mPoserAnimator.stopPosingAvatar(listAvatar); + } - mPoserAnimator.stopPosingAvatar(avatar); onAvatarSelect(); } @@ -1145,7 +1273,7 @@ void FSFloaterPoser::onUndoLastRotation() } enableOrDisableRedoButton(); - refreshRotationSliders(); + refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); } @@ -1169,8 +1297,8 @@ void FSFloaterPoser::onUndoLastPosition() mPoserAnimator.undoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle()); } - refreshAdvancedPositionSliders(); - refreshAvatarPositionSliders(); + refreshAdvancedPositionSlidersAndSpinners(); + refreshAvatarPositionSlidersAndSpinners(); } void FSFloaterPoser::onUndoLastScale() @@ -1193,7 +1321,7 @@ void FSFloaterPoser::onUndoLastScale() mPoserAnimator.undoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle()); } - refreshAdvancedScaleSliders(); + refreshAdvancedScaleSlidersAndSpinners(); } void FSFloaterPoser::onSetAvatarToTpose() @@ -1233,8 +1361,8 @@ void FSFloaterPoser::onResetPosition() mPoserAnimator.resetJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle()); } - refreshAdvancedPositionSliders(); - refreshAvatarPositionSliders(); + refreshAdvancedPositionSlidersAndSpinners(); + refreshAvatarPositionSlidersAndSpinners(); } void FSFloaterPoser::onResetScale() @@ -1260,7 +1388,7 @@ void FSFloaterPoser::onResetScale() mPoserAnimator.resetJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle()); } - refreshAdvancedScaleSliders(); + refreshAdvancedScaleSlidersAndSpinners(); } void FSFloaterPoser::onRedoLastRotation() @@ -1284,7 +1412,7 @@ void FSFloaterPoser::onRedoLastRotation() } enableOrDisableRedoButton(); - refreshRotationSliders(); + refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); } @@ -1308,8 +1436,8 @@ void FSFloaterPoser::onRedoLastPosition() mPoserAnimator.redoLastJointPosition(avatar, *item, getUiSelectedBoneDeflectionStyle()); } - refreshAdvancedPositionSliders(); - refreshAvatarPositionSliders(); + refreshAdvancedPositionSlidersAndSpinners(); + refreshAvatarPositionSlidersAndSpinners(); } void FSFloaterPoser::onRedoLastScale() @@ -1332,7 +1460,7 @@ void FSFloaterPoser::onRedoLastScale() mPoserAnimator.redoLastJointScale(avatar, *item, getUiSelectedBoneDeflectionStyle()); } - refreshAdvancedScaleSliders(); + refreshAdvancedScaleSlidersAndSpinners(); } void FSFloaterPoser::enableOrDisableRedoButton() @@ -1565,8 +1693,15 @@ void FSFloaterPoser::onAdvancedPositionSet() F32 posY = mAdvPosYSlider->getValueF32(); F32 posZ = mAdvPosZSlider->getValueF32(); + mAdvPosXSpnr->setValue(posX); + mInOutSpnr->setValue(posX); + mAdvPosYSpnr->setValue(posY); + mLeftRightSpnr->setValue(posY); + mAdvPosZSpnr->setValue(posZ); + mUpDownSpnr->setValue(posZ); + setSelectedJointsPosition(posX, posY, posZ); - refreshAvatarPositionSliders(); + refreshAvatarPositionSlidersAndSpinners(); } void FSFloaterPoser::onAdvancedScaleSet() @@ -1575,6 +1710,10 @@ void FSFloaterPoser::onAdvancedScaleSet() F32 scY = mAdvScaleYSlider->getValueF32(); F32 scZ = mAdvScaleZSlider->getValueF32(); + mScaleXSpnr->setValue(scX); + mScaleYSpnr->setValue(scY); + mScaleZSpnr->setValue(scZ); + setSelectedJointsScale(scX, scY, scZ); } @@ -1584,8 +1723,15 @@ void FSFloaterPoser::onAvatarPositionSet() 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); + setSelectedJointsPosition(posX, posY, posZ); - refreshAdvancedPositionSliders(); + refreshAdvancedPositionSlidersAndSpinners(); } void FSFloaterPoser::onLimbTrackballChanged() @@ -1624,6 +1770,10 @@ void FSFloaterPoser::onLimbTrackballChanged() 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()); } F32 FSFloaterPoser::unWrapScale(F32 scale) @@ -1665,11 +1815,14 @@ 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() { - gSavedSettings.setF32(POSER_TRACKPAD_SENSITIVITY_SAVE_KEY, mTrackpadSensitivitySlider->getValueF32()); refreshTrackpadCursor(); } @@ -1689,7 +1842,7 @@ void FSFloaterPoser::refreshTrackpadCursor() /// /// This only sets the position sliders of the 'basic' view (not the advanced sliders). /// -void FSFloaterPoser::refreshAvatarPositionSliders() +void FSFloaterPoser::refreshAvatarPositionSlidersAndSpinners() { auto activeTab = mJointsTabs->getCurrentPanel(); if (!activeTab) @@ -1700,36 +1853,48 @@ void FSFloaterPoser::refreshAvatarPositionSliders() 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::refreshRotationSliders() +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]); } -void FSFloaterPoser::refreshAdvancedPositionSliders() +void FSFloaterPoser::refreshAdvancedPositionSlidersAndSpinners() { LLVector3 position = getPositionOfFirstSelectedJoint(); mAdvPosXSlider->setValue(position.mV[VX]); + mAdvPosXSpnr->setValue(position.mV[VX]); mAdvPosYSlider->setValue(position.mV[VY]); + mAdvPosYSpnr->setValue(position.mV[VY]); mAdvPosZSlider->setValue(position.mV[VZ]); + mAdvPosZSpnr->setValue(position.mV[VZ]); } -void FSFloaterPoser::refreshAdvancedScaleSliders() +void FSFloaterPoser::refreshAdvancedScaleSlidersAndSpinners() { LLVector3 rotation = getScaleOfFirstSelectedJoint(); mAdvScaleXSlider->setValue(rotation.mV[VX]); + mScaleXSpnr->setValue(rotation.mV[VX]); mAdvScaleYSlider->setValue(rotation.mV[VY]); + mScaleYSpnr->setValue(rotation.mV[VY]); mAdvScaleZSlider->setValue(rotation.mV[VZ]); + mScaleZSpnr->setValue(rotation.mV[VZ]); } void FSFloaterPoser::setSelectedJointsPosition(F32 x, F32 y, F32 z) @@ -1873,16 +2038,16 @@ LLVector3 FSFloaterPoser::getScaleOfFirstSelectedJoint() const void FSFloaterPoser::onJointTabSelect() { - refreshAvatarPositionSliders(); - refreshRotationSliders(); + refreshAvatarPositionSlidersAndSpinners(); + refreshRotationSlidersAndSpinners(); refreshTrackpadCursor(); enableOrDisableRedoButton(); onClickSetBaseRotZero(); if (mToggleAdvancedPanelBtn->getValue().asBoolean()) { - refreshAdvancedPositionSliders(); - refreshAdvancedScaleSliders(); + refreshAdvancedPositionSlidersAndSpinners(); + refreshAdvancedScaleSlidersAndSpinners(); } } @@ -2074,7 +2239,7 @@ void FSFloaterPoser::onAvatarsRefresh() LLAvatarName av_name; std::string animeshName = getControlAvatarName(avatar); if (animeshName.empty()) - animeshName = avatar->getFullname(); + continue; LLSD row; row["columns"][COL_ICON]["column"] = "icon"; @@ -2109,6 +2274,9 @@ std::string FSFloaterPoser::getControlAvatarName(const LLControlAvatar* avatar) if (attachedItem) return attachedItem->getName(); + if (rootEditObject->permYouOwner()) + return avatar->getFullname(); + return ""; } @@ -2146,24 +2314,6 @@ void FSFloaterPoser::setSavePosesButtonText(bool setAsSaveDiff) setAsSaveDiff ? mSavePosesBtn->setLabel("Save Diff") : mSavePosesBtn->setLabel("Save Pose"); } -bool FSFloaterPoser::posingAnyoneOnScrollList() -{ - for (auto listItem : mAvatarSelectionScrollList->getAllData()) - { - LLScrollListCell* cell = listItem->getColumn(COL_UUID); - if (!cell) - continue; - - LLUUID selectedAvatarId = cell->getValue().asUUID(); - LLVOAvatar* listAvatar = getAvatarByUuid(selectedAvatarId); - - if (mPoserAnimator.isPosingAvatar(listAvatar)) - return true; - } - - return false; -} - void FSFloaterPoser::addBoldToScrollList(LLScrollListCtrl* list, LLVOAvatar* avatar) { if (!avatar) diff --git a/indra/newview/fsfloaterposer.h b/indra/newview/fsfloaterposer.h index f847fb587a..bd8e4c09db 100644 --- a/indra/newview/fsfloaterposer.h +++ b/indra/newview/fsfloaterposer.h @@ -236,7 +236,7 @@ class FSFloaterPoser : public LLFloater void enableOrDisableRedoButton(); void onPoseStartStop(); void startPosingSelf(); - void stopPosingSelf(); + void stopPosingAllAvatars(); void onLimbTrackballChanged(); void onYawPitchRollSliderChanged(); void onAvatarPositionSet(); @@ -253,13 +253,15 @@ class FSFloaterPoser : public LLFloater void onClickLoadRightHandPose(); void onClickLoadHandPose(bool isRightHand); void onClickSetBaseRotZero(); + //void onCommitSpinner(LLUICtrl* spinner); + void onCommitSpinner(LLUICtrl* spinner, S32 ID); // UI Refreshments - void refreshRotationSliders(); - void refreshAvatarPositionSliders(); + void refreshRotationSlidersAndSpinners(); + void refreshAvatarPositionSlidersAndSpinners(); void refreshTrackpadCursor(); - void refreshAdvancedPositionSliders(); - void refreshAdvancedScaleSliders(); + void refreshAdvancedPositionSlidersAndSpinners(); + void refreshAdvancedScaleSlidersAndSpinners(); /// /// Determines if we have permission to animate the supplied avatar. @@ -328,11 +330,6 @@ class FSFloaterPoser : public LLFloater /// Whether to indicate a diff will be saved, instead of a pose. void setSavePosesButtonText(bool setAsSaveDiff); - /// - /// Gets whether any avatar know by the UI is being posed. - /// - bool posingAnyoneOnScrollList(); - /// /// Applies the appropriate font-face (such as bold) to the text of the supplied list, to indicate use. /// @@ -501,6 +498,20 @@ class FSFloaterPoser : public LLFloater LLCheckBoxCtrl* mResetBaseRotCbx{ nullptr }; LLCheckBoxCtrl* mAlsoSaveBvhCbx{ nullptr }; + + LLUICtrl* mTrackpadSensitivitySpnr{ nullptr }; + LLUICtrl* mYawSpnr{ nullptr }; + LLUICtrl* mPitchSpnr{ nullptr }; + LLUICtrl* mRollSpnr{ nullptr }; + LLUICtrl* mUpDownSpnr{ nullptr }; + LLUICtrl* mLeftRightSpnr{ nullptr }; + LLUICtrl* mInOutSpnr{ nullptr }; + LLUICtrl* mAdvPosXSpnr{ nullptr }; + LLUICtrl* mAdvPosYSpnr{ nullptr }; + LLUICtrl* mAdvPosZSpnr{ nullptr }; + LLUICtrl* mScaleXSpnr{ nullptr }; + LLUICtrl* mScaleYSpnr{ nullptr }; + LLUICtrl* mScaleZSpnr{ nullptr }; }; #endif diff --git a/indra/newview/installers/darwin/apple-notarize.sh b/indra/newview/installers/darwin/apple-notarize.sh index c8ff10df5c..edaeb95896 100755 --- a/indra/newview/installers/darwin/apple-notarize.sh +++ b/indra/newview/installers/darwin/apple-notarize.sh @@ -28,11 +28,35 @@ if [[ -f "$CONFIG_FILE" ]]; then echo "Notarized with id: [$match]" else echo "No match found" + exit 1 fi - # if [[ ! $match -eq 0 ]]; then - echo "Running Stapler" - xcrun stapler staple "$app_file" + # --- WAIT / RETRY LOGIC FOR STAPLER --- + # Try stapler up to 5 times with a 5-second delay in between attempts + max_attempts=5 + sleep_seconds=5 + attempt=1 + + while [[ $attempt -le $max_attempts ]]; do + echo "Running stapler (attempt $attempt of $max_attempts)..." + xcrun stapler staple "$app_file" + ret=$? + + if [[ $ret -eq 0 ]]; then + echo "Stapling succeeded on attempt $attempt" + break + else + if [[ $attempt -lt $max_attempts ]]; then + echo "Stapling failed (Error $ret). Waiting $sleep_seconds seconds before retry..." + sleep $sleep_seconds + else + echo "Stapling failed after $max_attempts attempts, giving up." + exit 65 + fi + fi + attempt=$((attempt + 1)) + done + # Delete the zip file to stop it being packed in the dmg rm -f "$zip_file" if [[ $? -eq 0 ]]; then diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi index f514a937eb..332c1c689c 100755 Binary files a/indra/newview/installers/windows/lang_zh.nsi and b/indra/newview/installers/windows/lang_zh.nsi differ diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index eb3f7c3109..39e5ea7af3 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -103,6 +103,10 @@ echo "LIBGL_DRIVERS_PATH is ${LIBGL_DRIVERS_PATH}" if [ "$GTK_IM_MODULE" = "scim" ]; then export GTK_IM_MODULE=xim fi +if [ "$XMODIFIERS" = "" ]; then + ## IME is valid only for fcitx, not when using ibus + export XMODIFIERS="@im=fcitx" +fi ## - Automatically work around the ATI mouse cursor crash bug: ## (this workaround is disabled as most fglrx users do not see the bug) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index a9c740eec5..3feb484135 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1098,15 +1098,20 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it const LLWearableType::EType type = new_wearable->getType(); // BOM fallback legacy opensim - if(!gAgent.getRegion()->bakesOnMeshEnabled()) + #ifdef OPENSIM + if (!LLGridManager::getInstance()->isInSecondLife()) { - if(type == LLWearableType::WT_UNIVERSAL) + if(!gAgent.getRegion()->bakesOnMeshEnabled()) { - LL_DEBUGS("Avatar") << "Universal wearable not supported on this region - ignoring." << LL_ENDL; - mismatched++; - continue; + if(type == LLWearableType::WT_UNIVERSAL) + { + LL_DEBUGS("Avatar") << "Universal wearable not supported on this region - ignoring." << LL_ENDL; + mismatched++; + continue; + } } } + #endif // if (type < 0 || type>=LLWearableType::WT_COUNT) { diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 2c6cca1a68..64d0c9c935 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -966,3 +966,13 @@ void LLFloaterFlickr::onOpen(const LLSD& key) mFlickrPhotoPanel->onOpen(key); } // +// Add snapshot frame support to flickr +LLSnapshotLivePreview* LLFloaterFlickr::getPreviewView() +{ + if(mFlickrPhotoPanel) + { + return mFlickrPhotoPanel->getPreviewView(); + } + return nullptr; +} +// \ No newline at end of file diff --git a/indra/newview/llfloaterflickr.h b/indra/newview/llfloaterflickr.h index 400674f390..e0579ba870 100644 --- a/indra/newview/llfloaterflickr.h +++ b/indra/newview/llfloaterflickr.h @@ -134,6 +134,7 @@ public: // Exodus' flickr upload void onOpen(const LLSD& key); + LLSnapshotLivePreview* getPreviewView(); // Required for snapshot frame rendering private: LLFlickrPhotoPanel* mFlickrPhotoPanel; diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 0354021776..752a19b7c7 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1480,12 +1480,14 @@ bool LLFloaterSnapshot::isWaitingState() return (impl->getStatus() == ImplBase::STATUS_WORKING); } -bool LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized) +// FIRE-35002 - Post to flickr broken, improved solution +// bool LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized) +bool LLFloaterSnapshotBase::ImplBase::updatePreviewList(bool initialized, bool have_flickr) +// { // Share to Flickr //if (!initialized) - LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance("flickr"); - if (!initialized && !floater_flickr) + if (!initialized && !have_flickr) // return false; @@ -1504,8 +1506,11 @@ void LLFloaterSnapshotBase::ImplBase::updateLivePreview() { // don't update preview for hidden floater // FIRE-35002 - Post to flickr broken - // if (mFloater && mFloater->isInVisibleChain() && ImplBase::updatePreviewList(true)) - if (ImplBase::updatePreviewList(true) && mFloater) + LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance("flickr"); + auto have_flickr = floater_flickr != nullptr; + if ( ((mFloater && mFloater->isInVisibleChain()) || + have_flickr) && + ImplBase::updatePreviewList(true, have_flickr)) // { LL_DEBUGS() << "changed" << LL_ENDL; diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index c90f9a3e3c..1fc101848c 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -122,7 +122,7 @@ public: virtual EStatus getStatus() const { return mStatus; } virtual void setNeedRefresh(bool need); - static bool updatePreviewList(bool initialized); + static bool updatePreviewList(bool initialized, bool have_flickr = false); // FIRE-35002 - Post to flickr broken, improved solution void setAdvanced(bool advanced) { mAdvanced = advanced; } void setSkipReshaping(bool skip) { mSkipReshaping = skip; } diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index ddd3893bc4..fa1f800952 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -129,16 +129,12 @@ void LLHUDText::render() // If the current text object is highighed and the use hover highlight feature is enabled, then // disable writing to the depth buffer static LLCachedControl mbUseHoverHighlight(gSavedSettings, "FSHudTextUseHoverHighlight"); - if (mbUseHoverHighlight && mbIsHighlighted) - { - LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); - } - //Else, use the standard method of writing to the depth buffer for all other non-highlighted text objects - else - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - } - // [FIRE-35019] + // [FIRE-35102] - Hover text appearing through walls in Beta 7.1.12.7737 + // So it turns out when the LLGLDepthTest object goes out of scope, it reverts back + // to the previous state. So by having the LLGLDepthTest in the if statements, they were + // never applied. + LLGLDepthTest gls_depth(mbUseHoverHighlight && mbIsHighlighted ? GL_FALSE : GL_TRUE, GL_FALSE); + // [FIRE-35019] [FIRE-35102] //LLGLDisable gls_stencil(GL_STENCIL_TEST); renderText(); } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index bec3cd181b..be87303f36 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -3978,7 +3978,7 @@ bool LLViewerRegion::meshUploadEnabled() const bool LLViewerRegion::bakesOnMeshEnabled() const { - return (mSimulatorFeatures.has("BakesOnMeshEnabled") && + return (mSimulatorFeaturesReceived && mSimulatorFeatures.has("BakesOnMeshEnabled") && // FIRE-35111 (bugsplat) checking bakes on mesh feature before features received. mSimulatorFeatures["BakesOnMeshEnabled"].asBoolean()); } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 9b845cc6a1..983ae58df1 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -137,6 +137,7 @@ LLGLSLShader gGlowProgram; LLGLSLShader gGlowExtractProgram; LLGLSLShader gPostScreenSpaceReflectionProgram; LLGLSLShader gPostVignetteProgram; // Import Vignette from Exodus +LLGLSLShader gPostSnapshotFrameProgram; // Add Snapshot frame guide // Deferred rendering shaders LLGLSLShader gDeferredImpostorProgram; @@ -1033,6 +1034,7 @@ bool LLViewerShaderMgr::loadShadersEffects() gGlowProgram.unload(); gGlowExtractProgram.unload(); gPostVignetteProgram.unload(); // Import Vignette from Exodus + gPostSnapshotFrameProgram.unload(); // Add Snapshot framing shader return true; } @@ -1084,6 +1086,17 @@ bool LLViewerShaderMgr::loadShadersEffects() success = gPostVignetteProgram.createShader(); } // +// Add Snapshot framing shader + if (success) + { + gPostSnapshotFrameProgram.mName = "Snapshot Frame Post"; + gPostSnapshotFrameProgram.mShaderFiles.clear(); + gPostSnapshotFrameProgram.mShaderFiles.push_back(make_pair("post/exoPostBaseV.glsl", GL_VERTEX_SHADER)); + gPostSnapshotFrameProgram.mShaderFiles.push_back(make_pair("post/snapshotFrameF.glsl", GL_FRAGMENT_SHADER)); + gPostSnapshotFrameProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; + success = gPostSnapshotFrameProgram.createShader(); + } +// return success; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 8dca7c7622..f10fd9b3c1 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -214,6 +214,7 @@ extern LLGLSLShader gImpostorProgram; // Post Process Shaders extern LLGLSLShader gPostScreenSpaceReflectionProgram; extern LLGLSLShader gPostVignetteProgram; // Import Vignette from Exodus +extern LLGLSLShader gPostSnapshotFrameProgram; // Snapshot Frame overlay // Deferred rendering shaders extern LLGLSLShader gDeferredImpostorProgram; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 2e0db84afd..1b938944b4 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -109,6 +109,9 @@ #include "llfloaterpathfindingconsole.h" #include "llfloaterpathfindingcharacters.h" #include "llfloatertools.h" +#include "llfloatersnapshot.h" // for snapshotFrame +#include "llfloaterflickr.h" // for snapshotFrame +#include "llsnapshotlivepreview.h" // for snapshotFrame // #include "llpanelface.h" // switchable edit texture/materials panel - include not needed #include "llpathfindingpathtool.h" #include "llscenemonitor.h" @@ -7872,7 +7875,7 @@ void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst) } // updated Vignette code (based on original Exo Vignette) -void LLPipeline::renderVignette(LLRenderTarget* src, LLRenderTarget* dst) +bool LLPipeline::renderVignette(LLRenderTarget* src, LLRenderTarget* dst) { if (RenderVignette.mV[0] > 0.f) { @@ -7909,14 +7912,166 @@ void LLPipeline::renderVignette(LLRenderTarget* src, LLRenderTarget* dst) shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); shader->unbind(); dst->flush(); + return true; } else { - copyRenderTarget(src, dst); + return false; } } // +// Render Snapshot frame oerlay +bool LLPipeline::renderSnapshotFrame(LLRenderTarget* src, LLRenderTarget* dst) +{ + static LLCachedControl show_frame(gSavedSettings, "FSSnapshotShowCaptureFrame", false); + static LLCachedControl show_guides(gSavedSettings, "FSSnapshotShowGuides", false); + + float left = 0.f; + float top = 0.f; + float right = 1.f; + float bottom = 1.f; + + // TODO - add debug settings to control the appearance of the snapshot frameand guides + static LLCachedControl border_color(gSavedSettings, "FSSnapshotFrameBorderColor", LLColor3(1.f, 0.f, 0.f)); + static LLCachedControl guide_color(gSavedSettings, "FSSnapshotFrameGuideColor", LLColor3(1.f, 1.f, 0.f)); + static LLCachedControl border_thickness(gSavedSettings, "FSSnapshotFrameBorderWidth", 2.0f); + static LLCachedControl guide_thickness(gSavedSettings, "FSSnapshotFrameGuideWidth", 2.0f); + + F32 guide_style = 1.f; // 0:off, 1:rule_of_thirds, others maybe in the future + if (!show_guides) + { + guide_style = 0.f; + } + const bool simple_snapshot_visible = LLFloaterReg::instanceVisible("simple_snapshot"); + const bool flickr_snapshot_visible = LLFloaterReg::instanceVisible("flickr"); + const bool snapshot_visible = LLFloaterReg::instanceVisible("snapshot"); + const bool any_snapshot_visible = simple_snapshot_visible || flickr_snapshot_visible || snapshot_visible; + if (!show_frame || !any_snapshot_visible || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + return false; + + } + LLSnapshotLivePreview * previewView = nullptr; + if (snapshot_visible) + { + auto * floater =dynamic_cast(LLFloaterReg::findInstance("snapshot")); + previewView = floater->impl->getPreviewView(); + } + // Note: simple_snapshot not supported as there can be more than one active and more complex selection is required + if (flickr_snapshot_visible && !previewView) + { + auto * floater = dynamic_cast(LLFloaterReg::findInstance("flickr")); + previewView = floater->getPreviewView(); + } + if(!previewView) + { + return false; + } + + static LLCachedControl keep_aspect(gSavedSettings, "KeepAspectForSnapshot", false); + + S32 snapshot_width; + S32 snapshot_height; + previewView->getSize(snapshot_width, snapshot_height); + F32 screen_aspect = float(gViewerWindow->getWindowWidthRaw()) / float(gViewerWindow->getWindowHeightRaw()); + F32 snapshot_aspect = float(snapshot_width) / float(snapshot_height); + + if (keep_aspect || (std::fabs(screen_aspect - snapshot_aspect) < 1e-6f) ) + { + top = 0.0f; + left = 0.0f; + bottom = 1.0f; + right = 1.0f; + } + + float w = screen_aspect; + float h = 1.0; + if (snapshot_aspect > screen_aspect) + { + float frame_width = w; + float frame_height = frame_width / snapshot_aspect; + // Centre this box in [0..1]×[0..1] + float y_offset = 0.5f * (h - frame_height); + left = 0.f; + top = y_offset / h; + right = 1.f; + bottom = (y_offset + frame_height) / h; + } + else + { + float frame_height = h; + float frame_width = h * snapshot_aspect; + // Centre this box in [0..1]×[0..1] + float x_offset = 0.5f * (w - frame_width); + left = x_offset / w; + top = 0.f; + right = (x_offset + frame_width) / w; + bottom = 1.f; + + } + LL_PROFILE_GPU_ZONE("Snapshot Frame"); + dst->bindTarget(); + LLGLSLShader *shader = &gPostSnapshotFrameProgram; + + // bind the program and output to screentriangle VBO + shader->bind(); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); + if (channel > -1) + { + src->bindTexture(0, channel, LLTexUnit::TFO_POINT); + } + else + { + LL_ERRS("snapshot_frame") << "Failed to bind diffuse texture" << LL_ENDL; + } + + shader->uniform2f( + LLShaderMgr::DEFERRED_SCREEN_RES, + (GLfloat)dst->getWidth(), + (GLfloat)dst->getHeight()); + + // Assuming frame_rect is a static or accessible variable containing the frame dimensions + shader->uniform4f( + LLShaderMgr::SNAPSHOT_FRAME_RECT, + (GLfloat)left, + (GLfloat)top, + (GLfloat)right, + (GLfloat)bottom); + + shader->uniform3fv( + LLShaderMgr::SNAPSHOT_BORDER_COLOR, + 1, + border_color().mV); + + shader->uniform1f( + LLShaderMgr::SNAPSHOT_BORDER_THICKNESS, + (GLfloat)border_thickness); + + shader->uniform3fv( + LLShaderMgr::SNAPSHOT_GUIDE_COLOR, + 1, + guide_color().mV); + + shader->uniform1f( + LLShaderMgr::SNAPSHOT_GUIDE_THICKNESS, + (GLfloat)guide_thickness); + shader->uniform1f( + LLShaderMgr::SNAPSHOT_GUIDE_STYLE, + (GLfloat)guide_style); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + stop_glerror(); + + shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); + shader->unbind(); + dst->flush(); + return true; +} +// + void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) { { @@ -8217,8 +8372,23 @@ void LLPipeline::renderFinalize() targetBuffer = params.m_pSrcBuffer; } // [/RLVa:KB] - renderVignette(activeBuffer, targetBuffer); - finalBuffer = targetBuffer; + + if (renderVignette(activeBuffer, targetBuffer)) + { + auto prevActiveBuffer = activeBuffer; + activeBuffer = targetBuffer; + targetBuffer = prevActiveBuffer; + }; + // + // new shader for snapshot frame helper + if (renderSnapshotFrame(targetBuffer, activeBuffer)) + { + auto prevActiveBuffer = activeBuffer; + activeBuffer = targetBuffer; + targetBuffer = prevActiveBuffer; + }; + + finalBuffer = activeBuffer; // if (RenderBufferVisualization > -1) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 3b50453c40..5343dccfba 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -348,7 +348,8 @@ public: void renderShadow(const glm::mat4& view, const glm::mat4& proj, LLCamera& camera, LLCullResult& result, bool depth_clamp); void renderSelectedFaces(const LLColor4& color); void renderHighlights(); - void renderVignette(LLRenderTarget* src, LLRenderTarget* dst); + bool renderVignette(LLRenderTarget* src, LLRenderTarget* dst); + bool renderSnapshotFrame(LLRenderTarget* src, LLRenderTarget* dst); // Add snapshot frame rendering void renderDebug(); void renderPhysicsDisplay(); diff --git a/indra/newview/skins/default/xui/de/floater_fs_poser.xml b/indra/newview/skins/default/xui/de/floater_fs_poser.xml index 2119dfb5a5..4d2b073034 100644 --- a/indra/newview/skins/default/xui/de/floater_fs_poser.xml +++ b/indra/newview/skins/default/xui/de/floater_fs_poser.xml @@ -235,7 +235,7 @@ @@ -1419,7 +1574,7 @@ width="403"> image_unselected="Toolbar_Middle_Off" name="redo_position_change" tool_tip="Redo the last position change" - width="110" + width="108" top_delta="0" left_pad="4"> image_unselected="Toolbar_Middle_Off" name="reset_positions" tool_tip="Double click to reset position back to original" - width="110" + width="109" top_delta="0" left_pad="4"> + top_pad="2" + width="342" > + + + + width="342" > + + + + width="342" > + + + @@ -1535,7 +1738,7 @@ width="403"> image_unselected="Toolbar_Middle_Off" name="redo_scale_change" tool_tip="Redo the last scale change" - width="110" + width="108" top_delta="0" left_pad="4"> image_unselected="Toolbar_Middle_Off" name="reset_scales" tool_tip="Double click to reset scale back to original" - width="110" + width="109" top_delta="0" left_pad="4"> + + Refreshing... + +