diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h
index 21ca4189ff714c17f2b2489c49e111ebcd4a054b..17fa981c7c2399e280e0959e0182d2f93b9a48ed 100644
--- a/indra/llmath/llrect.h
+++ b/indra/llmath/llrect.h
@@ -183,11 +183,10 @@ template <class Type> class LLRectBase
 
 	LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height)
 	{
-		// width and height could be odd, so favor top, right with extra pixel
 		mLeft = x - width/2;
+		mTop = y + height/2;
+		mRight = x + width/2;
 		mBottom = y - height/2;
-		mTop = mBottom + height;
-		mRight = mLeft + width;
 		return *this;
 	}
 
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 242b0809ebbb62f2bafb7700214446aaea64dce9..3b01140e3a639e4795fe9112e6b025fe8f91b0ee 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -104,128 +104,46 @@ BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLV
 	}
 } 
 
-BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size)
+// intersect test between triangle pt1,pt2,pt3 and line from linept to linept+vect
+//returns TRUE if intersecting and moves linept to the point of intersection
+BOOL LLTriangleLineSegmentIntersect( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, LLVector3& linept, const LLVector3& vect)
 {
-	float fAWdU[3];
-	LLVector3 dir;
-	LLVector3 diff;
-
-	for (U32 i = 0; i < 3; i++)
-	{
-		dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]);
-		diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i];
-		fAWdU[i] = fabsf(dir.mV[i]);
-		if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false;
-	}
-
-	float f;
-	f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1];    if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1])  return false;
-	f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2];    if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0])  return false;
-	f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0];    if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0])  return false;
+	LLVector3 V1 = pt2-pt1;
+	LLVector3 V2 = pt3-pt2;
 	
-	return true;
-}
-
-
-// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir.
-// returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b,
-// and returns the intersection point along dir in intersection_t.
-
-// Moller-Trumbore algorithm
-BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
-							F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided)
-{
-	F32 u, v, t;
-	
-	/* find vectors for two edges sharing vert0 */
-	LLVector3 edge1 = vert1 - vert0;
-	
-	LLVector3 edge2 = vert2 - vert0;;
-
-	/* begin calculating determinant - also used to calculate U parameter */
-	LLVector3 pvec = dir % edge2;
+	LLVector3 norm = V1 % V2;
 	
-	/* if determinant is near zero, ray lies in plane of triangle */
-	F32 det = edge1 * pvec;
+	F32 dotprod = norm * vect;
 
-	if (!two_sided)
+	if(dotprod < 0)
 	{
-		if (det < F_APPROXIMATELY_ZERO)
-		{
-			return FALSE;
-		}
-
-		/* calculate distance from vert0 to ray origin */
-		LLVector3 tvec = orig - vert0;
+		//Find point of intersect to triangle plane.
+		//find t to intersect point
+		F32 t = -(norm * (linept-pt1))/dotprod;
 
-		/* calculate U parameter and test bounds */
-		u = tvec * pvec;	
-
-		if (u < 0.f || u > det)
+		// if ds is neg line started past triangle so can't hit triangle.
+		if (t > 0) 
 		{
 			return FALSE;
 		}
 	
-		/* prepare to test V parameter */
-		LLVector3 qvec = tvec % edge1;
+		LLVector3 pt_int = linept + (vect*t);
 		
-		/* calculate V parameter and test bounds */
-		v = dir * qvec;
-		if (v < 0.f || u + v > det)
+		if(check_same_clock_dir(pt1, pt2, pt_int, norm))
 		{
-			return FALSE;
-		}
-
-		/* calculate t, scale parameters, ray intersects triangle */
-		t = edge2 * qvec;
-		F32 inv_det = 1.0 / det;
-		t *= inv_det;
-		u *= inv_det;
-		v *= inv_det;
-	}
-	
-	else // two sided
+			if(check_same_clock_dir(pt2, pt3, pt_int, norm))
 			{
-		if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO)
+				if(check_same_clock_dir(pt3, pt1, pt_int, norm))
 				{
-			return FALSE;
+					// answer in pt_int is insde triangle
+					linept.setVec(pt_int);
+					return TRUE;
 				}
-		F32 inv_det = 1.0 / det;
-
-		/* calculate distance from vert0 to ray origin */
-		LLVector3 tvec = orig - vert0;
-		
-		/* calculate U parameter and test bounds */
-		u = (tvec * pvec) * inv_det;
-		if (u < 0.f || u > 1.f)
-		{
-			return FALSE;
 			}
-
-		/* prepare to test V parameter */
-		LLVector3 qvec = tvec - edge1;
-		
-		/* calculate V parameter and test bounds */
-		v = (dir * qvec) * inv_det;
-		
-		if (v < 0.f || u + v > 1.f)
-		{
-			return FALSE;
 		}
-
-		/* calculate t, ray intersects triangle */
-		t = (edge2 * qvec) * inv_det;
 	}
 	
-	if (intersection_a != NULL)
-		*intersection_a = u;
-	if (intersection_b != NULL)
-		*intersection_b = v;
-	if (intersection_t != NULL)
-		*intersection_t = t;
-	
-	
-	return TRUE;
+	return FALSE;
 } 
 
 
@@ -3487,99 +3405,47 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
 	}
 }
 
-S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, 
-								   S32 face,
-								   LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
+S32 LLVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
 {
-	S32 hit_face = -1;
-	
-	S32 start_face;
-	S32 end_face;
+	S32 ret = -1;
 	
-	if (face == -1) // ALL_SIDES
-	{
-		start_face = 0;
-		end_face = getNumFaces() - 1;
-	}
-	else
-	{
-		start_face = face;
-		end_face = face;
-	}
-
-	LLVector3 dir = end - start;
-
-	F32 closest_t = 2.f; // must be larger than 1
+	LLVector3 vec = end - start;
 	
-	for (S32 i = start_face; i <= end_face; i++)
+	for (S32 i = 0; i < getNumFaces(); i++)
 	{
-		LLVolumeFace face = getVolumeFace((U32)i);
-
-		LLVector3 box_center = (face.mExtents[0] + face.mExtents[1]) / 2.f;
-		LLVector3 box_size   = face.mExtents[1] - face.mExtents[0];
-
-        if (LLLineSegmentBoxIntersect(start, end, box_center, box_size))
-		{
-			if (bi_normal != NULL) // if the caller wants binormals, we may need to generate them
-			{
-				genBinormals(i);
-			}
-			
-			for (U32 tri = 0; tri < face.mIndices.size()/3; tri++) 
-			{
-				S32 index1 = face.mIndices[tri*3+0];
-				S32 index2 = face.mIndices[tri*3+1];
-				S32 index3 = face.mIndices[tri*3+2];
+		const LLVolumeFace& face = getVolumeFace(i);
 
-				F32 a, b, t;
-			
-				if (LLTriangleRayIntersect(face.mVertices[index1].mPosition,
-										   face.mVertices[index2].mPosition,
-										   face.mVertices[index3].mPosition,
-										   start, dir, &a, &b, &t, FALSE))
-				{
-					if ((t >= 0.f) &&      // if hit is after start
-						(t <= 1.f) &&      // and before end
-						(t < closest_t))   // and this hit is closer
+		for (U32 j = 0; j < face.mIndices.size()/3; j++) 
 		{
-						closest_t = t;
-						hit_face = i;
+			//approximate normal
+			S32 v1 = face.mIndices[j*3+0];
+			S32 v2 = face.mIndices[j*3+1];
+			S32 v3 = face.mIndices[j*3+2];
 
-						if (intersection != NULL)
-						{
-							*intersection = start + dir * closest_t;
-						}
+			LLVector3 norm = (face.mVertices[v2].mPosition - face.mVertices[v1].mPosition) % 
+				(face.mVertices[v3].mPosition - face.mVertices[v2].mPosition);
 			
-						if (tex_coord != NULL)
+			if (norm.magVecSquared() >= 0.00000001f) 
 			{
-							*tex_coord = ((1.f - a - b)  * face.mVertices[index1].mTexCoord +
-										  a              * face.mVertices[index2].mTexCoord +
-										  b              * face.mVertices[index3].mTexCoord);
-
-						}
-
-						if (normal != NULL)
+				//get view vector
+				//LLVector3 view = (start-face.mVertices[v1].mPosition);
+				//if (view * norm < 0.0f)
 				{
-							*normal    = ((1.f - a - b)  * face.mVertices[index1].mNormal + 
-										  a              * face.mVertices[index2].mNormal +
-										  b              * face.mVertices[index3].mNormal);
-						}
-
-						if (bi_normal != NULL)
+					if (LLTriangleLineSegmentIntersect( face.mVertices[v1].mPosition,
+														face.mVertices[v2].mPosition,
+														face.mVertices[v3].mPosition,
+														end,
+														vec))
 					{
-							*bi_normal = ((1.f - a - b)  * face.mVertices[index1].mBinormal + 
-										  a              * face.mVertices[index2].mBinormal +
-										  b              * face.mVertices[index3].mBinormal);
-						}
-
+						vec = end-start;
+						ret = (S32) i;
 					}
 				}
 			}
 		}		
 	}
 	
-	
-	return hit_face;
+	return ret;
 }
 
 class LLVertexIndexPair
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 0444a028253f826f6552426705795827133850c5..c395ed737878886ea819ea8bc44e03f556343f7e 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -906,13 +906,7 @@ class LLVolume : public LLRefCount
 	//get the face index of the face that intersects with the given line segment at the point 
 	//closest to start.  Moves end to the point of intersection.  Returns -1 if no intersection.
 	//Line segment must be in volume space.
-	S32 lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
-							 S32 face = -1,                          // which face to check, -1 = ALL_SIDES
-							 LLVector3* intersection = NULL,         // return the intersection point
-							 LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point
-							 LLVector3* normal = NULL,               // return the surface normal at the intersection point
-							 LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point
-		);
+	S32 lineSegmentIntersect(const LLVector3& start, LLVector3& end) const;
 	
 	// The following cleans up vertices and triangles,
 	// getting rid of degenerate triangles and duplicate vertices,
@@ -973,10 +967,4 @@ LLVector3 calc_binormal_from_triangle(
 		const LLVector3& pos2,
 		const LLVector2& tex2);
 
-BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
-BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
-							F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided);
-	
-	
-
 #endif
diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp
index f9e62cbd538c39abb47e11027fe4ab5cf372adeb..70330485750faec493a08cee99d333d5b6989c93 100644
--- a/indra/llmath/v2math.cpp
+++ b/indra/llmath/v2math.cpp
@@ -33,7 +33,6 @@
 
 //#include "vmath.h"
 #include "v2math.h"
-#include "v3math.h"
 #include "v4math.h"
 #include "m4math.h"
 #include "m3math.h"
diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h
index c896b80977f1642ece972655d4607f8cf9bf5a20..5f46655a0721a13995ac17ac87e74329413eaae5 100644
--- a/indra/llmath/v2math.h
+++ b/indra/llmath/v2math.h
@@ -33,7 +33,6 @@
 #define LL_V2MATH_H
 
 #include "llmath.h"
-#include "v3math.h"
 
 class LLVector4;
 class LLMatrix3;
@@ -50,10 +49,9 @@ class LLVector2
 
 		static LLVector2 zero;
 
-		LLVector2();							  // Initializes LLVector2 to (0, 0)
-		LLVector2(F32 x, F32 y);			      // Initializes LLVector2 to (x. y)
-		LLVector2(const F32 *vec);				  // Initializes LLVector2 to (vec[0]. vec[1])
-        explicit LLVector2(const LLVector3 &vec); // Initializes LLVector2 to (vec[0]. vec[1])
+		LLVector2();							// Initializes LLVector2 to (0, 0)
+		LLVector2(F32 x, F32 y);			    // Initializes LLVector2 to (x. y)
+		LLVector2(const F32 *vec);				// Initializes LLVector2 to (vec[0]. vec[1])
 		
 		// Clears LLVector2 to (0, 0).  DEPRECATED - prefer zeroVec.
 		void	clear();
@@ -139,12 +137,6 @@ inline LLVector2::LLVector2(const F32 *vec)
 	mV[VY] = vec[VY];
 }
 
-inline LLVector2::LLVector2(const LLVector3 &vec)
-{
-	mV[VX] = vec.mV[VX];
-	mV[VY] = vec.mV[VY];
-}
-
 
 // Clear and Assignment Functions
 
diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp
index 12916b625387be877b1c8839217f09bed2ba2c6b..166761e55083521d1ee6e6c345d730edac4cec3c 100644
--- a/indra/llmath/v3math.cpp
+++ b/indra/llmath/v3math.cpp
@@ -34,7 +34,6 @@
 #include "v3math.h"
 
 //#include "vmath.h"
-#include "v2math.h"
 #include "v4math.h"
 #include "m4math.h"
 #include "m3math.h"
@@ -271,13 +270,6 @@ const LLVector3&	LLVector3::setVec(const LLVector4 &vec)
 	return (*this);
 }
 
-LLVector3::LLVector3(const LLVector2 &vec)
-{
-	mV[VX] = (F32)vec.mV[VX];
-	mV[VY] = (F32)vec.mV[VY];
-	mV[VZ] = 0;
-}
-
 LLVector3::LLVector3(const LLVector3d &vec)
 {
 	mV[VX] = (F32)vec.mdV[VX];
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h
index 42ca1f88b23755dc56aaa20a7f93e836f7dd3fe4..051d5376b7ca1953165d923eba8ed91a611b8e53 100644
--- a/indra/llmath/v3math.h
+++ b/indra/llmath/v3math.h
@@ -36,7 +36,6 @@
 #include "llmath.h"
 
 #include "llsd.h"
-class LLVector2;
 class LLVector4;
 class LLMatrix3;
 class LLVector3d;
@@ -63,7 +62,6 @@ class LLVector3
 		inline LLVector3();							// Initializes LLVector3 to (0, 0, 0)
 		inline LLVector3(const F32 x, const F32 y, const F32 z);			// Initializes LLVector3 to (x. y, z)
 		inline explicit LLVector3(const F32 *vec);				// Initializes LLVector3 to (vec[0]. vec[1], vec[2])
-		explicit LLVector3(const LLVector2 &vec);				// Initializes LLVector3 to (vec[0]. vec[1], 0)
 		explicit LLVector3(const LLVector3d &vec);				// Initializes LLVector3 to (vec[0]. vec[1], vec[2])
 		explicit LLVector3(const LLVector4 &vec);				// Initializes LLVector4 to (vec[0]. vec[1], vec[2])
 		LLVector3(const LLSD& sd);
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index b5186ad539736000b0a5f7828350b18c287ef69f..b1395b0b703f0d273303959841888ad5e664d870 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -574,9 +574,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
 			// repeat number is a single byte
 			if (decode_pos >= mReceiveSize)
 			{
-				// commented out - hetgrid says that missing variable blocks
-				// at end of message are legal
-				// logRanOffEndOfPacket(sender, decode_pos, 1);
+				logRanOffEndOfPacket(sender, decode_pos, 1);
 
 				// default to 0 repeats
 				repeat_number = 0;
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index dd034904d3efef3fee7ef62f166d8e34fd727ffc..0d537e05754e8d4db048e0966b55c5065814da1d 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -1371,7 +1371,4 @@ char* _PREHASH_OwnerMask = LLMessageStringTable::getInstance()->getString("Owner
 char* _PREHASH_TransferInventoryAck = LLMessageStringTable::getInstance()->getString("TransferInventoryAck");
 char* _PREHASH_RegionDenyAgeUnverified = LLMessageStringTable::getInstance()->getString("RegionDenyAgeUnverified");
 char* _PREHASH_AgeVerificationBlock = LLMessageStringTable::getInstance()->getString("AgeVerificationBlock");
-char* _PREHASH_UCoord = LLMessageStringTable::getInstance()->getString("UCoord");
-char* _PREHASH_VCoord = LLMessageStringTable::getInstance()->getString("VCoord");
-char* _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex");
 
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 9dfb3992ca079744a9c401d0ec4d69136e5fcf0b..287296d1eb59385d5689d1c3e76c0fea6eb73e26 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -1371,8 +1371,6 @@ extern char * _PREHASH_OwnerMask;
 extern char * _PREHASH_TransferInventoryAck;
 extern char * _PREHASH_RegionDenyAgeUnverified;
 extern char * _PREHASH_AgeVerificationBlock;
-extern char * _PREHASH_UCoord;
-extern char * _PREHASH_VCoord;
-extern char * _PREHASH_FaceIndex;
+
 
 #endif
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index c1da6c93fe8ce4df6d705499ee357d49ea2b5403..c20bfe6ac0c66ea1f264523c1e81675a4fdacd3d 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -63,6 +63,7 @@ BOOL	LLView::sDebugKeys = FALSE;
 S32		LLView::sDepth = 0;
 BOOL	LLView::sDebugMouseHandling = FALSE;
 std::string LLView::sMouseHandlerMessage;
+S32	LLView::sSelectID = GL_NAME_UI_RESERVED;
 BOOL	LLView::sEditingUI = FALSE;
 BOOL	LLView::sForceReshape = FALSE;
 LLView*	LLView::sEditingUIView = NULL;
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index df3fb2e2403dfa4cd58517057bffca8e2561384e..65f0a2b7e270b31ba86ba1ed2c1cd5eb4fcaa720 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -1411,11 +1411,6 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
 	// Under certain circumstances, this will trigger us to decouple the cursor.
 	adjustCursorDecouple(true);
 
-	// trigger mouse move callback
-	LLCoordGL gl_pos;
-	convertCoords(position, &gl_pos);
-	mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
-
 	return result;
 }
 
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 526a6769a0c7666648cf58550ff183b35925e795..4a81ddd1fd2c7da1d0f7d617aa006babbfa81855 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1387,10 +1387,6 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
 		return FALSE;
 	}
 
-	LLCoordGL gl_pos;
-	convertCoords(position, &gl_pos);
-	mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
-	
 	return SetCursorPos(screen_pos.mX, screen_pos.mY);
 }
 
diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp
index b99bd64f2afa2da6a2768bebf6ddad5e1f40d8d9..0b357c9182b157eb41ffb2183ab2492027be1025 100644
--- a/indra/lscript/lscript_library/lscript_library.cpp
+++ b/indra/lscript/lscript_library/lscript_library.cpp
@@ -442,14 +442,6 @@ void LLScriptLibrary::init()
 	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetRegionAgentCount", "i", NULL, "int llGetRegionAgentCount()\nreturns the number of agents in a region"));
 	addFunction(new LLScriptLibraryFunction(10.f, 1.f, dummy_func, "llTextBox", NULL, "ksi", "llTextBox(key avatar, string message, integer chat_channel\nShows a dialog box on the avatar's screen with the message.\nA text box asks for input, and if entered the text is chatted on chat_channel."));
 	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llGetAgentLanguage", "s", "k", "string llGetAgentLanguage(key id)\nGets the agents preferred language.."));
-	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchUV", "v", "i", "vector llDetectedTouchUV(integer number)\nreturns the u and v coordinates in the first two components of a vector, for a triggered touch event"));
-	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchFace", "i", "i", "integer llDetectedTouchFace(integer number)\nreturns the index of the face on the object for a triggered touch event"));
-	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchPos", "v", "i", "vector llDetectedTouchPos(integer number)\nreturns the position touched for a triggered touch event"));
-	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchNormal", "v", "i", "vector llDetectedTouchNormal(integer number)\nreturns the surface normal for a triggered touch event"));
-	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchBinormal", "v", "i", "vector llDetectedTouchBinormal(integer number)\nreturns the surface binormal for a triggered touch event"));
-	addFunction(new LLScriptLibraryFunction(10.f, 0.f, dummy_func, "llDetectedTouchST", "v", "i", "vector llDetectedTouchST(integer number)\nreturns the s and t coordinates in the first two components of a vector, for a triggered touch event"));
-
-
 
 	// energy, sleep, dummy_func, name, return type, parameters, help text, gods-only
 
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4c47cb45b2c87bd0e5439e008762484ebb38ccab..8ca74f6d0f24076214b97303e28808186c0f4c3e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5201,28 +5201,6 @@
       <key>Value</key>
       <string />
     </map>
-    <key>PerFrameHoverPick</key>
-    <map>
-      <key>Comment</key>
-      <string>Detect the object under the mouse continually</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <real>1</real>
-    </map>
-    <key>PerFrameHoverPickCount</key>
-    <map>
-      <key>Comment</key>
-      <string>Detect the object under the mouse every n frames</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>S32</string>
-      <key>Value</key>
-      <integer>1</integer>
-    </map>
     <key>PermissionsCautionEnabled</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index cffd4410c380b2adcbc1cd64e4e130a3e94f1c89..7fb9e57507bcd54fd59217ff704b753245c01172 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -133,6 +133,7 @@
 // end Ventrella
 
 extern LLMenuBarGL* gMenuBarView;
+extern U8 gLastPickAlpha;
 
 //drone wandering constants
 const F32 MAX_WANDER_TIME = 20.f;						// seconds
@@ -329,8 +330,6 @@ LLAgent::LLAgent()
 	mCameraZoomFraction(1.f),			// deprecated
 	mThirdPersonHeadOffset(0.f, 0.f, 1.f),
 	mSitCameraEnabled(FALSE),
-	mHUDTargetZoom(1.f),
-	mHUDCurZoom(1.f),
 	mFocusOnAvatar(TRUE),
 	mFocusGlobal(),
 	mFocusTargetGlobal(),
@@ -531,7 +530,10 @@ void LLAgent::resetView(BOOL reset_camera)
 		setFocusOnAvatar(TRUE, ANIMATE);
 	}
 
-	mHUDTargetZoom = 1.f;
+	if (mAvatarObject.notNull())
+	{
+		mAvatarObject->mHUDTargetZoom = 1.f;
+	}
 }
 
 // Handle any actions that need to be performed when the main app gains focus
@@ -1296,7 +1298,7 @@ LLQuaternion LLAgent::getQuat() const
 //-----------------------------------------------------------------------------
 // calcFocusOffset()
 //-----------------------------------------------------------------------------
-LLVector3 LLAgent::calcFocusOffset(LLViewerObject *object, S32 x, S32 y)
+LLVector3d LLAgent::calcFocusOffset(LLViewerObject *object, S32 x, S32 y)
 {
 	// calculate offset based on view direction
 	BOOL is_avatar = object->isAvatar();
@@ -1455,10 +1457,10 @@ LLVector3 LLAgent::calcFocusOffset(LLViewerObject *object, S32 x, S32 y)
 		
 		obj_rel = lerp(focus_delta, obj_rel, bias);
 		
-		return LLVector3(obj_rel);
+		return LLVector3d(obj_rel);
 	}
 
-	return LLVector3(focus_delta.mV[VX], focus_delta.mV[VY], focus_delta.mV[VZ]);
+	return LLVector3d(focus_delta.mV[VX], focus_delta.mV[VY], focus_delta.mV[VZ]);
 }
 
 //-----------------------------------------------------------------------------
@@ -1648,7 +1650,7 @@ F32 LLAgent::getCameraZoomFraction()
 	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		// already [0,1]
-		return mHUDTargetZoom;
+		return mAvatarObject->mHUDTargetZoom;
 	}
 	else if (mFocusOnAvatar && cameraThirdPerson())
 	{
@@ -1696,7 +1698,7 @@ void LLAgent::setCameraZoomFraction(F32 fraction)
 
 	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 	{
-		mHUDTargetZoom = fraction;
+		mAvatarObject->mHUDTargetZoom = fraction;
 	}
 	else if (mFocusOnAvatar && cameraThirdPerson())
 	{
@@ -1806,7 +1808,7 @@ void LLAgent::cameraZoomIn(const F32 fraction)
 	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		// just update hud zoom level
-		mHUDTargetZoom /= fraction;
+		mAvatarObject->mHUDTargetZoom /= fraction;
 		return;
 	}
 
@@ -3755,7 +3757,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
 
 					lag_interp *= u;
 
-					if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == mAvatarObject->getID())
+					if (gViewerWindow->getLeftMouseDown() && gLastHitObjectID == mAvatarObject->getID())
 					{
 						// disable camera lag when using mouse-directed steering
 						target_lag.clearVec();
@@ -4283,12 +4285,6 @@ void LLAgent::setFocusObject(LLViewerObject* object)
 //-----------------------------------------------------------------------------
 // setFocusGlobal()
 //-----------------------------------------------------------------------------
-void LLAgent::setFocusGlobal(const LLPickInfo& pick)
-{
-	setFocusGlobal(pick.mPosGlobal, pick.mObjectID);
-}
-
-
 void LLAgent::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id)
 {
 	setFocusObject(gObjectList.findObject(object_id));
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index ea9138fdd1510bd104748fc5cd14276f37a7b555..45006fef8d76dc7874d34d2360a0a89b3439cfa3 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -95,7 +95,6 @@ class LLMessageSystem;
 class LLPermissions;
 class LLHost;
 class LLFriendObserver;
-class LLPickInfo;
 
 struct LLGroupData
 {
@@ -192,7 +191,6 @@ class LLAgent : public LLObservable
 	void			changeCameraToFollow(BOOL animate = TRUE);
 	//end Ventrella
 
-	void			setFocusGlobal(const LLPickInfo& pick);
 	void			setFocusGlobal(const LLVector3d &focus, const LLUUID &object_id = LLUUID::null);
 	void			setFocusOnAvatar(BOOL focus, BOOL animate);
 	void			setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id);
@@ -376,7 +374,7 @@ class LLAgent : public LLObservable
 	void			sendAnimationRequests(LLDynamicArray<LLUUID> &anim_ids, EAnimRequest request);
 	void			sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request);
 
-	LLVector3		calcFocusOffset(LLViewerObject *object, S32 x, S32 y);
+	LLVector3d		calcFocusOffset(LLViewerObject *object, S32 x, S32 y);
 	BOOL			calcCameraMinDistance(F32 &obj_min_distance);
 
 	void			startCameraAnimation();
@@ -713,9 +711,6 @@ class LLAgent : public LLObservable
 
 	LLDynamicArray<LLGroupData> mGroups;
 
-	F32				mHUDTargetZoom;	// target zoom level for HUD objects (used when editing)
-	F32				mHUDCurZoom;	// current animated zoom level for HUD objects
-
 	BOOL			mInitialized;
 
 	static BOOL		sDebugDisplayTarget;
@@ -791,7 +786,6 @@ class LLAgent : public LLObservable
 	LLVector3		mSitCameraFocus;				// root relative camera target when sitting
 	LLVector3d      mCameraSmoothingLastPositionGlobal;    
 	LLVector3d      mCameraSmoothingLastPositionAgent;    
-
 	
 	//Ventrella
 	LLVector3		mCameraUpVector;				// camera's up direction in world coordinates (determines the 'roll' of the view)
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 6d81edd7ca00f3cddff0994b8610865cd4144281..422c0dc9a870f2b6dfdd8eae49abbd366d9b9fab 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -53,6 +53,8 @@ static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
 static U32 sShaderLevel = 0;
 static LLGLSLShader* sVertexProgram = NULL;
 
+extern BOOL gUseGLPick;
+
 F32 CLOTHING_GRAVITY_EFFECT = 0.7f;
 F32 CLOTHING_ACCEL_FORCE_FACTOR = 0.2f;
 const S32 NUM_TEST_AVATARS = 30;
