From 45e7a396a914b1d0690fc03e44f61baff31f4026 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Thu, 31 Dec 2020 03:14:20 -0500
Subject: [PATCH] Spicy mouselook zoom

---
 .../newview/app_settings/settings_alchemy.xml | 22 +++++
 .../settings_per_account_alchemy.xml          | 33 ++++---
 indra/newview/lltoolcomp.cpp                  | 86 ++++++++++++++++---
 indra/newview/lltoolcomp.h                    | 30 ++++---
 indra/newview/llviewercamera.cpp              | 10 +++
 indra/newview/llviewercamera.h                |  8 +-
 6 files changed, 155 insertions(+), 34 deletions(-)

diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml
index 7c3b814fe3a..40bccbff5b7 100644
--- a/indra/newview/app_settings/settings_alchemy.xml
+++ b/indra/newview/app_settings/settings_alchemy.xml
@@ -442,6 +442,28 @@
       <key>Value</key>
       <real>380.0</real>
     </map>
+    <key>AlchemyMouseLookZoomTime</key>
+    <map>
+      <key>Comment</key>
+      <string>Scalar for smooth mouselook zoom time</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>6.66</real>
+    </map>
+    <key>AlchemyMouseLookZoomTimeout</key>
+    <map>
+      <key>Comment</key>
+      <string>Cuttoff to force zoom to target fov</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>0.15</real>
+    </map>
     <key>AlchemyPointAtPrivate</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/app_settings/settings_per_account_alchemy.xml b/indra/newview/app_settings/settings_per_account_alchemy.xml
index 9d0267fad7d..dc1f5e71247 100644
--- a/indra/newview/app_settings/settings_per_account_alchemy.xml
+++ b/indra/newview/app_settings/settings_per_account_alchemy.xml
@@ -1,15 +1,26 @@
 <llsd>
-    <map>
+  <map>
     <key>AlchemyAOEnable</key>
-        <map>
-        <key>Comment</key>
-            <string>Use Animation Overrides</string>
-        <key>Persist</key>
-            <integer>1</integer>
-        <key>Type</key>
-            <string>Boolean</string>
-        <key>Value</key>
-            <integer>0</integer>
-        </map>
+    <map>
+      <key>Comment</key>
+      <string>Use Animation Overrides</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>AlchemyMouselookAlternativeFOV</key>
+    <map>
+      <key>Comment</key>
+      <string>Adjusted when scrolling back and forth while holding rightclick in mouselook.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>F32</string>
+      <key>Value</key>
+      <real>0.5</real>
     </map>
+  </map>
 </llsd>
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index 87defe907de..3f00422d220 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -51,8 +51,8 @@
 #include "llagentcamera.h"
 #include "llfloatertools.h"
 #include "llviewercontrol.h"
-
-extern LLControlGroup gSavedSettings;
+#include "llviewercamera.h"
+#include "lleventtimer.h"
 
 // we use this in various places instead of NULL
 static LLPointer<LLTool> sNullTool(new LLTool(std::string("null"), NULL)); 
@@ -681,6 +681,8 @@ void LLToolCompRotate::render()
 
 LLToolCompGun::LLToolCompGun()
 	: LLToolComposite(std::string("Mouselook"))
+	, mRightMouseDown(false)
+	, mTimerFOV()
 {
 	mGun = new LLToolGun(this);
 	mGrab = new LLToolGrabBase(this);
@@ -688,6 +690,9 @@ LLToolCompGun::LLToolCompGun()
 
 	setCurrentTool(mGun);
 	mDefault = mGun;
+
+	mTimerFOV.stop();
+	mStartFOV = mOriginalFOV = mTargetFOV = LLViewerCamera::getInstance()->getAndSaveDefaultFOV();
 }
 
 
@@ -776,21 +781,38 @@ BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask)
 
 BOOL LLToolCompGun::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
-	/* JC - suppress context menu 8/29/2002
+	if (!(gKeyboard->currentMask(TRUE) & MASK_ALT))
+	{
+		mRightMouseDown = true;
 
-	// On right mouse, go through some convoluted steps to
-	// make the build menu appear.
-	setCurrentTool( (LLTool*) mNull );
+		if (!mTimerFOV.getStarted())
+		{
+			mStartFOV = LLViewerCamera::getInstance()->getAndSaveDefaultFOV();
+			mOriginalFOV = mStartFOV;
+		}
+		else
+			mStartFOV = LLViewerCamera::getInstance()->getDefaultFOV();
 
-	// This should return FALSE, meaning the context menu will
-	// be shown.
-	return FALSE;
-	*/
+		mTargetFOV = gSavedPerAccountSettings.getF32("AlchemyMouselookAlternativeFOV");
+		mTimerFOV.start();
+
+		return TRUE;
+	}
 
 	// Returning true will suppress the context menu
 	return TRUE;
 }
 
