From 7f87fcced67ee39c5e9ae90d83144c576ec52fe1 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Sat, 7 May 2022 02:12:18 -0400
Subject: [PATCH] Add depth of field focus lock

---
 .../newview/app_settings/settings_alchemy.xml | 22 ++++++
 indra/newview/llviewerwindow.cpp              |  2 +-
 indra/newview/pipeline.cpp                    | 68 ++++++++++++-------
 indra/newview/pipeline.h                      |  2 +
 .../skins/default/xui/en/menu_viewer.xml      | 12 ++++
 5 files changed, 82 insertions(+), 24 deletions(-)

diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml
index 3b3766bb1ee..bd0ad7244be 100644
--- a/indra/newview/app_settings/settings_alchemy.xml
+++ b/indra/newview/app_settings/settings_alchemy.xml
@@ -783,6 +783,28 @@
       <key>Value</key>
       <string></string>
     </map>
+	<key>RenderFocusPointLocked</key>
+	<map>
+		<key>Comment</key>
+		<string>Whether the focus point used for DoF is currently Locked in place</string>
+		<key>Persist</key>
+		<integer>0</integer>
+		<key>Type</key>
+		<string>Boolean</string>
+		<key>Value</key>
+		<integer>0</integer>
+	</map>
+	<key>RenderFocusPointFollowsPointer</key>
+	<map>
+		<key>Comment</key>
+		<string>Allows the Depth of Field focus to actively follow the mouse point</string>
+		<key>Persist</key>
+		<integer>0</integer>
+		<key>Type</key>
+		<string>Boolean</string>
+		<key>Value</key>
+		<integer>0</integer>
+	</map>
     <key>RenderSharpenMethod</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ae4c3405009..dbfe0522ec6 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -4512,7 +4512,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
 	LLVector3 mouse_world_start = mouse_point_global;
 	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
 
-	if (!LLViewerJoystick::getInstanceFast()->getOverrideCamera())
+	if (!LLViewerJoystick::getInstanceFast()->getOverrideCamera() && !gPipeline.RenderFocusPointFollowsPointer)
 	{ //always set raycast intersection to mouse_world_end unless
 		//flycam is on (for DoF effect)
 		gDebugRaycastIntersection.load3(mouse_world_end.mV);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index e5c05c4aac6..0cc60d2c501 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -195,6 +195,8 @@ F32 LLPipeline::RenderGlowWidth;
 F32 LLPipeline::RenderGlowStrength;
 bool LLPipeline::RenderDepthOfField;
 bool LLPipeline::RenderDepthOfFieldInEditMode;
+bool LLPipeline::RenderFocusPointLocked;
+bool LLPipeline::RenderFocusPointFollowsPointer;
 F32 LLPipeline::CameraFocusTransitionTime;
 F32 LLPipeline::CameraFNumber;
 F32 LLPipeline::CameraFocalLength;
@@ -648,6 +650,10 @@ void LLPipeline::init()
 	connectRefreshCachedSettingsSafe("CameraDoFResScale");
 	connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit");
 	connectRefreshCachedSettingsSafe("RenderNormalMapScale");
+	connectRefreshCachedSettingsSafe("RenderAttachedLights");
+	connectRefreshCachedSettingsSafe("RenderAttachedParticles");
+	connectRefreshCachedSettingsSafe("RenderFocusPointLocked");
+	connectRefreshCachedSettingsSafe("RenderFocusPointFollowsPointer");
 }
 
 LLPipeline::~LLPipeline()
@@ -1164,6 +1170,8 @@ void LLPipeline::refreshCachedSettings()
 	LLVOAvatar::sMaxNonImpostors = gSavedSettings.getU32("RenderAvatarMaxNonImpostors");
 	LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors);
 	LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate");