@@ -564,6 +566,11 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 //-----------------------------------------------------------------------------
 void LLDrawPoolAvatar::renderForSelect()
 {
+	if (gUseGLPick)
+	{
+		return;
+	}
+	
 	if (!gRenderAvatar)
 	{
 		return;
@@ -611,7 +618,7 @@ void LLDrawPoolAvatar::renderForSelect()
 
 	glColor4ubv(color.mV);
 
-	if (sShaderLevel > 0)  // for hardware blending
+	if ((sShaderLevel > 0) && !gUseGLPick)  // for hardware blending
 	{
 		sRenderingSkinned = TRUE;
 		sVertexProgram->bind();
@@ -621,7 +628,7 @@ void LLDrawPoolAvatar::renderForSelect()
 	avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
 
 	// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
-	if (sShaderLevel > 0)
+	if ((sShaderLevel > 0) && !gUseGLPick)
 	{
 		sRenderingSkinned = FALSE;
 		sVertexProgram->unbind();
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 16668f81e2b9d7e25243734a9694e9a95e1c34a4..b2f5caa57d06a3d1ff0d086fec67fe5eca6b57e5 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -54,6 +54,8 @@
 
 #define LL_MAX_INDICES_COUNT 1000000
 
+extern BOOL gPickFaces;
+
 BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE
 
 #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2])
@@ -71,15 +73,14 @@ The resulting texture coordinate <u,v> is:
 	u = 2(B dot P)
 	v = 2(T dot P)
 */
-void planarProjection(LLVector2 &tc, const LLVector3& normal,
-					  const LLVector3 &mCenter, const LLVector3& vec)
+void planarProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec)
 {	//DONE!
 	LLVector3 binormal;
-	float d = normal * LLVector3(1,0,0);
+	float d = vd.mNormal * LLVector3(1,0,0);
 	if (d >= 0.5f || d <= -0.5f)
 	{
 		binormal = LLVector3(0,1,0);
-		if (normal.mV[0] < 0)
+		if (vd.mNormal.mV[0] < 0)
 		{
 			binormal = -binormal;
 		}
@@ -87,19 +88,18 @@ void planarProjection(LLVector2 &tc, const LLVector3& normal,
 	else
 	{
         binormal = LLVector3(1,0,0);
-		if (normal.mV[1] > 0)
+		if (vd.mNormal.mV[1] > 0)
 		{
 			binormal = -binormal;
 		}
 	}
-	LLVector3 tangent = binormal % normal;
+	LLVector3 tangent = binormal % vd.mNormal;
 
 	tc.mV[1] = -((tangent*vec)*2 - 0.5f);
 	tc.mV[0] = 1.0f+((binormal*vec)*2 - 0.5f);
 }
 
-void sphericalProjection(LLVector2 &tc, const LLVector3& normal,
-						 const LLVector3 &mCenter, const LLVector3& vec)
+void sphericalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec)
 {	//BROKEN
 	/*tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/3.14159f;
 	
@@ -110,7 +110,7 @@ void sphericalProjection(LLVector2 &tc, const LLVector3& normal,
 	}*/
 }
 
-void cylindricalProjection(LLVector2 &tc, const LLVector3& normal, const LLVector3 &mCenter, const LLVector3& vec)
+void cylindricalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, const LLVector3 &mCenter, const LLVector3& vec)
 {	//BROKEN
 	/*LLVector3 binormal;
 	float d = vd.mNormal * LLVector3(1,0,0);
@@ -374,7 +374,7 @@ void LLFace::renderForSelect(U32 data_mask)
 #if !LL_RELEASE_FOR_DOWNLOAD
 		LLGLState::checkClientArrays(data_mask);
 #endif
-		if (mTEOffset != -1)
+		if (gPickFaces && mTEOffset != -1)
 		{
 			// mask off high 4 bits (16 total possible faces)
 			color.mV[0] &= 0x0f;
@@ -419,11 +419,12 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color)
 
 	if (mGeomCount > 0 && mIndicesCount > 0)
 	{
-		gGL.color4fv(color.mV);
+		LLGLSPipelineAlpha gls_pipeline_alpha;
+		glColor4fv(color.mV);
 
 		LLViewerImage::bindTexture(imagep);
 	
-		gGL.pushMatrix();
+		glPushMatrix();
 		if (mDrawablep->isActive())
 		{
 			glMultMatrixf((GLfloat*)mDrawablep->getRenderMatrix().mMatrix);
@@ -433,49 +434,137 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color)
 			glMultMatrixf((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix);
 		}
 
-		mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD);
+		mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD);
 #if !LL_RELEASE_FOR_DOWNLOAD
-		LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD);
+		LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD);
 #endif
 		mVertexBuffer->draw(LLVertexBuffer::TRIANGLES, mIndicesCount, mIndicesIndex);
 				
-		gGL.popMatrix();
+		glPopMatrix();
 	}
 }
 
-
-/* removed in lieu of raycast uv detection
-void LLFace::renderSelectedUV()
+void LLFace::renderSelectedUV(const S32 offset, const S32 count)
 {
+#if 0
 	LLViewerImage* red_blue_imagep = gImageList.getImageFromFile("uv_test1.j2c", TRUE, TRUE);
 	LLViewerImage* green_imagep = gImageList.getImageFromFile("uv_test2.tga", TRUE, TRUE);
 
-	LLGLSUVSelect object_select;
+	LLGLSObjectSelect object_select;
+	LLGLEnable blend(GL_BLEND);
+	
+	if (!mDrawPoolp || !getIndicesCount() || getIndicesStart() < 0)
+	{
+		return;
+	}
+	for (S32 pass = 0; pass < 2; pass++)
+	{
+		static F32 bias = 0.f;
+		static F32 factor = -10.f;
+		if (mGeomCount > 0)
+		{
+			gGL.color4fv(LLColor4::white.mV);
+
+			if (pass == 0)
+			{
+				LLViewerImage::bindTexture(red_blue_imagep);
+				red_blue_imagep->setMipFilterNearest (TRUE, TRUE);
+			}
+			else // pass == 1
+			{
+				gGL.blendFunc(GL_ONE, GL_ONE);
+				LLViewerImage::bindTexture(green_imagep);
+				glMatrixMode(GL_TEXTURE);
+				glPushMatrix();
+				glScalef(256.f, 256.f, 1.f);
+				green_imagep->setMipFilterNearest (TRUE, TRUE);
+			}
+
+
+			if (!isState(GLOBAL))
+			{
+				// Apply the proper transform for non-global objects.
+				glMatrixMode(GL_MODELVIEW);
+				glPushMatrix();
+				glMultMatrixf((float*)getRenderMatrix().mMatrix);
+			}
+
+			glEnable(GL_POLYGON_OFFSET_FILL);
+			glPolygonOffset(factor, bias);
+			if (sSafeRenderSelect)
+			{
+				gGL.begin(LLVertexBuffer::TRIANGLES);
+				if (count)
+				{
+					for (S32 i = offset; i < offset + count; i++)
+					{
+						LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0);
+						gGL.texCoord2fv(tc.mV);
+						LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i));
+						gGL.vertex3fv(vertex.mV);
+					}
+				}
+				else
+				{
+					for (U32 i = 0; i < getIndicesCount(); i++)
+					{
+						LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0);
+						gGL.texCoord2fv(tc.mV);
+						LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i));
+						gGL.vertex3fv(vertex.mV);
+					}
+				}
+				gGL.end();
+			}
+			else
+			{
+				llassert(mGeomIndex >= 0);
+				if (count)
+				{
+					if (mIndicesCount > 0)
+					{
+						glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, getRawIndices() + offset); 
+					}
+					else
+					{
+						llerrs << "Rendering non-indexed volume face!" << llendl;
+						glDrawArrays(mPrimType, mGeomIndex, mGeomCount); 
+					}
+				}
+				else
+				{
+					if (mIndicesCount > 0)
+					{
+						glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_SHORT, getRawIndices()); 
+					}
+					else
+					{
+						glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount); 
+					}
+				}
+			}
 
-	// use red/blue gradient to get coarse UV coordinates
-	renderSelected(red_blue_imagep, LLColor4::white);
+			glDisable(GL_POLYGON_OFFSET_FILL);
+			if (!isState(GLOBAL))
+			{
+				// Restore the tranform for non-global objects
+				glPopMatrix();
+			}
+			if (pass == 1)
+			{
+				glMatrixMode(GL_TEXTURE);
+				glPopMatrix();
+				glMatrixMode(GL_MODELVIEW);
+				gGL.blendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
+			}
+		}
+	}
 	
-	static F32 bias = 0.f;
-	static F32 factor = -10.f;
-	glPolygonOffset(factor, bias);
-
-	// add green dither pattern on top of red/blue gradient
-	gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_ONE);
-	glMatrixMode(GL_TEXTURE);
-	glPushMatrix();
-	// make green pattern repeat once per texel in red/blue texture
-	glScalef(256.f, 256.f, 1.f);
-	glMatrixMode(GL_MODELVIEW);
-
-	renderSelected(green_imagep, LLColor4::white);
-
-	glMatrixMode(GL_TEXTURE);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
+	//restore blend func
+	gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+#endif
 }
 
-*/
 
 void LLFace::printDebugInfo() const
 {
@@ -671,69 +760,6 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
 	return TRUE;
 }
 
-
-
-// convert surface coordinates to texture coordinates, based on
-// the values in the texture entry.  probably should be
-// integrated with getGeometryVolume() for its texture coordinate
-// generation - but i'll leave that to someone more familiar
-// with the implications.
-LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position, LLVector3 normal)
-{
-	LLVector2 tc = surface_coord;
-	
-	const LLTextureEntry *tep = getTextureEntry();
-
-	if (tep == NULL)
-	{
-		// can't do much without the texture entry
-		return surface_coord;
-	}
-
-	// see if we have a non-default mapping
-    U8 texgen = getTextureEntry()->getTexGen();
-	if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
-	{
-		LLVector3 center = mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter;
-		
-		LLVector3 scale = (mDrawablep->getVOVolume()->isVolumeGlobal()) ? LLVector3(1,1,1) : mVObjp->getScale();
-		LLVector3 vec = position;
-		vec.scaleVec(scale);
-
-		switch (texgen)
-		{
-		case LLTextureEntry::TEX_GEN_PLANAR:
-			planarProjection(tc, normal, center, vec);
-			break;
-		case LLTextureEntry::TEX_GEN_SPHERICAL:
-			sphericalProjection(tc, normal, center, vec);
-			break;
-		case LLTextureEntry::TEX_GEN_CYLINDRICAL:
-			cylindricalProjection(tc, normal, center, vec);
-			break;
-		default:
-			break;
-		}		
-	}
-
-	if (mTextureMatrix)	// if we have a texture matrix, use it
-	{
-		LLVector3 tc3(tc);
-		tc3 = tc3 * *mTextureMatrix;
-		tc = LLVector2(tc3);
-	}
-	
-	else // otherwise use the texture entry parameters
-	{
-		xform(tc, cos(tep->getRotation()), sin(tep->getRotation()),
-			  tep->mOffsetS, tep->mOffsetT, tep->mScaleS, tep->mScaleT);
-	}
-
-	
-	return tc;
-}
-
-
 BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 							   const S32 &f,
 								const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
@@ -1013,13 +1039,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				switch (texgen)
 				{
 					case LLTextureEntry::TEX_GEN_PLANAR:
-						planarProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec);
+						planarProjection(tc, vf.mVertices[i], vf.mCenter, vec);
 						break;
 					case LLTextureEntry::TEX_GEN_SPHERICAL:
-						sphericalProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec);
+						sphericalProjection(tc, vf.mVertices[i], vf.mCenter, vec);
 						break;
 					case LLTextureEntry::TEX_GEN_CYLINDRICAL:
-						cylindricalProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec);
+						cylindricalProjection(tc, vf.mVertices[i], vf.mCenter, vec);
 						break;
 					default:
 						break;
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 9e7a33eb7b59ac2c8ca9aa0cb9d9c536fe26111b..0391cda66fc0a0dd9e2a6c2e64fc3d4a9dfb2eec 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -91,7 +91,6 @@ class LLFace
 	LLXformMatrix*	getXform()			const	{ return mXform; }
 	BOOL			hasGeometry()		const	{ return mGeomCount > 0; }
 	LLVector3		getPositionAgent()	const;
-	LLVector2       surfaceToTexture(LLVector2 surface_coord, LLVector3 position, LLVector3 normal);
 	
 	U32				getState()			const	{ return mState; }
 	void			setState(U32 state)			{ mState |= state; }
@@ -166,7 +165,7 @@ class LLFace
 	void		update();
 
 	void		updateCenterAgent(); // Update center when xform has changed.
-	void		renderSelectedUV();
+	void		renderSelectedUV(const S32 offset = 0, const S32 count = 0);
 
 	void		renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD);
 	void		renderSelected(LLImageGL *image, const LLColor4 &color);
diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h
index 12b2eced9b4145c399f12b2c66a29ffb644415b9..11d9f43fcc9a8b06e6a5c86518ad7ab2b4b3cb2a 100644
--- a/indra/newview/llhudobject.h
+++ b/indra/newview/llhudobject.h
@@ -67,8 +67,6 @@ class LLHUDObject : public LLRefCount
 
 	U8 getType() const { return mType; }
 
-	LLVector3d getPositionGlobal() const { return mPositionGlobal; }
-
 	static LLHUDObject *addHUDObject(const U8 type);
 	static LLHUDEffect *addHUDEffect(const U8 type);
 	static void updateAll();
diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp
index 891dd69f84da6992661cdd5fd684d82c4683f60e..5e09e69e2bf35de1095fe572938de2e43a62cc0c 100644
--- a/indra/newview/llmanip.cpp
+++ b/indra/newview/llmanip.cpp
@@ -96,8 +96,7 @@ LLManip::LLManip( const std::string& name, LLToolComposite* composite )
 	:
 	LLTool( name, composite ),
 	mInSnapRegime(FALSE),
-	mHighlightedPart(LL_NO_PART),
-	mManipPart(LL_NO_PART)
+	mHighlightedPart(LL_NO_PART)
 {
 }
 
@@ -178,7 +177,7 @@ F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVecto
 	LLVector3 cam_to_reference;
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
-		cam_to_reference = LLVector3(1.f / gAgent.mHUDCurZoom, 0.f, 0.f);
+		cam_to_reference = LLVector3(1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f);
 	}
 	else
 	{
@@ -200,8 +199,6 @@ void LLManip::handleSelect()
 
 void LLManip::handleDeselect()
 {
-	mHighlightedPart = LL_NO_PART;
-	mManipPart = LL_NO_PART;
 	mObjectSelection = NULL;
 }
 
@@ -263,8 +260,8 @@ BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVect
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		BOOL result = FALSE;
-		F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidth() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom;
-		F32 mouse_y = ((F32)y / gViewerWindow->getWindowHeight() - 0.5f) / gAgent.mHUDCurZoom;
+		F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidth() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.getAvatarObject()->mHUDCurZoom;
+		F32 mouse_y = ((F32)y / gViewerWindow->getWindowHeight() - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
 
 		LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin);
 		LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y);
@@ -302,8 +299,8 @@ BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, co
 
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
-		F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.mHUDCurZoom;
-		F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.mHUDCurZoom;
+		F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgent.getAvatarObject()->mHUDCurZoom;
+		F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
 		a1 = LLVector3(llmin(b1.mV[VX] - 0.1f, b2.mV[VX] - 0.1f, 0.f), -mouse_x, mouse_y);
 		a2 = a1 + LLVector3(1.f, 0.f, 0.f);
 	}
@@ -487,7 +484,7 @@ void LLManip::renderTickText(const LLVector3& pos, const std::string& text, cons
 	LLVector3 render_pos = pos;
 	if (hud_selection)
 	{
-		F32 zoom_amt = gAgent.mHUDCurZoom;
+		F32 zoom_amt = gAgent.getAvatarObject()->mHUDCurZoom;
 		F32 inv_zoom_amt = 1.f / zoom_amt;
 		// scale text back up to counter-act zoom level
 		render_pos = pos * zoom_amt;
@@ -545,7 +542,7 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string
 	LLVector3 render_pos = pos;
 	if (hud_selection)
 	{
-		F32 zoom_amt = gAgent.mHUDCurZoom;
+		F32 zoom_amt = gAgent.getAvatarObject()->mHUDCurZoom;
 		F32 inv_zoom_amt = 1.f / zoom_amt;
 		// scale text back up to counter-act zoom level
 		render_pos = pos * zoom_amt;
diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h
index 43d6eaadc812651e3573e6ab71c8e5471cbd29fa..1313f77c5b1fc85b04bab66a2184a7b812ba1d87 100644
--- a/indra/newview/llmanip.h
+++ b/indra/newview/llmanip.h
@@ -155,7 +155,6 @@ class LLManip : public LLTool
 	BOOL				mInSnapRegime;
 	LLSafeHandle<LLObjectSelection> mObjectSelection;
 	EManipPart			mHighlightedPart;
-	EManipPart			mManipPart;
 
 	static F32			sHelpTextVisibleTime;
 	static F32			sHelpTextFadeTime;
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index ca0812c8a041e4c17ccf5688e2efc6e92a890b88..e98ded2a879dae8aa6f2810600a76e6e2ea17e06 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -98,6 +98,7 @@ LLManipRotate::LLManipRotate( LLToolComposite* composite )
 	mCenterToCamMag(0.f),
 	mCenterToProfilePlane(),
 	mCenterToProfilePlaneMag(0.f),
+	mManipPart( LL_NO_PART ),
 	mSendUpdateOnMouseUp( FALSE ),
 	mSmoothRotate( FALSE ),
 	mCamEdgeOn(FALSE),
@@ -112,6 +113,13 @@ void LLManipRotate::handleSelect()
 	LLManip::handleSelect();
 }
 
+void LLManipRotate::handleDeselect()
+{
+	mHighlightedPart = LL_NO_PART;
+	mManipPart = LL_NO_PART;
+	LLManip::handleDeselect();
+}
+
 void LLManipRotate::render()
 {
 	LLGLSUIDefault gls_ui;
@@ -136,7 +144,7 @@ void LLManipRotate::render()
 	glPushMatrix();
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
-		F32 zoom = gAgent.mHUDCurZoom;
+		F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 		glScalef(zoom, zoom, zoom);
 	}
 
@@ -355,7 +363,8 @@ BOOL LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask)
 	LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE);
 	if( first_object )
 	{
-		if( mHighlightedPart != LL_NO_PART )
+		LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
+		if( hit_obj && mHighlightedPart != LL_NO_PART )
 		{
 			handled = handleMouseDownOnPart( x, y, mask );
 		}
@@ -1117,18 +1126,18 @@ BOOL LLManipRotate::updateVisiblity()
 	LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
-		mCenterToCam = LLVector3(-1.f / gAgent.mHUDCurZoom, 0.f, 0.f);
+		mCenterToCam = LLVector3(-1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f);
 		mCenterToCamNorm = mCenterToCam;
 		mCenterToCamMag = mCenterToCamNorm.normVec();
 
 		mRadiusMeters = RADIUS_PIXELS / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
-		mRadiusMeters /= gAgent.mHUDCurZoom;
+		mRadiusMeters /= gAgent.getAvatarObject()->mHUDCurZoom;
 
 		mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag;
 		mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm;
 
-		mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) / gAgent.mHUDCurZoom * gViewerWindow->getWindowWidth()),
-							(S32)((mRotationCenter.mdV[VZ] + 0.5f) / gAgent.mHUDCurZoom * gViewerWindow->getWindowHeight()));
+		mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) / gAgent.getAvatarObject()->mHUDCurZoom * gViewerWindow->getWindowWidth()),
+							(S32)((mRotationCenter.mdV[VZ] + 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom * gViewerWindow->getWindowHeight()));
 		visible = TRUE;
 	}
 	else
@@ -1644,8 +1653,8 @@ void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_
 {
 	if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD)
 	{
-		F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgent.mHUDCurZoom;
-		F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.mHUDCurZoom;
+		F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
+		F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
 
 		*ray_pt = LLVector3(-1.f, -mouse_x, mouse_y);
 		*ray_dir = LLVector3(1.f, 0.f, 0.f);
diff --git a/indra/newview/llmaniprotate.h b/indra/newview/llmaniprotate.h
index f5c815d53773f3936152e0f2c2af781572ef3aef..460bd3fcbab580905fbb134a1b97f5b369eed92c 100644
--- a/indra/newview/llmaniprotate.h
+++ b/indra/newview/llmaniprotate.h
@@ -64,6 +64,7 @@ class LLManipRotate : public LLManip
 	virtual void	render();
 
 	virtual void	handleSelect();
+	virtual void	handleDeselect();
 
 	virtual BOOL	handleMouseDownOnPart(S32 x, S32 y, MASK mask);
 	virtual void	highlightManipulators(S32 x, S32 y);
@@ -108,6 +109,8 @@ class LLManipRotate : public LLManip
 	LLVector3			mCenterToProfilePlane;
 	F32					mCenterToProfilePlaneMag;
 
+	EManipPart			mManipPart;
+
 	BOOL				mSendUpdateOnMouseUp;
 
 	BOOL				mSmoothRotate;
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 5859d4c75ff6309478a9be9b4403e77e6f4a31e0..57c901e9bcdb22fb67006af9eb2025b4c6fe0717 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -166,11 +166,19 @@ void LLManipScale::handleSelect()
 	LLManip::handleSelect();
 }
 
+void LLManipScale::handleDeselect()
+{
+	mHighlightedPart = LL_NO_PART;
+	mManipPart = LL_NO_PART;
+	LLManip::handleDeselect();
+}
+
 LLManipScale::LLManipScale( LLToolComposite* composite )
 	: 
 	LLManip( std::string("Scale"), composite ),
 	mBoxHandleSize( 1.f ),
 	mScaledBoxHandleSize( 1.f ),
+	mManipPart( LL_NO_PART ),
 	mLastMouseX( -1 ),
 	mLastMouseY( -1 ),
 	mSendUpdateOnMouseUp( FALSE ),
@@ -208,7 +216,7 @@ void LLManipScale::render()
 		glPushMatrix();
 		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
-			F32 zoom = gAgent.mHUDCurZoom;
+			F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 			glScalef(zoom, zoom, zoom);
 		}
 
@@ -225,7 +233,7 @@ void LLManipScale::render()
 		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
-			mBoxHandleSize /= gAgent.mHUDCurZoom;
+			mBoxHandleSize /= gAgent.getAvatarObject()->mHUDCurZoom;
 		}
 		else
 		{
@@ -308,7 +316,9 @@ BOOL LLManipScale::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	BOOL	handled = FALSE;
 
-	if(mHighlightedPart != LL_NO_PART)
+	LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
+	if( hit_obj ||  
+		(mHighlightedPart != LL_NO_PART) )
 	{
 		handled = handleMouseDownOnPart( x, y, mask );
 	}
@@ -436,7 +446,7 @@ void LLManipScale::highlightManipulators(S32 x, S32 y)
 			LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
 			transform *= cfr;
 			LLMatrix4 window_scale;
-			F32 zoom_level = 2.f * gAgent.mHUDCurZoom;
+			F32 zoom_level = 2.f * gAgent.getAvatarObject()->mHUDCurZoom;
 			window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f),
 				LLQuaternion::DEFAULT,
 				LLVector3::zero);
@@ -1357,7 +1367,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox)
 
 	if(mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
-		mSnapRegimeOffset = SNAP_GUIDE_SCREEN_OFFSET / gAgent.mHUDCurZoom;
+		mSnapRegimeOffset = SNAP_GUIDE_SCREEN_OFFSET / gAgent.getAvatarObject()->mHUDCurZoom;
 
 	}
 	else
@@ -1370,7 +1380,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox)
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		cam_at_axis.setVec(1.f, 0.f, 0.f);
-		snap_guide_length = SNAP_GUIDE_SCREEN_LENGTH / gAgent.mHUDCurZoom;
+		snap_guide_length = SNAP_GUIDE_SCREEN_LENGTH / gAgent.getAvatarObject()->mHUDCurZoom;
 	}
 	else
 	{
diff --git a/indra/newview/llmanipscale.h b/indra/newview/llmanipscale.h
index 432be2cd3e50be2df2992335de0279199291da92..c02845e3586a87e1a181702445d32bbb28759ef6 100644
--- a/indra/newview/llmanipscale.h
+++ b/indra/newview/llmanipscale.h
@@ -76,6 +76,7 @@ class LLManipScale : public LLManip
 	virtual BOOL	handleHover( S32 x, S32 y, MASK mask );
 	virtual void	render();
 	virtual void	handleSelect();
+	virtual void	handleDeselect();
 
 	virtual BOOL	handleMouseDownOnPart(S32 x, S32 y, MASK mask);
 	virtual void	highlightManipulators(S32 x, S32 y);	// decided which manipulator, if any, should be highlighted by mouse hover
@@ -139,6 +140,7 @@ class LLManipScale : public LLManip
 
 	F32				mBoxHandleSize;		// The size of the handles at the corners of the bounding box
 	F32				mScaledBoxHandleSize; // handle size after scaling for selection feedback
+	EManipPart		mManipPart;
 	LLVector3d		mDragStartPointGlobal;
 	LLVector3d		mDragStartCenterGlobal;	// The center of the bounding box of all selected objects at time of drag start
 	LLVector3d		mDragPointGlobal;
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 7785b5a07894d0272c096fee52683b510b9a4997..f4f3a535de67066fd4fa3a9235d3585c170b4562 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -113,6 +113,7 @@ LLManipTranslate::LLManipTranslate( LLToolComposite* composite )
 	mConeSize(0),
 	mArrowLengthMeters(0.f),
 	mPlaneManipOffsetMeters(0.f),
+	mManipPart(LL_NO_PART),
 	mUpdateTimer(),
 	mSnapOffsetMeters(0.f),
 	mArrowScales(1.f, 1.f, 1.f),
@@ -256,12 +257,21 @@ void LLManipTranslate::handleSelect()
 	LLManip::handleSelect();
 }
 
+void LLManipTranslate::handleDeselect()
+{
+	mHighlightedPart = LL_NO_PART;
+	mManipPart = LL_NO_PART;
+	LLManip::handleDeselect();
+}
+
 BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	BOOL	handled = FALSE;
 
 	// didn't click in any UI object, so must have clicked in the world
-	if( (mHighlightedPart == LL_X_ARROW ||
+	LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
+	if( hit_obj && 
+		(mHighlightedPart == LL_X_ARROW ||
 		 mHighlightedPart == LL_Y_ARROW ||
 		 mHighlightedPart == LL_Z_ARROW ||
 		 mHighlightedPart == LL_YZ_PLANE ||
@@ -808,7 +818,7 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
 		LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
 		transform *= cfr;
 		LLMatrix4 window_scale;
-		F32 zoom_level = 2.f * gAgent.mHUDCurZoom;
+		F32 zoom_level = 2.f * gAgent.getAvatarObject()->mHUDCurZoom;
 		window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f),
 			LLQuaternion::DEFAULT,
 			LLVector3::zero);
@@ -1046,7 +1056,7 @@ void LLManipTranslate::render()
 	gGL.pushMatrix();
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
-		F32 zoom = gAgent.mHUDCurZoom;
+		F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 		glScalef(zoom, zoom, zoom);
 	}
 	{
@@ -1210,7 +1220,7 @@ void LLManipTranslate::renderSnapGuides()
 
 		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
-			guide_size_meters = 1.f / gAgent.mHUDCurZoom;
+			guide_size_meters = 1.f / gAgent.getAvatarObject()->mHUDCurZoom;
 			mSnapOffsetMeters = mArrowLengthMeters * 1.5f;
 		}
 		else
@@ -1793,7 +1803,7 @@ void LLManipTranslate::renderTranslationHandles()
 	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWindowHeight();
-		mArrowLengthMeters /= gAgent.mHUDCurZoom;
+		mArrowLengthMeters /= gAgent.getAvatarObject()->mHUDCurZoom;
 	}
 	else
 	{
diff --git a/indra/newview/llmaniptranslate.h b/indra/newview/llmaniptranslate.h
index 8c17dd3d510f52cf50f7c2d058428d44c85eb8cb..c9f98e9c7d500fe517ee476aba224c663765666a 100644
--- a/indra/newview/llmaniptranslate.h
+++ b/indra/newview/llmaniptranslate.h
@@ -61,6 +61,7 @@ class LLManipTranslate : public LLManip
 	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
 	virtual void	render();
 	virtual void	handleSelect();
+	virtual void	handleDeselect();
 
 	virtual void	highlightManipulators(S32 x, S32 y);
 	virtual BOOL	handleMouseDownOnPart(S32 x, S32 y, MASK mask);
@@ -109,6 +110,7 @@ class LLManipTranslate : public LLManip
 	F32			mArrowLengthMeters;		// meters
 	F32			mGridSizeMeters;
 	F32			mPlaneManipOffsetMeters;
+	EManipPart	mManipPart;
 	LLVector3	mManipNormal;
 	LLVector3d	mDragCursorStartGlobal;
 	LLVector3d	mDragSelectionStartGlobal;
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 2f11dad010f23d0f79901a73e5069fd479affad0..8ebaeb67585a762098233861e4764a132b64eaca 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -96,6 +96,9 @@ const S32 MAX_ACTION_QUEUE_SIZE = 20;
 const S32 MAX_SILS_PER_FRAME = 50;
 const S32 MAX_OBJECTS_PER_PACKET = 254;
 
+extern LLUUID			gLastHitObjectID;
+extern LLVector3d		gLastHitObjectOffset;
+
 //
 // Globals
 //
@@ -4830,7 +4833,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 	{
 		LLBBox hud_bbox = avatar->getHUDBBox();
 
-		F32 cur_zoom = gAgent.mHUDCurZoom;
+		F32 cur_zoom = avatar->mHUDCurZoom;
 
 		// set up transform to encompass bounding box of HUD
 		glMatrixMode(GL_PROJECTION);
@@ -5277,7 +5280,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
 		F32 silhouette_thickness;
 		if (is_hud_object && gAgent.getAvatarObject())
 		{
-			silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgent.mHUDCurZoom;
+			silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgent.getAvatarObject()->mHUDCurZoom;
 		}
 		else
 		{
@@ -5476,8 +5479,8 @@ void LLSelectMgr::updateSelectionCenter()
 		if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject())
 		{
 			// reset hud ZOOM
-			gAgent.mHUDTargetZoom = 1.f;
-			gAgent.mHUDCurZoom = 1.f;
+			gAgent.getAvatarObject()->mHUDTargetZoom = 1.f;
+			gAgent.getAvatarObject()->mHUDCurZoom = 1.f;
 		}
 
 		mShowSelection = FALSE;
@@ -5561,12 +5564,11 @@ void LLSelectMgr::updatePointAt()
 		if (mSelectedObjects->getObjectCount())
 		{					
 			LLVector3 select_offset;
-			const LLPickInfo& pick = gViewerWindow->getLastPick();
-			LLViewerObject *click_object = pick.getObject();
+			LLViewerObject *click_object = gObjectList.findObject(gLastHitObjectID);
 			if (click_object && click_object->isSelected())
 			{
 				// clicked on another object in our selection group, use that as target
-				select_offset.setVec(pick.mObjectOffset);
+				select_offset.setVec(gLastHitObjectOffset);
 				select_offset.rotVec(~click_object->getRenderRotation());
 		
 				gAgent.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset);
@@ -5764,20 +5766,29 @@ BOOL LLSelectMgr::setForceSelection(BOOL force)
 
 void LLSelectMgr::resetAgentHUDZoom()
 {
-	gAgent.mHUDTargetZoom = 1.f;
-	gAgent.mHUDCurZoom = 1.f;
+	if (gAgent.getAvatarObject())
+	{
+		gAgent.getAvatarObject()->mHUDTargetZoom = 1.f;
+		gAgent.getAvatarObject()->mHUDCurZoom = 1.f;
+	}
 }
 
 void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 &current_zoom) const
 {
-	target_zoom = gAgent.mHUDTargetZoom;
-	current_zoom = gAgent.mHUDCurZoom;
+	if (gAgent.getAvatarObject())
+	{
+		target_zoom = gAgent.getAvatarObject()->mHUDTargetZoom;
+		current_zoom = gAgent.getAvatarObject()->mHUDCurZoom;
+	}
 }
 
 void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom)
 {
-	gAgent.mHUDTargetZoom = target_zoom;
-	gAgent.mHUDCurZoom = current_zoom;
+	if (gAgent.getAvatarObject())
+	{
+		gAgent.getAvatarObject()->mHUDTargetZoom = target_zoom;
+		gAgent.getAvatarObject()->mHUDCurZoom = current_zoom;
+	}
 }
 
 LLObjectSelection::LLObjectSelection() : 
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index e9b09599e2fd055c79d123949cf39120ca773a1b..a62b1ac56a3d494b95f00733969ae98ec4e435c5 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -36,7 +36,6 @@
 #include "llviewerwindow.h"
 #include "llviewerobjectlist.h"
 #include "llvovolume.h"
-#include "llvolume.h"
 #include "llviewercamera.h"
 #include "llface.h"
 #include "llviewercontrol.h"
@@ -244,6 +243,28 @@ void LLSpatialGroup::buildOcclusion()
 
 BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group);
 
+BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size)
+{
+	float fAWdU[3];
+	LLVector3 dir;
+	LLVector3 diff;
+	
+	for (U32 i = 0; i < 3; i++)
+	{
+		dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]);
+		diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i];
+		fAWdU[i] = fabsf(dir.mV[i]);
+		if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i])	return false;
+	}
+
+	float f;
+	f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1];	if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1])	return false;
+	f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2];	if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0])	return false;
+	f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0];	if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0])	return false;
+
+	return true;
+}
+
 //returns:
 //	0 if sphere and AABB are not intersecting 
 //	1 if they are
@@ -2284,56 +2305,6 @@ void renderLights(LLDrawable* drawablep)
 	}
 }
 
-
-void renderRaycast(LLDrawable* drawablep)
-{
-	if (drawablep->getVObj() != gDebugRaycastObject)
-	{
-		return;
-	}
-	
-	if (drawablep->getNumFaces())
-	{
-		LLGLEnable blend(GL_BLEND);
-		gGL.color4f(0,1,1,0.5f);
-
-		for (S32 i = 0; i < drawablep->getNumFaces(); i++)
-		{
-			pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
-		}
-
-		// draw intersection point
-		glPushMatrix();
-		glLoadMatrixd(gGLModelView);
-		LLVector3 translate = gDebugRaycastIntersection;
-		glTranslatef(translate.mV[0], translate.mV[1], translate.mV[2]);
-		LLCoordFrame orient;
-		orient.lookDir(gDebugRaycastNormal, gDebugRaycastBinormal);
-		LLMatrix4 rotation;
-		orient.getRotMatrixToParent(rotation);
-		glMultMatrixf((float*)rotation.mMatrix);
-		
-		gGL.color4f(1,0,0,0.5f);
-		drawBox(LLVector3(0, 0, 0), LLVector3(0.1f, 0.022f, 0.022f));
-		gGL.color4f(0,1,0,0.5f);
-		drawBox(LLVector3(0, 0, 0), LLVector3(0.021f, 0.1f, 0.021f));
-		gGL.color4f(0,0,1,0.5f);
-		drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f));
-		glPopMatrix();
-
-		// draw bounding box of prim
-		const LLVector3* ext = drawablep->getSpatialExtents();
-
-		LLVector3 pos = (ext[0] + ext[1]) * 0.5f;
-		LLVector3 size = (ext[1] - ext[0]) * 0.5f;
-
-		LLGLDepthTest depth(GL_FALSE, GL_TRUE);
-		gGL.color4f(0,0.5f,0.5f,1);
-		drawBoxOutline(pos, size);
-
-	}
-}
-
 class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
 {
 public:
@@ -2410,11 +2381,6 @@ class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
 			{
 				renderLights(drawable);
 			}
-
-			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
-			{
-				renderRaycast(drawable);
-			}
 		}
 		
 		for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
@@ -2445,8 +2411,7 @@ void LLSpatialPartition::renderDebug()
 									  LLPipeline::RENDER_DEBUG_BBOXES |
 									  LLPipeline::RENDER_DEBUG_POINTS |
 									  LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
-									  LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |
-									  LLPipeline::RENDER_DEBUG_RAYCAST))
+									  LLPipeline::RENDER_DEBUG_TEXTURE_ANIM))
 	{
 		return;
 	}
@@ -2492,37 +2457,17 @@ BOOL LLSpatialPartition::isVisible(const LLVector3& v)
 	return TRUE;
 }
 
-class LLOctreeIntersect : public LLSpatialGroup::OctreeTraveler
+class LLOctreePick : public LLSpatialGroup::OctreeTraveler
 {
 public:
 	LLVector3 mStart;
 	LLVector3 mEnd;
-	S32       *mFaceHit;
-	LLVector3 *mIntersection;
-	LLVector2 *mTexCoord;
-	LLVector3 *mNormal;
-	LLVector3 *mBinormal;
-	LLDrawable* mHit;
+	LLDrawable* mRet;
 	
-	LLOctreeIntersect(LLVector3 start, LLVector3 end,
-					  S32* face_hit, LLVector3* intersection, LLVector2* tex_coord, LLVector3* normal, LLVector3* binormal)
-		: mStart(start),
-		  mEnd(end),
-		  mFaceHit(face_hit),
-		  mIntersection(intersection),
-		  mTexCoord(tex_coord),
-		  mNormal(normal),
-		  mBinormal(binormal),
-		  mHit(NULL)
+	LLOctreePick(LLVector3 start, LLVector3 end)
+	: mStart(start), mEnd(end)
 	{
-	}
-	
-	virtual void visit(const LLSpatialGroup::OctreeNode* branch) 
-	{	
-		for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
-	{
-			check(*i);
-		}
+		mRet = NULL;
 	}
 
 	virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node)
@@ -2542,73 +2487,41 @@ class LLOctreeIntersect : public LLSpatialGroup::OctreeTraveler
 			size = group->mBounds[1];
 			center = group->mBounds[0];
 			
-			LLVector3 local_start = mStart;
-			LLVector3 local_end   = mEnd;
-
-			if (group->mSpatialPartition->isBridge())
-			{
-				LLMatrix4 local_matrix = group->mSpatialPartition->asBridge()->mDrawable->getRenderMatrix();
-				local_matrix.invert();
-				
-				local_start = mStart * local_matrix;
-				local_end   = mEnd   * local_matrix;
-			}
-
-			if (LLLineSegmentBoxIntersect(local_start, local_end, center, size))
+			if (LLLineSegmentAABB(mStart, mEnd, center, size))
 			{
 				check(child);
 			}
 		}	
 
-		return mHit;
+		return mRet;
 	}
 
-	virtual bool check(LLDrawable* drawable)
+	virtual void visit(const LLSpatialGroup::OctreeNode* branch) 
 	{	
-		if (drawable->isSpatialBridge())
+		for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
 		{
-			LLSpatialPartition *part = drawable->asPartition();
-
-			check(part->mOctree);
+			check(*i);
+		}
 	}
 
-		else
+	virtual bool check(LLDrawable* drawable)
 	{
 		LLViewerObject* vobj = drawable->getVObj();
-
-			if (vobj)
-			{
-				LLVector3 intersection;
-				if (vobj->lineSegmentIntersect(mStart, mEnd, -1, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal))
-				{
-					mEnd = intersection;  // shorten ray so we only find CLOSER hits
-					if (mIntersection)
+		if (vobj->lineSegmentIntersect(mStart, mEnd))
 		{
-						*mIntersection = intersection;
-					}
-					
-					mHit = vobj->mDrawable;
-				}
-			}
+			mRet = vobj->mDrawable;
 		}
 		
 		return false;
 	}
 };
 
-LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
-													 S32* face_hit,                   // return the face hit
-													 LLVector3* intersection,         // return the intersection point
-													 LLVector2* tex_coord,            // return the texture coordinates of the intersection point
-													 LLVector3* normal,               // return the surface normal at the intersection point
-													 LLVector3* bi_normal             // return the surface bi-normal at the intersection point
-	)
-
+LLDrawable*	LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVector3& end, LLVector3& collision)
 {
-	LLOctreeIntersect intersect(start, end, face_hit, intersection, tex_coord, normal, bi_normal);
-	LLDrawable* drawable = intersect.check(mOctree);
-
-	return drawable;
+	LLOctreePick pick(start, end);
+	LLDrawable* ret = pick.check(mOctree);
+	collision.setVec(pick.mEnd);
+	return ret;
 }
 
 LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, 
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index d9a81d8b9e1553b5a8241c67aa6b917dd60e2564..7e872915b9ac271191b8ff61bb3aeec852880a4f 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -300,14 +300,7 @@ class LLSpatialPartition: public LLGeometryManager
 	LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE);
 	BOOL remove(LLDrawable *drawablep, LLSpatialGroup *curp);
 	
-	LLDrawable* lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
-									 S32* face_hit,                          // return the face hit
-									 LLVector3* intersection = NULL,         // return the intersection point
-									 LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point
-									 LLVector3* normal = NULL,               // return the surface normal at the intersection point
-									 LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point
-		);
-	
+	LLDrawable*	pickDrawable(const LLVector3& start, const LLVector3& end, LLVector3& collision);
 	
 	// If the drawable moves, move it here.
 	virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate = FALSE);
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 83b5cdbb66c26e7fe9281797b5e3e6d897e86627..c522bd069745403d3e0a7e302ceda6dad1406ffa 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -1452,15 +1452,13 @@ LLToolTexEyedropper::~LLToolTexEyedropper()
 
 BOOL LLToolTexEyedropper::handleMouseDown(S32 x, S32 y, MASK mask)
 {
-	// this will affect framerate on mouse down
-	const LLPickInfo& pick = gViewerWindow->pickImmediate(x, y, FALSE);
-	LLViewerObject* hit_obj	= pick.getObject();
+	LLViewerObject* hit_obj	= gViewerWindow->lastObjectHit();
 	if (hit_obj && 
 		!hit_obj->isAvatar())
 	{
-		if( (0 <= pick.mObjectFace) && (pick.mObjectFace < hit_obj->getNumTEs()) )
+		if( (0 <= gLastHitObjectFace) && (gLastHitObjectFace < hit_obj->getNumTEs()) )
 		{
-			LLViewerImage* image = hit_obj->getTEImage( pick.mObjectFace );
+			LLViewerImage* image = hit_obj->getTEImage( gLastHitObjectFace );
 			if( image )
 			{
 				if( mCallback )
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index 9fd8044cca539f75aa92b6870066b87988dbaeeb..4efc6f74d45fc83c95e213ce74c7e5fa5e687c48 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -145,18 +145,18 @@ LLToolCompInspect::~LLToolCompInspect()
 BOOL LLToolCompInspect::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	mMouseDown = TRUE;
-	gViewerWindow->pickAsync(x, y, mask, pickCallback);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 	return TRUE;
 }
 
-void LLToolCompInspect::pickCallback(const LLPickInfo& pick_info)
+void LLToolCompInspect::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* hit_obj = pick_info.getObject();
+	LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
 
 	if (!LLToolCompInspect::getInstance()->mMouseDown)
 	{
 		// fast click on object, but mouse is already up...just do select
-		LLToolCompInspect::getInstance()->mSelectRect->handleObjectSelection(pick_info, gSavedSettings.getBOOL("EditLinkedParts"), FALSE);
+		LLToolCompInspect::getInstance()->mSelectRect->handleObjectSelection(hit_obj, mask, gSavedSettings.getBOOL("EditLinkedParts"), FALSE);
 		return;
 	}
 
@@ -167,13 +167,13 @@ void LLToolCompInspect::pickCallback(const LLPickInfo& pick_info)
 			LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance();
 		}
 		LLToolCompInspect::getInstance()->setCurrentTool( LLToolCompInspect::getInstance()->mSelectRect );
-		LLToolCompInspect::getInstance()->mSelectRect->handlePick( pick_info );
+		LLToolCompInspect::getInstance()->mSelectRect->handleMouseDown( x, y, mask );
 
 	}
 	else
 	{
 		LLToolCompInspect::getInstance()->setCurrentTool( LLToolCompInspect::getInstance()->mSelectRect );
-		LLToolCompInspect::getInstance()->mSelectRect->handlePick( pick_info );
+		LLToolCompInspect::getInstance()->mSelectRect->handleMouseDown( x, y, mask);
 	}
 }
 
@@ -218,19 +218,19 @@ BOOL LLToolCompTranslate::handleHover(S32 x, S32 y, MASK mask)
 BOOL LLToolCompTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	mMouseDown = TRUE;
-	gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, TRUE);
 	return TRUE;
 }
 
-void LLToolCompTranslate::pickCallback(const LLPickInfo& pick_info)
+void LLToolCompTranslate::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* hit_obj = pick_info.getObject();
+	LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
 
-	LLToolCompTranslate::getInstance()->mManip->highlightManipulators(pick_info.mMousePt.mX, pick_info.mMousePt.mY);
+	LLToolCompTranslate::getInstance()->mManip->highlightManipulators(x, y);
 	if (!LLToolCompTranslate::getInstance()->mMouseDown)
 	{
 		// fast click on object, but mouse is already up...just do select
-		LLToolCompTranslate::getInstance()->mSelectRect->handleObjectSelection(pick_info, gSavedSettings.getBOOL("EditLinkedParts"), FALSE);
+		LLToolCompTranslate::getInstance()->mSelectRect->handleObjectSelection(hit_obj, mask, gSavedSettings.getBOOL("EditLinkedParts"), FALSE);
 		return;
 	}
 
@@ -246,12 +246,12 @@ void LLToolCompTranslate::pickCallback(const LLPickInfo& pick_info)
 		if(	LLManip::LL_NO_PART != LLToolCompTranslate::getInstance()->mManip->getHighlightedPart() && can_move)
 		{
 			LLToolCompTranslate::getInstance()->setCurrentTool( LLToolCompTranslate::getInstance()->mManip );
-			LLToolCompTranslate::getInstance()->mManip->handleMouseDownOnPart( pick_info.mMousePt.mX, pick_info.mMousePt.mY, pick_info.mKeyMask );
+			LLToolCompTranslate::getInstance()->mManip->handleMouseDownOnPart( x, y, mask );
 		}
 		else
 		{
 			LLToolCompTranslate::getInstance()->setCurrentTool( LLToolCompTranslate::getInstance()->mSelectRect );
-			LLToolCompTranslate::getInstance()->mSelectRect->handlePick( pick_info );
+			LLToolCompTranslate::getInstance()->mSelectRect->handleMouseDown( x, y, mask );
 
 			// *TODO: add toggle to trigger old click-drag functionality
 			// LLToolCompTranslate::getInstance()->mManip->handleMouseDownOnPart( XY_part, x, y, mask);
@@ -260,7 +260,7 @@ void LLToolCompTranslate::pickCallback(const LLPickInfo& pick_info)
 	else
 	{
 		LLToolCompTranslate::getInstance()->setCurrentTool( LLToolCompTranslate::getInstance()->mSelectRect );
-		LLToolCompTranslate::getInstance()->mSelectRect->handlePick( pick_info );
+		LLToolCompTranslate::getInstance()->mSelectRect->handleMouseDown( x, y, mask);
 	}
 }
 
@@ -342,19 +342,19 @@ BOOL LLToolCompScale::handleHover(S32 x, S32 y, MASK mask)
 BOOL LLToolCompScale::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	mMouseDown = TRUE;
-	gViewerWindow->pickAsync(x, y, mask, pickCallback);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 	return TRUE;
 }
 
-void LLToolCompScale::pickCallback(const LLPickInfo& pick_info)
+void LLToolCompScale::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* hit_obj = pick_info.getObject();
+	LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
 
-	LLToolCompScale::getInstance()->mManip->highlightManipulators(pick_info.mMousePt.mX, pick_info.mMousePt.mY);
+	LLToolCompScale::getInstance()->mManip->highlightManipulators(x, y);
 	if (!LLToolCompScale::getInstance()->mMouseDown)
 	{
 		// fast click on object, but mouse is already up...just do select
-		LLToolCompScale::getInstance()->mSelectRect->handleObjectSelection(pick_info, gSavedSettings.getBOOL("EditLinkedParts"), FALSE);
+		LLToolCompScale::getInstance()->mSelectRect->handleObjectSelection(hit_obj, mask, gSavedSettings.getBOOL("EditLinkedParts"), FALSE);
 
 		return;
 	}
@@ -368,18 +368,18 @@ void LLToolCompScale::pickCallback(const LLPickInfo& pick_info)
 		if(	LLManip::LL_NO_PART != LLToolCompScale::getInstance()->mManip->getHighlightedPart() )
 		{
 			LLToolCompScale::getInstance()->setCurrentTool( LLToolCompScale::getInstance()->mManip );
-			LLToolCompScale::getInstance()->mManip->handleMouseDownOnPart( pick_info.mMousePt.mX, pick_info.mMousePt.mY, pick_info.mKeyMask );
+			LLToolCompScale::getInstance()->mManip->handleMouseDownOnPart( x, y, mask );
 		}
 		else
 		{
 			LLToolCompScale::getInstance()->setCurrentTool( LLToolCompScale::getInstance()->mSelectRect );
-			LLToolCompScale::getInstance()->mSelectRect->handlePick( pick_info );
+			LLToolCompScale::getInstance()->mSelectRect->handleMouseDown( x, y, mask );
 		}
 	}
 	else
 	{
 		LLToolCompScale::getInstance()->setCurrentTool( LLToolCompScale::getInstance()->mSelectRect );
-		LLToolCompScale::getInstance()->mSelectRect->handlePick( pick_info );
+		LLToolCompScale::getInstance()->mCur->handleMouseDown( x, y, mask );
 	}
 }
 
@@ -457,15 +457,15 @@ BOOL LLToolCompCreate::handleMouseDown(S32 x, S32 y, MASK mask)
 	BOOL handled = FALSE;
 	mMouseDown = TRUE;
 
-	if ( (mask == MASK_SHIFT) || (mask == MASK_CONTROL) )
+	if ( !(mask == MASK_SHIFT) && !(mask == MASK_CONTROL) )
 	{
-		gViewerWindow->pickAsync(x, y, mask, pickCallback);
-		handled = TRUE;
+		setCurrentTool( mPlacer );
+		handled = mPlacer->placeObject( x, y, mask );
 	}
 	else
 	{
-		setCurrentTool( mPlacer );
-		handled = mPlacer->placeObject( x, y, mask );
+		gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
+		handled = TRUE;
 	}
 	
 	mObjectPlacedOnMouseDown = TRUE;
@@ -473,15 +473,15 @@ BOOL LLToolCompCreate::handleMouseDown(S32 x, S32 y, MASK mask)
 	return TRUE;
 }
 
-void LLToolCompCreate::pickCallback(const LLPickInfo& pick_info)
+void LLToolCompCreate::pickCallback(S32 x, S32 y, MASK mask)
 {
 	// *NOTE: We mask off shift and control, so you cannot
 	// multi-select multiple objects with the create tool.
-	MASK mask = (pick_info.mKeyMask & ~MASK_SHIFT);
+	mask = (mask & ~MASK_SHIFT);
 	mask = (mask & ~MASK_CONTROL);
 
 	LLToolCompCreate::getInstance()->setCurrentTool( LLToolCompCreate::getInstance()->mSelectRect );
-	LLToolCompCreate::getInstance()->mSelectRect->handlePick( pick_info );
+	LLToolCompCreate::getInstance()->mSelectRect->handleMouseDown( x, y, mask);
 }
 
 BOOL LLToolCompCreate::handleDoubleClick(S32 x, S32 y, MASK mask)
@@ -543,19 +543,19 @@ BOOL LLToolCompRotate::handleHover(S32 x, S32 y, MASK mask)
 BOOL LLToolCompRotate::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	mMouseDown = TRUE;
-	gViewerWindow->pickAsync(x, y, mask, pickCallback);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 	return TRUE;
 }
 
-void LLToolCompRotate::pickCallback(const LLPickInfo& pick_info)
+void LLToolCompRotate::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* hit_obj = pick_info.getObject();
+	LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
 
-	LLToolCompRotate::getInstance()->mManip->highlightManipulators(pick_info.mMousePt.mX, pick_info.mMousePt.mY);
+	LLToolCompRotate::getInstance()->mManip->highlightManipulators(x, y);
 	if (!LLToolCompRotate::getInstance()->mMouseDown)
 	{
 		// fast click on object, but mouse is already up...just do select
-		LLToolCompRotate::getInstance()->mSelectRect->handleObjectSelection(pick_info, gSavedSettings.getBOOL("EditLinkedParts"), FALSE);
+		LLToolCompRotate::getInstance()->mSelectRect->handleObjectSelection(hit_obj, mask, gSavedSettings.getBOOL("EditLinkedParts"), FALSE);
 		return;
 	}
 	
@@ -568,18 +568,18 @@ void LLToolCompRotate::pickCallback(const LLPickInfo& pick_info)
 		if(	LLManip::LL_NO_PART != LLToolCompRotate::getInstance()->mManip->getHighlightedPart() )
 		{
 			LLToolCompRotate::getInstance()->setCurrentTool( LLToolCompRotate::getInstance()->mManip );
-			LLToolCompRotate::getInstance()->mManip->handleMouseDownOnPart( pick_info.mMousePt.mX, pick_info.mMousePt.mY, pick_info.mKeyMask );
+			LLToolCompRotate::getInstance()->mManip->handleMouseDownOnPart( x, y, mask );
 		}
 		else
 		{
 			LLToolCompRotate::getInstance()->setCurrentTool( LLToolCompRotate::getInstance()->mSelectRect );
-			LLToolCompRotate::getInstance()->mSelectRect->handlePick( pick_info );
+			LLToolCompRotate::getInstance()->mSelectRect->handleMouseDown( x, y, mask );
 		}
 	}
 	else
 	{
 		LLToolCompRotate::getInstance()->setCurrentTool( LLToolCompRotate::getInstance()->mSelectRect );
-		LLToolCompRotate::getInstance()->mSelectRect->handlePick( pick_info );
+		LLToolCompRotate::getInstance()->mCur->handleMouseDown( x, y, mask );
 	}
 }
 
diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h
index 5547a6d15b01e4607df07016adb728938b6579f9..8926cd34d21dbc778b5f4d7ba133156c22b69dca 100644
--- a/indra/newview/lltoolcomp.h
+++ b/indra/newview/lltoolcomp.h
@@ -37,7 +37,6 @@
 class LLManip;
 class LLToolSelectRect;
 class LLToolPlacer;
-class LLPickInfo;
 
 class LLView;
 class LLTextBox;
@@ -115,7 +114,7 @@ class LLToolCompInspect : public LLToolComposite, public LLSingleton<LLToolCompI
     virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask);
     virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask);
 
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 };
 
 //-----------------------------------------------------------------------
@@ -136,7 +135,7 @@ class LLToolCompTranslate : public LLToolComposite, public LLSingleton<LLToolCom
 
 	virtual LLTool*		getOverrideTool(MASK mask);
 
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 };
 
 //-----------------------------------------------------------------------
@@ -157,7 +156,7 @@ class LLToolCompScale : public LLToolComposite, public LLSingleton<LLToolCompSca
 
 	virtual LLTool*		getOverrideTool(MASK mask);
 	
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 };
 
 
@@ -179,7 +178,7 @@ class LLToolCompRotate : public LLToolComposite, public LLSingleton<LLToolCompRo
 
 	virtual LLTool*		getOverrideTool(MASK mask);
 
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 
 protected:
 };
@@ -198,7 +197,7 @@ class LLToolCompCreate : public LLToolComposite, public LLSingleton<LLToolCompCr
     virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask);
 	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask);
 	
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 protected:
 	LLToolPlacer*		mPlacer;
 	BOOL				mObjectPlacedOnMouseDown;
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 109a11755bbfe87fead3cdd08090c4a1122d2cce..940f5ba62d92449118ca5f945ee98fdf5fbe7dd9 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -988,37 +988,32 @@ void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAccep
 	mDrop = drop;
 	if (mDrop)
 	{
+		gPickFaces = TRUE;
 		// don't allow drag and drop onto transparent objects
-		pickCallback(gViewerWindow->pickImmediate(x, y, FALSE));
+		gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, pickCallback, FALSE);
 	}
 	else
 	{
+		// Don't pick faces during hover.  Nothing currently requires per-face
+		// data.
 		// don't allow drag and drop onto transparent objects
-		gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE);
+		gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, FALSE);
 	}
 
 	*acceptance = mLastAccept;
 }
 
-void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
+void LLToolDragAndDrop::pickCallback(S32 x, S32 y, MASK mask)
 {
 	EDropTarget target = DT_NONE;
 	S32	hit_face = -1;
 
-	LLViewerObject* hit_obj = pick_info.getObject();
+	LLViewerObject* hit_obj = gViewerWindow->lastNonFloraObjectHit();
 	LLSelectMgr::getInstance()->unhighlightAll();
 
 	// Treat attachments as part of the avatar they are attached to.
 	if (hit_obj)
 	{
-		// don't allow drag and drop on grass, trees, etc.
-		if(pick_info.mPickType == LLPickInfo::PICK_FLORA)
-		{
-			LLToolDragAndDrop::getInstance()->mCursor = UI_CURSOR_NO;
-			gViewerWindow->getWindow()->setCursor( LLToolDragAndDrop::getInstance()->mCursor );
-			return;
-		}
-
 		if(hit_obj->isAttachment() && !hit_obj->isHUDAttachment())
 		{
 			LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj );
@@ -1049,12 +1044,12 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
 		else
 		{
 			target = DT_OBJECT;
-			hit_face = pick_info.mObjectFace;
+			hit_face = gLastHitNonFloraObjectFace;
 			// if any item being dragged will be applied to the object under our cursor
 			// highlight that object
 			for (S32 i = 0; i < (S32)LLToolDragAndDrop::getInstance()->mCargoIDs.size(); i++)
 			{
-				if (LLToolDragAndDrop::getInstance()->mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL))
+				if (LLToolDragAndDrop::getInstance()->mCargoTypes[i] != DAD_OBJECT || (mask & MASK_CONTROL))
 				{
 					LLSelectMgr::getInstance()->highlightObjectAndFamily(hit_obj);
 					break;
@@ -1062,7 +1057,7 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
 			}
 		}
 	}
-	else if(pick_info.mPickType == LLPickInfo::PICK_LAND)
+	else if(gLastHitLand)
 	{
 		target = DT_LAND;
 		hit_face = -1;
@@ -1078,7 +1073,7 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
 			(U32)LLToolDragAndDrop::getInstance()->mLastAccept,
 			(U32)callMemberFunction((*LLToolDragAndDrop::getInstance()), 
 				LLToolDragAndDrop::getInstance()->sDragAndDrop3d[LLToolDragAndDrop::getInstance()->mCargoTypes[LLToolDragAndDrop::getInstance()->mCurItemIndex]][target])
-				(hit_obj, hit_face, pick_info.mKeyMask, FALSE));
+				(hit_obj, hit_face, mask, FALSE));
 	}
 
 	if (LLToolDragAndDrop::getInstance()->mDrop && (U32)LLToolDragAndDrop::getInstance()->mLastAccept >= ACCEPT_YES_COPY_SINGLE)
@@ -1100,7 +1095,7 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
 			// Call the right implementation function
 			(U32)callMemberFunction((*LLToolDragAndDrop::getInstance()), 
 				LLToolDragAndDrop::getInstance()->sDragAndDrop3d[LLToolDragAndDrop::getInstance()->mCargoTypes[LLToolDragAndDrop::getInstance()->mCurItemIndex]][target])
-				(hit_obj, hit_face, pick_info.mKeyMask, TRUE);
+				(hit_obj, hit_face, mask, TRUE);
 		}
 	}
 
@@ -1147,7 +1142,7 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
 		llassert( FALSE );
 	}
 
-	LLToolDragAndDrop::getInstance()->mLastHitPos = pick_info.mPosGlobal;
+	LLToolDragAndDrop::getInstance()->mLastHitPos = gLastHitPosGlobal + gLastHitObjectOffset;
 	LLToolDragAndDrop::getInstance()->mLastCameraPos = gAgent.getCameraPositionGlobal();
 
 	gViewerWindow->getWindow()->setCursor( LLToolDragAndDrop::getInstance()->mCursor );
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 8e2788a1739033c97a6c5112021578a9e6ff3600..8f6d1713fa68ab19247c230547800ed597bf0a31 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -45,7 +45,6 @@
 class LLToolDragAndDrop;
 class LLViewerRegion;
 class LLVOAvatar;
-class LLPickInfo;
 
 class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop>
 {
@@ -107,7 +106,7 @@ class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop>
 					EAcceptance* acceptance);
 	void dragOrDrop3D(S32 x, S32 y, MASK mask, BOOL drop,
 					  EAcceptance* acceptance);
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 
 protected:
 
diff --git a/indra/newview/lltoolface.cpp b/indra/newview/lltoolface.cpp
index 138fc9960687ff16d8fd3596f88f4f1a9bc34df9..324891318288e6f5a66243f3666eaad204065579 100644
--- a/indra/newview/lltoolface.cpp
+++ b/indra/newview/lltoolface.cpp
@@ -82,16 +82,17 @@ BOOL LLToolFace::handleDoubleClick(S32 x, S32 y, MASK mask)
 
 BOOL LLToolFace::handleMouseDown(S32 x, S32 y, MASK mask)
 {
-	gViewerWindow->pickAsync(x, y, mask, pickCallback);
+	gPickFaces = TRUE;
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 	return TRUE;
 }
 