+BOOL LLToolCompGun::handleRightMouseUp(S32 x, S32 y, MASK mask)
+{
+	mRightMouseDown = false;
+
+	mStartFOV = LLViewerCamera::getInstance()->getDefaultFOV();
+	mTargetFOV = mOriginalFOV;
+	mTimerFOV.start();
+
+	return TRUE;
+}
 
 BOOL LLToolCompGun::handleMouseUp(S32 x, S32 y, MASK mask)
 {
@@ -818,16 +840,56 @@ void	LLToolCompGun::handleSelect()
 void	LLToolCompGun::handleDeselect()
 {
 	LLToolComposite::handleDeselect();
+	if (mRightMouseDown || mTimerFOV.getStarted())
+	{
+		LLViewerCamera::getInstance()->loadDefaultFOV();
+		mRightMouseDown = false;
+		mTimerFOV.stop();
+	}
 	setMouseCapture(FALSE);
 }
 
 
 BOOL LLToolCompGun::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
-	if (clicks > 0)
+	if(mRightMouseDown)
 	{
-		gAgentCamera.changeCameraToDefault();
+		mStartFOV = LLViewerCamera::getInstance()->getDefaultFOV();
+
+		gSavedPerAccountSettings.setF32(
+			"AlchemyMouselookAlternativeFOV",
+			mTargetFOV = clicks > 0 ?
+				llclamp(mTargetFOV += (0.05f * clicks), 0.1f, 3.0f) :
+				llclamp(mTargetFOV -= (0.05f * -clicks), 0.1f, 3.0f)
+		);
 
+		mTimerFOV.start();
+	}
+	else if (clicks > 0)
+	{
+		gAgentCamera.changeCameraToDefault();
 	}
 	return TRUE;
 }
+
+void LLToolCompGun::draw()
+{
+	if(mTimerFOV.getStarted())
+	{
+		if(!LLViewerCamera::getInstance()->mSavedFOVLoaded && mStartFOV != mTargetFOV)
+		{
+			F32 timer = mTimerFOV.getElapsedTimeF32();
+
+			static LLCachedControl<F32> ml_zoom_timeout(gSavedSettings, "AlchemyMouseLookZoomTimeout", 0.15f);
+			static LLCachedControl<F32> ml_zoom_time(gSavedSettings, "AlchemyMouseLookZoomTime", 6.66f);
+			if(timer > ml_zoom_timeout)
+			{
+				LLViewerCamera::getInstance()->setDefaultFOV(mTargetFOV);
+				mTimerFOV.stop();
+			}
+			else LLViewerCamera::getInstance()->setDefaultFOV(lerp(mStartFOV, mTargetFOV, timer * ml_zoom_time));
+		}
+		else mTimerFOV.stop();
+	}
+	LLToolComposite::draw();
+}
diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h
index f0aa9ac76c2..4b6a32042a5 100644
--- a/indra/newview/lltoolcomp.h
+++ b/indra/newview/lltoolcomp.h
@@ -53,6 +53,7 @@ class LLToolComposite : public LLTool
     virtual BOOL			handleHover(S32 x, S32 y, MASK mask)			{ return mCur->handleHover( x, y, mask ); }
 	virtual BOOL			handleScrollWheel(S32 x, S32 y, S32 clicks)		{ return mCur->handleScrollWheel( x, y, clicks ); }
 	virtual BOOL			handleRightMouseDown(S32 x, S32 y, MASK mask)	{ return mCur->handleRightMouseDown( x, y, mask ); }
+	virtual BOOL			handleRightMouseUp(S32 x, S32 y, MASK mask)		{ return mCur->handleRightMouseUp( x, y, mask ); }
 
 	virtual LLViewerObject*	getEditingObject()								{ return mCur->getEditingObject(); }
 	virtual LLVector3d		getEditingPointGlobal()							{ return mCur->getEditingPointGlobal(); }
@@ -223,22 +224,31 @@ class LLToolCompGun final : public LLToolComposite, public LLSingleton<LLToolCom
 	virtual ~LLToolCompGun();
 public:
 
