From d61601289110b0e406e70bf65ced2c4a1e110760 Mon Sep 17 00:00:00 2001
From: andreykproductengine <andreykproductengine@lindenlab.com>
Date: Tue, 1 Oct 2019 20:35:59 +0300
Subject: [PATCH] SL-6109 Implemented LLDrawFrustum

---
 indra/newview/CMakeLists.txt                |   2 +
 indra/newview/lldrawfrustum.cpp             | 113 ++++++++++++++++++++
 indra/newview/lldrawfrustum.h               |  55 ++++++++++
 indra/newview/llfloateravatarpicker.cpp     |  75 +------------
 indra/newview/llfloateravatarpicker.h       |   9 +-
 indra/newview/llfloatercolorpicker.cpp      |  59 +---------
 indra/newview/llfloatercolorpicker.h        |  11 +-
 indra/newview/llfloaterexperiencepicker.cpp |  72 +------------
 indra/newview/llfloaterexperiencepicker.h   |  10 +-
 indra/newview/lltexturectrl.cpp             |  62 +----------
 indra/newview/lltexturectrl.h               |   6 +-
 11 files changed, 194 insertions(+), 280 deletions(-)
 create mode 100644 indra/newview/lldrawfrustum.cpp
 create mode 100644 indra/newview/lldrawfrustum.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 9a72fcc228d..a35d0cba50d 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -179,6 +179,7 @@ set(viewer_SOURCE_FILES
     lldonotdisturbnotificationstorage.cpp
     lldndbutton.cpp
     lldrawable.cpp
+    lldrawfrustum.cpp
     lldrawpool.cpp
     lldrawpoolalpha.cpp
     lldrawpoolavatar.cpp
@@ -807,6 +808,7 @@ set(viewer_HEADER_FILES
     lldonotdisturbnotificationstorage.h
     lldndbutton.h
     lldrawable.h
+    lldrawfrustum.h
     lldrawpool.h
     lldrawpoolalpha.h
     lldrawpoolavatar.h
diff --git a/indra/newview/lldrawfrustum.cpp b/indra/newview/lldrawfrustum.cpp
new file mode 100644
index 00000000000..1d583223c8d
--- /dev/null
+++ b/indra/newview/lldrawfrustum.cpp
@@ -0,0 +1,113 @@
+/** 
+* @file lldrawfrustum.cpp
+* @brief Implementation of lldrawfrustum
+*
+* $LicenseInfo:firstyear=2019&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2019, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldrawfrustum.h"
+
+#include "llviewercontrol.h"
+
+LLDrawFrustum::LLDrawFrustum()
+    : mContextConeOpacity(0.f)
+{
+    mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha"); // 0.0f
+    mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha"); // 1.f
+    mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime"); // 0.08f
+}
+
+LLDrawFrustum::LLDrawFrustum(LLView *origin)
+    : mContextConeOpacity(0.f)
+{
+    mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
+    mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
+    mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
+    setFrustumOrigin(origin);
+}
+
+void LLDrawFrustum::setFrustumOrigin(LLView *origin)
+{
+    if (origin)
+    {
+        mFrustumOrigin = origin->getHandle();
+    }
+}
+
+void LLDrawFrustum::drawFrustum(const LLRect &derived_local_rect, const LLView *root_view, const LLView *drag_handle, bool has_focus)
+{
+    if (mFrustumOrigin.get())
+    {
+        LLView * frustumOrigin = mFrustumOrigin.get();
+        LLRect origin_rect;
+        frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, root_view);
+        // draw context cone connecting derived floater (ex: color picker) with view (ex: color swatch) in parent floater
+        if (has_focus && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
+        {
+            gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+            LLGLEnable(GL_CULL_FACE);
+            gGL.begin(LLRender::QUADS);
+            {
+                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
+                gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
+                gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
+                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
+                gGL.vertex2i(derived_local_rect.mRight, derived_local_rect.mTop);
+                gGL.vertex2i(derived_local_rect.mLeft, derived_local_rect.mTop);
+
+                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
+                gGL.vertex2i(derived_local_rect.mLeft, derived_local_rect.mTop);
+                gGL.vertex2i(derived_local_rect.mLeft, derived_local_rect.mBottom);
+                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
+                gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
+                gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
+
+                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
+                gGL.vertex2i(derived_local_rect.mRight, derived_local_rect.mBottom);
+                gGL.vertex2i(derived_local_rect.mRight, derived_local_rect.mTop);
+                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
+                gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
+                gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
+
+                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
+                gGL.vertex2i(derived_local_rect.mLeft, derived_local_rect.mBottom);
+                gGL.vertex2i(derived_local_rect.mRight, derived_local_rect.mBottom);
+                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
+                gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
+                gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
+            }
+            gGL.end();
+        }
+
+        if (gFocusMgr.childHasMouseCapture(drag_handle))
+        {
+            mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime));
+        }
+        else
+        {
+            mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime));
+        }
+    }
+}
+
diff --git a/indra/newview/lldrawfrustum.h b/indra/newview/lldrawfrustum.h
new file mode 100644
index 00000000000..f6f62d737c3
--- /dev/null
+++ b/indra/newview/lldrawfrustum.h
@@ -0,0 +1,55 @@
+/** 
+* @file   lldrawfrustum.h
+* @brief  Header file for lldrawfrustum
+*
+* $LicenseInfo:firstyear=2019&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2019, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLDRAWFRUSTUM_H
+#define LL_LLDRAWFRUSTUM_H
+
+#include "llview.h" 
+
+class LLDrawFrustum
+{
+public:
+    LLDrawFrustum();
+    LLDrawFrustum(LLView *origin);
+protected:
+
+    // Draw's a cone from origin to derived view or floater
+    // @derived_local_rect derived flaoter's local rect
+    // @droot_view usually it is a derived floater
+    // @drag_handle floater's drag handle getDragHandle()
+    void drawFrustum(const LLRect &derived_local_rect, const LLView *root_view, const LLView *drag_handle, bool has_focus);
+
+    void setFrustumOrigin(LLView *origin);
+private:
+
+    LLHandle <LLView>   mFrustumOrigin;
+    F32		            mContextConeOpacity;
+    F32                 mContextConeInAlpha;
+    F32                 mContextConeOutAlpha;
+    F32                 mContextConeFadeTime;
+};
+
+#endif // LL_LLDRAWFRUSTUM_H
+
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 33099db1b94..e86c10d00bc 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -81,6 +81,7 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
 	floater->mNearMeListComplete = FALSE;
 	floater->mCloseOnSelect = closeOnSelect;
 	floater->mExcludeAgentFromSearchResults = skip_agent;
+    floater->setFrustumOrigin(frustumOrigin);
 	
 	if (!closeOnSelect)
 	{
@@ -91,10 +92,6 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
 		floater->getChild<LLButton>("cancel_btn")->setLabel(close_string);
 	}
 
-    if(frustumOrigin)
-    {
-        floater->mFrustumOrigin = frustumOrigin->getHandle();
-    }
 
 	return floater;
 }
@@ -104,17 +101,9 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key)
   : LLFloater(key),
 	mNumResultsReturned(0),
 	mNearMeListComplete(FALSE),
-	mCloseOnSelect(FALSE),
-    mContextConeOpacity	(0.f),
-    mContextConeInAlpha(0.f),
-    mContextConeOutAlpha(0.f),
-    mContextConeFadeTime(0.f)
+	mCloseOnSelect(FALSE)
 {
 	mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
-
-    mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
-    mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
-    mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
 }
 
 BOOL LLFloaterAvatarPicker::postBuild()
@@ -359,66 +348,10 @@ void LLFloaterAvatarPicker::populateFriend()
 	friends_scroller->sortByColumnIndex(0, TRUE);
 }
 
-void LLFloaterAvatarPicker::drawFrustum()
-{
-    if(mFrustumOrigin.get())
-    {
-        LLView * frustumOrigin = mFrustumOrigin.get();
-        LLRect origin_rect;
-        frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
-        // draw context cone connecting color picker with color swatch in parent floater
-        LLRect local_rect = getLocalRect();
-        if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
-        {
-            gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-            LLGLEnable(GL_CULL_FACE);
-            gGL.begin(LLRender::QUADS);
-            {
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-                gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-                gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-                gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-                gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-                gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-                gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-                gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-                gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-                gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-                gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-                gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-                gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-                gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-                gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-                gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-                gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-                gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-            }
-            gGL.end();
-        }
-
-        if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-        {
-            mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-        }
-        else
-        {
-            mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-        }
-    }
-}
-
 void LLFloaterAvatarPicker::draw()
 {
-    drawFrustum();
+    LLRect local_rect = getLocalRect();
+    drawFrustum(local_rect, this, getDragHandle(), hasFocus());
 
 	// sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars).
 	// lets check this via mOkButtonValidateSignal callback periodically.
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index fbee61b0549..7d941997868 100644
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -28,6 +28,7 @@
 #define LLFLOATERAVATARPICKER_H
 
 #include "llfloater.h"
+#include "lldrawfrustum.h"
 #include "lleventcoro.h"
 #include "llcoros.h"
 
@@ -36,7 +37,7 @@
 class LLAvatarName;
 class LLScrollListCtrl;
 
-class LLFloaterAvatarPicker :public LLFloater
+class LLFloaterAvatarPicker :public LLFloater, public LLDrawFrustum
 {
 public:
 	typedef boost::signals2::signal<bool(const uuid_vec_t&), boost_boolean_combiner> validate_signal_t;
@@ -91,7 +92,6 @@ class LLFloaterAvatarPicker :public LLFloater
 	void setAllowMultiple(BOOL allow_multiple);
 	LLScrollListCtrl* getActiveList();
 
-    void drawFrustum();
 	virtual void draw();
 	virtual BOOL handleKeyHere(KEY key, MASK mask);
 
@@ -100,11 +100,6 @@ class LLFloaterAvatarPicker :public LLFloater
 	BOOL				mNearMeListComplete;
 	BOOL				mCloseOnSelect;
 	BOOL                mExcludeAgentFromSearchResults;
-    LLHandle <LLView>   mFrustumOrigin;
-    F32		            mContextConeOpacity;
-    F32                 mContextConeInAlpha;
-    F32                 mContextConeOutAlpha;
-    F32                 mContextConeFadeTime;
 
 	validate_signal_t mOkButtonValidateSignal;
 	select_callback_t mSelectionCallback;
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index ec2c9740afe..9c06f777fb1 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -70,6 +70,7 @@
 
 LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate )
 	: LLFloater(LLSD()),
+      LLDrawFrustum(swatch),
 	  mComponents			( 3 ),
 	  mMouseDownInLumRegion	( FALSE ),
 	  mMouseDownInHueRegion	( FALSE ),
@@ -100,11 +101,7 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show
 	  mPaletteRegionHeight	( 40 ),
 	  mSwatch				( swatch ),
 	  mActive				( TRUE ),
-	  mCanApplyImmediately	( show_apply_immediate ),
-	  mContextConeOpacity	( 0.f ),
-      mContextConeInAlpha   ( 0.f ),
-      mContextConeOutAlpha   ( 0.f ),
-      mContextConeFadeTime   ( 0.f )
+	  mCanApplyImmediately	( show_apply_immediate )
 {
 	buildFromFile ( "floater_color_picker.xml");
 
@@ -116,10 +113,6 @@ LLFloaterColorPicker::LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show
 		mApplyImmediateCheck->setEnabled(FALSE);
 		mApplyImmediateCheck->set(FALSE);
 	}
-
-    mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
-    mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
-    mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
 }
 
 LLFloaterColorPicker::~LLFloaterColorPicker()
@@ -485,56 +478,10 @@ BOOL LLFloaterColorPicker::isColorChanged()
 //
 void LLFloaterColorPicker::draw()
 {
-	LLRect swatch_rect;
-	mSwatch->localRectToOtherView(mSwatch->getLocalRect(), &swatch_rect, this);
 	// draw context cone connecting color picker with color swatch in parent floater
 	LLRect local_rect = getLocalRect();
-	if (hasFocus() && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f)
-	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		LLGLEnable(GL_CULL_FACE);
-		gGL.begin(LLRender::QUADS);
-		{
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-			gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-			gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
-		}
-		gGL.end();
-	}
+	drawFrustum(local_rect, this, getDragHandle(), hasFocus());
 
-	if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), 
-                                        LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-	}
-	else
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-	}
 
 	mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
 	mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately);
diff --git a/indra/newview/llfloatercolorpicker.h b/indra/newview/llfloatercolorpicker.h
index 16974a872ef..74b99d5e68e 100644
--- a/indra/newview/llfloatercolorpicker.h
+++ b/indra/newview/llfloatercolorpicker.h
@@ -30,6 +30,7 @@
 #include <vector>
 
 #include "llfloater.h"
+#include "lldrawfrustum.h"
 #include "llpointer.h"
 #include "llcolorswatch.h"
 #include "llspinctrl.h"
@@ -41,7 +42,7 @@ class LLCheckBoxCtrl;
 //////////////////////////////////////////////////////////////////////////////
 // floater class
 class LLFloaterColorPicker 
-	: public LLFloater
+	: public LLFloater, public LLDrawFrustum
 {
 	public:
 		LLFloaterColorPicker (LLColorSwatchCtrl* swatch, BOOL show_apply_immediate = FALSE);
@@ -63,7 +64,7 @@ class LLFloaterColorPicker
 		void destroyUI ();
 		void cancelSelection ();
 		LLColorSwatchCtrl* getSwatch () { return mSwatch; };
-		void setSwatch( LLColorSwatchCtrl* swatch) { mSwatch = swatch; }
+        void setSwatch(LLColorSwatchCtrl* swatch) { mSwatch = swatch; setFrustumOrigin(mSwatch); }
 
 		// mutator / accessor for original RGB value
 		void setOrigRgb ( F32 origRIn, F32 origGIn, F32 origBIn );
@@ -196,12 +197,6 @@ class LLFloaterColorPicker
 		LLButton* mCancelBtn;
 
 		LLButton* mPipetteBtn;
-
-		F32		  mContextConeOpacity;
-        F32       mContextConeInAlpha;
-        F32       mContextConeOutAlpha;
-        F32       mContextConeFadeTime;
-
 };
 
 #endif // LL_LLFLOATERCOLORPICKER_H
diff --git a/indra/newview/llfloaterexperiencepicker.cpp b/indra/newview/llfloaterexperiencepicker.cpp
index bb54c57baf1..352b3a4ecef 100644
--- a/indra/newview/llfloaterexperiencepicker.cpp
+++ b/indra/newview/llfloaterexperiencepicker.cpp
@@ -64,88 +64,22 @@ LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t ca
 		floater->mSearchPanel->filterContent();
 	}
 
-	if(frustumOrigin)
-	{
-		floater->mFrustumOrigin = frustumOrigin->getHandle();
-	}
+	floater->setFrustumOrigin(frustumOrigin);
 
 	return floater;
 }
 
-void LLFloaterExperiencePicker::drawFrustum()
-{
-	if(mFrustumOrigin.get())
-	{
-		LLView * frustumOrigin = mFrustumOrigin.get();
-		LLRect origin_rect;
-		frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
-		// draw context cone connecting color picker with color swatch in parent floater
-		LLRect local_rect = getLocalRect();
-		if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLGLEnable(GL_CULL_FACE);
-			gGL.begin(LLRender::QUADS);
-			{
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-			}
-			gGL.end();
-		}
-
-		if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-		{
-			mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime));
-		}
-		else
-		{
-			mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime));
-		}
-	}
-}
-
 void LLFloaterExperiencePicker::draw()
 {
-	drawFrustum();
+    LLRect local_rect = getLocalRect();
+    drawFrustum(local_rect, this, getDragHandle(), hasFocus());
 	LLFloater::draw();
 }
 
 LLFloaterExperiencePicker::LLFloaterExperiencePicker( const LLSD& key )
 	:LLFloater(key)
 	,mSearchPanel(NULL)
-	,mContextConeOpacity(0.f)
-	,mContextConeInAlpha(0.f)
-	,mContextConeOutAlpha(0.f)
-	,mContextConeFadeTime(0.f)
 {
-	mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
-	mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
-	mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
 }
 
 LLFloaterExperiencePicker::~LLFloaterExperiencePicker()
diff --git a/indra/newview/llfloaterexperiencepicker.h b/indra/newview/llfloaterexperiencepicker.h
index 29054a57db2..55fc632e18e 100644
--- a/indra/newview/llfloaterexperiencepicker.h
+++ b/indra/newview/llfloaterexperiencepicker.h
@@ -28,13 +28,14 @@
 #define LL_LLFLOATEREXPERIENCEPICKER_H
 
 #include "llfloater.h"
+#include "lldrawfrustum.h"
 
 class LLScrollListCtrl;
 class LLLineEditor;
 class LLPanelExperiencePicker;
 
 
-class LLFloaterExperiencePicker : public LLFloater
+class LLFloaterExperiencePicker : public LLFloater, public LLDrawFrustum
 {
 public:
 
@@ -54,13 +55,6 @@ class LLFloaterExperiencePicker : public LLFloater
 private:
 
 	LLPanelExperiencePicker* mSearchPanel;
-
-	void drawFrustum();
-	LLHandle <LLView>   mFrustumOrigin;
-	F32		            mContextConeOpacity;
-	F32                 mContextConeInAlpha;
-	F32                 mContextConeOutAlpha;
-	F32                 mContextConeFadeTime;
 };
 
 #endif // LL_LLFLOATEREXPERIENCEPICKER_H
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 8a2fc881a94..f10e0bdd811 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -73,10 +73,6 @@
 
 #include "llavatarappearancedefines.h"
 
-static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
-static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
-static const F32 CONTEXT_FADE_TIME = 0.08f;
-
 static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
 
 //static const char CURRENT_IMAGE_NAME[] = "Current Texture";
@@ -113,7 +109,6 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
 	mImmediateFilterPermMask(immediate_filter_perm_mask),
 	mDnDFilterPermMask(dnd_filter_perm_mask),
 	mNonImmediateFilterPermMask(non_immediate_filter_perm_mask),
-	mContextConeOpacity(0.f),
 	mSelectedItemPinned( FALSE ),
 	mCanApply(true),
 	mCanPreview(true),
@@ -127,6 +122,7 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
 	buildFromFile("floater_texture_ctrl.xml");
 	mCanApplyImmediately = can_apply_immediately;
 	setCanMinimize(FALSE);
+	setFrustumOrigin(mOwner);
 }
 
 LLFloaterTexturePicker::~LLFloaterTexturePicker()
@@ -442,59 +438,9 @@ BOOL LLFloaterTexturePicker::postBuild()
 // virtual
 void LLFloaterTexturePicker::draw()
 {
-	if (mOwner)
-	{
-		// draw cone of context pointing back to texture swatch	
-		LLRect owner_rect;
-		mOwner->localRectToOtherView(mOwner->getLocalRect(), &owner_rect, this);
-		LLRect local_rect = getLocalRect();
-		if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f)
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLGLEnable(GL_CULL_FACE);
-			gGL.begin(LLRender::QUADS);
-			{
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
-
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
-			}
-			gGL.end();
-		}
-	}
-
-	if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME));
-	}
-	else
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME));
-	}
+	// draw cone of context pointing back to texture swatch	
+    LLRect local_rect = getLocalRect();
+    drawFrustum(local_rect, this, getDragHandle(), hasFocus());
 
 	updateImageStats();
 
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index b2a34a37c48..c962cf98a2c 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -29,6 +29,7 @@
 #define LL_LLTEXTURECTRL_H
 
 #include "llcoord.h"
+#include "lldrawfrustum.h"
 #include "llfiltereditor.h"
 #include "llfloater.h"
 #include "llfolderview.h"
@@ -249,7 +250,7 @@ typedef boost::function<void()> floater_close_callback;
 typedef boost::function<void(const LLUUID& asset_id)> set_image_asset_id_callback;
 typedef boost::function<void(LLPointer<LLViewerTexture> texture)> set_on_update_image_stats_callback;
 
-class LLFloaterTexturePicker : public LLFloater
+class LLFloaterTexturePicker : public LLFloater, public LLDrawFrustum
 {
 public:
 	LLFloaterTexturePicker(
@@ -291,7 +292,7 @@ class LLFloaterTexturePicker : public LLFloater
 	void			setActive(BOOL active);
 
 	LLView*			getOwner() const { return mOwner; }
-	void			setOwner(LLView* owner) { mOwner = owner; }
+	void			setOwner(LLView* owner) { mOwner = owner; setFrustumOrigin(owner); }
 	void			stopUsingPipette();
 	PermissionMask 	getFilterPermMask();
 
@@ -363,7 +364,6 @@ class LLFloaterTexturePicker : public LLFloater
 	PermissionMask		mNonImmediateFilterPermMask;
 	BOOL				mCanApplyImmediately;
 	BOOL				mNoCopyTextureSelected;
-	F32					mContextConeOpacity;
 	LLSaveFolderState	mSavedFolderState;
 	BOOL				mSelectedItemPinned;
 
-- 
GitLab