From b5c4565c62433d603a673d94f691c687ac907c7d Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 25 Nov 2015 15:33:05 -0500
Subject: MAINT-5901: Make avatar auto pilot work correctly through transparent
 objects

---
 indra/newview/lltoolpie.cpp | 86 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 61 insertions(+), 25 deletions(-)

diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 2081297717..60a7d284ef 100755
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -106,7 +106,7 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
 	mMouseDownX = x;
 	mMouseDownY = y;
 
-	//left mouse down always picks transparent
+	//left mouse down always picks transparent (but see handleMouseUp)
 	mPick = gViewerWindow->pickImmediate(x, y, TRUE);
 	mPick.mKeyMask = mask;
 
@@ -661,30 +661,52 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
 		&& gAgentAvatarp
 		&& !gAgentAvatarp->isSitting()
 		&& !mBlockClickToWalk							// another behavior hasn't cancelled click to walk
-		&& !mPick.mPosGlobal.isExactlyZero()			// valid coordinates for pick
-		&& (mPick.mPickType == LLPickInfo::PICK_LAND	// we clicked on land
-			|| mPick.mObjectID.notNull()))				// or on an object
-	{
-		// handle special cases of steering picks
-		LLViewerObject* avatar_object = mPick.getObject();
-
-		// get pointer to avatar
-		while (avatar_object && !avatar_object->isAvatar())
-		{
-			avatar_object = (LLViewerObject*)avatar_object->getParent();
-		}
-
-		if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
-		{
-			const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
-			// pretend we picked some point a bit in front of avatar
-			mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
-		}
-		gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
-		walkToClickedLocation();
-		LLFirstUse::notMoving(false);
-
-		return TRUE;
+        )
+	{
+        // We may be doing click to walk, but we don't want to use a target on
+        // a transparent object because the user thought they were clicking on
+        // whatever they were seeing through it, so recompute what was clicked on
+        // ignoring transparent objects
+        LLPickInfo savedPick = mPick;
+        mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
+                                             FALSE /* ignore transparent */,
+                                             FALSE /* ignore particles */);
+
+        if (!mPick.mPosGlobal.isExactlyZero()			// valid coordinates for pick
+            && (mPick.mPickType == LLPickInfo::PICK_LAND	// we clicked on land
+                || mPick.mObjectID.notNull()))				// or on an object
+        {
+            // handle special cases of steering picks
+            LLViewerObject* avatar_object = mPick.getObject();
+
+            // get pointer to avatar
+            while (avatar_object && !avatar_object->isAvatar())
+            {
+                avatar_object = (LLViewerObject*)avatar_object->getParent();
+            }
+
+            if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
+            {
+                const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
+                // pretend we picked some point a bit in front of avatar
+                mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
+            }
+            gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
+            walkToClickedLocation();
+            LLFirstUse::notMoving(false);
+
+            return TRUE;
+        }
+        else
+        {
+            LL_DEBUGS("maint5901") << "walk target was "
+                                   << (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
+                                   << ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
+                                   << ", pick object was " << mPick.mObjectID
+                                   << LL_ENDL;
+            // we didn't click to walk, so restore the original target
+            mPick = savedPick;
+        }
 	}
 	gViewerWindow->setCursor(UI_CURSOR_ARROW);
 	if (hasMouseCapture())
@@ -718,12 +740,26 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
 
 	if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
 	{
+        // We may be doing double click to walk, but we don't want to use a target on
+        // a transparent object because the user thought they were clicking on
+        // whatever they were seeing through it, so recompute what was clicked on
+        // ignoring transparent objects
+        LLPickInfo savedPick = mPick;
+        mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
+                                             FALSE /* ignore transparent */,
+                                             FALSE /* ignore particles */);
+
 		if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
 			(mPick.mObjectID.notNull()  && !mPick.mPosGlobal.isExactlyZero()))
 		{
 			walkToClickedLocation();
 			return TRUE;
 		}
+        else
+        {
+            // restore the original pick for any other purpose
+            mPick = savedPick;
+        }
 	}
 	else if (gSavedSettings.getBOOL("DoubleClickTeleport"))
 	{
-- 
cgit v1.2.3