+	void			draw() override;
+
 	// Overridden from LLToolComposite
-    virtual BOOL			handleHover(S32 x, S32 y, MASK mask);
-	virtual BOOL			handleMouseDown(S32 x, S32 y, MASK mask);
-	virtual BOOL			handleDoubleClick(S32 x, S32 y, MASK mask);
-	virtual BOOL			handleRightMouseDown(S32 x, S32 y, MASK mask);
-	virtual BOOL			handleMouseUp(S32 x, S32 y, MASK mask);
-	virtual BOOL			handleScrollWheel(S32 x, S32 y, S32 clicks);
-	virtual void			onMouseCaptureLost();
-	virtual void			handleSelect();
-	virtual void			handleDeselect();
-	virtual LLTool*			getOverrideTool(MASK mask) { return NULL; }
+    BOOL			handleHover(S32 x, S32 y, MASK mask) override;
+	BOOL			handleMouseDown(S32 x, S32 y, MASK mask) override;
+	BOOL			handleDoubleClick(S32 x, S32 y, MASK mask) override;
+	BOOL			handleRightMouseDown(S32 x, S32 y, MASK mask) override;
+	BOOL			handleRightMouseUp(S32 x, S32 y, MASK mask) override;
+	BOOL			handleMouseUp(S32 x, S32 y, MASK mask) override;
+	BOOL			handleScrollWheel(S32 x, S32 y, S32 clicks) override;
+	void			onMouseCaptureLost() override;
+	void			handleSelect() override;
+	void			handleDeselect() override;
+	LLTool*			getOverrideTool(MASK mask) override { return NULL; }
 
 protected:
 	LLToolGun*			mGun;
 	LLToolGrabBase*		mGrab;
 	LLTool*				mNull;
+
+	bool				mRightMouseDown;
+	LLTimer				mTimerFOV;
+	F32				mOriginalFOV,
+					mStartFOV,
+					mTargetFOV;
 };
 
 
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index d109f2f02f8..791023eca9b 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -92,6 +92,7 @@ LLViewerCamera::LLViewerCamera() : LLCamera()
 	calcProjection(getFar());
 	mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
 	mPrevCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
+	mSavedFOVDefault = DEFAULT_FIELD_OF_VIEW;
 	mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
 	mPixelMeterRatio = 0.f;
 	mScreenPixelArea = 0;
@@ -882,6 +883,15 @@ BOOL LLViewerCamera::isDefaultFOVChanged()
 	return FALSE;
 }
 
+void LLViewerCamera::loadDefaultFOV()
+{
+	setView(mSavedFOVDefault);
+	mSavedFOVLoaded = true;
+	mCameraFOVDefault = mSavedFOVDefault; 
+	mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);
+}
+
+
 // static
 void LLViewerCamera::updateCameraAngle( void* user_data, const LLSD& value)
 {
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 103fa0c02b8..ca0dee8ecfc 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -102,11 +102,16 @@ class LLViewerCamera final : public LLCamera, public LLSingleton<LLViewerCamera>
 	LLVector3 roundToPixel(const LLVector3 &pos_agent);
 
 	// Sets the current matrix
-	/* virtual */ void setView(F32 vertical_fov_rads);
+	/* virtual */ void setView(F32 vertical_fov_rads) override;
 
 	void setDefaultFOV(F32 fov) ;
 	F32 getDefaultFOV() { return mCameraFOVDefault; }
 
+	bool mSavedFOVLoaded;
+	F32 getAndSaveDefaultFOV() { mSavedFOVLoaded = false; return mSavedFOVDefault = mCameraFOVDefault; }
+	void setAndSaveDefaultFOV(F32 fov) { mSavedFOVDefault = fov; setDefaultFOV(mSavedFOVDefault); }
+	void loadDefaultFOV();
+
 	BOOL isDefaultFOVChanged();
 
 	BOOL cameraUnderWater() const;
@@ -133,6 +138,7 @@ class LLViewerCamera final : public LLCamera, public LLSingleton<LLViewerCamera>
 	mutable LLMatrix4	mModelviewMatrix;
 	F32					mCameraFOVDefault;
 	F32					mPrevCameraFOVDefault;
+	F32					mSavedFOVDefault;
 	F32					mCosHalfCameraFOV;
 	LLVector3			mLastPointOfInterest;
 	F32					mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance.
-- 
GitLab