-void LLToolFace::pickCallback(const LLPickInfo& pick_info)
+void LLToolFace::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* hit_obj	= pick_info.getObject();
+	LLViewerObject* hit_obj	= gViewerWindow->lastObjectHit();
 	if (hit_obj)
 	{
-		S32 hit_face = pick_info.mObjectFace;
+		S32 hit_face = gLastHitObjectFace;
 		
 		if (hit_obj->isAvatar())
 		{
@@ -101,7 +102,7 @@ void LLToolFace::pickCallback(const LLPickInfo& pick_info)
 
 		// ...clicked on a world object, try to pick the appropriate face
 
-		if (pick_info.mKeyMask & MASK_SHIFT)
+		if (mask & MASK_SHIFT)
 		{
 			// If object not selected, need to inform sim
 			if ( !hit_obj->isSelected() )
@@ -132,7 +133,7 @@ void LLToolFace::pickCallback(const LLPickInfo& pick_info)
 	}
 	else
 	{
-		if (!(pick_info.mKeyMask == MASK_SHIFT))
+		if (!(mask == MASK_SHIFT))
 		{
 			LLSelectMgr::getInstance()->deselectAll();
 		}
diff --git a/indra/newview/lltoolface.h b/indra/newview/lltoolface.h
index 113dcc9fbd814e0c76ee805750c24a5da3866130..f573bfa9c50e4fea05b2182edb14c190815a812a 100644
--- a/indra/newview/lltoolface.h
+++ b/indra/newview/lltoolface.h
@@ -35,7 +35,6 @@
 #include "lltool.h"
 
 class LLViewerObject;
-class LLPickInfo;
 
 class LLToolFace
 :	public LLTool, public LLSingleton<LLToolFace>
@@ -50,7 +49,7 @@ class LLToolFace
 	virtual void	handleDeselect();
 	virtual void	render();			// draw face highlights
 
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 };
 
 #endif
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index 3fdf24bbc367687ae61c111ed598293d33f9c2d2..b46d25583a68701e3581fac0067a72067020ae17 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -126,28 +126,28 @@ BOOL LLToolCamera::handleMouseDown(S32 x, S32 y, MASK mask)
 
 	gViewerWindow->hideCursor();
 
-	gViewerWindow->pickAsync(x, y, mask, pickCallback);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 	// don't steal focus from UI
 	return FALSE;
 }
 
-void LLToolCamera::pickCallback(const LLPickInfo& pick_info)
+void LLToolCamera::pickCallback(S32 x, S32 y, MASK mask)
 {
 	if (!LLToolCamera::getInstance()->hasMouseCapture())
 	{
 		return;
 	}
 
-	LLToolCamera::getInstance()->mMouseDownX = pick_info.mMousePt.mX;
-	LLToolCamera::getInstance()->mMouseDownY = pick_info.mMousePt.mY;
+	LLToolCamera::getInstance()->mMouseDownX = x;
+	LLToolCamera::getInstance()->mMouseDownY = y;
 
 	gViewerWindow->moveCursorToCenter();
 
 	// Potentially recenter if click outside rectangle
-	LLViewerObject* hit_obj = pick_info.getObject();
+	LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
 
 	// Check for hit the sky, or some other invalid point
-	if (!hit_obj && pick_info.mPosGlobal.isExactlyZero())
+	if (!hit_obj && gLastHitPosGlobal.isExactlyZero())
 	{
 		LLToolCamera::getInstance()->mValidClickPoint = FALSE;
 		return;
@@ -195,27 +195,29 @@ void LLToolCamera::pickCallback(const LLPickInfo& pick_info)
 		}
 	}
 	//RN: check to see if this is mouse-driving as opposed to ALT-zoom or Focus tool
-	else if (pick_info.mKeyMask & MASK_ALT || 
+	else if (mask & MASK_ALT || 
 			(LLToolMgr::getInstance()->getCurrentTool()->getName() == "Camera")) 
 	{
-		LLViewerObject* hit_obj = pick_info.getObject();
+		LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
 		if (hit_obj)
 		{
 			// ...clicked on a world object, so focus at its position
+			// Use "gLastHitPosGlobal" because it's correct for avatar heads,
+			// not pelvis.
 			if (!hit_obj->isHUDAttachment())
 			{
 				gAgent.setFocusOnAvatar(FALSE, ANIMATE);
-				gAgent.setFocusGlobal(pick_info);
+				gAgent.setFocusGlobal( gLastHitObjectOffset + gLastHitPosGlobal, gLastHitObjectID);
 			}
 		}
-		else if (!pick_info.mPosGlobal.isExactlyZero())
+		else if (!gLastHitPosGlobal.isExactlyZero())
 		{
 			// Hit the ground
 			gAgent.setFocusOnAvatar(FALSE, ANIMATE);
-			gAgent.setFocusGlobal(pick_info);
+			gAgent.setFocusGlobal( gLastHitPosGlobal, gLastHitObjectID);
 		}
 
-		if (!(pick_info.mKeyMask & MASK_ALT) &&
+		if (!(mask & MASK_ALT) &&
 			gAgent.cameraThirdPerson() &&
 			gViewerWindow->getLeftMouseDown() && 
 			!gSavedSettings.getBOOL("FreezeTime") &&
@@ -236,7 +238,7 @@ void LLToolCamera::pickCallback(const LLPickInfo& pick_info)
 		LLVector3d cam_pos = gAgent.getCameraPositionGlobal();
 		cam_pos -= LLVector3d(LLViewerCamera::getInstance()->getLeftAxis() * gAgent.calcCustomizeAvatarUIOffset( cam_pos ));
 
-		gAgent.setCameraPosAndFocusGlobal( cam_pos, pick_info.mPosGlobal, pick_info.mObjectID);
+		gAgent.setCameraPosAndFocusGlobal( cam_pos, gLastHitObjectOffset + gLastHitPosGlobal, gLastHitObjectID);
 	}
 }
 
diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h
index c8c748a1b013de99ef6f32367f06a05d09ea931e..2ed456b188171bc42d4d332a275fe48ba9f942fc 100644
--- a/indra/newview/lltoolfocus.h
+++ b/indra/newview/lltoolfocus.h
@@ -34,8 +34,6 @@
 
 #include "lltool.h"
 
-class LLPickInfo;
-
 class LLToolCamera
 :	public LLTool, public LLSingleton<LLToolCamera>
 {
@@ -54,7 +52,7 @@ class LLToolCamera
 
 	virtual LLTool*	getOverrideTool(MASK mask) { return NULL; }
 
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 	BOOL mouseSteerMode() { return mMouseSteering; }
 
 protected:
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index 13037c6a20b36b3587abe6fb026eac7fd792e604..a41e9381f69f8bd4e9e23fe25e2b6501cda69be6 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -78,6 +78,16 @@ LLToolGrab::LLToolGrab( LLToolComposite* composite )
 :	LLTool( std::string("Grab"), composite ),
 	mMode( GRAB_INACTIVE ),
 	mVerticalDragging( FALSE ),
+	mHitLand(FALSE),
+	mHitObjectID(),
+	mGrabObject( NULL ),
+	mLastMouseX(0),
+	mLastMouseY(0),
+	mMouseDownX( -1 ),
+	mMouseDownY( -1 ),
+	mMouseMask(0),
+	mAccumDeltaX(0),
+	mAccumDeltaY(0),
 	mHasMoved( FALSE ),
 	mOutsideSlop(FALSE),
 	mDeselectedThisClick(FALSE),
@@ -128,23 +138,24 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask)
 		llinfos << "LLToolGrab handleMouseDown" << llendl;
 	}
 
+	mHitLand = FALSE;
+
 	// call the base class to propogate info to sim
 	LLTool::handleMouseDown(x, y, mask);
 	
 	if (!gAgent.leftButtonGrabbed())
 	{
 		// can grab transparent objects (how touch event propagates, scripters rely on this)
-		gViewerWindow->pickAsync(x, y, mask, pickCallback, TRUE);
+		gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, TRUE);
 	}
 	return TRUE;
 }
 
-void LLToolGrab::pickCallback(const LLPickInfo& pick_info)
+void LLToolGrab::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLToolGrab::getInstance()->mGrabPick = pick_info;
-	LLViewerObject	*objectp = pick_info.getObject();
+	LLViewerObject	*objectp = gObjectList.findObject( gLastHitObjectID );
 
-	BOOL extend_select = (pick_info.mKeyMask & MASK_SHIFT);
+	BOOL extend_select = (mask & MASK_SHIFT);
 
 	if (!extend_select && !LLSelectMgr::getInstance()->getSelection()->isEmpty())
 	{
@@ -161,22 +172,23 @@ void LLToolGrab::pickCallback(const LLPickInfo& pick_info)
 	{
 		LLToolGrab::getInstance()->setMouseCapture(TRUE);
 		LLToolGrab::getInstance()->mMode = GRAB_NOOBJECT;
-		LLToolGrab::getInstance()->mGrabPick.mObjectID.setNull();
+		LLToolGrab::getInstance()->mHitObjectID.setNull();
 	}
 	else
 	{
-		LLToolGrab::getInstance()->handleObjectHit(LLToolGrab::getInstance()->mGrabPick);
+		LLToolGrab::getInstance()->handleObjectHit(objectp, x, y, mask);
 	}
 }
 
-BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
+BOOL LLToolGrab::handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mask)
 {
-	mGrabPick = info;
-	LLViewerObject* objectp = mGrabPick.getObject();
+	mMouseDownX = x;
+	mMouseDownY = y;
+	mMouseMask = mask;
 
 	if (gDebugClicks)
 	{
-		llinfos << "LLToolGrab handleObjectHit " << info.mMousePt.mX << "," << info.mMousePt.mY << llendl;
+		llinfos << "LLToolGrab handleObjectHit " << mMouseDownX << "," << mMouseDownY << llendl;
 	}
 
 	if (NULL == objectp) // unexpected
@@ -197,6 +209,8 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
 
 	setMouseCapture( TRUE );
 
+	mHitObjectID = objectp->getID();
+
 	// Grabs always start from the root
 	// objectp = (LLViewerObject *)objectp->getRoot();
 
@@ -216,13 +230,13 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
 		if (gAgent.cameraMouselook() && !script_touch)
 		{
 			mMode = GRAB_LOCKED;
-			gViewerWindow->hideCursor();
-			gViewerWindow->moveCursorToCenter();
 		}
 		else
 		{
 			mMode = GRAB_NONPHYSICAL;
 		}
+		gViewerWindow->hideCursor();
+		gViewerWindow->moveCursorToCenter();
 		// Don't bail out here, go on and grab so buttons can get
 		// their "touched" event.
 	}
@@ -247,18 +261,20 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
 
 	// Always send "touched" message
 
-	mLastMouseX = gViewerWindow->getCurrentMouseX();
-	mLastMouseY = gViewerWindow->getCurrentMouseY();
 	mAccumDeltaX = 0;
 	mAccumDeltaY = 0;
 	mHasMoved = FALSE;
 	mOutsideSlop = FALSE;
 
-	mVerticalDragging = (info.mKeyMask == MASK_VERTICAL) || gGrabBtnVertical;
+	mGrabObject = objectp;
 
-	startGrab();
+	mGrabOffset.clearVec();
 
-	if ((info.mKeyMask == MASK_SPIN) || gGrabBtnSpin)
+	mVerticalDragging = (mask == MASK_VERTICAL) || gGrabBtnVertical;
+
+	startGrab(x, y);
+
+	if ((mask == MASK_SPIN) || gGrabBtnSpin)
 	{
 		startSpin();
 	}
@@ -266,10 +282,10 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
 	LLSelectMgr::getInstance()->updateSelectionCenter();		// update selection beam
 
 	// update point at
-	LLViewerObject *edit_object = info.getObject();
-	if (edit_object && info.mPickType != LLPickInfo::PICK_FLORA)
+	LLViewerObject *edit_object = gObjectList.findObject(mHitObjectID);
+	if (edit_object)
 	{
-		LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(info.mPosGlobal);
+		LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(gLastHitNonFloraPosGlobal);
 		local_edit_point -= edit_object->getPositionAgent();
 		local_edit_point = local_edit_point * ~edit_object->getRenderRotation();
 		gAgent.setPointAt(POINTAT_TARGET_GRAB, edit_object, local_edit_point );
@@ -291,15 +307,10 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info)
 
 void LLToolGrab::startSpin()
 {
-	LLViewerObject* objectp = mGrabPick.getObject();
-	if (!objectp)
-	{
-		return;
-	}
 	mSpinGrabbing = TRUE;
 
 	// Was saveSelectedObjectTransform()
-	LLViewerObject *root = (LLViewerObject *)objectp->getRoot();
+	LLViewerObject *root = (LLViewerObject *)mGrabObject->getRoot();
 	mSpinRotation = root->getRotation();
 
 	LLMessageSystem *msg = gMessageSystem;
@@ -308,8 +319,8 @@ void LLToolGrab::startSpin()
 	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
 	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 	msg->nextBlockFast(_PREHASH_ObjectData);
-	msg->addUUIDFast(_PREHASH_ObjectID, mGrabPick.mObjectID );
-	msg->sendMessage( objectp->getRegion()->getHost() );
+	msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() );
+	msg->sendMessage( mGrabObject->getRegion()->getHost() );
 }
 
 
@@ -317,12 +328,6 @@ void LLToolGrab::stopSpin()
 {
 	mSpinGrabbing = FALSE;
 
-	LLViewerObject* objectp = mGrabPick.getObject();
-	if (!objectp)
-	{
-		return;
-	}
-
 	LLMessageSystem *msg = gMessageSystem;
 	switch(mMode)
 	{
@@ -334,8 +339,8 @@ void LLToolGrab::stopSpin()
 		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
 		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 		msg->nextBlockFast(_PREHASH_ObjectData);
-		msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() );
-		msg->sendMessage( objectp->getRegion()->getHost() );
+		msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() );
+		msg->sendMessage( mGrabObject->getRegion()->getHost() );
 		break;
 
 	case GRAB_NOOBJECT:
@@ -347,17 +352,11 @@ void LLToolGrab::stopSpin()
 }
 
 
-void LLToolGrab::startGrab()
+void LLToolGrab::startGrab(S32 x, S32 y)
 {
 	// Compute grab_offset in the OBJECT's root's coordinate frame
 	// (sometimes root == object)
-	LLViewerObject* objectp = mGrabPick.getObject();
-	if (!objectp)
-	{
-		return;
-	}
-
-	LLViewerObject *root = (LLViewerObject *)objectp->getRoot();
+	LLViewerObject *root = (LLViewerObject *)mGrabObject->getRoot();
 
 	// drag from center
 	LLVector3d grab_start_global = root->getPositionGlobal();
@@ -366,7 +365,7 @@ void LLToolGrab::startGrab()
 	// JC - This code looks wonky, but I believe it does the right thing.
 	// Otherwise, when you grab a linked object set, it "pops" on the start
 	// of the drag.
-	LLVector3d grab_offsetd = root->getPositionGlobal() - objectp->getPositionGlobal();
+	LLVector3d grab_offsetd = root->getPositionGlobal() - mGrabObject->getPositionGlobal();
 
 	LLVector3 grab_offset;
 	grab_offset.setVec(grab_offsetd);
@@ -385,16 +384,9 @@ void LLToolGrab::startGrab()
 	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 	msg->nextBlockFast(_PREHASH_ObjectData);
-	msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID);
+	msg->addU32Fast(_PREHASH_LocalID, mGrabObject->mLocalID);
 	msg->addVector3Fast(_PREHASH_GrabOffset, grab_offset );
-	msg->nextBlock("SurfaceInfo");
-	msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords));
-	msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords));
-	msg->addS32Fast(_PREHASH_FaceIndex, mGrabPick.mObjectFace);
-	msg->addVector3("Position", mGrabPick.mIntersection);
-	msg->addVector3("Normal", mGrabPick.mNormal);
-	msg->addVector3("Binormal", mGrabPick.mBinormal);
-	msg->sendMessage( objectp->getRegion()->getHost());
+	msg->sendMessage( mGrabObject->getRegion()->getHost());
 
 	mGrabOffsetFromCenterInitial = grab_offset;
 	mGrabHiddenOffsetFromCamera = mDragStartFromCamera;
@@ -405,6 +397,9 @@ void LLToolGrab::startGrab()
 
 BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask)
 {
+	mLastMouseX = x;
+	mLastMouseY = y;
+
 	if (!gViewerWindow->getLeftMouseDown())
 	{
 		gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
@@ -416,11 +411,8 @@ BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask)
 	switch( mMode )
 	{
 	case GRAB_ACTIVE_CENTER:
-		handleHoverActive( x, y, mask );	// cursor hidden
-		break;
-		
 	case GRAB_NONPHYSICAL:
-		handleHoverNonPhysical(x, y, mask);
+		handleHoverActive( x, y, mask );	// cursor hidden
 		break;
 
 	case GRAB_INACTIVE:
@@ -434,24 +426,18 @@ BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask)
 
 	}
 
-	mLastMouseX = x;
-	mLastMouseY = y;
-	
 	return TRUE;
 }
 
-const F32 GRAB_SENSITIVITY_X = 0.0075f;
-const F32 GRAB_SENSITIVITY_Y = 0.0075f;
-
 
 
 		
 // Dragging.
 void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* objectp = mGrabPick.getObject();
-	if (!objectp || !hasMouseCapture() ) return;
-	if (objectp->isDead())
+	llassert( hasMouseCapture() );
+	llassert( mGrabObject );
+	if (mGrabObject->isDead())
 	{
 		// Bail out of drag because object has been killed
 		setMouseCapture(FALSE);
@@ -480,7 +466,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 		// ...switch to horizontal dragging
 		mVerticalDragging = FALSE;
 
-		mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp);
+		mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, mGrabObject);
 		mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal();
 	}
 	else if (!mVerticalDragging && (mask == MASK_VERTICAL) )
@@ -488,13 +474,16 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 		// ...switch to vertical dragging
 		mVerticalDragging = TRUE;
 
-		mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp);
+		mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, mGrabObject);
 		mDragStartFromCamera = mDragStartPointGlobal - gAgent.getCameraPositionGlobal();
 	}
 
 	const F32 RADIANS_PER_PIXEL_X = 0.01f;
 	const F32 RADIANS_PER_PIXEL_Y = 0.01f;
 
+	const F32 SENSITIVITY_X = 0.0075f;
+	const F32 SENSITIVITY_Y = 0.0075f;
+
 	S32 dx = x - (gViewerWindow->getWindowWidth() / 2);
 	S32 dy = y - (gViewerWindow->getWindowHeight() / 2);
 
@@ -536,9 +525,9 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
 			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 			msg->nextBlockFast(_PREHASH_ObjectData);
-			msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() );
+			msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() );
 			msg->addQuatFast(_PREHASH_Rotation, mSpinRotation );
-			msg->sendMessage( objectp->getRegion()->getHost() );
+			msg->sendMessage( mGrabObject->getRegion()->getHost() );
 		}
 		else
 		{
@@ -566,8 +555,8 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 			}
 
 			mGrabHiddenOffsetFromCamera = mGrabHiddenOffsetFromCamera 
-				+ (x_part * (-dx * GRAB_SENSITIVITY_X)) 
-				+ (y_part * ( dy * GRAB_SENSITIVITY_Y));
+				+ (x_part * (-dx * SENSITIVITY_X)) 
+				+ (y_part * ( dy * SENSITIVITY_Y));
 
 
 			// Send the message to the viewer.
@@ -651,7 +640,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 				&& (grab_center_gl.mY > 24))
 			{
 				// Transmit update to simulator
-				LLVector3 grab_pos_region = objectp->getRegion()->getPosRegionFromGlobal( grab_point_global );
+				LLVector3 grab_pos_region = mGrabObject->getRegion()->getPosRegionFromGlobal( grab_point_global );
 
 				LLMessageSystem *msg = gMessageSystem;
 				msg->newMessageFast(_PREHASH_ObjectGrabUpdate);
@@ -659,19 +648,11 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 				msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 				msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 				msg->nextBlockFast(_PREHASH_ObjectData);
-				msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() );
+				msg->addUUIDFast(_PREHASH_ObjectID, mGrabObject->getID() );
 				msg->addVector3Fast(_PREHASH_GrabOffsetInitial, mGrabOffsetFromCenterInitial );
 				msg->addVector3Fast(_PREHASH_GrabPosition, grab_pos_region );
 				msg->addU32Fast(_PREHASH_TimeSinceLast, dt_milliseconds );
-				msg->nextBlock("SurfaceInfo");
-				msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords));
-				msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords));
-				msg->addS32Fast(_PREHASH_FaceIndex, mGrabPick.mObjectFace);
-				msg->addVector3("Position", mGrabPick.mIntersection);
-				msg->addVector3("Normal", mGrabPick.mNormal);
-				msg->addVector3("Binormal", mGrabPick.mBinormal);
-
-				msg->sendMessage( objectp->getRegion()->getHost() );
+				msg->sendMessage( mGrabObject->getRegion()->getHost() );
 			}
 		}
 
@@ -685,8 +666,8 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 	if (mHasMoved)
 	{
 		if (!gAgent.cameraMouselook() && 
-			!objectp->isHUDAttachment() && 
-			objectp->getRoot() == gAgent.getAvatarObject()->getRoot())
+			!mGrabObject->isHUDAttachment() && 
+			mGrabObject->getRoot() == gAgent.getAvatarObject()->getRoot())
 		{
 			// force focus to point in space where we were looking previously
 			gAgent.setFocusGlobal(gAgent.calcFocusPositionTargetGlobal(), LLUUID::null);
@@ -705,134 +686,6 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask)
 }
  
 
