diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index fd2c408fd4a0cf3d5fc01c7c1890e88248c54bd1..0a21c3a2a720c16f46274632dad0031a4b83c9c0 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -10,6 +10,11 @@
 
 #include "llmemory.h"
 
+// not defining nullfunc will currently crash when trying to use a LLHandle
+template< typename _Ty >
+  const typename LLHandle< _Ty >::NullFunc
+    LLHandle< _Ty >::sNullFunc = LLHandle< _Ty >::defaultNullFunc;
+
 //----------------------------------------------------------------------------
 
 //static
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 905d05254ae2906c323918ec303ae23bb0298748..962a4aa5d505941e526262ac0b6feb4ffc78f88d 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -120,6 +120,7 @@ class LLRefCount
 		}
 		return mRef;
 	}	
+
 	S32 getNumRefs() const
 	{
 		return mRef;
@@ -249,6 +250,154 @@ template <class Type> class LLPointer
 	Type*	mPointer;
 };
 
+//template <class Type> 
+//class LLPointerTraits
+//{
+//	static Type* null();
+//};
+//
+// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
+// This is useful in instances where operations on NULL pointers are semantically safe and/or
+// when error checking occurs at a different granularity or in a different part of the code
+// than when referencing an object via a LLHandle.
+// 
+
+template <class Type> 
+class LLHandle
+{
+public:
+	LLHandle() :
+		mPointer(sNullFunc())
+	{
+		ref();
+	}
+
+	LLHandle(Type* ptr) : 
+		mPointer(nonNull(ptr))
+	{
+		ref();
+	}
+
+	LLHandle(const LLHandle<Type>& ptr) : 
+		mPointer(ptr.mPointer)
+	{
+		ref();
+	}
+
+	// support conversion up the type hierarchy.  See Item 45 in Effective C++, 3rd Ed.
+	template<typename Subclass>
+	LLHandle(const LLPointer<Subclass>& ptr) : 
+		mPointer(ptr.get())
+	{
+		ref();
+	}
+
+	~LLHandle()								
+	{
+		unref();
+	}
+
+	Type*	get() const							{ return mPointer; }
+	const Type*	operator->() const				{ return mPointer; }
+	Type*	operator->()						{ return mPointer; }
+	const Type&	operator*() const				{ return *mPointer; }
+	Type&	operator*()							{ return *mPointer; }
+
+	operator BOOL()  const						{ return (mPointer != sNullFunc()); }
+	operator bool()  const						{ return (mPointer != sNullFunc()); }
+	bool operator!() const						{ return (mPointer == sNullFunc()); }
+	bool isNull() const							{ return (mPointer == sNullFunc()); }
+	bool notNull() const						{ return (mPointer != sNullFunc()); }
+
+
+	operator Type*()       const				{ return mPointer; }
+	operator const Type*() const				{ return mPointer; }
+	bool operator !=(Type* ptr) const           { return (mPointer != nonNull(ptr)); 	}
+	bool operator ==(Type* ptr) const           { return (mPointer == nonNull(ptr)); 	}
+	bool operator ==(const LLHandle<Type>& ptr) const           { return (mPointer == ptr.mPointer); 	}
+	bool operator < (const LLHandle<Type>& ptr) const           { return (mPointer < ptr.mPointer); 	}
+	bool operator > (const LLHandle<Type>& ptr) const           { return (mPointer > ptr.mPointer); 	}
+
+	LLHandle<Type>& operator =(Type* ptr)                   
+	{ 
+		if( mPointer != ptr )
+		{
+			unref(); 
+			mPointer = nonNull(ptr); 
+			ref();
+		}
+
+		return *this; 
+	}
+
+	LLHandle<Type>& operator =(const LLHandle<Type>& ptr)  
+	{ 
+		if( mPointer != ptr.mPointer )
+		{
+			unref(); 
+			mPointer = ptr.mPointer;
+			ref();
+		}
+		return *this; 
+	}
+
+	// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
+	template<typename Subclass>
+	LLHandle<Type>& operator =(const LLHandle<Subclass>& ptr)  
+	{ 
+		if( mPointer != ptr.get() )
+		{
+			unref(); 
+			mPointer = ptr.get();
+			ref();
+		}
+		return *this; 
+	}
+
+public:
+	typedef Type* (*NullFunc)();
+	static const NullFunc sNullFunc;
+
+protected:
+	void ref()                             
+	{ 
+		if (mPointer)
+		{
+			mPointer->ref();
+		}
+	}
+
+	void unref()
+	{
+		if (mPointer)
+		{
+			Type *tempp = mPointer;
+			mPointer = sNullFunc();
+			tempp->unref();
+			if (mPointer != sNullFunc())
+			{
+				llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
+				unref();
+			}
+		}
+	}
+
+	static Type* nonNull(Type* ptr)
+	{
+		return ptr == NULL ? sNullFunc() : ptr;
+	}
+
+	static Type* defaultNullFunc()
+	{
+		llerrs << "No null value provided for LLHandle" << llendl;
+		return NULL;
+	}
+
+protected:
+
+	Type*	mPointer;
+};
+
 // LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL
 // NOT a smart pointer like LLPointer<>
 // Useful for example in std::map<int,LLInitializedPointer<LLFoo> >
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 5d4711ef1080c25b8656f40bbb1dad2750adaac0..22d898c5cef99325ab2c76018e47cf4871cfe0d8 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -527,6 +527,8 @@ void LLFloater::open()	/* Flawfinder: ignore */
 			make_ui_sound("UISndWindowOpen");
 		}
 	}
+
+	onOpen();
 }
 
 void LLFloater::close(bool app_quitting)
@@ -1336,6 +1338,11 @@ void LLFloater::draw()
 	}
 }
 
+// virtual
+void LLFloater::onOpen()
+{
+}
+
 // virtual
 void LLFloater::onClose(bool app_quitting)
 {
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index c1ef54ed42ee65a092654009cf471103e2de261e..a743081335214d6af1469286ed233803eabbecf2 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -157,6 +157,9 @@ friend class LLFloaterView;
 
 	virtual void	draw();
 
+	// does nothing by default
+	virtual void	onOpen();
+
 	// Call destroy() to free memory, or setVisible(FALSE) to keep it
 	// If app_quitting, you might not want to save your visibility.
 	// Defaults to destroy().
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 6ec0719ad5e107d391243a7b7f721f6ba65e358a..7aaa306f05442ad738db47ed1ab66be2af4d80bc 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -385,11 +385,7 @@ void LLMenuItemGL::doIt( void )
 {
 	// close all open menus by default
 	// if parent menu is actually visible (and we are not triggering menu item via accelerator)
-	// HACK: do not call hidemenus() from a pie menu item, as most pie menu operations
-	// assume that the thing you clicked on stays selected (parcel and/or object) after the
-	// pie menu is gone --RN
-	if (getMenu()->getWidgetType() != WIDGET_TYPE_PIE_MENU 
-		&& !getMenu()->getTornOff() 
+	if (!getMenu()->getTornOff() 
 		&& getMenu()->getVisible())
 	{
 		LLMenuGL::sMenuContainer->hideMenus();
@@ -3283,7 +3279,7 @@ void LLPieMenuBranch::doIt( void )
 	S32 center_y;
 	parent->localPointToScreen(rect.getWidth() / 2, rect.getHeight() / 2, &center_x, &center_y);
 
-	parent->hide(TRUE);
+	parent->hide(FALSE);
 	mBranch->show(	center_x, center_y, FALSE );
 }
 
@@ -3473,6 +3469,11 @@ BOOL LLPieMenu::handleMouseDown( S32 x, S32 y, MASK mask )
 		// to make sure it's within the item's rectangle
 		handled = item->handleMouseDown( 0, 0, mask );
 	}
+	else if (!mRightMouseDown)
+	{
+		// call hidemenus to make sure transient selections get cleared
+		((LLMenuHolderGL*)getParent())->hideMenus();
+	}
 
 	// always handle mouse down as mouse up will close open menus
 	return handled;
@@ -3546,6 +3547,11 @@ BOOL LLPieMenu::handleMouseUp( S32 x, S32 y, MASK mask )
 			hide(TRUE);
 		}
 	}
+	else if (!mRightMouseDown)
+	{
+		// call hidemenus to make sure transient selections get cleared
+		((LLMenuHolderGL*)getParent())->hideMenus();
+	}
 
 	if (handled)
 	{
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index ca8f2e0f6a37d4049f3e6f9a1cca806e1fa6a082..9d2f4fac32876abe69639dff4a6115b82ba4b865 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -462,17 +462,16 @@ void LLAgent::resetView(BOOL reset_camera)
 
 	if (!gNoRender)
 	{
-		gSelectMgr->deselectAll();
 		gSelectMgr->unhighlightAll();
 
 		// By popular request, keep land selection while walking around. JC
 		// gParcelMgr->deselectLand();
 
+		//FIXME: force deselect when walking? - RN
+		//	gSelectMgr->deselectAll();
+
 		// Hide all popup menus
-		gPieSelf->hide(FALSE);
-		gPieAvatar->hide(FALSE);
-		gPieObject->hide(FALSE);
-		gPieLand->hide(FALSE);
+		gMenuHolder->hideMenus();
 	}
 
 	if (reset_camera && !gSavedSettings.getBOOL("FreezeTime"))
@@ -1565,7 +1564,8 @@ F32 LLAgent::getCameraZoomFraction()
 {
 	// 0.f -> camera zoomed all the way out
 	// 1.f -> camera zoomed all the way in
-	if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		// already [0,1]
 		return mAvatarObject->mHUDTargetZoom;
@@ -1612,7 +1612,9 @@ void LLAgent::setCameraZoomFraction(F32 fraction)
 {
 	// 0.f -> camera zoomed all the way out
 	// 1.f -> camera zoomed all the way in
-	if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+
+	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		mAvatarObject->mHUDTargetZoom = fraction;
 	}
@@ -1662,7 +1664,8 @@ void LLAgent::setCameraZoomFraction(F32 fraction)
 //-----------------------------------------------------------------------------
 void LLAgent::cameraOrbitAround(const F32 radians)
 {
-	if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		// do nothing for hud selection
 	}
@@ -1684,7 +1687,8 @@ void LLAgent::cameraOrbitAround(const F32 radians)
 //-----------------------------------------------------------------------------
 void LLAgent::cameraOrbitOver(const F32 angle)
 {
-	if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		// do nothing for hud selection
 	}
@@ -1718,7 +1722,8 @@ void LLAgent::cameraZoomIn(const F32 fraction)
 		return;
 	}
 
-	if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		// just update hud zoom level
 		mAvatarObject->mHUDTargetZoom /= fraction;
@@ -2237,11 +2242,9 @@ void LLAgent::stopAutoPilot(BOOL user_cancel)
 			resetAxes(mAutoPilotTargetFacing);
 		}
 		//NB: auto pilot can terminate for a reason other than reaching the destination
-		//TODO: enforce rotation constraint here as well
-		if (mAutoPilotFinishedCallback && 
-			((mAutoPilotTargetDist < mAutoPilotStopDistance) || (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped)))
+		if (mAutoPilotFinishedCallback)
 		{
-			mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotTargetDist, mAutoPilotCallbackData);
+			mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData);
 		}
 		mLeaderID = LLUUID::null;
 
@@ -2712,8 +2715,8 @@ U8 LLAgent::getRenderState()
 		stopTyping();
 	}
 	
-	if ((!gSelectMgr->isEmpty() && gSelectMgr->shouldShowSelection())
-		|| gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) )->isEditing() )
+	if ((!gSelectMgr->getSelection()->isEmpty() && gSelectMgr->shouldShowSelection())
+		|| gToolMgr->getCurrentTool()->isEditing() )
 	{
 		setRenderState(AGENT_STATE_EDITING);
 	}
@@ -2755,8 +2758,7 @@ void LLAgent::endAnimationUpdateUI()
 		gMenuBarView->setVisible(TRUE);
 		gStatusBar->setVisibleForMouselook(true);
 
-		gCurrentToolset = gBasicToolset;
-		gToolMgr->useSelectedTool( gCurrentToolset );
+		gToolMgr->setCurrentToolset(gBasicToolset);
 
 		// Only pop if we have pushed...
 		if (TRUE == mViewsPushed)
@@ -2804,8 +2806,7 @@ void LLAgent::endAnimationUpdateUI()
 	{
 		// make sure we ask to save changes
 
-		gCurrentToolset = gBasicToolset;
-		gToolMgr->useSelectedTool( gCurrentToolset );
+		gToolMgr->setCurrentToolset(gBasicToolset);
 
 		// HACK: If we're quitting, and we were in customize avatar, don't
 		// let the mini-map go visible again. JC
@@ -2842,8 +2843,7 @@ void LLAgent::endAnimationUpdateUI()
 		// JC - Added for always chat in third person option
 		gFocusMgr.setKeyboardFocus(NULL, NULL);
 
-		gCurrentToolset = gMouselookToolset;
-		gToolMgr->useSelectedTool( gMouselookToolset );
+		gToolMgr->setCurrentToolset(gMouselookToolset);
 
 		mViewsPushed = TRUE;
 
@@ -2901,8 +2901,7 @@ void LLAgent::endAnimationUpdateUI()
 	}
 	else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR)
 	{
-		gCurrentToolset = gFaceEditToolset;
-		gToolMgr->useSelectedTool( gFaceEditToolset );
+		gToolMgr->setCurrentToolset(gFaceEditToolset);
 
 		gFloaterMap->pushVisible(FALSE);
 		/*
@@ -3854,6 +3853,7 @@ void LLAgent::handleScrollWheel(S32 clicks)
 	}
 	else
 	{
+		LLObjectSelectionHandle selection = gSelectMgr->getSelection();
 		const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2);
 
 		// Block if camera is animating
@@ -3862,7 +3862,7 @@ void LLAgent::handleScrollWheel(S32 clicks)
 			return;
 		}
 
-		if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			F32 zoom_factor = (F32)pow(0.8, -clicks);
 			cameraZoomIn(zoom_factor);
@@ -3933,9 +3933,7 @@ void LLAgent::changeCameraToMouselook(BOOL animate)
 	// unpause avatar animation
 	mPauseRequest = NULL;
 
-	gCurrentToolset = gMouselookToolset;
-	gCurrentToolset->selectFirstTool();
-	gToolMgr->useSelectedTool( gCurrentToolset );
+	gToolMgr->setCurrentToolset(gMouselookToolset);
 
 	gSavedSettings.setBOOL("FirstPersonBtnState",	FALSE);
 	gSavedSettings.setBOOL("MouselookBtnState",		TRUE);
@@ -4017,9 +4015,7 @@ void LLAgent::changeCameraToFollow(BOOL animate)
 		
 		if (gBasicToolset)
 		{
-			gCurrentToolset = gBasicToolset;
-			gCurrentToolset->selectFirstTool();
-			gToolMgr->useSelectedTool( gCurrentToolset );
+			gToolMgr->setCurrentToolset(gBasicToolset);
 		}
 
 		if (mAvatarObject)
@@ -4092,9 +4088,7 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate)
 	{
 		if (gBasicToolset)
 		{
-			gCurrentToolset = gBasicToolset;
-			gCurrentToolset->selectFirstTool();
-			gToolMgr->useSelectedTool( gCurrentToolset );
+			gToolMgr->setCurrentToolset(gBasicToolset);
 		}
 
 		mCameraLag.clearVec();
@@ -4157,9 +4151,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL animate)
 
 	if (gFaceEditToolset)
 	{
-		gCurrentToolset = gFaceEditToolset;
-		gCurrentToolset->selectFirstTool();
-		gToolMgr->useSelectedTool( gCurrentToolset );
+		gToolMgr->setCurrentToolset(gFaceEditToolset);
 	}
 
 	gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index 0a10fa3db3023b70164ecdcd8ad3f44c00138564..12891bd7b22fecc0695871b358d0129c4e0558dc 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -88,21 +88,22 @@ void LLFloaterAuction::show()
 
 void LLFloaterAuction::initialize()
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	mParcelp = gParcelMgr->getParcelSelection();
 	LLViewerRegion* region = gParcelMgr->getSelectionRegion();
-	if(parcel && region && !parcel->getForSale())
+	LLParcel* parcelp = mParcelp->getParcel();
+	if(parcelp && region && !parcelp->getForSale())
 	{
 		mParcelHost = region->getHost();
-		mParcelID = parcel->getLocalID();
+		mParcelID = parcelp->getLocalID();
 
-		childSetText("parcel_text", parcel->getName());
+		childSetText("parcel_text", parcelp->getName());
 		childEnable("snapshot_btn");
 		childEnable("ok_btn");
 	}
 	else
 	{
 		mParcelHost.invalidate();
-		if(parcel && parcel->getForSale())
+		if(parcelp && parcelp->getForSale())
 		{
 			childSetText("parcel_text", childGetText("already for sale"));
 		}
diff --git a/indra/newview/llfloaterauction.h b/indra/newview/llfloaterauction.h
index fe5ce8f9d91540250edfbfba55f2ad7ae2969a69..157222b501db72b6d4f552a09bff4575812feaa1 100644
--- a/indra/newview/llfloaterauction.h
+++ b/indra/newview/llfloaterauction.h
@@ -20,6 +20,7 @@
 //
 // Class which holds the functionality to start auctions.
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLParcelSelection;
 
 class LLFloaterAuction : public LLFloater
 {
@@ -45,6 +46,7 @@ class LLFloaterAuction : public LLFloater
 	LLTransactionID mTransactionID;
 	LLAssetID mImageID;
 	LLPointer<LLImageGL> mImage;
+	LLHandle<LLParcelSelection> mParcelp;
 	S32 mParcelID;
 	LLHost mParcelHost;
 };
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index c4d0d6e2088917754d9d2ffc358ec8f9a9edbe51..eb5a3de1de123c528ba1bd0fa5330e94bffd9405 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -44,8 +44,6 @@ LLFloaterBuy::LLFloaterBuy()
 
 LLFloaterBuy::~LLFloaterBuy()
 {
-	gSelectMgr->deselectAll();
-
 	sInstance = NULL;
 }
 
@@ -61,7 +59,9 @@ void LLFloaterBuy::reset()
 // static
 void LLFloaterBuy::show(const LLSaleInfo& sale_info)
 {
-	if (gSelectMgr->getRootObjectCount() != 1)
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+
+	if (selection->getRootObjectCount() != 1)
 	{
 		gViewerWindow->alertXml("BuyOneObjectOnly");
 		return;
@@ -81,6 +81,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
 	sInstance->open(); /*Flawfinder: ignore*/
 	sInstance->setFocus(TRUE);
 	sInstance->mSaleInfo = sale_info;
+	sInstance->mObjectSelection = gSelectMgr->getEditSelection();
 
 	// Always center the dialog.  User can change the size,
 	// but purchases are important and should be center screen.
@@ -88,7 +89,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
 	// mid-session and the saved rect is off-center.
 	sInstance->center();
 
-	LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	LLSelectNode* node = selection->getFirstRootNode();
 	if (!node) return;
 
 	// Set title based on sale type
@@ -162,7 +163,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
 	// Must do this after the floater is created, because
 	// sometimes the inventory is already there and 
 	// the callback is called immediately.
-	LLViewerObject* obj = gSelectMgr->getFirstRootObject();
+	LLViewerObject* obj = selection->getFirstRootObject();
 	sInstance->registerVOInventoryListener(obj,NULL);
 	sInstance->requestVOInventory();
 }
diff --git a/indra/newview/llfloaterbuy.h b/indra/newview/llfloaterbuy.h
index e90a77b7c9736eb5fe2c7ec7b641be9ed798121d..fb61ccdfccb8a12b90aab268da3f09c050015aff 100644
--- a/indra/newview/llfloaterbuy.h
+++ b/indra/newview/llfloaterbuy.h
@@ -22,6 +22,7 @@
 
 class LLViewerObject;
 class LLSaleInfo;
+class LLObjectSelection;
 
 class LLFloaterBuy
 : public LLFloater, public LLVOInventoryListener
@@ -47,6 +48,7 @@ class LLFloaterBuy
 private:
 	static LLFloaterBuy* sInstance;
 
+	LLHandle<LLObjectSelection>	mObjectSelection;
 	LLSaleInfo mSaleInfo;
 };
 
diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp
index a09ebbfab407074a033c23d5a1fc3d0f95dadec9..155d4d6ff7eb318b34d15c778892642e5c067e43 100644
--- a/indra/newview/llfloaterbuycontents.cpp
+++ b/indra/newview/llfloaterbuycontents.cpp
@@ -49,8 +49,6 @@ LLFloaterBuyContents::LLFloaterBuyContents()
 
 LLFloaterBuyContents::~LLFloaterBuyContents()
 {
-	gSelectMgr->deselectAll();
-
 	sInstance = NULL;
 }
 
@@ -58,7 +56,9 @@ LLFloaterBuyContents::~LLFloaterBuyContents()
 // static
 void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
 {
-	if (gSelectMgr->getRootObjectCount() != 1)
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+
+	if (selection->getRootObjectCount() != 1)
 	{
 		gViewerWindow->alertXml("BuyContentsOneOnly");
 		return;
@@ -77,6 +77,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
 
 	sInstance->open(); /*Flawfinder: ignore*/
 	sInstance->setFocus(TRUE);
+	sInstance->mObjectSelection = gSelectMgr->getEditSelection();
 
 	// Always center the dialog.  User can change the size,
 	// but purchases are important and should be center screen.
@@ -96,7 +97,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
 	sInstance->mSaleInfo = sale_info;
 
 	// Update the display
-	LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	LLSelectNode* node = selection->getFirstRootNode();
 	if (!node) return;
 	if(node->mPermissions->isGroupOwned())
 	{
@@ -112,7 +113,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
 	// Must do this after the floater is created, because
 	// sometimes the inventory is already there and 
 	// the callback is called immediately.
-	LLViewerObject* obj = gSelectMgr->getFirstRootObject();
+	LLViewerObject* obj = selection->getFirstRootObject();
 	sInstance->registerVOInventoryListener(obj,NULL);
 	sInstance->requestVOInventory();
 }
diff --git a/indra/newview/llfloaterbuycontents.h b/indra/newview/llfloaterbuycontents.h
index 1f834da6681620e898ebb74f5fb5e866e27f2aa1..2d6855500eec6c6a19609e6575a5225c9ce74009 100644
--- a/indra/newview/llfloaterbuycontents.h
+++ b/indra/newview/llfloaterbuycontents.h
@@ -20,6 +20,7 @@
 #include "llinventory.h"
 
 class LLViewerObject;
+class LLObjectSelection;
 
 class LLFloaterBuyContents
 : public LLFloater, public LLVOInventoryListener
@@ -43,6 +44,7 @@ class LLFloaterBuyContents
 protected:
 	static LLFloaterBuyContents* sInstance;
 
+	LLHandle<LLObjectSelection> mObjectSelection;
 	LLSaleInfo mSaleInfo;
 };
 
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index c3b2ae70e784befaa58d219d3f8fd028e510f32b..e0af892878afb30dd6a4fba2636b224d43ab87f1 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -56,7 +56,7 @@ class LLFloaterBuyLandUI
 	virtual ~LLFloaterBuyLandUI();
 
 	LLViewerRegion*	mRegion;
-	LLParcel*		mParcel;
+	LLParcelSelectionHandle mParcel;
 	bool			mIsClaim;
 	bool			mIsForGroup;
 
@@ -127,7 +127,7 @@ class LLFloaterBuyLandUI
 	static LLFloaterBuyLandUI* soleInstance(bool createIfNeeded);
 
 	void setForGroup(bool is_for_group);
-	void setParcel(LLViewerRegion* region, LLParcel* parcel);
+	void setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
 		
 	void updateAgentInfo();
 	void updateParcelInfo();
@@ -186,7 +186,7 @@ static void cacheNameUpdateRefreshesBuyLand(const LLUUID&,
 
 // static
 void LLFloaterBuyLand::buyLand(
-	LLViewerRegion* region, LLParcel* parcel, bool is_for_group)
+	LLViewerRegion* region, LLParcelSelectionHandle parcel, bool is_for_group)
 {
 	if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
 	{
@@ -331,7 +331,7 @@ void LLFloaterBuyLandUI::SelectionObserver::changed()
 		else {
 			ui->setParcel(
 				gParcelMgr->getSelectionRegion(),
-				gParcelMgr->getSelectedParcel());
+				gParcelMgr->getParcelSelection());
 		}
 	}
 }
@@ -349,7 +349,8 @@ void LLFloaterBuyLandUI::updateAgentInfo()
 
 void LLFloaterBuyLandUI::updateParcelInfo()
 {
-	mParcelValid = mParcel && mRegion;
+	LLParcel* parcel = mParcel->getParcel();
+	mParcelValid = parcel && mRegion;
 	mParcelIsForSale = false;
 	mParcelIsFirstLand = false;
 	mParcelIsGroupLand = false;
@@ -372,42 +373,41 @@ void LLFloaterBuyLandUI::updateParcelInfo()
 		return;
 	}
 	
-	if (gParcelMgr->getMultipleOwners())
+	if (mParcel->getMultipleOwners())
 	{
 		mCannotBuyReason = childGetText("multiple_parcels_selected");
 		return;
 	}
 
+	const LLUUID& parcelOwner = parcel->getOwnerID();
 	
-	const LLUUID& parcelOwner = mParcel->getOwnerID();
-	
-	mIsClaim = mParcel->isPublic();
+	mIsClaim = parcel->isPublic();
 	if (!mIsClaim)
 	{
-		mParcelActualArea = mParcel->getArea();
-		mParcelIsForSale = mParcel->getForSale();
-		mParcelIsFirstLand = mParcel->getReservedForNewbie();
-		mParcelIsGroupLand = mParcel->getIsGroupOwned();
-		mParcelPrice = mParcelIsForSale ? mParcel->getSalePrice() : 0;
+		mParcelActualArea = parcel->getArea();
+		mParcelIsForSale = parcel->getForSale();
+		mParcelIsFirstLand = parcel->getReservedForNewbie();
+		mParcelIsGroupLand = parcel->getIsGroupOwned();
+		mParcelPrice = mParcelIsForSale ? parcel->getSalePrice() : 0;
 		
 		if (mParcelIsGroupLand)
 		{
-			LLUUID group_id = mParcel->getGroupID();
+			LLUUID group_id = parcel->getGroupID();
 			mParcelGroupContribution = gAgent.getGroupContribution(group_id);
 		}
 	}
 	else
 	{
-		mParcelActualArea = gParcelMgr->getClaimableArea();
+		mParcelActualArea = mParcel->getClaimableArea();
 		mParcelIsForSale = true;
-		mParcelPrice = mParcelActualArea * mParcel->getClaimPricePerMeter();
+		mParcelPrice = mParcelActualArea * parcel->getClaimPricePerMeter();
 	}
 
 	mParcelBillableArea =
 		llround(mRegion->getBillableFactor() * mParcelActualArea);
 
  	mParcelSupportedObjects = llround(
-		mParcel->getMaxPrimCapacity() * mParcel->getParcelPrimBonus()); 
+		parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()); 
  	// Can't have more than region max tasks, regardless of parcel 
  	// object bonus factor. 
  	LLViewerRegion* region = gParcelMgr->getSelectionRegion(); 
@@ -418,15 +418,16 @@ void LLFloaterBuyLandUI::updateParcelInfo()
 			mParcelSupportedObjects, max_tasks_per_region); 
  	} 
 
-	mParcelSoldWithObjects = mParcel->getSellWithObjects();
+	mParcelSoldWithObjects = parcel->getSellWithObjects();
+
 	
-	LLVector3 center = mParcel->getCenterpoint();
+	LLVector3 center = parcel->getCenterpoint();
 	mParcelLocation = llformat("%s %d,%d",
 				mRegion->getName().c_str(),
 				(int)center[VX], (int)center[VY]
 				);
 	
-	mParcelSnapshot = mParcel->getSnapshotID();
+	mParcelSnapshot = parcel->getSnapshotID();
 	
 	updateNames();
 	
@@ -445,7 +446,7 @@ void LLFloaterBuyLandUI::updateParcelInfo()
 
 	if (!mIsClaim)
 	{
-		const LLUUID& authorizedBuyer = mParcel->getAuthorizedBuyerID();
+		const LLUUID& authorizedBuyer = parcel->getAuthorizedBuyerID();
 		const LLUUID buyer = gAgent.getID();
 		const LLUUID newOwner = mIsForGroup ? gAgent.getGroupID() : buyer;
 
@@ -484,7 +485,7 @@ void LLFloaterBuyLandUI::updateParcelInfo()
 			return;
 		}
 
-		if (gParcelMgr->hasOthersSelected())
+		if (mParcel->hasOthersSelected())
 		{
 			// Policy: Must not have someone else's land selected
 			mCannotBuyReason = childGetText("not_owned_by_you");
@@ -503,7 +504,7 @@ void LLFloaterBuyLandUI::updateParcelInfo()
 	}
 	*/
 	
-	if (mParcel->getReservedForNewbie())
+	if (parcel->getReservedForNewbie())
 	{
 		if (mIsForGroup)
 		{
@@ -814,7 +815,9 @@ void LLFloaterBuyLandUI::sendBuyLand()
 
 void LLFloaterBuyLandUI::updateNames()
 {
-	if (!mParcelValid)
+	LLParcel* parcelp = mParcel->getParcel();
+
+	if (!parcelp)
 	{
 		mParcelSellerName = "";
 		return;
@@ -824,11 +827,11 @@ void LLFloaterBuyLandUI::updateNames()
 	{
 		mParcelSellerName = "Linden Lab";
 	}
-	else if (mParcel->getIsGroupOwned())
+	else if (parcelp->getIsGroupOwned())
 	{
 		char groupName[DB_LAST_NAME_BUF_SIZE];	/*Flawfinder: ignore*/
 		
-		gCacheName->getGroupName(mParcel->getGroupID(), &groupName[0]);
+		gCacheName->getGroupName(parcelp->getGroupID(), &groupName[0]);
 		mParcelSellerName = groupName;
 	}
 	else
@@ -836,7 +839,7 @@ void LLFloaterBuyLandUI::updateNames()
 		char firstName[DB_LAST_NAME_BUF_SIZE];		/*Flawfinder: ignore*/
 		char lastName[DB_LAST_NAME_BUF_SIZE];		/*Flawfinder: ignore*/
 		
-		gCacheName->getName(mParcel->getOwnerID(), firstName, lastName);
+		gCacheName->getName(parcelp->getOwnerID(), firstName, lastName);
 		mParcelSellerName = llformat("%s %s", firstName, lastName);
 	}
 }
@@ -933,7 +936,7 @@ BOOL LLFloaterBuyLandUI::postBuild()
 	return TRUE;
 }
 
-void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcel* parcel)
+void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
 {
 	if (mTransaction &&  mTransactionType == TransactionBuy)
 	{
diff --git a/indra/newview/llfloaterbuyland.h b/indra/newview/llfloaterbuyland.h
index 22049d97a9748206f89aa993a81100a4e20deee7..0a092bd01f9f8b42bef539f8210d89c662acc8b1 100644
--- a/indra/newview/llfloaterbuyland.h
+++ b/indra/newview/llfloaterbuyland.h
@@ -9,15 +9,15 @@
 #ifndef LL_LLFLOATERBUYLAND_H
 #define LL_LLFLOATERBUYLAND_H
 
-class LLParcel;
 class LLViewerRegion;
 class LLViewerTextEditor;
+class LLParcelSelection;
 
 class LLFloaterBuyLand
 {
 public:
 	static void buyLand(LLViewerRegion* region,
-						LLParcel* parcel,
+						LLHandle<LLParcelSelection> parcel,
 						bool is_for_group);
 	static void updateCovenantText(const std::string& string, const LLUUID& asset_id);
 	static void updateEstateName(const std::string& name);
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index 17a5cbec96c204cac79d1248ea0ed63aa325b9a8..144833a3f5bb0f738b8ad5d7296d25595b77368c 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -616,7 +616,7 @@ void LLFloaterColorPicker::draw()
 	}
 
 	mPipetteBtn->setEnabled(gToolMgr != NULL);
-	mPipetteBtn->setToggleState(gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette);
+	mPipetteBtn->setToggleState(gToolMgr && gToolMgr->getCurrentTool() == gToolPipette);
 	mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately);
 	mSelectBtn->setEnabled(mActive);
 
@@ -1253,7 +1253,7 @@ void LLFloaterColorPicker::setActive(BOOL active)
 
 void LLFloaterColorPicker::stopUsingPipette()
 {
-	if (gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette)
+	if (gToolMgr && gToolMgr->getCurrentTool() == gToolPipette)
 	{
 		gToolMgr->clearTransientTool();
 	}
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index 7096f5dbf6df8914874f49b51a24eb02258786aa..3b7a86847263cc1fffc8651f0dcd63b1fccc959b 100644
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -1237,8 +1237,8 @@ void LLPanelObjectTools::onClickSetBySelection(void* data)
 	LLPanelObjectTools* panelp = (LLPanelObjectTools*) data;
 	if (!panelp) return;
 
-	LLSelectNode* node = gSelectMgr->getFirstRootNode();
-	if (!node) node = gSelectMgr->getFirstNode();
+	LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
+	if (!node) node = gSelectMgr->getSelection()->getFirstNode();
 	if (!node) return;
 
 	LLString owner_name;
diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index f45d22ba014298168da31c17b76736e1745e80db..0b9d836a1a77a4006fb3f5815ea4a238793d3a2d 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -25,15 +25,12 @@ LLFloaterInspect::~LLFloaterInspect(void)
 {
 	if(!gFloaterTools->getVisible())
 	{
-		if(gToolMgr->getCurrentTool(MASK_NONE) == gToolInspect)
+		if(gToolMgr->getBaseTool() == gToolInspect)
 		{
 			select_tool(gToolNull);
 		}
-		gSelectMgr->deselectAll();
 		// Switch back to basic toolset
-		gCurrentToolset = gBasicToolset;
-		gBasicToolset->selectFirstTool();
-		gToolMgr->useSelectedTool( gBasicToolset );
+		gToolMgr->setCurrentToolset(gBasicToolset);
 	}
 	else
 	{
@@ -58,13 +55,16 @@ void LLFloaterInspect::show(void* ignored)
 		LLFloaterInspect* self = new LLFloaterInspect;
 		self->open();
 	}
+
+	sInstance->mObjectSelection = gSelectMgr->getSelection();
 	select_tool(gToolInspect);
+	sInstance->refresh();
 }
 
 void LLFloaterInspect::onClickCreatorProfile(void* ctrl)
 {
 	if(sInstance->mObjectList->getAllSelected().size() == 0) return;
-	LLSelectNode* obj = gSelectMgr->getFirstNode();
+	LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode();
 	LLUUID obj_id, creator_id;
 	obj_id = sInstance->mObjectList->getFirstSelected()->getUUID();
 	while(obj)
@@ -74,7 +74,7 @@ void LLFloaterInspect::onClickCreatorProfile(void* ctrl)
 			creator_id = obj->mPermissions->getCreator();
 			break;
 		}
-		obj = gSelectMgr->getNextNode();
+		obj = sInstance->mObjectSelection->getNextNode();
 	}
 	if(obj)
 	{
@@ -85,7 +85,7 @@ void LLFloaterInspect::onClickCreatorProfile(void* ctrl)
 void LLFloaterInspect::onClickOwnerProfile(void* ctrl)
 {
 	if(sInstance->mObjectList->getAllSelected().size() == 0) return;
-	LLSelectNode* obj = gSelectMgr->getFirstNode();
+	LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode();
 	LLUUID obj_id, owner_id;
 	obj_id = sInstance->mObjectList->getFirstSelected()->getUUID();
 	while(obj)
@@ -95,7 +95,7 @@ void LLFloaterInspect::onClickOwnerProfile(void* ctrl)
 			owner_id = obj->mPermissions->getOwner();
 			break;
 		}
-		obj = gSelectMgr->getNextNode();
+		obj = sInstance->mObjectSelection->getNextNode();
 	}
 	if(obj)
 	{
@@ -109,7 +109,6 @@ BOOL LLFloaterInspect::postBuild()
 	childSetAction("button owner",onClickOwnerProfile, this);
 	childSetAction("button creator",onClickCreatorProfile, this);
 	childSetCommitCallback("object_list", onSelectObject);
-	refresh();
 	return TRUE;
 }
 
@@ -143,7 +142,7 @@ void LLFloaterInspect::refresh()
 	if(selected_index > -1) selected_uuid = mObjectList->getFirstSelected()->getUUID();
 	mObjectList->operateOnAll(LLScrollListCtrl::OP_DELETE);
 	//List all transient objects, then all linked objects
-	LLSelectNode* obj = gSelectMgr->getFirstNode();
+	LLSelectNode* obj = mObjectSelection->getFirstNode();
 	LLSD row;
 	while(obj)
 	{
@@ -182,7 +181,7 @@ void LLFloaterInspect::refresh()
 		row["columns"][3]["type"] = "text";
 		row["columns"][3]["value"] = time;
 		mObjectList->addElement(row, ADD_TOP);
-		obj = gSelectMgr->getNextNode();
+		obj = mObjectSelection->getNextNode();
 	}
 	if(selected_index > -1 && mObjectList->getItemIndex(selected_uuid) == selected_index)
 	{
@@ -218,4 +217,4 @@ void LLFloaterInspect::draw()
 	}
 
 	LLFloater::draw();
-}
+}
\ No newline at end of file
diff --git a/indra/newview/llfloaterinspect.h b/indra/newview/llfloaterinspect.h
index d43988a797fdbba9dbbdd47e7425a58a59780051..6a3f49497826b5a4f23e9b6eeca331cf3ae0a140 100644
--- a/indra/newview/llfloaterinspect.h
+++ b/indra/newview/llfloaterinspect.h
@@ -14,6 +14,7 @@
 #include "llfloater.h"
 
 //class LLTool;
+class LLObjectSelection;
 class LLScrollListCtrl;
 class LLUICtrl;
 
@@ -42,6 +43,8 @@ class LLFloaterInspect : public LLFloater
 private:
 	// static data
 	static LLFloaterInspect* sInstance;
+
+	LLHandle<LLObjectSelection> mObjectSelection;
 };
 
-#endif //LL_LLFLOATERINSPECT_H
+#endif //LL_LLFLOATERINSPECT_H
\ No newline at end of file
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 3997051782a8f86785e740d914ce0d6f0ec638d7..d091b4c01fea2944e79f1baac33f6b3a014dd408 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -94,7 +94,7 @@ static const BOOL BUY_PERSONAL_LAND = FALSE;
 LLFloaterLand* LLFloaterLand::sInstance = NULL;
 LLParcelSelectionObserver* LLFloaterLand::sObserver = NULL;
 S32 LLFloaterLand::sLastTab = 0;
-BOOL LLFloaterLand::sRequestReplyOnUpdate = TRUE;
+
 LLViewHandle LLPanelLandGeneral::sBuyPassDialogHandle;
 
 // Local classes
@@ -174,13 +174,11 @@ void LLFloaterLand::show()
 
 	// If we've already got the parcel data, fill the
 	// floater with it.
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
-	if (parcel)
+	sInstance->mParcel = gParcelMgr->getFloatingParcelSelection();
+	if (sInstance->mParcel->getParcel())
 	{
 		sInstance->refresh();
 	}
-
-	sRequestReplyOnUpdate = TRUE;
 }
 
 //static
@@ -214,19 +212,6 @@ void LLFloaterLand::refreshAll()
 	}
 }
 
-
-// virtual
-BOOL LLFloaterLand::canClose()
-{
-	// canClose is checked as the first step of attempting to close
-	// the window, before focus is released from controls.  Since we're
-	// closing the window and deselecting the land, we
-	// don't want replies to the upstream messages that get sent
-	// (because the reply will cause the land to be selected again).
-	sRequestReplyOnUpdate = FALSE;
-	return TRUE;
-}
-
 // virtual
 void LLFloaterLand::onClose(bool app_quitting)
 {
@@ -234,10 +219,6 @@ void LLFloaterLand::onClose(bool app_quitting)
 	delete sObserver;
 	sObserver = NULL;
 
-	// Must do this after removing observer, otherwise
-	// infinite loops notifying and closing.
-	gParcelMgr->deselectLand();
-
 	// Might have been showing owned objects
 	gSelectMgr->unhighlightAll();
 
@@ -302,7 +283,7 @@ void LLFloaterLand::refresh()
 void* LLFloaterLand::createPanelLandGeneral(void* data)
 {
 	LLFloaterLand* self = (LLFloaterLand*)data;
-	self->mPanelGeneral = new LLPanelLandGeneral();
+	self->mPanelGeneral = new LLPanelLandGeneral(self->mParcel);
 	return self->mPanelGeneral;
 }
 
@@ -312,7 +293,7 @@ void* LLFloaterLand::createPanelLandGeneral(void* data)
 void* LLFloaterLand::createPanelLandCovenant(void* data)
 {
 	LLFloaterLand* self = (LLFloaterLand*)data;
-	self->mPanelCovenant = new LLPanelLandCovenant();
+	self->mPanelCovenant = new LLPanelLandCovenant(self->mParcel);
 	return self->mPanelCovenant;
 }
 
@@ -321,7 +302,7 @@ void* LLFloaterLand::createPanelLandCovenant(void* data)
 void* LLFloaterLand::createPanelLandObjects(void* data)
 {
 	LLFloaterLand* self = (LLFloaterLand*)data;
-	self->mPanelObjects = new LLPanelLandObjects();
+	self->mPanelObjects = new LLPanelLandObjects(self->mParcel);
 	return self->mPanelObjects;
 }
 
@@ -329,7 +310,7 @@ void* LLFloaterLand::createPanelLandObjects(void* data)
 void* LLFloaterLand::createPanelLandOptions(void* data)
 {
 	LLFloaterLand* self = (LLFloaterLand*)data;
-	self->mPanelOptions = new LLPanelLandOptions();
+	self->mPanelOptions = new LLPanelLandOptions(self->mParcel);
 	return self->mPanelOptions;
 }
 
@@ -337,7 +318,7 @@ void* LLFloaterLand::createPanelLandOptions(void* data)
 void* LLFloaterLand::createPanelLandMedia(void* data)
 {
 	LLFloaterLand* self = (LLFloaterLand*)data;
-	self->mPanelMedia = new LLPanelLandMedia();
+	self->mPanelMedia = new LLPanelLandMedia(self->mParcel);
 	return self->mPanelMedia;
 }
 
@@ -345,7 +326,7 @@ void* LLFloaterLand::createPanelLandMedia(void* data)
 void* LLFloaterLand::createPanelLandAccess(void* data)
 {
 	LLFloaterLand* self = (LLFloaterLand*)data;
-	self->mPanelAccess = new LLPanelLandAccess();
+	self->mPanelAccess = new LLPanelLandAccess(self->mParcel);
 	return self->mPanelAccess;
 }
 
@@ -353,7 +334,7 @@ void* LLFloaterLand::createPanelLandAccess(void* data)
 void* LLFloaterLand::createPanelLandBan(void* data)
 {
 	LLFloaterLand* self = (LLFloaterLand*)data;
-	self->mPanelBan = new LLPanelLandBan();
+	self->mPanelBan = new LLPanelLandBan(self->mParcel);
 	return self->mPanelBan;
 }
 
@@ -363,8 +344,9 @@ void* LLFloaterLand::createPanelLandBan(void* data)
 //---------------------------------------------------------------------------
 
 
-LLPanelLandGeneral::LLPanelLandGeneral()
+LLPanelLandGeneral::LLPanelLandGeneral(LLParcelSelectionHandle& parcel)
 :	LLPanel("land_general_panel"),
+	mParcel(parcel),
 	mUncheckedSell(FALSE)
 {
 }
@@ -452,9 +434,8 @@ BOOL LLPanelLandGeneral::postBuild()
 	mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND);
 	
 	
-	static BOOL deselect_when_done = FALSE;
 	mBtnBuyPass = LLUICtrlFactory::getButtonByName(this, "Buy Pass...");
-	mBtnBuyPass->setClickedCallback(onClickBuyPass, &deselect_when_done);
+	mBtnBuyPass->setClickedCallback(onClickBuyPass, this);
 
 	mBtnReleaseLand = LLUICtrlFactory::getButtonByName(this, "Abandon Land...");
 	mBtnReleaseLand->setClickedCallback(onClickRelease, NULL);
@@ -479,7 +460,7 @@ void LLPanelLandGeneral::refresh()
 {
 	mBtnStartAuction->setVisible(gAgent.isGodlike());
 
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = mParcel->getParcel();
 	bool region_owner = false;
 	LLViewerRegion* regionp = gParcelMgr->getSelectionRegion();
 	if(regionp && (regionp->getOwner() == gAgent.getID()))
@@ -761,7 +742,7 @@ void LLPanelLandGeneral::refresh()
 // public
 void LLPanelLandGeneral::refreshNames()
 {
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = mParcel->getParcel();
 	if (!parcel)
 	{
 		mTextOwner->setText("");
@@ -841,7 +822,8 @@ void LLPanelLandGeneral::onClickSetGroup(void* userdata)
 // static
 void LLPanelLandGeneral::onClickProfile(void* data)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+	LLParcel* parcel = panelp->mParcel->getParcel();
 	if (!parcel) return;
 
 	if (parcel->getIsGroupOwned())
@@ -866,7 +848,7 @@ void LLPanelLandGeneral::cbGroupID(LLUUID group_id, void* userdata)
 // public
 void LLPanelLandGeneral::setGroup(const LLUUID& group_id)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = mParcel->getParcel();
 	if (!parcel) return;
 
 	// Set parcel properties and send message
@@ -875,7 +857,7 @@ void LLPanelLandGeneral::setGroup(const LLUUID& group_id)
 	//mTextGroup->setText(group_name);
 
 	// Send update
-	gParcelMgr->sendParcelPropertiesUpdate(parcel, LLFloaterLand::sRequestReplyOnUpdate);
+	gParcelMgr->sendParcelPropertiesUpdate(parcel);
 
 	// Update UI
 	refresh();
@@ -888,16 +870,17 @@ void LLPanelLandGeneral::onClickBuyLand(void* data)
 	gParcelMgr->startBuyLand(*for_group);
 }
 
-BOOL LLPanelLandGeneral::enableDeedToGroup(void*)
+BOOL LLPanelLandGeneral::enableDeedToGroup(void* data)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+	LLParcel* parcel = panelp->mParcel->getParcel();
 	return (parcel != NULL) && (parcel->getParcelFlag(PF_ALLOW_DEED_TO_GROUP));
 }
 
 // static
 void LLPanelLandGeneral::onClickDeed(void*)
 {
-	//LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	//LLParcel* parcel = mParcel->getParcel();
 	//if (parcel)
 	//{
 	gParcelMgr->startDeedLandToGroup();
@@ -918,17 +901,20 @@ void LLPanelLandGeneral::onClickReclaim(void*)
 }
 
 // static
-BOOL LLPanelLandGeneral::enableBuyPass(void*)
+BOOL LLPanelLandGeneral::enableBuyPass(void* data)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+	LLParcel* parcel = panelp != NULL ? panelp->mParcel->getParcel() : gParcelMgr->getParcelSelection()->getParcel();
 	return (parcel != NULL) && (parcel->getParcelFlag(PF_USE_PASS_LIST) && !gParcelMgr->isCollisionBanned());
 }
 
 
 // static
-void LLPanelLandGeneral::onClickBuyPass(void* deselect_when_done)
+void LLPanelLandGeneral::onClickBuyPass(void* data)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+	LLParcel* parcel = panelp != NULL ? panelp->mParcel->getParcel() : gParcelMgr->getParcelSelection()->getParcel();
+
 	if (!parcel) return;
 
 	S32 pass_price = parcel->getPassPrice();
@@ -944,13 +930,14 @@ void LLPanelLandGeneral::onClickBuyPass(void* deselect_when_done)
 	args["[PARCEL_NAME]"] = parcel_name;
 	args["[TIME]"] = time;
 	
-	sBuyPassDialogHandle = gViewerWindow->alertXml("LandBuyPass", args, cbBuyPass, deselect_when_done)->getHandle();
+	sBuyPassDialogHandle = gViewerWindow->alertXml("LandBuyPass", args, cbBuyPass)->getHandle();
 }
 
 // static
-void LLPanelLandGeneral::onClickStartAuction(void*)
+void LLPanelLandGeneral::onClickStartAuction(void* data)
 {
-	LLParcel* parcelp = gParcelMgr->getSelectedParcel();
+	LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+	LLParcel* parcelp = panelp->mParcel->getParcel();
 	if(parcelp)
 	{
 		if(parcelp->getForSale())
@@ -967,18 +954,11 @@ void LLPanelLandGeneral::onClickStartAuction(void*)
 // static
 void LLPanelLandGeneral::cbBuyPass(S32 option, void* data)
 {
-	BOOL deselect_when_done = (BOOL)(intptr_t)data;
-
 	if (0 == option)
 	{
 		// User clicked OK
 		gParcelMgr->buyPass();
 	}
-
-	if (deselect_when_done)
-	{
-		gParcelMgr->deselectLand();
-	}
 }
 
 //static 
@@ -992,7 +972,7 @@ void LLPanelLandGeneral::onCommitAny(LLUICtrl *ctrl, void *userdata)
 {
 	LLPanelLandGeneral *panelp = (LLPanelLandGeneral *)userdata;
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = panelp->mParcel->getParcel();
 	if (!parcel)
 	{
 		return;
@@ -1015,7 +995,7 @@ void LLPanelLandGeneral::onCommitAny(LLUICtrl *ctrl, void *userdata)
 	parcel->setContributeWithDeed(contribute_with_deed);
 
 	// Send update to server
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 
 	// Might have changed properties, so let's redraw!
 	panelp->refresh();
@@ -1030,20 +1010,21 @@ void LLPanelLandGeneral::onClickSellLand(void* data)
 // static
 void LLPanelLandGeneral::onClickStopSellLand(void* data)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+	LLParcel* parcel = panelp->mParcel->getParcel();
 
 	parcel->setParcelFlag(PF_FOR_SALE, FALSE);
 	parcel->setSalePrice(0);
 	parcel->setAuthorizedBuyerID(LLUUID::null);
 
-	gParcelMgr->sendParcelPropertiesUpdate(parcel, LLFloaterLand::sRequestReplyOnUpdate);
+	gParcelMgr->sendParcelPropertiesUpdate(parcel);
 }
 
 //---------------------------------------------------------------------------
 // LLPanelLandObjects
 //---------------------------------------------------------------------------
-LLPanelLandObjects::LLPanelLandObjects()
-:	LLPanel("land_objects_panel")
+LLPanelLandObjects::LLPanelLandObjects(LLParcelSelectionHandle& parcel)
+:	LLPanel("land_objects_panel"), mParcel(parcel)
 {
 }
 
@@ -1211,7 +1192,7 @@ void LLPanelLandObjects::onDoubleClickOwner(void *userdata)
 // public
 void LLPanelLandObjects::refresh()
 {
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = mParcel->getParcel();
 
 	mBtnShowOwnerObjects->setEnabled(FALSE);
 	mBtnShowGroupObjects->setEnabled(FALSE);
@@ -1406,7 +1387,7 @@ void send_return_objects_message(S32 parcel_local_id, S32 return_type,
 void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata)
 {
 	LLPanelLandObjects	*lop = (LLPanelLandObjects *)userdata;
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = lop->mParcel->getParcel();
 	if (0 == option)
 	{
 		if (parcel)
@@ -1431,7 +1412,7 @@ void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata)
 	}
 
 	gSelectMgr->unhighlightAll();
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 	lop->refresh();
 }
 
@@ -1439,7 +1420,7 @@ void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata)
 void LLPanelLandObjects::callbackReturnGroupObjects(S32 option, void* userdata)
 {
 	LLPanelLandObjects	*lop = (LLPanelLandObjects *)userdata;
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = lop->mParcel->getParcel();
 	if (0 == option)
 	{
 		if (parcel)
@@ -1453,7 +1434,7 @@ void LLPanelLandObjects::callbackReturnGroupObjects(S32 option, void* userdata)
 		}
 	}
 	gSelectMgr->unhighlightAll();
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 	lop->refresh();
 }
 
@@ -1461,7 +1442,7 @@ void LLPanelLandObjects::callbackReturnGroupObjects(S32 option, void* userdata)
 void LLPanelLandObjects::callbackReturnOtherObjects(S32 option, void* userdata)
 {
 	LLPanelLandObjects	*lop = (LLPanelLandObjects *)userdata;
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = lop->mParcel->getParcel();
 	if (0 == option)
 	{
 		if (parcel)
@@ -1471,7 +1452,7 @@ void LLPanelLandObjects::callbackReturnOtherObjects(S32 option, void* userdata)
 		}
 	}
 	gSelectMgr->unhighlightAll();
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 	lop->refresh();
 }
 
@@ -1479,7 +1460,7 @@ void LLPanelLandObjects::callbackReturnOtherObjects(S32 option, void* userdata)
 void LLPanelLandObjects::callbackReturnOwnerList(S32 option, void* userdata)
 {
 	LLPanelLandObjects	*self = (LLPanelLandObjects *)userdata;
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = self->mParcel->getParcel();
 	if (0 == option)
 	{
 		if (parcel)
@@ -1506,7 +1487,7 @@ void LLPanelLandObjects::callbackReturnOwnerList(S32 option, void* userdata)
 		}
 	}
 	gSelectMgr->unhighlightAll();
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 	self->refresh();
 }
 
@@ -1524,7 +1505,7 @@ void LLPanelLandObjects::onClickReturnOwnerList(void* userdata)
 
 	gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time);
 
-	LLParcel* parcelp = gParcelMgr->getSelectedParcel();
+	LLParcel* parcelp = self->mParcel->getParcel();
 	if (!parcelp) return;
 
 	// Make sure we have something selected.
@@ -1558,7 +1539,7 @@ void LLPanelLandObjects::onClickRefresh(void* userdata)
 
 	LLMessageSystem *msg = gMessageSystem;
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = self->mParcel->getParcel();
 	if (!parcel) return;
 
 	LLViewerRegion* region = gParcelMgr->getSelectionRegion();
@@ -1711,7 +1692,7 @@ void LLPanelLandObjects::onCommitList(LLUICtrl* ctrl, void* data)
 		self->mBtnReturnOwnerList->setEnabled(TRUE);
 
 		// Highlight this user's objects
-		clickShowCore(RT_LIST, &(self->mSelectedOwners));
+		clickShowCore(self, RT_LIST, &(self->mSelectedOwners));
 	}
 }
 
@@ -1738,30 +1719,30 @@ void LLPanelLandObjects::onClickName(void* userdata)
 }
 
 // static
-void LLPanelLandObjects::clickShowCore(S32 return_type, uuid_list_t* list)
+void LLPanelLandObjects::clickShowCore(LLPanelLandObjects* self, S32 return_type, uuid_list_t* list)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = self->mParcel->getParcel();
 	if (!parcel) return;
 
 	send_parcel_select_objects(parcel->getLocalID(), return_type, list);
 }
 
 // static
-void LLPanelLandObjects::onClickShowOwnerObjects(void*)
+void LLPanelLandObjects::onClickShowOwnerObjects(void* userdata)
 {
-	clickShowCore(RT_OWNER);
+	clickShowCore((LLPanelLandObjects*)userdata, RT_OWNER);
 }
 
 // static
-void LLPanelLandObjects::onClickShowGroupObjects(void*)
+void LLPanelLandObjects::onClickShowGroupObjects(void* userdata)
 {
-	clickShowCore(RT_GROUP);
+	clickShowCore((LLPanelLandObjects*)userdata, (RT_GROUP));
 }
 
 // static
-void LLPanelLandObjects::onClickShowOtherObjects(void*)
+void LLPanelLandObjects::onClickShowOtherObjects(void* userdata)
 {
-	clickShowCore(RT_OTHER);
+	clickShowCore((LLPanelLandObjects*)userdata, RT_OTHER);
 }
 
 // static
@@ -1775,7 +1756,8 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata)
 
 	gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time);
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata;
+	LLParcel* parcel = panelp->mParcel->getParcel();
 	if (!parcel) return;
 
 	send_parcel_select_objects(parcel->getLocalID(), RT_OWNER);
@@ -1813,7 +1795,8 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata)
 	
 	gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time);
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata;
+	LLParcel* parcel = panelp->mParcel->getParcel();
 	if (!parcel) return;
 
 	send_parcel_select_objects(parcel->getLocalID(), RT_GROUP);
@@ -1840,7 +1823,8 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
 
 	gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time);
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata;
+	LLParcel* parcel = panelp->mParcel->getParcel();
 	if (!parcel) return;
 
 	send_parcel_select_objects(parcel->getLocalID(), RT_OTHER);
@@ -1884,7 +1868,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
 void LLPanelLandObjects::onLostFocus(LLLineEditor *caller, void* user_data)
 {
 	LLPanelLandObjects	*lop = (LLPanelLandObjects *)user_data;
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = lop->mParcel->getParcel();
 	if (parcel)
 	{
 		lop->mOtherTime = atoi(lop->mCleanOtherObjectsTime->getText().c_str());
@@ -1899,7 +1883,7 @@ void LLPanelLandObjects::onLostFocus(LLLineEditor *caller, void* user_data)
 // LLPanelLandOptions
 //---------------------------------------------------------------------------
 
-LLPanelLandOptions::LLPanelLandOptions()
+LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel)
 :	LLPanel("land_options_panel"),
 	mCheckEditObjects(NULL),
 	mCheckEditGroupObjects(NULL),
@@ -1921,7 +1905,8 @@ LLPanelLandOptions::LLPanelLandOptions()
 	mAllowPublishCtrl(NULL),
 	mMatureCtrl(NULL),
 	mPushRestrictionCtrl(NULL),
-	mPublishHelpButton(NULL)
+	mPublishHelpButton(NULL),
+	mParcel(parcel)
 {
 
 }
@@ -2054,7 +2039,7 @@ LLPanelLandOptions::~LLPanelLandOptions()
 // public
 void LLPanelLandOptions::refresh()
 {
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = mParcel->getParcel();
 	
 	if (!parcel)
 	{
@@ -2225,7 +2210,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata)
 {
 	LLPanelLandOptions *self = (LLPanelLandOptions *)userdata;
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = self->mParcel->getParcel();
 	if (!parcel)
 	{
 		return;
@@ -2279,7 +2264,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata)
 	parcel->setSnapshotID(snapshot_id);
 
 	// Send current parcel data upstream to server
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 
 	// Might have changed properties, so let's redraw!
 	self->refresh();
@@ -2291,7 +2276,7 @@ void LLPanelLandOptions::onClickSet(void* userdata)
 {
 	LLPanelLandOptions* self = (LLPanelLandOptions*)userdata;
 
-	LLParcel* selected_parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* selected_parcel = self->mParcel->getParcel();
 	if (!selected_parcel) return;
 
 	LLParcel* agent_parcel = gParcelMgr->getAgentParcel();
@@ -2307,7 +2292,7 @@ void LLPanelLandOptions::onClickSet(void* userdata)
 	selected_parcel->setUserLocation(pos_region);
 	selected_parcel->setUserLookAt(gAgent.getFrameAgent().getAtAxis());
 
-	gParcelMgr->sendParcelPropertiesUpdate(selected_parcel, LLFloaterLand::sRequestReplyOnUpdate);
+	gParcelMgr->sendParcelPropertiesUpdate(selected_parcel);
 
 	self->refresh();
 }
@@ -2316,7 +2301,7 @@ void LLPanelLandOptions::onClickClear(void* userdata)
 {
 	LLPanelLandOptions* self = (LLPanelLandOptions*)userdata;
 
-	LLParcel* selected_parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* selected_parcel = self->mParcel->getParcel();
 	if (!selected_parcel) return;
 
 	// yes, this magic number of 0,0,0 means that it is clear
@@ -2324,7 +2309,7 @@ void LLPanelLandOptions::onClickClear(void* userdata)
 	selected_parcel->setUserLocation(zero_vec);
 	selected_parcel->setUserLookAt(zero_vec);
 
-	gParcelMgr->sendParcelPropertiesUpdate(selected_parcel, LLFloaterLand::sRequestReplyOnUpdate);
+	gParcelMgr->sendParcelPropertiesUpdate(selected_parcel);
 
 	self->refresh();
 }
@@ -2339,8 +2324,8 @@ void LLPanelLandOptions::onClickPublishHelp(void*)
 // LLPanelLandMedia
 //---------------------------------------------------------------------------
 
-LLPanelLandMedia::LLPanelLandMedia()
-:	LLPanel("land_media_panel")
+LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel)
+:	LLPanel("land_media_panel"), mParcel(parcel)
 {
 }
 
@@ -2382,7 +2367,7 @@ LLPanelLandMedia::~LLPanelLandMedia()
 // public
 void LLPanelLandMedia::refresh()
 {
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = mParcel->getParcel();
 
 	if (!parcel)
 	{
@@ -2467,7 +2452,7 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl *ctrl, void *userdata)
 {
 	LLPanelLandMedia *self = (LLPanelLandMedia *)userdata;
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = self->mParcel->getParcel();
 	if (!parcel)
 	{
 		return;
@@ -2488,7 +2473,7 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl *ctrl, void *userdata)
 	parcel->setMediaAutoScale ( media_auto_scale );
 
 	// Send current parcel data upstream to server
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 
 	// Might have changed properties, so let's redraw!
 	self->refresh();
@@ -2512,8 +2497,8 @@ void LLPanelLandMedia::onClickStartMedia ( void* data )
 // LLPanelLandAccess
 //---------------------------------------------------------------------------
 
-LLPanelLandAccess::LLPanelLandAccess()
-:	LLPanel("land_access_panel")
+LLPanelLandAccess::LLPanelLandAccess(LLParcelSelectionHandle& parcel)
+:	LLPanel("land_access_panel"), mParcel(parcel)
 {
 }
 
@@ -2555,13 +2540,14 @@ BOOL LLPanelLandAccess::postBuild()
 
 
 LLPanelLandAccess::~LLPanelLandAccess()
-{ }
+{ 
+}
 
 void LLPanelLandAccess::refresh()
 {
 	mListAccess->deleteAllItems();
 
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = mParcel->getParcel();
 
 	if (parcel)
 	{
@@ -2667,7 +2653,7 @@ void LLPanelLandAccess::refresh()
 // public
 void LLPanelLandAccess::refreshNames()
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = mParcel->getParcel();
 	char group_name[DB_GROUP_NAME_BUF_SIZE];		/*Flawfinder: ignore*/
 	group_name[0] = '\0';
 	if(parcel)
@@ -2698,7 +2684,7 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata)
 {
 	LLPanelLandAccess *self = (LLPanelLandAccess *)userdata;
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = self->mParcel->getParcel();
 	if (!parcel)
 	{
 		return;
@@ -2731,7 +2717,7 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata)
 	parcel->setPassHours( pass_hours );
 
 	// Send current parcel data upstream to server
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 
 	// Might have changed properties, so let's redraw!
 	self->refresh();
@@ -2755,7 +2741,7 @@ void LLPanelLandAccess::callbackAvatarID(const std::vector<std::string>& names,
 
 void LLPanelLandAccess::addAvatar(LLUUID id)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = mParcel->getParcel();
 	if (!parcel) return;
 
 	parcel->addToAccessList(id, 0);
@@ -2775,7 +2761,7 @@ void LLPanelLandAccess::onClickRemove(void* data)
 	LLScrollListItem* item = self->mListAccess->getFirstSelected();
 	if (!item) return;
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = self->mParcel->getParcel();
 	if (!parcel) return;
 
 	const LLUUID& agent_id = item->getUUID();
@@ -2792,8 +2778,8 @@ void LLPanelLandAccess::onClickRemove(void* data)
 //---------------------------------------------------------------------------
 // LLPanelLandBan
 //---------------------------------------------------------------------------
-LLPanelLandBan::LLPanelLandBan()
-:	LLPanel("land_ban_panel")
+LLPanelLandBan::LLPanelLandBan(LLParcelSelectionHandle& parcel)
+:	LLPanel("land_ban_panel"), mParcel(parcel)
 {
 
 }
@@ -2837,7 +2823,7 @@ void LLPanelLandBan::refresh()
 {
 	mList->deleteAllItems();
 
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = mParcel->getParcel();
 
 	if (parcel)
 	{
@@ -2949,7 +2935,7 @@ void LLPanelLandBan::onCommitAny(LLUICtrl *ctrl, void *userdata)
 {
 	LLPanelLandBan *self = (LLPanelLandBan*)userdata;
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = self->mParcel->getParcel();
 	if (!parcel)
 	{
 		return;
@@ -2968,7 +2954,7 @@ void LLPanelLandBan::onCommitAny(LLUICtrl *ctrl, void *userdata)
 	parcel->setParcelFlag(PF_DENY_TRANSACTED, deny_access_transacted);
 
 	// Send current parcel data upstream to server
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 
 	// Might have changed properties, so let's redraw!
 	self->refresh();
@@ -2992,7 +2978,7 @@ void LLPanelLandBan::callbackAvatarID(const std::vector<std::string>& names, con
 
 void LLPanelLandBan::addAvatar(LLUUID id)
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = mParcel->getParcel();
 	if (!parcel) return;
 
 	parcel->addToBanList(id, 0);
@@ -3012,7 +2998,7 @@ void LLPanelLandBan::onClickRemove(void* data)
 	LLScrollListItem* item = self->mList->getFirstSelected();
 	if (!item) return;
 
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = self->mParcel->getParcel();
 	if (!parcel) return;
 
 	const LLUUID& agent_id = item->getUUID();
@@ -3027,8 +3013,8 @@ void LLPanelLandBan::onClickRemove(void* data)
 //---------------------------------------------------------------------------
 // LLPanelLandRenters
 //---------------------------------------------------------------------------
-LLPanelLandRenters::LLPanelLandRenters()
-:	LLPanel("landrenters", LLRect(0,500,500,0))
+LLPanelLandRenters::LLPanelLandRenters(LLParcelSelectionHandle& parcel)
+:	LLPanel("landrenters", LLRect(0,500,500,0)), mParcel(parcel)
 {
 	const S32 BTN_WIDTH = 64;
 
@@ -3103,8 +3089,8 @@ void LLPanelLandRenters::onClickRemove(void*)
 //---------------------------------------------------------------------------
 // LLPanelLandCovenant
 //---------------------------------------------------------------------------
-LLPanelLandCovenant::LLPanelLandCovenant()
-:	LLPanel("land_covenant_panel")
+LLPanelLandCovenant::LLPanelLandCovenant(LLParcelSelectionHandle& parcel)
+:	LLPanel("land_covenant_panel"), mParcel(parcel)
 {	
 }
 
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index a28fea261f882b621983a143ceeb344649ebb3b4..b1aad89d7db2853fdbbf2f266dc981ca7c16f041 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -31,6 +31,7 @@ class LLParcelSelectionObserver;
 class LLTabContainer;
 class LLTextureCtrl;
 class LLViewerTextEditor;
+class LLParcelSelection;
 
 class LLPanelLandGeneral;
 class LLPanelLandObjects;
@@ -54,9 +55,6 @@ class LLFloaterLand
 	static LLPanelLandObjects* getCurrentPanelLandObjects();
 	static LLPanelLandCovenant* getCurrentPanelLandCovenant();
 
-	// Returns TRUE, but does some early prep work for closing the window.
-	virtual BOOL canClose();
-
 	// Destroys itself on close.
 	virtual void onClose(bool app_quitting);
 
@@ -93,6 +91,8 @@ class LLFloaterLand
 	LLPanelLandCovenant*	mPanelCovenant;
 	LLPanelLandRenters*		mPanelRenters;
 
+	LLHandle<LLParcelSelection>	mParcel;
+
 public:
 	// When closing the dialog, we want to deselect the land.  But when
 	// we send an update to the simulator, it usually replies with the
@@ -106,7 +106,7 @@ class LLPanelLandGeneral
 :	public LLPanel
 {
 public:
-	LLPanelLandGeneral();
+	LLPanelLandGeneral(LLHandle<LLParcelSelection>& parcelp);
 	virtual ~LLPanelLandGeneral();
 	void refresh();
 	void refreshNames();
@@ -198,6 +198,8 @@ class LLPanelLandGeneral
 	LLButton*		mBtnBuyPass;
 	LLButton* mBtnStartAuction;
 
+	LLHandle<LLParcelSelection>&	mParcel;
+
 	static LLViewHandle sBuyPassDialogHandle;
 };
 
@@ -205,7 +207,7 @@ class LLPanelLandObjects
 :	public LLPanel
 {
 public:
-	LLPanelLandObjects();
+	LLPanelLandObjects(LLHandle<LLParcelSelection>& parcelp);
 	virtual ~LLPanelLandObjects();
 	void refresh();
 	virtual void draw();
@@ -215,7 +217,7 @@ class LLPanelLandObjects
 	static void callbackReturnOtherObjects(S32, void*);
 	static void callbackReturnOwnerList(S32, void*);
 
-	static void clickShowCore(S32 return_type, uuid_list_t* list = 0);
+	static void clickShowCore(LLPanelLandObjects* panelp, S32 return_type, uuid_list_t* list = 0);
 	static void onClickShowOwnerObjects(void*);
 	static void onClickShowGroupObjects(void*);
 	static void onClickShowOtherObjects(void*);
@@ -295,6 +297,8 @@ class LLPanelLandObjects
 	LLString		mSelectedName;
 	S32				mSelectedCount;
 	BOOL			mSelectedIsGroup;
+
+	LLHandle<LLParcelSelection>&	mParcel;
 };
 
 
@@ -302,7 +306,7 @@ class LLPanelLandOptions
 :	public LLPanel
 {
 public:
-	LLPanelLandOptions();
+	LLPanelLandOptions(LLHandle<LLParcelSelection>& parcelp);
 	virtual ~LLPanelLandOptions();
 	void refresh();
 
@@ -340,6 +344,8 @@ class LLPanelLandOptions
 	LLCheckBoxCtrl		*mMatureCtrl;
 	LLCheckBoxCtrl		*mPushRestrictionCtrl;
 	LLButton			*mPublishHelpButton;
+
+	LLHandle<LLParcelSelection>&	mParcel;
 };
 
 
@@ -347,7 +353,7 @@ class LLPanelLandMedia
 :	public LLPanel
 {
 public:
-	LLPanelLandMedia();
+	LLPanelLandMedia(LLHandle<LLParcelSelection>& parcelp);
 	virtual ~LLPanelLandMedia();
 	void refresh();
 
@@ -365,6 +371,8 @@ class LLPanelLandMedia
 	LLCheckBoxCtrl*	mMediaAutoScaleCheck;
 	//LLButton*		mMediaStopButton;
 	//LLButton*		mMediaStartButton;
+
+	LLHandle<LLParcelSelection>&	mParcel;
 };
 
 
@@ -373,7 +381,7 @@ class LLPanelLandAccess
 :	public LLPanel
 {
 public:
-	LLPanelLandAccess();
+	LLPanelLandAccess(LLHandle<LLParcelSelection>& parcelp);
 	virtual ~LLPanelLandAccess();
 	void refresh();
 	void refreshNames();
@@ -407,6 +415,7 @@ class LLPanelLandAccess
 	LLCheckBoxCtrl*		mCheckTransacted;
 	LLRadioGroup*		mCheckStatusLevel;
 
+	LLHandle<LLParcelSelection>&	mParcel;
 };
 
 
@@ -414,7 +423,7 @@ class LLPanelLandBan
 :	public LLPanel
 {
 public:
-	LLPanelLandBan();
+	LLPanelLandBan(LLHandle<LLParcelSelection>& parcelp);
 	virtual ~LLPanelLandBan();
 	void refresh();
 
@@ -437,6 +446,8 @@ class LLPanelLandBan
 	LLCheckBoxCtrl*		mCheckDenyAnonymous;
 	LLCheckBoxCtrl*		mCheckDenyIdentified;
 	LLCheckBoxCtrl*		mCheckDenyTransacted;
+
+	LLHandle<LLParcelSelection>&	mParcel;
 };
 
 
@@ -444,7 +455,7 @@ class LLPanelLandRenters
 :	public LLPanel
 {
 public:
-	LLPanelLandRenters();
+	LLPanelLandRenters(LLHandle<LLParcelSelection>& parcelp);
 	virtual ~LLPanelLandRenters();
 	void refresh();
 
@@ -456,13 +467,15 @@ class LLPanelLandRenters
 	LLNameListCtrl*		mListRenters;
 	LLButton*			mBtnAddRenter;
 	LLButton*			mBtnRemoveRenter;
+
+	LLHandle<LLParcelSelection>&	mParcel;
 };
 
 class LLPanelLandCovenant
 :	public LLPanel
 {
 public:
-	LLPanelLandCovenant();
+	LLPanelLandCovenant(LLHandle<LLParcelSelection>& parcelp);
 	virtual ~LLPanelLandCovenant();
 	virtual BOOL postBuild();
 	void refresh();
@@ -470,6 +483,9 @@ class LLPanelLandCovenant
 	static void updateEstateName(const std::string& name);
 	static void updateLastModified(const std::string& text);
 	static void updateEstateOwnerName(const std::string& name);
+
+protected:
+	LLHandle<LLParcelSelection>&	mParcel;
 };
 
 #endif
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index 7e15c373d422d1c482dd57fea98d74bbcb102902..7f29b37913f4eb2cbaad6e21059c6059b3712a33 100644
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -49,7 +49,6 @@ LLFloaterOpenObject::LLFloaterOpenObject()
 
 LLFloaterOpenObject::~LLFloaterOpenObject()
 {
-	gSelectMgr->deselectAll();
 	sInstance = NULL;
 }
 
@@ -57,7 +56,7 @@ void LLFloaterOpenObject::refresh()
 {
 	mPanelInventory->refresh();
 
-	LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	LLSelectNode* node = mObjectSelection->getFirstRootNode();
 	if (node)
 	{
 		std::string name = node->mName;
@@ -84,7 +83,8 @@ void LLFloaterOpenObject::dirty()
 // static
 void LLFloaterOpenObject::show()
 {
-	if (gSelectMgr->getRootObjectCount() != 1)
+	LLObjectSelectionHandle object_selection = gSelectMgr->getSelection();
+	if (object_selection->getRootObjectCount() != 1)
 	{
 		gViewerWindow->alertXml("UnableToViewContentsMoreThanOne");
 		return;
@@ -99,19 +99,20 @@ void LLFloaterOpenObject::show()
 
 	sInstance->open();		/* Flawfinder: ignore */
 	sInstance->setFocus(TRUE);
+
+	sInstance->mObjectSelection = gSelectMgr->getEditSelection();
 }
 
 
-// static
 void LLFloaterOpenObject::moveToInventory(bool wear)
 {
-	if (gSelectMgr->getRootObjectCount() != 1)
+	if (mObjectSelection->getRootObjectCount() != 1)
 	{
 		gViewerWindow->alertXml("OnlyCopyContentsOfSingleItem");
 		return;
 	}
 
-	LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	LLSelectNode* node = mObjectSelection->getFirstRootNode();
 	if (!node) return;
 	LLViewerObject* object = node->getObject();
 	if (!object) return;
@@ -175,7 +176,7 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data)
 void LLFloaterOpenObject::onClickMoveToInventory(void* data)
 {
 	LLFloaterOpenObject* self = (LLFloaterOpenObject*)data;
-	moveToInventory(false);
+	self->moveToInventory(false);
 	self->close();
 }
 
@@ -183,7 +184,7 @@ void LLFloaterOpenObject::onClickMoveToInventory(void* data)
 void LLFloaterOpenObject::onClickMoveAndWear(void* data)
 {
 	LLFloaterOpenObject* self = (LLFloaterOpenObject*)data;
-	moveToInventory(true);
+	self->moveToInventory(true);
 	self->close();
 }
 
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index 8de8832ca9c227547ce03b4d302a7d2458d19240..88635d58b1c5fada4b255090e28a392cc11e4e3b 100644
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -16,8 +16,7 @@
 
 #include "llfloater.h"
 
-
-
+class LLObjectSelection;
 class LLPanelInventory;
 
 class LLFloaterOpenObject
@@ -40,9 +39,10 @@ class LLFloaterOpenObject
 	void refresh();
 	void draw();
 
+	void moveToInventory(bool wear);
+
 	static void onClickMoveToInventory(void* data);
 	static void onClickMoveAndWear(void* data);
-	static void moveToInventory(bool wear);
 	static void callbackMoveInventory(S32 result, void* data);
 	static void* createPanelInventory(void* data);
 
@@ -50,6 +50,7 @@ class LLFloaterOpenObject
 	static LLFloaterOpenObject* sInstance;
 
 	LLPanelInventory*	mPanelInventory;
+	LLHandle<LLObjectSelection> mObjectSelection;
 	BOOL mDirty;
 };
 
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 89ff4bc66d9b802a633c0726164fa6428c8cd7a9..84c99db8daa626055ca5c4c885012043eec58937 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -211,11 +211,6 @@ LLFloaterReporter::~LLFloaterReporter()
 	std::for_each(mMCDList.begin(), mMCDList.end(), DeletePointer() );
 	mMCDList.clear();
 
-	if (gSelectMgr)
-	{
-		gSelectMgr->deselectTransient();
-	}
-
 	gDialogVisible = FALSE;
 }
 
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 65c5f5607eae2bfc6b1d0567755b3cd6c9c96530..098417d1b455fdd4fec9d852351d341803035ee6 100755
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -36,15 +36,15 @@ class LLFloaterSellLandUI
 	virtual ~LLFloaterSellLandUI();
 
 	LLViewerRegion*	mRegion;
-	LLParcel*		mParcel;
-	bool			mParcelIsForSale;
-	bool			mSellToBuyer;
-	bool			mChoseSellTo;
-	S32				mParcelPrice;
-	S32				mParcelActualArea;
-	LLUUID			mParcelSnapshot;
-	LLUUID			mAuthorizedBuyer;
-	bool			mParcelSoldWithObjects;
+	LLParcelSelectionHandle	mParcelSelection;
+	bool					mParcelIsForSale;
+	bool					mSellToBuyer;
+	bool					mChoseSellTo;
+	S32						mParcelPrice;
+	S32						mParcelActualArea;
+	LLUUID					mParcelSnapshot;
+	LLUUID					mAuthorizedBuyer;
+	bool					mParcelSoldWithObjects;
 	
 	void updateParcelInfo();
 	void refreshUI();
@@ -68,12 +68,19 @@ class LLFloaterSellLandUI
 	
 	static LLFloaterSellLandUI* soleInstance(bool createIfNeeded);
 
-	bool setParcel(LLViewerRegion* region, LLParcel* parcel);
+	bool setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel);
+
+private:
+	class SelectionObserver : public LLParcelObserver
+	{
+	public:
+		virtual void changed();
+	};
 };
 
 // static
 void LLFloaterSellLand::sellLand(
-	LLViewerRegion* region, LLParcel* parcel)
+	LLViewerRegion* region, LLParcelSelectionHandle parcel)
 {
 	LLFloaterSellLandUI* ui = LLFloaterSellLandUI::soleInstance(true);
 	if (ui->setParcel(region, parcel))
@@ -96,12 +103,20 @@ LLFloaterSellLandUI* LLFloaterSellLandUI::soleInstance(bool createIfNeeded)
 		sInstance->center();
 	}
 	
+
+	static SelectionObserver* parcelSelectionObserver = NULL;
+	if (!parcelSelectionObserver)
+	{
+		parcelSelectionObserver = new SelectionObserver;
+		gParcelMgr->addObserver(parcelSelectionObserver);
+	}
+
 	return sInstance;
 }
 
 LLFloaterSellLandUI::LLFloaterSellLandUI()
 :	LLFloater("Sell Land"),
-	mRegion(0), mParcel(0)
+	mRegion(0)
 {
 }
 
@@ -113,6 +128,22 @@ LLFloaterSellLandUI::~LLFloaterSellLandUI()
 	}
 }
 
+void LLFloaterSellLandUI::SelectionObserver::changed()
+{
+	LLFloaterSellLandUI* ui = LLFloaterSellLandUI::soleInstance(false);
+	if (ui)
+	{
+		if (gParcelMgr->selectionEmpty())
+		{
+			ui->close();
+		}
+		else {
+			ui->setParcel(
+				gParcelMgr->getSelectionRegion(),
+				gParcelMgr->getParcelSelection());
+		}
+	}
+}
 
 void LLFloaterSellLandUI::onClose(bool app_quitting)
 {
@@ -133,17 +164,18 @@ BOOL LLFloaterSellLandUI::postBuild()
 	return TRUE;
 }
 
-bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcel* parcel)
+bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel)
 {
-	if (!parcel) // || !can_agent_modify_parcel(parcel)) // can_agent_modify_parcel was deprecated by GROUPS
+	if (!parcel->getParcel()) // || !can_agent_modify_parcel(parcel)) // can_agent_modify_parcel was deprecated by GROUPS
 	{
 		return false;
 	}
 
 	mRegion = region;
-	mParcel = parcel;
+	mParcelSelection = parcel;
 	mChoseSellTo = false;
 
+
 	updateParcelInfo();
 	refreshUI();
 
@@ -152,14 +184,17 @@ bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcel* parcel)
 
 void LLFloaterSellLandUI::updateParcelInfo()
 {
-	mParcelActualArea = mParcel->getArea();
-	mParcelIsForSale = mParcel->getForSale();
+	LLParcel* parcelp = mParcelSelection->getParcel();
+	if (!parcelp) return;
+
+	mParcelActualArea = parcelp->getArea();
+	mParcelIsForSale = parcelp->getForSale();
 	if (mParcelIsForSale)
 	{
 		mChoseSellTo = true;
 	}
-	mParcelPrice = mParcelIsForSale ? mParcel->getSalePrice() : 0;
-	mParcelSoldWithObjects = mParcel->getSellWithObjects();
+	mParcelPrice = mParcelIsForSale ? parcelp->getSalePrice() : 0;
+	mParcelSoldWithObjects = parcelp->getSellWithObjects();
 	if (mParcelIsForSale)
 	{
 		childSetValue("price", mParcelPrice);
@@ -178,9 +213,9 @@ void LLFloaterSellLandUI::updateParcelInfo()
 		childSetValue("sell_objects", "none");
 	}
 
-	mParcelSnapshot = mParcel->getSnapshotID();
+	mParcelSnapshot = parcelp->getSnapshotID();
 
-	mAuthorizedBuyer = mParcel->getAuthorizedBuyerID();
+	mAuthorizedBuyer = parcelp->getAuthorizedBuyerID();
 	mSellToBuyer = mAuthorizedBuyer.notNull();
 
 	if(mSellToBuyer)
@@ -219,13 +254,16 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge)
 
 void LLFloaterSellLandUI::refreshUI()
 {
+	LLParcel* parcelp = mParcelSelection->getParcel();
+	if (!parcelp) return;
+
 	LLTextureCtrl* snapshot = LLViewerUICtrlFactory::getTexturePickerByName(this, "info_image");
 	if (snapshot)
 	{
 		snapshot->setImageAssetID(mParcelSnapshot);
 	}
 
-	childSetText("info_parcel", mParcel->getName());
+	childSetText("info_parcel", parcelp->getName());
 	childSetTextArg("info_size", "[AREA]", llformat("%d", mParcelActualArea));
 
 	LLString price_str = childGetValue("price").asString();
@@ -358,7 +396,7 @@ void LLFloaterSellLandUI::doSelectAgent(void *userdata)
 void LLFloaterSellLandUI::callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data)
 {	
 	LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)data;
-	LLParcel* parcel = floaterp->mParcel;
+	LLParcel* parcel = floaterp->mParcelSelection->getParcel();
 
 	if (names.empty() || ids.empty()) return;
 	
@@ -383,7 +421,10 @@ void LLFloaterSellLandUI::doCancel(void *userdata)
 void LLFloaterSellLandUI::doShowObjects(void *userdata)
 {
 	LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
-	send_parcel_select_objects(self->mParcel->getLocalID(), RT_SELL);
+	LLParcel* parcel = self->mParcelSelection->getParcel();
+	if (!parcel) return;
+
+	send_parcel_select_objects(parcel->getLocalID(), RT_SELL);
 
 	LLNotifyBox::showXml("TransferObjectsHighlighted",
 						 callbackHighlightTransferable,
@@ -401,7 +442,7 @@ void LLFloaterSellLandUI::doSellLand(void *userdata)
 {
 	LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
 
-	LLParcel* parcel = self->mParcel;
+	LLParcel* parcel = self->mParcelSelection->getParcel();
 
 	// Do a confirmation
 	if (!parcel->getForSale())
@@ -453,7 +494,8 @@ void LLFloaterSellLandUI::onConfirmSale(S32 option, void *userdata)
 		return;
 	}
 
-	LLParcel* parcel = self->mParcel;
+	LLParcel* parcel = self->mParcelSelection->getParcel();
+	if (!parcel) return;
 
 	// can_agent_modify_parcel deprecated by GROUPS
 // 	if (!can_agent_modify_parcel(parcel))
@@ -480,7 +522,7 @@ void LLFloaterSellLandUI::onConfirmSale(S32 option, void *userdata)
 	}
 
 	// Send update to server
-	gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate );
+	gParcelMgr->sendParcelPropertiesUpdate( parcel );
 
 	self->close();
 }
diff --git a/indra/newview/llfloatersellland.h b/indra/newview/llfloatersellland.h
index 077a775ffcce9c994e6a730a5ea6bf51af7dd436..f9bf84ebcf9e06bceb7a48d44c01f8c84e0824b5 100755
--- a/indra/newview/llfloatersellland.h
+++ b/indra/newview/llfloatersellland.h
@@ -7,15 +7,17 @@
 
 #ifndef LL_LLFLOATERSELLLAND_H
 #define LL_LLFLOATERSELLLAND_H
+#include "llmemory.h"
 
 class LLParcel;
 class LLViewerRegion;
+class LLParcelSelection;
 
 class LLFloaterSellLand
 {
 public:
 	static void sellLand(LLViewerRegion* region,
-						LLParcel* parcel);
+						LLHandle<LLParcelSelection> parcel);
 };
 
 #endif // LL_LLFLOATERSELLLAND_H
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 1b82b6b43dfcecb4163603677d6ae39a73e34b5c..05047e1a4aa74cd95cced54fc3d9ebbc77ab2b71 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -813,13 +813,12 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
 		// freeze everything else
 		gSavedSettings.setBOOL("FreezeTime", TRUE);
 
-		if (gCurrentToolset != gCameraToolset)
+		if (gToolMgr->getCurrentToolset() != gCameraToolset)
 		{
-			sInstance->impl.mLastToolset = gCurrentToolset;
-			gCurrentToolset = gCameraToolset;
+			sInstance->impl.mLastToolset = gToolMgr->getCurrentToolset();
 			if (gToolMgr)
 			{
-				gToolMgr->useSelectedTool( gCurrentToolset );
+				gToolMgr->setCurrentToolset(gCameraToolset);
 			}
 		}
 	}
@@ -842,10 +841,9 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp)
 		// restore last tool (e.g. pie menu, etc)
 		if (sInstance->impl.mLastToolset)
 		{
-			gCurrentToolset = sInstance->impl.mLastToolset;
 			if (gToolMgr)
 			{
-				gToolMgr->useSelectedTool( gCurrentToolset );
+				gToolMgr->setCurrentToolset(sInstance->impl.mLastToolset);
 			}
 		}
 	}
@@ -1220,10 +1218,9 @@ LLFloaterSnapshot::~LLFloaterSnapshot()
 
 	if (impl.mLastToolset)
 	{
-		gCurrentToolset = impl.mLastToolset;
-		if (gToolMgr && gCurrentToolset)
+		if (gToolMgr)
 		{
-			gToolMgr->useSelectedTool( gCurrentToolset );
+			gToolMgr->setCurrentToolset(impl.mLastToolset);
 		}
 	}
 
@@ -1487,7 +1484,7 @@ BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask)
 	// give floater a change to handle mouse, else camera tool
 	if (childrenHandleMouseDown(x, y, mask) == NULL)
 	{
-		gToolMgr->getCurrentTool(mask)->handleMouseDown( x, y, mask );
+		gToolMgr->getCurrentTool()->handleMouseDown( x, y, mask );
 	}
 	return TRUE;
 }
@@ -1502,7 +1499,7 @@ BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask)
 	// give floater a change to handle mouse, else camera tool
 	if (childrenHandleMouseUp(x, y, mask) == NULL)
 	{
-		gToolMgr->getCurrentTool(mask)->handleMouseUp( x, y, mask );
+		gToolMgr->getCurrentTool()->handleMouseUp( x, y, mask );
 	}
 	return TRUE;
 }
@@ -1517,7 +1514,7 @@ BOOL LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask)
 	// give floater a change to handle mouse, else camera tool
 	if (childrenHandleHover(x, y, mask) == NULL)
 	{
-		gToolMgr->getCurrentTool(mask)->handleHover( x, y, mask );
+		gToolMgr->getCurrentTool()->handleHover( x, y, mask );
 	}
 	return TRUE;
 }
diff --git a/indra/newview/llfloatertelehub.cpp b/indra/newview/llfloatertelehub.cpp
index 25cfc12c3eff30cd2d2af171c0c1a77f58942559..1c75b7e220e909f3a6bbeffdd3a189613cdeb129 100644
--- a/indra/newview/llfloatertelehub.cpp
+++ b/indra/newview/llfloatertelehub.cpp
@@ -39,8 +39,8 @@ void LLFloaterTelehub::show()
 	sInstance = new LLFloaterTelehub();
 
 	// Show tools floater by selecting translate (select) tool
-	gCurrentToolset = gBasicToolset;
-	gCurrentToolset->selectTool( gToolTranslate );
+	gToolMgr->setCurrentToolset(gBasicToolset);
+	gToolMgr->getCurrentToolset()->selectTool( gToolTranslate );
 
 	// Find tools floater, glue to bottom
 	if (gFloaterTools)
@@ -82,6 +82,8 @@ LLFloaterTelehub::LLFloaterTelehub()
 		// otherwise you can't walk with arrow keys while floater is up
 		list->setAllowKeyboardMovement(FALSE);
 	}
+
+	mObjectSelection = gSelectMgr->getEditSelection();
 }
 
 LLFloaterTelehub::~LLFloaterTelehub()
@@ -104,10 +106,10 @@ void LLFloaterTelehub::draw()
 // Per-frame updates, because we don't have a selection manager observer.
 void LLFloaterTelehub::refresh()
 {
-	LLViewerObject* object = gSelectMgr->getFirstRootObject();
+	LLViewerObject* object = mObjectSelection->getFirstRootObject();
 	if(!object)
 	{
-		object = gSelectMgr->getFirstObject();
+		object = mObjectSelection->getFirstObject();
 	}
 	
 	BOOL have_selection = (object != NULL);
diff --git a/indra/newview/llfloatertelehub.h b/indra/newview/llfloatertelehub.h
index 39f12f9443bd4d02851110b4e23b1fbadf13597b..287769b03731151a43e3d3f9f3a82e6824ad3da9 100644
--- a/indra/newview/llfloatertelehub.h
+++ b/indra/newview/llfloatertelehub.h
@@ -13,6 +13,7 @@
 #include "llfloater.h"
 
 class LLMessageSystem;
+class LLObjectSelection;
 
 const S32 MAX_SPAWNPOINTS_PER_TELEHUB = 16;
 
@@ -50,6 +51,8 @@ class LLFloaterTelehub : public LLFloater
 
 	S32 mNumSpawn;
 	LLVector3 mSpawnPointPos[MAX_SPAWNPOINTS_PER_TELEHUB];
+	
+	LLHandle<LLObjectSelection> mObjectSelection;
 
 	static LLFloaterTelehub* sInstance;
 };
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index e21c7a45a8c61edfd827d5325f17273009fd014f..34eb84156812d6559777bd7a0789998fa46b24c6 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -376,7 +376,7 @@ LLFloaterTools::LLFloaterTools()
 	factory_map["ContentsInventory"] = LLCallbackMap(createPanelContentsInventory, this);//LLPanelContents
 	factory_map["land info panel"] = LLCallbackMap(createPanelLandInfo, this);//LLPanelLandInfo
 
-	gUICtrlFactory->buildFloater(this,"floater_tools.xml",&factory_map);
+	gUICtrlFactory->buildFloater(this,"floater_tools.xml",&factory_map,FALSE);
 
 	mLargeHeight = getRect().getHeight();
 	mSmallHeight = mLargeHeight;
@@ -459,7 +459,7 @@ void LLFloaterTools::resetToolState()
 
 void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
 {
-	LLTool *tool = gToolMgr->getCurrentTool( mask );
+	LLTool *tool = gToolMgr->getCurrentTool();
 
 	// HACK to allow seeing the buttons when you have the app in a window.
 	// Keep the visibility the same as it 
@@ -560,7 +560,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)
 		S32 index = mComboGridMode->getCurrentIndex();
 		mComboGridMode->removeall();
 
-		switch (gSelectMgr->getSelectType())
+		switch (mObjectSelection->getSelectType())
 		{
 		case SELECT_TYPE_HUD:
 			mComboGridMode->add("Screen");
@@ -706,6 +706,13 @@ BOOL LLFloaterTools::canClose()
 	return !gQuit;
 }
 
+// virtual
+void LLFloaterTools::onOpen()
+{
+	mParcelSelection = gParcelMgr->getFloatingParcelSelection();
+	mObjectSelection = gSelectMgr->getEditSelection();
+}
+
 // virtual
 void LLFloaterTools::onClose(bool app_quitting)
 {
@@ -725,10 +732,14 @@ void LLFloaterTools::onClose(bool app_quitting)
 
 	resetToolState();
 
+	mParcelSelection = NULL;
+	mObjectSelection = NULL;
+
 	// Switch back to basic toolset
-	gCurrentToolset = gBasicToolset;
-	gBasicToolset->selectFirstTool();
-	gToolMgr->useSelectedTool( gBasicToolset );
+	gToolMgr->setCurrentToolset(gBasicToolset);
+	// we were already in basic toolset, using build tools
+	// so manually reset tool to default (pie menu tool)
+	gToolMgr->getCurrentToolset()->selectFirstTool();
 }
 
 void LLFloaterTools::showMore(BOOL show_more)
@@ -936,6 +947,5 @@ void LLFloaterTools::setEditTool(void* tool_pointer)
 
 void LLFloaterTools::onFocusReceived()
 {
-	gCurrentToolset = gBasicToolset;
-	gCurrentToolset->selectTool(gCurrentToolset->getSelectedTool());
+	gToolMgr->setCurrentToolset(gBasicToolset);
 }
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index e13e15ba015907f7fd6c0399a6414a0537b611ff..7c854445788ccf26016197c8813581e149a1da0a 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -25,6 +25,11 @@ class LLPanelFace;
 class LLPanelLandInfo;
 class LLComboBox;
 class LLVolumeSliderCtrl;
+class LLParcelSelection;
+class LLObjectSelection;
+
+typedef LLHandle<LLParcelSelection> LLParcelSelectionHandle;
+typedef LLHandle<LLObjectSelection> LLObjectSelectionHandle;
 
 class LLFloaterTools
 : public LLFloater
@@ -42,6 +47,7 @@ class LLFloaterTools
 	LLFloaterTools();
 	virtual ~LLFloaterTools();
 
+	virtual void onOpen();
 	virtual void onClose(bool app_quitting);
 	virtual BOOL canClose();
 
@@ -156,7 +162,10 @@ class LLFloaterTools
 	LLPanelLandInfo			*mPanelLandInfo;
 
 	LLTabContainer*			mTabLand;
-	
+
+	LLParcelSelectionHandle	mParcelSelection;
+	LLObjectSelectionHandle	mObjectSelection;
+
 private:
 	BOOL					mDirty;
 	S32						mSmallHeight;
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index b51bdd057d6f8b66e22c369ec57705c815f916af..2cb6db5a16d148de981c07675b4dc84a564be53c 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -226,9 +226,11 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask)
 
 	if (shrink_selection)
 	{
-		for (LLViewerObject* vobjp = gSelectMgr->getFirstHighlightedObject();
+		LLObjectSelectionHandle highlighted_objects = gSelectMgr->getHighlightedObjects();
+
+		for (LLViewerObject* vobjp = highlighted_objects->getFirstObject();
 			vobjp;
-			vobjp = gSelectMgr->getNextHighlightedObject())
+			vobjp = highlighted_objects->getNextObject())
 			{
 				LLDrawable* drawable = vobjp->mDrawable;
 				if (!drawable || vobjp->getPCode() != LL_PCODE_VOLUME || vobjp->isAttachment())
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index b2022eb658caec300a856d1c2a4476c527dc9ac1..b1b57fb0036ae7eb2a8daa48797db92361f1e181 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3317,7 +3317,7 @@ BOOL LLObjectBridge::renameItem(const LLString& new_name)
 			{
 				gSelectMgr->deselectAll();
 				gSelectMgr->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
-				gSelectMgr->setObjectName( new_name );
+				gSelectMgr->selectionSetObjectName( new_name );
 				gSelectMgr->deselectAll();
 			}
 		}
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index bdc57c798d94f363919c58f3ce0ea971f18cc2ab..90455f5902e4d14c7354aa05250cea8015fcd1a2 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -28,6 +28,7 @@
 #include "llmutelist.h"
 #include "llnotify.h"
 #include "llcallbacklist.h"
+#include "llpreview.h"
 #include <deque>
 
 //#define DIFF_INVENTORY_FILES
@@ -2295,6 +2296,8 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo
 	item_array_t items;
 	update_map_t update;
 	S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
+	bool all_one_folder = true;
+	LLUUID folder_id;
 	for(S32 i = 0; i < count; ++i)
 	{
 		LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
@@ -2321,6 +2324,14 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo
 		{
 			++update[titem->getParentUUID()];
 		}
+		if (folder_id.isNull())
+		{
+			folder_id = titem->getParentUUID();
+		}
+		else
+		{
+			all_one_folder = false;
+		}
 	}
 	if(account)
 	{
@@ -2344,6 +2355,18 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo
 		trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
 		if(!gInventory.isObjectDescendentOf(lastitem->getUUID(), trash_id))
 		{
+			LLMultiPreview* multi_previewp = LLMultiPreview::getAutoOpenInstance(folder_id);
+			if (!multi_previewp && all_one_folder)
+			{
+				S32 left, top;
+				gFloaterView->getNewFloaterPosition(&left, &top);
+
+				multi_previewp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100));
+				LLMultiPreview::setAutoOpenInstance(multi_previewp, folder_id);
+			}
+
+			LLFloater::setFloaterHost(multi_previewp);
+
 			bool show_keep_discard = lastitem->getPermissions().getCreator() != gAgent.getID();
 			switch(lastitem->getType())
 			{
@@ -2374,6 +2397,13 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo
 			default:
 				break;
 			}
+
+			LLFloater::setFloaterHost(NULL);
+			if (multi_previewp)
+			{
+				multi_previewp->open();
+			}
+
 			LLInventoryView* view = LLInventoryView::getActiveInventory();
 			if(view)
 			{
diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp
index 1eded1512134656641a63efc451b64459353f496..f47bbbd2b2c5efadad19236bfbb3783b4c040c91 100644
--- a/indra/newview/llmanip.cpp
+++ b/indra/newview/llmanip.cpp
@@ -150,7 +150,7 @@ F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVecto
 {
 	//update current snap subdivision level
 	LLVector3 cam_to_reference;
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		cam_to_reference = LLVector3(1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f);
 	}
@@ -167,12 +167,27 @@ F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVecto
 	return subdivisions;
 }
 
+void LLManip::handleSelect()
+{
+	mObjectSelection = gSelectMgr->getEditSelection();
+}
+
+void LLManip::handleDeselect()
+{
+	mObjectSelection = NULL;
+}
+
+LLObjectSelectionHandle LLManip::getSelection()
+{
+	return mObjectSelection;
+}
+
 BOOL LLManip::handleHover(S32 x, S32 y, MASK mask)
 {
 	// We only handle the event if mousedown started with us
 	if( hasMouseCapture() )
 	{
-		if( gSelectMgr->isEmpty() )
+		if( mObjectSelection->isEmpty() )
 		{
 			// Somehow the object got deselected while we were dragging it.
 			// Release the mouse
@@ -217,7 +232,7 @@ BOOL LLManip::getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector
 
 BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal)
 {
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		BOOL result = FALSE;
 		F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidth() - 0.5f) * gCamera->getAspect() / gAgent.getAvatarObject()->mHUDCurZoom;
@@ -252,12 +267,12 @@ BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVect
 // Given the line defined by mouse cursor (a1 + a_param*(a2-a1)) and the line defined by b1 + b_param*(b2-b1),
 // returns a_param and b_param for the points where lines are closest to each other.
 // Returns false if the two lines are parallel.
-BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param ) const
+BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param )
 {
 	LLVector3 a1;
 	LLVector3 a2;
 
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) * gCamera->getAspect() / gAgent.getAvatarObject()->mHUDCurZoom;
 		F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
@@ -305,11 +320,11 @@ LLVector3 LLManip::getSavedPivotPoint() const
 	return gSelectMgr->getSavedBBoxOfSelection().getCenterAgent();
 }
 
-LLVector3 LLManip::getPivotPoint() const
+LLVector3 LLManip::getPivotPoint()
 {
-	if (gSelectMgr->getFirstObject() && gSelectMgr->getObjectCount() == 1 && gSelectMgr->getSelectType() != SELECT_TYPE_HUD)
+	if (mObjectSelection->getFirstObject() && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
 	{
-		return gSelectMgr->getFirstObject()->getPivotPositionAgent();
+		return mObjectSelection->getFirstObject()->getPivotPositionAgent();
 	}
 	return gSelectMgr->getBBoxOfSelection().getCenterAgent();
 }
@@ -322,10 +337,10 @@ void LLManip::renderGuidelines(BOOL draw_x, BOOL draw_y, BOOL draw_z)
 	LLVector3 grid_scale;
 	gSelectMgr->getGrid(grid_origin, grid_rot, grid_scale);
 
-	LLViewerObject* object = gSelectMgr->getFirstRootObject();
+	LLViewerObject* object = mObjectSelection->getFirstRootObject();
 	if (!object)
 	{
-		object = gSelectMgr->getFirstObject();
+		object = mObjectSelection->getFirstObject();
 		if (!object)
 		{
 			return;
@@ -447,7 +462,7 @@ void LLManip::renderTickText(const LLVector3& pos, const char* text, const LLCol
 {
 	const LLFontGL* big_fontp = gResMgr->getRes( LLFONT_SANSSERIF );
 
-	BOOL hud_selection = gSelectMgr->getSelectType() == SELECT_TYPE_HUD;
+	BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD;
 	glMatrixMode(GL_MODELVIEW);
 	glPushMatrix();
 	LLVector3 render_pos = pos;
@@ -465,9 +480,9 @@ void LLManip::renderTickText(const LLVector3& pos, const char* text, const LLCol
 	LLGLEnable tex(GL_TEXTURE_2D);
 	shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f;
 	gViewerWindow->setupViewport(1, -1);
-	hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
+	hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
 	gViewerWindow->setupViewport();
-	hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
+	hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
 
 	glPopMatrix();
 }
@@ -506,7 +521,7 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const char* suffi
 		}
 	}
 
-	BOOL hud_selection = gSelectMgr->getSelectType() == SELECT_TYPE_HUD;
+	BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD;
 	glMatrixMode(GL_MODELVIEW);
 	glPushMatrix();
 	LLVector3 render_pos = pos;
diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h
index b1c24741660550b142c36e6dbc39690be943e4eb..b4101b65bd3b23e074efdabac49bd2942ed315fa 100644
--- a/indra/newview/llmanip.h
+++ b/indra/newview/llmanip.h
@@ -17,6 +17,7 @@ class LLTextBox;
 class LLViewerObject;
 class LLToolComposite;
 class LLVector3;
+class LLObjectSelection;
 
 const S32 MIN_DIVISION_PIXEL_WIDTH = 9;
 
@@ -102,14 +103,18 @@ class LLManip : public LLTool
 	void				renderGuidelines(BOOL draw_x = TRUE, BOOL draw_y = TRUE, BOOL draw_z = TRUE);
 	static void			renderXYZ(const LLVector3 &vec);
 
-    virtual BOOL		handleMouseDown(S32 x, S32 y, MASK mask) = 0;
     /*virtual*/ BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
     /*virtual*/ BOOL	handleHover(S32 x, S32 y, MASK mask);
 	virtual EManipPart	getHighlightedPart() { return LL_NO_PART; }
 	virtual void		highlightManipulators(S32 x, S32 y) {};
+	virtual void		handleSelect();
+	virtual void		handleDeselect();
+
+	LLHandle<LLObjectSelection> getSelection();
+
 protected:
 	LLVector3			getSavedPivotPoint() const;
-	LLVector3			getPivotPoint() const;
+	LLVector3			getPivotPoint();
 	void				getManipNormal(LLViewerObject* object, EManipPart manip, LLVector3 &normal);
 	BOOL				getManipAxis(LLViewerObject* object, EManipPart manip, LLVector3 &axis);
 	F32					getSubdivisionLevel(const LLVector3 &reference_point, const LLVector3 &translate_axis, F32 grid_scale, S32 min_pixel_spacing = MIN_DIVISION_PIXEL_WIDTH);
@@ -118,11 +123,12 @@ class LLManip : public LLTool
 	void				updateGridSettings();
 	BOOL				getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal);
 	BOOL				getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector3 origin, LLVector3 normal);
-	BOOL				nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param ) const;
+	BOOL				nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param );
 	LLColor4			setupSnapGuideRenderPass(S32 pass);
 protected:
 	LLFrameTimer		mHelpTextTimer;
 	BOOL				mInSnapRegime;
+	LLHandle<LLObjectSelection> mObjectSelection;
 
 	static F32			sHelpTextVisibleTime;
 	static F32			sHelpTextFadeTime;
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index 46014f2a0b21da33439307cd1b42b8661760a23d..e9a6b1d1baed39326a544dfee13b8c33da26e546 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -62,7 +62,6 @@ const F32 SELECTED_MANIPULATOR_SCALE = 1.05f;
 const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
 
 extern void handle_reset_rotation(void*);  // in LLViewerWindow
-extern void handle_first_tool(void*);
 
 LLManipRotate::LLManipRotate( LLToolComposite* composite )
 : 	LLManip( "Rotate", composite ),
@@ -89,6 +88,7 @@ void LLManipRotate::handleSelect()
 	// *FIX: put this in mouseDown?
 	gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
 	gFloaterTools->setStatusText("Drag colored bands to rotate object");
+	LLManip::handleSelect();
 }
 
 void LLManipRotate::handleDeselect()
@@ -97,6 +97,7 @@ void LLManipRotate::handleDeselect()
 	mManipPart = LL_NO_PART;
 
 	gFloaterTools->setStatusText("");
+	LLManip::handleDeselect();
 }
 
 void LLManipRotate::render()
@@ -108,7 +109,7 @@ void LLManipRotate::render()
 	LLGLEnable gls_alpha_test(GL_ALPHA_TEST);
 	
 	// You can rotate if you can move
-	LLViewerObject* first_object = gSelectMgr->getFirstMoveableObject(TRUE);
+	LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE);
 	if( !first_object )
 	{
 		return;
@@ -121,7 +122,7 @@ void LLManipRotate::render()
 
 	glMatrixMode(GL_MODELVIEW);
 	glPushMatrix();
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 		glScalef(zoom, zoom, zoom);
@@ -339,7 +340,7 @@ BOOL LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	BOOL	handled = FALSE;
 
-	LLViewerObject* first_object = gSelectMgr->getFirstMoveableObject(TRUE);
+	LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE);
 	if( first_object )
 	{
 		LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
@@ -355,10 +356,10 @@ BOOL LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask)
 // Assumes that one of the parts of the manipulator was hit.
 BOOL LLManipRotate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
 {
-	BOOL can_rotate = gSelectMgr->getObjectCount() != 0;
-	for (LLViewerObject* objectp = gSelectMgr->getFirstObject();
+	BOOL can_rotate = mObjectSelection->getObjectCount() != 0;
+	for (LLViewerObject* objectp = mObjectSelection->getFirstObject();
 		objectp;
-		objectp = gSelectMgr->getNextObject())
+		objectp = mObjectSelection->getNextObject())
 	{
 		can_rotate = can_rotate && objectp->permMove() && (objectp->permModify() || gSavedSettings.getBOOL("SelectLinkedSet"));
 	}
@@ -463,7 +464,7 @@ BOOL LLManipRotate::handleHover(S32 x, S32 y, MASK mask)
 {
 	if( hasMouseCapture() )
 	{
-		if( gSelectMgr->isEmpty() )
+		if( mObjectSelection->isEmpty() )
 		{
 			// Somehow the object got deselected while we were dragging it.
 			setMouseCapture( FALSE );
@@ -531,7 +532,7 @@ void LLManipRotate::drag( S32 x, S32 y )
 	LLSelectNode* selectNode;
 	BOOL using_linked_selection = gSavedSettings.getBOOL("SelectLinkedSet");
 
-	for( selectNode = gSelectMgr->getFirstNode(); selectNode != NULL; selectNode = gSelectMgr->getNextNode() )
+	for( selectNode = mObjectSelection->getFirstNode(); selectNode != NULL; selectNode = mObjectSelection->getNextNode() )
 	{
 		object = selectNode->getObject();
 
@@ -603,7 +604,7 @@ void LLManipRotate::drag( S32 x, S32 y )
 	}
 
 	// update positions
-	for( selectNode = gSelectMgr->getFirstNode(); selectNode != NULL; selectNode = gSelectMgr->getNextNode() )
+	for( selectNode = mObjectSelection->getFirstNode(); selectNode != NULL; selectNode = mObjectSelection->getNextNode() )
 	{
 		object = selectNode->getObject();
 		
@@ -766,7 +767,7 @@ void LLManipRotate::renderSnapGuides()
 
 	LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
 	LLVector3 cam_at_axis;
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		cam_at_axis.setVec(1.f, 0.f, 0.f);
 	}
@@ -780,7 +781,7 @@ void LLManipRotate::renderSnapGuides()
 	LLVector3 test_axis = constraint_axis;
 
 	BOOL constrain_to_ref_object = FALSE;
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
 	{
 		test_axis = test_axis * ~grid_rotation;
 	}
@@ -807,7 +808,7 @@ void LLManipRotate::renderSnapGuides()
 	}
 
 	LLVector3 projected_snap_axis = world_snap_axis;
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
 	{
 		projected_snap_axis = projected_snap_axis * grid_rotation;
 	}
@@ -947,32 +948,32 @@ void LLManipRotate::renderSnapGuides()
 					{
 						if (i == 0)
 						{
-							renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Forward" : "East", LLColor4::white);
+							renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white);
 						}
 						else if (i == 16)
 						{
 							if (constraint_axis.mV[VZ] > 0.f)
 							{
-								renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Left" : "North", LLColor4::white);
+								renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white);
 							}
 							else
 							{
-								renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Right" : "South", LLColor4::white);
+								renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white);
 							}
 						}
 						else if (i == 32)
 						{
-							renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Back" : "West", LLColor4::white);
+							renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white);
 						}
 						else
 						{
 							if (constraint_axis.mV[VZ] > 0.f)
 							{
-								renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Right" : "South", LLColor4::white);
+								renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white);
 							}
 							else
 							{
-								renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Left" : "North", LLColor4::white);
+								renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white);
 							}
 						}
 					}
@@ -980,7 +981,7 @@ void LLManipRotate::renderSnapGuides()
 					{
 						if (i == 0)
 						{
-							renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Left" : "North", LLColor4::white);
+							renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white);
 						}
 						else if (i == 16)
 						{
@@ -995,7 +996,7 @@ void LLManipRotate::renderSnapGuides()
 						}
 						else if (i == 32)
 						{
-							renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Right" : "South", LLColor4::white);
+							renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white);
 						}
 						else
 						{
@@ -1019,11 +1020,11 @@ void LLManipRotate::renderSnapGuides()
 						{
 							if (constraint_axis.mV[VY] > 0.f)
 							{
-								renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Forward" : "East", LLColor4::white);
+								renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white);
 							}
 							else
 							{
-								renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Back" : "West", LLColor4::white);
+								renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white);
 							}
 						}
 						else if (i == 32)
@@ -1034,11 +1035,11 @@ void LLManipRotate::renderSnapGuides()
 						{
 							if (constraint_axis.mV[VY] > 0.f)
 							{
-								renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Back" : "West", LLColor4::white);
+								renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white);
 							}
 							else
 							{
-								renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Forward" : "East", LLColor4::white);
+								renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white);
 							}
 						}
 					}
@@ -1053,7 +1054,7 @@ void LLManipRotate::renderSnapGuides()
 				getObjectAxisClosestToMouse(object_axis);
 
 				// project onto constraint plane
-				LLSelectNode* first_node = gSelectMgr->getFirstMoveableNode(TRUE);
+				LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE);
 				object_axis = object_axis * first_node->getObject()->getRenderRotation();
 				object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
 				object_axis.normVec();
@@ -1137,7 +1138,7 @@ BOOL LLManipRotate::updateVisiblity()
 	BOOL visible = FALSE;
 
 	LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		mCenterToCam = LLVector3(-1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f);
 		mCenterToCamNorm = mCenterToCam;
@@ -1246,7 +1247,7 @@ LLQuaternion LLManipRotate::dragUnconstrained( S32 x, S32 y )
 		F32 angle = (-1.f + dist_to_intersection / dist_to_tangent_point) * in_sphere_angle;
 
 		LLVector3 axis;
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			axis = LLVector3(-1.f, 0.f, 0.f) % profile_center_to_intersection;
 		}
@@ -1289,7 +1290,7 @@ LLVector3 LLManipRotate::getConstraintAxis()
 
 		gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
 
-		LLSelectNode* first_node = gSelectMgr->getFirstMoveableNode(TRUE);
+		LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE);
 		if (first_node)
 		{
 			// *FIX: get agent local attachment grid working
@@ -1303,7 +1304,7 @@ LLVector3 LLManipRotate::getConstraintAxis()
 
 LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
 {
-	LLSelectNode* first_object_node = gSelectMgr->getFirstMoveableNode(TRUE);
+	LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE);
 	LLVector3 constraint_axis = getConstraintAxis();
 	LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter );
 
@@ -1320,7 +1321,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
 	LLVector3 axis2;
 
 	LLVector3 test_axis = constraint_axis;
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
 	{
 		test_axis = test_axis * ~grid_rotation;
 	}
@@ -1344,7 +1345,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
 		axis1 = LLVector3::x_axis;
 	}
 
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
 	{
 		axis1 = axis1 * grid_rotation;
 	}
@@ -1366,7 +1367,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
 		// We're looking at the ring edge-on.
 		LLVector3 snap_plane_center = (center + (constraint_axis * mRadiusMeters * 0.5f));
 		LLVector3 cam_to_snap_plane;
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			cam_to_snap_plane.setVec(1.f, 0.f, 0.f);
 		}
@@ -1416,7 +1417,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
 		{
 			// try other plane
 			snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f));
-			if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+			if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 			{
 				cam_to_snap_plane.setVec(1.f, 0.f, 0.f);
 			}
@@ -1463,7 +1464,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y )
 		if (snap_plane > 0)
 		{
 			LLVector3 cam_at_axis;
-			if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+			if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 			{
 				cam_at_axis.setVec(1.f, 0.f, 0.f);
 			}
@@ -1661,9 +1662,10 @@ LLVector3 LLManipRotate::intersectRayWithSphere( const LLVector3& ray_pt, const
 }
 
 // Utility function.  Should probably be moved to another class.
+//static
 void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_dir )
 {
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (gSelectMgr->getSelection()->getSelectType() == SELECT_TYPE_HUD)
 	{
 		F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
 		F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom;
@@ -1685,7 +1687,7 @@ void LLManipRotate::highlightManipulators( S32 x, S32 y )
 	mHighlightedPart = LL_NO_PART;
 
 	//LLBBox bbox = gSelectMgr->getBBoxOfSelection();
-	LLViewerObject *first_object = gSelectMgr->getFirstMoveableObject(TRUE);
+	LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE);
 	
 	if (!first_object)
 	{
@@ -1821,7 +1823,7 @@ void LLManipRotate::highlightManipulators( S32 x, S32 y )
 
 S32 LLManipRotate::getObjectAxisClosestToMouse(LLVector3& object_axis)
 {
-	LLSelectNode* first_object_node = gSelectMgr->getFirstMoveableNode(TRUE);
+	LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE);
 
 	if (!first_object_node)
 	{
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 2b5926514e3f73e95d9023cbadc7fab01e1a3d8c..cec8ff0b13c1f0bab301b808602a3435b085b093 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -140,6 +140,7 @@ void LLManipScale::handleSelect()
 	updateSnapGuides(bbox);
 	gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
 	gFloaterTools->setStatusText("Click and drag to stretch selected side");
+	LLManip::handleSelect();
 }
 
 void LLManipScale::handleDeselect()
@@ -147,6 +148,7 @@ void LLManipScale::handleDeselect()
 	mHighlightedPart = LL_NO_PART;
 	mManipPart = LL_NO_PART;
 	gFloaterTools->setStatusText("");
+	LLManip::handleDeselect();
 }
 
 BOOL sort_manip_by_z(LLManipScale::ManipulatorHandle *new_manip, LLManipScale::ManipulatorHandle *test_manip)
@@ -196,7 +198,7 @@ void LLManipScale::render()
 	{
 		glMatrixMode(GL_MODELVIEW);
 		glPushMatrix();
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 			glScalef(zoom, zoom, zoom);
@@ -212,7 +214,7 @@ void LLManipScale::render()
 
 		F32 range;
 		F32 range_from_agent;
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) gCamera->getViewHeightInPixels();
 			mBoxHandleSize /= gAgent.getAvatarObject()->mHUDCurZoom;
@@ -311,10 +313,10 @@ BOOL LLManipScale::handleMouseDown(S32 x, S32 y, MASK mask)
 // Assumes that one of the arrows on an object was hit.
 BOOL LLManipScale::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
 {
-	BOOL can_scale = gSelectMgr->getObjectCount() != 0;
-	for (LLViewerObject* objectp = gSelectMgr->getFirstObject();
+	BOOL can_scale = mObjectSelection->getObjectCount() != 0;
+	for (LLViewerObject* objectp = mObjectSelection->getFirstObject();
 		objectp;
-		objectp = gSelectMgr->getNextObject())
+		objectp = mObjectSelection->getNextObject())
 	{
 		can_scale = can_scale && objectp->permModify() && objectp->permMove() && !objectp->isSeat();
 	}
@@ -377,7 +379,7 @@ BOOL LLManipScale::handleHover(S32 x, S32 y, MASK mask)
 {
 	if( hasMouseCapture() )
 	{
-		if( gSelectMgr->isEmpty() )
+		if( mObjectSelection->isEmpty() )
 		{
 			// Somehow the object got deselected while we were dragging it.
 			setMouseCapture( FALSE );
@@ -413,7 +415,7 @@ void LLManipScale::highlightManipulators(S32 x, S32 y)
 	if( isSelectionScalable() )
 	{
 		LLMatrix4 transform;
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			LLVector4 translation(bbox.getPositionAgent());
 			transform.initRotTrans(bbox.getRotation(), translation);
@@ -454,7 +456,7 @@ void LLManipScale::highlightManipulators(S32 x, S32 y)
 		mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], max.mV[VY], max.mV[VZ], 1.f);
 		
 		// 1-D highlights are applicable iff one object is selected
-		if( gSelectMgr->getObjectCount() == 1 )
+		if( mObjectSelection->getObjectCount() == 1 )
 		{
 			// face centers
 			mManipulatorVertices[numManips++] = LLVector4(ctr.mV[VX], ctr.mV[VY], max.mV[VZ], 1.f);
@@ -520,7 +522,7 @@ void LLManipScale::renderFaces( const LLBBox& bbox )
 {
 	// Don't bother to render the drag handles for 1-D scaling if 
 	// more than one object is selected or if it is an attachment
-	if ( gSelectMgr->getObjectCount() > 1 )
+	if ( mObjectSelection->getObjectCount() > 1 )
 	{
 		return;
 	}
@@ -926,7 +928,7 @@ void LLManipScale::dragCorner( S32 x, S32 y )
 
 	// find max and min scale factors that will make biggest object hit max absolute scale and smallest object hit min absolute scale
 	LLSelectNode* selectNode;
-	for( selectNode = gSelectMgr->getFirstNode(); selectNode; selectNode = gSelectMgr->getNextNode() )
+	for( selectNode = mObjectSelection->getFirstNode(); selectNode; selectNode = mObjectSelection->getNextNode() )
 	{
 		LLViewerObject* cur = selectNode->getObject();
 		if(  cur->permModify() && cur->permMove() && !cur->isAvatar() )
@@ -946,7 +948,7 @@ void LLManipScale::dragCorner( S32 x, S32 y )
 	LLVector3d drag_global = uniform ? mDragStartCenterGlobal : mDragFarHitGlobal;
 
 	// do the root objects i.e. (TRUE == cur->isRootEdit())
-	for( selectNode = gSelectMgr->getFirstNode(); selectNode; selectNode = gSelectMgr->getNextNode() )
+	for( selectNode = mObjectSelection->getFirstNode(); selectNode; selectNode = mObjectSelection->getNextNode() )
 	{
 		LLViewerObject* cur = selectNode->getObject();
 		if( cur->permModify() && cur->permMove() && !cur->isAvatar() && cur->isRootEdit() )
@@ -990,7 +992,7 @@ void LLManipScale::dragCorner( S32 x, S32 y )
 		}
 	}
 	// do the child objects i.e. (FALSE == cur->isRootEdit())
-	for( selectNode = gSelectMgr->getFirstNode(); selectNode; selectNode = gSelectMgr->getNextNode() )
+	for( selectNode = mObjectSelection->getFirstNode(); selectNode; selectNode = mObjectSelection->getNextNode() )
 	{
 		LLViewerObject*cur = selectNode->getObject();
 		if( cur->permModify() && cur->permMove() && !cur->isAvatar() && !cur->isRootEdit() )
@@ -1209,7 +1211,7 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto
 	LLVector3 drag_start_center_agent = gAgent.getPosAgentFromGlobal(mDragStartCenterGlobal);
 
 	LLSelectNode *selectNode;
-	for( selectNode = gSelectMgr->getFirstNode(); selectNode; selectNode = gSelectMgr->getNextNode() )
+	for( selectNode = mObjectSelection->getFirstNode(); selectNode; selectNode = mObjectSelection->getNextNode() )
 	{
 		LLViewerObject*cur = selectNode->getObject();
 		if( cur->permModify() && cur->permMove() && !cur->isAvatar() )
@@ -1330,7 +1332,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox)
 	mScaleDir = box_corner_agent - mScaleCenter;
 	mScaleDir.normVec();
 
-	if(gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if(mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		mSnapRegimeOffset = SNAP_GUIDE_SCREEN_OFFSET / gAgent.getAvatarObject()->mHUDCurZoom;
 
@@ -1342,7 +1344,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox)
 	}
 	LLVector3 cam_at_axis;
 	F32 snap_guide_length;
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		cam_at_axis.setVec(1.f, 0.f, 0.f);
 		snap_guide_length = SNAP_GUIDE_SCREEN_LENGTH / gAgent.getAvatarObject()->mHUDCurZoom;
@@ -1389,7 +1391,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox)
 	{
 		LLVector3 local_scale_dir = partToUnitVector( mManipPart );
 		LLVector3 local_camera_dir;
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			local_camera_dir = LLVector3(-1.f, 0.f, 0.f) * ~bbox.getRotation();
 		}
@@ -1668,7 +1670,7 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
 		start_tick = -(llmin(ticks_from_scale_center_1, num_ticks_per_side1));
 		stop_tick = llmin(max_ticks1, num_ticks_per_side1);
 
-		F32 grid_resolution = gSelectMgr->getSelectType() == SELECT_TYPE_HUD ? 0.25f : llmax(gSavedSettings.getF32("GridResolution"), 0.001f);
+		F32 grid_resolution = mObjectSelection->getSelectType() == SELECT_TYPE_HUD ? 0.25f : llmax(gSavedSettings.getF32("GridResolution"), 0.001f);
 		S32 label_sub_div_offset_1 = llround(fmod(dist_grid_axis - grid_offset1, mScaleSnapUnit1  * 32.f) / (mScaleSnapUnit1 / max_subdivisions));
 		S32 label_sub_div_offset_2 = llround(fmod(dist_grid_axis - grid_offset2, mScaleSnapUnit2  * 32.f) / (mScaleSnapUnit2 / max_subdivisions));
 
@@ -1774,7 +1776,7 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
 
 
 		// render help text
-		if (gSelectMgr->getSelectType() != SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
 		{
 			if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText)
 			{
@@ -1796,10 +1798,10 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
 				std::string help_text = "Move mouse cursor over ruler";
 				LLColor4 help_text_color = LLColor4::white;
 				help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, grid_alpha, 0.f);
-				hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
+				hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
 				help_text = "to snap to grid";
 				help_text_pos -= gCamera->getUpAxis() * mSnapRegimeOffset * 0.4f;
-				hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
+				hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
 			}
 		}
 	}
@@ -2003,14 +2005,16 @@ LLVector3 LLManipScale::nearestAxis( const LLVector3& v ) const
 	return LLVector3( coords[greatest_index] );
 }
 
-BOOL LLManipScale::isSelectionScalable() const
+//FIXME: make this const once we switch to iterator interface 
+//(making object traversal a const-able operation)
+BOOL LLManipScale::isSelectionScalable()
 {
 	// An selection is scalable if you are allowed to both edit and move 
 	// everything in it, and it does not have any sitting agents
-	BOOL scalable = gSelectMgr->getFirstObject() ? TRUE : FALSE;
-	for(LLViewerObject* cur = gSelectMgr->getFirstObject(); 
+	BOOL scalable = mObjectSelection->getFirstObject() ? TRUE : FALSE;
+	for(LLViewerObject* cur = mObjectSelection->getFirstObject(); 
 		cur; 
-		cur = gSelectMgr->getNextObject() )
+		cur = mObjectSelection->getNextObject() )
 	{
 		if( !(cur->permModify() && cur->permMove())
 			|| cur->isSeat())
diff --git a/indra/newview/llmanipscale.h b/indra/newview/llmanipscale.h
index 0ba141cc0142abdfb4363edea24589bb7cf216ac..af6fb91b15afd4aad52bc0de7b70d3729feb7403 100644
--- a/indra/newview/llmanipscale.h
+++ b/indra/newview/llmanipscale.h
@@ -94,7 +94,7 @@ class LLManipScale : public LLManip
 	F32				partToMinScale( S32 part, const LLBBox& bbox ) const;
 	LLVector3		nearestAxis( const LLVector3& v ) const;
 
-	BOOL			isSelectionScalable() const;
+	BOOL			isSelectionScalable();
 
 	void			stretchFace( const LLVector3& drag_start_agent, const LLVector3& drag_delta_agent);
 
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index b1a9b067206f47339794835a1090e68319baa420..f308eb9f5c0ffc7c24819b472db2fbbb26a85834 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -238,6 +238,7 @@ void LLManipTranslate::handleSelect()
 {
 	gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
 	gFloaterTools->setStatusText("Drag to move, shift-drag to copy");
+	LLManip::handleSelect();
 }
 
 void LLManipTranslate::handleDeselect()
@@ -245,6 +246,7 @@ void LLManipTranslate::handleDeselect()
 	mHighlightedPart = LL_NO_PART;
 	mManipPart = LL_NO_PART;
 	gFloaterTools->setStatusText("");
+	LLManip::handleDeselect();
 }
 
 BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -270,10 +272,10 @@ BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask)
 // Assumes that one of the arrows on an object was hit.
 BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
 {
-	BOOL can_move = gSelectMgr->getObjectCount() != 0;
-	for (LLViewerObject* objectp = gSelectMgr->getFirstObject();
+	BOOL can_move = mObjectSelection->getObjectCount() != 0;
+	for (LLViewerObject* objectp = mObjectSelection->getFirstObject();
 		objectp;
-		objectp = gSelectMgr->getNextObject())
+		objectp = mObjectSelection->getNextObject())
 	{
 		can_move = can_move && objectp->permMove() && (objectp->permModify() || gSavedSettings.getBOOL("SelectLinkedSet"));
 	}
@@ -313,7 +315,7 @@ BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask )
 
 	LLVector3		axis;
 
-	LLSelectNode *selectNode = gSelectMgr->getFirstMoveableNode(TRUE);
+	LLSelectNode *selectNode = mObjectSelection->getFirstMoveableNode(TRUE);
 
 	if (!selectNode)
 	{
@@ -388,7 +390,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
 	BOOL rotated = FALSE;
 
 	// ...build mode moves camera about focus point
-	if (gSelectMgr->getSelectType() != SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
 	{
 		if (x < ROTATE_H_MARGIN)
 		{
@@ -452,7 +454,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
 
 	// pick the first object to constrain to grid w/ common origin
 	// this is so we don't screw up groups
-	LLSelectNode* selectNode = gSelectMgr->getFirstMoveableNode(TRUE);
+	LLSelectNode* selectNode = mObjectSelection->getFirstMoveableNode(TRUE);
 	if (!selectNode)
 	{
 		// somehow we lost the object!
@@ -624,9 +626,9 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask)
 	LLVector3d clamped_relative_move = axis_magnitude * axis_d;	// scalar multiply
 	LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply
 	
-	for(selectNode = gSelectMgr->getFirstNode(); 
+	for(selectNode = mObjectSelection->getFirstNode(); 
 		selectNode; 
-		selectNode = gSelectMgr->getNextNode() )
+		selectNode = mObjectSelection->getNextNode() )
 	{
 		object = selectNode->getObject();
 
@@ -792,7 +794,7 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
 {
 	mHighlightedPart = LL_NO_PART;
 
-	if (!gSelectMgr->getObjectCount())
+	if (!mObjectSelection->getObjectCount())
 	{
 		return;
 	}
@@ -813,7 +815,7 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y)
 
 	LLMatrix4 transform;
 
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation;
 		LLVector4 translation(object_position);
@@ -1060,7 +1062,7 @@ void LLManipTranslate::render()
 {
 	glMatrixMode(GL_MODELVIEW);
 	glPushMatrix();
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 		glScalef(zoom, zoom, zoom);
@@ -1098,7 +1100,7 @@ void LLManipTranslate::renderSnapGuides()
 		return;
 	}
 
-	LLSelectNode *first_node = gSelectMgr->getFirstMoveableNode(TRUE);
+	LLSelectNode *first_node = mObjectSelection->getFirstMoveableNode(TRUE);
 	if (!first_node)
 	{
 		return;
@@ -1123,7 +1125,7 @@ void LLManipTranslate::renderSnapGuides()
 		getManipAxis(first_object, mManipPart, translate_axis);
 
 		LLVector3 at_axis_abs;
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			at_axis_abs = LLVector3::x_axis * ~grid_rotation;
 		}
@@ -1198,7 +1200,7 @@ void LLManipTranslate::renderSnapGuides()
 
 		F32 guide_size_meters;
 
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			guide_size_meters = 1.f / gAgent.getAvatarObject()->mHUDCurZoom;
 			mSnapOffsetMeters = mArrowLengthMeters * 1.5f;
@@ -1400,7 +1402,7 @@ void LLManipTranslate::renderSnapGuides()
 				}
 			}
 		}
-		if (gSelectMgr->getSelectType() != SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
 		{
 			// render helpful text
 			if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText)
@@ -1424,10 +1426,10 @@ void LLManipTranslate::renderSnapGuides()
 				std::string help_text = "Move mouse cursor over ruler to snap";
 				LLColor4 help_text_color = LLColor4::white;
 				help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f);
-				hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
+				hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
 				help_text = "to snap to grid";
 				help_text_pos -= gCamera->getUpAxis() * mSnapOffsetMeters * 0.2f;
-				hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
+				hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD);
 			}
 		}
 	}
@@ -1592,17 +1594,17 @@ void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F
 
 void LLManipTranslate::renderText()
 {
-	if (gSelectMgr->getRootObjectCount() && !gSelectMgr->selectionIsAttachment())
+	if (mObjectSelection->getRootObjectCount() && !mObjectSelection->isAttachment())
 	{
 		LLVector3 pos = getPivotPoint();
 		renderXYZ(pos);
 	}
 	else
 	{
-		LLViewerObject* objectp = gSelectMgr->getFirstRootObject();
+		LLViewerObject* objectp = mObjectSelection->getFirstRootObject();
 		if(!objectp)
 		{
-			objectp = gSelectMgr->getFirstObject();
+			objectp = mObjectSelection->getFirstObject();
 		}
 
 		if (objectp)
@@ -1621,7 +1623,7 @@ void LLManipTranslate::renderTranslationHandles()
 	
 	gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale);
 	LLVector3 at_axis;
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		at_axis = LLVector3::x_axis * ~grid_rotation;
 	}
@@ -1657,13 +1659,13 @@ void LLManipTranslate::renderTranslationHandles()
 		mPlaneManipPositions.mV[VZ] = -1.f;
 	}
 
-	LLViewerObject *first_object = gSelectMgr->getFirstMoveableObject(TRUE);
+	LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE);
 	if (!first_object) return;
 
 	LLVector3 selection_center = getPivotPoint();
 
 	// Drag handles 	
-	if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 	{
 		mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWindowHeight();
 		mArrowLengthMeters /= gAgent.getAvatarObject()->mHUDCurZoom;
@@ -1716,7 +1718,7 @@ void LLManipTranslate::renderTranslationHandles()
 
 		LLVector3 relative_camera_dir;
 		
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+		if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 		{
 			relative_camera_dir = LLVector3::x_axis * invRotation;
 		}
@@ -1988,7 +1990,7 @@ void LLManipTranslate::renderTranslationHandles()
 
 			// draw arrows for deeper faces first, closer faces last
 			LLVector3 camera_axis;
-			if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+			if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
 			{
 				camera_axis = LLVector3::x_axis;
 			}
diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp
index 848a9c26ae6cfdea418d411f4cbc2293a94d80a0..4c76e7491b456b08c81f88ac70dbf8e7e534360c 100644
--- a/indra/newview/llpanelcontents.cpp
+++ b/indra/newview/llpanelcontents.cpp
@@ -96,8 +96,8 @@ void LLPanelContents::getState(LLViewerObject *objectp )
 	// unambiguous destination for the object.
 	if(	editable && 
 		all_volume && 
-		((gSelectMgr->getRootObjectCount() == 1)
-					|| (gSelectMgr->getObjectCount() == 1)))
+		((gSelectMgr->getSelection()->getRootObjectCount() == 1)
+					|| (gSelectMgr->getSelection()->getObjectCount() == 1)))
 	{
 		//mBtnNewScript->setEnabled(TRUE);
 		childSetEnabled("button new script",TRUE);
@@ -112,10 +112,10 @@ void LLPanelContents::getState(LLViewerObject *objectp )
 
 void LLPanelContents::refresh()
 {
-	LLViewerObject* object = gSelectMgr->getFirstRootObject();
+	LLViewerObject* object = gSelectMgr->getSelection()->getFirstRootObject();
 	if(!object)
 	{
-		object = gSelectMgr->getFirstObject();
+		object = gSelectMgr->getSelection()->getFirstObject();
 	}
 
 	getState(object);
@@ -134,10 +134,10 @@ void LLPanelContents::refresh()
 // static
 void LLPanelContents::onClickNewScript(void *userdata)
 {
-	LLViewerObject* object = gSelectMgr->getFirstRootObject();
+	LLViewerObject* object = gSelectMgr->getSelection()->getFirstRootObject();
 	if(!object)
 	{
-		object = gSelectMgr->getFirstObject();
+		object = gSelectMgr->getSelection()->getFirstObject();
 	}
 	if(object)
 	{
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index d9ef9e4c133aa071cd06bca6ae9f15a0a6ea62bc..cdcaed43f97aa8514be7a89de7de0b2991dfb8d4 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -238,7 +238,8 @@ void LLPanelFace::sendTextureInfo()
 {
 	S32 te;
 	LLViewerObject* object;
-	for ( gSelectMgr->getFirstTE(&object, &te); object; gSelectMgr->getNextTE(&object, &te) )
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	for ( selection->getFirstTE(&object, &te); object; selection->getNextTE(&object, &te) )
 	{
 		BOOL valid;
 		F32 value;
@@ -317,7 +318,7 @@ void LLPanelFace::sendTextureInfo()
 		}
 	}
 
-	for ( object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() )
+	for ( object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() )
 	{
 		object->sendTEUpdate();
 	}
@@ -325,7 +326,7 @@ void LLPanelFace::sendTextureInfo()
 
 void LLPanelFace::getState()
 {
-	LLViewerObject* objectp = gSelectMgr->getFirstObject();
+	LLViewerObject* objectp = gSelectMgr->getSelection()->getFirstObject();
 
 	if( objectp
 		&& objectp->getPCode() == LL_PCODE_VOLUME)
@@ -600,7 +601,7 @@ BOOL LLPanelFace::allFacesSameValue( F32 (get_face_value(LLViewerObject*, S32)),
 	// Get the value from the primary selected TE
 	F32 first_value = *value;
 	BOOL got_first = FALSE;
-	gSelectMgr->getPrimaryTE(&object, &te);
+	gSelectMgr->getSelection()->getPrimaryTE(&object, &te);
 	if (object)
 	{
 		first_value = get_face_value(object, te);
@@ -609,7 +610,8 @@ BOOL LLPanelFace::allFacesSameValue( F32 (get_face_value(LLViewerObject*, S32)),
 
 	// Now iterate through all TEs to test for sameness
 	BOOL identical = TRUE;
-	for ( gSelectMgr->getFirstTE(&object, &te); object; gSelectMgr->getNextTE(&object, &te) )
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	for ( selection->getFirstTE(&object, &te); object; selection->getNextTE(&object, &te) )
 	{
 		if (!got_first)
 		{
@@ -760,13 +762,13 @@ void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata)
 BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item, void*)
 {
 	BOOL accept = TRUE;
-	LLViewerObject* obj = gSelectMgr->getFirstRootObject();
+	LLViewerObject* obj = gSelectMgr->getSelection()->getFirstRootObject();
 	while(accept && obj)
 	{
 		if(!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item))
 			accept = FALSE;
 		else
-			obj = gSelectMgr->getNextRootObject();
+			obj = gSelectMgr->getSelection()->getNextRootObject();
 	}
 	return accept;
 }
@@ -823,7 +825,8 @@ void LLPanelFace::onClickAutoFix(void* userdata)
 	LLViewerObject* object;
 
 	// for all selected objects
-	for ( gSelectMgr->getFirstTE(&object, &te); object; gSelectMgr->getNextTE(&object, &te) )
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	for ( selection->getFirstTE(&object, &te); object; selection->getNextTE(&object, &te) )
 	{
 		// only do this if it's a media texture
 		if ( object->getTE ( te )->getID() ==  LLMediaEngine::getInstance()->getImageUUID () )
@@ -848,7 +851,7 @@ void LLPanelFace::onClickAutoFix(void* userdata)
 	};
 
 	// not clear why this is in a separate loop but i followed the patter from further up this file just in case.
-	for ( object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() )
+	for ( object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() )
 	{
 		object->sendTEUpdate();
 	};
diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp
index 1a8885d05b8a17784fa54ba35a33f925b5ba0351..9363b98d120d13108fadb9acf16ef10d78c11551 100644
--- a/indra/newview/llpanelland.cpp
+++ b/indra/newview/llpanelland.cpp
@@ -90,7 +90,7 @@ void LLPanelLandInfo::refreshAll()
 // public
 void LLPanelLandInfo::refresh()
 {
-	LLParcel *parcel = gParcelMgr->getSelectedParcel();
+	LLParcel *parcel = gParcelMgr->getParcelSelection()->getParcel();
 	LLViewerRegion *regionp = gParcelMgr->getSelectionRegion();
 
 	if (!parcel || !regionp)
@@ -158,7 +158,7 @@ void LLPanelLandInfo::refresh()
 		// and it must not be a whole parcel.
 		if (gParcelMgr->getSelectedArea() > PARCEL_UNIT_AREA
 			//&& gParcelMgr->getSelfCount() > 1
-			&& !gParcelMgr->getWholeParcelSelected())
+			&& !gParcelMgr->getParcelSelection()->getWholeParcelSelected())
 		{
 			childSetEnabled("button join land",TRUE);
 		}
@@ -181,7 +181,7 @@ void LLPanelLandInfo::refresh()
 								   &rent_price,
 								   &for_sale,
 								   &dwell);
-		if(is_public || (is_for_sale && gParcelMgr->getWholeParcelSelected()))
+		if(is_public || (is_for_sale && gParcelMgr->getParcelSelection()->getWholeParcelSelected()))
 		{
 			childSetTextArg("label_area_price","[PRICE]", llformat("%d",claim_price));
 			childSetTextArg("label_area_price","[AREA]", llformat("%d",area));
@@ -227,7 +227,7 @@ void LLPanelLandInfo::onClickJoin(void*)
 void LLPanelLandInfo::onClickAbout(void*)
 {
 	// Promote the rectangle selection to a parcel selection
-	if (!gParcelMgr->getWholeParcelSelected())
+	if (!gParcelMgr->getParcelSelection()->getWholeParcelSelected())
 	{
 		gParcelMgr->selectParcelInRectangle();
 	}
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index ac50425e67005c44be1d793a2f7e3734eda28116..39d77c630b62087f29da4090087bbcb1ba159193 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -256,11 +256,11 @@ LLPanelObject::~LLPanelObject()
 
 void LLPanelObject::getState( )
 {
-	LLViewerObject* objectp = gSelectMgr->getFirstRootObject();
+	LLViewerObject* objectp = gSelectMgr->getSelection()->getFirstRootObject();
 	LLViewerObject* root_objectp = objectp;
 	if(!objectp)
 	{
-		objectp = gSelectMgr->getFirstObject();
+		objectp = gSelectMgr->getSelection()->getFirstObject();
 		// *FIX: shouldn't we just keep the child?
 		if (objectp)
 		{
@@ -372,9 +372,9 @@ void LLPanelObject::getState( )
 	owners_identical = gSelectMgr->selectGetOwner(owner_id, owner_name);
 
 	// BUG? Check for all objects being editable?
-	S32 roots_selected = gSelectMgr->getRootObjectCount();
+	S32 roots_selected = gSelectMgr->getSelection()->getRootObjectCount();
 	BOOL editable = root_objectp->permModify();
-	S32 selected_count = gSelectMgr->getObjectCount();
+	S32 selected_count = gSelectMgr->getSelection()->getObjectCount();
 	BOOL single_volume = (gSelectMgr->selectionAllPCode( LL_PCODE_VOLUME ))
 						 && (selected_count == 1);
 
@@ -1506,7 +1506,7 @@ void LLPanelObject::draw()
 	const LLColor4	blue(	0.f,	0.5f,	1.0f,	1);
 
 	// Tune the colors of the labels
-	LLTool* tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) );
+	LLTool* tool = gToolMgr->getCurrentTool();
 
 	if (tool == gToolTranslate)
 	{
@@ -1626,7 +1626,7 @@ void LLPanelObject::onCommitLock(LLUICtrl *ctrl, void *data)
 
 	BOOL new_state = self->mCheckLock->get();
 	
-	gSelectMgr->setObjectPermissions(PERM_OWNER, !new_state, PERM_MOVE | PERM_MODIFY);
+	gSelectMgr->selectionSetObjectPermissions(PERM_OWNER, !new_state, PERM_MOVE | PERM_MODIFY);
 }
 
 // static
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index 332d22ade62a5694cf0a95a9e5c4ae7444b9a1bc..155e178a5e80777e1ad6e7fde76130db58f1911e 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -128,16 +128,16 @@ void LLPanelPermissions::refresh()
 		BtnDeedToGroup->setLabelUnselected(deedText);
 	}
 	BOOL root_selected = TRUE;
-	LLSelectNode* nodep = gSelectMgr->getFirstRootNode();
-	S32 object_count = gSelectMgr->getRootObjectCount();
+	LLSelectNode* nodep = gSelectMgr->getSelection()->getFirstRootNode();
+	S32 object_count = gSelectMgr->getSelection()->getRootObjectCount();
 	if(!nodep || 0 == object_count)
 	{
-		nodep = gSelectMgr->getFirstNode();
-		object_count = gSelectMgr->getObjectCount();
+		nodep = gSelectMgr->getSelection()->getFirstNode();
+		object_count = gSelectMgr->getSelection()->getObjectCount();
 		root_selected = FALSE;
 	}
 
-	//BOOL attachment_selected = gSelectMgr->selectionIsAttachment();
+	//BOOL attachment_selected = gSelectMgr->getSelection()->isAttachment();
 	//attachment_selected = false;
 	LLViewerObject* objectp = NULL;
 	if(nodep) objectp = nodep->getObject();
@@ -230,7 +230,7 @@ void LLPanelPermissions::refresh()
 	BOOL is_one_object = (object_count == 1);
 
 	// BUG: fails if a root and non-root are both single-selected.
-	BOOL is_perm_modify = (gSelectMgr->getFirstRootNode() 
+	BOOL is_perm_modify = (gSelectMgr->getSelection()->getFirstRootNode() 
 							&& gSelectMgr->selectGetRootsModify()) 
 							|| gSelectMgr->selectGetModify();
 	const LLView* keyboard_focus_view = gFocusMgr.getKeyboardFocus();
@@ -354,8 +354,8 @@ void LLPanelPermissions::refresh()
 
 
 	// Pre-compute object info string
-	S32 prim_count = gSelectMgr->getObjectCount();
-	S32 obj_count = gSelectMgr->getRootObjectCount();
+	S32 prim_count = gSelectMgr->getSelection()->getObjectCount();
+	S32 obj_count = gSelectMgr->getSelection()->getRootObjectCount();
 
 	LLString object_info_string;
 	if (1 == obj_count)
@@ -833,7 +833,7 @@ void LLPanelPermissions::onClickDeedToGroup(void* data)
 // static
 void LLPanelPermissions::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm)
 {
-	LLViewerObject* object = gSelectMgr->getFirstRootObject();
+	LLViewerObject* object = gSelectMgr->getSelection()->getFirstRootObject();
 	if(!object) return;
 
 	// Checkbox will have toggled itself
@@ -841,7 +841,7 @@ void LLPanelPermissions::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32
 	LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
 	BOOL new_state = check->get();
 	
-	gSelectMgr->setObjectPermissions(field, new_state, perm);
+	gSelectMgr->selectionSetObjectPermissions(field, new_state, perm);
 }
 
 // static
@@ -892,8 +892,8 @@ void LLPanelPermissions::onCommitName(LLUICtrl*, void* data)
 	LLLineEditor*	tb = gUICtrlFactory->getLineEditorByName(self,"Object Name");
 	if(tb)
 	{
-		gSelectMgr->setObjectName(tb->getText());
-//		gSelectMgr->setObjectName(self->mLabelObjectName->getText());
+		gSelectMgr->selectionSetObjectName(tb->getText());
+//		gSelectMgr->selectionSetObjectName(self->mLabelObjectName->getText());
 	}
 }
 
@@ -906,7 +906,7 @@ void LLPanelPermissions::onCommitDesc(LLUICtrl*, void* data)
 	LLLineEditor*	le = gUICtrlFactory->getLineEditorByName(self,"Object Description");
 	if(le)
 	{
-		gSelectMgr->setObjectDescription(le->getText());
+		gSelectMgr->selectionSetObjectDescription(le->getText());
 	}
 }
 
@@ -968,7 +968,7 @@ void LLPanelPermissions::setAllSaleInfo()
 	}
 
 	LLSaleInfo sale_info(sale_type, price);
-	gSelectMgr->setObjectSaleInfo(sale_info);
+	gSelectMgr->selectionSetObjectSaleInfo(sale_info);
 
 	// If turned off for-sale, make sure click-action buy is turned
 	// off as well
@@ -1022,7 +1022,7 @@ void LLPanelPermissions::onCommitClickAction(LLUICtrl* ctrl, void*)
 	{
 		// Verify object has script with money() handler
 		LLSelectionPayable payable;
-		bool can_pay = gSelectMgr->applyToObjects(&payable);
+		bool can_pay = gSelectMgr->getSelection()->applyToObjects(&payable);
 		if (!can_pay)
 		{
 			// Warn, but do it anyway.
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index d43513fc541e00908807051a336386e9ee40a53b..508645e22740324337dc7ab97281b0a19675dd3b 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -117,11 +117,11 @@ LLPanelVolume::~LLPanelVolume()
 
 void LLPanelVolume::getState( )
 {
-	LLViewerObject* objectp = gSelectMgr->getFirstRootObject();
+	LLViewerObject* objectp = gSelectMgr->getSelection()->getFirstRootObject();
 	LLViewerObject* root_objectp = objectp;
 	if(!objectp)
 	{
-		objectp = gSelectMgr->getFirstObject();
+		objectp = gSelectMgr->getSelection()->getFirstObject();
 		// *FIX: shouldn't we just keep the child?
 		if (objectp)
 		{
@@ -166,7 +166,7 @@ void LLPanelVolume::getState( )
 	// BUG? Check for all objects being editable?
 	BOOL editable = root_objectp->permModify();
 	BOOL single_volume = gSelectMgr->selectionAllPCode( LL_PCODE_VOLUME )
-		&& gSelectMgr->getObjectCount() == 1;
+		&& gSelectMgr->getSelection()->getObjectCount() == 1;
 
 	// Select Single Message
 	if (single_volume)
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index a2cb01310f38851d2ae3515486db148b03d428e7..7241b939ad2176b68b8047c44fdd8f1edea6a3d7 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -33,6 +33,7 @@
 // Globals and statics
 LLPreview::preview_multimap_t LLPreview::sPreviewsBySource;
 LLPreview::preview_map_t LLPreview::sInstances;
+std::map<LLUUID, LLViewHandle> LLMultiPreview::sAutoOpenPreviewHandles;
 
 // Functions
 LLPreview::LLPreview(const std::string& name) :
@@ -200,11 +201,11 @@ void LLPreview::onCommit()
 					{
 						gSelectMgr->deselectAll();
 						gSelectMgr->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
-						gSelectMgr->setObjectDescription( childGetText("desc") );
+						gSelectMgr->selectionSetObjectDescription( childGetText("desc") );
 					
 						if( has_sale_info )
 						{
-							gSelectMgr->setObjectSaleInfo( sale_info );
+							gSelectMgr->selectionSetObjectSaleInfo( sale_info );
 						}
 
 						gSelectMgr->deselectAll();
@@ -492,3 +493,23 @@ void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)
 		opened_preview->loadAsset();
 	}
 }
+
+//static 
+LLMultiPreview* LLMultiPreview::getAutoOpenInstance(const LLUUID& id)
+{
+	handle_map_t::iterator found_it = sAutoOpenPreviewHandles.find(id);
+	if (found_it != sAutoOpenPreviewHandles.end())
+	{
+		return (LLMultiPreview*)gFloaterView->getFloaterByHandle(found_it->second);	
+	}
+	return NULL;
+}
+
+//static
+void LLMultiPreview::setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id)
+{
+	if (previewp)
+	{
+		sAutoOpenPreviewHandles[id] = previewp->getHandle();
+	}
+}
\ No newline at end of file
diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h
index 6477393267793f2c531dd59bf9106a93bf7e8d2e..ac3f4da9963ba381389785e7b925e51aa28d2ca5 100644
--- a/indra/newview/llpreview.h
+++ b/indra/newview/llpreview.h
@@ -15,7 +15,7 @@
 #include "lluuid.h"
 #include "llviewerinventory.h"
 #include "lltabcontainer.h"
-#include "lllineeditor.h"
+#include <map>
 
 class LLLineEditor;
 class LLRadioGroup;
@@ -28,6 +28,13 @@ class LLMultiPreview : public LLMultiFloater
 
 	/*virtual*/void open();		/*Flawfinder: ignore*/
 	/*virtual*/void tabOpen(LLFloater* opened_floater, bool from_click);
+
+	static LLMultiPreview* getAutoOpenInstance(const LLUUID& id);
+	static void setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id);
+
+protected:
+	typedef std::map<LLUUID, LLViewHandle> handle_map_t;
+	static std::map<LLUUID, LLViewHandle> sAutoOpenPreviewHandles;
 };
 
 class LLPreview : public LLFloater
diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp
index 8b0f55aff97102532c63388c00d146149477471f..871a0c55b7a72161cc7ceeab5fe5732820b859e1 100644
--- a/indra/newview/llpreviewsound.cpp
+++ b/indra/newview/llpreviewsound.cpp
@@ -16,6 +16,7 @@
 #include "audioengine.h"
 #include "llviewermessage.h"  // send_guid_sound_trigger
 #include "llagent.h"          // gAgent
+#include "lllineeditor.h"
 #include "llvieweruictrlfactory.h"
 
 extern LLAudioEngine* gAudiop;
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index d1817c8cdae4083045cfaece0c8c8a9edac138a8..b9c63b5ad8bd5f81b92f450fa0368e3888e1a376 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -23,6 +23,7 @@
 #include "llimagetga.h"
 #include "llfilepicker.h"
 #include "llvieweruictrlfactory.h"
+#include "lllineeditor.h"
 
 const S32 PREVIEW_TEXTURE_MIN_WIDTH = 300;
 const S32 PREVIEW_TEXTURE_MIN_HEIGHT = 120;
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 3ae4ba910770937c05d4a7724f734f01fc3dd86f..b1c6ea7213f0ce3bf08d392d3ea33b47091c6502 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -103,6 +103,10 @@ LLColor4 LLSelectMgr::sHighlightParentColor;
 LLColor4 LLSelectMgr::sHighlightChildColor;
 LLColor4 LLSelectMgr::sContextSilhouetteColor;
 
+static LLObjectSelection* get_null_object_selection();
+template<> 
+	const LLHandle<LLObjectSelection>::NullFunc 
+		LLHandle<LLObjectSelection>::sNullFunc = get_null_object_selection;
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // struct LLDeRezInfo
@@ -127,6 +131,13 @@ struct LLDeRezInfo
 // Functions
 //
 
+LLObjectSelection* get_null_object_selection()
+{
+	static LLObjectSelectionHandle null_ptr(new LLObjectSelection());
+	return (LLObjectSelection*)null_ptr;
+}
+
+
 //-----------------------------------------------------------------------------
 // LLSelectMgr()
 //-----------------------------------------------------------------------------
@@ -158,7 +169,9 @@ LLSelectMgr::LLSelectMgr()
 	gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD);
 	mGridValid = FALSE;
 
-	mSelectType = SELECT_TYPE_WORLD;
+	mSelectedObjects = new LLObjectSelection();
+	mHoverObjects = new LLObjectSelection();
+	mHighlightedObjects = new LLObjectSelection();
 }
 
 
@@ -167,55 +180,18 @@ LLSelectMgr::LLSelectMgr()
 //-----------------------------------------------------------------------------
 LLSelectMgr::~LLSelectMgr()
 {
-	mHoverObjects.deleteAllNodes();
-	mSelectedObjects.deleteAllNodes();
-	mHighlightedObjects.deleteAllNodes();
+	mHoverObjects->deleteAllNodes();
+	mSelectedObjects->deleteAllNodes();
+	mHighlightedObjects->deleteAllNodes();
 	mRectSelectedObjects.clear();
 	mGridObjects.deleteAllNodes();
-	mUndoQueue.clear();
-	mRedoQueue.clear();
-}
-
-bool LLSelectMgr::applyToObjects(LLSelectedObjectFunctor* func)
-{
-	bool result = true;
-	LLViewerObject* object;
-	for (object = getFirstObject(); object != NULL; object = getNextObject())
-	{
-		result = result && func->apply(object);
-	}
-	return result;
-}
-
-bool LLSelectMgr::applyToRootObjects(LLSelectedObjectFunctor* func)
-{
-	bool result = true;
-	LLViewerObject* object;
-	for (object = getFirstRootObject(); 
-		 object != NULL; 
-		 object = getNextRootObject())
-	{
-		result = result && func->apply(object);
-	}
-	return result;
-}
-
-bool LLSelectMgr::applyToNodes(LLSelectedNodeFunctor *func)
-{
-	bool result = true;
-	LLSelectNode* node;
-	for (node = getFirstNode(); node != NULL; node = getNextNode())
-	{
-		result = result && func->apply(node);
-	}
-	return result;
 }
 
 void LLSelectMgr::updateEffects()
 {
 	if (mEffectsTimer.getElapsedTimeF32() > 1.f)
 	{
-		mSelectedObjects.updateEffects();
+		mSelectedObjects->updateEffects();
 		mEffectsTimer.reset();
 	}
 }
@@ -223,7 +199,7 @@ void LLSelectMgr::updateEffects()
 //-----------------------------------------------------------------------------
 // Select just the object, not any other group members.
 //-----------------------------------------------------------------------------
-void LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face)
+LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face)
 {
 	llassert( object );
 
@@ -232,13 +208,13 @@ void LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face)
 		// make sure point at position is updated
 		updatePointAt();
 		gEditMenuHandler = this;
-		return;
+		return NULL;
 	}
 
 	if (!canSelectObject(object))
 	{
 		//make_ui_sound("UISndInvalidOp");
-		return;
+		return NULL;
 	}
 
 	// llinfos << "Adding object to selected object list" << llendl;
@@ -272,16 +248,18 @@ void LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face)
 
 	// have selection manager handle edit menu immediately after 
 	// user selects an object
-	if (getObjectCount())
+	if (mSelectedObjects->getObjectCount())
 	{
 		gEditMenuHandler = this;
 	}
+
+	return mSelectedObjects;
 }
 
 //-----------------------------------------------------------------------------
 // Select the object, parents and children.
 //-----------------------------------------------------------------------------
-void LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end)
+LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end)
 {
 	llassert( obj );
 
@@ -292,13 +270,13 @@ void LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end)
 		// make sure pointat position is updated
 		updatePointAt();
 		gEditMenuHandler = this;
-		return;
+		return NULL;
 	}
 
 	if (!canSelectObject(obj))
 	{
 		//make_ui_sound("UISndInvalidOp");
-		return;
+		return NULL;
 	}
 
 	// Since we're selecting a family, start at the root, but
@@ -347,16 +325,18 @@ void LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end)
 
 	// have selection manager handle edit menu immediately after 
 	// user selects an object
-	if (getObjectCount())
+	if (mSelectedObjects->getObjectCount())
 	{
 		gEditMenuHandler = this;
 	}
+
+	return mSelectedObjects;
 }
 
 //-----------------------------------------------------------------------------
 // Select the object, parents and children.
 //-----------------------------------------------------------------------------
-void LLSelectMgr::selectObjectAndFamily(const LLDynamicArray<LLViewerObject*>& object_list,
+LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const LLDynamicArray<LLViewerObject*>& object_list,
 										BOOL send_to_sim)
 {
 	// Collect all of the objects, children included
@@ -364,7 +344,7 @@ void LLSelectMgr::selectObjectAndFamily(const LLDynamicArray<LLViewerObject*>& o
 	LLViewerObject *object;
 	S32 i;
 
-	if (object_list.count() < 1) return;
+	if (object_list.count() < 1) return NULL;
 
 	// NOTE -- we add the objects in REVERSE ORDER 
 	// to preserve the order in the mSelectedObjects list
@@ -410,25 +390,25 @@ void LLSelectMgr::selectObjectAndFamily(const LLDynamicArray<LLViewerObject*>& o
 
 	// have selection manager handle edit menu immediately after 
 	// user selects an object
-	if (getObjectCount())
+	if (mSelectedObjects->getObjectCount())
 	{
 		gEditMenuHandler = this;
 	}
+
+	return mSelectedObjects;
 }
 
 // Use for when the simulator kills an object.  This version also
 // handles informing the current tool of the object's deletion.
 //
 // Caller needs to call dialog_refresh_all if necessary.
-BOOL LLSelectMgr::selectionRemoveObject(const LLUUID &id)
+BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id)
 {
-
-
 	BOOL object_found = FALSE;
 	LLTool *tool = NULL;
 	if (!gNoRender)
 	{
-		tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) );
+		tool = gToolMgr->getCurrentTool();
 
 		// It's possible that the tool is editing an object that is not selected
 		LLViewerObject* tool_editing_object = tool->getEditingObject();
@@ -443,13 +423,13 @@ BOOL LLSelectMgr::selectionRemoveObject(const LLUUID &id)
 	if( !object_found )
 	{
 		LLViewerObject* prevobjp = NULL;
-		for( LLViewerObject* tobjp = getFirstObject(); tobjp != NULL; tobjp = getNextObject() )
+		for( LLViewerObject* tobjp = mSelectedObjects->getFirstObject(); tobjp != NULL; tobjp = mSelectedObjects->getNextObject() )
 		{
 			if (tobjp == prevobjp)
 			{
 				// Somehow we got stuck in an infinite loop... (DaveP)
 				//  this logic is kind of twisted, not sure how this is happening, so...
-				llwarns << "Detected infinite loop #1 in LLSelectMgr::selectionRemoveObject:|" << llendl;
+				llwarns << "Detected infinite loop #1 in LLSelectMgr::removeObjectFromSelections:|" << llendl;
 				//MikeS. adding warning and comment...
 				//These infinite loops happen because the LLSelectMgr iteration routines are non-reentrant.
 				//deselectObjectAndFamily uses getFirstObject and getNextObject to mess with the array,
@@ -473,7 +453,7 @@ BOOL LLSelectMgr::selectionRemoveObject(const LLUUID &id)
 					if(object_found == TRUE){
 						//MikeS. adding warning... This happens when removing a linked attachment while sitting on an object..
 						//I think the selection manager needs to be rewritten. BAD.
-						llwarns << "Detected infinite loop #2 in LLSelectMgr::selectionRemoveObject:|" << llendl;
+						llwarns << "Detected infinite loop #2 in LLSelectMgr::removeObjectFromSelections:|" << llendl;
 						break;
 					}
 					object_found = TRUE;
@@ -594,11 +574,11 @@ void LLSelectMgr::addAsFamily(LLDynamicArray<LLViewerObject*>& objects, BOOL add
 			nodep = new LLSelectNode(objectp, TRUE);
 			if (add_to_end)
 			{
-				mSelectedObjects.addNodeAtEnd(nodep);
+				mSelectedObjects->addNodeAtEnd(nodep);
 			}
 			else
 			{
-				mSelectedObjects.addNode(nodep);
+				mSelectedObjects->addNode(nodep);
 			}
 			objectp->setSelected(TRUE);
 
@@ -615,7 +595,7 @@ void LLSelectMgr::addAsFamily(LLDynamicArray<LLViewerObject*>& objects, BOOL add
 		{
 			// we want this object to be selected for real
 			// so clear transient flag
-			LLSelectNode* select_node = findSelectNode(objectp);
+			LLSelectNode* select_node = mSelectedObjects->findNode(objectp);
 			if (select_node)
 			{
 				select_node->setTransient(FALSE);
@@ -631,21 +611,21 @@ void LLSelectMgr::addAsFamily(LLDynamicArray<LLViewerObject*>& objects, BOOL add
 void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable)
 {
 	// check to see if object is already in list
-	LLSelectNode *nodep = findSelectNode(objectp);
+	LLSelectNode *nodep = mSelectedObjects->findNode(objectp);
 
 	// if not in list, add it
 	if (!nodep)
 	{
 		nodep = new LLSelectNode(objectp, TRUE);
-		mSelectedObjects.addNode(nodep);
+		mSelectedObjects->addNode(nodep);
 	}
 	else
 	{
 		// make this a full-fledged selection
 		nodep->setTransient(FALSE);
 		// Move it to the front of the list
-		mSelectedObjects.removeNode(nodep);
-		mSelectedObjects.addNode(nodep);
+		mSelectedObjects->removeNode(nodep);
+		mSelectedObjects->addNode(nodep);
 	}
 
 	// Make sure the object is tagged as selected
@@ -679,26 +659,26 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab
 }
 
 
-void LLSelectMgr::setHoverObject(LLViewerObject *objectp)
+LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp)
 {
 	// Always blitz hover list when setting
-	mHoverObjects.deleteAllNodes();
+	mHoverObjects->deleteAllNodes();
 
 	if (!objectp)
 	{
-		return;
+		return NULL;
 	}
 
 	// Can't select yourself
 	if (objectp->mID == gAgentID)
 	{
-		return;
+		return NULL;
 	}
 
 	// Can't select land
 	if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
 	{
-		return;
+		return NULL;
 	}
 
 	// Collect all of the objects
@@ -714,15 +694,16 @@ void LLSelectMgr::setHoverObject(LLViewerObject *objectp)
 	{
 		cur_objectp = objects[i];
 		nodep = new LLSelectNode(cur_objectp, FALSE);
-		mHoverObjects.addNodeAtEnd(nodep);
+		mHoverObjects->addNodeAtEnd(nodep);
 	}
 
 	requestObjectPropertiesFamily(objectp);
+	return mHoverObjects;
 }
 
 LLSelectNode *LLSelectMgr::getHoverNode()
 {
-	return getHoverObjects().getFirstRootNode();
+	return getHoverObjects()->getFirstRootNode();
 }
 
 void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
@@ -823,20 +804,20 @@ void LLSelectMgr::unhighlightObjectAndFamily(LLViewerObject* objectp)
 void LLSelectMgr::unhighlightAll()
 {
 	mRectSelectedObjects.clear();
-	mHighlightedObjects.deleteAllNodes();
+	mHighlightedObjects->deleteAllNodes();
 }
 
-void LLSelectMgr::selectHighlightedObjects()
+LLObjectSelectionHandle LLSelectMgr::selectHighlightedObjects()
 {
-	if (!mHighlightedObjects.getNumNodes())
+	if (!mHighlightedObjects->getNumNodes())
 	{
-		return;
+		return NULL;
 	}
 
 	LLSelectNode *nodep;
-	for (nodep = mHighlightedObjects.getFirstNode();
+	for (nodep = mHighlightedObjects->getFirstNode();
 		nodep;
-		nodep = mHighlightedObjects.getNextNode())
+		nodep = mHighlightedObjects->getNextNode())
 	{
 		LLViewerObject* objectp = nodep->getObject();
 
@@ -852,12 +833,12 @@ void LLSelectMgr::selectHighlightedObjects()
 		}
 
 		LLSelectNode* new_nodep = new LLSelectNode(*nodep);
-		mSelectedObjects.addNode(new_nodep);
+		mSelectedObjects->addNode(new_nodep);
 
 		// flag this object as selected
 		objectp->setSelected(TRUE);
 
-		mSelectType = getSelectTypeForObject(objectp);
+		mSelectedObjects->mSelectType = getSelectTypeForObject(objectp);
 
 		// request properties on root objects
 		if (objectp->isRootEdit())
@@ -873,10 +854,12 @@ void LLSelectMgr::selectHighlightedObjects()
 	saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
 	updatePointAt();
 
-	if (getObjectCount())
+	if (mSelectedObjects->getObjectCount())
 	{
 		gEditMenuHandler = this;
 	}
+
+	return mSelectedObjects;
 }
 
 void LLSelectMgr::deselectHighlightedObjects()
@@ -938,7 +921,7 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &
 		grid_object = NULL;
 	}
 
-	if (mGridMode == GRID_MODE_LOCAL && gSelectMgr->getObjectCount())
+	if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount())
 	{
 		LLBBox bbox = mSavedSelectionBBox;
 		mGridOrigin = mSavedSelectionBBox.getCenterAgent();
@@ -992,18 +975,18 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &
 	}
 	else // GRID_MODE_WORLD or just plain default
 	{
-		LLViewerObject* first_object = gSelectMgr->getFirstRootObject();
+		LLViewerObject* first_object = mSelectedObjects->getFirstRootObject();
 		if (!first_object)
 		{
-			first_object = gSelectMgr->getFirstObject();
+			first_object = mSelectedObjects->getFirstObject();
 		}
 
 		mGridOrigin.clearVec();
 		mGridRotation.loadIdentity();
 
-		mSelectType = getSelectTypeForObject( first_object );
+		mSelectedObjects->mSelectType = getSelectTypeForObject( first_object );
 
-		switch (mSelectType)
+		switch (mSelectedObjects->mSelectType)
 		{
 		case SELECT_TYPE_ATTACHMENT:
 			if (first_object)
@@ -1032,59 +1015,6 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &
 	mGridValid = TRUE;
 }
 
-
-
-LLSelectNode* LLSelectMgr::findSelectNode(LLViewerObject *object)
-{
-	return mSelectedObjects.findNode(object);
-}
-
-//-----------------------------------------------------------------------------
-// contains()
-//-----------------------------------------------------------------------------
-BOOL LLSelectMgr::contains(LLViewerObject* object)
-{
-	return mSelectedObjects.findNode(object) != NULL;
-}
-
-
-//-----------------------------------------------------------------------------
-// contains()
-//-----------------------------------------------------------------------------
-BOOL LLSelectMgr::contains(LLViewerObject* object, S32 te)
-{
-	LLSelectNode *nodep;
-	if (te == SELECT_ALL_TES)
-	{
-		// ...all faces
-		for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode() )
-		{
-			if (nodep->getObject() == object)
-			{
-				BOOL all_selected = TRUE;
-				for (S32 i = 0; i < SELECT_MAX_TES; i++)
-				{
-					all_selected = all_selected && nodep->isTESelected(i);
-				}
-				return all_selected;
-			}
-		}
-		return FALSE;
-	}
-	else
-	{
-		// ...one face
-		for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode() )
-		{
-			if (nodep->getObject() == object && nodep->isTESelected(te))
-			{
-				return TRUE;
-			}
-		}
-		return FALSE;
-	}
-}
-
 //-----------------------------------------------------------------------------
 // remove() - an array of objects
 //-----------------------------------------------------------------------------
@@ -1097,14 +1027,14 @@ void LLSelectMgr::remove(LLDynamicArray<LLViewerObject*>& objects)
 	for(S32 i = 0; i < count; i++)
 	{
 		objectp = objects.get(i);
-		for(nodep = mSelectedObjects.getFirstNode();
+		for(nodep = mSelectedObjects->getFirstNode();
 			nodep != NULL;
-			nodep = mSelectedObjects.getNextNode())
+			nodep = mSelectedObjects->getNextNode())
 		{
 			if(nodep->getObject() == objectp)
 			{
 				objectp->setSelected(FALSE);
-				mSelectedObjects.removeNode(nodep);
+				mSelectedObjects->removeNode(nodep);
 				break;
 			}
 		}
@@ -1121,7 +1051,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable)
 {
 	// check if object already in list
 	// *FIX: can we just check isSelected()?
-	LLSelectNode *nodep = findSelectNode(objectp);
+	LLSelectNode *nodep = mSelectedObjects->findNode(objectp);
 
 	if (!nodep)
 	{
@@ -1133,12 +1063,12 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable)
 	if (objectp->getNumTEs() <= 0)
 	{
 		// object doesn't have faces, so blow it away
-		mSelectedObjects.removeNode(nodep);
+		mSelectedObjects->removeNode(nodep);
 		objectp->setSelected( FALSE );
 	}
 	else if (te == SELECT_ALL_TES)
 	{
-		mSelectedObjects.removeNode(nodep);
+		mSelectedObjects->removeNode(nodep);
 		objectp->setSelected( FALSE );
 	}
 	else if (0 <= te && te < SELECT_MAX_TES)
@@ -1164,7 +1094,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable)
 		// ...all faces now turned off, so remove
 		if (!found)
 		{
-			mSelectedObjects.removeNode(nodep);
+			mSelectedObjects->removeNode(nodep);
 			objectp->setSelected( FALSE );
 
 			// BUG: Doesn't update simulator that object is gone.
@@ -1187,12 +1117,12 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable)
 void LLSelectMgr::removeAll()
 {
 	LLViewerObject *objectp;
-	for (objectp = mSelectedObjects.getFirstObject(); objectp; objectp = mSelectedObjects.getNextObject() )
+	for (objectp = mSelectedObjects->getFirstObject(); objectp; objectp = mSelectedObjects->getNextObject() )
 	{
 		objectp->setSelected( FALSE );
 	}
 
-	mSelectedObjects.deleteAllNodes();
+	mSelectedObjects->deleteAllNodes();
 
 	updateSelectionCenter();
 	dialog_refresh_all();
@@ -1209,9 +1139,9 @@ void LLSelectMgr::promoteSelectionToRoot()
 
 	LLSelectNode* nodep;
 	LLViewerObject *objectp;
-	for (nodep = mSelectedObjects.getFirstNode(); 
+	for (nodep = mSelectedObjects->getFirstNode(); 
 		 nodep; 
-		 nodep = mSelectedObjects.getNextNode() )
+		 nodep = mSelectedObjects->getNextNode() )
 	{
 		if (nodep->mIndividualSelection)
 		{
@@ -1247,9 +1177,9 @@ void LLSelectMgr::demoteSelectionToIndividuals()
 {
 	LLDynamicArray<LLViewerObject*> objects;
 
-	for (LLViewerObject* root_objectp = mSelectedObjects.getFirstRootObject();
+	for (LLViewerObject* root_objectp = mSelectedObjects->getFirstRootObject();
 		root_objectp;
-		root_objectp = mSelectedObjects.getNextRootObject())
+		root_objectp = mSelectedObjects->getNextRootObject())
 	{
 		root_objectp->addThisAndNonJointChildren(objects);
 	}
@@ -1264,72 +1194,21 @@ void LLSelectMgr::demoteSelectionToIndividuals()
 	}
 }
 
-//-----------------------------------------------------------------------------
-// getObjectCount()
-//-----------------------------------------------------------------------------
-S32 LLSelectMgr::getObjectCount()
-{
-	return mSelectedObjects.getNumNodes();
-}
-
-
-//-----------------------------------------------------------------------------
-// getTECount()
-//-----------------------------------------------------------------------------
-S32 LLSelectMgr::getTECount()
-{
-	S32 count = 0;
-
-	LLSelectNode* nodep;
-	for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode() )
-	{
-		if (nodep->getObject())
-		{
-			S32 num_tes = nodep->getObject()->getNumTEs();
-			for (S32 te = 0; te < num_tes; te++)
-			{
-				if (nodep->isTESelected(te))
-				{
-					count++;
-				}
-			}
-		}
-	}
-
-	return count;
-}
-
-//-----------------------------------------------------------------------------
-// getRootObjectCount()
-//-----------------------------------------------------------------------------
-S32 LLSelectMgr::getRootObjectCount()
-{
-	LLSelectNode *nodep;
-
-	S32 count = 0;
-	for(nodep = mSelectedObjects.getFirstRootNode(); nodep; nodep = mSelectedObjects.getNextRootNode())
-	{
-		++count;
-	}
-	return count;
-}
-
-
 //-----------------------------------------------------------------------------
 // dump()
 //-----------------------------------------------------------------------------
 void LLSelectMgr::dump()
 {
-	llinfos << "Selection Manager: " << mSelectedObjects.getNumNodes() << " items" << llendl;
+	llinfos << "Selection Manager: " << mSelectedObjects->getNumNodes() << " items" << llendl;
 
 	llinfos << "TE mode " << mTEMode << llendl;
 
 	S32 i = 0;
 
 	LLViewerObject *objectp;
-	for (objectp = mSelectedObjects.getFirstObject();
+	for (objectp = mSelectedObjects->getFirstObject();
 		 objectp;
-		 objectp = mSelectedObjects.getNextObject())
+		 objectp = mSelectedObjects->getNextObject())
 	{
 		llinfos << "Object " << i << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << llendl;
 		llinfos << "  hasLSL " << objectp->flagScripted() << llendl;
@@ -1347,14 +1226,14 @@ void LLSelectMgr::dump()
 
 	// Face iterator
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&objectp, &te);
+	for (mSelectedObjects->getFirstTE(&objectp, &te);
 		 objectp;
-		 mSelectedObjects.getNextTE(&objectp, &te))
+		 mSelectedObjects->getNextTE(&objectp, &te))
 	{
 		llinfos << "Object " << objectp << " te " << te << llendl;
 	}
 
-	llinfos << mHighlightedObjects.getNumNodes() << " objects currently highlighted." << llendl;
+	llinfos << mHighlightedObjects->getNumNodes() << " objects currently highlighted." << llendl;
 
 	llinfos << "Center global " << mSelectionCenterGlobal << llendl;
 }
@@ -1383,7 +1262,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
 
 	if(item 
 		&& !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())
-		&& (mSelectedObjects.getNumNodes() > 1) )
+		&& (mSelectedObjects->getNumNodes() > 1) )
 	{
 		llwarns << "Attempted to apply no-copy texture to multiple objects"
 				<< llendl;
@@ -1394,7 +1273,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
 	S32 te;
 
 	// Apply the texture to each side
-	for (mSelectedObjects.getFirstTE(&objectp, &te); objectp; mSelectedObjects.getNextTE(&objectp, &te))
+	for (mSelectedObjects->getFirstTE(&objectp, &te); objectp; mSelectedObjects->getNextTE(&objectp, &te))
 	{
 
 		if (item)
@@ -1405,14 +1284,14 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
 			// *TODO: Replace mSelectedObjects with a REAL container class!
 			LLViewerObject* tmp_object;
 			S32 tmp_te;
-			mSelectedObjects.getCurrentTE(&tmp_object,&tmp_te);
+			mSelectedObjects->getCurrentTE(&tmp_object,&tmp_te);
 			if ((tmp_object != objectp) || (tmp_te != te) )
 			{
 				//AAARG someone has moved our list around!
-				mSelectedObjects.getFirstTE(&tmp_object, &tmp_te);
+				mSelectedObjects->getFirstTE(&tmp_object, &tmp_te);
 				while ((tmp_object != objectp) || (tmp_te != te))
 				{
-					mSelectedObjects.getNextTE(&tmp_object, &tmp_te);
+					mSelectedObjects->getNextTE(&tmp_object, &tmp_te);
 				}
 			}
 		}
@@ -1427,9 +1306,9 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid)
 	}
 
 	// 1 particle effect per object
-	if (mSelectType != SELECT_TYPE_HUD)
+	if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD)
 	{
-		for (objectp = mSelectedObjects.getFirstObject(); objectp; objectp = mSelectedObjects.getNextObject())
+		for (objectp = mSelectedObjects->getFirstObject(); objectp; objectp = mSelectedObjects->getNextObject())
 		{
 			LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
 			effectp->setSourceObject(gAgent.getAvatarObject());     
@@ -1447,7 +1326,7 @@ void LLSelectMgr::selectionSetColor(const LLColor4 &color)
 {
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
@@ -1456,7 +1335,7 @@ void LLSelectMgr::selectionSetColor(const LLColor4 &color)
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1473,7 +1352,7 @@ void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color)
 	LLViewerObject* object;
 	LLColor4 new_color = color;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
@@ -1484,7 +1363,7 @@ void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color)
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1500,7 +1379,7 @@ void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha)
 {
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
@@ -1511,7 +1390,7 @@ void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha)
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1525,11 +1404,11 @@ void LLSelectMgr::selectionRevertColors()
 	LLViewerObject* object;
 	S32 te;
 
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
-			LLSelectNode* nodep = mSelectedObjects.findNode(object);
+			LLSelectNode* nodep = mSelectedObjects->findNode(object);
 			if (nodep && te < (S32)nodep->mSavedColors.size())
 			{
 				LLColor4 color = nodep->mSavedColors[te];
@@ -1539,7 +1418,7 @@ void LLSelectMgr::selectionRevertColors()
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1554,11 +1433,11 @@ BOOL LLSelectMgr::selectionRevertTextures()
 	S32 te;
 
 	BOOL revert_successful = TRUE;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
-			LLSelectNode* nodep = mSelectedObjects.findNode(object);
+			LLSelectNode* nodep = mSelectedObjects->findNode(object);
 			if (nodep && te < (S32)nodep->mSavedTextures.size())
 			{
 				LLUUID id = nodep->mSavedTextures[te];
@@ -1577,7 +1456,7 @@ BOOL LLSelectMgr::selectionRevertTextures()
 	}
 
 	// propagate texture changes to server
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1592,7 +1471,7 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap)
 {
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
@@ -1601,7 +1480,7 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap)
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1614,7 +1493,7 @@ void LLSelectMgr::selectionSetTexGen(U8 texgen)
 {
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
@@ -1623,7 +1502,7 @@ void LLSelectMgr::selectionSetTexGen(U8 texgen)
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1637,7 +1516,7 @@ void LLSelectMgr::selectionSetShiny(U8 shiny)
 {
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
@@ -1646,7 +1525,7 @@ void LLSelectMgr::selectionSetShiny(U8 shiny)
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1659,7 +1538,7 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright)
 {
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
@@ -1668,7 +1547,7 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright)
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1699,7 +1578,7 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string&
 		media_flags = LLTextureEntry::MF_WEB_PAGE;
 	}
 
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) )
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) )
 	{
 		if (object->permModify())
 		{
@@ -1708,7 +1587,7 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string&
 		}
 	}
 
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -1730,7 +1609,7 @@ LLPermissions* LLSelectMgr::findObjectPermissions(const LLViewerObject* object)
 {
 	LLSelectNode* nodep;
 
-	for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode() )
+	for (nodep = mSelectedObjects->getFirstNode(); nodep; nodep = mSelectedObjects->getNextNode() )
 	{
 		if((nodep->getObject() == object) && nodep->mValid)
 		{
@@ -1749,7 +1628,7 @@ BOOL LLSelectMgr::selectionGetTexUUID(LLUUID& id)
 {
 	LLViewerObject* first_objectp;
 	S32 first_te;
-	mSelectedObjects.getPrimaryTE(&first_objectp, &first_te);
+	mSelectedObjects->getPrimaryTE(&first_objectp, &first_te);
 
 	// nothing selected
 	if (!first_objectp)
@@ -1767,7 +1646,7 @@ BOOL LLSelectMgr::selectionGetTexUUID(LLUUID& id)
 	BOOL identical = TRUE;
 	LLViewerObject *objectp;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&objectp, &te); objectp; mSelectedObjects.getNextTE(&objectp, &te) )
+	for (mSelectedObjects->getFirstTE(&objectp, &te); objectp; mSelectedObjects->getNextTE(&objectp, &te) )
 	{
 		if (objectp->getTEImage(te) != first_imagep)
 		{
@@ -1787,7 +1666,7 @@ BOOL LLSelectMgr::selectionGetColor(LLColor4 &color)
 {
 	LLViewerObject* first_object;
 	S32 first_te;
-	mSelectedObjects.getPrimaryTE(&first_object, &first_te);
+	mSelectedObjects->getPrimaryTE(&first_object, &first_te);
 
 	// nothing selected
 	if (!first_object)
@@ -1808,7 +1687,7 @@ BOOL LLSelectMgr::selectionGetColor(LLColor4 &color)
 	BOOL identical = TRUE;
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te))
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te))
 	{
 		if (!object->getTE(te) || (object->getTE(te)->getColor() != first_color))
 		{
@@ -1829,7 +1708,7 @@ BOOL LLSelectMgr::selectionGetBumpmap(U8 *bumpmap)
 {
 	LLViewerObject* first_object;
 	S32 first_te;
-	mSelectedObjects.getPrimaryTE(&first_object, &first_te);
+	mSelectedObjects->getPrimaryTE(&first_object, &first_te);
 
 	// nothing selected
 	if (!first_object)
@@ -1850,7 +1729,7 @@ BOOL LLSelectMgr::selectionGetBumpmap(U8 *bumpmap)
 	BOOL identical = TRUE;
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te))
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te))
 	{
 		if (!object->getTE(te) || (object->getTE(te)->getBumpmap() != first_value))
 		{
@@ -1870,7 +1749,7 @@ BOOL LLSelectMgr::selectionGetShiny(U8 *shiny)
 {
 	LLViewerObject* first_object;
 	S32 first_te;
-	mSelectedObjects.getPrimaryTE(&first_object, &first_te);
+	mSelectedObjects->getPrimaryTE(&first_object, &first_te);
 
 	// nothing selected
 	if (!first_object)
@@ -1891,7 +1770,7 @@ BOOL LLSelectMgr::selectionGetShiny(U8 *shiny)
 	BOOL identical = TRUE;
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te))
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te))
 	{
 		if (!object->getTE(te) || (object->getTE(te)->getShiny() != first_value))
 		{
@@ -1911,7 +1790,7 @@ BOOL LLSelectMgr::selectionGetFullbright(U8 *fullbright)
 {
 	LLViewerObject* first_object;
 	S32 first_te;
-	mSelectedObjects.getPrimaryTE(&first_object, &first_te);
+	mSelectedObjects->getPrimaryTE(&first_object, &first_te);
 
 	// nothing selected
 	if (!first_object)
@@ -1932,7 +1811,7 @@ BOOL LLSelectMgr::selectionGetFullbright(U8 *fullbright)
 	BOOL identical = TRUE;
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te))
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te))
 	{
 		if (!object->getTE(te) || (object->getTE(te)->getFullbright() != first_value))
 		{
@@ -1950,7 +1829,7 @@ bool LLSelectMgr::selectionGetMediaType(U8 *media_type)
 {
 	LLViewerObject* first_object;
 	S32 first_te;
-	mSelectedObjects.getPrimaryTE(&first_object, &first_te);
+	mSelectedObjects->getPrimaryTE(&first_object, &first_te);
 
 	// nothing selected
 	if (!first_object)
@@ -1971,7 +1850,7 @@ bool LLSelectMgr::selectionGetMediaType(U8 *media_type)
 	bool identical = true;
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te))
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te))
 	{
 		if (!object->getTE(te) || (object->getTE(te)->getMediaFlags() != first_value))
 		{
@@ -1992,7 +1871,7 @@ bool LLSelectMgr::selectionGetMediaType(U8 *media_type)
 void LLSelectMgr::selectionSetMaterial(U8 material)
 {
 	LLViewerObject* object;
-	for (object = mSelectedObjects.getFirstObject(); object != NULL; object = mSelectedObjects.getNextObject() )
+	for (object = mSelectedObjects->getFirstObject(); object != NULL; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->permModify())
 		{
@@ -2008,7 +1887,7 @@ void LLSelectMgr::selectionSetMaterial(U8 material)
 BOOL LLSelectMgr::selectionAllPCode(LLPCode code)
 {
 	LLViewerObject *object;
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (object->getPCode() != code)
 		{
@@ -2023,13 +1902,13 @@ BOOL LLSelectMgr::selectionAllPCode(LLPCode code)
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectionGetMaterial(U8 *out_material)
 {
-	LLViewerObject *object = mSelectedObjects.getFirstObject();
+	LLViewerObject *object = mSelectedObjects->getFirstObject();
 	if (!object) return FALSE;
 
 	U8 material = object->getMaterial();
 
 	BOOL identical = TRUE;
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if ( material != object->getMaterial())
 		{
@@ -2044,13 +1923,13 @@ BOOL LLSelectMgr::selectionGetMaterial(U8 *out_material)
 
 BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action)
 {
-	LLViewerObject *object = mSelectedObjects.getFirstObject();
+	LLViewerObject *object = mSelectedObjects->getFirstObject();
 	if (!object) return FALSE;
 
 	U8 action = object->getClickAction();
 
 	BOOL identical = TRUE;
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if ( action != object->getClickAction())
 		{
@@ -2066,7 +1945,7 @@ BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action)
 void LLSelectMgr::selectionSetClickAction(U8 action)
 {
 	LLViewerObject* object = NULL;
-	for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+	for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		object->setClickAction(action);
 	}
@@ -2099,7 +1978,7 @@ void LLSelectMgr::sendGodlikeRequest(const LLString& request, const LLString& pa
 	}
 
 	godlike_request_t data(request, param);
-	if(!getRootObjectCount())
+	if(!mSelectedObjects->getRootObjectCount())
 	{
 		LLMessageSystem* msg = gMessageSystem;
 		msg->newMessage(message_type.c_str());
@@ -2153,7 +2032,7 @@ void LLSelectMgr::selectionResetRotation()
 	LLQuaternion identity(0.f, 0.f, 0.f, 1.f);
 
 	LLViewerObject* object;
-	for (object = mSelectedObjects.getFirstRootObject(); object; object = mSelectedObjects.getNextRootObject() )
+	for (object = mSelectedObjects->getFirstRootObject(); object; object = mSelectedObjects->getNextRootObject() )
 	{
 		object->setRotation(identity);
 		if (object->mDrawable.notNull())
@@ -2169,7 +2048,7 @@ void LLSelectMgr::selectionRotateAroundZ(F32 degrees)
 	LLQuaternion rot( degrees * DEG_TO_RAD, LLVector3(0,0,1) );
 
 	LLViewerObject* object;
-	for (object = mSelectedObjects.getFirstRootObject(); object; object = mSelectedObjects.getNextRootObject() )
+	for (object = mSelectedObjects->getFirstRootObject(); object; object = mSelectedObjects->getNextRootObject() )
 	{
 		object->setRotation( object->getRotationEdit() * rot );
 		if (object->mDrawable.notNull())
@@ -2188,7 +2067,7 @@ void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter)
 {
 	LLViewerObject* object;
 	S32 te;
-	for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te))
+	for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te))
 	{
 		if (!object->permModify())
 		{
@@ -2213,7 +2092,7 @@ void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter)
 		object->setTEScale(te, new_s, new_t);
 	}
 
-	for (object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject())
+	for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject())
 	{
 		if (object->permModify())
 		{
@@ -2280,7 +2159,7 @@ void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch)
 
 	BOOL send = FALSE;
 	
-	for (selectNode = mSelectedObjects.getFirstNode(); selectNode; selectNode = mSelectedObjects.getNextNode())
+	for (selectNode = mSelectedObjects->getFirstNode(); selectNode; selectNode = mSelectedObjects->getNextNode())
 	{
 		object = selectNode->getObject();
 		if (!object->permModify())
@@ -2338,7 +2217,7 @@ void LLSelectMgr::selectionResetTexInfo(S32 selected_face)
 	S32 start_face, end_face;
 
 	LLViewerObject* object;
-	for (object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject())
+	for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject())
 	{
 		if (!object->permModify())
 		{
@@ -2373,336 +2252,89 @@ void LLSelectMgr::selectionResetTexInfo(S32 selected_face)
 }
 
 //-----------------------------------------------------------------------------
-// getFirstEditableObject()
+// selectGetAllRootsValid()
+// Returns true if the viewer has information on all selected objects
 //-----------------------------------------------------------------------------
-LLViewerObject* LLSelectMgr::getFirstEditableObject(BOOL get_root)
+BOOL LLSelectMgr::selectGetAllRootsValid()
 {
-	LLViewerObject* object = NULL;
-	for(LLViewerObject* cur = mSelectedObjects.getFirstObject(); cur; cur = mSelectedObjects.getNextObject())
+	for( LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 	{
-		if( cur->permModify() )
+	
+		if( !node->mValid )
 		{
-			object = cur;
-			break;
+			return FALSE;
 		}
-	}	
 
-	if (get_root && object)
-	{
-		LLViewerObject *parent;
-		while ((parent = (LLViewerObject*)object->getParent()))
+		if( !node->getObject() )
 		{
-			if (parent->isSelected())
-			{
-				object = parent;
-			}
-			else
-			{
-				break;
-			}
+			return FALSE;
 		}
 	}
-
-	return object;
+	return TRUE;
 }
 
+
 //-----------------------------------------------------------------------------
-// getFirstMoveableObject()
+// selectGetAllValid()
+// Returns true if the viewer has information on all selected objects
 //-----------------------------------------------------------------------------
-LLViewerObject* LLSelectMgr::getFirstMoveableObject(BOOL get_root)
+BOOL LLSelectMgr::selectGetAllValid()
 {
-	LLViewerObject* object = NULL;
-	for(LLViewerObject* cur = mSelectedObjects.getFirstObject(); cur; cur = mSelectedObjects.getNextObject())
+	for( LLSelectNode* node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() )
 	{
-		if( cur->permMove() )
+	
+		if( !node->mValid )
 		{
-			object = cur;
-			break;
+			return FALSE;
 		}
-	}	
 
-	if (get_root && object && !object->isJointChild())
-	{
-		LLViewerObject *parent;
-		while ((parent = (LLViewerObject*)object->getParent()))
+		if( !node->getObject() )
 		{
-			if (parent->isSelected())
-			{
-				object = parent;
-			}
-			else
-			{
-				break;
-			}
+			return FALSE;
 		}
 	}
-
-	return object;
+	return TRUE;
 }
 
+
 //-----------------------------------------------------------------------------
-// getFirstEditableNode()
+// selectGetModify() - return true if current agent can modify all
+// selected objects.
 //-----------------------------------------------------------------------------
-LLSelectNode* LLSelectMgr::getFirstEditableNode(BOOL get_root)
+BOOL LLSelectMgr::selectGetModify()
 {
-	LLSelectNode* selectNode = NULL;
-
-	if (get_root)
+	for( LLSelectNode* node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() )
 	{
-		for(selectNode = mSelectedObjects.getFirstRootNode(); selectNode; selectNode = mSelectedObjects.getNextRootNode())
+		if( !node->mValid )
 		{
-			if( selectNode->getObject()->permModify() )
-			{
-				return selectNode;
-				break;
-			}
+			return FALSE;
 		}
-	}
-	for(selectNode = mSelectedObjects.getFirstNode(); selectNode; selectNode = mSelectedObjects.getNextNode())
-	{
-		if( selectNode->getObject()->permModify() )
+		LLViewerObject* object = node->getObject();
+		if( !object || !object->permModify() )
 		{
-			return selectNode;
-			break;
+			return FALSE;
 		}
 	}
-	
-	return NULL;
+
+	return TRUE;
 }
 
 //-----------------------------------------------------------------------------
-// getFirstMoveableNode()
+// selectGetRootsModify() - return true if current agent can modify all
+// selected root objects.
 //-----------------------------------------------------------------------------
-LLSelectNode* LLSelectMgr::getFirstMoveableNode(BOOL get_root)
+BOOL LLSelectMgr::selectGetRootsModify()
 {
-	LLSelectNode* selectNode = NULL;
-
-	if (get_root)
+	for( LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 	{
-		for(selectNode = mSelectedObjects.getFirstRootNode(); selectNode; selectNode = mSelectedObjects.getNextRootNode())
+		if( !node->mValid )
 		{
-			if( selectNode->getObject()->permMove() )
-			{
-				return selectNode;
-				break;
-			}
+			return FALSE;
 		}
-	}
-	for(selectNode = mSelectedObjects.getFirstNode(); selectNode; selectNode = mSelectedObjects.getNextNode())
-	{
-		if( selectNode->getObject()->permMove() )
+		LLViewerObject* object = node->getObject();
+		if( !object || !object->permModify() )
 		{
-			return selectNode;
-			break;
-		}
-	}
-	
-	return NULL;
-}
-
-//-----------------------------------------------------------------------------
-// getFirstDeleteableObject()
-//-----------------------------------------------------------------------------
-LLViewerObject* LLSelectMgr::getFirstDeleteableObject(BOOL get_root)
-{
-	//RN: don't currently support deletion of child objects, as that requires separating them first
-	// then derezzing to trash
-	get_root = TRUE;
-
-	LLViewerObject* object = NULL;
-	if (get_root)
-	{
-		for(LLViewerObject* current = getFirstRootObject();
-			current != NULL;
-			current = getNextRootObject())
-		{
-			// you can delete an object if permissions allow it, you are
-			// the owner, you are an officer in the group that owns the
-			// object, or you are not the owner but it is on land you own
-			// or land owned by your group. (whew!)
-			if(   (current->permModify()) 
-			|| (current->permYouOwner())
-			|| (!current->permAnyOwner())			// public
-			|| (current->isOverAgentOwnedLand())
-			|| (current->isOverGroupOwnedLand())
-			)
-			{
-
-				if( !current->isAttachment() )
-				{
-					object = current;
-					break;
-				}
-			}
-		}	
-	}
-	else
-	{
-		for(LLViewerObject* current = getFirstObject();
-			current != NULL;
-			current = getNextObject())
-		{
-			// you can delete an object if permissions allow it, you are
-			// the owner, you are an officer in the group that owns the
-			// object, or you are not the owner but it is on land you own
-			// or land owned by your group. (whew!)
-			if(   (current->permModify()) 
-			|| (current->permYouOwner())
-			|| (!current->permAnyOwner())			// public
-			|| (current->isOverAgentOwnedLand())
-			|| (current->isOverGroupOwnedLand())
-			)
-			{
-				if( !current->isAttachment() )
-				{
-					object = current;
-					break;
-				}
-			}
-		}	
-	}
-
-	return object;
-}
-
-//-----------------------------------------------------------------------------
-// getFirstCopyableObject()
-//-----------------------------------------------------------------------------
-LLViewerObject* LLSelectMgr::getFirstCopyableObject(BOOL get_root)
-{
-	LLViewerObject* object = NULL;
-	for(LLViewerObject* cur = mSelectedObjects.getFirstObject(); cur; cur = mSelectedObjects.getNextObject())
-	{
-		if( cur->permCopy() && !cur->isAttachment())
-		{
-			object = cur;
-			break;
-		}
-	}	
-
-	if (get_root && object)
-	{
-		LLViewerObject *parent;
-		while ((parent = (LLViewerObject*)object->getParent()))
-		{
-			if (parent->isSelected())
-			{
-				object = parent;
-			}
-			else
-			{
-				break;
-			}
-		}
-	}
-
-	return object;
-}
-
-//-----------------------------------------------------------------------------
-// areMultpleEditableObjectsSelected()
-//-----------------------------------------------------------------------------
-BOOL LLSelectMgr::areMultpleEditableObjectsSelected()
-{
-	S32 count = 0;
-	for( LLViewerObject* cur = mSelectedObjects.getFirstObject(); cur; cur = mSelectedObjects.getNextObject() )
-	{
-		if( cur->permModify() )
-		{
-			count++;
-			if( count > 1 )
-			{
-				return TRUE;
-			}
-		}
-	}
-	return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// selectGetAllRootsValid()
-// Returns true if the viewer has information on all selected objects
-//-----------------------------------------------------------------------------
-BOOL LLSelectMgr::selectGetAllRootsValid()
-{
-	for( LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode() )
-	{
-	
-		if( !node->mValid )
-		{
-			return FALSE;
-		}
-
-		if( !node->getObject() )
-		{
-			return FALSE;
-		}
-	}
-	return TRUE;
-}
-
-
-//-----------------------------------------------------------------------------
-// selectGetAllValid()
-// Returns true if the viewer has information on all selected objects
-//-----------------------------------------------------------------------------
-BOOL LLSelectMgr::selectGetAllValid()
-{
-	for( LLSelectNode* node = getFirstNode(); node; node = getNextNode() )
-	{
-	
-		if( !node->mValid )
-		{
-			return FALSE;
-		}
-
-		if( !node->getObject() )
-		{
-			return FALSE;
-		}
-	}
-	return TRUE;
-}
-
-
-//-----------------------------------------------------------------------------
-// selectGetModify() - return true if current agent can modify all
-// selected objects.
-//-----------------------------------------------------------------------------
-BOOL LLSelectMgr::selectGetModify()
-{
-	for( LLSelectNode* node = getFirstNode(); node; node = getNextNode() )
-	{
-		if( !node->mValid )
-		{
-			return FALSE;
-		}
-		LLViewerObject* object = node->getObject();
-		if( !object || !object->permModify() )
-		{
-			return FALSE;
-		}
-	}
-
-	return TRUE;
-}
-
-//-----------------------------------------------------------------------------
-// selectGetRootsModify() - return true if current agent can modify all
-// selected root objects.
-//-----------------------------------------------------------------------------
-BOOL LLSelectMgr::selectGetRootsModify()
-{
-	for( LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode() )
-	{
-		if( !node->mValid )
-		{
-			return FALSE;
-		}
-		LLViewerObject* object = node->getObject();
-		if( !object || !object->permModify() )
-		{
-			return FALSE;
+			return FALSE;
 		}
 	}
 
@@ -2716,7 +2348,7 @@ BOOL LLSelectMgr::selectGetRootsModify()
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectGetRootsTransfer()
 {
-	for(LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode())
+	for(LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode())
 	{
 		if(!node->mValid)
 		{
@@ -2737,7 +2369,7 @@ BOOL LLSelectMgr::selectGetRootsTransfer()
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectGetRootsCopy()
 {
-	for(LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode())
+	for(LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode())
 	{
 		if(!node->mValid)
 		{
@@ -2758,8 +2390,8 @@ BOOL LLSelectMgr::selectGetRootsCopy()
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectGetCreator(LLUUID& id, LLString& name)
 {
-	LLSelectNode* node = getFirstRootNode();
-	if(!node) node = getFirstNode();
+	LLSelectNode* node = mSelectedObjects->getFirstRootNode();
+	if(!node) node = mSelectedObjects->getFirstNode();
 	if(!node) return FALSE;
 	if(!node->mValid) return FALSE;
 	LLViewerObject* obj = node->getObject();
@@ -2769,7 +2401,7 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& id, LLString& name)
 	id = node->mPermissions->getCreator();
 
 	BOOL identical = TRUE;
-	for ( node = getNextRootNode(); node; node = getNextRootNode() )
+	for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 	{
 		if (!node->mValid)
 		{
@@ -2808,8 +2440,8 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& id, LLString& name)
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectGetOwner(LLUUID& id, LLString& name)
 {
-	LLSelectNode* node = getFirstRootNode();
-	if(!node) node = getFirstNode();
+	LLSelectNode* node = mSelectedObjects->getFirstRootNode();
+	if(!node) node = mSelectedObjects->getFirstNode();
 	if(!node) return FALSE;
 	if(!node->mValid) return FALSE;
 	LLViewerObject* obj = node->getObject();
@@ -2821,7 +2453,7 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& id, LLString& name)
 	node->mPermissions->getOwnership(id, group_owner);
 
 	BOOL identical = TRUE;
-	for ( node = getNextRootNode(); node; node = getNextRootNode() )
+	for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 	{
 		if (!node->mValid)
 		{
@@ -2876,8 +2508,8 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& id, LLString& name)
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectGetLastOwner(LLUUID& id, LLString& name)
 {
-	LLSelectNode* node = getFirstRootNode();
-	if(!node) node = getFirstNode();
+	LLSelectNode* node = mSelectedObjects->getFirstRootNode();
+	if(!node) node = mSelectedObjects->getFirstNode();
 	if(!node) return FALSE;
 	if(!node->mValid) return FALSE;
 	LLViewerObject* obj = node->getObject();
@@ -2887,7 +2519,7 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& id, LLString& name)
 	id = node->mPermissions->getLastOwner();
 
 	BOOL identical = TRUE;
-	for ( node = getNextRootNode(); node; node = getNextRootNode() )
+	for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 	{
 		if (!node->mValid)
 		{
@@ -2935,8 +2567,8 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& id, LLString& name)
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectGetGroup(LLUUID& id)
 {
-	LLSelectNode* node = getFirstRootNode();
-	if(!node) node = getFirstNode();
+	LLSelectNode* node = mSelectedObjects->getFirstRootNode();
+	if(!node) node = mSelectedObjects->getFirstNode();
 	if(!node) return FALSE;
 	if(!node->mValid) return FALSE;
 	LLViewerObject* obj = node->getObject();
@@ -2946,7 +2578,7 @@ BOOL LLSelectMgr::selectGetGroup(LLUUID& id)
 	id = node->mPermissions->getGroup();
 
 	BOOL identical = TRUE;
-	for ( node = getNextRootNode(); node; node = getNextRootNode() )
+	for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 	{
 		if (!node->mValid)
 		{
@@ -2971,8 +2603,8 @@ BOOL LLSelectMgr::selectGetGroup(LLUUID& id)
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectIsGroupOwned()
 {
-	LLSelectNode* node = getFirstRootNode();
-	if(!node) node = getFirstNode();
+	LLSelectNode* node = mSelectedObjects->getFirstRootNode();
+	if(!node) node = mSelectedObjects->getFirstNode();
 	if(!node) return FALSE;
 	if(!node->mValid) return FALSE;
 	LLViewerObject* obj = node->getObject();
@@ -2983,7 +2615,7 @@ BOOL LLSelectMgr::selectIsGroupOwned()
 
 	if(is_group_owned)
 	{
-		for ( node = getNextRootNode(); node; node = getNextRootNode() )
+		for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 		{
 			if (!node->mValid)
 			{
@@ -3012,7 +2644,7 @@ BOOL LLSelectMgr::selectIsGroupOwned()
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off)
 {
-	LLSelectNode* node = getFirstRootNode();
+	LLSelectNode* node = mSelectedObjects->getFirstRootNode();
 	if (!node) return FALSE;
 	if (!node->mValid)	return FALSE;
 
@@ -3021,7 +2653,7 @@ BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off)
 	U32 mask_or		= 0x00000000;
 	BOOL all_valid	= TRUE;
 
-	for ( node = getFirstRootNode(); node; node = getNextRootNode() )
+	for ( node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 	{
 		if (!node->mValid)
 		{
@@ -3075,17 +2707,17 @@ BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off)
 
 BOOL LLSelectMgr::selectGetOwnershipCost(S32* out_cost)
 {
-	return mSelectedObjects.getOwnershipCost(*out_cost);
+	return mSelectedObjects->getOwnershipCost(*out_cost);
 }
 
 BOOL LLSelectMgr::selectGetPermissions(LLPermissions& perm)
 {
-	LLSelectNode* node = getFirstRootNode();
+	LLSelectNode* node = mSelectedObjects->getFirstRootNode();
 	if (!node) return FALSE;
 	if (!node->mValid)	return FALSE;
 	BOOL valid = TRUE;
 	perm = *(node->mPermissions);
-	for(node = getNextRootNode(); node != NULL; node = getNextRootNode())
+	for(node = mSelectedObjects->getNextRootNode(); node != NULL; node = mSelectedObjects->getNextRootNode())
 	{
 		if(!node->mValid)
 		{
@@ -3105,9 +2737,9 @@ void LLSelectMgr::selectDelete()
 	BOOL locked_but_deleteable_object = FALSE;
 	BOOL no_copy_but_deleteable_object = FALSE;
 	BOOL all_owned_by_you = TRUE;
-	for(LLViewerObject* obj = getFirstObject();
+	for(LLViewerObject* obj = mSelectedObjects->getFirstObject();
 		obj != NULL;
-		obj = getNextObject())
+		obj = mSelectedObjects->getNextObject())
 	{
 		if( obj->isAttachment() )
 		{
@@ -3226,13 +2858,13 @@ void LLSelectMgr::confirmDelete(S32 option, void* data)
 									(void*)info,
 									SEND_ONLY_ROOTS);
 			// VEFFECT: Delete Object - one effect for all deletes
-			if (self->mSelectType != SELECT_TYPE_HUD)
+			if (self->mSelectedObjects->mSelectType != SELECT_TYPE_HUD)
 			{
 				LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
 				effectp->setPositionGlobal( self->getSelectionCenterGlobal() );
 				effectp->setColor(LLColor4U(gAgent.getEffectColor()));
 				F32 duration = 0.5f;
-				duration += self->getObjectCount() / 64.f;
+				duration += self->mSelectedObjects->getObjectCount() / 64.f;
 				effectp->setDuration(duration);
 			}
 
@@ -3240,7 +2872,7 @@ void LLSelectMgr::confirmDelete(S32 option, void* data)
 
 			// Keep track of how many objects have been deleted.
 			F64 obj_delete_count = gViewerStats->getStat(LLViewerStats::ST_OBJECT_DELETE_COUNT);
-			obj_delete_count += self->getObjectCount();
+			obj_delete_count += self->mSelectedObjects->getObjectCount();
 			gViewerStats->setStat(LLViewerStats::ST_OBJECT_DELETE_COUNT, obj_delete_count );
 		}
 		break;
@@ -3270,7 +2902,7 @@ BOOL LLSelectMgr::selectIsForSale(S32& price)
 	price = 0;
 
 	LLSelectNode *node;
-	for (node = getFirstRootNode(); node; node = getNextRootNode() )
+	for (node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode() )
 	{
 		if (node->mSaleInfo.isForSale())
 		{
@@ -3287,12 +2919,12 @@ BOOL LLSelectMgr::selectIsForSale(S32& price)
 // accumulated sale info.
 BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& sale_info)
 {
-	LLSelectNode* node = getFirstRootNode();
+	LLSelectNode* node = mSelectedObjects->getFirstRootNode();
 	if (!node) return FALSE;
 	if (!node->mValid)	return FALSE;
 	BOOL valid = TRUE;
 	sale_info = node->mSaleInfo;
-	for(node = getNextRootNode(); node != NULL; node = getNextRootNode())
+	for(node = mSelectedObjects->getNextRootNode(); node != NULL; node = mSelectedObjects->getNextRootNode())
 	{
 		if(!node->mValid)
 		{
@@ -3306,12 +2938,12 @@ BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& sale_info)
 
 BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& ag_perm)
 {
-	LLSelectNode* node = getFirstNode();
+	LLSelectNode* node = mSelectedObjects->getFirstNode();
 	if (!node) return FALSE;
 	if (!node->mValid)	return FALSE;
 	BOOL valid = TRUE;
 	ag_perm = node->mAggregatePerm;
-	for(node = getNextNode(); node != NULL; node = getNextNode())
+	for(node = mSelectedObjects->getNextNode(); node != NULL; node = mSelectedObjects->getNextNode())
 	{
 		if(!node->mValid)
 		{
@@ -3325,12 +2957,12 @@ BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& ag_perm)
 
 BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& ag_perm)
 {
-	LLSelectNode* node = getFirstNode();
+	LLSelectNode* node = mSelectedObjects->getFirstNode();
 	if (!node) return FALSE;
 	if (!node->mValid)	return FALSE;
 	BOOL valid = TRUE;
 	ag_perm = node->getObject()->permYouOwner() ? node->mAggregateTexturePermOwner : node->mAggregateTexturePerm;
-	for(node = getNextNode(); node != NULL; node = getNextNode())
+	for(node = mSelectedObjects->getNextNode(); node != NULL; node = mSelectedObjects->getNextNode())
 	{
 		if(!node->mValid)
 		{
@@ -3343,12 +2975,6 @@ BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& a
 }
 
 
-// returns TRUE is any node is currenly worn as an attachment
-BOOL LLSelectMgr::selectionIsAttachment()
-{
-	return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD);
-}
-
 //--------------------------------------------------------------------
 // Duplicate objects
 //--------------------------------------------------------------------
@@ -3364,7 +2990,7 @@ struct LLDuplicateData
 
 void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy)
 {
-	if (selectionIsAttachment())
+	if (mSelectedObjects->isAttachment())
 	{
 		//RN: do not duplicate attachments
 		make_ui_sound("UISndInvalidOp");
@@ -3384,7 +3010,7 @@ void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy)
 	}
 	else
 	{
-		for (LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode())
+		for (LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode())
 		{
 			node->mDuplicated = TRUE;
 			node->mDuplicatePos = node->getObject()->getPositionGlobal();
@@ -3395,7 +3021,7 @@ void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy)
 
 void LLSelectMgr::repeatDuplicate()
 {
-	if (selectionIsAttachment())
+	if (mSelectedObjects->isAttachment())
 	{
 		//RN: do not duplicate attachments
 		make_ui_sound("UISndInvalidOp");
@@ -3405,7 +3031,7 @@ void LLSelectMgr::repeatDuplicate()
 	LLSelectNode* node;
 	LLDynamicArray<LLViewerObject*> non_duplicated_objects;
 
-	for (node = getFirstRootNode(); node; node = getNextRootNode())
+	for (node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode())
 	{
 		if (!node->mDuplicated)
 		{
@@ -3428,7 +3054,7 @@ void LLSelectMgr::repeatDuplicate()
 	sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS);
 
 	// move current selection based on delta from duplication position and update duplication position
-	for (node = getFirstRootNode(); node; node = getNextRootNode())
+	for (node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode())
 	{
 		if (node->mDuplicated)
 		{
@@ -3483,7 +3109,7 @@ void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region,
 									   BOOL copy_rotates,
 									   BOOL select_copy)
 {
-	if (selectionIsAttachment())
+	if (mSelectedObjects->isAttachment())
 	{
 		// do not duplicate attachments
 		make_ui_sound("UISndInvalidOp");
@@ -3695,7 +3321,7 @@ struct LLPermData
 };
 
 // TODO: Make this able to fail elegantly.
-void LLSelectMgr::setObjectPermissions(U8 field,
+void LLSelectMgr::selectionSetObjectPermissions(U8 field,
 									   BOOL set,
 									   U32 mask,
 									   BOOL override)
@@ -3732,7 +3358,7 @@ void LLSelectMgr::sendSelect()
 
 void LLSelectMgr::deselectAll()
 {
-	if (!mSelectedObjects.getNumNodes())
+	if (!mSelectedObjects->getNumNodes())
 	{
 		return;
 	}
@@ -3753,42 +3379,29 @@ void LLSelectMgr::deselectAll()
 	updateSelectionCenter();
 }
 
-void LLSelectMgr::deselectTransient()
+void LLSelectMgr::deselectUnused()
 {
-	std::set<LLViewerObject*> objects_to_deselect;
-	LLSelectNode *nodep;
-	for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode())
+	// no more outstanding references to this selection
+	if (mSelectedObjects->getNumRefs() == 1)
 	{
-		if (nodep->isTransient())
-		{
-			objects_to_deselect.insert(nodep->getObject());
-		}
-	}
-
-	std::set<LLViewerObject*>::iterator iter;
-	for (iter = objects_to_deselect.begin();
-		iter != objects_to_deselect.end();
-		++iter)
-	{
-		deselectObjectOnly(*iter);
+		deselectAll();
 	}
-
-	gHUDManager->clearJoints();
-	updateSelectionCenter();
 }
 
 void LLSelectMgr::convertTransient()
 {
-	LLSelectNode *nodep;
-	for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode())
+	// use STL-style iteration to avoid recursive iteration problems
+	LLObjectSelection::iterator node_it;
+	for (node_it = mSelectedObjects->begin(); node_it != mSelectedObjects->end(); ++node_it)
 	{
+		LLSelectNode *nodep = *node_it;
 		nodep->setTransient(FALSE);
 	}
 }
 
 void LLSelectMgr::deselectAllIfTooFar()
 {
-	if (isEmpty() || mSelectType == SELECT_TYPE_HUD)
+	if (mSelectedObjects->isEmpty() || mSelectedObjects->mSelectType == SELECT_TYPE_HUD)
 	{
 		return;
 	}
@@ -3825,10 +3438,10 @@ void LLSelectMgr::deselectAllIfTooFar()
 }
 
 
-void LLSelectMgr::setObjectName(const LLString& name)
+void LLSelectMgr::selectionSetObjectName(const LLString& name)
 {
 	// we only work correctly if 1 object is selected.
-	if(getRootObjectCount() == 1)
+	if(mSelectedObjects->getRootObjectCount() == 1)
 	{
 		sendListToRegions("ObjectName",
 						  packAgentAndSessionID,
@@ -3836,7 +3449,7 @@ void LLSelectMgr::setObjectName(const LLString& name)
 						  (void*)name.c_str(),
 						  SEND_ONLY_ROOTS);
 	}
-	else if(getObjectCount() == 1)
+	else if(mSelectedObjects->getObjectCount() == 1)
 	{
 		sendListToRegions("ObjectName",
 						  packAgentAndSessionID,
@@ -3846,10 +3459,10 @@ void LLSelectMgr::setObjectName(const LLString& name)
 	}
 }
 
-void LLSelectMgr::setObjectDescription(const LLString& desc)
+void LLSelectMgr::selectionSetObjectDescription(const LLString& desc)
 {
 	// we only work correctly if 1 object is selected.
-	if(getRootObjectCount() == 1)
+	if(mSelectedObjects->getRootObjectCount() == 1)
 	{
 		sendListToRegions("ObjectDescription",
 						  packAgentAndSessionID,
@@ -3857,7 +3470,7 @@ void LLSelectMgr::setObjectDescription(const LLString& desc)
 						  (void*)desc.c_str(),
 						  SEND_ONLY_ROOTS);
 	}
-	else if(getObjectCount() == 1)
+	else if(mSelectedObjects->getObjectCount() == 1)
 	{
 		sendListToRegions("ObjectDescription",
 						  packAgentAndSessionID,
@@ -3867,11 +3480,11 @@ void LLSelectMgr::setObjectDescription(const LLString& desc)
 	}
 }
 
-void LLSelectMgr::setObjectCategory(const LLCategory& category)
+void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category)
 {
 	// for now, we only want to be able to set one root category at
 	// a time.
-	if(getRootObjectCount() != 1) return;
+	if(mSelectedObjects->getRootObjectCount() != 1) return;
 	sendListToRegions("ObjectCategory",
 					  packAgentAndSessionID,
 					  packObjectCategory,
@@ -3879,10 +3492,10 @@ void LLSelectMgr::setObjectCategory(const LLCategory& category)
 					  SEND_ONLY_ROOTS);
 }
 
-void LLSelectMgr::setObjectSaleInfo(const LLSaleInfo& sale_info)
+void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info)
 {
 	// Only one sale info at a time for now
-	if(getRootObjectCount() != 1) return;
+	if(mSelectedObjects->getRootObjectCount() != 1) return;
 	sendListToRegions("ObjectSaleInfo",
 					  packAgentAndSessionID,
 					  packObjectSaleInfo,
@@ -3896,9 +3509,9 @@ void LLSelectMgr::setObjectSaleInfo(const LLSaleInfo& sale_info)
 
 void LLSelectMgr::sendAttach(U8 attachment_point)
 {
-	LLViewerObject* attach_object = mSelectedObjects.getFirstRootObject();
+	LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject();
 
-	if (!attach_object || !gAgent.getAvatarObject() || mSelectType != SELECT_TYPE_WORLD)
+	if (!attach_object || !gAgent.getAvatarObject() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD)
 	{
 		return;
 	}
@@ -3964,7 +3577,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point)
 
 void LLSelectMgr::sendDetach()
 {
-	if (!mSelectedObjects.getNumNodes() || mSelectType == SELECT_TYPE_WORLD)
+	if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD)
 	{
 		return;
 	}
@@ -3980,7 +3593,7 @@ void LLSelectMgr::sendDetach()
 
 void LLSelectMgr::sendDropAttachment()
 {
-	if (!mSelectedObjects.getNumNodes() || mSelectType == SELECT_TYPE_WORLD)
+	if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD)
 	{
 		return;
 	}
@@ -3999,7 +3612,7 @@ void LLSelectMgr::sendDropAttachment()
 
 void LLSelectMgr::sendLink()
 {
-	if (!mSelectedObjects.getNumNodes())
+	if (!mSelectedObjects->getNumNodes())
 	{
 		return;
 	}
@@ -4014,7 +3627,7 @@ void LLSelectMgr::sendLink()
 
 void LLSelectMgr::sendDelink()
 {
-	if (!mSelectedObjects.getNumNodes())
+	if (!mSelectedObjects->getNumNodes())
 	{
 		return;
 	}
@@ -4036,7 +3649,7 @@ void LLSelectMgr::sendDelink()
 
 void LLSelectMgr::sendHinge(U8 type)
 {
-	if (!mSelectedObjects.getNumNodes())
+	if (!mSelectedObjects->getNumNodes())
 	{
 		return;
 	}
@@ -4052,7 +3665,7 @@ void LLSelectMgr::sendHinge(U8 type)
 
 void LLSelectMgr::sendDehinge()
 {
-	if (!mSelectedObjects.getNumNodes())
+	if (!mSelectedObjects->getNumNodes())
 	{
 		return;
 	}
@@ -4067,7 +3680,7 @@ void LLSelectMgr::sendDehinge()
 
 void LLSelectMgr::sendSelect()
 {
-	if (!mSelectedObjects.getNumNodes())
+	if (!mSelectedObjects->getNumNodes())
 	{
 		return;
 	}
@@ -4097,7 +3710,7 @@ void LLSelectMgr::selectionDump()
 {
 	LLViewerObject *object;
 
-	for (object = getFirstObject(); object; object = getNextObject() )
+	for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		object->dump();
 	}
@@ -4106,7 +3719,7 @@ void LLSelectMgr::selectionDump()
 void LLSelectMgr::saveSelectedObjectColors()
 {
 	LLSelectNode* selectNode;
-	for (selectNode = getFirstNode(); selectNode; selectNode = getNextNode() )
+	for (selectNode = mSelectedObjects->getFirstNode(); selectNode; selectNode = mSelectedObjects->getNextNode() )
 	{
 		selectNode->saveColors();
 	}
@@ -4117,7 +3730,7 @@ void LLSelectMgr::saveSelectedObjectTextures()
 	LLSelectNode*		selectNode;
 
 	// invalidate current selection so we update saved textures
-	for (selectNode = getFirstNode(); selectNode; selectNode = getNextNode() )
+	for (selectNode = mSelectedObjects->getFirstNode(); selectNode; selectNode = mSelectedObjects->getNextNode() )
 	{
 		selectNode->mValid = FALSE;
 	}
@@ -4133,13 +3746,13 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type)
 {
 	LLSelectNode*		selectNode;
 
-	if (isEmpty())
+	if (mSelectedObjects->isEmpty())
 	{
 		// nothing selected, so nothing to save
 		return;
 	}
 
-	for (selectNode = getFirstNode(); selectNode; selectNode = getNextNode() )
+	for (selectNode = mSelectedObjects->getFirstNode(); selectNode; selectNode = mSelectedObjects->getNextNode() )
 	{
 		LLViewerObject*		object;
 		object = selectNode->getObject();
@@ -4170,42 +3783,6 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type)
 		selectNode->mSavedScale = object->getScale();
 		selectNode->saveTextureScaleRatios();
 
-		if (object->isAttachment() && 
-			action_type != SELECT_ACTION_TYPE_PICK)
-		{
-			LLSelectAction*		selectAction = new LLSelectAction();
-			selectAction->mActionType = action_type;
-			selectAction->mPosition = object->getPosition();
-			selectAction->mRotation = object->getRotation();
-			selectAction->mScale = object->getScale();
-			selectAction->mObjectID = object->getID();
-			selectAction->mIndividualSelection = selectNode->mIndividualSelection;
-
-			mUndoQueue.push_back(selectAction);
-
-			while ((mUndoQueue.size() > (U32)MAX_ACTION_QUEUE_SIZE))
-			{
-				LLSelectAction* action = mUndoQueue.front();
-				mUndoQueue.pop_front();
-				delete action;
-			}
-	
-			// remove this object from the redo queue
-			std::deque<LLSelectAction*>::iterator it;
-			for (it = mRedoQueue.begin(); it != mRedoQueue.end();)
-			{
-				if ((*it)->mObjectID == object->getID())
-				{
-					LLSelectAction* actionp = *it;
-					it = mRedoQueue.erase(it);
-					delete actionp;
-				}
-				else
-				{
-					++it;
-				}
-			}
-		}
 	}
 	mSavedSelectionBBox = getBBoxOfSelection();
 }
@@ -4214,7 +3791,7 @@ void LLSelectMgr::selectionUpdatePhysics(BOOL physics)
 {
 	LLViewerObject *object;
 
-	for (object = getFirstObject(); object; object = getNextObject() )
+	for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (   !object->permModify()  		// preemptive permissions check
 			|| !(object->isRoot()			// don't send for child objects
@@ -4230,7 +3807,7 @@ void LLSelectMgr::selectionUpdateTemporary(BOOL is_temporary)
 {
 	LLViewerObject *object;
 
-	for (object = getFirstObject(); object; object = getNextObject() )
+	for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (   !object->permModify()  		// preemptive permissions check
 			|| !(object->isRoot()			// don't send for child objects
@@ -4246,7 +3823,7 @@ void LLSelectMgr::selectionUpdatePhantom(BOOL is_phantom)
 {
 	LLViewerObject *object;
 
-	for (object = getFirstObject(); object; object = getNextObject() )
+	for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (   !object->permModify()  		// preemptive permissions check
 			|| !(object->isRoot()			// don't send for child objects
@@ -4262,7 +3839,7 @@ void LLSelectMgr::selectionUpdateCastShadows(BOOL cast_shadows)
 {
 	LLViewerObject *object;
 
-	for (object = getFirstObject(); object; object = getNextObject() )
+	for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 	{
 		if (   !object->permModify()  		// preemptive permissions check
 			|| object->isJointChild())
@@ -4491,65 +4068,65 @@ void LLSelectMgr::sendListToRegions(const LLString& message_name,
 	switch(send_type)
 	{
 	case SEND_ONLY_ROOTS:
-		node = mSelectedObjects.getFirstRootNode();
+		node = mSelectedObjects->getFirstRootNode();
 		while(node)
 		{
 			nodes_to_send.push(node);
-			node = mSelectedObjects.getNextRootNode();
+			node = mSelectedObjects->getNextRootNode();
 		}
 		break;
 	case SEND_INDIVIDUALS:
-		node = mSelectedObjects.getFirstNode();
+		node = mSelectedObjects->getFirstNode();
 		while(node)
 		{
 			nodes_to_send.push(node);
-			node = mSelectedObjects.getNextNode();
+			node = mSelectedObjects->getNextNode();
 		}
 		break;
 	case SEND_ROOTS_FIRST:
 		// first roots...
-		node = mSelectedObjects.getFirstNode();
+		node = mSelectedObjects->getFirstNode();
 		while(node)
 		{
 			if (node->getObject()->isRootEdit())
 			{
 				nodes_to_send.push(node);
 			}
-			node = mSelectedObjects.getNextNode();
+			node = mSelectedObjects->getNextNode();
 		}
 
 		// then children...
-		node = mSelectedObjects.getFirstNode();
+		node = mSelectedObjects->getFirstNode();
 		while(node)
 		{
 			if (!node->getObject()->isRootEdit())
 			{
 				nodes_to_send.push(node);
 			}
-			node = mSelectedObjects.getNextNode();
+			node = mSelectedObjects->getNextNode();
 		}
 		break;
 	case SEND_CHILDREN_FIRST:
 		// first children...
-		node = mSelectedObjects.getFirstNode();
+		node = mSelectedObjects->getFirstNode();
 		while(node)
 		{
 			if (!node->getObject()->isRootEdit())
 			{
 				nodes_to_send.push(node);
 			}
-			node = mSelectedObjects.getNextNode();
+			node = mSelectedObjects->getNextNode();
 		}
 
 		// ...then roots
-		node = mSelectedObjects.getFirstNode();
+		node = mSelectedObjects->getFirstNode();
 		while(node)
 		{
 			if (node->getObject()->isRootEdit())
 			{
 				nodes_to_send.push(node);
 			}
-			node = mSelectedObjects.getNextNode();
+			node = mSelectedObjects->getNextNode();
 		}
 		break;
 
@@ -4731,9 +4308,9 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data
 		// Iterate through nodes at end, since it can be on both the regular AND hover list
 		BOOL found = FALSE;
 		LLSelectNode* node;
-		for (node = gSelectMgr->mSelectedObjects.getFirstNode();
+		for (node = gSelectMgr->mSelectedObjects->getFirstNode();
 			 node;
-			 node = gSelectMgr->mSelectedObjects.getNextNode())
+			 node = gSelectMgr->mSelectedObjects->getNextNode())
 		{
 			if (node->getObject()->mID == id)
 			{
@@ -4881,9 +4458,9 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
 	// Now look through all of the hovered nodes
 	BOOL found = FALSE;
 	LLSelectNode* node;
-	for (node = gSelectMgr->mHoverObjects.getFirstNode();
+	for (node = gSelectMgr->mHoverObjects->getFirstNode();
 		 node;
-		 node = gSelectMgr->mHoverObjects.getNextNode())
+		 node = gSelectMgr->mHoverObjects->getNextNode())
 	{
 		if (node->getObject()->mID == id)
 		{
@@ -4966,7 +4543,7 @@ void LLSelectMgr::updateSilhouettes()
 
 	if((cameraPos - mLastCameraPos).magVecSquared() > SILHOUETTE_UPDATE_THRESHOLD_SQUARED * currentCameraZoom * currentCameraZoom)
 	{
-		for (node = mSelectedObjects.getFirstNode(); node; node = mSelectedObjects.getNextNode() )
+		for (node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() )
 		{
 			if (node->getObject())
 			{
@@ -4979,7 +4556,7 @@ void LLSelectMgr::updateSilhouettes()
 	
 	LLDynamicArray<LLViewerObject*> changed_objects;
 
-	if (mSelectedObjects.getNumNodes())
+	if (mSelectedObjects->getNumNodes())
 	{
 		//gGLSPipelineSelection.set();
 
@@ -4988,7 +4565,7 @@ void LLSelectMgr::updateSilhouettes()
 
 		for (S32 pass = 0; pass < 2; pass++)
 		{
-			for (node = mSelectedObjects.getFirstNode(); node; node = mSelectedObjects.getNextNode() )
+			for (node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() )
 			{
 				LLViewerObject* objectp = node->getObject();
 
@@ -5058,7 +4635,7 @@ void LLSelectMgr::updateSilhouettes()
 		// remove highlight nodes not in roots list
 		LLDynamicArray<LLSelectNode*> remove_these_nodes;
 		LLDynamicArray<LLViewerObject*> remove_these_roots;
-		for (LLSelectNode* nodep = mHighlightedObjects.getFirstNode(); nodep; nodep = mHighlightedObjects.getNextNode())
+		for (LLSelectNode* nodep = mHighlightedObjects->getFirstNode(); nodep; nodep = mHighlightedObjects->getNextNode())
 		{
 			LLViewerObject* objectp = nodep->getObject();
 			if (objectp->isRoot() || !select_linked_set)
@@ -5087,7 +4664,7 @@ void LLSelectMgr::updateSilhouettes()
 		S32 i;
 		for (i = 0; i < remove_these_nodes.count(); i++)
 		{
-			mHighlightedObjects.removeNode(remove_these_nodes[i]);
+			mHighlightedObjects->removeNode(remove_these_nodes[i]);
 		}
 
 		// remove all root objects already being highlighted
@@ -5109,7 +4686,7 @@ void LLSelectMgr::updateSilhouettes()
 				continue;
 			}
 
-			mHighlightedObjects.addNode(rect_select_node);
+			mHighlightedObjects->addNode(rect_select_node);
 
 			if (!select_linked_set)
 			{
@@ -5128,7 +4705,7 @@ void LLSelectMgr::updateSilhouettes()
 
 					rect_select_node = new LLSelectNode(objectp->mChildList[i], TRUE);
 					rect_select_node->selectAllTEs(TRUE);
-					mHighlightedObjects.addNode(rect_select_node);
+					mHighlightedObjects->addNode(rect_select_node);
 				}
 			}
 		}
@@ -5139,7 +4716,7 @@ void LLSelectMgr::updateSilhouettes()
 		//BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL);
 		for (S32 pass = 0; pass < 2; pass++)
 		{
-			for (node = mHighlightedObjects.getFirstNode(); node; node = mHighlightedObjects.getNextNode() )
+			for (node = mHighlightedObjects->getFirstNode(); node; node = mHighlightedObjects->getNextNode() )
 			{
 				LLViewerObject* objectp = node->getObject();
 
@@ -5188,7 +4765,7 @@ void LLSelectMgr::updateSilhouettes()
 	}
 	else
 	{
-		mHighlightedObjects.deleteAllNodes();
+		mHighlightedObjects->deleteAllNodes();
 	}
 
 	for (S32 i = 0; i < changed_objects.count(); i++)
@@ -5235,13 +4812,13 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 		glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
 		glScalef(cur_zoom, cur_zoom, cur_zoom);
 	}
-	if (mSelectedObjects.getNumNodes())
+	if (mSelectedObjects->getNumNodes())
 	{
 		glPushAttrib(GL_FOG_BIT);
 		LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID();
 		for (S32 pass = 0; pass < 2; pass++)
 		{
-			for (node = mSelectedObjects.getFirstNode(); node; node = mSelectedObjects.getNextNode() )
+			for (node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() )
 			{
 				LLViewerObject* objectp = node->getObject();
 				if (objectp->isHUDAttachment() != for_hud)
@@ -5272,13 +4849,13 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
 		glPopAttrib();
 	}
 
-	if (mHighlightedObjects.getNumNodes())
+	if (mHighlightedObjects->getNumNodes())
 	{
 		// render silhouettes for highlighted objects
 		BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL);
 		for (S32 pass = 0; pass < 2; pass++)
 		{
-			for (node = mHighlightedObjects.getFirstNode(); node; node = mHighlightedObjects.getNextNode() )
+			for (node = mHighlightedObjects->getFirstNode(); node; node = mHighlightedObjects->getNextNode() )
 			{
 				LLViewerObject* objectp = node->getObject();
 				if (objectp->isHUDAttachment() != for_hud)
@@ -5889,7 +5466,7 @@ void LLSelectMgr::updateSelectionCenter()
 	const F32 MOVE_SELECTION_THRESHOLD = 1.f;		//  Movement threshold in meters for updating selection
 													//  center (tractor beam)
 
-	LLViewerObject* object = mSelectedObjects.getFirstObject();
+	LLViewerObject* object = mSelectedObjects->getFirstObject();
 	if (!object)
 	{
 		// nothing selected, probably grabbing
@@ -5906,9 +5483,9 @@ void LLSelectMgr::updateSelectionCenter()
 	}
 	else
 	{
-		mSelectType = getSelectTypeForObject(object);
+		mSelectedObjects->mSelectType = getSelectTypeForObject(object);
 
-		if (mSelectType == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
+		if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject())
 		{
 			mPauseRequest = gAgent.getAvatarObject()->requestPause();
 		}
@@ -5917,7 +5494,7 @@ void LLSelectMgr::updateSelectionCenter()
 			mPauseRequest = NULL;
 		}
 
-		if (mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject())
+		if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject())
 		{
 			// reset hud ZOOM
 			gAgent.getAvatarObject()->mHUDTargetZoom = 1.f;
@@ -5933,11 +5510,11 @@ void LLSelectMgr::updateSelectionCenter()
 		gHUDManager->clearJoints();
 		LLDynamicArray < LLViewerObject *> jointed_objects;
 
-		for (object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() )
+		for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() )
 		{
 			LLViewerObject *myAvatar = gAgent.getAvatarObject();
 			LLViewerObject *root = object->getRootEdit();
-			if (mSelectType == SELECT_TYPE_WORLD && // not an attachment
+			if (mSelectedObjects->mSelectType == SELECT_TYPE_WORLD && // not an attachment
 				!root->isChild(myAvatar) && // not the object you're sitting on
 				!object->isAvatar()) // not another avatar
 			{
@@ -5964,7 +5541,7 @@ void LLSelectMgr::updateSelectionCenter()
 	
 	if ( !(gAgentID == LLUUID::null) ) 
 	{
-		LLTool		*tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) );
+		LLTool		*tool = gToolMgr->getCurrentTool();
 		if (mShowSelection)
 		{
 			LLVector3d select_center_global;
@@ -5991,7 +5568,7 @@ void LLSelectMgr::updateSelectionCenter()
 	}
 
 	// give up edit menu if no objects selected
-	if (gEditMenuHandler == this && getObjectCount() == 0)
+	if (gEditMenuHandler == this && mSelectedObjects->getObjectCount() == 0)
 	{
 		gEditMenuHandler = NULL;
 	}
@@ -6001,7 +5578,7 @@ void LLSelectMgr::updatePointAt()
 {
 	if (mShowSelection)
 	{
-		if (getObjectCount())
+		if (mSelectedObjects->getObjectCount())
 		{					
 			LLVector3 select_offset;
 			LLViewerObject *click_object = gObjectList.findObject(gLastHitObjectID);
@@ -6017,8 +5594,8 @@ void LLSelectMgr::updatePointAt()
 			else
 			{
 				// didn't click on an object this time, revert to pointing at center of first object
-				gAgent.setPointAt(POINTAT_TARGET_SELECT, getFirstObject());
-				gAgent.setLookAt(LOOKAT_TARGET_SELECT, getFirstObject());
+				gAgent.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject());
+				gAgent.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject());
 			}
 		}
 		else
@@ -6048,7 +5625,7 @@ LLBBox LLSelectMgr::getBBoxOfSelection() const
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::canUndo()
 {
-	return getFirstEditableObject() != NULL;
+	return mSelectedObjects->getFirstEditableObject() != NULL;
 }
 
 //-----------------------------------------------------------------------------
@@ -6066,7 +5643,7 @@ void LLSelectMgr::undo()
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::canRedo()
 {
-	return getFirstEditableObject() != NULL;
+	return mSelectedObjects->getFirstEditableObject() != NULL;
 }
 
 //-----------------------------------------------------------------------------
@@ -6084,7 +5661,7 @@ void LLSelectMgr::redo()
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::canDoDelete()
 {
-	return getFirstDeleteableObject() != NULL;
+	return mSelectedObjects->getFirstDeleteableObject() != NULL;
 }
 
 //-----------------------------------------------------------------------------
@@ -6100,7 +5677,7 @@ void LLSelectMgr::doDelete()
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::canDeselect()
 {
-	return !isEmpty();
+	return !mSelectedObjects->isEmpty();
 }
 
 //-----------------------------------------------------------------------------
@@ -6115,7 +5692,7 @@ void LLSelectMgr::deselect()
 //-----------------------------------------------------------------------------
 BOOL LLSelectMgr::canDuplicate()
 {
-	return getFirstCopyableObject() != NULL;
+	return mSelectedObjects->getFirstCopyableObject() != NULL;
 }
 //-----------------------------------------------------------------------------
 // duplicate()
@@ -6125,161 +5702,42 @@ void LLSelectMgr::duplicate()
 	LLVector3 offset(0.5f, 0.5f, 0.f);
 	selectDuplicate(offset, TRUE);
 }
-//-----------------------------------------------------------------------------
-// undoRedo()
-//-----------------------------------------------------------------------------
-U32 LLSelectMgr::undoRedo(std::deque<LLSelectAction*> &queue_src, std::deque<LLSelectAction*> &queue_dst, const LLUUID &object_id)
+
+ESelectType LLSelectMgr::getSelectTypeForObject(LLViewerObject* object)
 {
-	if (queue_src.size() == 0)
+	if (!object)
 	{
-		return 0;
+		return SELECT_TYPE_WORLD;
 	}
+	if (object->isHUDAttachment())
+	{
+		return SELECT_TYPE_HUD;
+	}
+	else if (object->isAttachment())
+	{
+		return SELECT_TYPE_ATTACHMENT;
+	}
+	else
+	{
+		return SELECT_TYPE_WORLD;
+	}
+}
 
-	U32 update_type = 0;
-	std::deque<LLSelectAction*> temp_queue;
-	LLSelectAction* src_actionp = queue_src.back();
-
-	while (src_actionp->mObjectID != object_id)
+void LLSelectMgr::validateSelection()
+{
+	LLViewerObject* objectp;
+	for (objectp = mSelectedObjects->getFirstObject(); objectp; objectp = mSelectedObjects->getNextObject())
 	{
-		temp_queue.push_back(src_actionp);
-		queue_src.pop_back();
-		if (!queue_src.size())
+		if (!canSelectObject(objectp))
 		{
-			// put everything back
-			LLSelectAction* actionp;
-			while (temp_queue.size())
-			{
-				actionp = temp_queue.back();
-				temp_queue.pop_back();
-				queue_src.push_back(actionp);
-			}
-			return 0;
+			deselectObjectOnly(objectp);
 		}
-		src_actionp = queue_src.back();
 	}
+}
 
-	if(src_actionp)
-	{
-		LLSelectAction* dst_actionp = new LLSelectAction();
-		dst_actionp->mActionType = src_actionp->mActionType;
-		dst_actionp->mObjectID = src_actionp->mObjectID;
-		dst_actionp->mIndividualSelection = src_actionp->mIndividualSelection;
-
-		LLViewerObject* object = gObjectList.findObject(src_actionp->mObjectID);
-		if (object && object->mDrawable.notNull())
-		{
-			LLVector3 old_position_local = object->getPosition();
-
-			switch(src_actionp->mActionType)
-			{
-			case SELECT_ACTION_TYPE_MOVE:
-				dst_actionp->mPosition = object->mDrawable->getPosition();
-				object->setPosition(src_actionp->mPosition, TRUE);
-				if (object->isRootEdit() && src_actionp->mIndividualSelection)
-				{
-					// counter-translate children
-					LLVector3 parent_offset = (src_actionp->mPosition - old_position_local) * ~object->getRotation();
-
-					// counter-translate child objects if we are moving the root as an individual
-					for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++)
-					{
-						LLViewerObject* childp = object->mChildList[child_num];
-						childp->setPosition(childp->getPosition() - parent_offset);
-					}
-				}
-				update_type |= UPD_POSITION;
-				break;
-			case SELECT_ACTION_TYPE_ROTATE:
-				dst_actionp->mPosition = object->mDrawable->getPosition();
-				dst_actionp->mRotation = object->mDrawable->getRotation();
-				object->setRotation(src_actionp->mRotation, TRUE);
-				object->setPosition(src_actionp->mPosition, TRUE);
-				if (object->isRootEdit() && src_actionp->mIndividualSelection)
-				{
-					// counter-translate and rotate children
-					LLVector3 parent_offset = (src_actionp->mPosition - old_position_local) * ~object->getRotation();
-
-					for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++)
-					{
-						LLViewerObject* childp = object->mChildList[child_num];
-						LLQuaternion delta_rot_inv = dst_actionp->mRotation * ~src_actionp->mRotation;
-						childp->setPosition((childp->getPosition() * delta_rot_inv) - parent_offset);
-						childp->setRotation(childp->getRotation() * delta_rot_inv );
-					}
-				}
-				update_type |= UPD_ROTATION | UPD_POSITION;
-				break;
-			case SELECT_ACTION_TYPE_SCALE:
-				dst_actionp->mPosition = object->mDrawable->getPosition();
-				dst_actionp->mScale = object->getScale();
-				object->setScale(src_actionp->mScale, TRUE);
-				object->setPosition(src_actionp->mPosition, TRUE);
-				update_type |= UPD_SCALE | UPD_POSITION;
-				break;
-			default:
-				// do nothing
-				break;
-			}
-		}
-		queue_src.pop_back();
-		delete src_actionp;
-		queue_dst.push_back(dst_actionp);
-		while (queue_dst.size() > (U32)MAX_ACTION_QUEUE_SIZE)
-		{
-			LLSelectAction* action = queue_dst.front();
-			queue_dst.pop_front();
-			delete action;
-		}
-
-	}
-
-	// put everything back
-	LLSelectAction* actionp;
-	while (temp_queue.size())
-	{
-		actionp = temp_queue.back();
-		temp_queue.pop_back();
-		queue_src.push_back(actionp);
-	}
-
-	return update_type;
-}
-
-ESelectType LLSelectMgr::getSelectTypeForObject(LLViewerObject* object)
-{
-	if (!object)
-	{
-		return SELECT_TYPE_WORLD;
-	}
-	if (object->isHUDAttachment())
-	{
-		return SELECT_TYPE_HUD;
-	}
-	else if (object->isAttachment())
-	{
-		return SELECT_TYPE_ATTACHMENT;
-	}
-	else
-	{
-		return SELECT_TYPE_WORLD;
-	}
-}
-
-void LLSelectMgr::validateSelection()
-{
-	LLViewerObject* objectp;
-	for (objectp = getFirstObject(); objectp; objectp = getNextObject())
-	{
-		if (!canSelectObject(objectp))
-		{
-			deselectObjectOnly(objectp);
-		}
-	}
-}
-
-BOOL LLSelectMgr::canSelectObject(LLViewerObject* object)
-{
-	if (mForceSelection)
+BOOL LLSelectMgr::canSelectObject(LLViewerObject* object)
+{
+	if (mForceSelection)
 	{
 		return TRUE;
 	}
@@ -6304,44 +5762,47 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object)
 	if (object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) return FALSE;
 
 	ESelectType selection_type = getSelectTypeForObject(object);
-	if (getObjectCount() > 0 && mSelectType != selection_type) return FALSE;
+	if (mSelectedObjects->getObjectCount() > 0 && mSelectedObjects->mSelectType != selection_type) return FALSE;
 
 	return TRUE;
 }
 
-LLSelectNodeList::LLSelectNodeList() : std::list<LLSelectNode*>()
+LLObjectSelection::LLObjectSelection() : 
+	std::list<LLSelectNode*>(), 
+	LLRefCount(),
+	mCurrentTE(-1),
+	mCurrentNode(end()),
+	mSelectType(SELECT_TYPE_WORLD)
 {
-	mCurrentTE = -1;
-	mCurrentNode = end();
 }
 
-LLSelectNodeList::~LLSelectNodeList()
+LLObjectSelection::~LLObjectSelection()
 {
 	std::for_each(begin(), end(), DeletePointer());
 }
 
-void LLSelectNodeList::updateEffects()
+void LLObjectSelection::updateEffects()
 {
 }
 
-S32 LLSelectNodeList::getNumNodes()
+S32 LLObjectSelection::getNumNodes()
 {
 	return size();
 }
 
-void LLSelectNodeList::addNode(LLSelectNode *nodep)
+void LLObjectSelection::addNode(LLSelectNode *nodep)
 {
 	push_front(nodep);
 	mSelectNodeMap[nodep->getObject()] = nodep;
 }
 
-void LLSelectNodeList::addNodeAtEnd(LLSelectNode *nodep)
+void LLObjectSelection::addNodeAtEnd(LLSelectNode *nodep)
 {
 	push_back(nodep);
 	mSelectNodeMap[nodep->getObject()] = nodep;
 }
 
-void LLSelectNodeList::removeNode(LLSelectNode *nodep)
+void LLObjectSelection::removeNode(LLSelectNode *nodep)
 {
 	std::list<LLSelectNode*>::iterator iter = begin();
 	while(iter != end())
@@ -6358,14 +5819,14 @@ void LLSelectNodeList::removeNode(LLSelectNode *nodep)
 	}
 }
 
-void LLSelectNodeList::deleteAllNodes()
+void LLObjectSelection::deleteAllNodes()
 {
 	std::for_each(begin(), end(), DeletePointer());
 	clear();
 	mSelectNodeMap.clear();
 }
 
-LLSelectNode* LLSelectNodeList::findNode(LLViewerObject* objectp)
+LLSelectNode* LLObjectSelection::findNode(LLViewerObject* objectp)
 {
 	std::map<LLViewerObject*, LLSelectNode*>::iterator found_it = mSelectNodeMap.find(objectp);
 	if (found_it != mSelectNodeMap.end())
@@ -6378,7 +5839,7 @@ LLSelectNode* LLSelectNodeList::findNode(LLViewerObject* objectp)
 //-----------------------------------------------------------------------------
 // getFirstNode()
 //-----------------------------------------------------------------------------
-LLSelectNode *LLSelectNodeList::getFirstNode()
+LLSelectNode *LLObjectSelection::getFirstNode()
 {
 	mCurrentNode = begin();//getFirstData();
 
@@ -6399,7 +5860,7 @@ LLSelectNode *LLSelectNodeList::getFirstNode()
 //-----------------------------------------------------------------------------
 // getCurrentNode()
 //-----------------------------------------------------------------------------
-LLSelectNode *LLSelectNodeList::getCurrentNode()
+LLSelectNode *LLObjectSelection::getCurrentNode()
 {
 	while (mCurrentNode != end() && !(*mCurrentNode)->getObject())
 	{
@@ -6417,7 +5878,7 @@ LLSelectNode *LLSelectNodeList::getCurrentNode()
 //-----------------------------------------------------------------------------
 // getNextNode()
 //-----------------------------------------------------------------------------
-LLSelectNode *LLSelectNodeList::getNextNode()
+LLSelectNode *LLObjectSelection::getNextNode()
 {
 	++mCurrentNode;
 
@@ -6439,7 +5900,7 @@ LLSelectNode *LLSelectNodeList::getNextNode()
 //-----------------------------------------------------------------------------
 // getFirstObject()
 //-----------------------------------------------------------------------------
-LLViewerObject* LLSelectNodeList::getFirstObject()
+LLViewerObject* LLObjectSelection::getFirstObject()
 {
 	mCurrentNode = begin();
 
@@ -6461,7 +5922,7 @@ LLViewerObject* LLSelectNodeList::getFirstObject()
 //-----------------------------------------------------------------------------
 // getNextObject()
 //-----------------------------------------------------------------------------
-LLViewerObject* LLSelectNodeList::getNextObject()
+LLViewerObject* LLObjectSelection::getNextObject()
 {
 	++mCurrentNode;// = getNextData();
 
@@ -6484,7 +5945,7 @@ LLViewerObject* LLSelectNodeList::getNextObject()
 //-----------------------------------------------------------------------------
 // getPrimaryTE()
 //-----------------------------------------------------------------------------
-void LLSelectNodeList::getPrimaryTE(LLViewerObject* *object, S32 *te)
+void LLObjectSelection::getPrimaryTE(LLViewerObject* *object, S32 *te)
 {
 	// initialize object and te
 	*te = 0;
@@ -6539,7 +6000,7 @@ void LLSelectNodeList::getPrimaryTE(LLViewerObject* *object, S32 *te)
 //-----------------------------------------------------------------------------
 // getFirstTE()
 //-----------------------------------------------------------------------------
-void LLSelectNodeList::getFirstTE(LLViewerObject* *object, S32 *te)
+void LLObjectSelection::getFirstTE(LLViewerObject* *object, S32 *te)
 {
 	// start with first face
 	mCurrentTE = 0;
@@ -6593,7 +6054,7 @@ void LLSelectNodeList::getFirstTE(LLViewerObject* *object, S32 *te)
 //-----------------------------------------------------------------------------
 // getNextFace()
 //-----------------------------------------------------------------------------
-void LLSelectNodeList::getNextTE(LLViewerObject* *object, S32 *te)
+void LLObjectSelection::getNextTE(LLViewerObject* *object, S32 *te)
 {
 	// try next face
 	mCurrentTE++;
@@ -6636,7 +6097,7 @@ void LLSelectNodeList::getNextTE(LLViewerObject* *object, S32 *te)
 	return;
 }
 
-void LLSelectNodeList::getCurrentTE(LLViewerObject* *object, S32 *te)
+void LLObjectSelection::getCurrentTE(LLViewerObject* *object, S32 *te)
 {
 	if (mCurrentNode != end())
 	{
@@ -6652,7 +6113,7 @@ void LLSelectNodeList::getCurrentTE(LLViewerObject* *object, S32 *te)
 //-----------------------------------------------------------------------------
 // getFirstRootNode()
 //-----------------------------------------------------------------------------
-LLSelectNode *LLSelectNodeList::getFirstRootNode()
+LLSelectNode *LLObjectSelection::getFirstRootNode()
 {
 	LLSelectNode *cur_node = getFirstNode();
 
@@ -6671,7 +6132,7 @@ LLSelectNode *LLSelectNodeList::getFirstRootNode()
 //-----------------------------------------------------------------------------
 // getNextRootNode()
 //-----------------------------------------------------------------------------
-LLSelectNode *LLSelectNodeList::getNextRootNode()
+LLSelectNode *LLObjectSelection::getNextRootNode()
 {
 	LLSelectNode *cur_node = getNextNode();
 
@@ -6689,7 +6150,7 @@ LLSelectNode *LLSelectNodeList::getNextRootNode()
 //-----------------------------------------------------------------------------
 // getFirstRootObject()
 //-----------------------------------------------------------------------------
-LLViewerObject *LLSelectNodeList::getFirstRootObject()
+LLViewerObject *LLObjectSelection::getFirstRootObject()
 {
 	LLSelectNode *node = getFirstRootNode();
 
@@ -6707,7 +6168,7 @@ LLViewerObject *LLSelectNodeList::getFirstRootObject()
 //-----------------------------------------------------------------------------
 // getNextRootObject()
 //-----------------------------------------------------------------------------
-LLViewerObject *LLSelectNodeList::getNextRootObject()
+LLViewerObject *LLObjectSelection::getNextRootObject()
 {
 	LLSelectNode *node = getNextRootNode();
 
@@ -6724,7 +6185,7 @@ LLViewerObject *LLSelectNodeList::getNextRootObject()
 //-----------------------------------------------------------------------------
 // isEmpty()
 //-----------------------------------------------------------------------------
-BOOL LLSelectNodeList::isEmpty()
+BOOL LLObjectSelection::isEmpty()
 {
 	return (size() == 0);
 }
@@ -6732,7 +6193,7 @@ BOOL LLSelectNodeList::isEmpty()
 //-----------------------------------------------------------------------------
 // getOwnershipCost()
 //-----------------------------------------------------------------------------
-BOOL LLSelectNodeList::getOwnershipCost(S32 &cost)
+BOOL LLObjectSelection::getOwnershipCost(S32 &cost)
 {
 	S32 count = 0;
 	for( LLSelectNode* nodep = getFirstNode(); nodep; nodep = getNextNode() )
@@ -6744,3 +6205,341 @@ BOOL LLSelectNodeList::getOwnershipCost(S32 &cost)
 
 	return (count > 0);
 }
+
+
+
+//-----------------------------------------------------------------------------
+// getObjectCount()
+//-----------------------------------------------------------------------------
+S32 LLObjectSelection::getObjectCount()
+{
+	return getNumNodes();
+}
+
+
+//-----------------------------------------------------------------------------
+// getTECount()
+//-----------------------------------------------------------------------------
+S32 LLObjectSelection::getTECount()
+{
+	S32 count = 0;
+
+	LLSelectNode* nodep;
+	for (nodep = getFirstNode(); nodep; nodep = getNextNode() )
+	{
+		if (nodep->getObject())
+		{
+			S32 num_tes = nodep->getObject()->getNumTEs();
+			for (S32 te = 0; te < num_tes; te++)
+			{
+				if (nodep->isTESelected(te))
+				{
+					count++;
+				}
+			}
+		}
+	}
+
+	return count;
+}
+
+//-----------------------------------------------------------------------------
+// getRootObjectCount()
+//-----------------------------------------------------------------------------
+S32 LLObjectSelection::getRootObjectCount()
+{
+	LLSelectNode *nodep;
+
+	S32 count = 0;
+	for(nodep = getFirstRootNode(); nodep; nodep = getNextRootNode())
+	{
+		++count;
+	}
+	return count;
+}
+
+bool LLObjectSelection::applyToObjects(LLSelectedObjectFunctor* func)
+{
+	bool result = true;
+	LLViewerObject* object;
+	for (object = getFirstObject(); object != NULL; object = getNextObject())
+	{
+		result = result && func->apply(object);
+	}
+	return result;
+}
+
+bool LLObjectSelection::applyToRootObjects(LLSelectedObjectFunctor* func)
+{
+	bool result = true;
+	LLViewerObject* object;
+	for (object = getFirstRootObject(); 
+		 object != NULL; 
+		 object = getNextRootObject())
+	{
+		result = result && func->apply(object);
+	}
+	return result;
+}
+
+bool LLObjectSelection::applyToNodes(LLSelectedNodeFunctor *func)
+{
+	bool result = true;
+	LLSelectNode* node;
+	for (node = getFirstNode(); node != NULL; node = getNextNode())
+	{
+		result = result && func->apply(node);
+	}
+	return result;
+}
+
+//-----------------------------------------------------------------------------
+// contains()
+//-----------------------------------------------------------------------------
+BOOL LLObjectSelection::contains(LLViewerObject* object)
+{
+	return findNode(object) != NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+// contains()
+//-----------------------------------------------------------------------------
+BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te)
+{
+	LLSelectNode *nodep;
+	if (te == SELECT_ALL_TES)
+	{
+		// ...all faces
+		for (nodep = getFirstNode(); nodep; nodep = getNextNode() )
+		{
+			if (nodep->getObject() == object)
+			{
+				BOOL all_selected = TRUE;
+				for (S32 i = 0; i < SELECT_MAX_TES; i++)
+				{
+					all_selected = all_selected && nodep->isTESelected(i);
+				}
+				return all_selected;
+			}
+		}
+		return FALSE;
+	}
+	else
+	{
+		// ...one face
+		for (nodep = getFirstNode(); nodep; nodep = getNextNode() )
+		{
+			if (nodep->getObject() == object && nodep->isTESelected(te))
+			{
+				return TRUE;
+			}
+		}
+		return FALSE;
+	}
+}
+
+// returns TRUE is any node is currenly worn as an attachment
+BOOL LLObjectSelection::isAttachment()
+{
+	return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD);
+}
+
+//-----------------------------------------------------------------------------
+// getFirstMoveableNode()
+//-----------------------------------------------------------------------------
+LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root)
+{
+	LLSelectNode* selectNode = NULL;
+
+	if (get_root)
+	{
+		for(selectNode = getFirstRootNode(); selectNode; selectNode = getNextRootNode())
+		{
+			if( selectNode->getObject()->permMove() )
+			{
+				return selectNode;
+				break;
+			}
+		}
+	}
+	for(selectNode = getFirstNode(); selectNode; selectNode = getNextNode())
+	{
+		if( selectNode->getObject()->permMove() )
+		{
+			return selectNode;
+			break;
+		}
+	}
+	
+	return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// getFirstCopyableObject()
+//-----------------------------------------------------------------------------
+LLViewerObject* LLObjectSelection::getFirstCopyableObject(BOOL get_root)
+{
+	LLViewerObject* object = NULL;
+	for(LLViewerObject* cur = getFirstObject(); cur; cur = getNextObject())
+	{
+		if( cur->permCopy() && !cur->isAttachment())
+		{
+			object = cur;
+			break;
+		}
+	}	
+
+	if (get_root && object)
+	{
+		LLViewerObject *parent;
+		while ((parent = (LLViewerObject*)object->getParent()))
+		{
+			if (parent->isSelected())
+			{
+				object = parent;
+			}
+			else
+			{
+				break;
+			}
+		}
+	}
+
+	return object;
+}
+
+
+//-----------------------------------------------------------------------------
+// getFirstDeleteableObject()
+//-----------------------------------------------------------------------------
+LLViewerObject* LLObjectSelection::getFirstDeleteableObject(BOOL get_root)
+{
+	//RN: don't currently support deletion of child objects, as that requires separating them first
+	// then derezzing to trash
+	get_root = TRUE;
+
+	LLViewerObject* object = NULL;
+	if (get_root)
+	{
+		for(LLViewerObject* current = getFirstRootObject();
+			current != NULL;
+			current = getNextRootObject())
+		{
+			// you can delete an object if permissions allow it, you are
+			// the owner, you are an officer in the group that owns the
+			// object, or you are not the owner but it is on land you own
+			// or land owned by your group. (whew!)
+			if(   (current->permModify()) 
+			|| (current->permYouOwner())
+			|| (!current->permAnyOwner())			// public
+			|| (current->isOverAgentOwnedLand())
+			|| (current->isOverGroupOwnedLand())
+			)
+			{
+
+				if( !current->isAttachment() )
+				{
+					object = current;
+					break;
+				}
+			}
+		}	
+	}
+	else
+	{
+		for(LLViewerObject* current = getFirstObject();
+			current != NULL;
+			current = getNextObject())
+		{
+			// you can delete an object if permissions allow it, you are
+			// the owner, you are an officer in the group that owns the
+			// object, or you are not the owner but it is on land you own
+			// or land owned by your group. (whew!)
+			if(   (current->permModify()) 
+			|| (current->permYouOwner())
+			|| (!current->permAnyOwner())			// public
+			|| (current->isOverAgentOwnedLand())
+			|| (current->isOverGroupOwnedLand())
+			)
+			{
+				if( !current->isAttachment() )
+				{
+					object = current;
+					break;
+				}
+			}
+		}	
+	}
+
+	return object;
+}
+
+
+//-----------------------------------------------------------------------------
+// getFirstEditableObject()
+//-----------------------------------------------------------------------------
+LLViewerObject* LLObjectSelection::getFirstEditableObject(BOOL get_root)
+{
+	LLViewerObject* object = NULL;
+	for(LLViewerObject* cur = getFirstObject(); cur; cur = getNextObject())
+	{
+		if( cur->permModify() )
+		{
+			object = cur;
+			break;
+		}
+	}	
+
+	if (get_root && object)
+	{
+		LLViewerObject *parent;
+		while ((parent = (LLViewerObject*)object->getParent()))
+		{
+			if (parent->isSelected())
+			{
+				object = parent;
+			}
+			else
+			{
+				break;
+			}
+		}
+	}
+
+	return object;
+}
+
+//-----------------------------------------------------------------------------
+// getFirstMoveableObject()
+//-----------------------------------------------------------------------------
+LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_root)
+{
+	LLViewerObject* object = NULL;
+	for(LLViewerObject* cur = getFirstObject(); cur; cur = getNextObject())
+	{
+		if( cur->permMove() )
+		{
+			object = cur;
+			break;
+		}
+	}	
+
+	if (get_root && object && !object->isJointChild())
+	{
+		LLViewerObject *parent;
+		while ((parent = (LLViewerObject*)object->getParent()))
+		{
+			if (parent->isSelected())
+			{
+				object = parent;
+			}
+			else
+			{
+				break;
+			}
+		}
+	}
+
+	return object;
+}
\ No newline at end of file
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 77c1206b894573e0bd8f4f40aeb8b2ec30e5d734..2b1568fb458d3d29f1f1bc1aead1b3138d85f0e6 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -91,11 +91,12 @@ typedef enum e_selection_type
 	SELECT_TYPE_HUD
 }ESelectType;
 
-class LLSelectNodeList : public std::list<LLSelectNode*>
+class LLObjectSelection : public std::list<LLSelectNode*>, public LLRefCount
 {
+	friend class LLSelectMgr;
 public:
-	LLSelectNodeList();
-	virtual ~LLSelectNodeList();
+	LLObjectSelection();
+	virtual ~LLObjectSelection();
 
 	void updateEffects();
 
@@ -110,6 +111,8 @@ class LLSelectNodeList : public std::list<LLSelectNode*>
 	LLSelectNode *getFirstRootNode();
 	LLSelectNode *getNextRootNode();
 
+	LLSelectNode*	getFirstMoveableNode(BOOL get_root = FALSE);
+
 	// iterate through objects
 	LLViewerObject* getFirstObject();
 	LLViewerObject* getNextObject();
@@ -118,6 +121,11 @@ class LLSelectNodeList : public std::list<LLSelectNode*>
 	LLViewerObject *getFirstRootObject();
 	LLViewerObject *getNextRootObject();
 
+	LLViewerObject*	getFirstEditableObject(BOOL get_root = FALSE);
+	LLViewerObject*	getFirstCopyableObject(BOOL get_root = FALSE);
+	LLViewerObject* getFirstDeleteableObject(BOOL get_root = FALSE);
+	LLViewerObject*	getFirstMoveableObject(BOOL get_root = FALSE);
+
 	// iterate through texture entries
 	void getPrimaryTE(LLViewerObject* *object, S32 *te);
 	void getFirstTE(LLViewerObject* *object, S32 *te);
@@ -130,24 +138,36 @@ class LLSelectNodeList : public std::list<LLSelectNode*>
 	void deleteAllNodes();			// Delete all nodes
 	S32 getNumNodes();
 	LLSelectNode* findNode(LLViewerObject* objectp);
+
+	// count members
+	S32 getObjectCount();
+	S32 getTECount();
+	S32 getRootObjectCount();
+
+	BOOL contains(LLViewerObject* object);
+	BOOL contains(LLViewerObject* object, S32 te);
+
+	// returns TRUE is any node is currenly worn as an attachment
+	BOOL isAttachment();
+
+	// Apply functors to various subsets of the selected objects
+	// Returns the AND of all apply() calls.
+	bool applyToRootObjects(LLSelectedObjectFunctor* func);
+	bool applyToObjects(LLSelectedObjectFunctor* func);
+	bool applyToNodes(LLSelectedNodeFunctor* func);
+
+	ESelectType getSelectType() { return mSelectType; }
+
 private:
-	const LLSelectNodeList &operator=(const LLSelectNodeList &);
+	const LLObjectSelection &operator=(const LLObjectSelection &);
 
-	std::list<LLSelectNode*>::iterator mCurrentNode;
-	S32 mCurrentTE;
-	std::map<LLViewerObject*, LLSelectNode*> mSelectNodeMap;
+	std::list<LLSelectNode*>::iterator			mCurrentNode;
+	S32											mCurrentTE;
+	std::map<LLViewerObject*, LLSelectNode*>	mSelectNodeMap;
+	ESelectType									mSelectType;
 };
 
-struct LLSelectAction
-{
-public:
-	EActionType	mActionType;
-	LLVector3	mPosition;
-	LLVector3	mScale;
-	LLQuaternion	mRotation;
-	LLUUID		mObjectID;
-	BOOL		mIndividualSelection;
-};
+typedef LLHandle<LLObjectSelection> LLObjectSelectionHandle;
 
 class LLSelectMgr : public LLEditMenuHandler
 {
@@ -168,6 +188,7 @@ class LLSelectMgr : public LLEditMenuHandler
 	static LLColor4				sHighlightChildColor;
 	static LLColor4				sHighlightInspectColor;
 	static LLColor4				sContextSilhouetteColor;
+
 public:
 	LLSelectMgr();
 	~LLSelectMgr();
@@ -188,115 +209,90 @@ class LLSelectMgr : public LLEditMenuHandler
 	virtual void duplicate();
 	virtual BOOL canDuplicate();
 
-	// Apply functors to various subsets of the selected objects
-	// Returns the AND of all apply() calls.
-	bool applyToRootObjects(LLSelectedObjectFunctor* func);
-	bool applyToObjects(LLSelectedObjectFunctor* func);
-	bool applyToNodes(LLSelectedNodeFunctor* func);
-
 	void updateEffects(); // Update HUD effects
 
 	void setForceSelection(BOOL force) { mForceSelection = force; }
 
+	////////////////////////////////////////////////////////////////
+	// Selection methods
+	////////////////////////////////////////////////////////////////
+
+	////////////////////////////////////////////////////////////////
+	// Add
+	////////////////////////////////////////////////////////////////
+
 	// For when you want just a child object.
-	void selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES);
+	LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES);
 
 	// This method is meant to select an object, and then select all
 	// of the ancestors and descendents. This should be the normal behavior.
-	void selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE);
+	LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE);
 
 	// Same as above, but takes a list of objects.  Used by rectangle select.
-	void selectObjectAndFamily(const LLDynamicArray<LLViewerObject*>& object_list, BOOL send_to_sim = TRUE);
+	LLObjectSelectionHandle selectObjectAndFamily(const LLDynamicArray<LLViewerObject*>& object_list, BOOL send_to_sim = TRUE);
 
-	void deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim = TRUE);
+	// converts all objects currently highlighted to a selection, and returns it
+	LLObjectSelectionHandle selectHighlightedObjects();
 
-	void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE);
+	LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp);
 
-	void deselectTransient(); // deselect "temporarily" selected objects (via pie menu)
-	void convertTransient(); // converts temporarily selected objects to full-fledged selections
+	void highlightObjectOnly(LLViewerObject *objectp);
+	void highlightObjectAndFamily(LLViewerObject *objectp);
+	void highlightObjectAndFamily(const LLDynamicArray<LLViewerObject*>& list);
+
+	////////////////////////////////////////////////////////////////
+	// Remove
+	////////////////////////////////////////////////////////////////
+
+	void deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim = TRUE);
+	void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE);
 
 	// Send deselect messages to simulator, then clear the list
 	void deselectAll();
 
+	// deselect only if nothing else currently referencing the selection
+	void deselectUnused();
+
 	// Deselect if the selection center is too far away from the agent.
 	void deselectAllIfTooFar();
 
-	BOOL selectionRemoveObject(const LLUUID &id);
-
-	BOOL contains(LLViewerObject* object);
-	BOOL contains(LLViewerObject* object, S32 te);
-
-	ESelectType getSelectType() { return mSelectType; }
-
-	// count members
-	S32 getObjectCount();
-	S32 getTECount();
-	S32 getRootObjectCount();
-
-	BOOL isEmpty()				{ return !mSelectedObjects.getNumNodes(); }
-
-	BOOL shouldShowSelection()	{ return mShowSelection; }
-
-	LLSelectNodeList &getHoverObjects() { return mHoverObjects; }
-	LLSelectNodeList &getSelectedObjects() { return mSelectedObjects; }
-
-	// iterate through objects
-	LLViewerObject* getFirstObject()	{ return mSelectedObjects.getFirstObject(); }
-	LLViewerObject* getNextObject()		{ return mSelectedObjects.getNextObject(); }
-
-	// iterate through root objects
-	LLViewerObject *getFirstRootObject()	{ return mSelectedObjects.getFirstRootObject(); }
-	LLViewerObject *getNextRootObject()		{ return mSelectedObjects.getNextRootObject(); }
-
-	LLViewerObject* getFirstHighlightedObject() { return mHighlightedObjects.getFirstObject(); }
-	LLViewerObject* getNextHighlightedObject() { return mHighlightedObjects.getNextObject(); }
-
-	// iterate through tes
-	void getPrimaryTE(LLViewerObject* *object, S32 *te) { mSelectedObjects.getPrimaryTE(object, te); }
-	void getFirstTE(LLViewerObject* *object, S32 *te)	{ mSelectedObjects.getFirstTE(object, te); }
-	void getNextTE(LLViewerObject* *object, S32 *te)	{ mSelectedObjects.getNextTE(object, te); };
-
-	void setHoverObject(LLViewerObject *objectp);
-	
-	void addGridObject(LLViewerObject* objectp);
-	void clearGridObjects();
-	void setGridMode(EGridMode mode);
-	EGridMode getGridMode() { return mGridMode; }
-	void getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale);
+	// Removes all highlighted objects from current selection
+	void deselectHighlightedObjects();
 
-	void highlightObjectOnly(LLViewerObject *objectp);
-	void highlightObjectAndFamily(LLViewerObject *objectp);
-	void highlightObjectAndFamily(const LLDynamicArray<LLViewerObject*>& list);
 	void unhighlightObjectOnly(LLViewerObject *objectp);
 	void unhighlightObjectAndFamily(LLViewerObject *objectp);
 	void unhighlightAll();
-	void selectHighlightedObjects();
-	void deselectHighlightedObjects();
 
-	LLSelectNode *findSelectNode(LLViewerObject *objectp);
-	LLSelectNode *getFirstRootNode()	{ return mSelectedObjects.getFirstRootNode(); }
-	LLSelectNode *getNextRootNode()		{ return mSelectedObjects.getNextRootNode(); }
-	LLSelectNode* getFirstNode()	{ return mSelectedObjects.getFirstNode(); }
-	LLSelectNode* getNextNode()		{ return mSelectedObjects.getNextNode(); }
+	BOOL removeObjectFromSelections(const LLUUID &id);
+
+	////////////////////////////////////////////////////////////////
+	// Selection accessors
+	////////////////////////////////////////////////////////////////
+	LLObjectSelectionHandle	getHoverObjects() { return mHoverObjects; }
+	LLObjectSelectionHandle	getSelection() { return mSelectedObjects; }
+	// right now this just renders the selection with root/child colors instead of a single color
+	LLObjectSelectionHandle	getEditSelection() { convertTransient(); return mSelectedObjects; }
+	LLObjectSelectionHandle	getHighlightedObjects() { return mHighlightedObjects; }
 
 	LLSelectNode *getHoverNode();
 
+	////////////////////////////////////////////////////////////////
+	// Grid manipulation
+	////////////////////////////////////////////////////////////////
+	void			addGridObject(LLViewerObject* objectp);
+	void			clearGridObjects();
+	void			setGridMode(EGridMode mode);
+	EGridMode		getGridMode() { return mGridMode; }
+	void			getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale);
+
 	BOOL getTEMode()			{ return mTEMode; }
 	void setTEMode(BOOL b)	{ mTEMode = b; }
 
-	LLViewerObject*	getFirstCopyableObject(BOOL get_root = FALSE);
-	LLViewerObject*	getFirstEditableObject(BOOL get_root = FALSE);
-	LLViewerObject*	getFirstMoveableObject(BOOL get_root = FALSE);
-	LLViewerObject* getFirstDeleteableObject(BOOL get_root = FALSE);
-
-	LLSelectNode*	getFirstEditableNode(BOOL get_root = FALSE);
-	LLSelectNode*	getFirstMoveableNode(BOOL get_root = FALSE);
+	BOOL shouldShowSelection()	{ return mShowSelection; }
 
 	LLBBox getBBoxOfSelection() const;
 	LLBBox getSavedBBoxOfSelection() const { return mSavedSelectionBBox; }
 
-	BOOL areMultpleEditableObjectsSelected();
-
 	void dump();
 	void cleanup();
 
@@ -304,17 +300,18 @@ class LLSelectMgr : public LLEditMenuHandler
 	void renderSilhouettes(BOOL for_hud);
 	void enableSilhouette(BOOL enable) { mRenderSilhouettes = enable; }
 	
-	// Utility functions to operate on the list
-
-	void			saveSelectedObjectTransform(EActionType action_type);
-	void			saveSelectedObjectColors();
-	void			saveSelectedObjectTextures();
-
-	void			selectionUpdatePhysics(BOOL use_physics);
-	void			selectionUpdateTemporary(BOOL is_temporary);
-	void			selectionUpdatePhantom(BOOL is_ghost);
-	void			selectionUpdateCastShadows(BOOL cast_shadows);
-	void			selectionDump();
+	////////////////////////////////////////////////////////////////
+	// Utility functions that operate on the current selection
+	////////////////////////////////////////////////////////////////
+	void saveSelectedObjectTransform(EActionType action_type);
+	void saveSelectedObjectColors();
+	void saveSelectedObjectTextures();
+
+	void selectionUpdatePhysics(BOOL use_physics);
+	void selectionUpdateTemporary(BOOL is_temporary);
+	void selectionUpdatePhantom(BOOL is_ghost);
+	void selectionUpdateCastShadows(BOOL cast_shadows);
+	void selectionDump();
 
 	BOOL selectionAllPCode(LLPCode code);		// all objects have this PCode
 	BOOL selectionGetMaterial(U8 *material);	// all objects have same material
@@ -343,11 +340,11 @@ class LLSelectMgr : public LLEditMenuHandler
 	void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url );
 	void selectionSetClickAction(U8 action);
 
-	void setObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE);
-	void setObjectName(const LLString& name);
-	void setObjectDescription(const LLString& desc);
-	void setObjectCategory(const LLCategory& category);
-	void setObjectSaleInfo(const LLSaleInfo& sale_info);
+	void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE);
+	void selectionSetObjectName(const LLString& name);
+	void selectionSetObjectDescription(const LLString& desc);
+	void selectionSetObjectCategory(const LLCategory& category);
+	void selectionSetObjectSaleInfo(const LLSaleInfo& sale_info);
 
 	void selectionTexScaleAutofit(F32 repeats_per_meter);
 	void selectionResetTexInfo(S32 te);						// sets S,T to 1
@@ -414,23 +411,20 @@ class LLSelectMgr : public LLEditMenuHandler
 	// with the aggregate permissions for texture inventory items of the selection.
 	BOOL selectGetAggregateTexturePermissions(LLAggregatePermissions& ag_perm);
 
-	// returns TRUE is any node is currenly worn as an attachment
-	BOOL selectionIsAttachment();
-
 	LLPermissions* findObjectPermissions(const LLViewerObject* object);
 
 	void selectDelete();							// Delete on simulator
-	void	selectForceDelete();			// just delete, no into trash
+	void selectForceDelete();			// just delete, no into trash
 	void selectDuplicate(const LLVector3& offset, BOOL select_copy);	// Duplicate on simulator
 	void repeatDuplicate();
-	void		selectDuplicateOnRay(const LLVector3 &ray_start_region,
-									   const LLVector3 &ray_end_region,
-									   BOOL bypass_raycast,
-									   BOOL ray_end_is_intersection,
-									   const LLUUID &ray_target_id,
-									   BOOL copy_centers,
-									   BOOL copy_rotates,
-									   BOOL select_copy);
+	void selectDuplicateOnRay(const LLVector3 &ray_start_region,
+								const LLVector3 &ray_end_region,
+								BOOL bypass_raycast,
+								BOOL ray_end_is_intersection,
+								const LLUUID &ray_target_id,
+								BOOL copy_centers,
+								BOOL copy_rotates,
+								BOOL select_copy);
 
 	void sendMultipleUpdate(U32 type);	// Position, rotation, scale all in one
 	void sendOwner(const LLUUID& owner_id, const LLUUID& group_id, BOOL override = FALSE);
@@ -471,7 +465,7 @@ class LLSelectMgr : public LLEditMenuHandler
 	void demoteSelectionToIndividuals();
 
 private:
-	
+	void convertTransient(); // converts temporarily selected objects to full-fledged selections
 	ESelectType getSelectTypeForObject(LLViewerObject* object);
 	void addAsFamily(LLDynamicArray<LLViewerObject*>& objects, BOOL add_to_end = FALSE);
 	void generateSilhouette(LLSelectNode *nodep, const LLVector3& view_point);
@@ -482,7 +476,6 @@ class LLSelectMgr : public LLEditMenuHandler
 							void (*pack_body)(LLSelectNode* node, void *user_data), 
 							void *user_data,
 							ESendType send_type);
-	U32 undoRedo(std::deque<LLSelectAction*> &queue_src, std::deque<LLSelectAction*> &queue_dst, const LLUUID &object_id);
 
 	static void packAgentID(	void *);
 	static void packAgentAndSessionID(void* user_data);
@@ -517,22 +510,19 @@ class LLSelectMgr : public LLEditMenuHandler
 	static void confirmDelete(S32 option, void* data);
 	
 private:
-	LLPointer<LLViewerImage> mSilhouetteImagep;
-
-	LLSelectNodeList		mSelectedObjects;
-
-	LLSelectNodeList		mHoverObjects;
-
+	LLPointer<LLViewerImage>				mSilhouetteImagep;
+	LLObjectSelectionHandle					mSelectedObjects;
+	LLObjectSelectionHandle					mHoverObjects;
+	LLObjectSelectionHandle					mHighlightedObjects;
 	std::set<LLPointer<LLViewerObject> >	mRectSelectedObjects;
 	
-	LLSelectNodeList		mGridObjects;
+	LLObjectSelection		mGridObjects;
 	LLQuaternion			mGridRotation;
 	LLVector3				mGridOrigin;
 	LLVector3				mGridScale;
 	EGridMode				mGridMode;
 	BOOL					mGridValid;
 
-	LLSelectNodeList		mHighlightedObjects;
 
 	BOOL					mTEMode;			// render te
 	LLVector3d				mSelectionCenterGlobal;
@@ -544,15 +534,10 @@ class LLSelectMgr : public LLEditMenuHandler
 	BOOL					mRenderSilhouettes;	// do we render the silhouette
 	LLBBox					mSavedSelectionBBox;
 
-	ESelectType				mSelectType;
-
 	LLFrameTimer			mEffectsTimer;
 	BOOL					mForceSelection;
 
-	std::deque<LLSelectAction*>	mUndoQueue;
-	std::deque<LLSelectAction*>	mRedoQueue;
-
-	LLAnimPauseRequest	mPauseRequest;
+	LLAnimPauseRequest		mPauseRequest;
 };
 
 
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 5eae8c2ff1ed82c0c3c183b6acbd8ba9a8301aa1..b2f2a861ed57aa9723b537612b533bf0bb92550e 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -296,7 +296,7 @@ void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b)
 
 void LLFloaterTexturePicker::stopUsingPipette()
 {
-	if (gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette)
+	if (gToolMgr && gToolMgr->getCurrentTool() == gToolPipette)
 	{
 		gToolMgr->clearTransientTool();
 	}
@@ -451,7 +451,7 @@ void LLFloaterTexturePicker::draw()
 	childSetEnabled("show_folders_check", mActive && mCanApplyImmediately && !mNoCopyTextureSelected);
 	childSetEnabled("Select", mActive);
 	childSetEnabled("Pipette", gToolMgr != NULL && mActive);
-	childSetValue("Pipette", gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette);
+	childSetValue("Pipette", gToolMgr && gToolMgr->getCurrentTool() == gToolPipette);
 
 	//RN: reset search bar to reflect actual search query (all caps, for example)
 	mSearchEdit->setText(mInventoryPanel->getFilterSubString());
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 01bc0bd5fdb37f25c924d39a3771c4594a98d8b5..d115cf1158d1e954d739709d6158ab0cd9f137a2 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -131,7 +131,8 @@ void LLTextureView::draw()
 			{
 				S32 te;
 				LLViewerObject *objectp;
-				for (gSelectMgr->getFirstTE(&objectp, &te); objectp; gSelectMgr->getNextTE(&objectp, &te))
+				LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+				for (selection->getFirstTE(&objectp, &te); objectp; selection->getNextTE(&objectp, &te))
 				{
 					if (imagep == objectp->getTEImage(te))
 					{
diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp
index f9ff070289df9a165ecf500518172b268b09ae7c..1053e4a56951a8df8f0a222527975a4b673b19e4 100644
--- a/indra/newview/lltool.cpp
+++ b/indra/newview/lltool.cpp
@@ -16,6 +16,7 @@
 
 #include "llviewerwindow.h"
 #include "lltoolcomp.h"
+#include "lltoolfocus.h"
 #include "llfocusmgr.h"
 #include "llagent.h"
 #include "llviewborder.h"
@@ -135,6 +136,14 @@ BOOL LLTool::handleKey(KEY key, MASK mask)
 	return FALSE;
 }
 
+LLTool* LLTool::getOverrideTool(MASK mask)
+{
+	if (mask & MASK_ALT)
+	{
+		return gToolCamera;
+	}
+	return NULL;
+}
 
 // static
 void	LLTool::onMouseCaptureLost( LLMouseHandler* old_captor )
diff --git a/indra/newview/lltool.h b/indra/newview/lltool.h
index f0e1b170bd7728e716abeac2ed7c59ff66aabbfd..d67a0d7d24c15af723aaf257e15261d8127e6662 100644
--- a/indra/newview/lltool.h
+++ b/indra/newview/lltool.h
@@ -58,6 +58,8 @@ class LLTool
 	virtual void			handleSelect()			{ }	// do stuff when your tool is selected
 	virtual void			handleDeselect()		{ }	// clean up when your tool is deselected
 
+	virtual LLTool*			getOverrideTool(MASK mask);
+
 	// isAlwaysRendered() - return true if this is a tool that should
 	// always be rendered regardless of selection.
 	virtual BOOL isAlwaysRendered() { return FALSE; }
diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp
index 8255008aa0a38d345c6150fae6c0eebaeaefd1d2..e56635e1810ed624192bdb83a2836efa1d1d7e81 100644
--- a/indra/newview/lltoolbrush.cpp
+++ b/indra/newview/lltoolbrush.cpp
@@ -163,7 +163,7 @@ void LLToolBrushLand::modifyLandInSelectionGlobal()
 		return;
 	}
 
-	if (gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolParcel)
+	if (gToolMgr->getCurrentTool() == gToolParcel)
 	{
 		// selecting land, don't do anything
 		return;
@@ -282,8 +282,8 @@ void LLToolBrushLand::modifyLandInSelectionGlobal()
 		msg->addF32Fast(_PREHASH_Seconds, seconds);
 		msg->addF32Fast(_PREHASH_Height, mStartingZ);
 
-		BOOL parcel_selected = gParcelMgr->getWholeParcelSelected();
-		LLParcel* selected_parcel = gParcelMgr->getSelectedParcel();
+		BOOL parcel_selected = gParcelMgr->getParcelSelection()->getWholeParcelSelected();
+		LLParcel* selected_parcel = gParcelMgr->getParcelSelection()->getParcel();
 
 		if (parcel_selected && selected_parcel)
 		{
@@ -516,7 +516,7 @@ void LLToolBrushLand::onIdle( void* brush_tool )
 {
 	LLToolBrushLand* self = reinterpret_cast<LLToolBrushLand*>(brush_tool);
 
-	if( gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ) == self )
+	if( gToolMgr->getCurrentTool() == self )
 	{
 		self->brush();
 	}
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index 945a172b1ce0d6190fb1b84f99d4a2a83d34b519..3f111583b511f6dcb91a4d45ad8e0ccb88896eb7 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -148,7 +148,7 @@ void LLToolCompInspect::pickCallback(S32 x, S32 y, MASK mask)
 
 	if( hit_obj )
 	{
-		if (gSelectMgr->getObjectCount())
+		if (gSelectMgr->getSelection()->getObjectCount())
 		{
 			gEditMenuHandler = gSelectMgr;
 		}
@@ -222,7 +222,7 @@ void LLToolCompTranslate::pickCallback(S32 x, S32 y, MASK mask)
 
 	if( hit_obj || gToolTranslate->mManip->getHighlightedPart() != LLManip::LL_NO_PART )
 	{
-		if (gSelectMgr->getObjectCount())
+		if (gToolTranslate->mManip->getSelection()->getObjectCount())
 		{
 			gEditMenuHandler = gSelectMgr;
 		}
@@ -253,9 +253,22 @@ BOOL LLToolCompTranslate::handleMouseUp(S32 x, S32 y, MASK mask)
 	return LLToolComposite::handleMouseUp(x, y, mask);
 }
 
+LLTool* LLToolCompTranslate::getOverrideTool(MASK mask)
+{
+	if (mask == MASK_CONTROL)
+	{
+		return gToolRotate;
+	}
+	else if (mask == (MASK_CONTROL | MASK_SHIFT))
+	{
+		return gToolStretch;
+	}
+	return LLToolComposite::getOverrideTool(mask);
+}
+
 BOOL LLToolCompTranslate::handleDoubleClick(S32 x, S32 y, MASK mask)
 {
-	if (!gSelectMgr->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART)
+	if (mManip->getSelection()->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART)
 	{
 		// You should already have an object selected from the mousedown.
 		// If so, show its properties
@@ -331,7 +344,7 @@ void LLToolCompScale::pickCallback(S32 x, S32 y, MASK mask)
 
 	if( hit_obj || gToolStretch->mManip->getHighlightedPart() != LLManip::LL_NO_PART)
 	{
-		if (gSelectMgr->getObjectCount())
+		if (gToolStretch->mManip->getSelection()->getObjectCount())
 		{
 			gEditMenuHandler = gSelectMgr;
 		}
@@ -359,9 +372,20 @@ BOOL LLToolCompScale::handleMouseUp(S32 x, S32 y, MASK mask)
 	return LLToolComposite::handleMouseUp(x, y, mask);
 }
 
+LLTool* LLToolCompScale::getOverrideTool(MASK mask)
+{
+	if (mask == MASK_CONTROL)
+	{
+		return gToolRotate;
+	}
+
+	return LLToolComposite::getOverrideTool(mask);
+}
+
+
 BOOL LLToolCompScale::handleDoubleClick(S32 x, S32 y, MASK mask)
 {
-	if (!gSelectMgr->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART)
+	if (!mManip->getSelection()->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART)
 	{
 		// You should already have an object selected from the mousedown.
 		// If so, show its properties
@@ -515,7 +539,7 @@ void LLToolCompRotate::pickCallback(S32 x, S32 y, MASK mask)
 	
 	if( hit_obj || gToolRotate->mManip->getHighlightedPart() != LLManip::LL_NO_PART)
 	{
-		if (gSelectMgr->getObjectCount())
+		if (gToolRotate->mManip->getSelection()->getObjectCount())
 		{
 			gEditMenuHandler = gSelectMgr;
 		}
@@ -543,10 +567,18 @@ BOOL LLToolCompRotate::handleMouseUp(S32 x, S32 y, MASK mask)
 	return LLToolComposite::handleMouseUp(x, y, mask);
 }
 
+LLTool* LLToolCompRotate::getOverrideTool(MASK mask)
+{
+	if (mask == (MASK_CONTROL | MASK_SHIFT))
+	{
+		return gToolStretch;
+	}
+	return LLToolComposite::getOverrideTool(mask);
+}
 
 BOOL LLToolCompRotate::handleDoubleClick(S32 x, S32 y, MASK mask)
 {
-	if (!gSelectMgr->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART)
+	if (!mManip->getSelection()->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART)
 	{
 		// You should already have an object selected from the mousedown.
 		// If so, show its properties
@@ -649,7 +681,7 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
 
 	// On mousedown, start grabbing
 	gGrabTransientTool = this;
-	gCurrentToolset->selectTool( (LLTool*) mGrab );
+	gToolMgr->getCurrentToolset()->selectTool( (LLTool*) mGrab );
 
 	return gToolGrab->handleMouseDown(x, y, mask);
 }
@@ -666,7 +698,7 @@ BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask)
 
 	// On mousedown, start grabbing
 	gGrabTransientTool = this;
-	gCurrentToolset->selectTool( (LLTool*) mGrab );
+	gToolMgr->getCurrentToolset()->selectTool( (LLTool*) mGrab );
 
 	return gToolGrab->handleDoubleClick(x, y, mask);
 }
diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h
index c319904ee8801b9bef91e9d0ef0e216b2ee6a4b3..c348379a1692db78f1a7a79c7af85ebacbed3bd4 100644
--- a/indra/newview/lltoolcomp.h
+++ b/indra/newview/lltoolcomp.h
@@ -110,6 +110,8 @@ class LLToolCompTranslate : public LLToolComposite
 	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask);			// Returns to the default tool
 	virtual void		render();
 
+	virtual LLTool*		getOverrideTool(MASK mask);
+
 	static void pickCallback(S32 x, S32 y, MASK mask);
 };
 
@@ -129,8 +131,9 @@ class LLToolCompScale : public LLToolComposite
 	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask);			// Returns to the default tool
 	virtual void		render();
 
+	virtual LLTool*		getOverrideTool(MASK mask);
+	
 	static void pickCallback(S32 x, S32 y, MASK mask);
-
 };
 
 
@@ -150,6 +153,8 @@ class LLToolCompRotate : public LLToolComposite
 	virtual BOOL		handleMouseUp(S32 x, S32 y, MASK mask);
 	virtual void		render();
 
+	virtual LLTool*		getOverrideTool(MASK mask);
+
 	static void pickCallback(S32 x, S32 y, MASK mask);
 
 protected:
diff --git a/indra/newview/lltoolface.cpp b/indra/newview/lltoolface.cpp
index c35fcb434c00125aef0e0186e46a87058c4db687..e103af0bd340be80951ad444459e04c8fdb42421 100644
--- a/indra/newview/lltoolface.cpp
+++ b/indra/newview/lltoolface.cpp
@@ -42,7 +42,7 @@ LLToolFace::~LLToolFace()
 
 BOOL LLToolFace::handleDoubleClick(S32 x, S32 y, MASK mask)
 {
-	if (!gSelectMgr->isEmpty())
+	if (!gSelectMgr->getSelection()->isEmpty())
 	{
 		// You should already have an object selected from the mousedown.
 		// If so, show its properties
@@ -90,7 +90,7 @@ void LLToolFace::pickCallback(S32 x, S32 y, MASK mask)
 				// object wasn't selected so add the object and face
 				gSelectMgr->selectObjectOnly(hit_obj, hit_face);
 			}
-			else if (!gSelectMgr->contains(hit_obj, hit_face) )
+			else if (!gSelectMgr->getSelection()->contains(hit_obj, hit_face) )
 			{
 				// object is selected, but not this face, so add it.
 				gSelectMgr->addAsIndividual(hit_obj, hit_face);
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index 627a49a6cc883cc6791a8722de830bb759af52f1..2d1cb9c4930a90fc066871d9498ccda1e5eb1ae7 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -43,9 +43,6 @@ BOOL gCameraBtnPan = FALSE;
 const S32 SLOP_RANGE = 4;
 const F32 FOCUS_OFFSET_FACTOR = 1.f;
 
-extern void handle_first_tool(void*);
-
-
 //
 // Camera - shared functionality
 //
@@ -136,7 +133,8 @@ void LLToolCamera::pickCallback(S32 x, S32 y, MASK mask)
 	// check for hud attachments
 	if (hit_obj && hit_obj->isHUDAttachment())
 	{
-		if (!gSelectMgr->getObjectCount() || gSelectMgr->getSelectType() != SELECT_TYPE_HUD)
+		LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+		if (!selection->getObjectCount() || selection->getSelectType() != SELECT_TYPE_HUD)
 		{
 			gToolCamera->mValidClickPoint = FALSE;
 			return;
@@ -175,7 +173,7 @@ void LLToolCamera::pickCallback(S32 x, S32 y, MASK mask)
 	}
 	//RN: check to see if this is mouse-driving as opposed to ALT-zoom or Focus tool
 	else if (mask & MASK_ALT || 
-			(gToolMgr->getCurrentTool(mask)->getName() == "Camera")) 
+			(gToolMgr->getCurrentTool()->getName() == "Camera")) 
 	{
 		LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
 		if (hit_obj)
diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h
index 1d3d4a728bfdc479eda6cfaf79e5a626ef7bb4d5..e43da210360716834ed33dbff406f3bcc64d681c 100644
--- a/indra/newview/lltoolfocus.h
+++ b/indra/newview/lltoolfocus.h
@@ -27,6 +27,8 @@ class LLToolCamera
 	virtual void	handleSelect();
 	virtual void	handleDeselect();
 
+	virtual LLTool*	getOverrideTool(MASK mask) { return NULL; }
+
 	static void pickCallback(S32 x, S32 y, MASK mask);
 	BOOL mouseSteerMode() { return mMouseSteering; }
 
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index 898322d5ca226232a96190a7a3dac3c5c3d9ba73..549719250cf2be3d30b062291394e1023203f02e 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -126,7 +126,7 @@ void LLToolGrab::pickCallback(S32 x, S32 y, MASK mask)
 
 	BOOL extend_select = (mask & MASK_SHIFT);
 
-	if (!extend_select && !gSelectMgr->isEmpty())
+	if (!extend_select && !gSelectMgr->getSelection()->isEmpty())
 	{
 		gSelectMgr->deselectAll();
 		gToolGrab->mDeselectedThisClick = TRUE;
diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h
index 5073d0e2116b822bafa0432838f40ec73730effd..ebe74cb5b1cc9739bb780c91de6558afa699e755 100644
--- a/indra/newview/lltoolgrab.h
+++ b/indra/newview/lltoolgrab.h
@@ -34,7 +34,7 @@ class LLToolGrab : public LLTool
 
 	virtual void		handleSelect();
 	virtual void		handleDeselect();
-
+	
 	virtual LLViewerObject*	getEditingObject();
 	virtual LLVector3d		getEditingPointGlobal();
 	virtual BOOL			isEditing();
diff --git a/indra/newview/lltoolgun.cpp b/indra/newview/lltoolgun.cpp
index 4c01b861531905599921671c0757c76fae8700f5..c4bc524796f28e69d0821279126cecc26519281f 100644
--- a/indra/newview/lltoolgun.cpp
+++ b/indra/newview/lltoolgun.cpp
@@ -48,7 +48,7 @@ void LLToolGun::handleDeselect()
 BOOL LLToolGun::handleMouseDown(S32 x, S32 y, MASK mask)
 {
 	gGrabTransientTool = this;
-	gCurrentToolset->selectTool( gToolGrab );
+	gToolMgr->getCurrentToolset()->selectTool( gToolGrab );
 
 	return gToolGrab->handleMouseDown(x, y, mask);
 }
diff --git a/indra/newview/lltoolgun.h b/indra/newview/lltoolgun.h
index d567db30cad22a2f7eefe0c60381ea1aad9ad514..4232a401fd43438bb89bbadbfb69df17321c7212 100644
--- a/indra/newview/lltoolgun.h
+++ b/indra/newview/lltoolgun.h
@@ -26,6 +26,7 @@ class LLToolGun : public LLTool
 	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
 	virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
 
+	virtual LLTool*	getOverrideTool(MASK mask) { return NULL; }
 	virtual BOOL	clipMouseWhenDown()		{ return FALSE; }
 
 private:
diff --git a/indra/newview/lltoolindividual.cpp b/indra/newview/lltoolindividual.cpp
index a5afd379edeceeff927f7e10a293dc6bd5ea6d36..a6c74be00e8edcab820e1b43303bd83c092740f5 100644
--- a/indra/newview/lltoolindividual.cpp
+++ b/indra/newview/lltoolindividual.cpp
@@ -66,7 +66,7 @@ void LLToolIndividual::pickCallback(S32 x, S32 y, MASK mask)
 
 BOOL LLToolIndividual::handleDoubleClick(S32 x, S32 y, MASK mask)
 {
-	if(!gSelectMgr->isEmpty())
+	if(!gSelectMgr->getSelection()->isEmpty())
 	{
 		// You should already have an object selected from the mousedown.
 		// If so, show its inventory. 
@@ -85,10 +85,10 @@ BOOL LLToolIndividual::handleDoubleClick(S32 x, S32 y, MASK mask)
 
 void LLToolIndividual::handleSelect()
 {
-	LLViewerObject* obj = gSelectMgr->getFirstRootObject();
+	LLViewerObject* obj = gSelectMgr->getSelection()->getFirstRootObject();
 	if(!obj)
 	{
-		obj = gSelectMgr->getFirstObject();
+		obj = gSelectMgr->getSelection()->getFirstObject();
 	}
 	gSelectMgr->deselectAll();
 	if(obj)
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index 2c69db10c54481e728f5282aa806064ffa779083..7c9cd1b199fb153efbd3eb20ea79132bc5fc6b8e 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -34,7 +34,6 @@ LLToolMgr*		gToolMgr	= NULL;
 // Used when app not active to avoid processing hover.
 LLTool*			gToolNull	= NULL;
 
-LLToolset*		gCurrentToolset		= NULL;
 LLToolset*		gBasicToolset		= NULL;
 LLToolset*		gCameraToolset		= NULL;
 //LLToolset*		gLandToolset		= NULL;
@@ -46,10 +45,12 @@ LLToolset*		gFaceEditToolset	= NULL;
 
 LLToolMgr::LLToolMgr()
 	:
-	mCurrentTool(NULL), 
+	mBaseTool(NULL), 
 	mSavedTool(NULL),
 	mTransientTool( NULL ),
-	mOverrideTool( NULL )
+	mOverrideTool( NULL ),
+	mSelectedTool( NULL ),
+	mCurrentToolset( NULL )
 {
 	gToolNull = new LLTool(NULL);  // Does nothing
 	setCurrentTool(gToolNull);
@@ -59,8 +60,6 @@ LLToolMgr::LLToolMgr()
 //	gLandToolset		= new LLToolset();
 	gMouselookToolset	= new LLToolset();
 	gFaceEditToolset	= new LLToolset();
-
-	gCurrentToolset = gBasicToolset;
 }
 
 void LLToolMgr::initTools()
@@ -178,8 +177,8 @@ void LLToolMgr::initTools()
 	gToolObjPicker = new LLToolObjPicker();
 
 	// On startup, use "select" tool
+	setCurrentToolset(gBasicToolset);
 	gBasicToolset->selectTool( gToolPie );
-	useSelectedTool( gBasicToolset );
 }
 
 LLToolMgr::~LLToolMgr()
@@ -248,138 +247,103 @@ LLToolMgr::~LLToolMgr()
 	gToolNull = NULL;
 }
 
-
-void LLToolMgr::useSelectedTool( LLToolset* vp )
-{
-	setCurrentTool( vp->getSelectedTool() ); 
-}
-
 BOOL LLToolMgr::usingTransientTool()
 {
 	return mTransientTool ? TRUE : FALSE;
 }
 
-void LLToolMgr::setCurrentTool( LLTool* tool )
+void LLToolMgr::setCurrentToolset(LLToolset* current)
 {
-	if (tool == mCurrentTool)
+	if (!current) return;
+
+	// switching toolsets?
+	if (current != mCurrentToolset)
 	{
-		// didn't change tool, so don't mess with
-		// handleSelect or handleDeselect
-		return;
+		// deselect current tool
+		if (mSelectedTool)
+		{
+			mSelectedTool->handleDeselect();
+		}
+		mCurrentToolset = current;
+		// select first tool of new toolset only if toolset changed
+		mCurrentToolset->selectFirstTool();
 	}
+	// update current tool based on new toolset
+	setCurrentTool( mCurrentToolset->getSelectedTool() );
+}
+
+LLToolset* LLToolMgr::getCurrentToolset()
+{
+	return mCurrentToolset;
+}
 
+void LLToolMgr::setCurrentTool( LLTool* tool )
+{
 	if (mTransientTool)
 	{
-		mTransientTool->handleDeselect();
 		mTransientTool = NULL;
 	}
-	else if( mCurrentTool )
-	{
-		mCurrentTool->handleDeselect();
-	}
 
-	mCurrentTool = tool;
-	if (mCurrentTool)
-	{
-		mCurrentTool->handleSelect();
-	}
+	mBaseTool = tool;
+	updateToolStatus();
 }
 
-LLTool* LLToolMgr::getCurrentTool(MASK override_mask)
+LLTool* LLToolMgr::getCurrentTool()
 {
-	// In mid-drag, always keep the current tool
-	if (gToolTranslate->hasMouseCapture()
-		|| gToolRotate->hasMouseCapture()
-		|| gToolStretch->hasMouseCapture())
-	{
-		// might have gotten here by overriding another tool
-		if (mOverrideTool)
-		{
-			return mOverrideTool;
-		}
-		else
-		{
-			return mCurrentTool;
-		}
-	}
+	MASK override_mask = gKeyboard->currentMask(TRUE);
 
+	LLTool* cur_tool = NULL;
+	// always use transient tools if available
 	if (mTransientTool)
 	{
 		mOverrideTool = NULL;
-		return mTransientTool;
+		cur_tool = mTransientTool;
 	}
-
-	if (mCurrentTool == gToolGun)
+	// tools currently grabbing mouse input will stay active
+	else if (mSelectedTool && mSelectedTool->hasMouseCapture())
 	{
-		mOverrideTool = NULL;
-		return mCurrentTool;
+		cur_tool = mSelectedTool;
 	}
-
-	// ALT always gets you the camera tool
-	if (override_mask & MASK_ALT)
+	else
 	{
-		mOverrideTool = gToolCamera;
-		return mOverrideTool;
-	}
+		mOverrideTool = mBaseTool ? mBaseTool->getOverrideTool(override_mask) : NULL;
 
-	if (mCurrentTool == gToolCamera)
-	{
-		// ...can't switch out of camera
-		mOverrideTool = NULL;
-		return mCurrentTool;
-	}
-	else if (mCurrentTool == gToolGrab)
-	{
-		// ...can't switch out of grab
-		mOverrideTool = NULL;
-		return mCurrentTool;
+		// use override tool if available otherwise drop back to base tool
+		cur_tool = mOverrideTool ? mOverrideTool : mBaseTool;
 	}
-	else if (mCurrentTool == gToolInspect)
-	{
-		// ...can't switch out of grab
-		mOverrideTool = NULL;
-		return mCurrentTool;
-	}
-	else
+
+	//update tool selection status
+	if (mSelectedTool != cur_tool)
 	{
-		// ...can switch between editing tools
-		if (override_mask == MASK_CONTROL)
-		{
-			// Control lifts when in the pie tool, otherwise switches to rotate
-			if (mCurrentTool == gToolPie)
-			{
-				mOverrideTool = gToolGrab;
-			}
-			else
-			{
-				mOverrideTool = gToolRotate;
-			}
-			return mOverrideTool;
-		}
-		else if (override_mask == (MASK_CONTROL | MASK_SHIFT))
+		if (mSelectedTool)
 		{
-			// Shift-Control spins when in the pie tool, otherwise switches to scale
-			if (mCurrentTool == gToolPie)
-			{
-				mOverrideTool = gToolGrab;
-			}
-			else
-			{
-				mOverrideTool = gToolStretch;
-			}
-			return mOverrideTool;
+			mSelectedTool->handleDeselect();
 		}
-		else
+		if (cur_tool)
 		{
-			mOverrideTool = NULL;
-			return mCurrentTool;
+			cur_tool->handleSelect();
 		}
+		mSelectedTool = cur_tool;
 	}
+
+	return mSelectedTool;
+}
+
+LLTool* LLToolMgr::getBaseTool()
+{
+	return mBaseTool;
+}
+
+void LLToolMgr::updateToolStatus()
+{
+	// call getcurrenttool() to calculate active tool and call handleSelect() and handleDeselect() immediately
+	// when active tool changes
+	getCurrentTool();
 }
 
 BOOL LLToolMgr::inEdit()
 {
-	return mCurrentTool != gToolPie && mCurrentTool != gToolNull;
+	return mBaseTool != gToolPie && mBaseTool != gToolNull;
 }
 
 void LLToolMgr::setTransientTool(LLTool* tool)
@@ -392,34 +356,26 @@ void LLToolMgr::setTransientTool(LLTool* tool)
 	{
 		if (mTransientTool)
 		{
-			mTransientTool->handleDeselect();
 			mTransientTool = NULL;
 		}
-		else if (mCurrentTool)
-		{
-			mCurrentTool->handleDeselect();
-		}
 
 		mTransientTool = tool;
-		mTransientTool->handleSelect();
 	}
+
+	updateToolStatus();
 }
 
 void LLToolMgr::clearTransientTool()
 {
 	if (mTransientTool)
 	{
-		mTransientTool->handleDeselect();
 		mTransientTool = NULL;
-		if (mCurrentTool)
-		{
-			mCurrentTool->handleSelect();
-		}
-		else
+		if (!mBaseTool)
 		{
-			llwarns << "mCurrentTool is NULL" << llendl;
+			llwarns << "mBaseTool is NULL" << llendl;
 		}
 	}
+	updateToolStatus();
 }
 
 
@@ -428,26 +384,19 @@ void LLToolMgr::clearTransientTool()
 // release this locking.
 void LLToolMgr::onAppFocusLost()
 {
-	if (mCurrentTool 
-		&& mCurrentTool == gToolGun)
-	{
-		mCurrentTool->handleDeselect();
-	}
-	mSavedTool = mCurrentTool;
-	mCurrentTool = gToolNull;
+	mSavedTool = mBaseTool;
+	mBaseTool = gToolNull;
+	updateToolStatus();
 }
 
 void LLToolMgr::onAppFocusGained()
 {
 	if (mSavedTool)
 	{
-		if (mSavedTool == gToolGun)
-		{
-			mCurrentTool->handleSelect();
-		}
-		mCurrentTool = mSavedTool;
+		mBaseTool = mSavedTool;
 		mSavedTool = NULL;
 	}
+	updateToolStatus();
 }
 
 /////////////////////////////////////////////////////
@@ -491,7 +440,10 @@ BOOL LLToolset::isToolSelected( S32 index )
 void LLToolset::selectFirstTool()
 {
 	mSelectedTool = mToolList.getFirstData();
-	gToolMgr->setCurrentTool( mSelectedTool );
+	if (gToolMgr) 
+	{
+		gToolMgr->setCurrentTool( mSelectedTool );
+	}
 }
 
 
@@ -540,5 +492,5 @@ void LLToolset::selectPrevTool()
 void select_tool( void *tool_pointer )
 {
 	LLTool *tool = (LLTool *)tool_pointer;
-	gCurrentToolset->selectTool( tool );
+	gToolMgr->getCurrentToolset()->selectTool( tool );
 }
diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h
index b54a893b0eebfd154aa20bb14373da10db6fe90b..a57ebc32a665925c9d40da03eb1a71127502ab38 100644
--- a/indra/newview/lltoolmgr.h
+++ b/indra/newview/lltoolmgr.h
@@ -32,27 +32,33 @@ class LLToolMgr
 	// Must be called after gSavedSettings set up.
 	void			initTools();
 
-	LLTool*			getCurrentTool(MASK override_mask);
+	LLTool*			getCurrentTool(); // returns active tool, taking into account keyboard state
+	LLTool*			getBaseTool(); // returns active tool when overrides are deactivated
 
 	BOOL			inEdit();
-	void			useSelectedTool( LLToolset* vp );
 
 	void			setTransientTool(LLTool* tool);
 	void			clearTransientTool();
 	BOOL			usingTransientTool();
 
+	void			setCurrentToolset(LLToolset* current);
+	LLToolset*		getCurrentToolset();
+
 	void			onAppFocusGained();
 	void			onAppFocusLost();
 
 protected:
 	friend class LLToolset;  // to allow access to setCurrentTool();
 	void			setCurrentTool(LLTool* tool);
+	void			updateToolStatus();
 
 protected:
-	LLTool*			mCurrentTool;
+	LLTool*			mBaseTool;
 	LLTool*			mSavedTool;		// The current tool at the time application focus was lost.
 	LLTool*			mTransientTool;
 	LLTool*			mOverrideTool; // Tool triggered by keyboard override
+	LLTool*			mSelectedTool; // last known active tool
+	LLToolset*		mCurrentToolset;
 };
 
 // Sets of tools for various modes
@@ -87,7 +93,6 @@ void select_tool(void *tool);
 // Globals (created and destroyed by LLViewerWindow)
 extern LLToolMgr*   gToolMgr;
 
-extern LLToolset* gCurrentToolset;
 extern LLToolset* gBasicToolset;
 extern LLToolset *gCameraToolset;
 //extern LLToolset *gLandToolset;
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 89df9c52494e914521ac326261d049006f8c30be..68834fe5647ba6ebea19abeee09ba014ab5eccf0 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -63,7 +63,7 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
 	// if buttons swapped, don't pick transparent so users can't "pay" 
 	// transparent objects
 	gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, leftMouseCallback, 
-											  TRUE, TRUE);
+											  FALSE, TRUE);
 	mGrabMouseButtonDown = TRUE;
 	return TRUE;
 }
@@ -194,7 +194,7 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show)
 		!always_show)
 	{
 		gGrabTransientTool = this;
-		gCurrentToolset->selectTool( gToolGrab );
+		gToolMgr->getCurrentToolset()->selectTool( gToolGrab );
 		return gToolGrab->handleObjectHit( object, x, y, mask);
 	}
 	
@@ -253,8 +253,8 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show)
 	// Spawn pie menu
 	if (mHitLand)
 	{
-		gParcelMgr->selectParcelAt( gLastHitPosGlobal );
-
+		LLParcelSelectionHandle selection = gParcelMgr->selectParcelAt( gLastHitPosGlobal );
+		gMenuHolder->setParcelSelection(selection);
 		gPieLand->show(x, y, mPieMouseButtonDown);
 
 		// VEFFECT: ShowPie
@@ -269,6 +269,8 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show)
 	}
 	else if (object)
 	{
+		gMenuHolder->setObjectSelection(gSelectMgr->getSelection());
+
 		if (object->isAvatar() 
 			|| (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner()))
 		{
@@ -302,7 +304,7 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show)
 		{
 			// BUG: What about chatting child objects?
 			LLString name;
-			LLSelectNode* node = gSelectMgr->getFirstRootNode();
+			LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 			if (node)
 			{
 				name = node->mName;
@@ -397,7 +399,7 @@ void LLToolPie::selectionPropertiesReceived()
 	if (sClickActionObject
 		&& !sClickActionObject->isDead())
 	{
-		LLViewerObject* root = gSelectMgr->getFirstRootObject();
+		LLViewerObject* root = gSelectMgr->getSelection()->getFirstRootObject();
 		if (root == sClickActionObject)
 		{
 			U8 action = root->getClickAction();
@@ -603,6 +605,19 @@ void LLToolPie::handleDeselect()
 	gSelectMgr->validateSelection();
 }
 
+LLTool* LLToolPie::getOverrideTool(MASK mask)
+{
+	if (mask == MASK_CONTROL)
+	{
+		return gToolGrab;
+	}
+	else if (mask == (MASK_CONTROL | MASK_SHIFT))
+	{
+		return gToolGrab;
+	}
+
+	return LLTool::getOverrideTool(mask);
+}
 
 void LLToolPie::stopEditing()
 {
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index d440a443e25d5ca1e73240b28b7e7ee1a32afb14..6826b66ea74e671b1de8a5e8fd3f908933fe929a 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -33,6 +33,7 @@ class LLToolPie
 
 	virtual void		onMouseCaptureLost();
 	virtual void		handleDeselect();
+	virtual LLTool*		getOverrideTool(MASK mask);
 
 	static void			leftMouseCallback(S32 x, S32 y, MASK mask);
 	static void			rightMouseCallback(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp
index facfda2c8557bac017870c7aae8b651dd23e9760..20677fea983b39810389a3b53368822555cbf26d 100644
--- a/indra/newview/lltoolplacer.cpp
+++ b/indra/newview/lltoolplacer.cpp
@@ -110,7 +110,7 @@ BOOL LLToolPlacer::placeObject(S32 x, S32 y, MASK mask)
 	// ...and go back to the default tool
 	if (added && !gSavedSettings.getBOOL("CreateToolKeepSelected"))
 	{
-		gCurrentToolset->selectTool( gToolTranslate );
+		gToolMgr->getCurrentToolset()->selectTool( gToolTranslate );
 	}
 
 	return added;
diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp
index a303776ade67de3f37cfef5890313c6e3906f0c1..14ffb0015866b1997191eb218be56974950599c2 100644
--- a/indra/newview/lltoolselect.cpp
+++ b/indra/newview/lltoolselect.cpp
@@ -174,9 +174,10 @@ void LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL
 			if (!already_selected)
 			{
 				LLViewerObject* root_object = (LLViewerObject*)object->getRootEdit();
+				LLObjectSelectionHandle selection = gSelectMgr->getSelection();
 
 				// this is just a temporary selection
-				LLSelectNode* select_node = gSelectMgr->findSelectNode(root_object);
+				LLSelectNode* select_node = selection->findNode(root_object);
 				if (select_node)
 				{
 					select_node->setTransient(TRUE);
@@ -184,7 +185,7 @@ void LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL
 
 				for (S32 i = 0; i < (S32)root_object->mChildList.size(); i++)
 				{
-					select_node = gSelectMgr->findSelectNode(root_object->mChildList[i]);
+					select_node = selection->findNode(root_object->mChildList[i]);
 					if (select_node)
 					{
 						select_node->setTransient(TRUE);
diff --git a/indra/newview/lltoolselectland.cpp b/indra/newview/lltoolselectland.cpp
index 7d51d4a81c83a42a07ec99253ba6978119aabf0d..f64bf6bf2d50c59be038655587d4cf4937323a23 100644
--- a/indra/newview/lltoolselectland.cpp
+++ b/indra/newview/lltoolselectland.cpp
@@ -46,6 +46,10 @@ LLToolSelectLand::LLToolSelectLand( )
 	mLastShowParcelOwners(FALSE)
 { }
 
+LLToolSelectLand::~LLToolSelectLand()
+{
+}
+
 
 BOOL LLToolSelectLand::handleMouseDown(S32 x, S32 y, MASK mask)
 {
@@ -114,7 +118,7 @@ BOOL LLToolSelectLand::handleMouseUp(S32 x, S32 y, MASK mask)
 			roundXY(mEastNorthTop);
 
 			// Don't auto-select entire parcel.
-			gParcelMgr->selectLand( mWestSouthBottom, mEastNorthTop, FALSE );
+			mSelection = gParcelMgr->selectLand( mWestSouthBottom, mEastNorthTop, FALSE );
 		}
 
 		mMouseOutsideSlop = FALSE;
@@ -201,6 +205,7 @@ void LLToolSelectLand::handleSelect()
 void LLToolSelectLand::handleDeselect()
 {
 	gFloaterTools->setStatusText("");
+	mSelection = NULL;
 	//gParcelMgr->deselectLand();
 	gSavedSettings.setBOOL("ShowParcelOwners", mLastShowParcelOwners);
 }
diff --git a/indra/newview/lltoolselectland.h b/indra/newview/lltoolselectland.h
index 9ae2b071b5a7b544076b705c0403de12952f415d..02158b149541522a0355732d3900abe09211a794 100644
--- a/indra/newview/lltoolselectland.h
+++ b/indra/newview/lltoolselectland.h
@@ -12,11 +12,14 @@
 #include "lltool.h"
 #include "v3dmath.h"
 
+class LLParcelSelection;
+
 class LLToolSelectLand
 :	public LLTool
 {
 public:
 	LLToolSelectLand( );
+	virtual ~LLToolSelectLand();
 
 	/*virtual*/ BOOL		handleMouseDown(S32 x, S32 y, MASK mask);
 	/*virtual*/ BOOL		handleDoubleClick(S32 x, S32 y, MASK mask);
@@ -49,6 +52,7 @@ class LLToolSelectLand
 	LLVector3d		mEastNorthTop;			// global coords, from drag
 
 	BOOL			mLastShowParcelOwners;	// store last Show Parcel Owners setting
+	LLHandle<LLParcelSelection> mSelection;		// hold on to a parcel selection
 };
 
 extern LLToolSelectLand *gToolParcel;
diff --git a/indra/newview/lltoolview.cpp b/indra/newview/lltoolview.cpp
index 49e5896ab7a0510820067b88146bd2c561abfaac..f5c1e0b90b0b31db4afae73f9fb7790843001ef8 100644
--- a/indra/newview/lltoolview.cpp
+++ b/indra/newview/lltoolview.cpp
@@ -129,7 +129,7 @@ void LLToolView::draw()
 {
 	// turn off highlighting for all containers 
 	// and hide all option panels except for the selected one.
-	LLTool* selected = gCurrentToolset->getSelectedTool();
+	LLTool* selected = gToolMgr->getCurrentToolset()->getSelectedTool();
 	for( LLToolContainer* contain = mContainList.getFirstData();
 		 contain != NULL;
 		 contain = mContainList.getNextData()
@@ -169,7 +169,6 @@ void LLToolView::onClickToolButton(void* userdata)
 	LLToolContainer* clicked = (LLToolContainer*) userdata;
 
 	// Switch to this one
-	gCurrentToolset->selectTool( clicked->mTool );
-	gToolMgr->useSelectedTool( gCurrentToolset );
+	gToolMgr->getCurrentToolset()->selectTool( clicked->mTool );
 }
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 838bf68f3d061551e77ec9ad67b01a90af7e90a8..9b6fc425fa84c155e2b94a6fdce7b7b1e9d9136d 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -420,9 +420,6 @@ BOOL get_visibility(void*);
 void request_friendship(const LLUUID& agent_id);
 
 // Tools menu
-void handle_first_tool(void*);
-void handle_next_tool(void*);
-void handle_previous_tool(void*);
 void handle_force_unlock(void*);
 void handle_selected_texture_info(void*);
 void handle_dump_image_list(void*);
@@ -980,6 +977,7 @@ void init_debug_ui_menu(LLMenuGL* menu)
 	menu->append(new LLMenuItemToggleGL("Debug SelectMgr", &gDebugSelectMgr));
 	menu->append(new LLMenuItemToggleGL("Debug Clicks", &gDebugClicks));
 	menu->append(new LLMenuItemToggleGL("Debug Views", &LLView::sDebugRects));
+	menu->append(new LLMenuItemCheckGL("Show Name Tooltips", toggle_show_xui_names, NULL, check_show_xui_names, NULL));
 	menu->append(new LLMenuItemToggleGL("Debug Mouse Events", &LLView::sDebugMouseHandling));
 	menu->append(new LLMenuItemToggleGL("Debug Keys", &LLView::sDebugKeys));
 	menu->append(new LLMenuItemToggleGL("Debug WindowProc", &gDebugWindowProc));
@@ -1427,7 +1425,7 @@ class LLObjectRateOwner : public view_listener_t
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
 		// Don't allow rating of group owned objects.
-		LLSelectNode* node = gSelectMgr->getFirstRootNode();
+		LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 		if (!node) return true;
 		if (node->mPermissions->isGroupOwned())
 		{
@@ -1517,12 +1515,13 @@ class LLObjectEnableReportAbuse : public view_listener_t
 BOOL enable_attach(void*)
 {
 	// All root objects must be owned by agent.
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
 	BOOL rv = FALSE;
-	LLViewerObject* obj = gSelectMgr->getFirstRootObject();
+	LLViewerObject* obj = selection->getFirstRootObject();
 	if(obj)
 	{
 		rv = TRUE;
-		for(obj = gSelectMgr->getFirstRootObject() ; obj != NULL; obj = gSelectMgr->getNextRootObject())
+		for(obj = selection->getFirstRootObject() ; obj != NULL; obj = selection->getNextRootObject())
 		{
 			for (U32 child_num = 0; child_num < obj->mChildList.size(); child_num++ )
 			{
@@ -1572,7 +1571,6 @@ class LLObjectTouch : public view_listener_t
 		msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
 		msg->sendMessage(object->getRegion()->getHost());
 
-		gSelectMgr->deselectTransient();
 		return true;
 	}
 };
@@ -1588,7 +1586,7 @@ class LLObjectEnableTouch : public view_listener_t
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 
 		// Update label based on the node touch name if available.
-		LLSelectNode* node = gSelectMgr->getFirstRootNode();
+		LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 		if (node && node->mValid && !node->mTouchName.empty())
 		{
 			gMenuHolder->childSetText("Object Touch", node->mTouchName);
@@ -1604,7 +1602,7 @@ class LLObjectEnableTouch : public view_listener_t
 
 void label_touch(LLString& label, void*)
 {
-	LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 	if (node && node->mValid && !node->mTouchName.empty())
 	{
 		label.assign(node->mTouchName);
@@ -1620,8 +1618,6 @@ bool handle_object_open()
 	LLViewerObject* obj = gObjectList.findObject(gLastHitObjectID);
 	if(!obj) return true;
 
-	// transient selection must be made permanent
-	gSelectMgr->convertTransient();
 	LLFloaterOpenObject::show();
 	return true;
 }
@@ -1682,8 +1678,8 @@ bool toggle_build_mode()
 			gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD );
 		}
 
-		gCurrentToolset = gBasicToolset;
-		gCurrentToolset->selectTool( gToolCreate );
+		gToolMgr->setCurrentToolset(gBasicToolset);
+		gToolMgr->getCurrentToolset()->selectTool( gToolCreate );
 
 		// Could be first use
 		LLFirstUse::useBuild();
@@ -1719,8 +1715,8 @@ class LLObjectBuild : public view_listener_t
 			gViewerWindow->moveCursorToCenter();
 		}
 
-		gCurrentToolset = gBasicToolset;
-		gCurrentToolset->selectTool( gToolCreate );
+		gToolMgr->setCurrentToolset(gBasicToolset);
+		gToolMgr->getCurrentToolset()->selectTool( gToolCreate );
 
 		// Could be first use
 		LLFirstUse::useBuild();
@@ -1733,12 +1729,12 @@ class LLObjectEdit : public view_listener_t
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
 		gParcelMgr->deselectLand();
-		// convert transient selections to permanent
-		gSelectMgr->convertTransient();
 
 		if (gAgent.getFocusOnAvatar() && !gToolMgr->inEdit())
 		{
-			if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
+			LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+
+			if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement"))
 			{
 				// always freeze camera in space, even if camera doesn't move
 				// so, for example, follow cam scripts can't affect you when in build mode
@@ -1758,7 +1754,7 @@ class LLObjectEdit : public view_listener_t
 
 		gFloaterTools->open();		/* Flawfinder: ignore */
 	
-		gCurrentToolset = gBasicToolset;
+		gToolMgr->setCurrentToolset(gBasicToolset);
 		gFloaterTools->setEditTool( gToolTranslate );
 
 		// Could be first use
@@ -1771,7 +1767,6 @@ class LLObjectInspect : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		gSelectMgr->convertTransient();
 		LLFloaterInspect::show();
 		return true;
 	}
@@ -1804,8 +1799,8 @@ class LLLandBuild : public view_listener_t
 		}
 
 
-		gCurrentToolset = gBasicToolset;
-		gCurrentToolset->selectTool( gToolCreate );
+		gToolMgr->setCurrentToolset(gBasicToolset);
+		gToolMgr->getCurrentToolset()->selectTool( gToolCreate );
 
 		// Could be first use
 		LLFirstUse::useBuild();
@@ -1974,7 +1969,7 @@ class LLObjectMute : public view_listener_t
 			// it's an object
 			id = object->getID();
 
-			LLSelectNode* node = gSelectMgr->getFirstRootNode();
+			LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 			if (node)
 			{
 				name = node->mName;
@@ -1994,7 +1989,6 @@ class LLObjectMute : public view_listener_t
 			gFloaterMute->show();
 		}
 		
-		gSelectMgr->deselectAll();
 		return true;
 	}
 };
@@ -2012,9 +2006,6 @@ bool handle_go_to()
 	strings.push_back(val);
 	send_generic_message("autopilot", strings);
 
-	// Don't select anything
-	gSelectMgr->deselectTransient();
-
 	gParcelMgr->deselectLand();
 
 	if (gAgent.getAvatarObject() && !gSavedSettings.getBOOL("AutoPilotLocksCamera"))
@@ -2359,9 +2350,9 @@ BOOL enable_buy(void*)
 {
     // In order to buy, there must only be 1 purchaseable object in
     // the selection manger.
-	if(gSelectMgr->getRootObjectCount() != 1) return FALSE;
+	if(gSelectMgr->getSelection()->getRootObjectCount() != 1) return FALSE;
     LLViewerObject* obj = NULL;
-    LLSelectNode* node = gSelectMgr->getFirstRootNode();
+    LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 	if(node)
     {
         obj = node->getObject();
@@ -2422,14 +2413,12 @@ void handle_buy_object(LLSaleInfo sale_info)
 		return;
 	}
 
-	gSelectMgr->convertTransient();
 	LLFloaterBuy::show(sale_info);
 }
 
 
 void handle_buy_contents(LLSaleInfo sale_info)
 {
-	gSelectMgr->convertTransient();
 	LLFloaterBuyContents::show(sale_info);
 }
 
@@ -2772,7 +2761,6 @@ bool handle_sit_or_stand()
 	if (sitting_on_selection())
 	{
 		gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
-		gSelectMgr->deselectTransient();
 		return true;
 	}
 
@@ -2793,8 +2781,6 @@ bool handle_sit_or_stand()
 		gMessageSystem->addVector3Fast(_PREHASH_Offset, offset_single);
 
 		object->getRegion()->sendReliableMessage();
-
-		gSelectMgr->deselectTransient();
 	}
 	return true;
 }
@@ -2809,11 +2795,14 @@ class LLObjectSitOrStand : public view_listener_t
 
 void near_sit_down_point(BOOL success, void *)
 {
-	gAgent.setFlying(FALSE);
-	gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
+	if (success)
+	{
+		gAgent.setFlying(FALSE);
+		gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
 
-	// Might be first sit
-	LLFirstUse::useSit();
+		// Might be first sit
+		LLFirstUse::useSit();
+	}
 }
 
 class LLLandSit : public view_listener_t
@@ -3153,13 +3142,12 @@ void reset_view_final( BOOL proceed, void* )
 	gAgent.changeCameraToDefault();
 	
 	gAgent.resetView(!gFloaterTools->getVisible());
+	gFloaterTools->close();
 	
 	gViewerWindow->showCursor();
 
 	// Switch back to basic toolset
-	gCurrentToolset = gBasicToolset;
-	gBasicToolset->selectFirstTool();
-	gToolMgr->useSelectedTool( gBasicToolset );
+	gToolMgr->setCurrentToolset(gBasicToolset);
 }
 
 class LLViewLookAtLastChatter : public view_listener_t
@@ -3232,7 +3220,7 @@ class LLEditEnableDuplicate : public view_listener_t
 
 void disabled_duplicate(void*)
 {
-	if (gSelectMgr->getFirstObject())
+	if (gSelectMgr->getSelection()->getFirstObject())
 	{
 		LLNotifyBox::showXml("CopyFailed");
 	}
@@ -3262,7 +3250,7 @@ void handle_deed_object_to_group(void*)
 
 BOOL enable_deed_object_to_group(void*)
 {
-	if(gSelectMgr->isEmpty()) return FALSE;
+	if(gSelectMgr->getSelection()->isEmpty()) return FALSE;
 	LLPermissions perm;
 	LLUUID group_id;
 
@@ -3321,8 +3309,8 @@ void handle_object_owner_permissive(void*)
 	if(gAgent.isGodlike())
 	{
 		// do the objects.
-		gSelectMgr->setObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE);
-		gSelectMgr->setObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE);
+		gSelectMgr->selectionSetObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE);
+		gSelectMgr->selectionSetObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE);
 	}
 }
 
@@ -3338,7 +3326,7 @@ void handle_object_owner_self(void*)
 // Shortcut to set owner permissions to not editable.
 void handle_object_lock(void*)
 {
-	gSelectMgr->setObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY);
+	gSelectMgr->selectionSetObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY);
 }
 
 void handle_object_asset_ids(void*)
@@ -3490,8 +3478,9 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
 	}
 	//gInventoryView->setPanelOpen(TRUE);
 
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
 	LLViewerObject* object = NULL;
-	LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	LLSelectNode* node = selection->getFirstRootNode();
 	if(!node) return;
 	object = node->getObject();
 	if(!object) return;
@@ -3502,7 +3491,7 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
 	// everything that we'll actually be derezzing.
 	LLDynamicArray<LLViewerObject*> derez_objects;
 	BOOL can_derez_current;
-	for( ; node != NULL; node = gSelectMgr->getNextRootNode())
+	for( ; node != NULL; node = selection->getNextRootNode())
 	{
 		object = node->getObject();
 		if(!object || !node->mValid) continue;
@@ -3636,42 +3625,47 @@ class LLToolsTakeCopy : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		if (gSelectMgr->isEmpty()) return true;
+		if (gSelectMgr->getSelection()->isEmpty()) return true;
 
 		const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
 		derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
 
-		// Only deselect if we're not building
-		if (!gToolMgr->inEdit())
-		{
-			gSelectMgr->deselectTransient();
-		}
 		return true;
 	}
 };
 
 
-void callback_return_to_owner(S32 option, void* data)
-{
-	if (0 == option)
-	{
-		// Ignore category ID for this derez destination.
-		derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null);
-	}
-}
-
 // You can return an object to its owner if it is on your land.
 class LLObjectReturn : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		if (gSelectMgr->isEmpty()) return true;
+		if (gSelectMgr->getSelection()->isEmpty()) return true;
+		
+		mObjectSelection = gSelectMgr->getEditSelection();
 
 		gViewerWindow->alertXml("ReturnToOwner",
-			callback_return_to_owner,
-			NULL);
+			onReturnToOwner,
+			(void*)this);
 		return true;
 	}
+
+	static void onReturnToOwner(S32 option, void* data)
+	{
+		LLObjectReturn* object_return = (LLObjectReturn*)data;
+
+		if (0 == option)
+		{
+			// Ignore category ID for this derez destination.
+			derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null);
+		}
+
+		// drop reference to current selection
+		object_return->mObjectSelection = NULL;
+	}
+
+protected:
+	LLObjectSelectionHandle mObjectSelection;
 };
 
 
@@ -3701,10 +3695,11 @@ class LLObjectEnableReturn : public view_listener_t
 				}
 				else
 				{
+					LLObjectSelectionHandle selection = gSelectMgr->getSelection();
 					LLViewerObject* obj = NULL;
-					for(obj = gSelectMgr->getFirstRootObject();
+					for(obj = selection->getFirstRootObject();
 						obj;
-						obj = gSelectMgr->getNextRootObject())
+						obj = selection->getNextRootObject())
 					{
 						if (obj->isOverAgentOwnedLand()
 							|| obj->isOverGroupOwnedLand()
@@ -3725,22 +3720,16 @@ class LLObjectEnableReturn : public view_listener_t
 
 void force_take_copy(void*)
 {
-	if (gSelectMgr->isEmpty()) return;
+	if (gSelectMgr->getSelection()->isEmpty()) return;
 	const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
 	derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id);
-
-	// Only deselect if we're not building
-	if (!gToolMgr->inEdit())
-	{
-		gSelectMgr->deselectTransient();
-	}
 }
 #ifdef _CORY_TESTING
 
 void force_export_copy(void*)
 {
 	LLViewerObject* object = NULL;
-	LLSelectNode* node = gSelectMgr->getFirstNode();
+	LLSelectNode* node = gSelectMgr->getSelection()->getFirstNode();
 	if(!node) return;
 	object = node->getObject();
 	if(!object) return;
@@ -3761,7 +3750,7 @@ void force_export_copy(void*)
 
 	S32 object_index = 0;
 
-	for( ; node != NULL; node = gSelectMgr->getNextNode())
+	for( ; node != NULL; node = gSelectMgr->getSelection()->getNextNode())
 	{
 		object = node->getObject();
 		if(!object || !node->mValid)
@@ -4090,16 +4079,16 @@ void handle_take()
 {
 	// we want to use the folder this was derezzed from if it's
 	// available. Otherwise, derez to the normal place.
-	if(gSelectMgr->isEmpty()) return;
+	if(gSelectMgr->getSelection()->isEmpty()) return;
 	LLSelectNode* node = NULL;
 	LLViewerObject* object = NULL;
 	BOOL you_own_everything = TRUE;
 
 	BOOL locked_but_takeable_object = FALSE;
 	LLUUID category_id;
-	for(node = gSelectMgr->getFirstRootNode();
+	for(node = gSelectMgr->getSelection()->getFirstRootNode();
 		node != NULL;
-		node = gSelectMgr->getNextRootNode())
+		node = gSelectMgr->getSelection()->getNextRootNode())
 	{
 		object = node->getObject();
 		if(object)
@@ -4222,9 +4211,9 @@ BOOL enable_take()
 	}
 
 	LLViewerObject* object = NULL;
-	for(LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	for(LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 		node != NULL;
-		node = gSelectMgr->getNextRootNode())
+		node = gSelectMgr->getSelection()->getNextRootNode())
 	{
 		object = node->getObject();
 		if(!object || !node->mValid) continue;
@@ -4258,7 +4247,7 @@ class LLToolsBuyOrTake : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		if (gSelectMgr->isEmpty())
+		if (gSelectMgr->getSelection()->isEmpty())
 		{
 			return true;
 		}
@@ -4338,9 +4327,9 @@ class LLToolsEnableBuyOrTake : public view_listener_t
 BOOL is_selection_buy_not_take()
 {
 	LLViewerObject* obj = NULL;
-	for(LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	for(LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 		node != NULL;
-		node = gSelectMgr->getNextRootNode())
+		node = gSelectMgr->getSelection()->getNextRootNode())
 	{
 		obj = node->getObject();
 		if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
@@ -4357,9 +4346,9 @@ S32 selection_price()
 {
 	LLViewerObject* obj = NULL;
 	S32 total_price = 0;
-	for(LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	for(LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 		node != NULL;
-		node = gSelectMgr->getNextRootNode())
+		node = gSelectMgr->getSelection()->getNextRootNode())
 	{
 		obj = node->getObject();
 		if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
@@ -4408,7 +4397,7 @@ void handle_buy_currency(void*)
 
 void handle_buy(void*)
 {
-	if (gSelectMgr->isEmpty()) return;
+	if (gSelectMgr->getSelection()->isEmpty()) return;
 
 	LLSaleInfo sale_info;
 	BOOL valid = gSelectMgr->selectGetSaleInfo(sale_info);
@@ -4435,7 +4424,7 @@ class LLObjectBuy : public view_listener_t
 
 BOOL sitting_on_selection()
 {
-	LLSelectNode* node = gSelectMgr->getFirstRootNode();
+	LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 	if (!node)
 	{
 		return FALSE;
@@ -4480,7 +4469,7 @@ class LLToolsSaveToObjectInventory : public view_listener_t
 	{
 		if(gSelectMgr)
 		{
-			LLSelectNode* node = gSelectMgr->getFirstRootNode();
+			LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 			if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
 			{
 				// *TODO: check to see if the fromtaskid object exists.
@@ -4499,9 +4488,10 @@ class LLToolsSnapObjectXY : public view_listener_t
 		F64 snap_size = (F64)gSavedSettings.getF32("GridResolution");
 
 		LLViewerObject* obj;
-		for (obj = gSelectMgr->getFirstRootObject();
+		LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+		for (obj = selection->getFirstRootObject();
 			obj != NULL;
-			obj = gSelectMgr->getNextRootObject())
+			obj = selection->getNextRootObject())
 		{
 			if (obj->permModify())
 			{
@@ -4557,11 +4547,12 @@ class LLToolsEnableLink : public view_listener_t
 		// in component mode, can't link
 		if (gSavedSettings.getBOOL("SelectLinkedSet"))
 		{
-			if(gSelectMgr->selectGetAllRootsValid() && gSelectMgr->getRootObjectCount() >= 2)
+			if(gSelectMgr->selectGetAllRootsValid() && gSelectMgr->getSelection()->getRootObjectCount() >= 2)
 			{
-				for(LLViewerObject* object = gSelectMgr->getFirstRootObject();
+				LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+				for(LLViewerObject* object = selection->getFirstRootObject();
 					object != NULL;
-					object = gSelectMgr->getNextRootObject())
+					object = selection->getNextRootObject())
 				{
 					if(object->permModify())
 					{
@@ -4586,7 +4577,7 @@ class LLToolsLink : public view_listener_t
 			return true;
 		}
 
-		S32 object_count = gSelectMgr->getObjectCount();
+		S32 object_count = gSelectMgr->getSelection()->getObjectCount();
 		if (object_count > MAX_CHILDREN_PER_TASK + 1)
 		{
 			LLStringBase<char>::format_map_t args;
@@ -4597,7 +4588,7 @@ class LLToolsLink : public view_listener_t
 			return true;
 		}
 
-		if(gSelectMgr->getRootObjectCount() < 2)
+		if(gSelectMgr->getSelection()->getRootObjectCount() < 2)
 		{
 			gViewerWindow->alertXml("CannotLinkIncompleteSet");
 			return true;
@@ -4627,8 +4618,8 @@ class LLToolsEnableUnlink : public view_listener_t
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
 		bool new_value = gSelectMgr->selectGetAllRootsValid() &&
-			gSelectMgr->getFirstEditableObject() &&
-			!gSelectMgr->getFirstEditableObject()->isAttachment();
+			gSelectMgr->getSelection()->getFirstEditableObject() &&
+			!gSelectMgr->getSelection()->getFirstEditableObject()->isAttachment();
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 		return true;
 	}
@@ -4690,7 +4681,7 @@ void handle_dehinge(void*)
 
 BOOL enable_dehinge(void*)
 {
-	LLViewerObject* obj = gSelectMgr->getFirstEditableObject();
+	LLViewerObject* obj = gSelectMgr->getSelection()->getFirstEditableObject();
 	return obj && !obj->isAttachment();
 }
 
@@ -5890,12 +5881,13 @@ LLUploadDialog *gExportDialog = NULL;
 
 void handle_export_selected( void * )
 {
-	if (gSelectMgr->isEmpty())
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	if (selection->isEmpty())
 	{
 		return;
 	}
 	llinfos << "Exporting selected objects:" << llendl;
-	LLViewerObject *object = gSelectMgr->getFirstRootObject();
+	LLViewerObject *object = selection->getFirstRootObject();
 
 	gExporterRequestID.generate();
 	gExportDirectory = "";
@@ -5907,7 +5899,7 @@ void handle_export_selected( void * )
 	msg->addUUIDFast(_PREHASH_RequestID, gExporterRequestID);
 	msg->addS16Fast(_PREHASH_VolumeDetail, 4);
 
-	for (; object != NULL; object = gSelectMgr->getNextRootObject())
+	for (; object != NULL; object = selection->getNextRootObject())
 	{
 		msg->nextBlockFast(_PREHASH_ObjectData);
 		msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
@@ -5921,7 +5913,7 @@ void handle_export_selected( void * )
 BOOL menu_check_build_tool( void* user_data )
 {
 	S32 index = (intptr_t) user_data;
-	return gCurrentToolset->isToolSelected( index );
+	return gToolMgr->getCurrentToolset()->isToolSelected( index );
 }
 
 void handle_reload_settings(void*)
@@ -6070,7 +6062,7 @@ class LLToolsLookAtSelection : public view_listener_t
 	{
 		const F32 PADDING_FACTOR = 2.f;
 		BOOL zoom = (userdata.asString() == "zoom");
-		if (!gSelectMgr->isEmpty())
+		if (!gSelectMgr->getSelection()->isEmpty())
 		{
 			gAgent.setFocusOnAvatar(FALSE, ANIMATE);
 
@@ -6083,11 +6075,11 @@ class LLToolsLookAtSelection : public view_listener_t
 
 			if (zoom)
 			{
-				gAgent.setCameraPosAndFocusGlobal(gSelectMgr->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), gSelectMgr->getSelectionCenterGlobal(), gSelectMgr->getFirstObject()->mID );
+				gAgent.setCameraPosAndFocusGlobal(gSelectMgr->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), gSelectMgr->getSelectionCenterGlobal(), gSelectMgr->getSelection()->getFirstObject()->mID );
 			}
 			else
 			{
-				gAgent.setFocusGlobal( gSelectMgr->getSelectionCenterGlobal(), gSelectMgr->getFirstObject()->mID );
+				gAgent.setFocusGlobal( gSelectMgr->getSelectionCenterGlobal(), gSelectMgr->getSelection()->getFirstObject()->mID );
 			}
 		}
 		return true;
@@ -6112,7 +6104,6 @@ class LLAvatarAddFriend : public view_listener_t
 		{
 			request_friendship(avatar->getID());
 		}
-		gSelectMgr->deselectTransient();
 		return true;
 	}
 };
@@ -6239,7 +6230,7 @@ class LLObjectEnableSitOrStand : public view_listener_t
 		}
 		else
 		{
-			LLSelectNode* node = gSelectMgr->getFirstRootNode();
+			LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 			if (node && node->mValid && !node->mSitName.empty())
 			{
 				label.assign(node->mSitName);
@@ -6275,25 +6266,6 @@ void dump_inventory(void*)
 	gInventory.dumpInventory();
 }
 
-
-void handle_first_tool(void*)
-{
-	gCurrentToolset->selectFirstTool();
-}
-
-
-void handle_next_tool(void*)
-{
-	gCurrentToolset->selectNextTool();
-}
-
-
-void handle_previous_tool(void*)
-{
-	gCurrentToolset->selectPrevTool();
-}
-
-
 // forcibly unlock an object
 void handle_force_unlock(void*)
 {
@@ -6302,7 +6274,7 @@ void handle_force_unlock(void*)
 
 	// Second, lie to the viewer and mark it editable and unowned
 	LLViewerObject* object;
-	for (object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() )
+	for (object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() )
 	{
 		object->mFlags |= FLAGS_OBJECT_MOVE;
 		object->mFlags |= FLAGS_OBJECT_MODIFY;
@@ -6722,8 +6694,8 @@ void handle_focus(void *)
 	gViewerWindow->moveCursorToCenter();
 
 	// Switch to camera toolset
-//	gCurrentToolset = gCameraToolset;
-	gCurrentToolset->selectTool( gToolCamera );
+//	gToolMgr->setCurrentToolset(gCameraToolset);
+	gToolMgr->getCurrentToolset()->selectTool( gToolCamera );
 }
 
 class LLLandEdit : public view_listener_t
@@ -6749,10 +6721,10 @@ class LLLandEdit : public view_listener_t
 		gParcelMgr->selectParcelAt( gLastHitPosGlobal );
 
 		gFloaterTools->showMore(TRUE);
-	gFloaterView->bringToFront( gFloaterTools );
+		gFloaterView->bringToFront( gFloaterTools );
 
 		// Switch to land edit toolset
-		gCurrentToolset->selectTool( gToolParcel );
+		gToolMgr->getCurrentToolset()->selectTool( gToolParcel );
 		return true;
 	}
 };
@@ -6764,7 +6736,7 @@ class LLWorldEnableBuyLand : public view_listener_t
 		bool new_value = gParcelMgr->canAgentBuyParcel(
 								gParcelMgr->selectionEmpty()
 									? gParcelMgr->getAgentParcel()
-									: gParcelMgr->getSelectedParcel(),
+									: gParcelMgr->getParcelSelection()->getParcel(),
 								false);
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 		return true;
@@ -6774,7 +6746,7 @@ class LLWorldEnableBuyLand : public view_listener_t
 BOOL enable_buy_land(void*)
 {
 	return gParcelMgr->canAgentBuyParcel(
-				gParcelMgr->getSelectedParcel(), false);
+				gParcelMgr->getParcelSelection()->getParcel(), false);
 }
 
 
@@ -6795,46 +6767,59 @@ void handle_move(void*)
 
 	gViewerWindow->moveCursorToCenter();
 
-	gCurrentToolset = gBasicToolset;
-	gCurrentToolset->selectTool( gToolGrab );
-}
-
-
-void near_attach_object(BOOL success, void *user_data)
-{
-	LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
-	
-	U8 attachment_id;
-	if (attachment)
-	{
-		attachment_id = gAgent.getAvatarObject()->mAttachmentPoints.reverseLookup(attachment);
-	}
-	else
-	{
-		// interpret 0 as "default location"
-		attachment_id = 0;
-	}
-	
-	gSelectMgr->sendAttach(attachment_id);
+	gToolMgr->setCurrentToolset(gBasicToolset);
+	gToolMgr->getCurrentToolset()->selectTool( gToolGrab );
 }
 
 class LLObjectAttachToAvatar : public view_listener_t
 {
+public:
+	static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; }
+
+private:
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		LLViewerObject* selectedObject = gSelectMgr->getFirstRootObject();
+		setObjectSelection(gSelectMgr->getSelection());
+		LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject();
 		if (selectedObject)
 		{
-			confirm_replace_attachment(0, NULL);
+			LLViewerJointAttachment* attachment_point = gAgent.getAvatarObject()->mAttachmentPoints[userdata.asInteger()];
+			confirm_replace_attachment(0, attachment_point);
 		}
 		return true;
 	}
+
+protected:
+	static LLObjectSelectionHandle sObjectSelection;
 };
 
+LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection;
+
+void near_attach_object(BOOL success, void *user_data)
+{
+	if (success)
+	{
+		LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
+		
+		U8 attachment_id;
+		if (attachment)
+		{
+			attachment_id = gAgent.getAvatarObject()->mAttachmentPoints.reverseLookup(attachment);
+		}
+		else
+		{
+			// interpret 0 as "default location"
+			attachment_id = 0;
+		}
+		gSelectMgr->sendAttach(attachment_id);
+	}		
+	LLObjectAttachToAvatar::setObjectSelection(NULL);
+}
+
 // move this somewhere global
 void handle_attach_to_avatar(void* user_data)
 {
-    LLViewerObject* selectedObject = gSelectMgr->getFirstRootObject();
+    LLViewerObject* selectedObject = gSelectMgr->getSelection()->getFirstRootObject();
     if (selectedObject)
     {
         LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
@@ -6853,8 +6838,7 @@ void confirm_replace_attachment(S32 option, void* user_data)
 {
 	if (option == 0/*YES*/)
 	{
-		gSelectMgr->convertTransient();
-		LLViewerObject* selectedObject = gSelectMgr->getFirstRootObject();
+		LLViewerObject* selectedObject = gSelectMgr->getSelection()->getFirstRootObject();
 		if (selectedObject)
 		{
 			const F32 MIN_STOP_DISTANCE = 1.f;	// meters
@@ -6921,12 +6905,7 @@ class LLAttachmentDrop : public view_listener_t
 		// objects.  Thus we need to clear the list, make sure it only
 		// contains the object the user clicked, send the message,
 		// then clear the list.
-		// We use deselectAll to update the simulator's notion of what's
-		// selected, and removeAll just to change things locally.
-		//gSelectMgr->deselectAll();
-		//gSelectMgr->selectObjectAndFamily(object);
 		gSelectMgr->sendDropAttachment();
-		gSelectMgr->deselectTransient();
 		return true;
 	}
 };
@@ -7029,10 +7008,9 @@ class LLAttachmentDetach : public view_listener_t
 		// We use deselectAll to update the simulator's notion of what's
 		// selected, and removeAll just to change things locally.
 		//RN: I thought it was more useful to detach everything that was selected
-		if (gSelectMgr->selectionIsAttachment())
+		if (gSelectMgr->getSelection()->isAttachment())
 		{
 			gSelectMgr->sendDetach();
-			gSelectMgr->deselectAll();
 		}
 		return true;
 	}
@@ -7149,8 +7127,10 @@ class LLAttachmentEnableDetach : public view_listener_t
 BOOL object_selected_and_point_valid(void *user_data)
 {
 	//LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data;
+	if (gSelectMgr == NULL) return FALSE;
 
-	for (LLViewerObject *object = gSelectMgr->getFirstRootObject(); object; object = gSelectMgr->getNextRootObject())
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	for (LLViewerObject *object = selection->getFirstRootObject(); object; object = selection->getNextRootObject())
 	{
 		for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++ )
 		{
@@ -7161,12 +7141,11 @@ BOOL object_selected_and_point_valid(void *user_data)
 		}
 	}
 
-	return ((gSelectMgr != NULL) && 
-		(gSelectMgr->getRootObjectCount() == 1) && 
-		(gSelectMgr->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && 
-		gSelectMgr->getFirstRootObject()->permYouOwner() &&
-		!((LLViewerObject*)gSelectMgr->getFirstRootObject()->getRoot())->isAvatar() && 
-		(gSelectMgr->getFirstRootObject()->getNVPair("AssetContainer") == NULL));
+	return (selection->getRootObjectCount() == 1) && 
+		(selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && 
+		selection->getFirstRootObject()->permYouOwner() &&
+		!((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && 
+		(selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL);
 }
 
 // Also for seeing if object can be attached.  See above.
@@ -7177,13 +7156,14 @@ class LLObjectEnableWear : public view_listener_t
 		bool new_value = false;
 		if (gSelectMgr)
 		{
-			LLViewerObject* first_root = gSelectMgr->getFirstRootObject();
+			LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+			LLViewerObject* first_root = selection->getFirstRootObject();
 			if (first_root)
 			{
-				new_value = gSelectMgr->getRootObjectCount() == 1
+				new_value = selection->getRootObjectCount() == 1
 								&& first_root->getPCode() == LL_PCODE_VOLUME
 								&& first_root->permYouOwner()
-								&& !((LLViewerObject*)gSelectMgr->getFirstRootObject()->getRoot())->isAvatar()
+								&& !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar()
 								&& (first_root->getNVPair("AssetContainer") == NULL);
 			}
 		}
@@ -7266,9 +7246,9 @@ class LLToolsSelectedScriptAction : public view_listener_t
 		BOOL scripted = FALSE;
 		BOOL modifiable = FALSE;
 
-		for(LLViewerObject* obj = gSelectMgr->getFirstObject();
+		for(LLViewerObject* obj = gSelectMgr->getSelection()->getFirstObject();
 			obj;
-			obj = gSelectMgr->getNextObject())
+			obj = gSelectMgr->getSelection()->getNextObject())
 		{
 			scripted = obj->flagScripted();
 			modifiable = obj->permModify();
@@ -7301,9 +7281,9 @@ void handle_reset_selection(void*)
 	BOOL scripted = FALSE;
 	BOOL modifiable = FALSE;
 
-	for(LLViewerObject* obj = gSelectMgr->getFirstObject();
+	for(LLViewerObject* obj = gSelectMgr->getSelection()->getFirstObject();
 		obj;
-		obj = gSelectMgr->getNextObject())
+		obj = gSelectMgr->getSelection()->getNextObject())
 	{
 		scripted = obj->flagScripted();
 		modifiable = obj->permModify();
@@ -7334,9 +7314,9 @@ void handle_set_run_selection(void*)
 	BOOL scripted = FALSE;
 	BOOL modifiable = FALSE;
 
-	for(LLViewerObject* obj = gSelectMgr->getFirstObject();
+	for(LLViewerObject* obj = gSelectMgr->getSelection()->getFirstObject();
 		obj;
-		obj = gSelectMgr->getNextObject())
+		obj = gSelectMgr->getSelection()->getNextObject())
 	{
 		scripted = obj->flagScripted();
 		modifiable = obj->permModify();
@@ -7367,9 +7347,9 @@ void handle_set_not_run_selection(void*)
 	BOOL scripted = FALSE;
 	BOOL modifiable = FALSE;
 
-	for(LLViewerObject* obj = gSelectMgr->getFirstObject();
+	for(LLViewerObject* obj = gSelectMgr->getSelection()->getFirstObject();
 		obj;
-		obj = gSelectMgr->getNextObject())
+		obj = gSelectMgr->getSelection()->getNextObject())
 	{
 		scripted = obj->flagScripted();
 		modifiable = obj->permModify();
@@ -7396,7 +7376,7 @@ void handle_set_not_run_selection(void*)
 void handle_selected_texture_info(void*)
 {
 	LLSelectNode* node = NULL;
-	for (node = gSelectMgr->getFirstNode(); node != NULL; node = gSelectMgr->getNextNode())
+	for (node = gSelectMgr->getSelection()->getFirstNode(); node != NULL; node = gSelectMgr->getSelection()->getNextNode())
 	{
 		if (!node->mValid) continue;
 
@@ -7583,7 +7563,7 @@ class LLSomethingSelected : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		bool new_value = !(gSelectMgr->isEmpty());
+		bool new_value = !(gSelectMgr->getSelection()->isEmpty());
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 		return true;
 	}
@@ -7593,7 +7573,8 @@ class LLSomethingSelectedNoHUD : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		bool new_value = !(gSelectMgr->isEmpty()) && !(gSelectMgr->getSelectType() == SELECT_TYPE_HUD);
+		LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+		bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD);
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 		return true;
 	}
@@ -7601,14 +7582,14 @@ class LLSomethingSelectedNoHUD : public view_listener_t
 
 BOOL enable_more_than_one_selected(void* )
 {
-	return (gSelectMgr->getObjectCount() > 1);
+	return (gSelectMgr->getSelection()->getObjectCount() > 1);
 }
 
 class LLEditableSelected : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		bool new_value = (gSelectMgr->getFirstEditableObject() != NULL);
+		bool new_value = (gSelectMgr->getSelection()->getFirstEditableObject() != NULL);
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 		return true;
 	}
@@ -7627,10 +7608,11 @@ class LLToolsEnableTakeCopy : public view_listener_t
 			if (gInProductionGrid || !gAgent.isGodlike())
 # endif
 			{
-				LLViewerObject* obj = gSelectMgr->getFirstRootObject();
+				LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+				LLViewerObject* obj = selection->getFirstRootObject();
 				if(obj)
 				{
-					for( ; obj; obj = gSelectMgr->getNextRootObject())
+					for( ; obj; obj = selection->getNextRootObject())
 					{
 						if(!(obj->permCopy()) || obj->isAttachment())
 						{
@@ -7650,11 +7632,15 @@ class LLToolsEnableTakeCopy : public view_listener_t
 BOOL enable_selection_you_own_all(void*)
 {
 	LLViewerObject *obj;
-	for (obj = gSelectMgr->getFirstRootObject(); obj; obj = gSelectMgr->getNextRootObject())
+	if (gSelectMgr)
 	{
-		if (!obj->permYouOwner())
+		LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+		for (obj = selection->getFirstRootObject(); obj; obj = selection->getNextRootObject())
 		{
-			return FALSE;
+			if (!obj->permYouOwner())
+			{
+				return FALSE;
+			}
 		}
 	}
 
@@ -7663,15 +7649,18 @@ BOOL enable_selection_you_own_all(void*)
 
 BOOL enable_selection_you_own_one(void*)
 {
-	LLViewerObject *obj;
-	for (obj = gSelectMgr->getFirstRootObject(); obj; obj = gSelectMgr->getNextRootObject())
+	if (gSelectMgr)
 	{
-		if (obj->permYouOwner())
+		LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+		LLViewerObject *obj;
+		for (obj = selection->getFirstRootObject(); obj; obj = selection->getNextRootObject())
 		{
-			return TRUE;
+			if (obj->permYouOwner())
+			{
+				return TRUE;
+			}
 		}
 	}
-
 	return FALSE;
 }
 
@@ -7705,9 +7694,9 @@ BOOL enable_save_into_inventory(void*)
 	{
 		// find the last root
 		LLSelectNode* last_node = NULL;
-		for(LLSelectNode* node = gSelectMgr->getFirstRootNode();
+		for(LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 			node != NULL;
-			node = gSelectMgr->getNextRootNode())
+			node = gSelectMgr->getSelection()->getNextRootNode())
 		{
 			last_node = node;
 		}
@@ -7751,7 +7740,7 @@ BOOL enable_save_into_task_inventory(void*)
 {
 	if(gSelectMgr)
 	{
-		LLSelectNode* node = gSelectMgr->getFirstRootNode();
+		LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode();
 		if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
 		{
 			// *TODO: check to see if the fromtaskid object exists.
@@ -7792,7 +7781,7 @@ class LLFileEnableUpload : public view_listener_t
 
 BOOL enable_export_selected(void *)
 {
-	if (gSelectMgr->isEmpty())
+	if (gSelectMgr->getSelection()->isEmpty())
 	{
 		return FALSE;
 	}
@@ -7823,7 +7812,7 @@ class LLToolsEnableToolNotPie : public view_listener_t
 {
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
-		bool new_value = ( gToolMgr->getCurrentTool(MASK_NONE) != gToolPie );
+		bool new_value = ( gToolMgr->getBaseTool() != gToolPie );
 		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
 		return true;
 	}
@@ -8212,10 +8201,10 @@ class LLToolsUseSelectionForGrid : public view_listener_t
 	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
 	{
 		gSelectMgr->clearGridObjects();
-
-		for (LLViewerObject* objectp = gSelectMgr->getFirstRootObject();
+		LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+		for (LLViewerObject* objectp = selection->getFirstRootObject();
 			objectp;
-			objectp = gSelectMgr->getNextRootObject())
+			objectp = selection->getNextRootObject())
 			{
 				gSelectMgr->addGridObject(objectp);
 			}
@@ -8240,25 +8229,35 @@ void handle_test_load_url(void*)
 // LLViewerMenuHolderGL
 //
 
+LLViewerMenuHolderGL::LLViewerMenuHolderGL() : LLMenuHolderGL()
+{
+}
+
 BOOL LLViewerMenuHolderGL::hideMenus()
 {
 	BOOL handled = LLMenuHolderGL::hideMenus();
-	if (handled)
-	{
-		gSelectMgr->deselectTransient();
-		if(!gFloaterTools->getVisible()
-		   && !LLFloaterLand::floaterVisible()
-		   && !LLFloaterBuyLand::isOpen()) 
-		{
-			gParcelMgr->deselectLand();	
-		}
-	}
+
+	// drop pie menu selection
+	mParcelSelection = NULL;
+	mObjectSelection = NULL;
+
 	gMenuBarView->clearHoverItem();
 	gMenuBarView->resetMenuTrigger();
 
 	return handled;
 }
 
+void LLViewerMenuHolderGL::setParcelSelection(LLHandle<LLParcelSelection> selection) 
+{ 
+	mParcelSelection = selection; 
+}
+
+void LLViewerMenuHolderGL::setObjectSelection(LLHandle<LLObjectSelection> selection) 
+{ 
+	mObjectSelection = selection; 
+}
+
+
 const LLRect LLViewerMenuHolderGL::getMenuRect() const
 {
 	return LLRect(0, mRect.getHeight() - MENU_BAR_HEIGHT, mRect.getWidth(), STATUS_BAR_HEIGHT);
@@ -8586,23 +8585,23 @@ class LLToolsSelectTool : public view_listener_t
 		LLString tool_name = userdata.asString();
 		if (tool_name == "focus")
 		{
-			gCurrentToolset->selectToolByIndex(1);
+			gToolMgr->getCurrentToolset()->selectToolByIndex(1);
 		}
 		else if (tool_name == "move")
 		{
-			gCurrentToolset->selectToolByIndex(2);
+			gToolMgr->getCurrentToolset()->selectToolByIndex(2);
 		}
 		else if (tool_name == "edit")
 		{
-			gCurrentToolset->selectToolByIndex(3);
+			gToolMgr->getCurrentToolset()->selectToolByIndex(3);
 		}
 		else if (tool_name == "create")
 		{
-			gCurrentToolset->selectToolByIndex(4);
+			gToolMgr->getCurrentToolset()->selectToolByIndex(4);
 		}
 		else if (tool_name == "land")
 		{
-			gCurrentToolset->selectToolByIndex(5);
+			gToolMgr->getCurrentToolset()->selectToolByIndex(5);
 		}
 		return true;
 	}
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index 182190ccdf2b9edabdabb9676564c17237542018..f2d7e360c73ee9281c8d4ee1ed1ba77a73d521e9 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -18,6 +18,8 @@
 
 class LLUICtrl;
 class LLView;
+class LLParcelSelection;
+class LLObjectSelection;
 
 struct LLResourceData
 {
@@ -126,11 +128,18 @@ class LLPermissions;
 class LLViewerMenuHolderGL : public LLMenuHolderGL
 {
 public:
-	LLViewerMenuHolderGL() : LLMenuHolderGL() {};
+	LLViewerMenuHolderGL();
 
 	virtual BOOL hideMenus();
+	
+	void setParcelSelection(LLHandle<LLParcelSelection> selection);
+	void setObjectSelection(LLHandle<LLObjectSelection> selection);
+
 	virtual const LLRect getMenuRect() const;
-	//virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+
+protected:
+	LLHandle<LLParcelSelection> mParcelSelection;
+	LLHandle<LLObjectSelection> mObjectSelection;
 };
 
 extern const LLString SAVE_INTO_INVENTORY;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index f402fc320bbf23d4cdbbd380ee3a0dd6d35164d5..502171584c6b19512069682c01ab07045a048397 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2990,7 +2990,7 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
 			//llinfos << "Kill message for local " << local_id << llendl;
 		}
 
-		gSelectMgr->selectionRemoveObject(id);
+		gSelectMgr->removeObjectFromSelections(id);
 
 		// ...don't kill the avatar
 		if (!(id == gAgentID))
@@ -3472,12 +3472,15 @@ void process_camera_constraint(LLMessageSystem *mesgsys, void **user_data)
 
 void near_sit_object(BOOL success, void *data)
 {
-	// Send message to sit on object
-	gMessageSystem->newMessageFast(_PREHASH_AgentSit);
-	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	gAgent.sendReliableMessage();
+	if (success)
+	{
+		// Send message to sit on object
+		gMessageSystem->newMessageFast(_PREHASH_AgentSit);
+		gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+		gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+		gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		gAgent.sendReliableMessage();
+	}
 }
 
 void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data)
@@ -3518,9 +3521,6 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data)
 		{
 			gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(sit_spot), "Sit", &sitRotation, near_sit_object, NULL, 0.5f);
 		}
-
-		// deselect transient selections (pie menu) when sitting
-		gSelectMgr->deselectTransient();
 	}
 	else
 	{
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index b630572a9b34d26904b4a55f76e6b908eb8c23a8..f4c733299f6b0948d6fdcb2f212f72b8fdbe6650 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -211,7 +211,7 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
 		&& update_type != OUT_TERSE_IMPROVED 
 		&& objectp->mCreateSelected)
 	{
-		if ( gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ) != gToolPie )
+		if ( gToolMgr->getCurrentTool() != gToolPie )
 		{
 			//llinfos << "DEBUG selecting " << objectp->mID << " " 
 			//		<< objectp->mLocalID << llendl;
@@ -565,7 +565,8 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
 	}
 
 	// Selected
-	for (objectp = gSelectMgr->getFirstRootObject(); objectp; objectp = gSelectMgr->getNextRootObject())
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+	for (objectp = selection->getFirstRootObject(); objectp; objectp = selection->getNextRootObject())
 	{
 		objectp->boostTexturePriority();
 	}
@@ -1421,7 +1422,7 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
 
 	if (orphans_found && objectp->isSelected())
 	{
-		LLSelectNode* nodep = gSelectMgr->findSelectNode(objectp);
+		LLSelectNode* nodep = gSelectMgr->getSelection()->findNode(objectp);
 		if (nodep && !nodep->mIndividualSelection)
 		{
 			// rebuild selection with orphans
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 81576bd5fc01c737403aad36326a504eecf4e3eb..c1d2f2742eee1d16a93e127f698dfb8eba6f5245 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -46,6 +46,7 @@
 
 const F32 PARCEL_COLLISION_DRAW_SECS = 1.f;
 
+
 // Globals
 LLViewerParcelMgr *gParcelMgr = NULL;
 
@@ -53,6 +54,12 @@ U8* LLViewerParcelMgr::sPackedOverlay = NULL;
 
 LLUUID gCurrentMovieID = LLUUID::null;
 
+static LLParcelSelection* get_null_parcel_selection();
+template<> 
+	const LLHandle<LLParcelSelection>::NullFunc 
+		LLHandle<LLParcelSelection>::sNullFunc = get_null_parcel_selection;
+
+
 // Local functions
 void optionally_start_music(const LLString& music_url);
 void callback_start_music(S32 option, void* data);
@@ -83,8 +90,6 @@ struct LLGodForceOwnerData
 //
 LLViewerParcelMgr::LLViewerParcelMgr()
 :	mSelected(FALSE),
-	mSelectedMultipleOwners(FALSE),
-	mWholeParcelSelected(FALSE),
 	mWestSouth(),
 	mEastNorth(),
 	mSelectedDwell(0.f),
@@ -94,11 +99,12 @@ LLViewerParcelMgr::LLViewerParcelMgr()
 	mRenderCollision(FALSE),
 	mRenderSelection(TRUE),
 	mCollisionBanned(0),
-	mCollisionTimer(),
-	mMediaParcelId(0),
-	mMediaRegionId(0)
+	mCollisionTimer()
 {
-	mParcel = new LLParcel();
+	mCurrentParcel = new LLParcel();
+	mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
+	mFloatingParcelSelection = new LLParcelSelection(mCurrentParcel);
+
 	mAgentParcel = new LLParcel();
 	mHoverParcel = new LLParcel();
 	mCollisionParcel = new LLParcel();
@@ -130,8 +136,14 @@ LLViewerParcelMgr::LLViewerParcelMgr()
 
 LLViewerParcelMgr::~LLViewerParcelMgr()
 {
-	delete mParcel;
-	mParcel = NULL;
+	mCurrentParcelSelection->setParcel(NULL);
+	mCurrentParcelSelection = NULL;
+
+	mFloatingParcelSelection->setParcel(NULL);
+	mFloatingParcelSelection = NULL;
+
+	delete mCurrentParcel;
+	mCurrentParcel = NULL;
 
 	delete mAgentParcel;
 	mAgentParcel = NULL;
@@ -156,32 +168,17 @@ LLViewerParcelMgr::~LLViewerParcelMgr()
 	mAgentParcelOverlay = NULL;
 }
 
-
-void LLViewerParcelMgr::destroyGL()
-{
-	mBlockedImage = NULL;
-	mPassImage = NULL;
-}
-
-
-void LLViewerParcelMgr::restoreGL()
-{
-	mBlockedImage = gImageList.getImage(mBlockedImageID, TRUE, TRUE);
-	mPassImage = gImageList.getImage(mPassImageID, TRUE, TRUE);
-}
-
-
 void LLViewerParcelMgr::dump()
 {
 	llinfos << "Parcel Manager Dump" << llendl;
 	llinfos << "mSelected " << S32(mSelected) << llendl;
 	llinfos << "Selected parcel: " << llendl;
 	llinfos << mWestSouth << " to " << mEastNorth << llendl;
-	mParcel->dump();
-	llinfos << "banning " << mParcel->mBanList.size() << llendl;
+	mCurrentParcel->dump();
+	llinfos << "banning " << mCurrentParcel->mBanList.size() << llendl;
 	
-	access_map_const_iterator cit = mParcel->mBanList.begin();
-	access_map_const_iterator end = mParcel->mBanList.end();
+	access_map_const_iterator cit = mCurrentParcel->mBanList.begin();
+	access_map_const_iterator end = mCurrentParcel->mBanList.end();
 	for ( ; cit != end; ++cit)
 	{
 		llinfos << "ban id " << (*cit).first << llendl;
@@ -214,27 +211,27 @@ void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out,
 
 	if (mSelected)
 	{
-		if (mSelectedMultipleOwners)
+		if (mCurrentParcelSelection->mSelectedMultipleOwners)
 		{
-			area = getClaimableArea();
+			area = mCurrentParcelSelection->getClaimableArea();
 		}
 		else
 		{
 			area = getSelectedArea();
 		}
 
-		if (mParcel->getForSale())
+		if (mCurrentParcel->getForSale())
 		{
-			price = mParcel->getSalePrice();
+			price = mCurrentParcel->getSalePrice();
 			for_sale = TRUE;
 		}
 		else
 		{
-			price = area * mParcel->getClaimPricePerMeter();
+			price = area * mCurrentParcel->getClaimPricePerMeter();
 			for_sale = FALSE;
 		}
 
-		rent = mParcel->getTotalRent();
+		rent = mCurrentParcel->getTotalRent();
 
 		dwell = mSelectedDwell;
 	}
@@ -248,51 +245,27 @@ void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out,
 
 void LLViewerParcelMgr::getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean)
 {
-	if (mSelected && mParcel)
+	if (mSelected && mCurrentParcel)
 	{
-		sw_max = mParcel->getSimWideMaxPrimCapacity();
-		sw_total = mParcel->getSimWidePrimCount();
-		max = llround(mParcel->getMaxPrimCapacity()*mParcel->getParcelPrimBonus());
-		total = mParcel->getPrimCount();
-		owner = mParcel->getOwnerPrimCount();
-		group = mParcel->getGroupPrimCount();
-		other = mParcel->getOtherPrimCount();
-		selected = mParcel->getSelectedPrimCount();
-		parcel_object_bonus = mParcel->getParcelPrimBonus();
-		other_clean = mParcel->getCleanOtherTime();
+		sw_max = mCurrentParcel->getSimWideMaxPrimCapacity();
+		sw_total = mCurrentParcel->getSimWidePrimCount();
+		max = llround(mCurrentParcel->getMaxPrimCapacity()*mCurrentParcel->getParcelPrimBonus());
+		total = mCurrentParcel->getPrimCount();
+		owner = mCurrentParcel->getOwnerPrimCount();
+		group = mCurrentParcel->getGroupPrimCount();
+		other = mCurrentParcel->getOtherPrimCount();
+		selected = mCurrentParcel->getSelectedPrimCount();
+		parcel_object_bonus = mCurrentParcel->getParcelPrimBonus();
+		other_clean = mCurrentParcel->getCleanOtherTime();
 	}
 }
 
-BOOL LLViewerParcelMgr::getMultipleOwners() const
-{
-	return mSelectedMultipleOwners;
-}
-
-
-BOOL LLViewerParcelMgr::getWholeParcelSelected() const
-{
-	return mWholeParcelSelected;
-}
-
-
-S32 LLViewerParcelMgr::getClaimableArea() const
-{
-	const S32 UNIT_AREA = S32( PARCEL_GRID_STEP_METERS * PARCEL_GRID_STEP_METERS );
-	return mSelectedPublicCount * UNIT_AREA;
-}
-
-bool LLViewerParcelMgr::hasOthersSelected() const
-{
-	return mSelectedOtherCount != 0;
-}
-
-
 S32 LLViewerParcelMgr::getSelectedArea() const
 {
 	S32 rv = 0;
-	if(mSelected && mParcel && mWholeParcelSelected)
+	if(mSelected && mCurrentParcel && mCurrentParcelSelection->mWholeParcelSelected)
 	{
-		rv = mParcel->getArea();
+		rv = mCurrentParcel->getArea();
 	}
 	else if(mSelected)
 	{
@@ -428,7 +401,7 @@ void LLViewerParcelMgr::writeAgentParcelFromBitmap(U8* bitmap)
 
 // Given a point, find the PARCEL_GRID_STEP x PARCEL_GRID_STEP block
 // containing it and select that.
-void LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global)
+LLParcelSelectionHandle LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global)
 {
 	LLVector3d southwest = pos_global;
 	LLVector3d northeast = pos_global;
@@ -442,14 +415,14 @@ void LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global)
 	northeast.mdV[VY] = llround( northeast.mdV[VY], (F64)PARCEL_GRID_STEP_METERS );
 
 	// Snap to parcel
-	selectLand( southwest, northeast, TRUE );
+	return selectLand( southwest, northeast, TRUE );
 }
 
 
 // Tries to select the parcel inside the rectangle
-void LLViewerParcelMgr::selectParcelInRectangle()
+LLParcelSelectionHandle LLViewerParcelMgr::selectParcelInRectangle()
 {
-	selectLand(mWestSouth, mEastNorth, TRUE);
+	return selectLand(mWestSouth, mEastNorth, TRUE);
 }
 
 
@@ -479,28 +452,32 @@ void LLViewerParcelMgr::selectCollisionParcel()
 	mRequestResult = PARCEL_RESULT_NO_DATA;
 
 	// Hack: Copy some data over temporarily
-	mParcel->setName( mCollisionParcel->getName() );
-	mParcel->setDesc( mCollisionParcel->getDesc() );
-	mParcel->setPassPrice(mCollisionParcel->getPassPrice());
-	mParcel->setPassHours(mCollisionParcel->getPassHours());
+	mCurrentParcel->setName( mCollisionParcel->getName() );
+	mCurrentParcel->setDesc( mCollisionParcel->getDesc() );
+	mCurrentParcel->setPassPrice(mCollisionParcel->getPassPrice());
+	mCurrentParcel->setPassHours(mCollisionParcel->getPassHours());
 
 	// clear the list of segments to prevent flashing
 	resetSegments(mHighlightSegments);
 
+	mFloatingParcelSelection->setParcel(mCurrentParcel);
+	mCurrentParcelSelection->setParcel(NULL);
+	mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
+
 	mSelected = TRUE;
-	mWholeParcelSelected = TRUE;
+	mCurrentParcelSelection->mWholeParcelSelected = TRUE;
 	notifyObservers();
 	return;
 }
 
 
 // snap_selection = auto-select the hit parcel, if there is exactly one
-void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &corner2,
+LLParcelSelectionHandle LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &corner2,
 								   BOOL snap_selection)
 {
 	if (!gWorldp)
 	{
-		return;
+		return NULL;
 	}
 
 	sanitize_corners( corner1, corner2, mWestSouth, mEastNorth );
@@ -511,7 +488,7 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &
 	{
 		mSelected = FALSE;
 		notifyObservers();
-		return;
+		return NULL;
 	}
 
 	// ...y isn't more than one meter away
@@ -520,7 +497,7 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &
 	{
 		mSelected = FALSE;
 		notifyObservers();
-		return;
+		return NULL;
 	}
 
 	// Can't select across region boundary
@@ -537,7 +514,7 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &
 	{
 		// just in case they somehow selected no land.
 		mSelected = FALSE;
-		return;
+		return NULL;
 	}
 
 	if (region != region_other)
@@ -545,50 +522,13 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &
 		LLNotifyBox::showXml("CantSelectLandFromMultipleRegions");
 		mSelected = FALSE;
 		notifyObservers();
-		return;
+		return NULL;
 	}
 
 	// Build region global copies of corners
 	LLVector3 wsb_region = region->getPosRegionFromGlobal( mWestSouth );
 	LLVector3 ent_region = region->getPosRegionFromGlobal( mEastNorth );
 
-	/*
-	// Check land to make sure all is either public, owned, or self
-	LLViewerParcelOverlay* overlay = region->getParcelOverlay();
-	if (!overlay)
-	{
-		llerrs << "No overlay in LLViewerParcelMgr::selectLand" << llendl;
-		return;
-	}
-
-	U8 start_ownership = overlay->ownership( wsb_region );
-	BOOL identical = TRUE;
-	S32 x_steps = S32( getSelectionWidth() / PARCEL_GRID_STEP_METERS );
-	S32 y_steps = S32( getSelectionHeight() / PARCEL_GRID_STEP_METERS );
-
-	for (S32 x = 0; x < x_steps && identical; x++ )
-	{
-		for (S32 y = 0; y < y_steps && identical; y++ )
-		{
-			// strange recomputation each time to avoid error accumulation
-			LLVector3 check = wsb_region;
-			check.mV[VX] += x * PARCEL_GRID_STEP_METERS;
-			check.mV[VY] += y * PARCEL_GRID_STEP_METERS;
-
-			identical = (start_ownership == overlay->ownership(check));
-		}
-	}
-
-	if (!identical)
-	{
-		add_chat("Can't select mix of your own, other people's and public land.", FALSE, "", FALSE, CHAT_SOURCE_SYSTEM);
-		add_chat("Try selecting a smaller piece of land.", FALSE, "", FALSE, CHAT_SOURCE_SYSTEM);
-		mSelected = FALSE;
-		notifyObservers();
-		return;
-	}
-	*/
-
 	// Send request message
 	LLMessageSystem *msg = gMessageSystem;
 	msg->newMessageFast(_PREHASH_ParcelPropertiesRequest);
@@ -609,12 +549,24 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &
 	// clear the list of segments to prevent flashing
 	resetSegments(mHighlightSegments);
 
+	mFloatingParcelSelection->setParcel(mCurrentParcel);
+	mCurrentParcelSelection->setParcel(NULL);
+	mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
+
 	mSelected = TRUE;
-	mWholeParcelSelected = snap_selection;
+	mCurrentParcelSelection->mWholeParcelSelected = snap_selection;
 	notifyObservers();
-	return;
+	return mCurrentParcelSelection;
 }
 
+void LLViewerParcelMgr::deselectUnused()
+{
+	// no more outstanding references to this selection, other than our own
+	if (mCurrentParcelSelection->getNumRefs() == 1 && mFloatingParcelSelection->getNumRefs() == 1)
+	{
+		deselectLand();
+	}
+}
 
 void LLViewerParcelMgr::deselectLand()
 {
@@ -623,14 +575,20 @@ void LLViewerParcelMgr::deselectLand()
 		mSelected = FALSE;
 
 		// Invalidate the selected parcel
-		mParcel->setLocalID(-1);
-		mParcel->mAccessList.clear();
-		mParcel->mBanList.clear();
-		//mParcel->mRenterList.reset();
+		mCurrentParcel->setLocalID(-1);
+		mCurrentParcel->mAccessList.clear();
+		mCurrentParcel->mBanList.clear();
+		//mCurrentParcel->mRenterList.reset();
 
 		mSelectedDwell = 0.f;
 
 		notifyObservers();
+
+		// invalidate parcel selection so that existing users of this selection can clean up
+		mCurrentParcelSelection->setParcel(NULL);
+		mFloatingParcelSelection->setParcel(NULL);
+		// create new parcel selection
+		mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
 	}
 }
 
@@ -675,18 +633,15 @@ BOOL LLViewerParcelMgr::selectionEmpty() const
 }
 
 
-LLParcel *LLViewerParcelMgr::getSelectedParcel() const
+LLParcelSelectionHandle LLViewerParcelMgr::getParcelSelection() const
 {
-	if (mSelected)
-	{
-		return mParcel;
-	}
-	else
-	{
-		return NULL;
-	}
+	return mCurrentParcelSelection;
 }
 
+LLParcelSelectionHandle LLViewerParcelMgr::getFloatingParcelSelection() const
+{
+	return mFloatingParcelSelection;
+}
 
 LLParcel *LLViewerParcelMgr::getAgentParcel() const
 {
@@ -905,11 +860,11 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
 
 	if (flags & AL_BAN) 
 	{
-		mParcel->mBanList.clear();
+		mCurrentParcel->mBanList.clear();
 	}
 	if (flags & AL_ACCESS) 
 	{
-		mParcel->mAccessList.clear();
+		mCurrentParcel->mAccessList.clear();
 	}		
 
 	// Only the headers differ
@@ -920,7 +875,7 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
 	msg->nextBlockFast(_PREHASH_Data);
 	msg->addS32Fast(_PREHASH_SequenceID, 0);
 	msg->addU32Fast(_PREHASH_Flags, flags);
-	msg->addS32("LocalID", mParcel->getLocalID() );
+	msg->addS32("LocalID", mCurrentParcel->getLocalID() );
 	msg->sendReliable( region->getHost() );
 }
 
@@ -943,7 +898,7 @@ void LLViewerParcelMgr::sendParcelDwellRequest()
 	msg->addUUID("AgentID", gAgent.getID() );
 	msg->addUUID("SessionID", gAgent.getSessionID());
 	msg->nextBlock("Data");
-	msg->addS32("LocalID", mParcel->getLocalID());
+	msg->addS32("LocalID", mCurrentParcel->getLocalID());
 	msg->addUUID("ParcelID", LLUUID::null);	// filled in on simulator
 	msg->sendReliable( region->getHost() );
 }
@@ -982,8 +937,8 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
 
 	llinfos << "Region " << region->getOriginGlobal() << llendl;
 
-	LLGodForceOwnerData* data = new LLGodForceOwnerData(owner_id, mParcel->getLocalID(), region->getHost());
-	if(mParcel->getAuctionID())
+	LLGodForceOwnerData* data = new LLGodForceOwnerData(owner_id, mCurrentParcel->getLocalID(), region->getHost());
+	if(mCurrentParcel->getAuctionID())
 	{
 		gViewerWindow->alertXml("ForceOwnerAuctionWarning",
 			callback_god_force_owner,
@@ -1033,7 +988,7 @@ void LLViewerParcelMgr::sendParcelGodForceToContent()
 	msg->addUUID("AgentID", gAgent.getID());
 	msg->addUUID("SessionID", gAgent.getSessionID());
 	msg->nextBlock("ParcelData");
-	msg->addS32("LocalID", mParcel->getLocalID());
+	msg->addS32("LocalID", mCurrentParcel->getLocalID());
 	msg->sendReliable(region->getHost());
 }
 
@@ -1061,7 +1016,7 @@ void LLViewerParcelMgr::sendParcelRelease()
 	msg->addUUID("AgentID", gAgent.getID() );
 	msg->addUUID("SessionID", gAgent.getSessionID() );
 	msg->nextBlock("Data");
-	msg->addS32("LocalID", mParcel->getLocalID() );
+	msg->addS32("LocalID", mCurrentParcel->getLocalID() );
 	//msg->addU32("Flags", flags);
 	msg->sendReliable( region->getHost() );
 
@@ -1099,7 +1054,7 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
 	BOOL is_claim,
 	BOOL remove_contribution)
 {
-	if (!mSelected || !mParcel)
+	if (!mSelected || !mCurrentParcel)
 	{
 		gViewerWindow->alertXml("CannotBuyLandNothingSelected");
 		return NULL;
@@ -1144,7 +1099,7 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
 	
 	if (!is_claim)
 	{
-		info->mParcelID = mParcel->getLocalID();
+		info->mParcelID = mCurrentParcel->getLocalID();
 	}
 	else
 	{
@@ -1197,7 +1152,7 @@ void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info)
 
 void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
 {
-	if (!mSelected || !mParcel)
+	if (!mSelected || !mCurrentParcel)
 	{
 		gViewerWindow->alertXml("CannotDeedLandNothingSelected");
 		return;
@@ -1221,7 +1176,7 @@ void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
 	msg->addUUID("SessionID", gAgent.getSessionID() );
 	msg->nextBlock("Data");
 	msg->addUUID("GroupID", group_id );
-	msg->addS32("LocalID", mParcel->getLocalID() );
+	msg->addS32("LocalID", mCurrentParcel->getLocalID() );
 	//msg->addU32("JoinNeighbors", join);
 	msg->sendReliable( region->getHost() );
 }
@@ -1235,7 +1190,7 @@ void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
 void LLViewerParcelMgr::makeLandmarkAtSelection()
 {
 	// Don't create for parcels you don't own
-	if (gAgent.getID() != mParcel->getOwnerID())
+	if (gAgent.getID() != mCurrentParcel->getOwnerID())
 	{
 		return;
 	}
@@ -1271,7 +1226,7 @@ const char* LLViewerParcelMgr::getAgentParcelName() const
 }
 
 
-void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, BOOL want_reply_to_update)
+void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel)
 {
 	if (!parcel) return;
 
@@ -1288,7 +1243,8 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, BOOL want_r
 	msg->addS32Fast(_PREHASH_LocalID, parcel->getLocalID() );
 
 	U32 flags = 0x0;
-	if (want_reply_to_update) flags |= 0x01;
+	// request new properties update from simulator
+	flags |= 0x01;
 	msg->addU32("Flags", flags);
 
 	parcel->packMessage(msg);
@@ -1432,7 +1388,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 	{
 		// ...selected parcels report this sequence id
 		gParcelMgr->mRequestResult = PARCEL_RESULT_SUCCESS;
-		parcel = gParcelMgr->mParcel;
+		parcel = gParcelMgr->mCurrentParcel;
 	}
 	else if (sequence_id == HOVERED_PARCEL_SEQ_ID)
 	{
@@ -1541,11 +1497,11 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 	if (sequence_id == SELECTED_PARCEL_SEQ_ID)
 	{
 		// Update selected counts
-		gParcelMgr->mSelectedSelfCount = self_count;
-		gParcelMgr->mSelectedOtherCount = other_count;
-		gParcelMgr->mSelectedPublicCount = public_count;
+		gParcelMgr->mCurrentParcelSelection->mSelectedSelfCount = self_count;
+		gParcelMgr->mCurrentParcelSelection->mSelectedOtherCount = other_count;
+		gParcelMgr->mCurrentParcelSelection->mSelectedPublicCount = public_count;
 
-		gParcelMgr->mSelectedMultipleOwners =
+		gParcelMgr->mCurrentParcelSelection->mSelectedMultipleOwners =
 							(request_result == PARCEL_RESULT_MULTIPLE);
 
 		// Select the whole parcel
@@ -1565,7 +1521,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 								west_south.mV[VY],
 								east_north.mV[VX],
 								east_north.mV[VY] );
-				gParcelMgr->mWholeParcelSelected = FALSE;
+				gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = FALSE;
 			}
 			else if (0 == local_id)
 			{
@@ -1579,7 +1535,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 								aabb_min.mV[VY],
 								aabb_max.mV[VX],
 								aabb_max.mV[VY] );
-				gParcelMgr->mWholeParcelSelected = TRUE;
+				gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE;
 			}
 			else
 			{
@@ -1599,7 +1555,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 				delete bitmap;
 				bitmap = NULL;
 
-				gParcelMgr->mWholeParcelSelected = TRUE;
+				gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE;
 			}
 
 			// Request access list information for this land
@@ -1944,7 +1900,7 @@ void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void
 	msg->getU32Fast( _PREHASH_Data, _PREHASH_Flags, message_flags);
 	msg->getS32Fast( _PREHASH_Data, _PREHASH_LocalID, parcel_id);
 
-	LLParcel* parcel = gParcelMgr->mParcel;
+	LLParcel* parcel = gParcelMgr->mCurrentParcel;
 	if (!parcel) return;
 
 	if (parcel_id != parcel->getLocalID())
@@ -1986,7 +1942,7 @@ void LLViewerParcelMgr::processParcelDwellReply(LLMessageSystem* msg, void**)
 	F32 dwell;
 	msg->getF32("Data", "Dwell", dwell);
 
-	if (local_id == gParcelMgr->mParcel->getLocalID())
+	if (local_id == gParcelMgr->mCurrentParcel->getLocalID())
 	{
 		gParcelMgr->mSelectedDwell = dwell;
 		gParcelMgr->notifyObservers();
@@ -2010,7 +1966,7 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
 
 	LLMessageSystem* msg = gMessageSystem;
 
-	LLParcel* parcel = mParcel;
+	LLParcel* parcel = mCurrentParcel;
 	if (!parcel) return;
 
 	if (which & AL_ACCESS)
@@ -2131,17 +2087,17 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
 void LLViewerParcelMgr::deedLandToGroup()
 {
 	char group_name[MAX_STRING];		/* Flawfinder: ignore */
-	gCacheName->getGroupName(mParcel->getGroupID(), group_name);
+	gCacheName->getGroupName(mCurrentParcel->getGroupID(), group_name);
 	LLString::format_map_t args;
-	args["[AREA]"] = llformat("%d", mParcel->getArea());
+	args["[AREA]"] = llformat("%d", mCurrentParcel->getArea());
 	args["[GROUP_NAME]"] = group_name;
-	if(mParcel->getContributeWithDeed())
+	if(mCurrentParcel->getContributeWithDeed())
 	{
 		char first_name[DB_FIRST_NAME_BUF_SIZE];		/* Flawfinder: ignore */
 		first_name[0] = '\0';
 		char last_name[DB_FIRST_NAME_BUF_SIZE];		/* Flawfinder: ignore */
 		last_name[0] = '\0';		
-		gCacheName->getName(mParcel->getOwnerID(), first_name, last_name);
+		gCacheName->getName(mCurrentParcel->getOwnerID(), first_name, last_name);
 		args["[FIRST_NAME]"] = first_name;
 		args["[LAST_NAME]"] = last_name;
 		gViewerWindow->alertXml("DeedLandToGroupWithContribution",args, deedAlertCB, NULL);
@@ -2157,7 +2113,7 @@ void LLViewerParcelMgr::deedAlertCB(S32 option, void*)
 {
 	if (option == 0)
 	{
-		LLParcel* parcel = gParcelMgr->getSelectedParcel();
+		LLParcel* parcel = gParcelMgr->getParcelSelection()->getParcel();
 		LLUUID group_id;
 		if(parcel)
 		{
@@ -2188,7 +2144,7 @@ void LLViewerParcelMgr::startReleaseLand()
 		return;
 	}
 
-	if (!isParcelOwnedByAgent(mParcel, GP_LAND_RELEASE)
+	if (!isParcelOwnedByAgent(mCurrentParcel, GP_LAND_RELEASE)
 		&& !(gAgent.canManageEstate()))
 	{
 		gViewerWindow->alertXml("CannotReleaseLandDontOwn");
@@ -2213,7 +2169,7 @@ void LLViewerParcelMgr::startReleaseLand()
 	}
 */
 
-	if (!mWholeParcelSelected)
+	if (!mCurrentParcelSelection->mWholeParcelSelected)
 	{
 		gViewerWindow->alertXml("CannotReleaseLandPartialSelection");
 		return;
@@ -2221,7 +2177,7 @@ void LLViewerParcelMgr::startReleaseLand()
 
 	// Compute claim price
 	LLStringBase<char>::format_map_t args;
-	args["[AREA]"] = llformat("%d",mParcel->getArea());
+	args["[AREA]"] = llformat("%d",mCurrentParcel->getArea());
 	gViewerWindow->alertXml("ReleaseLandWarning", args,
 				releaseAlertCB, this);
 }
@@ -2233,7 +2189,7 @@ bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const
 		return false;
 	}
 	
-	if (mSelected  &&  parcel == mParcel)
+	if (mSelected  &&  parcel == mCurrentParcel)
 	{
 		if (mRequestResult == PARCEL_RESULT_NO_DATA)
 		{
@@ -2273,12 +2229,12 @@ bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const
 
 void LLViewerParcelMgr::startBuyLand(BOOL is_for_group)
 {
-	LLFloaterBuyLand::buyLand(getSelectionRegion(), mParcel, is_for_group == TRUE);
+	LLFloaterBuyLand::buyLand(getSelectionRegion(), mCurrentParcelSelection, is_for_group == TRUE);
 }
 
 void LLViewerParcelMgr::startSellLand()
 {
-	LLFloaterSellLand::sellLand(getSelectionRegion(), mParcel);
+	LLFloaterSellLand::sellLand(getSelectionRegion(), mCurrentParcelSelection);
 }
 
 void LLViewerParcelMgr::startDivideLand()
@@ -2289,7 +2245,7 @@ void LLViewerParcelMgr::startDivideLand()
 		return;
 	}
 
-	if (mWholeParcelSelected)
+	if (mCurrentParcelSelection->mWholeParcelSelected)
 	{
 		gViewerWindow->alertXml("CannotDivideLandPartialSelection");
 		return;
@@ -2341,13 +2297,13 @@ void LLViewerParcelMgr::startJoinLand()
 		return;
 	}
 
-	if (mWholeParcelSelected)
+	if (mCurrentParcelSelection->mWholeParcelSelected)
 	{
 		gViewerWindow->alertXml("CannotJoinLandEntireParcelSelected");
 		return;
 	}
 
-	if (!mSelectedMultipleOwners)
+	if (!mCurrentParcelSelection->mSelectedMultipleOwners)
 	{
 		gViewerWindow->alertXml("CannotJoinLandSelection");
 		return;
@@ -2393,7 +2349,7 @@ void LLViewerParcelMgr::callbackJoinLand(S32 option, void* data)
 
 void LLViewerParcelMgr::startDeedLandToGroup()
 {
-	if (!mSelected || !mParcel)
+	if (!mSelected || !mCurrentParcel)
 	{
 		gViewerWindow->alertXml("CannotDeedLandNothingSelected");
 		return;
@@ -2423,7 +2379,7 @@ void LLViewerParcelMgr::startDeedLandToGroup()
 	if(!gAgent.isGodlike())
 	{
 		if((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
-			&& (mParcel->getOwnerID() != region->getOwner()))
+			&& (mCurrentParcel->getOwnerID() != region->getOwner()))
 		{
 			LLStringBase<char>::format_map_t args;
 			args["[REGION]"] = region->getName();
@@ -2437,7 +2393,7 @@ void LLViewerParcelMgr::startDeedLandToGroup()
 }
 void LLViewerParcelMgr::reclaimParcel()
 {
-	LLParcel* parcel = gParcelMgr->getSelectedParcel();
+	LLParcel* parcel = gParcelMgr->getParcelSelection()->getParcel();
 	LLViewerRegion* regionp = gParcelMgr->getSelectionRegion();
 	if(parcel && parcel->getOwnerID().notNull()
 	   && (parcel->getOwnerID() != gAgent.getID())
@@ -2466,7 +2422,7 @@ void LLViewerParcelMgr::releaseAlertCB(S32 option, void *)
 
 void LLViewerParcelMgr::buyPass()
 {
-	LLParcel* parcel = getSelectedParcel();
+	LLParcel* parcel = getParcelSelection()->getParcel();
 	if (!parcel) return;
 
 	LLViewerRegion* region = getSelectionRegion();
@@ -2560,3 +2516,58 @@ void sanitize_corners(const LLVector3d &corner1,
 	east_north_top.mdV[VZ] = llmax( corner1.mdV[VZ], corner2.mdV[VZ] );
 }
 
+//
+// LLParcelSelection
+//
+LLParcelSelection::LLParcelSelection() : 
+	mParcel(NULL),
+	mSelectedMultipleOwners(FALSE),
+	mWholeParcelSelected(FALSE),
+	mSelectedPublicCount(0),
+	mSelectedSelfCount(0),
+	mSelectedOtherCount(0)
+{
+}
+
+LLParcelSelection::LLParcelSelection(LLParcel* parcel)  : 
+	mParcel(parcel),
+	mSelectedMultipleOwners(FALSE),
+	mWholeParcelSelected(FALSE),
+	mSelectedPublicCount(0),
+	mSelectedSelfCount(0),
+	mSelectedOtherCount(0)
+{
+}
+
+LLParcelSelection::~LLParcelSelection()
+{
+}
+
+BOOL LLParcelSelection::getMultipleOwners() const
+{
+	return mSelectedMultipleOwners;
+}
+
+
+BOOL LLParcelSelection::getWholeParcelSelected() const
+{
+	return mWholeParcelSelected;
+}
+
+
+S32 LLParcelSelection::getClaimableArea() const
+{
+	const S32 UNIT_AREA = S32( PARCEL_GRID_STEP_METERS * PARCEL_GRID_STEP_METERS );
+	return mSelectedPublicCount * UNIT_AREA;
+}
+
+bool LLParcelSelection::hasOthersSelected() const
+{
+	return mSelectedOtherCount != 0;
+}
+
+LLParcelSelection* get_null_parcel_selection()
+{
+	static LLParcelSelectionHandle null_ptr = new LLParcelSelection();
+	return null_ptr;
+}
\ No newline at end of file
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index d9823c82a0fc18c5a0c9620601e695c0598da23a..d7677c70e461f9dda68c5aaad5cb677623952334 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -49,15 +49,56 @@ class LLParcelObserver
 	virtual void changed() = 0;
 };
 
+class LLParcelSelection : public LLRefCount
+{
+	friend class LLViewerParcelMgr;
+
+public:
+	LLParcelSelection(LLParcel* parcel);
+	LLParcelSelection();
+
+	~LLParcelSelection();
+
+	// this can return NULL at any time, as parcel selection
+	// might have been invalidated.
+	LLParcel* getParcel() { return mParcel; }
+
+	// Return the number of grid units that are owned by you within
+	// the selection (computed by server).
+	S32 getSelfCount() const { return mSelectedSelfCount; }
+
+	// Returns area that will actually be claimed in meters squared.
+	S32		getClaimableArea() const;
+	bool	hasOthersSelected() const;
+
+	// Does the selection have multiple land owners in it?
+	BOOL	getMultipleOwners() const;
+
+	// Is the entire parcel selected, or just a part?
+	BOOL	getWholeParcelSelected() const;
+
+protected:
+	void setParcel(LLParcel* parcel) { mParcel = parcel; }
+
+protected:
+
+	LLParcel*	mParcel;
+	BOOL		mSelectedMultipleOwners;
+	BOOL		mWholeParcelSelected;
+	S32			mSelectedSelfCount;
+	S32			mSelectedOtherCount;
+	S32			mSelectedPublicCount;
+};
+
+typedef LLHandle<LLParcelSelection> LLParcelSelectionHandle;
+
 class LLViewerParcelMgr
 {
+
 public:
 	LLViewerParcelMgr();
 	~LLViewerParcelMgr();
 
-	void	destroyGL();
-	void	restoreGL();
-
 	BOOL	selectionEmpty() const;
 	F32		getSelectionWidth() const	{ return F32(mEastNorth.mdV[VX] - mWestSouth.mdV[VX]); }
 	F32		getSelectionHeight() const	{ return F32(mEastNorth.mdV[VY] - mWestSouth.mdV[VY]); }
@@ -68,16 +109,6 @@ class LLViewerParcelMgr
 
 	void	getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean);
 
-	// Does the selection have multiple land owners in it?
-	BOOL	getMultipleOwners() const;
-
-	// Is the entire parcel selected, or just a part?
-	BOOL	getWholeParcelSelected() const;
-
-	// Returns area that will actually be claimed in meters squared.
-	S32		getClaimableArea() const;
-	bool	hasOthersSelected() const;
-
 	// Returns selected area
 	S32 getSelectedArea() const;
 
@@ -96,18 +127,19 @@ class LLViewerParcelMgr
 	void selectCollisionParcel();
 
 	// Select the parcel at a specific point
-	void selectParcelAt(const LLVector3d& pos_global);
+	LLHandle<LLParcelSelection> selectParcelAt(const LLVector3d& pos_global);
 
 	// Take the current rectangle select, and select the parcel contained
 	// within it.
-	void selectParcelInRectangle();
+	LLParcelSelectionHandle selectParcelInRectangle();
 
 	// Select a piece of land
-	void	selectLand(const LLVector3d &corner1, const LLVector3d &corner2, 
+	LLParcelSelectionHandle selectLand(const LLVector3d &corner1, const LLVector3d &corner2, 
 					   BOOL snap_to_parcel);
 
 	// Clear the selection, and stop drawing the highlight.
 	void	deselectLand();
+	void	deselectUnused();
 
 	void addObserver(LLParcelObserver* observer);
 	void removeObserver(LLParcelObserver* observer);
@@ -122,15 +154,23 @@ class LLViewerParcelMgr
 
 	BOOL	canHearSound(const LLVector3d &pos_global) const;
 
-	LLParcel *getSelectedParcel() const;
+	// Returns a reference counted pointer to current parcel selection.  
+	// Selection does not change to reflect new selections made by user
+	// Use this when implementing a task UI that refers to a specific
+	// selection.
+	LLParcelSelectionHandle getParcelSelection() const;
+
+	// Returns a reference counted pointer to current parcel selection.
+	// Pointer tracks whatever the user has currently selected.
+	// Use this when implementing an inspector UI.
+	// http://en.wikipedia.org/wiki/Inspector_window
+	LLParcelSelectionHandle getFloatingParcelSelection() const;
+
+	//LLParcel *getParcelSelection() const;
 	LLParcel *getAgentParcel() const;
 
 	BOOL	inAgentParcel(const LLVector3d &pos_global) const;
 
-	// Return the number of grid units that are owned by you within
-	// the selection (computed by server).
-	S32 getSelfCount() const { return mSelectedSelfCount; }
-
 	// Returns a pointer only when it has valid data.
 	LLParcel*	getHoverParcel() const;
 
@@ -172,7 +212,7 @@ class LLViewerParcelMgr
 	// containing the southwest corner of the selection.
 	// If want_reply_to_update, simulator will send back a ParcelProperties
 	// message.
-	void	sendParcelPropertiesUpdate(LLParcel* parcel, BOOL want_reply_to_update);
+	void	sendParcelPropertiesUpdate(LLParcel* parcel);
 
 	// Takes an Access List flag, like AL_ACCESS or AL_BAN
 	void	sendParcelAccessListUpdate(U32 which);
@@ -265,26 +305,23 @@ class LLViewerParcelMgr
 	//void	finishClaim(BOOL user_to_user_sale, U32 join);
 
 private:
-	BOOL		mSelected;
-	BOOL		mSelectedMultipleOwners;
-	BOOL		mWholeParcelSelected;
-	S32			mSelectedSelfCount;
-	S32			mSelectedOtherCount;
-	S32			mSelectedPublicCount;
+	BOOL						mSelected;
 
-	LLParcel	*mParcel;			// selected parcel info
-	S32			mRequestResult;		// result of last parcel request
-	LLVector3d	mWestSouth;
-	LLVector3d	mEastNorth;
-	F32			mSelectedDwell;
+	LLParcel*					mCurrentParcel;			// selected parcel info
+	LLParcelSelectionHandle		mCurrentParcelSelection;
+	LLParcelSelectionHandle		mFloatingParcelSelection;
+	S32							mRequestResult;		// result of last parcel request
+	LLVector3d					mWestSouth;
+	LLVector3d					mEastNorth;
+	F32							mSelectedDwell;
 
-	LLParcel	*mAgentParcel;		// info for parcel agent is in
-	S32			mAgentParcelSequenceID;	// incrementing counter to suppress out of order updates
+	LLParcel					*mAgentParcel;		// info for parcel agent is in
+	S32							mAgentParcelSequenceID;	// incrementing counter to suppress out of order updates
 
-	LLParcel*	mHoverParcel;
-	S32			mHoverRequestResult;
-	LLVector3d	mHoverWestSouth;
-	LLVector3d	mHoverEastNorth;
+	LLParcel*					mHoverParcel;
+	S32							mHoverRequestResult;
+	LLVector3d					mHoverWestSouth;
+	LLVector3d					mHoverEastNorth;
 
 	LLDynamicArray<LLParcelObserver*> mObservers;
 
@@ -293,30 +330,30 @@ class LLViewerParcelMgr
 	// we can represent edges of the grid.
 	// WEST_MASK = draw west edge
 	// SOUTH_MASK = draw south edge
-	S32			mParcelsPerEdge;
-	U8*			mHighlightSegments;
-	U8*			mAgentParcelOverlay;
+	S32							mParcelsPerEdge;
+	U8*							mHighlightSegments;
+	U8*							mAgentParcelOverlay;
 
 	// Raw data buffer for unpacking parcel overlay chunks
 	// Size = parcels_per_edge * parcels_per_edge / parcel_overlay_chunks
-	static U8* sPackedOverlay;
+	static U8*					sPackedOverlay;
 
 	// Watch for pending collisions with a parcel you can't access.
 	// If it's coming, draw the parcel's boundaries.
-	LLParcel*		mCollisionParcel;
-	U8*				mCollisionSegments;
-	BOOL			mRenderCollision; 
-	BOOL			mRenderSelection;
-	S32				mCollisionBanned;     
-	LLFrameTimer	mCollisionTimer;
-	LLUUID			mBlockedImageID;
-	LLUUID			mPassImageID;
-	LLPointer<LLViewerImage> mBlockedImage;
-	LLPointer<LLViewerImage> mPassImage;
+	LLParcel*					mCollisionParcel;
+	U8*							mCollisionSegments;
+	BOOL						mRenderCollision; 
+	BOOL						mRenderSelection;
+	S32							mCollisionBanned;     
+	LLFrameTimer				mCollisionTimer;
+	LLUUID						mBlockedImageID;
+	LLUUID						mPassImageID;
+	LLPointer<LLViewerImage> 	mBlockedImage;
+	LLPointer<LLViewerImage> 	mPassImage;
 
 	// Media
-	S32 mMediaParcelId;
-	U64 mMediaRegionId;
+	S32 						mMediaParcelId;
+	U64 						mMediaRegionId;
 };
 
 extern LLViewerParcelMgr *gParcelMgr;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 871dfcbdeadfa70ffd7c0fda0853d4eb8fe389b9..10bd3cd1023bee1f469bca17be329fb046a716f4 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -378,7 +378,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask
 	if (gToolMgr)
 	{
 		// Don't let the user move the mouse out of the window until mouse up.
-		if( gToolMgr->getCurrentTool(mask)->clipMouseWhenDown() )
+		if( gToolMgr->getCurrentTool()->clipMouseWhenDown() )
 		{
 			mWindow->setMouseClipping(TRUE);
 		}
@@ -429,7 +429,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask
 
 	if (gToolMgr)
 	{
-		if(gToolMgr->getCurrentTool(mask)->handleMouseDown( x, y, mask ) )
+		if(gToolMgr->getCurrentTool()->handleMouseDown( x, y, mask ) )
 		{
 			// This is necessary to force clicks in the world to cause edit
 			// boxes that might have keyboard focus to relinquish it, and hence
@@ -507,7 +507,7 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK ma
 
 	if (gToolMgr)
 	{
-		if(gToolMgr->getCurrentTool(mask)->handleDoubleClick( x, y, mask ) )
+		if(gToolMgr->getCurrentTool()->handleDoubleClick( x, y, mask ) )
 		{
 			return TRUE;
 		}
@@ -550,7 +550,7 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
 	LLTool *tool = NULL;
 	if (gToolMgr)
 	{
-		tool = gToolMgr->getCurrentTool(mask);
+		tool = gToolMgr->getCurrentTool();
 
 		if( tool->clipMouseWhenDown() )
 		{
@@ -649,7 +649,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK
 	if (gToolMgr)
 	{
 		// Don't let the user move the mouse out of the window until mouse up.
-		if( gToolMgr->getCurrentTool(mask)->clipMouseWhenDown() )
+		if( gToolMgr->getCurrentTool()->clipMouseWhenDown() )
 		{
 			mWindow->setMouseClipping(TRUE);
 		}
@@ -692,7 +692,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK
 
 	if (gToolMgr)
 	{
-		if(gToolMgr->getCurrentTool(mask)->handleRightMouseDown( x, y, mask ) )
+		if(gToolMgr->getCurrentTool()->handleRightMouseDown( x, y, mask ) )
 		{
 			// This is necessary to force clicks in the world to cause edit
 			// boxes that might have keyboard focus to relinquish it, and hence
@@ -750,7 +750,7 @@ BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK m
 	LLTool *tool = NULL;
 	if (gToolMgr)
 	{
-		tool = gToolMgr->getCurrentTool(mask);
+		tool = gToolMgr->getCurrentTool();
 
 		if( tool->clipMouseWhenDown() )
 		{
@@ -1909,7 +1909,7 @@ void LLViewerWindow::draw()
 		if (gToolMgr)
 		{
 			// Draw tool specific overlay on world
-			gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) )->draw();
+			gToolMgr->getCurrentTool()->draw();
 		}
 
 		if( gAgent.cameraMouselook() )
@@ -2097,7 +2097,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
 
 	if (gToolMgr)
 	{
-		if( gToolMgr->getCurrentTool(mask)->handleKey(key, mask) )
+		if( gToolMgr->getCurrentTool()->handleKey(key, mask) )
 		{
 			return TRUE;
 		}
@@ -2457,7 +2457,7 @@ BOOL LLViewerWindow::handlePerFrameHover()
 	LLTool *tool = NULL;
 	if (gToolMgr && gHoverView)
 	{
-		tool = gToolMgr->getCurrentTool(mask);
+		tool = gToolMgr->getCurrentTool();
 
 		if(!handled && tool)
 		{
@@ -2477,8 +2477,8 @@ BOOL LLViewerWindow::handlePerFrameHover()
 		// Suppress the toolbox view if our source tool was the pie tool,
 		// and we've overridden to something else.
 		mSuppressToolbox = 
-			(gToolMgr->getCurrentTool(MASK_NONE) == gToolPie) &&
-			(gToolMgr->getCurrentTool(mask) != gToolPie);
+			(gToolMgr->getBaseTool() == gToolPie) &&
+			(gToolMgr->getCurrentTool() != gToolPie);
 
 	}
 
@@ -2539,8 +2539,8 @@ BOOL LLViewerWindow::handlePerFrameHover()
 			(tool != gToolPie						// not default tool
 			&& tool != gToolGun						// not coming out of mouselook
 			&& !mSuppressToolbox					// not override in third person
-			&& gCurrentToolset != gFaceEditToolset	// not special mode
-			&& gCurrentToolset != gMouselookToolset
+			&& gToolMgr->getCurrentToolset() != gFaceEditToolset	// not special mode
+			&& gToolMgr->getCurrentToolset() != gMouselookToolset
 			&& (!captor || captor->isView())) // not dragging
 			)
 		{
@@ -2653,7 +2653,7 @@ BOOL LLViewerWindow::handlePerFrameHover()
 	mLastMousePoint = mCurrentMousePoint;
 
 	// last ditch force of edit menu to selection manager
-	if (gEditMenuHandler == NULL && gSelectMgr && gSelectMgr->getObjectCount())
+	if (gEditMenuHandler == NULL && gSelectMgr && gSelectMgr->getSelection()->getObjectCount())
 	{
 		gEditMenuHandler = gSelectMgr;
 	}
@@ -2689,15 +2689,15 @@ BOOL LLViewerWindow::handlePerFrameHover()
 		gChatBar->startChat(NULL);
 	}
 
-	// sync land selection with edit and about land dialogs
-	if (gParcelMgr
-		&& !gMenuHolder->hasVisibleMenu()
-		&& !LLFloaterLand::floaterVisible()
-		&& !LLFloaterBuyLand::isOpen()
-		&& !LLPanelLandGeneral::buyPassDialogVisible()
-		&& (!gFloaterTools || !gFloaterTools->getVisible()))
+	// cleanup unused selections
+	if (gParcelMgr)
 	{
-		gParcelMgr->deselectLand();
+		gParcelMgr->deselectUnused();
+	}
+
+	if (gSelectMgr)
+	{
+		gSelectMgr->deselectUnused();
 	}
 
 	return handled;
@@ -2745,6 +2745,7 @@ void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
 void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
 {
 	LLViewerObject* object;
+	LLObjectSelectionHandle selection = gSelectMgr->getSelection();
 
 	if (!for_hud && !for_gl_pick)
 	{
@@ -2760,15 +2761,15 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
 			gParcelMgr->renderParcelCollision();
 		}
 	}
-	else if (( for_hud && gSelectMgr->getSelectType() == SELECT_TYPE_HUD) ||
-			 (!for_hud && gSelectMgr->getSelectType() != SELECT_TYPE_HUD))
+	else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) ||
+			 (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD))
 	{		
 		gSelectMgr->renderSilhouettes(for_hud);
 		
 		stop_glerror();
 
 		// setup HUD render
-		if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD && gSelectMgr->getObjectCount())
+		if (selection->getSelectType() == SELECT_TYPE_HUD && gSelectMgr->getSelection()->getObjectCount())
 		{
 			LLBBox hud_bbox = gAgent.getAvatarObject()->getHUDBBox();
 
@@ -2794,12 +2795,12 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
 			LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
 			glMatrixMode(GL_MODELVIEW);
 			glPushMatrix();
-			if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD)
+			if (selection->getSelectType() == SELECT_TYPE_HUD)
 			{
 				F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
 				glScalef(zoom, zoom, zoom);
 			}
-			for( object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() )
+			for( object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() )
 			{
 				LLDrawable* drawable = object->mDrawable;
 				if (drawable && drawable->isLight())
@@ -2834,7 +2835,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
 		// not be recalculated at this time.  If they are, then group rotations will break.
 
 		// Draw arrows at average center of all selected objects
-		LLTool* tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) );
+		LLTool* tool = gToolMgr->getCurrentTool();
 		if (tool)
 		{
 			if(tool->isAlwaysRendered())
@@ -2843,13 +2844,13 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
 			}
 			else
 			{
-				if( !gSelectMgr->isEmpty() )
+				if( !gSelectMgr->getSelection()->isEmpty() )
 				{
 					BOOL moveable_object_selected = FALSE;
 					BOOL all_selected_objects_move = TRUE;
 					BOOL all_selected_objects_modify = TRUE;
 					BOOL selecting_linked_set = gSavedSettings.getBOOL("SelectLinkedSet");
-					for( object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() )
+					for( object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() )
 					{
 						BOOL this_object_movable = FALSE;
 						if (object->permMove() && (object->permModify() || selecting_linked_set))
@@ -2884,7 +2885,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
 					}
 				}
 			}
-			if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD && gSelectMgr->getObjectCount())
+			if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount())
 			{
 				glMatrixMode(GL_PROJECTION);
 				glPopMatrix();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index b21df05afe189e2c2fb829ed6f2a9f5a9399f47c..193fd4e325880397a417d780cc3c0310a1faa12d 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1925,9 +1925,10 @@ void LLVOAvatar::buildCharacter()
 					{
 						LLMenuItemCallGL* item;
 						item = new LLMenuItemCallGL(attachment->getName(), 
-							&handle_attach_to_avatar, 
-							object_selected_and_point_valid, 
-							attachment);
+							NULL, 
+							object_selected_and_point_valid);
+						item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", mAttachmentPoints.reverseLookup(attachment));
+						
 						gAttachPieMenu->append(item);
 
 						attachment_found = TRUE;
@@ -1979,9 +1980,9 @@ void LLVOAvatar::buildCharacter()
 			{
 				LLMenuItemCallGL* item;
 				item = new LLMenuItemCallGL(attachment->getName(), 
-					&handle_attach_to_avatar, 
-					object_selected_and_point_valid, 
-					attachment);
+					NULL, 
+					object_selected_and_point_valid);
+				item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", mAttachmentPoints.reverseLookup(attachment));
 				gAttachScreenPieMenu->append(item);
 				gDetachScreenPieMenu->append(new LLMenuItemCallGL(attachment->getName(), 
 							&handle_detach_from_avatar, object_attached, attachment));
@@ -1998,8 +1999,11 @@ void LLVOAvatar::buildCharacter()
 				{
 					continue;
 				}
-				gAttachSubMenu->append(new LLMenuItemCallGL(attachment->getName(), 
-					&handle_attach_to_avatar, object_selected_and_point_valid, &attach_label, attachment));
+				LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), 
+					NULL, &object_selected_and_point_valid, &attach_label, NULL);
+				item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", mAttachmentPoints.reverseLookup(attachment));
+				gAttachSubMenu->append(item);
+
 				gDetachSubMenu->append(new LLMenuItemCallGL(attachment->getName(), 
 					&handle_detach_from_avatar, object_attached, &detach_label, attachment));
 				
@@ -2049,8 +2053,10 @@ void LLVOAvatar::buildCharacter()
 
 				LLViewerJointAttachment* attachment = attach_it->second;
 
-				gAttachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), 
-					&handle_attach_to_avatar, object_selected_and_point_valid, attachment));
+				LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), 
+					NULL, object_selected_and_point_valid);
+				gAttachBodyPartPieMenus[group]->append(item);
+				item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", mAttachmentPoints.reverseLookup(attachment));
 				gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), 
 					&handle_detach_from_avatar, object_attached, attachment));
 
@@ -2448,7 +2454,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 			if (attached_object && !attached_object->isDead() && attachment->getValid())
 			{
 				// if selecting any attachments, update all of them as non-damped
-				if (gSelectMgr->getObjectCount() && gSelectMgr->selectionIsAttachment())
+				if (gSelectMgr->getSelection()->getObjectCount() && gSelectMgr->getSelection()->isAttachment())
 				{
 					gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
 				}
@@ -2905,22 +2911,24 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
 
 	if (!mBeam.isNull())
 	{
+		LLObjectSelectionHandle selection = gSelectMgr->getSelection();
+
 		if (gAgent.mPointAt.notNull())
 		{
 			// get point from pointat effect
 			mBeam->setPositionGlobal(gAgent.mPointAt->getPointAtPosGlobal());
 			mBeam->triggerLocal();
 		}
-		else if (gSelectMgr->getFirstRootObject() && 
-				gSelectMgr->getSelectType() != SELECT_TYPE_HUD)
+		else if (selection->getFirstRootObject() && 
+				selection->getSelectType() != SELECT_TYPE_HUD)
 		{
-			LLViewerObject* objectp = gSelectMgr->getFirstRootObject();
+			LLViewerObject* objectp = selection->getFirstRootObject();
 			mBeam->setTargetObject(objectp);
 		}
 		else
 		{
 			mBeam->setTargetObject(NULL);
-			LLTool *tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) );
+			LLTool *tool = gToolMgr->getCurrentTool();
 			if (tool->isEditing())
 			{
 				if (tool->getEditingObject())
@@ -3654,7 +3662,7 @@ BOOL LLVOAvatar::needsRenderBeam()
 	{
 		return FALSE;
 	}
-	LLTool *tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) );
+	LLTool *tool = gToolMgr->getCurrentTool();
 
 	BOOL is_touching_or_grabbing = (tool == gToolGrab && gToolGrab->isEditing());
 	if (gToolGrab->getEditingObject() && 
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 0962d3e479eff0fe0837f40f8f0876e3c4aed95d..445f8c6fbfcaeeb0b1b5ceed7cb256c9db0cddca 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -2299,7 +2299,7 @@ void LLPipeline::stateSort()
 	{
 		LLViewerObject *vobjp;
 		S32             te;
-		gSelectMgr->getFirstTE(&vobjp,&te);
+		gSelectMgr->getSelection()->getFirstTE(&vobjp,&te);
 
 		while (vobjp)
 		{
@@ -2351,7 +2351,7 @@ void LLPipeline::stateSort()
 					}
 				}
 			}
-			gSelectMgr->getNextTE(&vobjp,&te);
+			gSelectMgr->getSelection()->getNextTE(&vobjp,&te);
 		}
 	}
 }