+	LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
+	LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
 
 	LLPipeline::sUseOcclusion = 
 			(!gUseWireframe
@@ -1215,6 +1223,8 @@ void LLPipeline::refreshCachedSettings()
 	RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength");
 	RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
 	RenderDepthOfFieldInEditMode = gSavedSettings.getBOOL("RenderDepthOfFieldInEditMode");
+	RenderFocusPointLocked = gSavedSettings.getBOOL("RenderFocusPointLocked");
+	RenderFocusPointFollowsPointer = gSavedSettings.getBOOL("RenderFocusPointFollowsPointer");
 	CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime");
 	CameraFNumber = gSavedSettings.getF32("CameraFNumber");
 	CameraFocalLength = gSavedSettings.getF32("CameraFocalLength");
@@ -7873,31 +7883,43 @@ void LLPipeline::renderFinalize()
                 }
             }
 
-            if (focus_point.isExactlyZero())
-            {
-                if (LLViewerJoystick::getInstanceFast()->getOverrideCamera())
-                { // focus on point under cursor
-                    focus_point.set(gDebugRaycastIntersection.getF32ptr());
-                }
-                else if (gAgentCamera.cameraMouselook())
-                { // focus on point under mouselook crosshairs
-                    LLVector4a result;
-                    result.clear();
+			// <FS:Beq> FIRE-16728 focus point lock & free focus DoF - based on a feature developed by NiranV Dean
+			static LLVector3 last_focus_point{};
+			if (LLPipeline::RenderFocusPointLocked && !last_focus_point.isExactlyZero())
+			{
+				focus_point = last_focus_point;
+			}
+			else
+			{
+				// </FS:Beq>
+				if (focus_point.isExactlyZero())
+				{
+					if (LLViewerJoystick::getInstanceFast()->getOverrideCamera() || LLPipeline::RenderFocusPointFollowsPointer)
+					{ // focus on point under cursor
+						focus_point.set(gDebugRaycastIntersection.getF32ptr());
+					}
+					else if (gAgentCamera.cameraMouselook())
+					{ // focus on point under mouselook crosshairs
+						LLVector4a result;
+						result.clear();
 
-                    gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result);
+						gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result);
 
-                    focus_point.set(result.getF32ptr());
-                }
-                else
-                {
-                    // focus on alt-zoom target
-                    LLViewerRegion *region = gAgent.getRegion();
-                    if (region)
-                    {
-                        focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal());
-                    }
-                }
-            }
+						focus_point.set(result.getF32ptr());
+					}
+					else
+					{
+						// focus on alt-zoom target
+						LLViewerRegion* region = gAgent.getRegion();
+						if (region)
+						{
+							focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal());
+						}
+					}
+				}
+			}
+
+			last_focus_point = focus_point;
 
 			const LLVector3& eye = viewerCamera.getOrigin();
             F32 target_distance = 16.f;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 905025644cc..bd36a31ae94 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -936,6 +936,8 @@ class LLPipeline
 	static F32 RenderGlowStrength;
 	static bool RenderDepthOfField;
 	static bool RenderDepthOfFieldInEditMode;
+	static bool RenderFocusPointLocked;
+	static bool RenderFocusPointFollowsPointer;
 	static F32 CameraFocusTransitionTime;
 	static F32 CameraFNumber;
 	static F32 CameraFocalLength;
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index ac795f859fb..04f416d6f07 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -920,6 +920,18 @@
                control="NavBarShowParcelProperties" />
           </menu_item_check>
           <menu_item_separator />
+          <menu_item_check
+	          label="Depth of Field Focus lock"
+	          layout="topleft"
+	          shortcut="alt|shift|X"
+	          name="lock_focus_point">
+	          <menu_item_check.on_check
+		          function="CheckControl"
+		          parameter="RenderFocusPointLocked" />
+	          <menu_item_check.on_click
+		          function="ToggleControl"
+		          parameter="RenderFocusPointLocked" />
+          </menu_item_check>
           <menu_item_check
              label="Advanced Menu"
              name="Show Advanced Menu"
-- 
GitLab