-void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask)
-{
-	LLViewerObject* objectp = mGrabPick.getObject();
-	if (!objectp || !hasMouseCapture() ) return;
-	if (objectp->isDead())
-	{
-		// Bail out of drag because object has been killed
-		setMouseCapture(FALSE);
-		return;
-	}
-
-	LLPickInfo pick = mGrabPick;
-	pick.mMousePt = LLCoordGL(x, y);
-	pick.getSurfaceInfo();
-
-	// compute elapsed time
-	F32 dt = mGrabTimer.getElapsedTimeAndResetF32();
-	U32 dt_milliseconds = (U32) (1000.f * dt);
-
-	// i'm not a big fan of the following code - it's been culled from the physical grab case.
-	// ideally these two would be nicely integrated - but the code in that method is a serious
-	// mess of spaghetti.  so here we go:
-
-	LLVector3 grab_pos_region(0,0,0);
-	
-	const BOOL SUPPORT_LLDETECTED_GRAB = TRUE;
-	if (SUPPORT_LLDETECTED_GRAB)
-	{
-		//--------------------------------------------------
-		// Toggle vertical dragging
-		//--------------------------------------------------
-		if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical)
-		{
-			mVerticalDragging = FALSE;
-		}
-	
-		else if (!mVerticalDragging && (mask == MASK_VERTICAL) )
-		{
-			mVerticalDragging = TRUE;
-		}
-	
-		S32 dx = x - mLastMouseX;
-		S32 dy = y - mLastMouseY;
-
-		if (dx != 0 || dy != 0)
-		{
-			mAccumDeltaX += dx;
-			mAccumDeltaY += dy;
-		
-			S32 dist_sq = mAccumDeltaX * mAccumDeltaX + mAccumDeltaY * mAccumDeltaY;
-			if (dist_sq > SLOP_DIST_SQ)
-			{
-				mOutsideSlop = TRUE;
-			}
-
-			// mouse has moved 
-			mHasMoved = TRUE;
-
-			//------------------------------------------------------
-			// Handle grabbing
-			//------------------------------------------------------
-
-			LLVector3d x_part;
-			x_part.setVec(LLViewerCamera::getInstance()->getLeftAxis());
-			x_part.mdV[VZ] = 0.0;
-			x_part.normVec();
-
-			LLVector3d y_part;
-			if( mVerticalDragging )
-			{
-				y_part.setVec(LLViewerCamera::getInstance()->getUpAxis());
-				// y_part.setVec(0.f, 0.f, 1.f);
-			}
-			else
-			{
-				// drag toward camera
-				y_part = x_part % LLVector3d::z_axis;
-				y_part.mdV[VZ] = 0.0;
-				y_part.normVec();
-			}
-
-			mGrabHiddenOffsetFromCamera = mGrabHiddenOffsetFromCamera 
-				+ (x_part * (-dx * GRAB_SENSITIVITY_X)) 
-				+ (y_part * ( dy * GRAB_SENSITIVITY_Y));
-
-		}
-		
-		// need to return offset from mGrabStartPoint
-		LLVector3d grab_point_global = gAgent.getCameraPositionGlobal() + mGrabHiddenOffsetFromCamera;
-		grab_pos_region = objectp->getRegion()->getPosRegionFromGlobal( grab_point_global );
-	}
-
-	LLMessageSystem *msg = gMessageSystem;
-	msg->newMessageFast(_PREHASH_ObjectGrabUpdate);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	msg->nextBlockFast(_PREHASH_ObjectData);
-	msg->addUUIDFast(_PREHASH_ObjectID, objectp->getID() );
-	msg->addVector3Fast(_PREHASH_GrabOffsetInitial, mGrabOffsetFromCenterInitial );
-	msg->addVector3Fast(_PREHASH_GrabPosition, grab_pos_region );
-	msg->addU32Fast(_PREHASH_TimeSinceLast, dt_milliseconds );
-	msg->nextBlock("SurfaceInfo");
-	msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
-	msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
-	msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
-	msg->addVector3("Position", pick.mIntersection);
-	msg->addVector3("Normal", pick.mNormal);
-	msg->addVector3("Binormal", pick.mBinormal);
-
-	msg->sendMessage( objectp->getRegion()->getHost() );
-
-	// update point-at / look-at
-	if (pick.mObjectFace != -1) // if the intersection was on the surface of the obejct
-	{
-		LLVector3 local_edit_point = pick.mIntersection;
-		local_edit_point -= objectp->getPositionAgent();
-		local_edit_point = local_edit_point * ~objectp->getRenderRotation();
-		gAgent.setPointAt(POINTAT_TARGET_GRAB, objectp, local_edit_point );
-		gAgent.setLookAt(LOOKAT_TARGET_SELECT, objectp, local_edit_point );
-	}
-	
-	
-	
-	gViewerWindow->setCursor(UI_CURSOR_HAND);  
-}
- 
-
 // Not dragging.  Just showing affordances
 void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask)
 {
@@ -873,7 +726,7 @@ void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask)
 	}
 	else
 	{
-		S32 dist_sq = (x-mGrabPick.mMousePt.mX) * (x-mGrabPick.mMousePt.mX) + (y-mGrabPick.mMousePt.mY) * (y-mGrabPick.mMousePt.mY);
+		S32 dist_sq = (x-mMouseDownX) * (x-mMouseDownX) + (y-mMouseDownY) * (y-mMouseDownY);
 		if( mOutsideSlop || dist_sq > SLOP_DIST_SQ )
 		{
 			mOutsideSlop = TRUE;
@@ -938,27 +791,23 @@ void LLToolGrab::stopEditing()
 
 void LLToolGrab::onMouseCaptureLost()
 {
-	LLViewerObject* objectp = mGrabPick.getObject();
-	if (!objectp)
-	{
-		gViewerWindow->showCursor();
-		return;
-	}
 	// First, fix cursor placement
 	if( !gAgent.cameraMouselook() 
-		&& (GRAB_ACTIVE_CENTER == mMode))
+		&& (GRAB_ACTIVE_CENTER == mMode || GRAB_NONPHYSICAL == mMode))
 	{
-		if (objectp->isHUDAttachment())
+		llassert( mGrabObject ); 
+
+		if (mGrabObject->isHUDAttachment())
 		{
 			// ...move cursor "naturally", as if it had moved when hidden
-			S32 x = mGrabPick.mMousePt.mX + mAccumDeltaX;
-			S32 y = mGrabPick.mMousePt.mY + mAccumDeltaY;
+			S32 x = mMouseDownX + mAccumDeltaX;
+			S32 y = mMouseDownY + mAccumDeltaY;
 			LLUI::setCursorPositionScreen(x, y);
 		}
 		else if (mHasMoved)
 		{
 			// ...move cursor back to the center of the object
-			LLVector3 grab_point_agent = objectp->getRenderPosition();
+			LLVector3 grab_point_agent = mGrabObject->getRenderPosition();
 
 			LLCoordGL gl_point;
 			if (LLViewerCamera::getInstance()->projectPosAgentToScreen(grab_point_agent, gl_point))
@@ -969,21 +818,19 @@ void LLToolGrab::onMouseCaptureLost()
 		else
 		{
 			// ...move cursor back to click position
-			LLUI::setCursorPositionScreen(mGrabPick.mMousePt.mX, mGrabPick.mMousePt.mY);
+			LLUI::setCursorPositionScreen(mMouseDownX, mMouseDownY);
 		}
 
 		gViewerWindow->showCursor();
 	}
 
 	stopGrab();
-	if (mSpinGrabbing)
 	stopSpin();
-	
 	mMode = GRAB_INACTIVE;
 
 	mHideBuildHighlight = FALSE;
 
-	mGrabPick.mObjectID.setNull();
+	mGrabObject = NULL;
 
 	LLSelectMgr::getInstance()->updateSelectionCenter();
 	gAgent.setPointAt(POINTAT_TARGET_CLEAR);
@@ -995,24 +842,6 @@ void LLToolGrab::onMouseCaptureLost()
 
 void LLToolGrab::stopGrab()
 {
-	LLViewerObject* objectp = mGrabPick.getObject();
-	if (!objectp)
-	{
-		return;
-	}
-
-	LLPickInfo pick = mGrabPick;
-
-	if (mMode == GRAB_NONPHYSICAL)
-	{
-		// for non-physical (touch) grabs,
-		// gather surface info for this degrab (mouse-up)
-		S32 x = gViewerWindow->getCurrentMouseX();
-		S32 y = gViewerWindow->getCurrentMouseY();
-		pick.mMousePt = LLCoordGL(x, y);
-		pick.getSurfaceInfo();
-	}
-
 	// Next, send messages to simulator
 	LLMessageSystem *msg = gMessageSystem;
 	switch(mMode)
@@ -1025,18 +854,11 @@ void LLToolGrab::stopGrab()
 		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 		msg->nextBlockFast(_PREHASH_ObjectData);
-		msg->addU32Fast(_PREHASH_LocalID, objectp->mLocalID);
-		msg->nextBlock("SurfaceInfo");
-		msg->addVector3("UVCoord", LLVector3(mGrabPick.mUVCoords));
-		msg->addVector3("STCoord", LLVector3(mGrabPick.mSTCoords));
-		msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
-		msg->addVector3("Position", pick.mIntersection);
-		msg->addVector3("Normal", pick.mNormal);
-		msg->addVector3("Binormal", pick.mBinormal);
-
-		msg->sendMessage(objectp->getRegion()->getHost());
+		msg->addU32Fast(_PREHASH_LocalID, mGrabObject->mLocalID);
+		msg->sendMessage(mGrabObject->getRegion()->getHost());
 
 		mVerticalDragging = FALSE;
+		mGrabOffset.clearVec();
 		break;
 
 	case GRAB_NOOBJECT:
@@ -1058,12 +880,14 @@ void LLToolGrab::render()
 
 BOOL LLToolGrab::isEditing()
 {
-	return (mGrabPick.getObject().notNull());
+	// Can't just compare to null directly due to "smart" pointer.
+	LLViewerObject *obj = mGrabObject;
+	return (obj != NULL);
 }
 
 LLViewerObject* LLToolGrab::getEditingObject()
 {
-	return mGrabPick.getObject();
+	return mGrabObject;
 }
 
 
diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h
index 696ce0742a24a9d8c5f95f1efc80bb7d2122b58b..d744c495a58d40ca0e44af6fd89be3294fc14d31 100644
--- a/indra/newview/lltoolgrab.h
+++ b/indra/newview/lltoolgrab.h
@@ -37,12 +37,10 @@
 #include "llquaternion.h"
 #include "llmemory.h"
 #include "lluuid.h"
-#include "llviewerwindow.h" // for LLPickInfo
 
 class LLView;
 class LLTextBox;
 class LLViewerObject;
-class LLPickInfo;
 
 class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab>
 {
@@ -71,15 +69,15 @@ class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab>
 	LLVector3		getGrabOffset(S32 x, S32 y);		// HACK
 
 	// Capture the mouse and start grabbing.
-	BOOL			handleObjectHit(const LLPickInfo& info);
+	BOOL			handleObjectHit(LLViewerObject *objectp, S32 x, S32 y, MASK mask);
 
 	// Certain grabs should not highlight the "Build" toolbar button
 	BOOL getHideBuildHighlight() { return mHideBuildHighlight; }
 
-	static void		pickCallback(const LLPickInfo& pick_info);
+	static void		pickCallback(S32 x, S32 y, MASK mask);
 private:
 	LLVector3d		getGrabPointGlobal();
-	void			startGrab();
+	void			startGrab(S32 x, S32 y);
 	void			stopGrab();
 
 	void			startSpin();
@@ -87,7 +85,6 @@ class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab>
 
 	void			handleHoverSpin(S32 x, S32 y, MASK mask);
 	void			handleHoverActive(S32 x, S32 y, MASK mask);
-	void			handleHoverNonPhysical(S32 x, S32 y, MASK mask);
 	void			handleHoverInactive(S32 x, S32 y, MASK mask);
 	void			handleHoverFailed(S32 x, S32 y, MASK mask);
 
@@ -99,26 +96,29 @@ class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab>
 	BOOL			mVerticalDragging;
 
 	BOOL			mHitLand;
+	LLUUID			mHitObjectID;				// if hit something, its ID
 
+	LLPointer<LLViewerObject>	mGrabObject;					// the object currently being grabbed
 	LLTimer			mGrabTimer;						// send simulator time between hover movements
 
 	LLVector3		mGrabOffsetFromCenterInitial;	// meters from CG of object
+	LLVector3		mGrabOffset;					// how far cursor currently is from grab start point, meters
 	LLVector3d		mGrabHiddenOffsetFromCamera;	// in cursor hidden drag, how far is grab offset from camera
 
 	LLVector3d		mDragStartPointGlobal;				// projected into world
 	LLVector3d		mDragStartFromCamera;			// drag start relative to camera
 
-	LLPickInfo		mGrabPick;
-
 	S32				mLastMouseX;
 	S32				mLastMouseY;
+	S32				mMouseDownX;
+	S32				mMouseDownY;
+	MASK			mMouseMask;
 	S32				mAccumDeltaX;	// since cursor hidden, how far have you moved?
 	S32				mAccumDeltaY;
 	BOOL			mHasMoved;		// has mouse moved off center at all?
 	BOOL			mOutsideSlop;	// has mouse moved outside center 5 pixels?
 	BOOL			mDeselectedThisClick;
 
-
 	BOOL			mSpinGrabbing;
 	LLQuaternion	mSpinRotation;
 
@@ -131,4 +131,3 @@ extern LLTool* gGrabTransientTool;
 
 #endif  // LL_TOOLGRAB_H
 
-
diff --git a/indra/newview/lltoolindividual.cpp b/indra/newview/lltoolindividual.cpp
index 0e0524daa64f8a8d8fb9d5d7d654bfdd99aeb272..3fa96cd84a7c497ec05b224e61012ae89ab0df21 100644
--- a/indra/newview/lltoolindividual.cpp
+++ b/indra/newview/lltoolindividual.cpp
@@ -72,13 +72,13 @@ LLToolIndividual::~LLToolIndividual()
 
 BOOL LLToolIndividual::handleMouseDown(S32 x, S32 y, MASK mask)
 {
-	gViewerWindow->pickAsync(x, y, mask, pickCallback);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 	return TRUE;
 }
 
-void LLToolIndividual::pickCallback(const LLPickInfo& pick_info)
+void LLToolIndividual::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* obj = pick_info.getObject();
+	LLViewerObject* obj = gViewerWindow->lastObjectHit();
 	LLSelectMgr::getInstance()->deselectAll();
 	if(obj)
 	{
diff --git a/indra/newview/lltoolindividual.h b/indra/newview/lltoolindividual.h
index 913e4ff2b8e0d1b334bfdb4b145f7f5d5c131a83..48a2365363d2366b93b8dce3c34d12b6a88efa9e 100644
--- a/indra/newview/lltoolindividual.h
+++ b/indra/newview/lltoolindividual.h
@@ -34,8 +34,6 @@
 
 #include "lltool.h"
 
-class LLPickInfo;
-
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class lltoolindividual
 //
@@ -54,7 +52,7 @@ class LLToolIndividual : public LLTool, public LLSingleton<LLToolIndividual>
 	//virtual void handleDeselect();
 	//virtual void render();
 
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 
 protected:
 
diff --git a/indra/newview/lltoolobjpicker.cpp b/indra/newview/lltoolobjpicker.cpp
index ee9c24f2699fd9a5e47e1d13e80a834591faaee3..67e0db962f8c0529974ade06d1c0466964f6638d 100644
--- a/indra/newview/lltoolobjpicker.cpp
+++ b/indra/newview/lltoolobjpicker.cpp
@@ -69,7 +69,7 @@ BOOL LLToolObjPicker::handleMouseDown(S32 x, S32 y, MASK mask)
 	if (! handled)
 	{
 		// didn't click in any UI object, so must have clicked in the world
-		gViewerWindow->pickAsync(x, y, mask, pickCallback);
+		gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 		handled = TRUE;
 	}
 	else
@@ -90,10 +90,16 @@ BOOL LLToolObjPicker::handleMouseDown(S32 x, S32 y, MASK mask)
 	return handled;
 }
 
-void LLToolObjPicker::pickCallback(const LLPickInfo& pick_info)
+void LLToolObjPicker::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLToolObjPicker::getInstance()->mHitObjectID = pick_info.mObjectID;
-	LLToolObjPicker::getInstance()->mPicked = pick_info.mObjectID.notNull();
+	// You must hit the body for this tool to think you hit the object.
+	LLViewerObject*	objectp = NULL;
+	objectp = gObjectList.findObject( gLastHitObjectID );
+	if (objectp)
+	{
+		LLToolObjPicker::getInstance()->mHitObjectID = objectp->mID;
+		LLToolObjPicker::getInstance()->mPicked = TRUE;
+	}
 }
 
 
@@ -175,4 +181,3 @@ void LLToolObjPicker::handleDeselect()
 }
 
 
-
diff --git a/indra/newview/lltoolobjpicker.h b/indra/newview/lltoolobjpicker.h
index 8d0c87c8ae1972e6ed6bfc6d8a900a707e8b7ea2..794d035a83f25859e835fecf82139d1c7bc2d168 100644
--- a/indra/newview/lltoolobjpicker.h
+++ b/indra/newview/lltoolobjpicker.h
@@ -36,8 +36,6 @@
 #include "v3math.h"
 #include "lluuid.h"
 
-class LLPickInfo;
-
 class LLToolObjPicker : public LLTool, public LLSingleton<LLToolObjPicker>
 {
 public:
@@ -56,7 +54,7 @@ class LLToolObjPicker : public LLTool, public LLSingleton<LLToolObjPicker>
 
 	LLUUID				getObjectID() const { return mHitObjectID; }
 
-	static void			pickCallback(const LLPickInfo& pick_info);
+	static void			pickCallback(S32 x, S32 y, MASK mask);
 
 protected:
 	BOOL				mPicked;
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index b444cb8ce620df400b31cced14153a04d6d8fb87..b6bcf9544df98a8f3d9ca4ea4ef0ca748a9fc383 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -84,48 +84,50 @@ LLToolPie::LLToolPie()
 :	LLTool(std::string("Select")),
 	mPieMouseButtonDown( FALSE ),
 	mGrabMouseButtonDown( FALSE ),
+	mHitLand( FALSE ),
+	mHitObjectID(),
 	mMouseOutsideSlop( FALSE )
 { }
 
 
 BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
 {
+	gPickFaces = TRUE;
 	//left mouse down always picks transparent
-	gViewerWindow->pickAsync(x, y, mask, leftMouseCallback, TRUE, TRUE);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, leftMouseCallback, 
+											  TRUE, TRUE);
 	mGrabMouseButtonDown = TRUE;
 	return TRUE;
 }
 
 // static
-void LLToolPie::leftMouseCallback(const LLPickInfo& pick_info)
+void LLToolPie::leftMouseCallback(S32 x, S32 y, MASK mask)
 {
-	LLToolPie::getInstance()->mPick = pick_info;
-	LLToolPie::getInstance()->pickAndShowMenu(FALSE);
+	LLToolPie::getInstance()->pickAndShowMenu(x, y, mask, FALSE);
 }
 
 BOOL LLToolPie::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
+	// Pick faces in case they select "Copy Texture" and need that info.
+	gPickFaces = TRUE;
 	// don't pick transparent so users can't "pay" transparent objects
-	gViewerWindow->pickAsync(x, y, mask, rightMouseCallback, FALSE);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, rightMouseCallback,
+											  FALSE, TRUE);
 	mPieMouseButtonDown = TRUE; 
 	// don't steal focus from UI
 	return FALSE;
 }
 
 // static
-void LLToolPie::rightMouseCallback(const LLPickInfo& pick_info)
+void LLToolPie::rightMouseCallback(S32 x, S32 y, MASK mask)
 {
-	LLToolPie::getInstance()->mPick = pick_info;
-	LLToolPie::getInstance()->pickAndShowMenu(TRUE);
+	LLToolPie::getInstance()->pickAndShowMenu(x, y, mask, TRUE);
 }
 
 // True if you selected an object.
-BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
+BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show)
 {
-	S32 x = mPick.mMousePt.mX;
-	S32 y = mPick.mMousePt.mY;
-	MASK mask = mPick.mKeyMask;
-	if (!always_show && mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL)
+	if (!always_show && gLastHitParcelWall)
 	{
 		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel();
 		if (parcel)
@@ -149,18 +151,25 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
 	}
 
 	// didn't click in any UI object, so must have clicked in the world
-	LLViewerObject *object = mPick.getObject();
+	LLViewerObject *object = gViewerWindow->lastObjectHit();
 	LLViewerObject *parent = NULL;
 
-	if (mPick.mPickType != LLPickInfo::PICK_LAND)
+	mHitLand = !object && !gLastHitPosGlobal.isExactlyZero();
+	if (!mHitLand)
 	{
 		LLViewerParcelMgr::getInstance()->deselectLand();
 	}
 	
 	if (object)
 	{
+		mHitObjectID = object->mID;
+
 		parent = object->getRootEdit();
 	}
+	else
+	{
+		mHitObjectID.setNull();
+	}
 
 	BOOL touchable = (object && object->flagHandleTouch()) 
 					 || (parent && parent->flagHandleTouch());
@@ -197,19 +206,19 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
 			{
 				// pay event goes to object actually clicked on
 				sClickActionObject = object;
-				sLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
+				sLeftClickSelection = LLToolSelect::handleObjectSelection(object, MASK_NONE, FALSE, TRUE);
 				return TRUE;
 			}
 			break;
 		case CLICK_ACTION_BUY:
 			sClickActionObject = parent;
-			sLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE);
+			sLeftClickSelection = LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE);
 			return TRUE;
 		case CLICK_ACTION_OPEN:
 			if (parent && parent->allowOpen())
 			{
 				sClickActionObject = parent;
-				sLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE);
+				sLeftClickSelection = LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE);
 			}
 			return TRUE;
 		case CLICK_ACTION_PLAY:
@@ -230,13 +239,12 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
 	{
 		gGrabTransientTool = this;
 		LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() );
-		return LLToolGrab::getInstance()->handleObjectHit( mPick );
+		return LLToolGrab::getInstance()->handleObjectHit( object, x, y, mask);
 	}
 	
-	LLHUDIcon* last_hit_hud_icon = mPick.mHUDIcon;
-	if (!object && last_hit_hud_icon && last_hit_hud_icon->getSourceObject())
+	if (!object && gLastHitHUDIcon && gLastHitHUDIcon->getSourceObject())
 	{
-		LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID());
+		LLFloaterScriptDebug::show(gLastHitHUDIcon->getSourceObject()->getID());
 	}
 
 	// If left-click never selects or spawns a menu
@@ -265,7 +273,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
 			LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance());
 			gViewerWindow->hideCursor();
 			LLToolCamera::getInstance()->setMouseCapture(TRUE);
-			LLToolCamera::getInstance()->pickCallback(mPick);
+			LLToolCamera::getInstance()->pickCallback(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY(), mask);
 			gAgent.setFocusOnAvatar(TRUE, TRUE);
 
 			return TRUE;
@@ -284,22 +292,22 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
 	}
 
 	// Can't ignore children here.
-	LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE);
+	LLToolSelect::handleObjectSelection(object, mask, FALSE, TRUE);
 
 	// Spawn pie menu
-	if (mPick.mPickType == LLPickInfo::PICK_LAND)
+	if (mHitLand)
 	{
-		LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal );
+		LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( gLastHitPosGlobal );
 		gMenuHolder->setParcelSelection(selection);
 		gPieLand->show(x, y, mPieMouseButtonDown);
 
 		// VEFFECT: ShowPie
 		LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
-		effectp->setPositionGlobal(mPick.mPosGlobal);
+		effectp->setPositionGlobal(gLastHitPosGlobal);
 		effectp->setColor(LLColor4U(gAgent.getEffectColor()));
 		effectp->setDuration(0.25f);
 	}
-	else if (mPick.mObjectID == gAgent.getID() )
+	else if (mHitObjectID == gAgent.getID() )
 	{
 		if(!gPieSelf) 
 		{
@@ -369,7 +377,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show)
 			// Don't show when you click on someone else, it freaks them
 			// out.
 			LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_SPHERE, TRUE);
-			effectp->setPositionGlobal(mPick.mPosGlobal);
+			effectp->setPositionGlobal(gLastHitPosGlobal);
 			effectp->setColor(LLColor4U(gAgent.getEffectColor()));
 			effectp->setDuration(0.25f);
 		}
@@ -536,7 +544,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
 	LLViewerObject *parent = NULL;
 	if (gHoverView)
 	{
-		object = gViewerWindow->getHoverPick().getObject();
+		object = gHoverView->getLastHoverObject();
 	}
 
 	if (object)
@@ -573,7 +581,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
 
 BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* obj = mPick.getObject();
+	LLViewerObject* obj = gViewerWindow->lastObjectHit();
 	U8 click_action = final_click_action(obj);
 	if (click_action != CLICK_ACTION_NONE)
 	{
@@ -618,18 +626,18 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
 
 	if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
 	{
-		if (mPick.mPickType == LLPickInfo::PICK_LAND
-			&& !mPick.mPosGlobal.isExactlyZero())
+		if (gLastHitLand
+			&& !gLastHitPosGlobal.isExactlyZero())
 		{
 			handle_go_to();
 			return TRUE;
 		}
-		else if (mPick.mObjectID.notNull()
-				 && !mPick.mPosGlobal.isExactlyZero())
+		else if (gLastHitObjectID.notNull()
+				 && !gLastHitPosGlobal.isExactlyZero())
 		{
 			// Hit an object
 			// HACK: Call the last hit position the point we hit on the object
-			//gLastHitPosGlobal += gLastHitObjectOffset;
+			gLastHitPosGlobal += gLastHitObjectOffset;
 			handle_go_to();
 			return TRUE;
 		}
@@ -641,7 +649,7 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
 	objects gets you into trouble.
 
 	// If double-click on object or land, go there.
-	LLViewerObject *object = gViewerWindow->getLastPick().getObject();
+	LLViewerObject *object = gViewerWindow->lastObjectHit();
 	if (object)
 	{
 		if (object->isAvatar())
@@ -748,11 +756,10 @@ static void handle_click_action_open_media(LLPointer<LLViewerObject> objectp)
 	if (objectp.isNull()) return;
 
 	// did we hit a valid face on the object?
-	S32 face = LLToolPie::getInstance()->getPick().mObjectFace;
-	if( face < 0 || face >= objectp->getNumTEs() ) return;
+	if( gLastHitObjectFace < 0 || gLastHitObjectFace >= objectp->getNumTEs() ) return;
 		
 	// is media playing on this face?
-	if (!LLViewerMedia::isActiveMediaTexture(objectp->getTE(face)->getID()))
+	if (!LLViewerMedia::isActiveMediaTexture(objectp->getTE(gLastHitObjectFace)->getID()))
 	{
 		handle_click_action_play();
 		return;
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index a8103f23a04f09c2863b8e6fcbe69ffa2c2f1a8d..4963940840a10b11d3f68ba07520b1982debb186 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -34,7 +34,6 @@
 
 #include "lltool.h"
 #include "lluuid.h"
-#include "llviewerwindow.h" // for LLPickInfo
 
 class LLViewerObject;
 class LLObjectSelection;
@@ -59,25 +58,23 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
 	virtual void		handleDeselect();
 	virtual LLTool*		getOverrideTool(MASK mask);
 
-	LLPickInfo&			getPick() { return mPick; }
-
-	static void			leftMouseCallback(const LLPickInfo& pick_info);
-	static void			rightMouseCallback(const LLPickInfo& pick_info);
+	static void			leftMouseCallback(S32 x, S32 y, MASK mask);
+	static void			rightMouseCallback(S32 x, S32 y, MASK mask);
 
 	static void			selectionPropertiesReceived();
 
-
 protected:
 	BOOL outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y);
-	BOOL pickAndShowMenu(BOOL edit_menu);
+	BOOL pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL edit_menu);
 	BOOL useClickAction(BOOL always_show, MASK mask, LLViewerObject* object,
 						LLViewerObject* parent);
 
 protected:
 	BOOL				mPieMouseButtonDown;
 	BOOL				mGrabMouseButtonDown;
+	BOOL				mHitLand;
+	LLUUID				mHitObjectID;
 	BOOL				mMouseOutsideSlop;				// for this drag, has mouse moved outside slop region
-	LLPickInfo			mPick;
 	static LLPointer<LLViewerObject> sClickActionObject;
 	static U8				sClickAction;
 	static LLSafeHandle<LLObjectSelection> sLeftClickSelection;
diff --git a/indra/newview/lltoolpipette.cpp b/indra/newview/lltoolpipette.cpp
index 9456cd4472b76494386c37f8550bf10ee0a40fb0..a565e4361b5c01d2c1b63e2a6b7caea39a2afc81 100644
--- a/indra/newview/lltoolpipette.cpp
+++ b/indra/newview/lltoolpipette.cpp
@@ -67,8 +67,9 @@ BOOL LLToolPipette::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	mSuccess = TRUE;
 	mTooltipMsg.clear();
+	gPickFaces = TRUE;
 	setMouseCapture(TRUE);
-	gViewerWindow->pickAsync(x, y, mask, pickCallback);
+	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 	return TRUE;
 }
 
@@ -87,7 +88,8 @@ BOOL LLToolPipette::handleHover(S32 x, S32 y, MASK mask)
 	gViewerWindow->setCursor(mSuccess ? UI_CURSOR_PIPETTE : UI_CURSOR_NO);
 	if (hasMouseCapture()) // mouse button is down
 	{
-		gViewerWindow->pickAsync(x, y, mask, pickCallback);
+		gPickFaces = TRUE;
+		gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback);
 		return TRUE;
 	}
 	return FALSE;
@@ -105,19 +107,19 @@ BOOL LLToolPipette::handleToolTip(S32 x, S32 y, std::string& msg, LLRect *sticky
 	return TRUE;
 }
 
-void LLToolPipette::pickCallback(const LLPickInfo& pick_info)
+void LLToolPipette::pickCallback(S32 x, S32 y, MASK mask)
 {
-	LLViewerObject* hit_obj	= pick_info.getObject();
+	LLViewerObject* hit_obj	= gViewerWindow->lastObjectHit();
 	LLSelectMgr::getInstance()->unhighlightAll();
 
 	// if we clicked on a face of a valid prim, save off texture entry data
 	if (hit_obj && 
 		hit_obj->getPCode() == LL_PCODE_VOLUME &&
-		pick_info.mObjectFace != -1)
+		gLastHitObjectFace != -1)
 	{
 		//TODO: this should highlight the selected face only
 		LLSelectMgr::getInstance()->highlightObjectOnly(hit_obj);
-		LLToolPipette::getInstance()->mTextureEntry = *hit_obj->getTE(pick_info.mObjectFace);
+		LLToolPipette::getInstance()->mTextureEntry = *hit_obj->getTE(gLastHitObjectFace);
 		if (LLToolPipette::getInstance()->mSelectCallback)
 		{
 			LLToolPipette::getInstance()->mSelectCallback(LLToolPipette::getInstance()->mTextureEntry, LLToolPipette::getInstance()->mUserData);
diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h
index 5d5b27f9648e15f5a05bc6347c53c2353275aec4..b88a6eebc87c775de10922be09766a46a212aa8c 100644
--- a/indra/newview/lltoolpipette.h
+++ b/indra/newview/lltoolpipette.h
@@ -41,7 +41,6 @@
 #include "lltextureentry.h"
 
 class LLViewerObject;
-class LLPickInfo;
 
 class LLToolPipette
 :	public LLTool, public LLSingleton<LLToolPipette>
@@ -59,7 +58,7 @@ class LLToolPipette
 	void setSelectCallback(select_callback callback, void* user_data);
 	void setResult(BOOL success, const std::string& msg);
 
-	static void pickCallback(const LLPickInfo& pick_info);
+	static void pickCallback(S32 x, S32 y, MASK mask);
 
 protected:
 	LLTextureEntry	mTextureEntry;
diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp
index 8806d1465aa45f4a89e9147407e8d61e7013a554..7d4d0397cca114852e2d9a9d912ccb7dd7e5026c 100644
--- a/indra/newview/lltoolplacer.cpp
+++ b/indra/newview/lltoolplacer.cpp
@@ -81,22 +81,14 @@ BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj,
 
 	// Viewer-side pick to find the right sim to create the object on.  
 	// First find the surface the object will be created on.
-	LLPickInfo pick = gViewerWindow->pickImmediate(x, y, FALSE);
+	gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, NULL, FALSE);
 	
 	// Note: use the frontmost non-flora version because (a) plants usually have lots of alpha and (b) pants' Havok
 	// representations (if any) are NOT the same as their viewer representation.
-	if (pick.mPickType == LLPickInfo::PICK_FLORA)
-	{
-		*hit_obj = NULL;
-		*hit_face = -1;
-	}
-	else
-	{
-		*hit_obj = pick.getObject();
-		*hit_face = pick.mObjectFace;
-	}
-	*b_hit_land = !(*hit_obj) && !pick.mPosGlobal.isExactlyZero();
-	LLVector3d land_pos_global = pick.mPosGlobal;
+	*hit_obj = gObjectList.findObject( gLastHitNonFloraObjectID );
+	*hit_face = gLastHitNonFloraObjectFace;
+	*b_hit_land = !(*hit_obj) && !gLastHitNonFloraPosGlobal.isExactlyZero();
+	LLVector3d land_pos_global = gLastHitNonFloraPosGlobal;
 
 	// Make sure there's a surface to place the new object on.
 	BOOL bypass_sim_raycast = FALSE;
diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp
index e74cd5892420c3c98fba57ef1dbe80d3fd01f1e8..8f84013a266fecbf3d2070a1ec6cc31a7aaf7af9 100644
--- a/indra/newview/lltoolselect.cpp
+++ b/indra/newview/lltoolselect.cpp
@@ -64,24 +64,39 @@ LLToolSelect::LLToolSelect( LLToolComposite* composite )
 // True if you selected an object.
 BOOL LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask)
 {
-	// do immediate pick query
-	mPick = gViewerWindow->pickImmediate(x, y, TRUE);
+	BOOL handled = FALSE;
+
+	// didn't click in any UI object, so must have clicked in the world
+	LLViewerObject*	object = NULL;
+
+	// You must hit the body for this tool to think you hit the object.
+	object = gObjectList.findObject( gLastHitObjectID );
+
+	if (object)
+	{
+		mSelectObjectID = object->getID();
+		handled = TRUE;
+	}
+	else
+	{
+		mSelectObjectID.setNull();
+	}
 
 	// Pass mousedown to agent
 	LLTool::handleMouseDown(x, y, mask);
 
-	return mPick.getObject().notNull();
+	return handled;
 }
 
+BOOL LLToolSelect::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+	//RN: double click to toggle individual/linked picking???
+	return LLTool::handleDoubleClick(x, y, mask);
+}
 
 // static
-LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pick, BOOL ignore_group, BOOL temp_select, BOOL select_root)
+LLSafeHandle<LLObjectSelection> LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL ignore_group, BOOL temp_select)
 {
-	LLViewerObject* object = pick.getObject();
-	if (select_root)
-	{
-		object = object->getRootEdit();
-	}
 	BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly");
 	BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly");
 	
@@ -93,16 +108,14 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
 		LLSelectMgr::getInstance()->setForceSelection(TRUE);
 	}
 
-	BOOL extend_select = (pick.mKeyMask == MASK_SHIFT) || (pick.mKeyMask == MASK_CONTROL);
+	BOOL extend_select = (mask == MASK_SHIFT) || (mask == MASK_CONTROL);
 
 	// If no object, check for icon, then just deselect
 	if (!object)
 	{
-		LLHUDIcon* last_hit_hud_icon = pick.mHUDIcon;
-
-		if (last_hit_hud_icon && last_hit_hud_icon->getSourceObject())
+		if (gLastHitHUDIcon && gLastHitHUDIcon->getSourceObject())
 		{
-			LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID());
+			LLFloaterScriptDebug::show(gLastHitHUDIcon->getSourceObject()->getID());
 		}
 		else if (!extend_select)
 		{
@@ -227,7 +240,8 @@ BOOL LLToolSelect::handleMouseUp(S32 x, S32 y, MASK mask)
 {
 	mIgnoreGroup = gSavedSettings.getBOOL("EditLinkedParts");
 
-	handleObjectSelection(mPick, mIgnoreGroup, FALSE);
+	LLViewerObject* object = gObjectList.findObject(mSelectObjectID);
+	LLToolSelect::handleObjectSelection(object, mask, mIgnoreGroup, FALSE);
 
 	return LLTool::handleMouseUp(x, y, mask);
 }
@@ -261,4 +275,3 @@ void LLToolSelect::onMouseCaptureLost()
 
 
 
-
diff --git a/indra/newview/lltoolselect.h b/indra/newview/lltoolselect.h
index f6359863a87a91eb66c138ad8b86e3493a4b9ccf..c3d10424b1a3ede3a71aff53747d91deafec3d9b 100644
--- a/indra/newview/lltoolselect.h
+++ b/indra/newview/lltoolselect.h
@@ -35,7 +35,6 @@
 #include "lltool.h"
 #include "v3math.h"
 #include "lluuid.h"
-#include "llviewerwindow.h" // for LLPickInfo
 
 class LLObjectSelection;
 
@@ -46,10 +45,11 @@ class LLToolSelect : public LLTool, public LLSingleton<LLToolSelect>
 
 	virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask);
+	virtual BOOL		handleDoubleClick(S32 x, S32 y, MASK mask);
 
 	virtual void		stopEditing();
 
-	static LLSafeHandle<LLObjectSelection>	handleObjectSelection(const LLPickInfo& pick, BOOL ignore_group, BOOL temp_select, BOOL select_root = FALSE);
+	static LLSafeHandle<LLObjectSelection>	handleObjectSelection(LLViewerObject *object, MASK mask, BOOL ignore_group, BOOL temp_select);
 
 	virtual void		onMouseCaptureLost();
 	virtual void		handleDeselect();
@@ -57,7 +57,6 @@ class LLToolSelect : public LLTool, public LLSingleton<LLToolSelect>
 protected:
 	BOOL				mIgnoreGroup;
 	LLUUID				mSelectObjectID;
-	LLPickInfo			mPick;
 };
 
 
diff --git a/indra/newview/lltoolselectrect.cpp b/indra/newview/lltoolselectrect.cpp
index 0d403bbb287f8cf060aa0e986619bf835446baec..67d9e2da657fdf4016f152fbecf74a131ba72c33 100644
--- a/indra/newview/lltoolselectrect.cpp
+++ b/indra/newview/lltoolselectrect.cpp
@@ -78,26 +78,18 @@ void dialog_refresh_all(void);
 
 BOOL LLToolSelectRect::handleMouseDown(S32 x, S32 y, MASK mask)
 {
-	handlePick(gViewerWindow->pickImmediate(x, y, TRUE));
-
-	LLTool::handleMouseDown(x, y, mask);
-
-	return mPick.getObject().notNull();
-}
-
-void LLToolSelectRect::handlePick(const LLPickInfo& pick)
-{
-	mPick = pick;
-
 	// start dragging rectangle
 	setMouseCapture( TRUE );
 
-	mDragStartX = pick.mMousePt.mX;
-	mDragStartY = pick.mMousePt.mY;
-	mDragEndX = pick.mMousePt.mX;
-	mDragEndY = pick.mMousePt.mY;
+	mDragStartX = x;
+	mDragStartY = y;
+	mDragEndX = x;
+	mDragEndY = y;
 
 	mMouseOutsideSlop = FALSE;
+
+	LLToolSelect::handleMouseDown(x, y, mask);
+	return TRUE;
 }
 
 
diff --git a/indra/newview/lltoolselectrect.h b/indra/newview/lltoolselectrect.h
index 63b8d26e242c904c5a60c3be4c62f248b313c9e6..d45f0a433c08ff191f11252379545c39b0382550 100644
--- a/indra/newview/lltoolselectrect.h
+++ b/indra/newview/lltoolselectrect.h
@@ -46,8 +46,6 @@ class LLToolSelectRect
 	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
 	virtual void	draw();							// draw the select rectangle
 
-	void handlePick(const LLPickInfo& pick);
-
 protected:
 	void			handleRectangleSelection(S32 x, S32 y, MASK mask);	// true if you selected one
 	BOOL			outsideSlop(S32 x, S32 y, S32 start_x, S32 start_y);
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 0e83ba1123b113083bb31ad83a20822015cdb711..b2cf873a2192bbbe43348b6c7595911875ebade4 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -798,12 +798,7 @@ void render_hud_attachments()
 	glh::matrix4f current_proj = glh_get_current_projection();
 	glh::matrix4f current_mod = glh_get_current_modelview();
 
-	// clamp target zoom level to reasonable values
-	gAgent.mHUDTargetZoom = llclamp(gAgent.mHUDTargetZoom, 0.1f, 1.f);
-	// smoothly interpolate current zoom level
-	gAgent.mHUDCurZoom = lerp(gAgent.mHUDCurZoom, gAgent.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
-
-	if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
+	if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices(FALSE))
 	{
 		LLCamera hud_cam = *LLViewerCamera::getInstance();
 		LLVector3 origin = hud_cam.getOrigin();
@@ -861,53 +856,52 @@ void render_hud_attachments()
 	glh_set_current_modelview(current_mod);
 }
 
-BOOL setup_hud_matrices()
-{
-	LLRect whole_screen = gViewerWindow->getVirtualWindowRect();
-
-	// apply camera zoom transform (for high res screenshots)
-	F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
-	S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
-	if (zoom_factor > 1.f)
-	{
-		S32 num_horizontal_tiles = llceil(zoom_factor);
-		S32 tile_width = llround((F32)gViewerWindow->getWindowWidth() / zoom_factor);
-		S32 tile_height = llround((F32)gViewerWindow->getWindowHeight() / zoom_factor);
-		int tile_y = sub_region / num_horizontal_tiles;
-		int tile_x = sub_region - (tile_y * num_horizontal_tiles);
-		glh::matrix4f mat;
-
-		whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeight() - (tile_y * tile_height), tile_width, tile_height);
-	}
-
-	return setup_hud_matrices(whole_screen);
-}
-
-BOOL setup_hud_matrices(const LLRect& screen_region)
+BOOL setup_hud_matrices(BOOL for_select)
 {
 	LLVOAvatar* my_avatarp = gAgent.getAvatarObject();
 	if (my_avatarp && my_avatarp->hasHUDAttachment())
 	{
-		F32 zoom_level = gAgent.mHUDCurZoom;
+		if (!for_select)
+		{
+			// clamp target zoom level to reasonable values
+			my_avatarp->mHUDTargetZoom = llclamp(my_avatarp->mHUDTargetZoom, 0.1f, 1.f);
+			// smoothly interpolate current zoom level
+			my_avatarp->mHUDCurZoom = lerp(my_avatarp->mHUDCurZoom, my_avatarp->mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
+		}
+
+		F32 zoom_level = my_avatarp->mHUDCurZoom;
+		// clear z buffer and set up transform for hud
+		if (!for_select)
+		{
+			//glClear(GL_DEPTH_BUFFER_BIT);
+		}
 		LLBBox hud_bbox = my_avatarp->getHUDBBox();
 
-		// set up transform to keep HUD objects in front of camera
+		
+		// set up transform to encompass bounding box of HUD
 		glMatrixMode(GL_PROJECTION);
 		F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
+		if (for_select)
+		{
+			//RN: reset viewport to window extents so ortho screen is calculated with proper reference frame
+			gViewerWindow->setupViewport();
+		}
 		glh::matrix4f proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
 		proj.element(2,2) = -0.01f;
 
-		F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
-
-		glh::matrix4f mat;
-		F32 scale_x = (F32)gViewerWindow->getWindowWidth() / (F32)screen_region.getWidth();
-		F32 scale_y = (F32)gViewerWindow->getWindowHeight() / (F32)screen_region.getHeight();
-		mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
-		mat.set_translate(
-			glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWindowWidth(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
-						clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeight(), 0.5f * scale_y, -0.5f * scale_y),
-						0.f));
-		proj *= mat;
+		// apply camera zoom transform (for high res screenshots)
+		F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
+		S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
+		if (zoom_factor > 1.f)
+		{
+			float offset = zoom_factor - 1.f;
+			int pos_y = sub_region / llceil(zoom_factor);
+			int pos_x = sub_region - (pos_y*llceil(zoom_factor));
+			glh::matrix4f mat;
+			mat.set_scale(glh::vec3f(zoom_factor, zoom_factor, 1.f));
+			mat.set_translate(glh::vec3f(LLViewerCamera::getInstance()->getAspect() * 0.5f * (offset - (F32)pos_x * 2.f), 0.5f * (offset - (F32)pos_y * 2.f), 0.f));
+			proj *= mat;
+		}
 
 		glLoadMatrixf(proj.m);
 		glh_set_current_projection(proj);
@@ -915,8 +909,9 @@ BOOL setup_hud_matrices(const LLRect& screen_region)
 		glMatrixMode(GL_MODELVIEW);
 		glh::matrix4f model((GLfloat*) OGL_TO_CFR_ROTATION);
 		
-		mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
+		glh::matrix4f mat;
 		mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
+		mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
 
 		model *= mat;
 		glLoadMatrixf(model.m);
@@ -1132,14 +1127,14 @@ void render_ui_2d()
 	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 
 	// render outline for HUD
-	if (gAgent.getAvatarObject() && gAgent.mHUDCurZoom < 0.98f)
+	if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mHUDCurZoom < 0.98f)
 	{
 		glPushMatrix();
 		S32 half_width = (gViewerWindow->getWindowWidth() / 2);
 		S32 half_height = (gViewerWindow->getWindowHeight() / 2);
 		glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
 		glTranslatef((F32)half_width, (F32)half_height, 0.f);
-		F32 zoom = gAgent.mHUDCurZoom;
+		F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 		glScalef(zoom,zoom,1.f);
 		gGL.color4fv(LLColor4::white.mV);
 		gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 3f57b26fec7c8de66699a4db238e27d465bb3755..1586f8dc75971982ca1bd859b0fae77dff63d8c9 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -694,3 +694,5 @@ void LLViewerMedia::setMimeType(std::string mime_type)
 {
 	sViewerMediaImpl.mMimeType = mime_type;
 }
+
+
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index a095c9e159113db4a32b3f7e98c8113e56f479b8..347ddac7977dbe75134fd87ca532aeeeb7e78d1d 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1359,9 +1359,6 @@ void init_debug_rendering_menu(LLMenuGL* menu)
 	sub_menu->append(new LLMenuItemCheckGL("Glow",&LLPipeline::toggleRenderDebug, NULL,
 													&LLPipeline::toggleRenderDebugControl,
 													(void*)LLPipeline::RENDER_DEBUG_GLOW));
-	sub_menu->append(new LLMenuItemCheckGL("Raycasting",	&LLPipeline::toggleRenderDebug, NULL,
-													&LLPipeline::toggleRenderDebugControl,
-													(void*)LLPipeline::RENDER_DEBUG_RAYCAST));
 	
 	sub_menu->append(new LLMenuItemCheckGL("Show Depth Buffer",
 										   &menu_toggle_control,
@@ -1631,11 +1628,7 @@ class LLObjectReportAbuse : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
-		if (objectp)
-		{
-			LLFloaterReporter::showFromObject(objectp->getID());
-		}
+		LLFloaterReporter::showFromObject(gLastHitObjectID);
 		return true;
 	}
 };
@@ -1645,7 +1638,7 @@ class LLObjectEnableReportAbuse : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0;
+		bool new_value = !gLastHitObjectID.isNull();
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 		return true;
 	}
@@ -1655,7 +1648,7 @@ class LLObjectTouch : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject* object = gObjectList.findObject(gLastHitObjectID);
 		if (!object) return true;
 
 		LLMessageSystem	*msg = gMessageSystem;
@@ -1690,7 +1683,7 @@ class LLObjectEnableTouch : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject* obj = gObjectList.findObject(gLastHitObjectID);
 		bool new_value = obj && obj->flagHandleTouch();
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 
@@ -1724,7 +1717,7 @@ void label_touch(std::string& label, void*)
 
 bool handle_object_open()
 {
-	LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+	LLViewerObject* obj = gObjectList.findObject(gLastHitObjectID);
 	if(!obj) return true;
 
 	LLFloaterOpenObject::show();
@@ -1745,7 +1738,7 @@ class LLObjectEnableOpen : public view_listener_t
 	{
 		// Look for contents in root object, which is all the LLFloaterOpenObject
 		// understands.
-		LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject* obj = gObjectList.findObject(gLastHitObjectID);
 		bool new_value = (obj != NULL);
 		if (new_value)
 		{
@@ -1845,14 +1838,14 @@ class LLObjectBuild : public view_listener_t
 		{
 			// zoom in if we're looking at the avatar
 			gAgent.setFocusOnAvatar(FALSE, ANIMATE);
-			gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 			gAgent.cameraZoomIn(0.666f);
 			gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
 			gViewerWindow->moveCursorToCenter();
 		}
 		else if ( gSavedSettings.getBOOL("EditCameraMovement") )
 		{
-			gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 			gViewerWindow->moveCursorToCenter();
 		}
 
@@ -1885,17 +1878,13 @@ class LLObjectEdit : public view_listener_t
 			else
 			{
 				gAgent.setFocusOnAvatar(FALSE, ANIMATE);
-				LLViewerObject* selected_objectp = selection->getFirstRootObject();
-				if (selected_objectp)
-				{
 				// zoom in on object center instead of where we clicked, as we need to see the manipulator handles
-					gAgent.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
+				gAgent.setFocusGlobal(gLastHitPosGlobal /*+ gLastHitObjectOffset*/, gLastHitObjectID);
 				gAgent.cameraZoomIn(0.666f);
 				gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
 				gViewerWindow->moveCursorToCenter();
 			}
 		}
-		}
 
 		gFloaterTools->open();		/* Flawfinder: ignore */
 	
@@ -1934,7 +1923,7 @@ class LLLandBuild : public view_listener_t
 		{
 			// zoom in if we're looking at the avatar
 			gAgent.setFocusOnAvatar(FALSE, ANIMATE);
-			gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 			gAgent.cameraZoomIn(0.666f);
 			gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
 			gViewerWindow->moveCursorToCenter();
@@ -1942,7 +1931,7 @@ class LLLandBuild : public view_listener_t
 		else if ( gSavedSettings.getBOOL("EditCameraMovement")  )
 		{
 			// otherwise just move focus
-			gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 			gViewerWindow->moveCursorToCenter();
 		}
 
@@ -2060,19 +2049,15 @@ BOOL enable_has_attachments(void*)
 //---------------------------------------------------------------------------
 void handle_follow(void *userdata)
 {
-	// follow a given avatar by ID
-	LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
-	if (objectp)
-	{
-		gAgent.startFollowPilot(objectp->getID());
-	}
+	// follow a given avatar, ID in gLastHitObjectID
+	gAgent.startFollowPilot(gLastHitObjectID);
 }
 
 class LLObjectEnableMute : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject* object = gViewerWindow->lastObjectHit();
 		bool new_value = (object != NULL);
 		if (new_value)
 		{
@@ -2095,7 +2080,7 @@ class LLObjectMute : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject* object = gViewerWindow->lastObjectHit();
 		if (!object) return true;
 		
 		LLUUID id;
@@ -2151,12 +2136,11 @@ bool handle_go_to()
 	// JAMESDEBUG try simulator autopilot
 	std::vector<std::string> strings;
 	std::string val;
-	LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
-	val = llformat("%g", pos.mdV[VX]);
+	val = llformat("%g", gLastHitPosGlobal.mdV[VX]);
 	strings.push_back(val);
-	val = llformat("%g", pos.mdV[VY]);
+	val = llformat("%g", gLastHitPosGlobal.mdV[VY]);
 	strings.push_back(val);
-	val = llformat("%g", pos.mdV[VZ]);
+	val = llformat("%g", gLastHitPosGlobal.mdV[VZ]);
 	strings.push_back(val);
 	send_generic_message("autopilot", strings);
 
@@ -2225,7 +2209,7 @@ class LLAvatarFreeze : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() );
+		LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() );
 		if( avatar )
 		{
 			LLUUID* avatar_id = new LLUUID( avatar->getID() );
@@ -2275,7 +2259,7 @@ class LLAvatarDebug : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() );
+		LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() );
 		if( avatar )
 		{
 			avatar->dumpLocalTextures();
@@ -2327,7 +2311,7 @@ class LLAvatarEject : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() );
+		LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() );
 		if( avatar )
 		{
 			LLUUID* avatar_id = new LLUUID( avatar->getID() );
@@ -2357,7 +2341,7 @@ class LLAvatarEnableFreezeEject : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() );
+		LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() );
 		bool new_value = (avatar != NULL);
 
 		if (new_value)
@@ -2382,7 +2366,7 @@ class LLAvatarGiveCard : public view_listener_t
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
 		llinfos << "handle_give_card()" << llendl;
-		LLViewerObject* dest = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject* dest = gViewerWindow->lastObjectHit();
 		if(dest && dest->isAvatar())
 		{
 			bool found_name = false;
@@ -2621,9 +2605,9 @@ void handle_dump_region_object_cache(void*)
 
 void handle_dump_focus(void *)
 {
-	LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
-
-	llinfos << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << llendl;
+	LLView *view = gFocusMgr.getKeyboardFocus();
+	std::string name = view ? view->getName() : "(none)";
+	llinfos << "Keyboard focus " << name << llendl;
 }
 
 class LLSelfStandUp : public view_listener_t
@@ -2839,7 +2823,7 @@ class LLAvatarEnableAddFriend : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getFirstObject());
+		LLVOAvatar* avatar = find_avatar_from_object(gViewerWindow->lastObjectHit());
 		bool new_value = avatar && !is_agent_friend(avatar->getID());
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 		return true;
@@ -2886,12 +2870,10 @@ class LLEditEnableCustomizeAvatar : public view_listener_t
 	}
 };
 
-// only works on pie menu
 bool handle_sit_or_stand()
 {
-	LLPickInfo pick = LLToolPie::getInstance()->getPick();
-	LLViewerObject *object = pick.getObject();;
-	if (!object || pick.mPickType == LLPickInfo::PICK_FLORA)
+	LLViewerObject *object = gObjectList.findObject(gLastHitNonFloraObjectID);	
+	if (!object)
 	{
 		return true;
 	}
@@ -2906,13 +2888,17 @@ bool handle_sit_or_stand()
 
 	if (object && object->getPCode() == LL_PCODE_VOLUME)
 	{
+		LLVector3d offset_double = gViewerWindow->lastNonFloraObjectHitOffset();
+		LLVector3 offset_single;
+		offset_single.setVec(offset_double);
+		
 		gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
 		gMessageSystem->nextBlockFast(_PREHASH_AgentData);
 		gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 		gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 		gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
 		gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
-		gMessageSystem->addVector3Fast(_PREHASH_Offset, pick.mObjectOffset);
+		gMessageSystem->addVector3Fast(_PREHASH_Offset, offset_single);
 
 		object->getRegion()->sendReliableMessage();
 	}
@@ -2946,7 +2932,7 @@ class LLLandSit : public view_listener_t
 		gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
 		LLViewerParcelMgr::getInstance()->deselectLand();
 
-		LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal;
+		LLVector3d posGlobal = gLastHitPosGlobal;
 		
 		LLQuaternion target_rot;
 		if (gAgent.getAvatarObject())
@@ -5042,7 +5028,7 @@ class LLAvatarInviteToGroup : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() );
+		LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() );
 		if(avatar)
 		{
 			invite_to_group(avatar->getID());
@@ -5055,7 +5041,7 @@ class LLAvatarAddFriend : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() );
+		LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() );
 		if(avatar && !is_agent_friend(avatar->getID()))
 		{
 			request_friendship(avatar->getID());
@@ -5128,11 +5114,11 @@ class LLEnablePayObject : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getFirstObject());
+		LLVOAvatar* avatar = find_avatar_from_object(gViewerWindow->lastObjectHit());
 		bool new_value = (avatar != NULL);
 		if (!new_value)
 		{
-			LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+			LLViewerObject* object = gViewerWindow->lastObjectHit();
 			if( object )
 			{
 				LLViewerObject *parent = (LLViewerObject *)object->getParent();
@@ -5152,9 +5138,8 @@ class LLObjectEnableSitOrStand : public view_listener_t
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
 		bool new_value = false;
-		LLViewerObject* dest_object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
-
-		if(dest_object)
+		LLViewerObject* dest_object = NULL;
+		if((dest_object = gObjectList.findObject(gLastHitObjectID)))
 		{
 			if(dest_object->getPCode() == LL_PCODE_VOLUME)
 			{
@@ -5517,11 +5502,7 @@ class LLShowAgentProfile : public view_listener_t
 		}
 		else if (userdata.asString() == "hit object")
 		{
-			LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
-			if (objectp)
-			{
-				agent_id = objectp->getID();
-			}
+			agent_id = gLastHitObjectID;
 		}
 		else
 		{
@@ -5557,12 +5538,12 @@ void handle_focus(void *)
 	{
 		// zoom in if we're looking at the avatar
 		gAgent.setFocusOnAvatar(FALSE, ANIMATE);
-		gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+		gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 		gAgent.cameraZoomIn(0.666f);
 	}
 	else
 	{
-		gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+		gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 	}
 
 	gViewerWindow->moveCursorToCenter();
@@ -5580,19 +5561,19 @@ class LLLandEdit : public view_listener_t
 		{
 			// zoom in if we're looking at the avatar
 			gAgent.setFocusOnAvatar(FALSE, ANIMATE);
-			gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 
 			gAgent.cameraOrbitOver( F_PI * 0.25f );
 			gViewerWindow->moveCursorToCenter();
 		}
 		else if ( gSavedSettings.getBOOL("EditCameraMovement") )
 		{
-			gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 			gViewerWindow->moveCursorToCenter();
 		}
 
 
-		LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal );
+		LLViewerParcelMgr::getInstance()->selectParcelAt( gLastHitPosGlobal );
 
 		gFloaterTools->showMore(TRUE);
 		gFloaterView->bringToFront( gFloaterTools );
@@ -5630,13 +5611,13 @@ void handle_move(void*)
 	{
 		// zoom in if we're looking at the avatar
 		gAgent.setFocusOnAvatar(FALSE, ANIMATE);
-		gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+		gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 
 		gAgent.cameraZoomIn(0.666f);
 	}
 	else
 	{
-		gAgent.setFocusGlobal(LLToolPie::getInstance()->getPick());
+		gAgent.setFocusGlobal(gLastHitPosGlobal + gLastHitObjectOffset, gLastHitObjectID);
 	}
 
 	gViewerWindow->moveCursorToCenter();
@@ -5738,7 +5719,7 @@ class LLAttachmentDrop : public view_listener_t
 	{
 		// Called when the user clicked on an object attached to them
 		// and selected "Drop".
-		LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject *object = gViewerWindow->lastObjectHit();
 		if (!object)
 		{
 			llwarns << "handle_drop_attachment() - no object to drop" << llendl;
@@ -5838,7 +5819,7 @@ class LLAttachmentDetach : public view_listener_t
 	{
 		// Called when the user clicked on an object attached to them
 		// and selected "Detach".
-		LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject *object = gViewerWindow->lastObjectHit();
 		if (!object)
 		{
 			llwarns << "handle_detach() - no object to detach" << llendl;
@@ -5918,7 +5899,7 @@ class LLAttachmentEnableDrop : public view_listener_t
 		// in your inventory.  Therefore, we disable the drop option until the
 		// item is in your inventory
 
-		LLViewerObject*              object         = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+		LLViewerObject*              object         = gViewerWindow->lastObjectHit();
 		LLViewerJointAttachment*     attachment_pt  = NULL;
 		LLInventoryItem*             item           = NULL;
 
@@ -5960,7 +5941,7 @@ class LLAttachmentEnableDrop : public view_listener_t
 
 BOOL enable_detach(void*)
 {
-	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+	LLViewerObject* object = gViewerWindow->lastObjectHit();
 	if (!object) return FALSE;
 	if (!object->isAttachment()) return FALSE;
 
@@ -6064,7 +6045,7 @@ class LLAvatarSendIM : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getFirstObject() );
+		LLVOAvatar* avatar = find_avatar_from_object( gViewerWindow->lastObjectHit() );
 		if(avatar)
 		{
 			std::string name("IM");
@@ -6840,11 +6821,7 @@ void handle_dump_avatar_local_textures(void*)
 
 void handle_debug_avatar_textures(void*)
 {
-	LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
-	if (objectp)
-	{
-		LLFloaterAvatarTextures::show(objectp->getID());
-	}
+	LLFloaterAvatarTextures::show(gLastHitObjectID);
 }
 
 void handle_grab_texture(void* data)
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1aa7d2c3ffde2a0d0c628cd37d2a8d55a3bf7b5b..19025b34a4d19ac40e70a7855f00b090934a9dbc 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -3039,7 +3039,7 @@ void LLViewerObject::updatePositionCaches() const
 
 const LLVector3d LLViewerObject::getPositionGlobal() const
 {
-	LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion());
+	LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion());;
 
 	if (isAttachment())
 	{
@@ -3365,19 +3365,6 @@ LLViewerObject* LLViewerObject::getRootEdit() const
 	return (LLViewerObject*)root;
 }
 
-
-BOOL LLViewerObject::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
-										  S32 face,
-										  S32* face_hit,
-										  LLVector3* intersection,
-										  LLVector2* tex_coord,
-										  LLVector3* normal,
-										  LLVector3* bi_normal)
-{
-	return false;
-}
-
-
 U8 LLViewerObject::getMediaType() const
 {
 	if (mMedia)
@@ -4849,6 +4836,11 @@ BOOL LLViewerObject::setFlags(U32 flags, BOOL state)
 	return setit;
 }
 
+BOOL LLViewerObject::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
+{
+	return FALSE;
+}
+
 void LLViewerObject::applyAngularVelocity(F32 dt)
 {
 	//do target omega here
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index a143589ee92fd4ab9cccea4adf24bcdf66163c71..0f0fa62ea1bb8615a1cdadb0e9a67cf8b83b87d4 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -242,15 +242,9 @@ class LLViewerObject : public LLPrimitive, public LLRefCount
 	
 
 	//detect if given line segment (in agent space) intersects with this viewer object.
-	//returns TRUE if intersection detected and returns information about intersection
-	virtual BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
-									  S32 face = -1,                          // which face to check, -1 = ALL_SIDES
-									  S32* face_hit = NULL,                   // which face was hit
-									  LLVector3* intersection = NULL,         // return the intersection point
-									  LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point
-									  LLVector3* normal = NULL,               // return the surface normal at the intersection point
-									  LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point
-		);
+	//returns TRUE if intersection detected and moves end to the point of intersection
+	//closest to start.
+	virtual BOOL lineSegmentIntersect(const LLVector3& start, LLVector3& end) const;
 	
 	virtual const LLVector3d getPositionGlobal() const;
 	virtual const LLVector3 &getPositionRegion() const;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index a37120451e3b92ba4867e2e5e6bb30bc99b3aa94..8cd295b8a828aefc5e32e6c4c99b555360be56de 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -1078,14 +1078,14 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 &center)
 {
 }
 
-void LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent)
-{
-	generatePickList(camera);
-	renderPickList(screen_rect, pick_parcel_wall, render_transparent);
-}
 
-void LLViewerObjectList::generatePickList(LLCamera &camera)
+U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall, BOOL keep_pick_list)
 {
+	gRenderForSelect = TRUE;
+
+	//	LLTimer pick_timer;
+	if (!keep_pick_list)
+	{
 		LLViewerObject *objectp;
 		S32 i;
 		// Reset all of the GL names to zero.
@@ -1199,14 +1199,11 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
 			}
 
 			LLHUDIcon::generatePickIDs(i * step, step);
-	}
-}
-
-void LLViewerObjectList::renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent)
-{
-	gRenderForSelect = TRUE;
 		
-	gPipeline.renderForSelect(mSelectPickList, render_transparent, screen_rect);
+			// At this point, we should only have live drawables/viewer objects
+			gPipeline.renderForSelect(mSelectPickList);
+		}
+	}
 
 	//
 	// Render pass for selected objects
@@ -1223,6 +1220,7 @@ void LLViewerObjectList::renderPickList(const LLRect& screen_rect, BOOL pick_par
 
 	//llinfos << "Rendered " << count << " for select" << llendl;
 	//llinfos << "Took " << pick_timer.getElapsedTimeF32()*1000.f << "ms to pick" << llendl;
+	return 0;
 }
 
 LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id)
@@ -1528,4 +1526,3 @@ bool LLViewerObjectList::OrphanInfo::operator!=(const OrphanInfo &rhs) const
 	return !operator==(rhs);
 }
 
-
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index a5285930b299881b296696d27bf8a3e83f899f06..b9b6ff243ff55e3b4c06d9f3f375398b9581af52 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -108,10 +108,7 @@ class LLViewerObjectList
 	void updateAvatarVisibility();
 
 	// Selection related stuff
-	void renderObjectsForSelect(LLCamera &camera, const LLRect& screen_rect, BOOL pick_parcel_wall = FALSE, BOOL render_transparent = TRUE);
-	void generatePickList(LLCamera &camera);
-	void renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent);
-
+	U32 renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall = FALSE, BOOL keep_pick_list = FALSE);
 	LLViewerObject *getSelectedObject(const U32 object_id);
 
 	inline S32 getNumObjects() { return mObjects.count(); }
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 4c575ff1392b98b8e72ae78cc2dde58ee5fa21e1..0296aee8cabf4c53c4d84f30b60b0ea7a86fe7de 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -203,8 +203,32 @@ extern S32 gJamesInt;
 LLViewerWindow	*gViewerWindow = NULL;
 LLVelocityBar	*gVelocityBar = NULL;
 
+LLVector3d		gLastHitPosGlobal;
+LLVector3d		gLastHitObjectOffset;
+LLUUID			gLastHitObjectID;
+S32				gLastHitObjectFace = -1;
+BOOL			gLastHitLand = FALSE;
+F32				gLastHitUCoord;
+F32				gLastHitVCoord;
+
+
+LLVector3d		gLastHitNonFloraPosGlobal;
+LLVector3d		gLastHitNonFloraObjectOffset;
+LLUUID			gLastHitNonFloraObjectID;
+S32				gLastHitNonFloraObjectFace = -1;
+BOOL			gLastHitParcelWall = FALSE;
+
+S32				gLastHitUIElement = 0;
+LLHUDIcon*		gLastHitHUDIcon = NULL;
 
 BOOL			gDebugSelect = FALSE;
+U8				gLastPickAlpha = 255;
+BOOL			gUseGLPick = FALSE;
+
+// On the next pick pass (whenever that happens)
+// should we try to pick individual faces?
+// Cleared to FALSE every time a pick happens.
+BOOL			gPickFaces = FALSE;
 
 LLFrameTimer	gMouseIdleTimer;
 LLFrameTimer	gAwayTimer;
@@ -215,11 +239,6 @@ BOOL			gShowOverlayTitle = FALSE;
 BOOL			gPickTransparent = TRUE;
 
 BOOL			gDebugFastUIRender = FALSE;
-LLViewerObject*  gDebugRaycastObject = NULL;
-LLVector3       gDebugRaycastIntersection;
-LLVector2       gDebugRaycastTexCoord;
-LLVector3       gDebugRaycastNormal;
-LLVector3       gDebugRaycastBinormal;
 
 // HUD display lines in lower right
 BOOL				gDisplayWindInfo = FALSE;
@@ -237,6 +256,9 @@ const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before co
 const F32 MAX_FAST_FRAME_TIME = 0.5f;
 const F32 FAST_FRAME_INCREMENT = 0.1f;
 
+const S32 PICK_HALF_WIDTH = 5;
+const S32 PICK_DIAMETER = 2 * PICK_HALF_WIDTH+1;
+
 const F32 MIN_DISPLAY_SCALE = 0.85f;
 
 const S32 CONSOLE_BOTTOM_PAD = 40;
@@ -1487,8 +1509,8 @@ LLViewerWindow::LLViewerWindow(
 	mToolStored( NULL ),
 	mSuppressToolbox( FALSE ),
 	mHideCursorPermanent( FALSE ),
-	mIgnoreActivate( FALSE ),
-	mHoverPick()
+	mPickPending(FALSE),
+	mIgnoreActivate( FALSE )
 {
 	// Default to application directory.
 	LLViewerWindow::sSnapshotBaseName = "Snapshot";
@@ -1596,6 +1618,8 @@ LLViewerWindow::LLViewerWindow(
 	mCurrentMousePoint.mX = getWindowWidth() / 2;
 	mCurrentMousePoint.mY = getWindowHeight() / 2;
 
+	mPickBuffer = new U8[PICK_DIAMETER * PICK_DIAMETER * 4];
+
 	gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
 	mOverlayTitle = gSavedSettings.getString("OverlayTitle");
 	// Can't have spaces in settings.ini strings, so use underscores instead and convert them.
@@ -2008,6 +2032,9 @@ LLViewerWindow::~LLViewerWindow()
 
 	LLViewerImage::cleanupClass();
 	
+	delete[] mPickBuffer;
+	mPickBuffer = NULL;
+
 	llinfos << "Cleaning up select manager" << llendl;
 	LLSelectMgr::getInstance()->cleanup();
 
@@ -2706,10 +2733,6 @@ BOOL LLViewerWindow::handlePerFrameHover()
 
 	LLView::sMouseHandlerMessage.clear();
 
-	S32 x = mCurrentMousePoint.mX;
-	S32 y = mCurrentMousePoint.mY;
-	MASK mask = gKeyboard->currentMask(TRUE);
-
 	//RN: fix for asynchronous notification of mouse leaving window not working
 	LLCoordWindow mouse_pos;
 	mWindow->getCursorPosition(&mouse_pos);
@@ -2725,7 +2748,6 @@ BOOL LLViewerWindow::handlePerFrameHover()
 		mMouseInWindow = TRUE;
 	}
 
-
 	S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
 	S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
 
@@ -2756,6 +2778,10 @@ BOOL LLViewerWindow::handlePerFrameHover()
 		return TRUE;
 	}
 
+	S32 x = mCurrentMousePoint.mX;
+	S32 y = mCurrentMousePoint.mY;
+	MASK mask = gKeyboard->currentMask(TRUE);
+
 	// clean up current focus
 	LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
 	if (cur_focus)
@@ -3097,41 +3123,10 @@ BOOL LLViewerWindow::handlePerFrameHover()
 		LLSelectMgr::getInstance()->deselectUnused();
 	}
 
-	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
-	{
-		gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1,
-											  NULL,
-											  &gDebugRaycastIntersection,
-											  &gDebugRaycastTexCoord,
-											  &gDebugRaycastNormal,
-											  &gDebugRaycastBinormal);
-	}
-
-	static U16 frame_counter = 0;
-	static S32 previous_x = -1;
-	static S32 previous_y = -1;
-	
-	if (((previous_x != x) || (previous_y != y)) ||
-		((gSavedSettings.getBOOL("PerFrameHoverPick"))
-		 && ((frame_counter % gSavedSettings.getS32("PerFrameHoverPickCount")) == 0)))
-		{
-			pickAsync(getCurrentMouseX(), getCurrentMouseY(), mask, hoverPickCallback, TRUE);
-		}
-	frame_counter++;
-	previous_x = x;
-	previous_y = y;
-	
 	return handled;
 }
 
 
-/* static */
-void LLViewerWindow::hoverPickCallback(const LLPickInfo& pick_info)
-{
-	gViewerWindow->mHoverPick = pick_info;
-}
-	
-
 void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
 {
 	// Store last mouse location.
@@ -3225,7 +3220,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
 			glPushMatrix();
 			if (selection->getSelectType() == SELECT_TYPE_HUD)
 			{
-				F32 zoom = gAgent.mHUDCurZoom;
+				F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 				glScalef(zoom, zoom, zoom);
 			}
 
@@ -3377,14 +3372,19 @@ BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewe
 	return intersect;
 }
 
-void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent, BOOL get_surface_info)
+void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent, BOOL pick_parcel_walls)
 {
 	if (gNoRender)
 	{
 		return;
 	}
 	
-	// push back pick info object
+	glClear(GL_DEPTH_BUFFER_BIT);
+	gDepthDirty = TRUE;
+
+	S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]);
+	S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]);
+
 	BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible();
 	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
 	{
@@ -3392,44 +3392,29 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback
 		// "Show Debug Alpha" means no object actually transparent
 		pick_transparent = TRUE;
 	}
+	gPickTransparent = pick_transparent;
 
-	// center initial pick frame buffer region under mouse cursor
-	// since that area is guaranteed to be onscreen and hence a valid
-	// part of the framebuffer
-	if (mPicks.empty())
-	{
-		mPickScreenRegion.setCenterAndSize(x, y_from_bot, PICK_DIAMETER, PICK_DIAMETER);
-
-		if (mPickScreenRegion.mLeft < 0) mPickScreenRegion.translate(-mPickScreenRegion.mLeft, 0);
-		if (mPickScreenRegion.mBottom < 0) mPickScreenRegion.translate(0, -mPickScreenRegion.mBottom);
-		if (mPickScreenRegion.mRight > mWindowRect.getWidth() ) mPickScreenRegion.translate(mWindowRect.getWidth() - mPickScreenRegion.mRight, 0);
-		if (mPickScreenRegion.mTop > mWindowRect.getHeight() ) mPickScreenRegion.translate(0, mWindowRect.getHeight() - mPickScreenRegion.mTop);
-	}
+	gUseGLPick = FALSE;
+	mPickCallback = callback;
 
-	// set frame buffer region for picking results
-	// stack multiple picks left to right
-	LLRect screen_region = mPickScreenRegion;
-	screen_region.translate(mPicks.size() * PICK_DIAMETER, 0);
-
-	LLPickInfo pick(LLCoordGL(x, y_from_bot), screen_region, mask, pick_transparent, get_surface_info, callback);
+	// Default to not hitting anything
+	gLastHitPosGlobal.zeroVec();
+	gLastHitObjectOffset.zeroVec();
+	gLastHitObjectID.setNull();
+	gLastHitObjectFace = -1;
 
-	schedulePick(pick);
-}
+	gLastHitNonFloraPosGlobal.zeroVec();
+	gLastHitNonFloraObjectOffset.zeroVec();
+	gLastHitNonFloraObjectID.setNull();
+	gLastHitNonFloraObjectFace = -1;
 
-void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
-{
-	llassert_always(pick_info.mScreenRegion.notNull());
-	mPicks.push_back(pick_info);
-	
-	S32 scaled_x = llround((F32)pick_info.mMousePt.mX * mDisplayScale.mV[VX]);
-	S32 scaled_y = llround((F32)pick_info.mMousePt.mY * mDisplayScale.mV[VY]);
+	gLastHitParcelWall = FALSE;
 
-	// Default to not hitting anything
 	LLCamera pick_camera;
 	pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin());
 	pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(),
 								   LLViewerCamera::getInstance()->getUpAxis(),
-								   LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(pick_info.mMousePt.mX, pick_info.mMousePt.mY));
+								   LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot));
 	pick_camera.setView(0.5f*DEG_TO_RAD);
 	pick_camera.setNear(LLViewerCamera::getInstance()->getNear());
 	pick_camera.setFar(LLViewerCamera::getInstance()->getFar());
@@ -3446,38 +3431,117 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
 	glPushMatrix();
 	glLoadIdentity();
 
-	// clear work area
-	{
-		LLGLState scissor_state(GL_SCISSOR_TEST);
-		scissor_state.enable();
-		glScissor(pick_info.mScreenRegion.mLeft, pick_info.mScreenRegion.mBottom, pick_info.mScreenRegion.getWidth(), pick_info.mScreenRegion.getHeight());
+	// build perspective transform and picking viewport
+	// Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point.
+	// Don't limit the select distance for this pick.
+	LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - (PICK_HALF_WIDTH + 2), scaled_y - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4, FALSE);
+	// make viewport big enough to handle antialiased frame buffers
+	gGLViewport[0] = scaled_x - (PICK_HALF_WIDTH + 2);
+	gGLViewport[1] = scaled_y - (PICK_HALF_WIDTH + 2);
+	gGLViewport[2] = PICK_DIAMETER + 4;
+	gGLViewport[3] = PICK_DIAMETER + 4;
+	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+	LLViewerCamera::updateFrustumPlanes(pick_camera);
+	stop_glerror();
+
 	glClearColor(0.f, 0.f, 0.f, 0.f);
 	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 	//glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+	// Draw the objects so the user can select them.
+	// The starting ID is 1, since land is zero.
+	gObjectList.renderObjectsForSelect(pick_camera, pick_parcel_walls);
+
+	stop_glerror();
+
+	// restore drawing state
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	setupViewport();
+
+	mPickPoint.set(x, y_from_bot);
+	mPickOffset.set(0, 0);
+	mPickMask = mask;
+	mPickPending = TRUE;
+
+	// delay further event processing until we receive results of pick
+	mWindow->delayInputProcessing();
+}
+
+void LLViewerWindow::hitUIElementImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask))
+{
+	// Performs the GL UI pick.
+	// Stores its results in global, gLastHitUIElement
+	if (gNoRender)
+	{
+		return;
 	}
 	
-	// build perspective transform and picking viewport
+	hitUIElementAsync(x, y, gKeyboard->currentMask(TRUE), NULL);
+	performPick();
+	if (callback)
+	{
+		callback(x, y, gKeyboard->currentMask(TRUE));
+	}
+}
+
+//RN: this currently doesn't do anything
+void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask))
+{
+	if (gNoRender)
+	{
+		return;
+	}
+
+// 	F32 delta_time = gAlphaFadeTimer.getElapsedTimeAndResetF32();
+
+	gUseGLPick = FALSE;
+	mPickCallback = callback;
+
+	// Default to not hitting anything
+	gLastHitUIElement = 0;
+
+	LLCamera pick_camera;
+	pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin());
+	pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(),
+								   LLViewerCamera::getInstance()->getUpAxis(),
+								   LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot));
+	pick_camera.setView(0.5f*DEG_TO_RAD);
+	pick_camera.setNear(LLViewerCamera::getInstance()->getNear());
+	pick_camera.setFar(LLViewerCamera::getInstance()->getFar());
+	pick_camera.setAspect(1.f);
+
+	// save our drawing state
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadIdentity();
+	
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadIdentity();
+
+	// build orthogonal transform and picking viewport
 	// Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point.
 	// Don't limit the select distance for this pick.
-	LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, FALSE);
+	setup2DRender();
+	const LLVector2& display_scale = getDisplayScale();
+	glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
 
-	// render for object picking
+	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 
 	// make viewport big enough to handle antialiased frame buffers
-	gGLViewport[0] = pick_info.mScreenRegion.mLeft;
-	gGLViewport[1] = pick_info.mScreenRegion.mBottom;
-	gGLViewport[2] = pick_info.mScreenRegion.getWidth();
-	gGLViewport[3] = pick_info.mScreenRegion.getHeight();
-
-	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-	LLViewerCamera::updateFrustumPlanes(pick_camera);
+	glViewport(x - (PICK_HALF_WIDTH + 2), y_from_bot - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4);
 	stop_glerror();
 
+	glClearColor(0.f, 0.f, 0.f, 0.f);
+	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+
 	// Draw the objects so the user can select them.
 	// The starting ID is 1, since land is zero.
-	LLRect pick_region;
-	pick_region.setOriginAndSize(scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER);
-	gObjectList.renderObjectsForSelect(pick_camera, pick_region, FALSE, pick_info.mPickTransparent);
+	//drawForSelect();
 
 	stop_glerror();
 
@@ -3487,121 +3551,309 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
 	glMatrixMode(GL_MODELVIEW);
 	glPopMatrix();
 
-	setup3DRender();
-	setup2DRender();
 	setupViewport();
 
-	// delay further event processing until we receive results of pick
-	mWindow->delayInputProcessing();
+	mPickPoint.set(x, y_from_bot);
+	mPickOffset.set(0, 0);
+	mPickMask = mask;
+	mPickPending = TRUE;
 }
 
-
 void LLViewerWindow::performPick()
 {
-	if (gNoRender)
+	if (gNoRender || !mPickPending)
 	{
 		return;
 	}
 
-	if (!mPicks.empty())
+	mPickPending = FALSE;
+	U32	te_offset = NO_FACE;
+	
+	// find pick region that is fully onscreen
+	LLCoordGL scaled_pick_point = mPickPoint;
+	scaled_pick_point.mX = llclamp(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), PICK_HALF_WIDTH, getWindowDisplayWidth() - PICK_HALF_WIDTH);
+	scaled_pick_point.mY = llclamp(llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]), PICK_HALF_WIDTH, getWindowDisplayHeight() - PICK_HALF_WIDTH);
+
+	glReadPixels(scaled_pick_point.mX - PICK_HALF_WIDTH, scaled_pick_point.mY - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
+
+	S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH;
+	S32 name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
+	gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
+
+	if (name >= (S32)GL_NAME_UI_RESERVED && name < (S32)GL_NAME_INDEX_OFFSET)
+	{
+		// hit a UI element
+		gLastHitUIElement = name;
+		if (mPickCallback)
+		{
+			mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask);
+		}
+	}
+
+	//imdebug("rgba rbga=bbba b=8 w=%d h=%d %p", PICK_DIAMETER, PICK_DIAMETER, mPickBuffer);
+
+	S32 x_offset = mPickPoint.mX - llround((F32)scaled_pick_point.mX / mDisplayScale.mV[VX]);
+	S32 y_offset = mPickPoint.mY - llround((F32)scaled_pick_point.mY / mDisplayScale.mV[VY]);
+
+	
+	// we hit nothing, scan surrounding pixels for something useful
+	if (!name)
 	{
-		std::vector<LLPickInfo>::iterator pick_it;
-		for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
+		S32 closest_distance = 10000;
+		//S32 closest_pick_name = 0;
+		for (S32 col = 0; col < PICK_DIAMETER; col++)
 		{
-			pick_it->fetchResults();
+			for (S32 row = 0; row < PICK_DIAMETER; row++)
+			{
+				S32 distance_squared = (llabs(col - x_offset - PICK_HALF_WIDTH) * llabs(col - x_offset - PICK_HALF_WIDTH)) + (llabs(row - y_offset - PICK_HALF_WIDTH) * llabs(row - y_offset - PICK_HALF_WIDTH));
+				pixel_index = row * PICK_DIAMETER + col;
+				S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
+				gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
+				if (test_name && distance_squared < closest_distance)
+				{
+					closest_distance = distance_squared;
+					name = test_name;
+					gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
+					mPickOffset.mX = col - PICK_HALF_WIDTH;
+					mPickOffset.mY = row - PICK_HALF_WIDTH;
+				}
+			}
 		}
+	}
 
-		mLastPick = mPicks.back();
-		mPicks.clear();
+	if (name)
+	{
+		mPickPoint.mX += llround((F32)mPickOffset.mX * mDisplayScale.mV[VX]);
+		mPickPoint.mY += llround((F32)mPickOffset.mY * mDisplayScale.mV[VY]);
 	}
 
-}
+	if (gPickFaces)
+	{
+		te_offset = ((U32)name >> 20);
+		name &= 0x000fffff;
+		// don't clear gPickFaces, as we still need to check for UV coordinates
+	}
 
-// Performs the GL object/land pick.
-LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot,  BOOL pick_transparent)
-{
-	if (gNoRender)
+	LLViewerObject	*objectp = NULL;
+
+	// Frontmost non-foreground object that isn't trees or grass
+	LLViewerObject* nonflora_objectp = NULL;
+	S32 nonflora_name = -1;
+	S32 nonflora_te_offset = NO_FACE;
+
+	if (name == (S32)GL_NAME_PARCEL_WALL)
 	{
-		return LLPickInfo();
+		gLastHitParcelWall = TRUE;
 	}
 
-	pickAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent);
-	// assume that pickAsync put the results in the back of the mPicks list
-	mLastPick = mPicks.back();
-	mLastPick.fetchResults();
-	mPicks.pop_back();
+	gLastHitHUDIcon = NULL;
 
-	return mLastPick;
+	objectp = gObjectList.getSelectedObject(name);
+	if (objectp)
+	{
+		LLViewerObject* parent = (LLViewerObject*)(objectp->getParent());
+		if (NULL == parent) {
+			// if you are the parent
+			parent = objectp;
+		}
+		if (objectp->mbCanSelect)
+		{
+			te_offset = (te_offset == 16) ? NO_FACE : te_offset;
+
+			// If the hit object isn't a plant, store it as the frontmost non-flora object.
+			LLPCode pcode = objectp->getPCode();
+			if( (LL_PCODE_LEGACY_GRASS != pcode) &&
+				(LL_PCODE_LEGACY_TREE != pcode) &&
+				(LL_PCODE_TREE_NEW != pcode))
+			{
+				nonflora_objectp = objectp;
+				nonflora_name = name;
+				nonflora_te_offset = te_offset;
+			}
+		}
+		else
+		{
+			//llinfos << "Hit object you can't select" << llendl;
+		}
+	}
+	else
+	{
+		// was this name referring to a hud icon?
+		gLastHitHUDIcon = LLHUDIcon::handlePick(name);
+	}
+
+	analyzeHit( 
+		mPickPoint.mX, mPickPoint.mY, objectp, te_offset,
+		&gLastHitObjectID, &gLastHitObjectFace, &gLastHitPosGlobal, &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord );
+
+	if (objectp && !gLastHitObjectID.isNull())
+	{
+		gLastHitObjectOffset = gAgent.calcFocusOffset(objectp, mPickPoint.mX, mPickPoint.mY);
+	}
+
+	if( objectp == nonflora_objectp )
+	{
+		gLastHitNonFloraObjectID	= gLastHitObjectID;
+		gLastHitNonFloraObjectFace	= gLastHitObjectFace;
+		gLastHitNonFloraPosGlobal	= gLastHitPosGlobal;
+		gLastHitNonFloraObjectOffset= gLastHitObjectOffset;
+	}
+	else
+	{
+		analyzeHit(  mPickPoint.mX, mPickPoint.mY, nonflora_objectp, nonflora_te_offset,
+			&gLastHitNonFloraObjectID, &gLastHitNonFloraObjectFace, &gLastHitNonFloraPosGlobal,
+			&gLastHitLand, &gLastHitUCoord, &gLastHitVCoord);
+
+		if( nonflora_objectp )
+		{
+			gLastHitNonFloraObjectOffset = gAgent.calcFocusOffset(nonflora_objectp, mPickPoint.mX, mPickPoint.mY);
+		}
+	}
+
+	if (mPickCallback)
+	{
+		mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask);
+	}
+
+	gPickFaces = FALSE;
 }
 
-LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
-												LLViewerObject *this_object,
-												S32 this_face,
-												S32* face_hit,
-												LLVector3 *intersection,
-												LLVector2 *uv,
-												LLVector3 *normal,
-												LLVector3 *binormal)
+// Performs the GL object/land pick.
+// Stores its results in globals, gHit*
+void LLViewerWindow::hitObjectOrLandGlobalImmediate(S32 x, S32 y_from_bot, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent)
 {
-	S32 x = mouse_x;
-	S32 y = mouse_y;
-
-	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
+	if (gNoRender)
 	{
-		x = getCurrentMouseX();
-		y = getCurrentMouseY();
+		return;
 	}
+	
+	hitObjectOrLandGlobalAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent);
+	performPick();
+	if (callback)
+	{
+		callback(x, y_from_bot, gKeyboard->currentMask(TRUE));
+	}
+}
 
-	// HUD coordinates of mouse
-	LLVector3 mouse_point_hud = mousePointHUD(x, y);
-	LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
-	LLVector3 mouse_hud_end   = mouse_point_hud + LLVector3(depth, 0, 0);
+LLViewerObject* LLViewerWindow::getObjectUnderCursor(const F32 depth)
+{
+	S32 x = getCurrentMouseX();
+	S32 y = getCurrentMouseY();
 	
-	// world coordinates of mouse
 	LLVector3		mouse_direction_global = mouseDirectionGlobal(x,y);
-	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
-	LLVector3 mouse_world_start = mouse_point_global;
-	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
-
+	LLVector3		camera_pos_global = LLViewerCamera::getInstance()->getOrigin();
+	LLVector3		pick_end = camera_pos_global + mouse_direction_global * depth;
+	LLVector3		collision_point;
+	return gPipeline.pickObject(camera_pos_global, pick_end, collision_point);
+}
+
+void LLViewerWindow::analyzeHit(
+	S32				x,				// input
+	S32				y_from_bot,		// input
+	LLViewerObject* objectp,		// input
+	U32				te_offset,		// input
+	LLUUID*			hit_object_id_p,// output
+	S32*			hit_face_p,		// output
+	LLVector3d*		hit_pos_p,		// output
+	BOOL*			hit_land,		// output
+	F32*			hit_u_coord,	// output
+	F32*			hit_v_coord)	// output
+{
+	// Clean up inputs
+	S32 face = -1;
 	
-	LLViewerObject* found = NULL;
+	if (te_offset != NO_FACE ) 
+	{
+		face = te_offset;
+	}
 
-	if (this_object)  // check only this object
+	*hit_land = FALSE;
+
+	if (objectp)
 	{
-		if (this_object->isHUDAttachment()) // is a HUD object?
+		if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
 		{
-			if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face,
-												  face_hit, intersection, uv, normal, binormal))
+			// Hit land
+			*hit_land = TRUE;
+
+			// put global position into land_pos
+			LLVector3d land_pos;
+			if (mousePointOnLandGlobal(x, y_from_bot, &land_pos))
 			{
-				found = this_object;
+				*hit_object_id_p = LLUUID::null;
+				*hit_face_p = -1;
+
+				// Fudge the land focus a little bit above ground.
+				*hit_pos_p = land_pos + LLVector3d(0.f, 0.f, 0.1f);
+				//llinfos << "DEBUG Hit Land " << *hit_pos_p  << llendl;
+				return;
 			}
+			else
+			{
+				//llinfos << "Hit land but couldn't find position" << llendl;
+				// Fall through to "Didn't hit anything"
 			}
-		
-		else // is a world object
+		}
+		else
 		{
-			if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face,
-												  face_hit, intersection, uv, normal, binormal))
+			*hit_object_id_p = objectp->mID;
+			*hit_face_p = face;
+
+			// Hit an object
+			if (objectp->isAvatar())
 			{
-				found = this_object;
+				*hit_pos_p = gAgent.getPosGlobalFromAgent(((LLVOAvatar*)objectp)->mPelvisp->getWorldPosition());
 			}
+			else if (objectp->mDrawable.notNull())
+			{
+				*hit_pos_p = gAgent.getPosGlobalFromAgent(objectp->getRenderPosition());
 			}
+			else
+			{
+				// regular object
+				*hit_pos_p = objectp->getPositionGlobal();
 			}
 
-	else // check ALL objects
+			if (gPickFaces && face > -1 &&
+				objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
+				face < objectp->mDrawable->getNumFaces())
 			{
-		found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end,
-													face_hit, intersection, uv, normal, binormal);
-
-		if (!found) // if not found in HUD, look in world:
-
+				// render red-blue gradient to get 1/256 precision
+				// then render green grid to get final 1/4096 precision
+				S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]);
+				S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]);
+				const S32 UV_PICK_WIDTH = 41;
+				const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
+				U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
+				S32 pick_face = face;
+				LLFace* facep = objectp->mDrawable->getFace(pick_face);
+				LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
+				glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
+				gPipeline.renderFaceForUVSelect(facep);
+
+				glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
+				U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
+				*hit_u_coord = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
+				*hit_v_coord = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
+			}
+			else
 			{
-			found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end,
-														  face_hit, intersection, uv, normal, binormal);
+				*hit_u_coord = 0.f;
+				*hit_v_coord = 0.f;
 			}
 
+			//llinfos << "DEBUG Hit Object " << *hit_pos_p << llendl;
+			return;
+		}
 	}
 
-	return found;
+	// Didn't hit anything.
+	*hit_object_id_p = LLUUID::null;
+	*hit_face_p = -1;
+	*hit_pos_p = LLVector3d::zero;
+	*hit_u_coord = 0.f;
+	*hit_v_coord = 0.f;
+	//llinfos << "DEBUG Hit Nothing " << llendl;
 }
 
 // Returns unit vector relative to camera
@@ -3632,18 +3884,6 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
 	return mouse_vector;
 }
 
-LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
-{
-	// find screen resolution
-	S32			height = getWindowHeight();
-	S32			width = getWindowWidth();
-
-	// remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
-	F32 hud_x = -((F32)x - (F32)width/2.f)  / height;
-	F32 hud_y = ((F32)y - (F32)height/2.f) / height;
-
-	return LLVector3(0.f, hud_x, hud_y);
-}
 
 // Returns unit vector relative to camera in camera space
 // indicating direction of point on screen x,y
@@ -4009,7 +4249,8 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p
 	LLHUDText::setDisplayText(FALSE) ;
 	if (type == SNAPSHOT_TYPE_OBJECT_ID)
 	{
-		gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE);
+		gPickTransparent = FALSE;
+		gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, FALSE);
 	}
 	else
 	{
@@ -4211,8 +4452,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 	F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
 	F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
 
-	gObjectList.generatePickList(*LLViewerCamera::getInstance());
-
 	for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
 	{
 		S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
@@ -4233,7 +4472,9 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 				LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor)));
 				setup3DRender();
 				setupViewport();
-				gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE);
+				BOOL first_time_through = (subimage_x + subimage_y == 0);
+				gPickTransparent = FALSE;
+				gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, !first_time_through);
 			}
 			else
 			{
@@ -4482,6 +4723,27 @@ void LLViewerWindow::setup2DRender()
 	gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight());
 }
 
+// Could cache the pointer from the last hitObjectOrLand here.
+LLViewerObject *LLViewerWindow::lastObjectHit()
+{
+	return gObjectList.findObject( gLastHitObjectID );
+}
+
+const LLVector3d& LLViewerWindow::lastObjectHitOffset()
+{
+	return gLastHitObjectOffset;
+}
+
+// Could cache the pointer from the last hitObjectOrLand here.
+LLViewerObject *LLViewerWindow::lastNonFloraObjectHit()
+{
+	return gObjectList.findObject( gLastHitNonFloraObjectID );
+}
+
+const LLVector3d& LLViewerWindow::lastNonFloraObjectHitOffset()
+{
+	return gLastHitNonFloraObjectOffset;
+}
 
 
 void LLViewerWindow::setShowProgress(const BOOL show)
@@ -4904,7 +5166,46 @@ F32 LLViewerWindow::getDisplayAspectRatio() const
 
 void LLViewerWindow::drawPickBuffer() const
 {
-	mHoverPick.drawPickBuffer();
+	if (mPickBuffer)
+	{
+		gGL.color4f(1,1,1,1);
+		gGL.pushMatrix();
+		LLGLDisable no_blend(GL_BLEND);
+		LLGLDisable no_alpha_test(GL_ALPHA_TEST);
+		LLGLSNoTexture no_texture;
+		glPixelZoom(10.f, 10.f);
+		glRasterPos2f(((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f), 
+			((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f));
+		glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
+		glPixelZoom(1.f, 1.f);
+		gGL.color4fv(LLColor4::white.mV);
+		gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)), 
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
+			llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
+			FALSE);
+		gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)), 
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
+			llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f), 
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f));
+		gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
+			llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f), 
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f));
+		gGL.translatef(10.f, 10.f, 0.f);
+		gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), 
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f),
+			llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f),
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]),
+			FALSE);
+		gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX)* 10.f), 
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH + mPickOffset.mY + 1) * 10.f),
+			llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX + 1) * 10.f),
+			llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH  + mPickOffset.mY) * 10.f),
+			FALSE);
+		gGL.popMatrix();
+		gGL.flush();
+	}
 }
 
 void LLViewerWindow::calcDisplayScale()
@@ -5093,342 +5394,3 @@ void* LLBottomPanel::createToolBar(void* data)
 	gToolBar = new LLToolBar();
 	return gToolBar;
 }
-
-//
-// LLPickInfo
-//
-LLPickInfo::LLPickInfo()
-	: mKeyMask(MASK_NONE),
-	  mPickCallback(NULL),
-	  mPickType(PICK_INVALID),
-	  mWantSurfaceInfo(FALSE),
-	  mObjectFace(-1),
-	  mUVCoords(-1.f, -1.f),
-	  mSTCoords(-1.f, -1.f),
-	  mXYCoords(-1, -1),
-	  mIntersection(),
-	  mNormal(),
-	  mBinormal(),
-	  mHUDIcon(NULL),
-	  mPickTransparent(FALSE)
-{
-}
-
-LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, 
-					   const LLRect& screen_region,
-						MASK keyboard_mask, 
-						BOOL pick_transparent,
-						BOOL pick_uv_coords,
-						void (*pick_callback)(const LLPickInfo& pick_info))
-	: mMousePt(mouse_pos),
-	  mScreenRegion(screen_region),
-	  mKeyMask(keyboard_mask),
-	  mPickCallback(pick_callback),
-	  mPickType(PICK_INVALID),
-	  mWantSurfaceInfo(pick_uv_coords),
-	  mObjectFace(-1),
-	  mUVCoords(-1.f, -1.f),
-	  mSTCoords(-1.f, -1.f),
-	  mXYCoords(-1, -1),
-	  mNormal(),
-	  mBinormal(),
-	  mHUDIcon(NULL),
-	  mPickTransparent(pick_transparent)
-{
-}
-
-LLPickInfo::~LLPickInfo()
-{
-}
-
-void LLPickInfo::fetchResults()
-{
-	// read back colors and depth values from buffer
-	glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
-	glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_DEPTH_COMPONENT, GL_FLOAT, mPickDepthBuffer );
-
-	// find pick region that is fully onscreen
-	LLCoordGL scaled_pick_point;;
-	scaled_pick_point.mX = llclamp(llround((F32)mMousePt.mX * gViewerWindow->getDisplayScale().mV[VX]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayWidth() - PICK_HALF_WIDTH);
-	scaled_pick_point.mY = llclamp(llround((F32)mMousePt.mY * gViewerWindow->getDisplayScale().mV[VY]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayHeight() - PICK_HALF_WIDTH);
-	S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH;
-	S32 pick_id = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
-	F32 depth = mPickDepthBuffer[pixel_index];
-
-	S32 x_offset = mMousePt.mX - llround((F32)scaled_pick_point.mX / gViewerWindow->getDisplayScale().mV[VX]);
-	S32 y_offset = mMousePt.mY - llround((F32)scaled_pick_point.mY / gViewerWindow->getDisplayScale().mV[VY]);
-
-	mPickPt = mMousePt;
-
-	// we hit nothing, scan surrounding pixels for something useful
-	if (!pick_id)
-	{
-		S32 closest_distance = 10000;
-		//S32 closest_pick_name = 0;
-		for (S32 col = 0; col < PICK_DIAMETER; col++)
-		{
-			for (S32 row = 0; row < PICK_DIAMETER; row++)
-			{
-				S32 distance_squared = (llabs(col - x_offset - PICK_HALF_WIDTH) * llabs(col - x_offset - PICK_HALF_WIDTH)) + (llabs(row - y_offset - PICK_HALF_WIDTH) * llabs(row - y_offset - PICK_HALF_WIDTH));
-				pixel_index = row * PICK_DIAMETER + col;
-				S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
-				if (test_name && distance_squared < closest_distance)
-				{
-					closest_distance = distance_squared;
-					pick_id = test_name;
-					depth = mPickDepthBuffer[pixel_index];
-					mPickPt.mX = mMousePt.mX + (col - PICK_HALF_WIDTH);
-					mPickPt.mY = mMousePt.mY + (row - PICK_HALF_WIDTH);
-				}
-			}
-		}
-	}
-
-	U32 te_offset = ((U32)pick_id >> 20);
-	pick_id &= 0x000fffff;
-
-	//unproject relative clicked coordinate from window coordinate using GL
-	GLint viewport[4];
-	GLdouble modelview[16];
-	GLdouble projection[16];
-	GLfloat winX, winY;
-	GLdouble posX, posY, posZ;
-
-	LLViewerObject* objectp = gObjectList.getSelectedObject(pick_id);
-
-	if (pick_id == (S32)GL_NAME_PARCEL_WALL)
-	{
-		mPickType = PICK_PARCEL_WALL;
-	}
-	else if (objectp)
-	{
-		if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
-		{
-			// Hit land
-			mPickType = PICK_LAND;
-			mObjectID.setNull(); // land has no id
-
-			// put global position into land_pos
-			LLVector3d land_pos;
-			if (gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos))
-			{
-				// Fudge the land focus a little bit above ground.
-				mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
-			}
-		}
-		else
-		{
-			if(isFlora(objectp))
-			{
-				mPickType = PICK_FLORA;
-			}
-			else
-			{
-				mPickType = PICK_OBJECT;
-			}
-			mObjectOffset = gAgent.calcFocusOffset(objectp, mPickPt.mX, mPickPt.mY);
-			mObjectID = objectp->mID;
-			mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
-
-			glh::matrix4f newModel((F32*)LLViewerCamera::getInstance()->getModelview().mMatrix);
-
-			for(U32 i = 0; i < 16; ++i)
-			{
-				modelview[i] = newModel.m[i];
-				projection[i] = LLViewerCamera::getInstance()->getProjection().mMatrix[i/4][i%4];
-			}
-			glGetIntegerv( GL_VIEWPORT, viewport );
-
-			winX = ((F32)mPickPt.mX) * gViewerWindow->getDisplayScale().mV[VX];
-			winY = ((F32)mPickPt.mY) * gViewerWindow->getDisplayScale().mV[VY];
-
-			gluUnProject( winX, winY, depth, modelview, projection, viewport, &posX, &posY, &posZ);
-
-			mPosGlobal = gAgent.getPosGlobalFromAgent(LLVector3(posX, posY, posZ));
-			
-			if (mWantSurfaceInfo)
-			{
-				getSurfaceInfo();
-			}
-		}
-	}
-	else
-	{
-		// was this name referring to a hud icon?
-		mHUDIcon = LLHUDIcon::handlePick(pick_id);
-		if (mHUDIcon)
-		{
-			mPickType = PICK_ICON;
-			mPosGlobal = mHUDIcon->getPositionGlobal();
-		}
-	}
-
-	if (mPickCallback)
-	{
-		mPickCallback(*this);
-	}
-}
-
-LLPointer<LLViewerObject> LLPickInfo::getObject() const
-{
-	return gObjectList.findObject( mObjectID );
-}
-
-void LLPickInfo::updateXYCoords()
-{
-	const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
-	LLPointer<LLViewerImage> imagep = gImageList.getImage(tep->getID());
-	if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
-	{
-		LLCoordGL coords;
-		
-		coords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
-		coords.mY = llround(mUVCoords.mV[VY] * (F32)imagep->getHeight());
-
-		gViewerWindow->getWindow()->convertCoords(coords, &mXYCoords);
-	}
-}
-
-void LLPickInfo::drawPickBuffer() const
-{
-	if (mPickBuffer)
-	{
-		gGL.pushMatrix();
-		LLGLDisable no_blend(GL_BLEND);
-		LLGLDisable no_alpha_test(GL_ALPHA_TEST);
-		LLGLSNoTexture no_texture;
-		glPixelZoom(10.f, 10.f);
-		LLVector2 display_scale = gViewerWindow->getDisplayScale();
-		glRasterPos2f(((F32)mMousePt.mX * display_scale.mV[VX] + 10.f), 
-			((F32)mMousePt.mY * display_scale.mV[VY] + 10.f));
-		glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
-		glPixelZoom(1.f, 1.f);
-		gGL.color4fv(LLColor4::white.mV);
-		gl_rect_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)), 
-			llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
-			llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
-			llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
-			FALSE);
-		gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] - (F32)(PICK_HALF_WIDTH)), 
-			llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
-			llround((F32)mMousePt.mX * display_scale.mV[VX] + 10.f), 
-			llround((F32)mMousePt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f));
-		gl_line_2d(llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
-			llround((F32)mMousePt.mY * display_scale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
-			llround((F32)mMousePt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f), 
-			llround((F32)mMousePt.mY * display_scale.mV[VY] + 10.f));
-		gGL.translatef(10.f, 10.f, 0.f);
-		gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]), 
-			llround((F32)mPickPt.mY * display_scale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f),
-			llround((F32)mPickPt.mX * display_scale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f),
-			llround((F32)mPickPt.mY * display_scale.mV[VY]),
-			FALSE);
-		gl_rect_2d(llround((F32)mPickPt.mX * display_scale.mV[VX]), 
-			llround((F32)mPickPt.mY * display_scale.mV[VY] + 10.f),
-			llround((F32)mPickPt.mX * display_scale.mV[VX] + 10.f),
-			llround((F32)mPickPt.mY * display_scale.mV[VY]),
-			FALSE);
-		gGL.popMatrix();
-	}
-}
-
-void LLPickInfo::getSurfaceInfo()
-{
-	// set values to uninitialized - this is what we return if no intersection is found
-	mObjectFace   = -1;
-	mUVCoords     = LLVector2(-1, -1);
-	mSTCoords     = LLVector2(-1, -1);
-	mXYCoords	  = LLCoordScreen(-1, -1);
-	mIntersection = LLVector3(0,0,0);
-	mNormal       = LLVector3(0,0,0);
-	mBinormal     = LLVector3(0,0,0);
-	
-	LLViewerObject* objectp = getObject();
-
-	if (objectp)
-	{
-		if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f,
-										   objectp, -1,
-										   &mObjectFace,
-										   &mIntersection,
-										   &mSTCoords,
-										   &mNormal,
-										   &mBinormal))
-		{
-			// if we succeeded with the intersect above, compute the texture coordinates:
-
-			if (objectp->mDrawable.notNull())
-			{
-				LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
-
-				mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal);
-			}
-
-			// and XY coords:
-			updateXYCoords();
-			
-		}
-	}
-}
-
-
-/* code to get UV via a special UV render - removed in lieu of raycast method
-LLVector2 LLPickInfo::pickUV()
-{
-	LLVector2 result(-1.f, -1.f);
-
-	LLViewerObject* objectp = getObject();
-	if (!objectp)
-	{
-		return result;
-	}
-
-	if (mObjectFace > -1 &&
-		objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
-		mObjectFace < objectp->mDrawable->getNumFaces())
-	{
-		S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]);
-		S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]);
-		const S32 UV_PICK_WIDTH = 5;
-		const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
-		U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
-		LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
-		if (facep)
-		{
-			LLGLState scissor_state(GL_SCISSOR_TEST);
-			scissor_state.enable();
-			LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
-			//glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
-			glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
-
-			glClear(GL_DEPTH_BUFFER_BIT);
-
-			facep->renderSelectedUV();
-
-			glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
-			U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
-
-			result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
-			result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
-		}
-	}
-
-	return result;
-} */
-
-
-//static 
-bool LLPickInfo::isFlora(LLViewerObject* object)
-{
-	if (!object) return false;
-
-	LLPCode pcode = object->getPCode();
-
-	if( (LL_PCODE_LEGACY_GRASS == pcode) 
-		|| (LL_PCODE_LEGACY_TREE == pcode) 
-		|| (LL_PCODE_TREE_NEW == pcode))
-	{
-		return true;
-	}
-	return false;
-}
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index c7d02cb720b0f25cc8a0bb95a08a67a8849bcf8d..5c0eae61be61c06c8ff6c07554379ed8ecb48bd2 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -60,70 +60,6 @@ class LLTextBox;
 class LLImageRaw;
 class LLHUDIcon;
 
-#define PICK_HALF_WIDTH 5
-#define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1)
-
-class LLPickInfo
-{
-public:
-	LLPickInfo();
-	LLPickInfo(const LLCoordGL& mouse_pos, 
-		const LLRect& screen_region,
-		MASK keyboard_mask, 
-		BOOL pick_transparent, 
-		BOOL pick_surface_info,
-		void (*pick_callback)(const LLPickInfo& pick_info));
-	~LLPickInfo();
-
-	void fetchResults();
-	LLPointer<LLViewerObject> getObject() const;
-	LLUUID getObjectID() const { return mObjectID; }
-	void drawPickBuffer() const;
-
-	static bool isFlora(LLViewerObject* object);
-
-	typedef enum e_pick_type
-	{
-		PICK_OBJECT,
-		PICK_FLORA,
-		PICK_LAND,
-		PICK_ICON,
-		PICK_PARCEL_WALL,
-		PICK_INVALID
-	} EPickType;
-
-public:
-	LLCoordGL		mMousePt;
-	MASK			mKeyMask;
-	void			(*mPickCallback)(const LLPickInfo& pick_info);
-
-	EPickType		mPickType;
-	LLCoordGL		mPickPt;
-	LLVector3d		mPosGlobal;
-	LLVector3		mObjectOffset;
-	LLUUID			mObjectID;
-	S32				mObjectFace;
-	LLHUDIcon*		mHUDIcon;
-	LLVector3       mIntersection;
-	LLVector2		mUVCoords;
-	LLVector2       mSTCoords;
-	LLCoordScreen	mXYCoords;
-	LLVector3		mNormal;
-	LLVector3		mBinormal;
-	BOOL			mPickTransparent;
-	LLRect			mScreenRegion;
-	void		    getSurfaceInfo();
-
-private:
-	void			updateXYCoords();
-
-	BOOL			mWantSurfaceInfo;   // do we populate mUVCoord, mNormal, mBinormal?
-	U8				mPickBuffer[PICK_DIAMETER * PICK_DIAMETER * 4];
-	F32				mPickDepthBuffer[PICK_DIAMETER * PICK_DIAMETER];
-	BOOL			mPickParcelWall;
-
-};
-
 #define MAX_IMAGE_SIZE 6144 //6 * 1024, max snapshot image size 6144 * 6144
 
 class LLViewerWindow : public LLWindowCallbacks
@@ -207,9 +143,6 @@ class LLViewerWindow : public LLWindowCallbacks
 	BOOL			getLeftMouseDown()	const	{ return mLeftMouseDown; }
 	BOOL			getRightMouseDown()	const	{ return mRightMouseDown; }
 
-	const LLPickInfo&	getLastPick() const { return mLastPick; }
-	const LLPickInfo&	getHoverPick() const { return mHoverPick; }
-
 	LLUICtrl*		getTopCtrl() const;
 	BOOL			hasTopCtrl(LLView* view) const;
 
@@ -217,10 +150,10 @@ class LLViewerWindow : public LLWindowCallbacks
 	void			setup3DRender();
 	void			setup2DRender();
 
+	BOOL			isPickPending()				{ return mPickPending; }
+
 	LLVector3		mouseDirectionGlobal(const S32 x, const S32 y) const;
 	LLVector3		mouseDirectionCamera(const S32 x, const S32 y) const;
-	LLVector3       mousePointHUD(const S32 x, const S32 y) const;
-		
 
 	// Is window of our application frontmost?
 	BOOL			getActive() const			{ return mActive; }
@@ -311,27 +244,20 @@ class LLViewerWindow : public LLWindowCallbacks
 	void			renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud );
 	void			performPick();
 
-	void			pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& pick_info),
-							  BOOL pick_transparent = FALSE, BOOL get_surface_info = FALSE);
-	LLPickInfo		pickImmediate(S32 x, S32 y, BOOL pick_transparent);
-	static void     hoverPickCallback(const LLPickInfo& pick_info);
-	
-	LLViewerObject* cursorIntersect(S32 mouse_x = -1, S32 mouse_y = -1, F32 depth = 512.f,
-									LLViewerObject *this_object = NULL,
-									S32 this_face = -1,
-									S32* face_hit = NULL,
-									LLVector3 *intersection = NULL,
-									LLVector2 *uv = NULL,
-									LLVector3 *normal = NULL,
-									LLVector3 *binormal = NULL);
+	void			hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent = FALSE, BOOL pick_parcel_walls = FALSE);
+	void			hitObjectOrLandGlobalImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent);
 	
+	void			hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask));
+	void			hitUIElementImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask));
+
+	LLViewerObject*	getObjectUnderCursor(const F32 depth = 16.0f);
 	
 	// Returns a pointer to the last object hit
-	//LLViewerObject	*getObject();
-	//LLViewerObject  *lastNonFloraObjectHit();
+	LLViewerObject	*lastObjectHit();
+	LLViewerObject  *lastNonFloraObjectHit();
 
-	//const LLVector3d& getObjectOffset();
-	//const LLVector3d& lastNonFloraObjectHitOffset();
+	const LLVector3d& lastObjectHitOffset();
+	const LLVector3d& lastNonFloraObjectHitOffset();
 
 	// mousePointOnLand() returns true if found point
 	BOOL			mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_pos_global);
@@ -380,7 +306,19 @@ class LLViewerWindow : public LLWindowCallbacks
 	void			stopGL(BOOL save_state = TRUE);
 	void			restoreGL(const std::string& progress_message = LLStringUtil::null);
 	void			initFonts(F32 zoom_factor = 1.f);
-	void			schedulePick(LLPickInfo& pick_info);
+	
+	void			analyzeHit(
+						S32				x,				// input
+						S32				y_from_bot,		// input
+						LLViewerObject* objectp,		// input
+						U32				te_offset,		// input
+						LLUUID*			hit_object_id_p,// output
+						S32*			hit_face_p,		// output
+						LLVector3d*		hit_pos_p,		// output
+						BOOL*			hit_land,		// output
+						F32*			hit_u_coord,	// output
+						F32*			hit_v_coord);	// output
+
 	
 public:
 	LLWindow*		mWindow;						// graphical window object
@@ -416,14 +354,16 @@ class LLViewerWindow : public LLWindowCallbacks
 	BOOL			mSuppressToolbox;	// sometimes hide the toolbox, despite
 										// having a camera tool selected
 	BOOL			mHideCursorPermanent;	// true during drags, mouselook
-	LLPickInfo		mLastPick;
-	LLPickInfo		mHoverPick;
-	std::vector<LLPickInfo> mPicks;
-	LLRect			mPickScreenRegion; // area of frame buffer for rendering pick frames (generally follows mouse to avoid going offscreen)
+	LLCoordGL		mPickPoint;
+	LLCoordGL		mPickOffset;
+	MASK			mPickMask;
+	BOOL			mPickPending;
+	void			(*mPickCallback)(S32 x, S32 y, MASK mask);
 
 	std::string		mOverlayTitle;		// Used for special titles such as "Second Life - Special E3 2003 Beta"
 
 	BOOL			mIgnoreActivate;
+	U8*				mPickBuffer;
 
 	std::string		mInitAlert;			// Window / GL initialization requires an alert
 	
@@ -458,7 +398,9 @@ void toggle_first_person();
 void toggle_build(void*);
 void reset_viewer_state_on_sim(void);
 void update_saved_window_size(const std::string& control,S32 delta_width, S32 delta_height);
-
+//
+// Constants
+//
 
 
 //
@@ -472,15 +414,28 @@ extern LLFrameTimer		gMouseIdleTimer;		// how long has it been since the mouse l
 extern LLFrameTimer		gAwayTimer;				// tracks time before setting the avatar away state to true
 extern LLFrameTimer		gAwayTriggerTimer;		// how long the avatar has been away
 
+extern LLVector3d		gLastHitPosGlobal;
+extern LLVector3d		gLastHitObjectOffset;
+extern LLUUID			gLastHitObjectID;
+extern S32				gLastHitObjectFace;
+extern BOOL				gLastHitLand;
+extern F32				gLastHitUCoord;
+extern F32				gLastHitVCoord;
+
+
+extern LLVector3d		gLastHitNonFloraPosGlobal;
+extern LLVector3d		gLastHitNonFloraObjectOffset;
+extern LLUUID			gLastHitNonFloraObjectID;
+extern S32				gLastHitNonFloraObjectFace;
+
+extern S32				gLastHitUIElement;
+extern LLHUDIcon*		gLastHitHUDIcon;
+extern BOOL				gLastHitParcelWall;
 extern BOOL				gDebugSelect;
+extern BOOL				gPickFaces;
+extern BOOL				gPickTransparent;
 
 extern BOOL				gDebugFastUIRender;
-extern LLViewerObject*  gDebugRaycastObject;
-extern LLVector3        gDebugRaycastIntersection;
-extern LLVector2        gDebugRaycastTexCoord;
-extern LLVector3        gDebugRaycastNormal;
-extern LLVector3        gDebugRaycastBinormal;
-
 extern S32 CHAT_BAR_HEIGHT; 
 
 extern BOOL			gDisplayCameraPos;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 47090d5c65cc4d39ca0672500c0a4406f91a9458..287f06375720a4b863cc99a564eb4c98c2327710 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -622,6 +622,8 @@ LLVOAvatar::LLVOAvatar(
 	LLViewerRegion* regionp)
 	:
 	LLViewerObject(id, pcode, regionp),
+	mHUDTargetZoom(1.f),
+	mHUDCurZoom(1.f),
 	mLastHeadBakedID( IMG_DEFAULT_AVATAR ),
 	mLastUpperBodyBakedID( IMG_DEFAULT_AVATAR ),
 	mLastLowerBodyBakedID( IMG_DEFAULT_AVATAR ),
@@ -3248,8 +3250,7 @@ void LLVOAvatar::idleUpdateTractorBeam()
 			}
 			else
 			{
-				const LLPickInfo& pick = gViewerWindow->getLastPick();
-				mBeam->setPositionGlobal(pick.mPosGlobal);
+				mBeam->setPositionGlobal(gLastHitNonFloraPosGlobal + gLastHitNonFloraObjectOffset);
 			}
 
 		}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index ff846c8d833ce490ad8f84e56c8e6790569dd5b8..54fd7d370f7751cc86dddb6aab0ced5590c10c0c 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -636,6 +636,8 @@ class LLVOAvatar :
 	// special purpose joint for HUD attachments
 	//--------------------------------------------------------------------
 	LLViewerJoint *mScreenp;
+	F32				mHUDTargetZoom;
+	F32				mHUDCurZoom;
 
 	//--------------------------------------------------------------------
 	// mesh objects for skinned avatar
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 1e1f8be859bbffc319c3980c74c07f156b0e1656..b84f8d8e4b4d57a4967de60efe554c4dc239a11f 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1893,42 +1893,26 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const
 
 LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const
 {
-	LLVector3 ret = dir * ~getRenderRotation();
-	
-	LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale();
-	ret.scaleVec(objScale);
-
-	return ret;
+	return dir * ~getRenderRotation();
 }
 
 LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const
 {
 	LLVector3 ret = dir;
-	LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale();
-	ret.scaleVec(objScale);
+	ret.scaleVec(getScale());
 	ret = ret * getRenderRotation();
 	ret += getRenderPosition();
 	
 	return ret;
 }
 
-LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const
+BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
 {
-	LLVector3 ret = dir;
-	LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale();
-	LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]);
-	ret.scaleVec(invObjScale);
-	ret = ret * getRenderRotation();
-
-	return ret;
-}
-
-
-BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, S32 *face_hitp,
-									  LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
+	return FALSE;
 	
-{
+#if 0 // needs to be rewritten to use face extents instead of volume bounds
 	LLVolume* volume = getVolume();
+	BOOL ret = FALSE;
 	if (volume)
 	{	
 		LLVector3 v_start, v_end, v_dir;
@@ -1936,38 +1920,17 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 		v_start = agentPositionToVolume(start);
 		v_end = agentPositionToVolume(end);
 		
-		S32 face_hit = volume->lineSegmentIntersect(v_start, v_end, face,
-													intersection, tex_coord, normal, bi_normal);
-		if (face_hit >= 0)
+		if (LLLineSegmentAABB(v_start, v_end, volume->mBounds[0], volume->mBounds[1]))
 		{
-			if (face_hitp != NULL)
-			{
-				*face_hitp = face_hit;
-			}
-			
-			if (intersection != NULL)
-			{
-				*intersection = volumePositionToAgent(*intersection);  // must map back to agent space
-			}
-
-			if (normal != NULL)
-			{
-				*normal = volumeDirectionToAgent(*normal);
-				(*normal).normVec();
-			}
-
-			if (bi_normal != NULL)
+			if (volume->lineSegmentIntersect(v_start, v_end) >= 0)
 			{
-				*bi_normal = volumeDirectionToAgent(*bi_normal);
-				(*bi_normal).normVec();
+				end = volumePositionToAgent(v_end);
+				ret = TRUE;
 			}
-
-			
-			return TRUE;
 		}
 	}
-	
-	return FALSE;
+	return ret;
+#endif
 }
 
 U32 LLVOVolume::getPartitionType() const
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 262d4ecc8d6a0a55722eb0a2ccdbada39935be18..d7b72f7a18a79eb04503ff2e6d31ae171f2bdb6e 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -111,20 +111,10 @@ class LLVOVolume : public LLViewerObject
 	const LLMatrix3&	getRelativeXformInvTrans() const		{ return mRelativeXformInvTrans; }
 	/*virtual*/	const LLMatrix4	getRenderMatrix() const;
 
-
-	/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, 
-										  S32 face = -1,                        // which face to check, -1 = ALL_SIDES
-										  S32* face_hit = NULL,                 // which face was hit
-										  LLVector3* intersection = NULL,       // return the intersection point
-										  LLVector2* tex_coord = NULL,          // return the texture coordinates of the intersection point
-										  LLVector3* normal = NULL,             // return the surface normal at the intersection point
-										  LLVector3* bi_normal = NULL           // return the surface bi-normal at the intersection point
-		);
-	
+	/*virtual*/ BOOL	lineSegmentIntersect(const LLVector3& start, LLVector3& end) const;
 				LLVector3 agentPositionToVolume(const LLVector3& pos) const;
 				LLVector3 agentDirectionToVolume(const LLVector3& dir) const;
 				LLVector3 volumePositionToAgent(const LLVector3& dir) const;
-				LLVector3 volumeDirectionToAgent(const LLVector3& dir) const;
 
 				
 				BOOL	getVolumeChanged() const				{ return mVolumeChanged; }
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index c24d1b882a715ab535fd0653ca741885ce9fd85f..f9a18bf1925e1901abd0b54ced845cea7e3a5c6c 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -2188,7 +2188,6 @@ void LLPipeline::renderHighlights()
 
 	// Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
 	// Render highlighted faces.
-	LLGLSPipelineAlpha gls_pipeline_alpha;
 	LLColor4 color(1.f, 1.f, 1.f, 0.5f);
 	LLGLEnable color_mat(GL_COLOR_MATERIAL);
 	disableLights();
@@ -2342,7 +2341,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
 
 	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
 	{
-		gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect());
+		gObjectList.renderObjectsForSelect(camera);
 	}
 	else if (gSavedSettings.getBOOL("RenderDeferred"))
 	{
@@ -2592,7 +2591,7 @@ void LLPipeline::renderDebug()
 	gGL.flush();
 }
 
-void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect)
+void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects)
 {
 	assertInitialized();
 
@@ -2645,7 +2644,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
 	}	
 
 	LLGLEnable alpha_test(GL_ALPHA_TEST);
-	if (render_transparent)
+	if (gPickTransparent)
 	{
 		gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f);
 	}
@@ -2690,7 +2689,14 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
 		glh::matrix4f save_proj(glh_get_current_projection());
 		glh::matrix4f save_model(glh_get_current_modelview());
 
-		setup_hud_matrices(screen_rect);
+		U32 viewport[4];
+
+		for (U32 i = 0; i < 4; i++)
+		{
+			viewport[i] = gGLViewport[i];
+		}
+		
+		setup_hud_matrices(TRUE);
 		for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); 
 			 iter != avatarp->mAttachmentPoints.end(); )
 		{
@@ -2742,6 +2748,11 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
 		glh_set_current_modelview(save_model);
 
 	
+		for (U32 i = 0; i < 4; i++)
+		{
+			gGLViewport[i] = viewport[i];
+		}
+		glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
 	}
 
 	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
@@ -2751,6 +2762,11 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
 	gGL.setColorMask(true, true);
 }
 
+void LLPipeline::renderFaceForUVSelect(LLFace* facep)
+{
+	if (facep) facep->renderSelectedUV();
+}
+
 void LLPipeline::rebuildPools()
 {
 	LLMemType mt(LLMemType::MTYPE_PIPELINE);
@@ -3943,13 +3959,7 @@ BOOL LLPipeline::getProcessBeacons(void* data)
 	return sRenderProcessBeacons;
 }
 
-LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
-														S32* face_hit,
-														LLVector3* intersection,         // return the intersection point
-														LLVector2* tex_coord,            // return the texture coordinates of the intersection point
-														LLVector3* normal,               // return the surface normal at the intersection point
-														LLVector3* bi_normal             // return the surface bi-normal at the intersection point
-	)
+LLViewerObject* LLPipeline::pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision)
 {
 	LLDrawable* drawable = NULL;
 
@@ -3957,45 +3967,10 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start,
 			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
 	{
 		LLViewerRegion* region = *iter;
-
-		for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
-		{
-			if ((j == LLViewerRegion::PARTITION_VOLUME) || (j == LLViewerRegion::PARTITION_BRIDGE))  // only check these partitions for now
-			{
-				LLSpatialPartition* part = region->getSpatialPartition(j);
-				if (part)
-				{
-					LLDrawable* hit = part->lineSegmentIntersect(start, end, face_hit, intersection, tex_coord, normal, bi_normal);
-					if (hit)
-					{
-						drawable = hit;
-					}
-				}
-			}
-		}
-	}
-	return drawable ? drawable->getVObj().get() : NULL;
-}
-
-LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end,
-													  S32* face_hit,
-													  LLVector3* intersection,         // return the intersection point
-													  LLVector2* tex_coord,            // return the texture coordinates of the intersection point
-													  LLVector3* normal,               // return the surface normal at the intersection point
-													  LLVector3* bi_normal             // return the surface bi-normal at the intersection point
-	)
-{
-	LLDrawable* drawable = NULL;
-
-	for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
+		LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_VOLUME);
 		if (part)
 		{
-			LLDrawable* hit = part->lineSegmentIntersect(start, end, face_hit, intersection, tex_coord, normal, bi_normal);
+			LLDrawable* hit = part->pickDrawable(start, end, collision);
 			if (hit)
 			{
 				drawable = hit;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index ac2c32fedd3f676e6da002d2dc5ea3e8326a7282..e98be79120d4c6d185a901b55ce6f05eb804135e 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -65,8 +65,8 @@ typedef enum e_avatar_skinning_method
 
 BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn't be defined here!
 bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon = 0);
-BOOL setup_hud_matrices(); // use whole screen to render hud
-BOOL setup_hud_matrices(const LLRect& screen_region); // specify portion of screen (in pixels) to render hud attachments from (for picking)
+BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
+BOOL setup_hud_matrices(BOOL for_select);
 glh::matrix4f glh_copy_matrix(GLdouble* src);
 glh::matrix4f glh_get_current_modelview();
 void glh_set_current_modelview(const glh::matrix4f& mat);
@@ -129,21 +129,8 @@ class LLPipeline
 	void        markTextured(LLDrawable *drawablep);
 	void        markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE);
 		
-	//get the object between start and end that's closest to start.
-	LLViewerObject* lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
-												S32* face_hit,                          // return the face hit
-												LLVector3* intersection = NULL,         // return the intersection point
-												LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point
-												LLVector3* normal = NULL,               // return the surface normal at the intersection point
-												LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point  
-		);
-	LLViewerObject* lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end,
-											  S32* face_hit,                          // return the face hit
-											  LLVector3* intersection = NULL,         // return the intersection point
-											  LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point
-											  LLVector3* normal = NULL,               // return the surface normal at the intersection point
-											  LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point
-		);
+	//get the object between start and end that's closest to start.  Return the point of collision in collision.
+	LLViewerObject* pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision);
 
 	// Something about these textures has changed.  Dirty them.
 	void        dirtyPoolObjectTextures(const std::set<LLViewerImage*>& textures);
@@ -198,7 +185,8 @@ class LLPipeline
 	void renderHighlights();
 	void renderDebug();
 
-	void renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect);
+	void renderForSelect(std::set<LLViewerObject*>& objects);
+	void renderFaceForUVSelect(LLFace* facep);
 	void rebuildPools(); // Rebuild pools
 
 	void findReferences(LLDrawable *drawablep);	// Find the lists which have references to this object
@@ -341,8 +329,7 @@ class LLPipeline
 		RENDER_DEBUG_TEXTURE_ANIM		= 0x080000,
 		RENDER_DEBUG_LIGHTS				= 0x100000,
 		RENDER_DEBUG_BATCH_SIZE			= 0x200000,
-		RENDER_DEBUG_RAYCAST            = 0x400000,
-		RENDER_DEBUG_SHAME				= 0x800000
+		RENDER_DEBUG_SHAME				= 0x400000,
 	};
 
 public:
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 6f49ef25b5ea9199d8304639f1306180d504d8b1..776128323954dd7f4583ac0bc8714cb2243820af 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -2436,15 +2436,6 @@ version 2.0
 		{	LocalID				U32  }
 		{	GrabOffset			LLVector3 }
 	}
-	{
-		SurfaceInfo     Variable
-		{   UVCoord     LLVector3 }
-		{   STCoord     LLVector3 }
-       	{   FaceIndex   S32 }
-       	{   Position    LLVector3 }
-       	{   Normal      LLVector3 }
-       	{   Binormal    LLVector3 }
-	}
 }
 
 
@@ -2466,16 +2457,6 @@ version 2.0
 		{	GrabPosition		LLVector3	}	// LLVector3, region local
 		{	TimeSinceLast		U32	}
 	}
-	{
-		SurfaceInfo     Variable
-		{   UVCoord     LLVector3 }
-		{   STCoord     LLVector3 }
-       	{   FaceIndex   S32 }
-       	{   Position    LLVector3 }
-       	{   Normal      LLVector3 }
-       	{   Binormal    LLVector3 }
-	}
-
 }
 
 
@@ -2491,15 +2472,6 @@ version 2.0
 		ObjectData			Single
 		{	LocalID				U32  }
 	}
-	{
-		SurfaceInfo     Variable
-		{   UVCoord     LLVector3 }
-		{   STCoord     LLVector3 }
-       	{   FaceIndex   S32 }
-       	{   Position    LLVector3 }
-       	{   Normal      LLVector3 }
-       	{   Binormal    LLVector3 }
-	}
 }