diff --git a/.hgtags b/.hgtags
index 419aae0475a230b1ee43aeaaaeace2ea2cdeb130..f970edf51a1bd2166b5bf332781ba74392cd29f4 100644
--- a/.hgtags
+++ b/.hgtags
@@ -77,5 +77,7 @@ b53a0576eec80614d7767ed72b40ed67aeff27c9 DRTVWR-38_2.5.2-release
 b53a0576eec80614d7767ed72b40ed67aeff27c9 2.5.2-release
 92e58e51776a4f8c29069b1a62ff21454d2085f0 2.6.0-start
 f1827b441e05bf37c68e2c15ebc6d09e9b03f527 2.6.0-start
+f1827b441e05bf37c68e2c15ebc6d09e9b03f527 2.6.0-start
+4e9eec6a347f89b2b3f295beb72f1cf7837dff66 2.6.0-start
 9283d6d1d7eb71dfe4c330e7c9144857e7356bde 2.6.0-beta1
 9283d6d1d7eb71dfe4c330e7c9144857e7356bde DRTVWR-40_2.6.0-beta1
diff --git a/BuildParams b/BuildParams
index 1172fe1c71451326063596d2a4bac75a51ce27ca..3ce41adc3a7945a8ade15b86686d2478344da68c 100644
--- a/BuildParams
+++ b/BuildParams
@@ -69,14 +69,6 @@ viewer-pre-release.build_debug_release_separately = true
 viewer-pre-release.build_viewer_update_version_manager = true
 #viewer-pre-release.release-viewer.jira = DRTVWR-13
 
-# ========================================
-# aimee
-# ========================================
-
-viewer-development-import.build_debug_release_separately = true
-viewer-development-fixes.build_debug_release_separately = true
-viewer-development-tweaks.build_debug_release_separately = true
-
 # =======================================
 # brad
 # ========================================
@@ -164,55 +156,7 @@ media.build_viewer_update_version_manager = false
 # oz
 # ================
 
-oz_viewer-review1_coverity.coverity_product = viewer
-
-oz_viewer-review1.build_Linux = true
-oz_viewer-review1_debug.build_Linux = false
-oz_viewer-review1_coverity.build_Linux = false
-
-oz_viewer-review1.build_Darwin = true
-oz_viewer-review1_debug.build_Darwin = false
-oz_viewer-review1_coverity.build_Darwin = false
-
-oz_viewer-review1.build_CYGWIN = true
-oz_viewer-review1.build_CYGWIN_Debug = false
-oz_viewer-review1.build_CYGWIN_RelWithDebInfo = false
-oz_viewer-review1.build_CYGWIN_Release = true
-oz_viewer-review1_debug.build_CYGWIN_Debug = true
-oz_viewer-review1_debug.build_CYGWIN_RelWithDebInfo = true
-oz_viewer-review1_debug.build_CYGWIN_Release = false
-oz_viewer-review1_coverity.build_coverity = true
-oz_viewer-review1_coverity.build_CYGWIN_Debug = false
-oz_viewer-review1_coverity.build_CYGWIN_RelWithDebInfo = false
-oz_viewer-review1_coverity.build_CYGWIN_Release = false
-
-oz_viewer-review2_coverity.coverity_product = viewer
-
-oz_viewer-review2.build_Linux = true
-oz_viewer-review2_debug.build_Linux = false
-oz_viewer-review2_coverity.build_Linux = false
-
-oz_viewer-review2.build_Darwin = true
-oz_viewer-review2_debug.build_Darwin = false
-oz_viewer-review2_coverity.build_Darwin = false
-
-oz_viewer-review2.build_CYGWIN = true
-oz_viewer-review2.build_CYGWIN_Debug = false
-oz_viewer-review2.build_CYGWIN_RelWithDebInfo = false
-oz_viewer-review2.build_CYGWIN_Release = true
-oz_viewer-review2_debug.build_CYGWIN_Debug = true
-oz_viewer-review2_debug.build_CYGWIN_RelWithDebInfo = true
-oz_viewer-review2_debug.build_CYGWIN_Release = false
-oz_viewer-review2_coverity.build_coverity = true
-oz_viewer-review2_coverity.build_CYGWIN_Debug = false
-oz_viewer-review2_coverity.build_CYGWIN_RelWithDebInfo = false
-oz_viewer-review2_coverity.build_CYGWIN_Release = false
-
-# ========================================
-# tofu
-# ========================================
-
-tofu_viewer-development-staging.email = tofu.linden@lindenlab.com
+oz_viewer-devreview.build_debug_release_separately = true
 
 # ========================================
 # enus
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 4c2a836b4ca9ceddea0046003309d8b825f8f592..560bedd518ef062f96be82462bc3a54563effd62 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -412,6 +412,7 @@ Jonathan Yap
 	STORM-975
 	STORM-990
 	STORM-1020
+	STORM-1064
 Kage Pixel
 	VWR-11
 Ken March
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 7d5afe92dcbfcde6b78616a1e621e6f60062b6d4..117d96ffa699cb693e9b2f5ba3c337d343de3b41 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
 
 const S32 LL_VERSION_MAJOR = 2;
 const S32 LL_VERSION_MINOR = 6;
-const S32 LL_VERSION_PATCH = 0;
+const S32 LL_VERSION_PATCH = 1;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
index 3f81c2b28f963465de8bff98157648ced8fcf6d7..b1c27126d9b6d09410b7b4c3e160e31475c08a98 100644
--- a/indra/llui/lldockcontrol.cpp
+++ b/indra/llui/lldockcontrol.cpp
@@ -1,361 +1,361 @@
-/** 
- * @file lldockcontrol.cpp
- * @brief Creates a panel of a specific kind for a toast
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lldockcontrol.h"
-#include "lldockablefloater.h"
-
-LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
-		const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
-		mDockWidget(dockWidget),
-		mDockableFloater(dockableFloater),
-		mDockTongue(dockTongue),
-		mDockTongueX(0),
-		mDockTongueY(0)
-{
-	mDockAt = dockAt;
-
-	if (dockableFloater->isDocked())
-	{
-		on();
-	}
-	else
-	{
-		off();
-	}
-
-	if (!(get_allowed_rect_callback))
-	{
-		mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1);
-	}
-	else
-	{
-		mGetAllowedRectCallback = get_allowed_rect_callback;
-	}
-
-	if (dockWidget != NULL) 
-	{
-		repositionDockable();
-	}
-
-	if (mDockWidget != NULL)
-	{
-		mDockWidgetVisible = isDockVisible();
-	}
-	else
-	{
-		mDockWidgetVisible = false;
-	}
-}
-
-LLDockControl::~LLDockControl()
-{
-}
-
-void LLDockControl::setDock(LLView* dockWidget)
-{
-	mDockWidget = dockWidget;
-	if (mDockWidget != NULL)
-	{
-		repositionDockable();
-		mDockWidgetVisible = isDockVisible();
-	}
-	else
-	{
-		mDockWidgetVisible = false;
-	}
-}
-
-void LLDockControl::getAllowedRect(LLRect& rect)
-{
-	rect = mDockableFloater->getRootView()->getRect();
-}
-
-void LLDockControl::repositionDockable()
-{
-	LLRect dockRect = mDockWidget->calcScreenRect();
-	LLRect rootRect;
-	mGetAllowedRectCallback(rootRect);
-
-	// recalculate dockable position if dock position changed, dock visibility changed,
-	// root view rect changed or recalculation is forced
-	if (mPrevDockRect != dockRect  || mDockWidgetVisible != isDockVisible()
-			|| mRootRect != rootRect || mRecalculateDocablePosition)
-	{
-		// undock dockable and off() if dock not visible
-		if (!isDockVisible())
-		{
-			mDockableFloater->setDocked(false);
-			// force off() since dockable may not have dockControll at this time
-			off();
-			LLDockableFloater* dockable_floater =
-					dynamic_cast<LLDockableFloater*> (mDockableFloater);
-			if(dockable_floater != NULL)
-			{
-				dockable_floater->onDockHidden();
-			}
-		}
-		else
-		{
-			if(mEnabled)
-			{
-				moveDockable();
-			}
-			LLDockableFloater* dockable_floater =
-					dynamic_cast<LLDockableFloater*> (mDockableFloater);
-			if(dockable_floater != NULL)
-			{
-				dockable_floater->onDockShown();
-			}
-		}
-
-		mPrevDockRect = dockRect;
-		mRootRect = rootRect;
-		mRecalculateDocablePosition = false;
-		mDockWidgetVisible = isDockVisible();
-	}
-}
-
-bool LLDockControl::isDockVisible()
-{
-	bool res = true;
-
-	if (mDockWidget != NULL)
-	{
-		//we should check all hierarchy
-		res = mDockWidget->isInVisibleChain();
-		if (res)
-		{
-			LLRect dockRect = mDockWidget->calcScreenRect();
-
-			switch (mDockAt)
-			{
-			case LEFT: // to keep compiler happy
-				break;
-			case BOTTOM:
-			case TOP:
-			{
-				// check is dock inside parent rect
-				// assume that parent for all dockable flaoters
-				// is the root view
-				LLRect dockParentRect =
-						mDockWidget->getRootView()->calcScreenRect();
-				if (dockRect.mRight <= dockParentRect.mLeft
-						|| dockRect.mLeft >= dockParentRect.mRight)
-				{
-					res = false;
-				}
-				break;
-			}
-			default:
-				break;
-			}
-		}
-	}
-
-	return res;
-}
-
-void LLDockControl::moveDockable()
-{
-	// calculate new dockable position
-	LLRect dockRect = mDockWidget->calcScreenRect();
-	LLRect rootRect;
-	mGetAllowedRectCallback(rootRect);
-
-	bool use_tongue = false;
-	LLDockableFloater* dockable_floater =
-			dynamic_cast<LLDockableFloater*> (mDockableFloater);
-	if (dockable_floater != NULL)
-	{
-		use_tongue = dockable_floater->getUseTongue();
-	}
-
-	LLRect dockableRect = mDockableFloater->calcScreenRect();
-	S32 x = 0;
-	S32 y = 0;
-	LLRect dockParentRect;
-	switch (mDockAt)
-	{
-	case LEFT:
-		x = dockRect.mLeft;
-		y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
-		// check is dockable inside root view rect
-		if (x < rootRect.mLeft)
-		{
-			x = rootRect.mLeft;
-		}
-		if (x + dockableRect.getWidth() > rootRect.mRight)
-		{
-			x = rootRect.mRight - dockableRect.getWidth();
-		}
-		
-		mDockTongueX = x + dockableRect.getWidth()/2 - mDockTongue->getWidth() / 2;
-		
-		mDockTongueY = dockRect.mTop;
-		break;
-
-	case TOP:
-		x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
-		y = dockRect.mTop + dockableRect.getHeight();
-		// unique docking used with dock tongue, so add tongue height to the Y coordinate
-		if (use_tongue)
-		{
-			y += mDockTongue->getHeight();
-
-			if ( y > rootRect.mTop)
-			{
-				y = rootRect.mTop;
-			}
-		}
-
-		// check is dockable inside root view rect
-		if (x < rootRect.mLeft)
-		{
-			x = rootRect.mLeft;
-		}
-		if (x + dockableRect.getWidth() > rootRect.mRight)
-		{
-			x = rootRect.mRight - dockableRect.getWidth();
-		}
-
-
-		// calculate dock tongue position
-		dockParentRect = mDockWidget->getParent()->calcScreenRect();
-		if (dockRect.getCenterX() < dockParentRect.mLeft)
-		{
-			mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
-		}
-		else if (dockRect.getCenterX() > dockParentRect.mRight)
-		{
-			mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
-		}
-		else
-		{
-			mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
-		}
-		mDockTongueY = dockRect.mTop;
-
-		break;
-	case BOTTOM:
-		x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
-		y = dockRect.mBottom;
-		// unique docking used with dock tongue, so add tongue height to the Y coordinate
-		if (use_tongue)
-		{
-			y -= mDockTongue->getHeight();
-		}
-
-		// check is dockable inside root view rect
-		if (x < rootRect.mLeft)
-		{
-			x = rootRect.mLeft;
-		}
-		if (x + dockableRect.getWidth() > rootRect.mRight)
-		{
-			x = rootRect.mRight - dockableRect.getWidth();
-		}
-
-		// calculate dock tongue position
-		dockParentRect = mDockWidget->getParent()->calcScreenRect();
-		if (dockRect.getCenterX() < dockParentRect.mLeft)
-		{
-			mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
-		}
-		else if (dockRect.getCenterX() > dockParentRect.mRight)
-		{
-			mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
-		}
-		else
-		{
-			mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
-		}
-		mDockTongueY = dockRect.mBottom - mDockTongue->getHeight();
-
-		break;
-	}
-
-	S32 max_available_height = rootRect.getHeight() - (rootRect.mBottom -  mDockTongueY) - mDockTongue->getHeight();
-
-	// A floater should be shrunk so it doesn't cover a part of its docking tongue and
-	// there is a space between a dockable floater and a control to which it is docked.
-	if (use_tongue && dockableRect.getHeight() >= max_available_height)
-	{
-		dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), max_available_height);
-		mDockableFloater->reshape(dockableRect.getWidth(), dockableRect.getHeight());
-	}
-	else
-	{
-		// move dockable
-		dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
-				dockableRect.getHeight());
-	}
-	LLRect localDocableParentRect;
-	mDockableFloater->getParent()->screenRectToLocal(dockableRect,
-			&localDocableParentRect);
-	mDockableFloater->setRect(localDocableParentRect);
-
-	mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
-			&mDockTongueX, &mDockTongueY);
-
-}
-
-void LLDockControl::on()
-{
-	 if (isDockVisible())
-	{
-		mEnabled = true;
-		mRecalculateDocablePosition = true;
-	}
-}
-
-void LLDockControl::off()
-{
-	mEnabled = false;
-}
-
-void LLDockControl::forceRecalculatePosition()
-{
-	mRecalculateDocablePosition = true;
-}
-
-void LLDockControl::drawToungue()
-{
-	bool use_tongue = false;
-	LLDockableFloater* dockable_floater =
-			dynamic_cast<LLDockableFloater*> (mDockableFloater);
-	if (dockable_floater != NULL)
-	{
-		use_tongue = dockable_floater->getUseTongue();
-	}
-
-	if (mEnabled && use_tongue)
-	{
-		mDockTongue->draw(mDockTongueX, mDockTongueY);
-	}
-}
-
+/** 
+ * @file lldockcontrol.cpp
+ * @brief Creates a panel of a specific kind for a toast
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lldockcontrol.h"
+#include "lldockablefloater.h"
+
+LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
+		const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
+		mDockWidget(dockWidget),
+		mDockableFloater(dockableFloater),
+		mDockTongue(dockTongue),
+		mDockTongueX(0),
+		mDockTongueY(0)
+{
+	mDockAt = dockAt;
+
+	if (dockableFloater->isDocked())
+	{
+		on();
+	}
+	else
+	{
+		off();
+	}
+
+	if (!(get_allowed_rect_callback))
+	{
+		mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1);
+	}
+	else
+	{
+		mGetAllowedRectCallback = get_allowed_rect_callback;
+	}
+
+	if (dockWidget != NULL) 
+	{
+		repositionDockable();
+	}
+
+	if (mDockWidget != NULL)
+	{
+		mDockWidgetVisible = isDockVisible();
+	}
+	else
+	{
+		mDockWidgetVisible = false;
+	}
+}
+
+LLDockControl::~LLDockControl()
+{
+}
+
+void LLDockControl::setDock(LLView* dockWidget)
+{
+	mDockWidget = dockWidget;
+	if (mDockWidget != NULL)
+	{
+		repositionDockable();
+		mDockWidgetVisible = isDockVisible();
+	}
+	else
+	{
+		mDockWidgetVisible = false;
+	}
+}
+
+void LLDockControl::getAllowedRect(LLRect& rect)
+{
+	rect = mDockableFloater->getRootView()->getRect();
+}
+
+void LLDockControl::repositionDockable()
+{
+	LLRect dockRect = mDockWidget->calcScreenRect();
+	LLRect rootRect;
+	mGetAllowedRectCallback(rootRect);
+
+	// recalculate dockable position if dock position changed, dock visibility changed,
+	// root view rect changed or recalculation is forced
+	if (mPrevDockRect != dockRect  || mDockWidgetVisible != isDockVisible()
+			|| mRootRect != rootRect || mRecalculateDocablePosition)
+	{
+		// undock dockable and off() if dock not visible
+		if (!isDockVisible())
+		{
+			mDockableFloater->setDocked(false);
+			// force off() since dockable may not have dockControll at this time
+			off();
+			LLDockableFloater* dockable_floater =
+					dynamic_cast<LLDockableFloater*> (mDockableFloater);
+			if(dockable_floater != NULL)
+			{
+				dockable_floater->onDockHidden();
+			}
+		}
+		else
+		{
+			if(mEnabled)
+			{
+				moveDockable();
+			}
+			LLDockableFloater* dockable_floater =
+					dynamic_cast<LLDockableFloater*> (mDockableFloater);
+			if(dockable_floater != NULL)
+			{
+				dockable_floater->onDockShown();
+			}
+		}
+
+		mPrevDockRect = dockRect;
+		mRootRect = rootRect;
+		mRecalculateDocablePosition = false;
+		mDockWidgetVisible = isDockVisible();
+	}
+}
+
+bool LLDockControl::isDockVisible()
+{
+	bool res = true;
+
+	if (mDockWidget != NULL)
+	{
+		//we should check all hierarchy
+		res = mDockWidget->isInVisibleChain();
+		if (res)
+		{
+			LLRect dockRect = mDockWidget->calcScreenRect();
+
+			switch (mDockAt)
+			{
+			case LEFT: // to keep compiler happy
+				break;
+			case BOTTOM:
+			case TOP:
+			{
+				// check is dock inside parent rect
+				// assume that parent for all dockable flaoters
+				// is the root view
+				LLRect dockParentRect =
+						mDockWidget->getRootView()->calcScreenRect();
+				if (dockRect.mRight <= dockParentRect.mLeft
+						|| dockRect.mLeft >= dockParentRect.mRight)
+				{
+					res = false;
+				}
+				break;
+			}
+			default:
+				break;
+			}
+		}
+	}
+
+	return res;
+}
+
+void LLDockControl::moveDockable()
+{
+	// calculate new dockable position
+	LLRect dockRect = mDockWidget->calcScreenRect();
+	LLRect rootRect;
+	mGetAllowedRectCallback(rootRect);
+
+	bool use_tongue = false;
+	LLDockableFloater* dockable_floater =
+			dynamic_cast<LLDockableFloater*> (mDockableFloater);
+	if (dockable_floater != NULL)
+	{
+		use_tongue = dockable_floater->getUseTongue();
+	}
+
+	LLRect dockableRect = mDockableFloater->calcScreenRect();
+	S32 x = 0;
+	S32 y = 0;
+	LLRect dockParentRect;
+	switch (mDockAt)
+	{
+	case LEFT:
+		x = dockRect.mLeft;
+		y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
+		// check is dockable inside root view rect
+		if (x < rootRect.mLeft)
+		{
+			x = rootRect.mLeft;
+		}
+		if (x + dockableRect.getWidth() > rootRect.mRight)
+		{
+			x = rootRect.mRight - dockableRect.getWidth();
+		}
+		
+		mDockTongueX = x + dockableRect.getWidth()/2 - mDockTongue->getWidth() / 2;
+		
+		mDockTongueY = dockRect.mTop;
+		break;
+
+	case TOP:
+		x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
+		y = dockRect.mTop + dockableRect.getHeight();
+		// unique docking used with dock tongue, so add tongue height to the Y coordinate
+		if (use_tongue)
+		{
+			y += mDockTongue->getHeight();
+
+			if ( y > rootRect.mTop)
+			{
+				y = rootRect.mTop;
+			}
+		}
+
+		// check is dockable inside root view rect
+		if (x < rootRect.mLeft)
+		{
+			x = rootRect.mLeft;
+		}
+		if (x + dockableRect.getWidth() > rootRect.mRight)
+		{
+			x = rootRect.mRight - dockableRect.getWidth();
+		}
+
+
+		// calculate dock tongue position
+		dockParentRect = mDockWidget->getParent()->calcScreenRect();
+		if (dockRect.getCenterX() < dockParentRect.mLeft)
+		{
+			mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
+		}
+		else if (dockRect.getCenterX() > dockParentRect.mRight)
+		{
+			mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
+		}
+		else
+		{
+			mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
+		}
+		mDockTongueY = dockRect.mTop;
+
+		break;
+	case BOTTOM:
+		x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
+		y = dockRect.mBottom;
+		// unique docking used with dock tongue, so add tongue height to the Y coordinate
+		if (use_tongue)
+		{
+			y -= mDockTongue->getHeight();
+		}
+
+		// check is dockable inside root view rect
+		if (x < rootRect.mLeft)
+		{
+			x = rootRect.mLeft;
+		}
+		if (x + dockableRect.getWidth() > rootRect.mRight)
+		{
+			x = rootRect.mRight - dockableRect.getWidth();
+		}
+
+		// calculate dock tongue position
+		dockParentRect = mDockWidget->getParent()->calcScreenRect();
+		if (dockRect.getCenterX() < dockParentRect.mLeft)
+		{
+			mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
+		}
+		else if (dockRect.getCenterX() > dockParentRect.mRight)
+		{
+			mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
+		}
+		else
+		{
+			mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
+		}
+		mDockTongueY = dockRect.mBottom - mDockTongue->getHeight();
+
+		break;
+	}
+
+	S32 max_available_height = rootRect.getHeight() - (rootRect.mBottom -  mDockTongueY) - mDockTongue->getHeight();
+
+	// A floater should be shrunk so it doesn't cover a part of its docking tongue and
+	// there is a space between a dockable floater and a control to which it is docked.
+	if (use_tongue && dockableRect.getHeight() >= max_available_height)
+	{
+		dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), max_available_height);
+		mDockableFloater->reshape(dockableRect.getWidth(), dockableRect.getHeight());
+	}
+	else
+	{
+		// move dockable
+		dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
+				dockableRect.getHeight());
+	}
+	LLRect localDocableParentRect;
+	mDockableFloater->getParent()->screenRectToLocal(dockableRect,
+			&localDocableParentRect);
+	mDockableFloater->setRect(localDocableParentRect);
+
+	mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
+			&mDockTongueX, &mDockTongueY);
+
+}
+
+void LLDockControl::on()
+{
+	 if (isDockVisible())
+	{
+		mEnabled = true;
+		mRecalculateDocablePosition = true;
+	}
+}
+
+void LLDockControl::off()
+{
+	mEnabled = false;
+}
+
+void LLDockControl::forceRecalculatePosition()
+{
+	mRecalculateDocablePosition = true;
+}
+
+void LLDockControl::drawToungue()
+{
+	bool use_tongue = false;
+	LLDockableFloater* dockable_floater =
+			dynamic_cast<LLDockableFloater*> (mDockableFloater);
+	if (dockable_floater != NULL)
+	{
+		use_tongue = dockable_floater->getUseTongue();
+	}
+
+	if (mEnabled && use_tongue)
+	{
+		mDockTongue->draw(mDockTongueX, mDockTongueY);
+	}
+}
+
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 35e0d9d8906b7df713fd13a8f3da3672493028bd..d19e33ea5537df5dd759c54126b4015999222039 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2869,7 +2869,7 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
 	// close callback 
 	if (p.close_callback.isProvided())
 	{
-		mCloseSignal.connect(initCommitCallback(p.close_callback));
+		setCloseCallback(initCommitCallback(p.close_callback));
 	}
 }
 
@@ -2879,6 +2879,11 @@ boost::signals2::connection LLFloater::setMinimizeCallback( const commit_signal_
 	return mMinimizeSignal->connect(cb); 
 }
 
+boost::signals2::connection LLFloater::setCloseCallback( const commit_signal_t::slot_type& cb )
+{
+	return mCloseSignal.connect(cb);
+}
+
 LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build");
 
 bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node)
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 0e83b80c898bbdcf81bd2e635e9c296ac9d1f430..5b7b020881191258cbf728ef577f4e9128269571 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -144,6 +144,7 @@ friend class LLMultiFloater;
 	bool buildFromFile(const std::string &filename, LLXMLNodePtr output_node = NULL);
 
 	boost::signals2::connection setMinimizeCallback( const commit_signal_t::slot_type& cb );
+	boost::signals2::connection setCloseCallback( const commit_signal_t::slot_type& cb );
 
 	void initFromParams(const LLFloater::Params& p);
 	bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL);
diff --git a/indra/media_plugins/winmmshim/CMakeLists.txt b/indra/media_plugins/winmmshim/CMakeLists.txt
index 3e3a9883109e8a22c03e2f55d62913ea2a272272..bf74f818093d60144e59752d215c6f669ef01ce6 100644
--- a/indra/media_plugins/winmmshim/CMakeLists.txt
+++ b/indra/media_plugins/winmmshim/CMakeLists.txt
@@ -3,12 +3,12 @@
 project(winmm_shim)
 
 ### winmm_shim
-# *HACK - override msvcrt implementation (intialized on 00-Common) to be
-# statically linked for winmm.dll this relies on vc taking the last flag on
-# the command line
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
-set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
-set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
+# *HACK - override msvcrt implementation (intialized on 00-Common) to be
+# statically linked for winmm.dll this relies on vc taking the last flag on
+# the command line
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
+set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
 
 set(winmm_shim_SOURCE_FILES
     forwarding_api.cpp
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 6d61be84ef0973d92ca06fca1a4113fb9b62261f..d0f9cae0782051212f4a0a57a385cbf0583b837b 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1,5137 +1,5137 @@
-	/** 
- * @file llappviewer.cpp
- * @brief The LLAppViewer class definitions
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llappviewer.h"
-
-// Viewer includes
-#include "llversioninfo.h"
-#include "llversionviewer.h"
-#include "llfeaturemanager.h"
-#include "lluictrlfactory.h"
-#include "lltexteditor.h"
-#include "llerrorcontrol.h"
-#include "lleventtimer.h"
-#include "llviewertexturelist.h"
-#include "llgroupmgr.h"
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llagentlanguage.h"
-#include "llagentwearables.h"
-#include "llwindow.h"
-#include "llviewerstats.h"
-#include "llviewerstatsrecorder.h"
-#include "llmd5.h"
-#include "llpumpio.h"
-#include "llmimetypes.h"
-#include "llslurl.h"
-#include "llstartup.h"
-#include "llfocusmgr.h"
-#include "llviewerjoystick.h"
-#include "llallocator.h"
-#include "llares.h" 
-#include "llcurl.h"
-#include "lltexturestats.h"
-#include "lltexturestats.h"
-#include "llviewerwindow.h"
-#include "llviewerdisplay.h"
-#include "llviewermedia.h"
-#include "llviewerparcelmedia.h"
-#include "llviewermediafocus.h"
-#include "llviewermessage.h"
-#include "llviewerobjectlist.h"
-#include "llworldmap.h"
-#include "llmutelist.h"
-#include "llviewerhelp.h"
-#include "lluicolortable.h"
-#include "llurldispatcher.h"
-#include "llurlhistory.h"
-//#include "llfirstuse.h"
-#include "llrender.h"
-#include "llteleporthistory.h"
-#include "lllocationhistory.h"
-#include "llfasttimerview.h"
-#include "llvoicechannel.h"
-#include "llvoavatarself.h"
-#include "llsidetray.h"
-#include "llfeaturemanager.h"
-#include "llurlmatch.h"
-#include "lltextutil.h"
-#include "lllogininstance.h"
-#include "llprogressview.h"
-
-#include "llweb.h"
-#include "llsecondlifeurls.h"
-#include "llupdaterservice.h"
-
-// Linden library includes
-#include "llavatarnamecache.h"
-#include "llimagej2c.h"
-#include "llmemory.h"
-#include "llprimitive.h"
-#include "llurlaction.h"
-#include "llurlentry.h"
-#include "llvfile.h"
-#include "llvfsthread.h"
-#include "llvolumemgr.h"
-#include "llxfermanager.h"
-
-#include "llnotificationmanager.h"
-#include "llnotifications.h"
-#include "llnotificationsutil.h"
-
-// Third party library includes
-#include <boost/bind.hpp>
-
-
-#if LL_WINDOWS
-#	include <share.h> // For _SH_DENYWR in initMarkerFile
-#else
-#   include <sys/file.h> // For initMarkerFile support
-#endif
-
-#include "llapr.h"
-#include "apr_dso.h"
-#include <boost/lexical_cast.hpp>
-
-#include "llviewerkeyboard.h"
-#include "lllfsthread.h"
-#include "llworkerthread.h"
-#include "lltexturecache.h"
-#include "lltexturefetch.h"
-#include "llimageworker.h"
-#include "llevents.h"
-
-// The files below handle dependencies from cleanup.
-#include "llkeyframemotion.h"
-#include "llworldmap.h"
-#include "llhudmanager.h"
-#include "lltoolmgr.h"
-#include "llassetstorage.h"
-#include "llpolymesh.h"
-#include "llcachename.h"
-#include "llaudioengine.h"
-#include "llstreamingaudio.h"
-#include "llviewermenu.h"
-#include "llselectmgr.h"
-#include "lltrans.h"
-#include "lltransutil.h"
-#include "lltracker.h"
-#include "llviewerparcelmgr.h"
-#include "llworldmapview.h"
-#include "llpostprocess.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-
-#include "lldebugview.h"
-#include "llconsole.h"
-#include "llcontainerview.h"
-#include "lltooltip.h"
-
-#include "llsdserialize.h"
-
-#include "llworld.h"
-#include "llhudeffecttrail.h"
-#include "llvectorperfoptions.h"
-#include "llslurl.h"
-#include "llwatchdog.h"
-
-// Included so that constants/settings might be initialized
-// in save_settings_to_globals()
-#include "llbutton.h"
-#include "llstatusbar.h"
-#include "llsurface.h"
-#include "llvosky.h"
-#include "llvotree.h"
-#include "llvoavatar.h"
-#include "llfolderview.h"
-#include "llagentpilot.h"
-#include "llvovolume.h"
-#include "llflexibleobject.h" 
-#include "llvosurfacepatch.h"
-#include "llviewerfloaterreg.h"
-#include "llcommandlineparser.h"
-#include "llfloatermemleak.h"
-#include "llfloaterreg.h"
-#include "llfloatersnapshot.h"
-#include "llfloaterinventory.h"
-
-// includes for idle() idleShutdown()
-#include "llviewercontrol.h"
-#include "lleventnotifier.h"
-#include "llcallbacklist.h"
-#include "pipeline.h"
-#include "llgesturemgr.h"
-#include "llsky.h"
-#include "llvlmanager.h"
-#include "llviewercamera.h"
-#include "lldrawpoolbump.h"
-#include "llvieweraudio.h"
-#include "llimview.h"
-#include "llviewerthrottle.h"
-#include "llparcel.h"
-#include "llavatariconctrl.h"
-#include "llgroupiconctrl.h"
-#include "llviewerassetstats.h"
-
-// Include for security api initialization
-#include "llsecapi.h"
-#include "llmachineid.h"
-
-#include "llmainlooprepeater.h"
-
-// *FIX: These extern globals should be cleaned up.
-// The globals either represent state/config/resource-storage of either 
-// this app, or another 'component' of the viewer. App globals should be 
-// moved into the app class, where as the other globals should be 
-// moved out of here.
-// If a global symbol reference seems valid, it will be included
-// via header files above.
-
-//----------------------------------------------------------------------------
-// llviewernetwork.h
-#include "llviewernetwork.h"
-// define a self-registering event API object
-#include "llappviewerlistener.h"
-
-#if (LL_LINUX || LL_SOLARIS) && LL_GTK
-#include "glib.h"
-#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
-
-#if LL_MSVC
-// disable boost::lexical_cast warning
-#pragma warning (disable:4702)
-#endif
-
-static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
-
-////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
-//
-//----------------------------------------------------------------------------
-// viewer.cpp - these are only used in viewer, should be easily moved.
-
-#if LL_DARWIN
-extern void init_apple_menu(const char* product);
-#endif // LL_DARWIN
-
-extern BOOL gRandomizeFramerate;
-extern BOOL gPeriodicSlowFrame;
-extern BOOL gDebugGL;
-
-////////////////////////////////////////////////////////////
-// All from the last globals push...
-const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user flagged as Away From Keyboard
-
-F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
-F32 gSimFrames;
-
-BOOL gShowObjectUpdates = FALSE;
-BOOL gUseQuickTime = TRUE;
-
-eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
-
-LLSD gDebugInfo;
-
-U32	gFrameCount = 0;
-U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
-LLPumpIO* gServicePump = NULL;
-
-U64 gFrameTime = 0;
-F32 gFrameTimeSeconds = 0.f;
-F32 gFrameIntervalSeconds = 0.f;
-F32 gFPSClamped = 10.f;						// Pretend we start at target rate.
-F32 gFrameDTClamped = 0.f;					// Time between adjacent checks to network for packets
-U64	gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
-U32 gFrameStalls = 0;
-const F64 FRAME_STALL_THRESHOLD = 1.0;
-
-LLTimer gRenderStartTime;
-LLFrameTimer gForegroundTime;
-LLFrameTimer gLoggedInTime;
-LLTimer gLogoutTimer;
-static const F32 LOGOUT_REQUEST_TIME = 6.f;  // this will be cut short by the LogoutReply msg.
-F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
-
-BOOL				gDisconnected = FALSE;
-
-// used to restore texture state after a mode switch
-LLFrameTimer	gRestoreGLTimer;
-BOOL			gRestoreGL = FALSE;
-BOOL				gUseWireframe = FALSE;
-
-// VFS globals - see llappviewer.h
-LLVFS* gStaticVFS = NULL;
-
-LLMemoryInfo gSysMemory;
-U64 gMemoryAllocated = 0; // updated in display_stats() in llviewerdisplay.cpp
-
-std::string gLastVersionChannel;
-
-LLVector3			gWindVec(3.0, 3.0, 0.0);
-LLVector3			gRelativeWindVec(0.0, 0.0, 0.0);
-
-U32		gPacketsIn = 0;
-
-BOOL				gPrintMessagesThisFrame = FALSE;
-
-BOOL gRandomizeFramerate = FALSE;
-BOOL gPeriodicSlowFrame = FALSE;
-
-BOOL gCrashOnStartup = FALSE;
-BOOL gLLErrorActivated = FALSE;
-BOOL gLogoutInProgress = FALSE;
-
-////////////////////////////////////////////////////////////
-// Internal globals... that should be removed.
-static std::string gArgs;
-
-const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
-const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
-const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker");
-const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
-static BOOL gDoDisconnect = FALSE;
-static std::string gLaunchFileOnQuit;
-
-// Used on Win32 for other apps to identify our window (eg, win_setup)
-const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
-
-//----------------------------------------------------------------------------
-
-// List of entries from strings.xml to always replace
-static std::set<std::string> default_trans_args;
-void init_default_trans_args()
-{
-	default_trans_args.insert("SECOND_LIFE"); // World
-	default_trans_args.insert("APP_NAME");
-	default_trans_args.insert("CAPITALIZED_APP_NAME");
-	default_trans_args.insert("SECOND_LIFE_GRID");
-	default_trans_args.insert("SUPPORT_SITE");
-}
-
-//----------------------------------------------------------------------------
-// File scope definitons
-const char *VFS_DATA_FILE_BASE = "data.db2.x.";
-const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
-
-
-struct SettingsFile : public LLInitParam::Block<SettingsFile>
-{
-	Mandatory<std::string>	name;
-	Optional<std::string>	file_name;
-	Optional<bool>			required,
-							persistent;
-	Optional<std::string>	file_name_setting;
-
-	SettingsFile()
-	:	name("name"),
-		file_name("file_name"),
-		required("required", false),
-		persistent("persistent", true),
-		file_name_setting("file_name_setting")
-	{}
-};
-
-struct SettingsGroup : public LLInitParam::Block<SettingsGroup>
-{
-	Mandatory<std::string>	name;
-	Mandatory<S32>			path_index;
-	Multiple<SettingsFile>	files;
-
-	SettingsGroup()
-	:	name("name"),
-		path_index("path_index"),
-		files("file")
-	{}
-};
-
-struct SettingsFiles : public LLInitParam::Block<SettingsFiles>
-{
-	Multiple<SettingsGroup>	groups;
-
-	SettingsFiles()
-	: groups("group")
-	{}
-};
-
-static std::string gWindowTitle;
-
-LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
-
-//----------------------------------------------------------------------------
-// Metrics logging control constants
-//----------------------------------------------------------------------------
-static const F32 METRICS_INTERVAL_DEFAULT = 600.0;
-static const F32 METRICS_INTERVAL_QA = 30.0;
-static F32 app_metrics_interval = METRICS_INTERVAL_DEFAULT;
-static bool app_metrics_qa_mode = false;
-
-void idle_afk_check()
-{
-	// check idle timers
-	if (gSavedSettings.getS32("AFKTimeout") && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getS32("AFKTimeout")))
-	{
-		gAgent.setAFK();
-	}
-}
-
-// A callback set in LLAppViewer::init()
-static void ui_audio_callback(const LLUUID& uuid)
-{
-	if (gAudiop)
-	{
-		gAudiop->triggerSound(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
-	}
-}
-
-bool	create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
-{
-	if(!match || !base || base->getPlainText())
-		return false;
-
-	LLUUID match_id = match->getID();
-
-	LLIconCtrl* icon;
-
-	if(gAgent.isInGroup(match_id, TRUE))
-	{
-		LLGroupIconCtrl::Params icon_params;
-		icon_params.group_id = match_id;
-		icon_params.rect = LLRect(0, 16, 16, 0);
-		icon_params.visible = true;
-		icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
-	}
-	else
-	{
-		LLAvatarIconCtrl::Params icon_params;
-		icon_params.avatar_id = match_id;
-		icon_params.rect = LLRect(0, 16, 16, 0);
-		icon_params.visible = true;
-		icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
-	}
-
-	LLInlineViewSegment::Params params;
-	params.force_newline = false;
-	params.view = icon;
-	params.left_pad = 4;
-	params.right_pad = 4;
-	params.top_pad = -2;
-	params.bottom_pad = 2;
-
-	base->appendWidget(params," ",false);
-	
-	return true;
-}
-
-void request_initial_instant_messages()
-{
-	static BOOL requested = FALSE;
-	if (!requested
-		&& gMessageSystem
-		&& LLMuteList::getInstance()->isLoaded()
-		&& isAgentAvatarValid())
-	{
-		// Auto-accepted inventory items may require the avatar object
-		// to build a correct name.  Likewise, inventory offers from
-		// muted avatars require the mute list to properly mute.
-		LLMessageSystem* msg = gMessageSystem;
-		msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
-		msg->nextBlockFast(_PREHASH_AgentData);
-		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-		gAgent.sendReliableMessage();
-		requested = TRUE;
-	}
-}
-
-// A settings system callback for CrashSubmitBehavior
-bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue)
-{
-	S32 cb = newvalue.asInteger();
-	const S32 NEVER_SUBMIT_REPORT = 2;
-	if(cb == NEVER_SUBMIT_REPORT)
-	{
-		LLAppViewer::instance()->destroyMainloopTimeout();
-	}
-	return true;
-}
-
-// Use these strictly for things that are constructed at startup,
-// or for things that are performance critical.  JC
-static void settings_to_globals()
-{
-	LLBUTTON_H_PAD		= gSavedSettings.getS32("ButtonHPad");
-	BTN_HEIGHT_SMALL	= gSavedSettings.getS32("ButtonHeightSmall");
-	BTN_HEIGHT			= gSavedSettings.getS32("ButtonHeight");
-
-	MENU_BAR_HEIGHT		= gSavedSettings.getS32("MenuBarHeight");
-	MENU_BAR_WIDTH		= gSavedSettings.getS32("MenuBarWidth");
-
-	LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
-	
-	LLImageGL::sGlobalUseAnisotropic	= gSavedSettings.getBOOL("RenderAnisotropic");
-	LLVOVolume::sLODFactor				= gSavedSettings.getF32("RenderVolumeLODFactor");
-	LLVOVolume::sDistanceFactor			= 1.f-LLVOVolume::sLODFactor * 0.1f;
-	LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
-	LLVOTree::sTreeFactor				= gSavedSettings.getF32("RenderTreeLODFactor");
-	LLVOAvatar::sLODFactor				= gSavedSettings.getF32("RenderAvatarLODFactor");
-	LLVOAvatar::sMaxVisible				= (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
-	LLVOAvatar::sVisibleInFirstPerson	= gSavedSettings.getBOOL("FirstPersonAvatarVisible");
-	// clamp auto-open time to some minimum usable value
-	LLFolderView::sAutoOpenTime			= llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
-	LLSelectMgr::sRectSelectInclusive	= gSavedSettings.getBOOL("RectangleSelectInclusive");
-	LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
-	LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
-
-	gAgentPilot.mNumRuns		= gSavedSettings.getS32("StatsNumRuns");
-	gAgentPilot.mQuitAfterRuns	= gSavedSettings.getBOOL("StatsQuitAfterRuns");
-	gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
-
-	gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
-	gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
-	LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
-}
-
-static void settings_modify()
-{
-	LLRenderTarget::sUseFBO				= gSavedSettings.getBOOL("RenderUseFBO");
-	LLVOAvatar::sUseImpostors			= gSavedSettings.getBOOL("RenderUseImpostors");
-	LLVOSurfacePatch::sLODFactor		= gSavedSettings.getF32("RenderTerrainLODFactor");
-	LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
-	gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
-	gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
-	gAuditTexture = gSavedSettings.getBOOL("AuditTexture");
-#if LL_VECTORIZE
-	if (gSysCPU.hasAltivec())
-	{
-		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
-		gSavedSettings.setU32("VectorizeProcessor", 0 );
-	}
-	else
-	if (gSysCPU.hasSSE2())
-	{
-		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
-		gSavedSettings.setU32("VectorizeProcessor", 2 );
-	}
-	else
-	if (gSysCPU.hasSSE())
-	{
-		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
-		gSavedSettings.setU32("VectorizeProcessor", 1 );
-	}
-	else
-	{
-		// Don't bother testing or running if CPU doesn't support it. JC
-		gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
-		gSavedSettings.setBOOL("VectorizeEnable", FALSE );
-		gSavedSettings.setU32("VectorizeProcessor", 0 );
-		gSavedSettings.setBOOL("VectorizeSkin", FALSE);
-	}
-#else
-	// This build target doesn't support SSE, don't test/run.
-	gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
-	gSavedSettings.setBOOL("VectorizeEnable", FALSE );
-	gSavedSettings.setU32("VectorizeProcessor", 0 );
-	gSavedSettings.setBOOL("VectorizeSkin", FALSE);
-
-	// disable fullscreen mode, unsupported
-	gSavedSettings.setBOOL("WindowFullScreen", FALSE);
-#endif
-}
-
-class LLFastTimerLogThread : public LLThread
-{
-public:
-	std::string mFile;
-
-	LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
-	{
-		std::string file_name = test_name + std::string(".slp");
-		mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
-	}
-
-	void run()
-	{
-		std::ofstream os(mFile.c_str());
-		
-		while (!LLAppViewer::instance()->isQuitting())
-		{
-			LLFastTimer::writeLog(os);
-			os.flush();
-			ms_sleep(32);
-		}
-
-		os.close();
-	}
-
-};
-
-//virtual
-bool LLAppViewer::initSLURLHandler()
-{
-	// does nothing unless subclassed
-	return false;
-}
-
-//virtual
-bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
-{
-	// does nothing unless subclassed
-	return false;
-}
-
-//----------------------------------------------------------------------------
-// LLAppViewer definition
-
-// Static members.
-// The single viewer app.
-LLAppViewer* LLAppViewer::sInstance = NULL;
-
-const std::string LLAppViewer::sGlobalSettingsName = "Global"; 
-
-LLTextureCache* LLAppViewer::sTextureCache = NULL; 
-LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; 
-LLTextureFetch* LLAppViewer::sTextureFetch = NULL; 
-
-LLAppViewer::LLAppViewer() : 
-	mMarkerFile(),
-	mLogoutMarkerFile(NULL),
-	mReportedCrash(false),
-	mNumSessions(0),
-	mPurgeCache(false),
-	mPurgeOnExit(false),
-	mSecondInstance(false),
-	mSavedFinalSnapshot(false),
-	mForceGraphicsDetail(false),
-	mQuitRequested(false),
-	mLogoutRequestSent(false),
-	mYieldTime(-1),
-	mMainloopTimeout(NULL),
-	mAgentRegionLastAlive(false),
-	mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
-	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
-	mFastTimerLogThread(NULL),
-	mUpdater(new LLUpdaterService()),
-	mSettingsLocationList(NULL)
-{
-	if(NULL != sInstance)
-	{
-		llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
-	}
-
-	setupErrorHandling();
-	sInstance = this;
-	gLoggedInTime.stop();
-	
-	LLLoginInstance::instance().setUpdaterService(mUpdater.get());
-}
-
-LLAppViewer::~LLAppViewer()
-{
-	delete mSettingsLocationList;
-
-	LLLoginInstance::instance().setUpdaterService(0);
-	
-	destroyMainloopTimeout();
-
-	// If we got to this destructor somehow, the app didn't hang.
-	removeMarkerFile();
-}
-
-bool LLAppViewer::init()
-{
-	//
-	// Start of the application
-	//
-	// IMPORTANT! Do NOT put anything that will write
-	// into the log files during normal startup until AFTER
-	// we run the "program crashed last time" error handler below.
-	//
-	LLFastTimer::reset();
-
-	// Need to do this initialization before we do anything else, since anything
-	// that touches files should really go through the lldir API
-	gDirUtilp->initAppDirs("SecondLife");
-	// set skin search path to default, will be overridden later
-	// this allows simple skinned file lookups to work
-	gDirUtilp->setSkinFolder("default");
-
-	initLogging();
-	
-	//
-	// OK to write stuff to logs now, we've now crash reported if necessary
-	//
-	
-	init_default_trans_args();
-	
-	if (!initConfiguration())
-		return false;
-
-	// write Google Breakpad minidump files to our log directory
-	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
-	logdir += gDirUtilp->getDirDelimiter();
-	setMiniDumpDir(logdir);
-
-	// Although initLogging() is the right place to mess with
-	// setFatalFunction(), we can't query gSavedSettings until after
-	// initConfiguration().
-	S32 rc(gSavedSettings.getS32("QAModeTermCode"));
-	if (rc >= 0)
-	{
-		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use _exit()
-		// rather than exit() because normal cleanup depends too much on
-		// successful startup!
-		LLError::setFatalFunction(boost::bind(_exit, rc));
-	}
-
-    mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
-
-#if LL_RECORD_VIEWER_STATS
-	LLViewerStatsRecorder::initClass();
-#endif
-
-    // *NOTE:Mani - LLCurl::initClass is not thread safe. 
-    // Called before threads are created.
-    LLCurl::initClass();
-    LLMachineID::init();
-	
-	{
-		// Viewer metrics initialization
-		static LLCachedControl<bool> metrics_submode(gSavedSettings,
-													 "QAModeMetrics",
-													 false,
-													 "Enables QA features (logging, faster cycling) for metrics collector");
-
-		if (metrics_submode)
-		{
-			app_metrics_qa_mode = true;
-			app_metrics_interval = METRICS_INTERVAL_QA;
-		}
-		LLViewerAssetStatsFF::init();
-	}
-
-    initThreads();
-    writeSystemInfo();
-
-	// Initialize updater service (now that we have an io pump)
-	initUpdater();
-	if(isQuitting())
-	{
-		// Early out here because updater set the quitting flag.
-		return true;
-	}
-
-	//////////////////////////////////////////////////////////////////////////////
-	//////////////////////////////////////////////////////////////////////////////
-	//////////////////////////////////////////////////////////////////////////////
-	//////////////////////////////////////////////////////////////////////////////
-	// *FIX: The following code isn't grouped into functions yet.
-
-	// Statistics / debug timer initialization
-	init_statistics();
-	
-	//
-	// Various introspection concerning the libs we're using - particularly
-        // the libs involved in getting to a full login screen.
-	//
-	LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
-	LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL;
-
-	// Get the single value from the crash settings file, if it exists
-	std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
-	gCrashSettings.loadFromFile(crash_settings_filename);
-	if(gSavedSettings.getBOOL("IgnoreAllNotifications"))
-	{
-		gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ALWAYS_SEND);
-		gCrashSettings.saveToFile(crash_settings_filename, FALSE);
-	}
-
-	/////////////////////////////////////////////////
-	// OS-specific login dialogs
-	/////////////////////////////////////////////////
-
-	//test_cached_control();
-
-	// track number of times that app has run
-	mNumSessions = gSavedSettings.getS32("NumSessions");
-	mNumSessions++;
-	gSavedSettings.setS32("NumSessions", mNumSessions);
-
-	if (gSavedSettings.getBOOL("VerboseLogs"))
-	{
-		LLError::setPrintLocation(true);
-	}
-	
-	// Widget construction depends on LLUI being initialized
-	LLUI::settings_map_t settings_map;
-	settings_map["config"] = &gSavedSettings;
-	settings_map["ignores"] = &gWarningSettings;
-	settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
-	settings_map["account"] = &gSavedPerAccountSettings;
-
-	LLUI::initClass(settings_map,
-		LLUIImageList::getInstance(),
-		ui_audio_callback,
-		&LLUI::sGLScaleFactor);
-	
-	// Setup paths and LLTrans after LLUI::initClass has been called
-	LLUI::setupPaths();
-	LLTransUtil::parseStrings("strings.xml", default_trans_args);		
-	LLTransUtil::parseLanguageStrings("language_settings.xml");
-	
-	// LLKeyboard relies on LLUI to know what some accelerator keys are called.
-	LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
-
-	LLWeb::initClass();			  // do this after LLUI
-	
-	// Provide the text fields with callbacks for opening Urls
-	LLUrlAction::setOpenURLCallback(&LLWeb::loadURL);
-	LLUrlAction::setOpenURLInternalCallback(&LLWeb::loadURLInternal);
-	LLUrlAction::setOpenURLExternalCallback(&LLWeb::loadURLExternal);
-	LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
-
-	// Let code in llui access the viewer help floater
-	LLUI::sHelpImpl = LLViewerHelp::getInstance();
-
-	// Load translations for tooltips
-	LLFloater::initClass();
-
-	/////////////////////////////////////////////////
-	
-	LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
-	
-	LLViewerFloaterReg::registerFloaters();
-	
-	/////////////////////////////////////////////////
-	//
-	// Load settings files
-	//
-	//
-	LLGroupMgr::parseRoleActions("role_actions.xml");
-
-	LLAgent::parseTeleportMessages("teleport_strings.xml");
-
-	LLViewerJointMesh::updateVectorize();
-
-	// load MIME type -> media impl mappings
-	std::string mime_types_name;
-#if LL_DARWIN
-	mime_types_name = "mime_types_mac.xml";
-#elif LL_LINUX
-	mime_types_name = "mime_types_linux.xml";
-#else
-	mime_types_name = "mime_types.xml";
-#endif
-	LLMIMETypes::parseMIMETypes( mime_types_name ); 
-
-	// Copy settings to globals. *TODO: Remove or move to appropriage class initializers
-	settings_to_globals();
-	// Setup settings listeners
-	settings_setup_listeners();
-	// Modify settings based on system configuration and compile options
-	settings_modify();
-
-	// Find partition serial number (Windows) or hardware serial (Mac)
-	mSerialNumber = generateSerialNumber();
-
-	// do any necessary set-up for accepting incoming SLURLs from apps
-	initSLURLHandler();
-
-	if(false == initHardwareTest())
-	{
-		// Early out from user choice.
-		return false;
-	}
-
-	// Prepare for out-of-memory situations, during which we will crash on
-	// purpose and save a dump.
-#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
-	MemSetErrorHandler(first_mem_error_handler);
-#endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
-
-	// *Note: this is where gViewerStats used to be created.
-
-	//
-	// Initialize the VFS, and gracefully handle initialization errors
-	//
-
-	if (!initCache())
-	{
-		std::ostringstream msg;
-		msg << LLTrans::getString("MBUnableToAccessFile");
-		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
-		return 1;
-	}
-	
-	// Initialize the repeater service.
-	LLMainLoopRepeater::instance().start();
-	
-	//
-	// Initialize the window
-	//
-	gGLActive = TRUE;
-	initWindow();
-
-	// initWindow also initializes the Feature List, so now we can initialize this global.
-	LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
-
-	// call all self-registered classes
-	LLInitClassList::instance().fireCallbacks();
-
-	LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
-		
-	gGLManager.getGLInfo(gDebugInfo);
-	gGLManager.printGLInfoString();
-
-	// Load Default bindings
-	std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
-														gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
-														gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
-
-
-	if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
-	{
-		std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
-															gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
-															gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
-		if (!gViewerKeyboard.loadBindings(key_bindings_file))
-		{
-			LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
-		}
-	}
-
-	// If we don't have the right GL requirements, exit.
-	if (!gGLManager.mHasRequirements && !gNoRender)
-	{	
-		// can't use an alert here since we're exiting and
-		// all hell breaks lose.
-		OSMessageBox(
-			LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"),
-			LLStringUtil::null,
-			OSMB_OK);
-		return 0;
-	}
-
-	// alert the user if they are using unsupported hardware
-	if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
-	{
-		bool unsupported = false;
-		LLSD args;
-		std::string minSpecs;
-		
-		// get cpu data from xml
-		std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount"));
-		S32 minCPU = 0;
-		minCPUString >> minCPU;
-
-		// get RAM data from XML
-		std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount"));
-		U64 minRAM = 0;
-		minRAMString >> minRAM;
-		minRAM = minRAM * 1024 * 1024;
-
-		if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
-		{
-			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
-			minSpecs += "\n";
-			unsupported = true;
-		}
-		if(gSysCPU.getMHz() < minCPU)
-		{
-			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
-			minSpecs += "\n";
-			unsupported = true;
-		}
-		if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
-		{
-			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
-			minSpecs += "\n";
-			unsupported = true;
-		}
-
-		if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
-		{
-			LLNotificationsUtil::add("UnknownGPU");
-		} 
-			
-		if(unsupported)
-		{
-			if(!gSavedSettings.controlExists("WarnUnsupportedHardware") 
-				|| gSavedSettings.getBOOL("WarnUnsupportedHardware"))
-			{
-				args["MINSPECS"] = minSpecs;
-				LLNotificationsUtil::add("UnsupportedHardware", args );
-			}
-
-		}
-	}
-
-
-	// save the graphics card
-	gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
-
-	// Save the current version to the prefs file
-	gSavedSettings.setString("LastRunVersion", 
-							 LLVersionInfo::getChannelAndVersion());
-
-	gSimLastTime = gRenderStartTime.getElapsedTimeF32();
-	gSimFrames = (F32)gFrameCount;
-
-	LLViewerJoystick::getInstance()->init(false);
-
-	try {
-		initializeSecHandler();
-	}
-	catch (LLProtectedDataException ex)
-	{
-	  LLNotificationsUtil::add("CorruptedProtectedDataStore");
-	}
-	LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback);
-
-
-	gGLActive = FALSE;
-	if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
-	{
-		loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort"));
-	}
-	
-	LLViewerMedia::initClass();
-	LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
-
-	//EXT-7013 - On windows for some locale (Japanese) standard 
-	//datetime formatting functions didn't support some parameters such as "weekday".
-	//Names for days and months localized in xml are also useful for Polish locale(STORM-107).
-	std::string language = LLControlGroup::getInstance(sGlobalSettingsName)->getString("Language");
-	if(language == "ja" || language == "pl")
-	{
-		LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
-		LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
-		LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
-		LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
-		LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
-
-		LLStringOps::sAM = LLTrans::getString("dateTimeAM");
-		LLStringOps::sPM = LLTrans::getString("dateTimePM");
-	}
-
-	LLAgentLanguage::init();
-
-
-
-	return true;
-}
-
-static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");
-static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep");
-static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache");
-static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode");
-static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread");
-static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread");
-static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads");
-static LLFastTimer::DeclareTimer FTM_IDLE("Idle");
-static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
-static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares");
-static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service");
-static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback");
-static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot");
-static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update");
-
-bool LLAppViewer::mainLoop()
-{
-	LLMemType mt1(LLMemType::MTYPE_MAIN);
-	mMainloopTimeout = new LLWatchdogTimeout();
-	
-	//-------------------------------------------
-	// Run main loop until time to quit
-	//-------------------------------------------
-
-	// Create IO Pump to use for HTTP Requests.
-	gServicePump = new LLPumpIO(gAPRPoolp);
-	LLHTTPClient::setPump(*gServicePump);
-	LLCurl::setCAFile(gDirUtilp->getCAFile());
-	
-	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
-
-	LLVoiceChannel::initClass();
-	LLVoiceClient::getInstance()->init(gServicePump);
-	LLTimer frameTimer,idleTimer;
-	LLTimer debugTime;
-	LLFrameTimer memCheckTimer;
-	LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
-	joystick->setNeedsReset(true);
-
-    LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
-    // As we do not (yet) send data on the mainloop LLEventPump that varies
-    // with each frame, no need to instantiate a new LLSD event object each
-    // time. Obviously, if that changes, just instantiate the LLSD at the
-    // point of posting.
-    LLSD newFrame;
-
-	const F32 memory_check_interval = 1.0f ; //second
-
-	// Handle messages
-	while (!LLApp::isExiting())
-	{
-		LLFastTimer::nextFrame(); // Should be outside of any timer instances
-
-		//clear call stack records
-		llclearcallstacks;
-
-		//check memory availability information
-		{
-			if(memory_check_interval < memCheckTimer.getElapsedTimeF32())
-			{
-				memCheckTimer.reset() ;
-
-				//update the availability of memory
-				LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
-			}
-			llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ;
-			llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ;
-		}
-
-		try
-		{
-			pingMainloopTimeout("Main:MiscNativeWindowEvents");
-
-			if (gViewerWindow)
-			{
-				LLFastTimer t2(FTM_MESSAGES);
-				gViewerWindow->mWindow->processMiscNativeEvents();
-			}
-		
-			pingMainloopTimeout("Main:GatherInput");
-			
-			if (gViewerWindow)
-			{
-				LLFastTimer t2(FTM_MESSAGES);
-				if (!restoreErrorTrap())
-				{
-					llwarns << " Someone took over my signal/exception handler (post messagehandling)!" << llendl;
-				}
-
-				gViewerWindow->mWindow->gatherInput();
-			}
-
-#if 1 && !LL_RELEASE_FOR_DOWNLOAD
-			// once per second debug info
-			if (debugTime.getElapsedTimeF32() > 1.f)
-			{
-				debugTime.reset();
-			}
-			
-#endif
-			//memory leaking simulation
-			LLFloaterMemLeak* mem_leak_instance =
-				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
-			if(mem_leak_instance)
-			{
-				mem_leak_instance->idle() ;				
-			}			
-
-            // canonical per-frame event
-            mainloop.post(newFrame);
-
-			if (!LLApp::isExiting())
-			{
-				pingMainloopTimeout("Main:JoystickKeyboard");
-				
-				// Scan keyboard for movement keys.  Command keys and typing
-				// are handled by windows callbacks.  Don't do this until we're
-				// done initializing.  JC
-				if (gViewerWindow->mWindow->getVisible() 
-					&& gViewerWindow->getActive()
-					&& !gViewerWindow->mWindow->getMinimized()
-					&& LLStartUp::getStartupState() == STATE_STARTED
-					&& !gViewerWindow->getShowProgress()
-					&& !gFocusMgr.focusLocked())
-				{
-					LLMemType mjk(LLMemType::MTYPE_JOY_KEY);
-					joystick->scanJoystick();
-					gKeyboard->scanKeyboard();
-				}
-
-				// Update state based on messages, user input, object idle.
-				{
-					pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
-					
-					LLFastTimer t3(FTM_IDLE);
-					idle();
-
-					if (gAres != NULL && gAres->isInitialized())
-					{
-						LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP);
-						pingMainloopTimeout("Main:ServicePump");				
-						LLFastTimer t4(FTM_PUMP);
-						{
-							LLFastTimer t(FTM_PUMP_ARES);
-							gAres->process();
-						}
-						{
-							LLFastTimer t(FTM_PUMP_SERVICE);
-							// this pump is necessary to make the login screen show up
-							gServicePump->pump();
-
-							{
-								LLFastTimer t(FTM_SERVICE_CALLBACK);
-								gServicePump->callback();
-							}
-						}
-					}
-					
-					resumeMainloopTimeout();
-				}
- 
-				if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
-				{
-					pauseMainloopTimeout();
-					saveFinalSnapshot();
-					disconnectViewer();
-					resumeMainloopTimeout();
-				}
-
-				// Render scene.
-				if (!LLApp::isExiting())
-				{
-					pingMainloopTimeout("Main:Display");
-					gGLActive = TRUE;
-					display();
-					pingMainloopTimeout("Main:Snapshot");
-					LLFloaterSnapshot::update(); // take snapshots
-					gGLActive = FALSE;
-				}
-
-			}
-
-			pingMainloopTimeout("Main:Sleep");
-			
-			pauseMainloopTimeout();
-
-			// Sleep and run background threads
-			{
-				LLMemType mt_sleep(LLMemType::MTYPE_SLEEP);
-				LLFastTimer t2(FTM_SLEEP);
-				
-				// yield some time to the os based on command line option
-				if(mYieldTime >= 0)
-				{
-					ms_sleep(mYieldTime);
-				}
-
-				// yield cooperatively when not running as foreground window
-				if (   gNoRender
-					   || (gViewerWindow && !gViewerWindow->mWindow->getVisible())
-						|| !gFocusMgr.getAppHasFocus())
-				{
-					// Sleep if we're not rendering, or the window is minimized.
-					S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
-					// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
-					// of equal priority on Windows
-					if (milliseconds_to_sleep > 0)
-					{
-						ms_sleep(milliseconds_to_sleep);
-						// also pause worker threads during this wait period
-						LLAppViewer::getTextureCache()->pause();
-						LLAppViewer::getImageDecodeThread()->pause();
-					}
-				}
-				
-				if (mRandomizeFramerate)
-				{
-					ms_sleep(rand() % 200);
-				}
-
-				if (mPeriodicSlowFrame
-					&& (gFrameCount % 10 == 0))
-				{
-					llinfos << "Periodic slow frame - sleeping 500 ms" << llendl;
-					ms_sleep(500);
-				}
-
-				static const F64 FRAME_SLOW_THRESHOLD = 0.5; //2 frames per seconds				
-				const F64 max_idle_time = llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second
-				idleTimer.reset();
-				bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ;
-				S32 total_work_pending = 0;
-				S32 total_io_pending = 0;				
-				while(!is_slow)//do not unpause threads if the frame rates are very low.
-				{
-					S32 work_pending = 0;
-					S32 io_pending = 0;
-					{
-						LLFastTimer ftm(FTM_TEXTURE_CACHE);
- 						work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
-					}
-					{
-						LLFastTimer ftm(FTM_DECODE);
-	 					work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
-					}
-					{
-						LLFastTimer ftm(FTM_DECODE);
-	 					work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
-					}
-
-					{
-						LLFastTimer ftm(FTM_VFS);
-	 					io_pending += LLVFSThread::updateClass(1);
-					}
-					{
-						LLFastTimer ftm(FTM_LFS);
-	 					io_pending += LLLFSThread::updateClass(1);
-					}
-
-					if (io_pending > 1000)
-					{
-						ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
-					}
-
-					total_work_pending += work_pending ;
-					total_io_pending += io_pending ;
-					
-					if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
-					{
-						break;
-					}
-				}
-
-				if(!total_work_pending) //pause texture fetching threads if nothing to process.
-				{
-					LLAppViewer::getTextureCache()->pause();
-					LLAppViewer::getImageDecodeThread()->pause();
-					LLAppViewer::getTextureFetch()->pause(); 
-				}
-				if(!total_io_pending) //pause file threads if nothing to process.
-				{
-					LLVFSThread::sLocal->pause(); 
-					LLLFSThread::sLocal->pause(); 
-				}									
-
-				if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
-					(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
-				{
-					gFrameStalls++;
-				}
-				frameTimer.reset();
-
-				resumeMainloopTimeout();
-	
-				pingMainloopTimeout("Main:End");
-			}	
-		}
-		catch(std::bad_alloc)
-		{			
-			{
-				llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ;
-				llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ;
-
-				LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
-
-				llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ;
-				llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ;
-			}
-
-			//stop memory leaking simulation
-			LLFloaterMemLeak* mem_leak_instance =
-				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
-			if(mem_leak_instance)
-			{
-				mem_leak_instance->stop() ;				
-				llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
-			}
-			else
-			{
-				//output possible call stacks to log file.
-				LLError::LLCallStacks::print() ;
-
-				llerrs << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
-			}
-		}
-	}
-
-	// Save snapshot for next time, if we made it through initialization
-	if (STATE_STARTED == LLStartUp::getStartupState())
-	{
-		try
-		{
-			saveFinalSnapshot();
-		}
-		catch(std::bad_alloc)
-		{
-			llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
-
-			//stop memory leaking simulation
-			LLFloaterMemLeak* mem_leak_instance =
-				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
-			if(mem_leak_instance)
-			{
-				mem_leak_instance->stop() ;				
-			}	
-		}
-	}
-	
-	delete gServicePump;
-
-	destroyMainloopTimeout();
-
-	llinfos << "Exiting main_loop" << llendflush;
-
-	return true;
-}
-
-void LLAppViewer::flushVFSIO()
-{
-	while (1)
-	{
-		S32 pending = LLVFSThread::updateClass(0);
-		pending += LLLFSThread::updateClass(0);
-		if (!pending)
-		{
-			break;
-		}
-		llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
-		ms_sleep(100);
-	}
-}
-
-bool LLAppViewer::cleanup()
-{
-	// workaround for DEV-35406 crash on shutdown
-	LLEventPumps::instance().reset();
-
-	// remove any old breakpad minidump files from the log directory
-	if (! isError())
-	{
-		std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
-		logdir += gDirUtilp->getDirDelimiter();
-		gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
-	}
-
-	// *TODO - generalize this and move DSO wrangling to a helper class -brad
-	std::set<struct apr_dso_handle_t *>::const_iterator i;
-	for(i = mPlugins.begin(); i != mPlugins.end(); ++i)
-	{
-		int (*ll_plugin_stop_func)(void) = NULL;
-		apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop");
-		ll_plugin_stop_func();
-
-		rv = apr_dso_unload(*i);
-	}
-	mPlugins.clear();
-
-	//flag all elements as needing to be destroyed immediately
-	// to ensure shutdown order
-	LLMortician::setZealous(TRUE);
-
-	LLVoiceClient::getInstance()->terminate();
-	
-	disconnectViewer();
-
-	llinfos << "Viewer disconnected" << llendflush;
-
-	display_cleanup(); 
-
-	release_start_screen(); // just in case
-
-	LLError::logToFixedBuffer(NULL);
-
-	llinfos << "Cleaning Up" << llendflush;
-
-	// Must clean up texture references before viewer window is destroyed.
-	if(LLHUDManager::instanceExists())
-	{
-		LLHUDManager::getInstance()->updateEffects();
-		LLHUDObject::updateAll();
-		LLHUDManager::getInstance()->cleanupEffects();
-		LLHUDObject::cleanupHUDObjects();
-		llinfos << "HUD Objects cleaned up" << llendflush;
-	}
-
-	LLKeyframeDataCache::clear();
-	
- 	// End TransferManager before deleting systems it depends on (Audio, VFS, AssetStorage)
-#if 0 // this seems to get us stuck in an infinite loop...
-	gTransferManager.cleanup();
-#endif
-	
-	// Note: this is where gWorldMap used to be deleted.
-
-	// Note: this is where gHUDManager used to be deleted.
-	if(LLHUDManager::instanceExists())
-	{
-		LLHUDManager::getInstance()->shutdownClass();
-	}
-
-	delete gAssetStorage;
-	gAssetStorage = NULL;
-
-	LLPolyMesh::freeAllMeshes();
-
-	LLStartUp::cleanupNameCache();
-
-	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
-
-	LLWorldMap::getInstance()->reset(); // release any images
-	
-	llinfos << "Global stuff deleted" << llendflush;
-
-	if (gAudiop)
-	{
-		// shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
-
-		LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
-		delete sai;
-		gAudiop->setStreamingAudioImpl(NULL);
-
-		// shut down the audio subsystem
-
-		bool want_longname = false;
-		if (gAudiop->getDriverName(want_longname) == "FMOD")
-		{
-			// This hack exists because fmod likes to occasionally
-			// crash or hang forever when shutting down, for no
-			// apparent reason.
-			llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush;
-		}
-		else
-		{
-			gAudiop->shutdown();
-		}
-
-		delete gAudiop;
-		gAudiop = NULL;
-	}
-
-	// Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
-
-	// Patch up settings for next time
-	// Must do this before we delete the viewer window,
-	// such that we can suck rectangle information out of
-	// it.
-	cleanupSavedSettings();
-	llinfos << "Settings patched up" << llendflush;
-
-	// delete some of the files left around in the cache.
-	removeCacheFiles("*.wav");
-	removeCacheFiles("*.tmp");
-	removeCacheFiles("*.lso");
-	removeCacheFiles("*.out");
-	removeCacheFiles("*.dsf");
-	removeCacheFiles("*.bodypart");
-	removeCacheFiles("*.clothing");
-
-	llinfos << "Cache files removed" << llendflush;
-
-	// Wait for any pending VFS IO
-	flushVFSIO();
-	llinfos << "Shutting down Views" << llendflush;
-
-	// Destroy the UI
-	if( gViewerWindow)
-		gViewerWindow->shutdownViews();
-
-	llinfos << "Cleaning up Inventory" << llendflush;
-	
-	// Cleanup Inventory after the UI since it will delete any remaining observers
-	// (Deleted observers should have already removed themselves)
-	gInventory.cleanupInventory();
-
-	llinfos << "Cleaning up Selections" << llendflush;
-	
-	// Clean up selection managers after UI is destroyed, as UI may be observing them.
-	// Clean up before GL is shut down because we might be holding on to objects with texture references
-	LLSelectMgr::cleanupGlobals();
-	
-	llinfos << "Shutting down OpenGL" << llendflush;
-
-	// Shut down OpenGL
-	if( gViewerWindow)
-	{
-		gViewerWindow->shutdownGL();
-	
-		// Destroy window, and make sure we're not fullscreen
-		// This may generate window reshape and activation events.
-		// Therefore must do this before destroying the message system.
-		delete gViewerWindow;
-		gViewerWindow = NULL;
-		llinfos << "ViewerWindow deleted" << llendflush;
-	}
-
-	llinfos << "Cleaning up Keyboard & Joystick" << llendflush;
-	
-	// viewer UI relies on keyboard so keep it aound until viewer UI isa gone
-	delete gKeyboard;
-	gKeyboard = NULL;
-
-	// Turn off Space Navigator and similar devices
-	LLViewerJoystick::getInstance()->terminate();
-	
-	llinfos << "Cleaning up Objects" << llendflush;
-	
-	LLViewerObject::cleanupVOClasses();
-
-	LLWaterParamManager::cleanupClass();
-	LLWLParamManager::cleanupClass();
-	LLPostProcess::cleanupClass();
-
-	LLTracker::cleanupInstance();
-	
-	// *FIX: This is handled in LLAppViewerWin32::cleanup().
-	// I'm keeping the comment to remember its order in cleanup,
-	// in case of unforseen dependency.
-	//#if LL_WINDOWS
-	//	gDXHardware.cleanup();
-	//#endif // LL_WINDOWS
-
-	LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager();
-	if (!volume_manager->cleanup())
-	{
-		llwarns << "Remaining references in the volume manager!" << llendflush;
-	}
-	LLPrimitive::cleanupVolumeManager();
-
-	llinfos << "Additional Cleanup..." << llendflush;	
-	
-	LLViewerParcelMgr::cleanupGlobals();
-
-	// *Note: this is where gViewerStats used to be deleted.
-
- 	//end_messaging_system();
-
-	LLFollowCamMgr::cleanupClass();
-	//LLVolumeMgr::cleanupClass();
-	LLPrimitive::cleanupVolumeManager();
-	LLWorldMapView::cleanupClass();
-	LLFolderViewItem::cleanupClass();
-	LLUI::cleanupClass();
-	
-	//
-	// Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles).
-	// Also after viewerwindow is deleted, since it may have image pointers (which have vfiles)
-	// Also after shutting down the messaging system since it has VFS dependencies
-
-	//
-	llinfos << "Cleaning up VFS" << llendflush;
-	LLVFile::cleanupClass();
-
-	llinfos << "Saving Data" << llendflush;
-	
-	// Store the time of our current logoff
-	gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
-
-	// Must do this after all panels have been deleted because panels that have persistent rects
-	// save their rects on delete.
-	gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
-	
-	LLUIColorTable::instance().saveUserSettings();
-
-	// PerAccountSettingsFile should be empty if no user has been logged on.
-	// *FIX:Mani This should get really saved in a "logoff" mode. 
-	if (gSavedSettings.getString("PerAccountSettingsFile").empty())
-	{
-		llinfos << "Not saving per-account settings; don't know the account name yet." << llendl;
-	}
-	else
-	{
-		gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
-		llinfos << "Saved settings" << llendflush;
-	}
-
-	std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
-	// save all settings, even if equals defaults
-	gCrashSettings.saveToFile(crash_settings_filename, FALSE);
-
-	std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
-	gWarningSettings.saveToFile(warnings_settings_filename, TRUE);
-
-	// Save URL history file
-	LLURLHistory::saveFile("url_history.xml");
-
-	// save mute list. gMuteList used to also be deleted here too.
-	LLMuteList::getInstance()->cache(gAgent.getID());
-
-	if (mPurgeOnExit)
-	{
-		llinfos << "Purging all cache files on exit" << llendflush;
-		std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
-		gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
-	}
-
-	removeMarkerFile(); // Any crashes from here on we'll just have to ignore
-	
-	writeDebugInfo();
-
-	LLLocationHistory::getInstance()->save();
-
-	LLAvatarIconIDCache::getInstance()->save();
-	
-	LLViewerMedia::saveCookieFile();
-
-	// Stop the plugin read thread if it's running.
-	LLPluginProcessParent::setUseReadThread(false);
-
-	llinfos << "Shutting down Threads" << llendflush;
-
-	// Let threads finish
-	LLTimer idleTimer;
-	idleTimer.reset();
-	const F64 max_idle_time = 5.f; // 5 seconds
-	while(1)
-	{
-		S32 pending = 0;
-		pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread
-		pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
-		pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
-		pending += LLVFSThread::updateClass(0);
-		pending += LLLFSThread::updateClass(0);
-		F64 idle_time = idleTimer.getElapsedTimeF64();
-		if(!pending)
-		{
-			break ; //done
-		}
-		else if(idle_time >= max_idle_time)
-		{
-			llwarns << "Quitting with pending background tasks." << llendl;
-			break;
-		}
-	}
-
-	// Delete workers first
-	// shotdown all worker threads before deleting them in case of co-dependencies
-	sTextureFetch->shutdown();
-	sTextureCache->shutdown();	
-	sImageDecodeThread->shutdown();
-	
-	sTextureFetch->shutDownTextureCacheThread() ;
-	sTextureFetch->shutDownImageDecodeThread() ;
-
-	delete sTextureCache;
-    sTextureCache = NULL;
-	delete sTextureFetch;
-    sTextureFetch = NULL;
-	delete sImageDecodeThread;
-    sImageDecodeThread = NULL;
-	delete mFastTimerLogThread;
-	mFastTimerLogThread = NULL;
-	
-	if (LLFastTimerView::sAnalyzePerformance)
-	{
-		llinfos << "Analyzing performance" << llendl;
-		
-		std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
-		std::string current_name  = LLFastTimer::sLogName + ".slp"; 
-		std::string report_name   = LLFastTimer::sLogName + "_report.csv";
-
-		LLFastTimerView::doAnalysis(
-			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
-			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
-			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
-	}
-	LLMetricPerformanceTesterBasic::cleanClass() ;
-
-#if LL_RECORD_VIEWER_STATS
-	LLViewerStatsRecorder::cleanupClass();
-#endif
-
-	llinfos << "Cleaning up Media and Textures" << llendflush;
-
-	//Note:
-	//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
-	//because some new image might be generated during cleaning up media. --bao
-	LLViewerMedia::cleanupClass();
-	LLViewerParcelMedia::cleanupClass();
-	gTextureList.shutdown(); // shutdown again in case a callback added something
-	LLUIImageList::getInstance()->cleanUp();
-	
-	// This should eventually be done in LLAppViewer
-	LLImage::cleanupClass();
-	LLVFSThread::cleanupClass();
-	LLLFSThread::cleanupClass();
-
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-	llinfos << "Auditing VFS" << llendl;
-	if(gVFS)
-	{
-		gVFS->audit();
-	}
-#endif
-
-	llinfos << "Misc Cleanup" << llendflush;
-	
-	// For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up.
-	// (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve
-	delete gStaticVFS;
-	gStaticVFS = NULL;
-	delete gVFS;
-	gVFS = NULL;
-	
-	gSavedSettings.cleanup();
-	LLUIColorTable::instance().clear();
-	gCrashSettings.cleanup();
-
-	LLWatchdog::getInstance()->cleanup();
-
-	LLViewerAssetStatsFF::cleanup();
-	
-	llinfos << "Shutting down message system" << llendflush;
-	end_messaging_system();
-
-	// *NOTE:Mani - The following call is not thread safe. 
-	LLCurl::cleanupClass();
-
-	// If we're exiting to launch an URL, do that here so the screen
-	// is at the right resolution before we launch IE.
-	if (!gLaunchFileOnQuit.empty())
-	{
-		llinfos << "Launch file on quit." << llendflush;
-#if LL_WINDOWS
-		// Indicate an application is starting.
-		SetCursor(LoadCursor(NULL, IDC_WAIT));
-#endif
-
-		// HACK: Attempt to wait until the screen res. switch is complete.
-		ms_sleep(1000);
-
-		LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
-		llinfos << "File launched." << llendflush;
-	}
-
-	LLMainLoopRepeater::instance().stop();
-
-	ll_close_fail_log();
-
-	MEM_TRACK_RELEASE
-
-    llinfos << "Goodbye!" << llendflush;
-
-	// return 0;
-	return true;
-}
-
-// A callback for llerrs to call during the watchdog error.
-void watchdog_llerrs_callback(const std::string &error_string)
-{
-	gLLErrorActivated = true;
-
-#ifdef LL_WINDOWS
-	RaiseException(0,0,0,0);
-#else
-	raise(SIGQUIT);
-#endif
-}
-
-// A callback for the watchdog to call.
-void watchdog_killer_callback()
-{
-	LLError::setFatalFunction(watchdog_llerrs_callback);
-	llerrs << "Watchdog killer event" << llendl;
-}
-
-bool LLAppViewer::initThreads()
-{
-#if MEM_TRACK_MEM
-	static const bool enable_threads = false;
-#else
-	static const bool enable_threads = true;
-#endif
-
-	LLVFSThread::initClass(enable_threads && false);
-	LLLFSThread::initClass(enable_threads && false);
-
-	// Image decoding
-	LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
-	LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
-	LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(),
-													sImageDecodeThread,
-													enable_threads && true,
-													app_metrics_qa_mode);
-	LLImage::initClass();
-
-	if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
-	{
-		LLFastTimer::sLogLock = new LLMutex(NULL);
-		mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName);
-		mFastTimerLogThread->start();
-	}
-
-	// *FIX: no error handling here!
-	return true;
-}
-
-void errorCallback(const std::string &error_string)
-{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-	OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
-#endif
-
-	//Set the ErrorActivated global so we know to create a marker file
-	gLLErrorActivated = true;
-	
-	LLError::crashAndLoop(error_string);
-}
-
-bool LLAppViewer::initLogging()
-{
-	//
-	// Set up logging defaults for the viewer
-	//
-	LLError::initForApplication(
-				gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
-	LLError::setFatalFunction(errorCallback);
-
-	// Remove the last ".old" log file.
-	std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
-							     "SecondLife.old");
-	LLFile::remove(old_log_file);
-
-	// Rename current log file to ".old"
-	std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
-							     "SecondLife.log");
-	LLFile::rename(log_file, old_log_file);
-
-	// Set the log file to SecondLife.log
-
-	LLError::logToFile(log_file);
-
-	// *FIX:Mani no error handling here!
-	return true;
-}
-
-bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
-					    bool set_defaults)
-{	
-	if (!mSettingsLocationList)
-	{
-		llerrs << "Invalid settings location list" << llendl;
-	}
-
-	LLControlGroup* global_settings = LLControlGroup::getInstance(sGlobalSettingsName);  
-	for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
-		it != end_it;
-		++it)
-	{
-		// skip settings groups that aren't the one we requested
-		if (it->name() != location_key) continue;
-
-		ELLPath path_index = (ELLPath)it->path_index();
-		if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
-		{
-			llerrs << "Out of range path index in app_settings/settings_files.xml" << llendl;
-			return false;
-		}
-
-		LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
-		for (file_it = it->files.begin(), end_file_it = it->files.end();
-			file_it != end_file_it;
-			++file_it)
-		{
-			llinfos << "Attempting to load settings for the group " << file_it->name()
-			    << " - from location " << location_key << llendl;
-
-			LLControlGroup* settings_group = LLControlGroup::getInstance(file_it->name);
-			if(!settings_group)
-			{
-				llwarns << "No matching settings group for name " << file_it->name() << llendl;
-				continue;
-			}
-
-			std::string full_settings_path;
-
-			if (file_it->file_name_setting.isProvided() 
-				&& global_settings->controlExists(file_it->file_name_setting))
-			{
-				// try to find filename stored in file_name_setting control
-				full_settings_path = global_settings->getString(file_it->file_name_setting);
-				if (!gDirUtilp->fileExists(full_settings_path))
-				{
-					// search in default path
-					full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path);
-				}
-			}
-			else
-			{
-				// by default, use specified file name
-				full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file_it->file_name());
-			}
-
-			if(settings_group->loadFromFile(full_settings_path, set_defaults, file_it->persistent))
-			{	// success!
-				llinfos << "Loaded settings file " << full_settings_path << llendl;
-			}
-			else
-			{	// failed to load
-				if(file_it->required)
-				{
-					llerrs << "Error: Cannot load required settings file from: " << full_settings_path << llendl;
-					return false;
-				}
-				else
-				{
-					// only complain if we actually have a filename at this point
-					if (!full_settings_path.empty())
-					{
-						llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
-					}
-				}
-			}
-		}
-	}
-
-	return true;
-}
-
-std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
-											 const std::string& file)
-{
-	for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
-		it != end_it;
-		++it)
-	{
-		if (it->name() == location_key)
-		{
-			LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
-			for (file_it = it->files.begin(), end_file_it = it->files.end();
-				file_it != end_file_it;
-				++file_it)
-			{
-				if (file_it->name() == file)
-				{
-					return file_it->file_name;
-				}
-			}
-		}
-	}
-
-	return std::string();
-}
-
-void LLAppViewer::loadColorSettings()
-{
-	LLUIColorTable::instance().loadFromSettings();
-}
-
-bool LLAppViewer::initConfiguration()
-{	
-	//Load settings files list
-	std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
-	//LLControlGroup settings_control("SettingsFiles");
-	//llinfos << "Loading settings file list " << settings_file_list << llendl;
-	//if (0 == settings_control.loadFromFile(settings_file_list))
-	//{
- //       llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
-	//}
-
-	LLXMLNodePtr root;
-	BOOL success  = LLXMLNode::parseFile(settings_file_list, root, NULL);
-	if (!success)
-	{
-        llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
-	}
-
-	mSettingsLocationList = new SettingsFiles();
-
-	LLXUIParser parser;
-	parser.readXUI(root, *mSettingsLocationList, settings_file_list);
-
-	if (!mSettingsLocationList->validateBlock())
-	{
-        llerrs << "Invalid settings file list " << settings_file_list << llendl;
-	}
-		
-	// The settings and command line parsing have a fragile
-	// order-of-operation:
-	// - load defaults from app_settings
-	// - set procedural settings values
-	// - read command line settings
-	// - selectively apply settings needed to load user settings.
-    // - load overrides from user_settings 
-	// - apply command line settings (to override the overrides)
-	// - load per account settings (happens in llstartup
-	
-	// - load defaults
-	bool set_defaults = true;
-	if(!loadSettingsFromDirectory("Default", set_defaults))
-	{
-		std::ostringstream msg;
-		msg << "Unable to load default settings file. The installation may be corrupted.";
-		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
-		return false;
-	}
-	
-	LLUI::setupPaths(); // setup paths for LLTrans based on settings files only
-	LLTransUtil::parseStrings("strings.xml", default_trans_args);
-	LLTransUtil::parseLanguageStrings("language_settings.xml");
-	// - set procedural settings
-	// Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet
-	gSavedSettings.setString("ClientSettingsFile", 
-        gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
-
-#ifndef	LL_RELEASE_FOR_DOWNLOAD
-	// provide developer build only overrides for these control variables that are not
-	// persisted to settings.xml
-	LLControlVariable* c = gSavedSettings.getControl("ShowConsoleWindow");
-	if (c)
-	{
-		c->setValue(true, false);
-	}
-	c = gSavedSettings.getControl("AllowMultipleViewers");
-	if (c)
-	{
-		c->setValue(true, false);
-	}
-#endif
-
-#ifndef	LL_RELEASE_FOR_DOWNLOAD
-	gSavedSettings.setBOOL("QAMode", TRUE );
-	gSavedSettings.setS32("WatchdogEnabled", 0);
-#endif
-	
-	gCrashSettings.getControl(CRASH_BEHAVIOR_SETTING)->getSignal()->connect(boost::bind(&handleCrashSubmitBehaviorChanged, _2));	
-
-	// These are warnings that appear on the first experience of that condition.
-	// They are already set in the settings_default.xml file, but still need to be added to LLFirstUse
-	// for disable/reset ability
-//	LLFirstUse::addConfigVariable("FirstBalanceIncrease");
-//	LLFirstUse::addConfigVariable("FirstBalanceDecrease");
-//	LLFirstUse::addConfigVariable("FirstSit");
-//	LLFirstUse::addConfigVariable("FirstMap");
-//	LLFirstUse::addConfigVariable("FirstGoTo");
-//	LLFirstUse::addConfigVariable("FirstBuild");
-//	LLFirstUse::addConfigVariable("FirstLeftClickNoHit");
-//	LLFirstUse::addConfigVariable("FirstTeleport");
-//	LLFirstUse::addConfigVariable("FirstOverrideKeys");
-//	LLFirstUse::addConfigVariable("FirstAttach");
-//	LLFirstUse::addConfigVariable("FirstAppearance");
-//	LLFirstUse::addConfigVariable("FirstInventory");
-//	LLFirstUse::addConfigVariable("FirstSandbox");
-//	LLFirstUse::addConfigVariable("FirstFlexible");
-//	LLFirstUse::addConfigVariable("FirstDebugMenus");
-//	LLFirstUse::addConfigVariable("FirstSculptedPrim");
-//	LLFirstUse::addConfigVariable("FirstVoice");
-//	LLFirstUse::addConfigVariable("FirstMedia");
-		
-	// - read command line settings.
-	LLControlGroupCLP clp;
-	std::string	cmd_line_config	= gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
-														  "cmd_line.xml");
-
-	clp.configure(cmd_line_config, &gSavedSettings);
-
-	if(!initParseCommandLine(clp))
-	{
-		llwarns	<< "Error parsing command line options.	Command	Line options ignored."  << llendl;
-		
-		llinfos	<< "Command	line usage:\n" << clp << llendl;
-
-		std::ostringstream msg;
-		msg << LLTrans::getString("MBCmdLineError") << clp.getErrorMessage();
-		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
-		return false;
-	}
-	
-	// - selectively apply settings 
-
-	// If the user has specified a alternate settings file name.
-	// Load	it now before loading the user_settings/settings.xml
-	if(clp.hasOption("settings"))
-	{
-		std::string	user_settings_filename = 
-			gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, 
-										   clp.getOption("settings")[0]);		
-		gSavedSettings.setString("ClientSettingsFile", user_settings_filename);
-		llinfos	<< "Using command line specified settings filename: " 
-			<< user_settings_filename << llendl;
-	}
-
-	// - load overrides from user_settings 
-	loadSettingsFromDirectory("User");
-
-	if (gSavedSettings.getBOOL("FirstRunThisInstall"))
-	{
-		gSavedSettings.setString("SessionSettingsFile", "settings_minimal.xml");
-	}
-
-	if (clp.hasOption("sessionsettings"))
-	{
-		std::string session_settings_filename = clp.getOption("sessionsettings")[0];		
-		gSavedSettings.setString("SessionSettingsFile", session_settings_filename);
-		llinfos	<< "Using session settings filename: " 
-			<< session_settings_filename << llendl;
-	}
-	loadSettingsFromDirectory("Session");
-
-	if (clp.hasOption("usersessionsettings"))
-	{
-		std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];		
-		gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename);
-		llinfos	<< "Using user session settings filename: " 
-			<< user_session_settings_filename << llendl;
-
-	}
-	loadSettingsFromDirectory("UserSession");
-
-	// - apply command line settings 
-	clp.notify(); 
-
-	// Register the core crash option as soon as we can
-	// if we want gdb post-mortem on cores we need to be up and running
-	// ASAP or we might miss init issue etc.
-	if(clp.hasOption("disablecrashlogger"))
-	{
-		llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl;
-		LLAppViewer::instance()->disableCrashlogger();
-	}
-
-	// Handle initialization from settings.
-	// Start up the debugging console before handling other options.
-	if (gSavedSettings.getBOOL("ShowConsoleWindow"))
-	{
-		initConsole();
-	}
-
-	if(clp.hasOption("help"))
-	{
-		std::ostringstream msg;
-		msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp;
-		llinfos	<< msg.str() << llendl;
-
-		OSMessageBox(
-			msg.str().c_str(),
-			LLStringUtil::null,
-			OSMB_OK);
-
-		return false;
-	}
-
-    if(clp.hasOption("set"))
-    {
-        const LLCommandLineParser::token_vector_t& set_values = clp.getOption("set");
-        if(0x1 & set_values.size())
-        {
-            llwarns << "Invalid '--set' parameter count." << llendl;
-        }
-        else
-        {
-            LLCommandLineParser::token_vector_t::const_iterator itr = set_values.begin();
-            for(; itr != set_values.end(); ++itr)
-            {
-                const std::string& name = *itr;
-                const std::string& value = *(++itr);
-				LLControlVariable* c = LLControlGroup::getInstance(sGlobalSettingsName)->getControl(name);
-                if(c)
-                {
-                    c->setValue(value, false);
-                }
-                else
-                {
-                    llwarns << "'--set' specified with unknown setting: '"
-                        << name << "'." << llendl;
-                }
-            }
-        }
-    }
-
-    if(clp.hasOption("channel"))
-    {
-		LLVersionInfo::resetChannel(clp.getOption("channel")[0]);
-	}
-	
-
-	// If we have specified crash on startup, set the global so we'll trigger the crash at the right time
-	if(clp.hasOption("crashonstartup"))
-	{
-		gCrashOnStartup = TRUE;
-	}
-
-	if (clp.hasOption("logperformance"))
-	{
-		LLFastTimer::sLog = TRUE;
-		LLFastTimer::sLogName = std::string("performance");
-	}
-	
-	if (clp.hasOption("logmetrics"))
-	{
-		LLFastTimer::sMetricLog = TRUE ;
-		// '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test
-		// In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...)
-		std::string test_name = clp.getOption("logmetrics")[0];
-		llinfos << "'--logmetrics' argument : " << test_name << llendl;
-		if (test_name == "")
-		{
-			llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl;
-			LLFastTimer::sLogName = DEFAULT_METRIC_NAME;
-		}
-		else
-		{
-			LLFastTimer::sLogName = test_name;
-		}
-	}
-
-	if (clp.hasOption("graphicslevel"))
-	{
-		const LLCommandLineParser::token_vector_t& value = clp.getOption("graphicslevel");
-        if(value.size() != 1)
-        {
-			llwarns << "Usage: -graphicslevel <0-3>" << llendl;
-        }
-        else
-        {
-			std::string detail = value.front();
-			mForceGraphicsDetail = TRUE;
-			
-			switch (detail.c_str()[0])
-			{
-				case '0': 
-					gSavedSettings.setU32("RenderQualityPerformance", 0);		
-					break;
-				case '1': 
-					gSavedSettings.setU32("RenderQualityPerformance", 1);		
-					break;
-				case '2': 
-					gSavedSettings.setU32("RenderQualityPerformance", 2);		
-					break;
-				case '3': 
-					gSavedSettings.setU32("RenderQualityPerformance", 3);		
-					break;
-				default:
-					mForceGraphicsDetail = FALSE;
-					llwarns << "Usage: -graphicslevel <0-3>" << llendl;
-					break;
-			}
-        }
-	}
-
-	if (clp.hasOption("analyzeperformance"))
-	{
-		LLFastTimerView::sAnalyzePerformance = TRUE;
-	}
-
-	if (clp.hasOption("replaysession"))
-	{
-		LLAgentPilot::sReplaySession = TRUE;
-	}
-
-	if (clp.hasOption("nonotifications"))
-	{
-		gSavedSettings.getControl("IgnoreAllNotifications")->setValue(true, false);
-	}
-	
-	if (clp.hasOption("debugsession"))
-	{
-		gDebugSession = TRUE;
-		gDebugGL = TRUE;
-
-		ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log"));
-	}
-
-	// Handle slurl use. NOTE: Don't let SL-55321 reappear.
-
-    // *FIX: This init code should be made more robust to prevent 
-    // the issue SL-55321 from returning. One thought is to allow 
-    // only select options to be set from command line when a slurl 
-    // is specified. More work on the settings system is needed to 
-    // achieve this. For now...
-
-    // *NOTE:Mani The command line parser parses tokens and is 
-    // setup to bail after parsing the '--url' option or the 
-    // first option specified without a '--option' flag (or
-    // any other option that uses the 'last_option' setting - 
-    // see LLControlGroupCLP::configure())
-
-    // What can happen is that someone can use IE (or potentially 
-    // other browsers) and do the rough equivalent of command 
-    // injection and steal passwords. Phoenix. SL-55321
-    if(clp.hasOption("url"))
-    {
-		LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0]));
-		if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION) 
-		{  
-			LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid());
-			
-		}  
-    }
-    else if(clp.hasOption("slurl"))
-    {
-		LLSLURL start_slurl(clp.getOption("slurl")[0]);
-		LLStartUp::setStartSLURL(start_slurl);
-    }
-
-    const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
-    if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
-    {   
-		// hack to force the skin to default.
-        gDirUtilp->setSkinFolder(skinfolder->getValue().asString());
-		//gDirUtilp->setSkinFolder("default");
-    }
-
-    mYieldTime = gSavedSettings.getS32("YieldTime");
-
-	// Read skin/branding settings if specified.
-	//if (! gDirUtilp->getSkinDir().empty() )
-	//{
-	//	std::string skin_def_file = gDirUtilp->findSkinnedFilename("skin.xml");
-	//	LLXmlTree skin_def_tree;
-
-	//	if (!skin_def_tree.parseFile(skin_def_file))
-	//	{
-	//		llerrs << "Failed to parse skin definition." << llendl;
-	//	}
-
-	//}
-
-#if LL_DARWIN
-	// Initialize apple menubar and various callbacks
-	init_apple_menu(LLTrans::getString("APP_NAME").c_str());
-
-#if __ppc__
-	// If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further.
-	// Only test PowerPC - all Intel Macs have SSE.
-	if(!gSysCPU.hasAltivec())
-	{
-		std::ostringstream msg;
-		msg << LLTrans::getString("MBRequiresAltiVec");
-		OSMessageBox(
-			msg.str(),
-			LLStringUtil::null,
-			OSMB_OK);
-		removeMarkerFile();
-		return false;
-	}
-#endif
-	
-#endif // LL_DARWIN
-
-	// Display splash screen.  Must be after above check for previous
-	// crash as this dialog is always frontmost.
-	std::string splash_msg;
-	LLStringUtil::format_map_t args;
-	args["[APP_NAME]"] = LLTrans::getString("SECOND_LIFE");
-	splash_msg = LLTrans::getString("StartupLoading", args);
-	LLSplashScreen::show();
-	LLSplashScreen::update(splash_msg);
-
-	//LLVolumeMgr::initClass();
-	LLVolumeMgr* volume_manager = new LLVolumeMgr();
-	volume_manager->useMutex();	// LLApp and LLMutex magic must be manually enabled
-	LLPrimitive::setVolumeManager(volume_manager);
-
-	// Note: this is where we used to initialize gFeatureManagerp.
-
-	gStartTime = totalTime();
-
-	//
-	// Set the name of the window
-	//
-	gWindowTitle = LLTrans::getString("APP_NAME");
-#if LL_DEBUG
-	gWindowTitle += std::string(" [DEBUG] ") + gArgs;
-#else
-	gWindowTitle += std::string(" ") + gArgs;
-#endif
-	LLStringUtil::truncate(gWindowTitle, 255);
-
-	//RN: if we received a URL, hand it off to the existing instance.
-	// don't call anotherInstanceRunning() when doing URL handoff, as
-	// it relies on checking a marker file which will not work when running
-	// out of different directories
-
-	if (LLStartUp::getStartSLURL().isValid())
-	{
-		if (sendURLToOtherInstance(LLStartUp::getStartSLURL().getSLURLString()))
-		{
-			// successfully handed off URL to existing instance, exit
-			return false;
-		}
-	}
-
-	if (!gSavedSettings.getBOOL("AllowMultipleViewers"))
-	{
-	    //
-	    // Check for another instance of the app running
-	    //
-
-		mSecondInstance = anotherInstanceRunning();
-		
-		if (mSecondInstance)
-		{
-			std::ostringstream msg;
-			msg << LLTrans::getString("MBAlreadyRunning");
-			OSMessageBox(
-				msg.str(),
-				LLStringUtil::null,
-				OSMB_OK);
-			return false;
-		}
-
-		initMarkerFile();
-        
-        checkForCrash();
-    }
-	else
-	{
-		mSecondInstance = anotherInstanceRunning();
-		
-		if (mSecondInstance)
-		{
-			// This is the second instance of SL. Turn off voice support,
-			// but make sure the setting is *not* persisted.
-			LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
-			if(disable_voice)
-			{
-				const BOOL DO_NOT_PERSIST = FALSE;
-				disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
-			}
-		}
-
-		initMarkerFile();
-        
-        if(!mSecondInstance)
-        {
-            checkForCrash();
-        }
-	}
-
-   	// need to do this here - need to have initialized global settings first
-	std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
-	if ( !nextLoginLocation.empty() )
-	{
-		LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
-	};
-
-	gLastRunVersion = gSavedSettings.getString("LastRunVersion");
-
-	loadColorSettings();
-
-	return true; // Config was successful.
-}
-
-namespace {
-    // *TODO - decide if there's a better place for these functions.
-    // do we need a file llupdaterui.cpp or something? -brad
-
-	void apply_update_callback(LLSD const & notification, LLSD const & response)
-	{
-		lldebugs << "LLUpdate user response: " << response << llendl;
-		if(response["OK_okcancelbuttons"].asBoolean())
-		{
-			llinfos << "LLUpdate restarting viewer" << llendl;
-			static const bool install_if_ready = true;
-			// *HACK - this lets us launch the installer immediately for now
-			LLUpdaterService().startChecking(install_if_ready);
-		}
-	}
-	
-	void apply_update_ok_callback(LLSD const & notification, LLSD const & response)
-	{
-		llinfos << "LLUpdate restarting viewer" << llendl;
-		static const bool install_if_ready = true;
-		// *HACK - this lets us launch the installer immediately for now
-		LLUpdaterService().startChecking(install_if_ready);
-	}
-	
-	void on_update_downloaded(LLSD const & data)
-	{
-		std::string notification_name;
-		void (*apply_callback)(LLSD const &, LLSD const &) = NULL;
-
-		if(data["required"].asBoolean())
-		{
-			if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT)
-			{
-				// The user never saw the progress bar.
-				apply_callback = &apply_update_ok_callback;
-				notification_name = "RequiredUpdateDownloadedVerboseDialog";
-			}
-			else if(LLStartUp::getStartupState() < STATE_WORLD_INIT)
-			{
-				// The user is logging in but blocked.
-				apply_callback = &apply_update_ok_callback;
-				notification_name = "RequiredUpdateDownloadedDialog";
-			}
-			else
-			{
-				// The user is already logged in; treat like an optional update.
-				apply_callback = &apply_update_callback;
-				notification_name = "DownloadBackgroundTip";
-			}
-		}
-		else
-		{
-			apply_callback = &apply_update_callback;
-			if(LLStartUp::getStartupState() < STATE_STARTED)
-			{
-				// CHOP-262 we need to use a different notification
-				// method prior to login.
-				notification_name = "DownloadBackgroundDialog";
-			}
-			else
-			{
-				notification_name = "DownloadBackgroundTip";
-			}
-		}
-
-		LLSD substitutions;
-		substitutions["VERSION"] = data["version"];
-
-		// truncate version at the rightmost '.' 
-		std::string version_short(data["version"]);
-		size_t short_length = version_short.rfind('.');
-		if (short_length != std::string::npos)
-		{
-			version_short.resize(short_length);
-		}
-
-		LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]");
-		relnotes_url.setArg("[VERSION_SHORT]", version_short);
-
-		// *TODO thread the update service's response through to this point
-		std::string const & channel = LLVersionInfo::getChannel();
-		boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free);
-
-		relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get());
-		relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL"));
-		substitutions["RELEASE_NOTES_FULL_URL"] = relnotes_url.getString();
-
-		LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback);
-	}
-
-	void install_error_callback(LLSD const & notification, LLSD const & response)
-	{
-		LLAppViewer::instance()->forceQuit();
-	}
-	
-    bool notify_update(LLSD const & evt)
-    {
-		std::string notification_name;
-		switch (evt["type"].asInteger())
-		{
-			case LLUpdaterService::DOWNLOAD_COMPLETE:
-				on_update_downloaded(evt);
-				break;
-			case LLUpdaterService::INSTALL_ERROR:
-				if(evt["required"].asBoolean()) {
-					LLNotificationsUtil::add("FailedRequiredUpdateInstall", LLSD(), LLSD(), &install_error_callback);
-				} else {
-					LLNotificationsUtil::add("FailedUpdateInstall");
-				}
-				break;
-			default:
-				break;
-		}
-
-		// let others also handle this event by default
-        return false;
-    }
-	
-	bool on_bandwidth_throttle(LLUpdaterService * updater, LLSD const & evt)
-	{
-		updater->setBandwidthLimit(evt.asInteger() * (1024/8));
-		return false; // Let others receive this event.
-	};
-};
-
-void LLAppViewer::initUpdater()
-{
-	// Initialize the updater service.
-	// Generate URL to the udpater service
-	// Get Channel
-	// Get Version
-	std::string url = gSavedSettings.getString("UpdaterServiceURL");
-	std::string channel = LLVersionInfo::getChannel();
-	std::string version = LLVersionInfo::getVersion();
-	std::string protocol_version = gSavedSettings.getString("UpdaterServiceProtocolVersion");
-	std::string service_path = gSavedSettings.getString("UpdaterServicePath");
-	U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod");
-
-	mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this));
-	mUpdater->initialize(protocol_version, 
-						 url, 
-						 service_path, 
-						 channel, 
-						 version);
- 	mUpdater->setCheckPeriod(check_period);
-	mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8));
-	gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()->
-		connect(boost::bind(&on_bandwidth_throttle, mUpdater.get(), _2));
-	if(gSavedSettings.getU32("UpdaterServiceSetting"))
-	{
-		bool install_if_ready = true;
-		mUpdater->startChecking(install_if_ready);
-	}
-
-    LLEventPump & updater_pump = LLEventPumps::instance().obtain(LLUpdaterService::pumpName());
-    updater_pump.listen("notify_update", &notify_update);
-}
-
-void LLAppViewer::checkForCrash(void)
-{
-    
-#if LL_SEND_CRASH_REPORTS
-	if (gLastExecEvent == LAST_EXEC_FROZE)
-    {
-        llinfos << "Last execution froze, requesting to send crash report." << llendl;
-        //
-        // Pop up a freeze or crash warning dialog
-        //
-        S32 choice;
-        if(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) == CRASH_BEHAVIOR_ASK)
-        {
-            std::ostringstream msg;
-			msg << LLTrans::getString("MBFrozenCrashed");
-			std::string alert = LLTrans::getString("APP_NAME") + " " + LLTrans::getString("MBAlert");
-            choice = OSMessageBox(msg.str(),
-                                  alert,
-                                  OSMB_YESNO);
-        } 
-        else if(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) == CRASH_BEHAVIOR_NEVER_SEND)
-        {
-            choice = OSBTN_NO;
-        }
-        else
-        {
-            choice = OSBTN_YES;
-        }
-
-        if (OSBTN_YES == choice)
-        {
-            llinfos << "Sending crash report." << llendl;
-            
-            bool report_freeze = true;
-            handleCrashReporting(report_freeze);
-        }
-        else
-        {
-            llinfos << "Not sending crash report." << llendl;
-        }
-    }
-#endif // LL_SEND_CRASH_REPORTS    
-    
-}
-
-bool LLAppViewer::initWindow()
-{
-	LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
-
-	// store setting in a global for easy access and modification
-	gNoRender = gSavedSettings.getBOOL("DisableRendering");
-
-	// always start windowed
-	BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
-	gViewerWindow = new LLViewerWindow(gWindowTitle, 
-		VIEWER_WINDOW_CLASSNAME,
-		gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"),
-		gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
-		gSavedSettings.getBOOL("WindowFullScreen"), ignorePixelDepth);
-
-	// Need to load feature table before cheking to start watchdog.
-	const S32 NEVER_SUBMIT_REPORT = 2;
-	bool use_watchdog = false;
-	int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled");
-	if(watchdog_enabled_setting == -1){
-		use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled");
-	}
-	else
-	{
-		// The user has explicitly set this setting; always use that value.
-		use_watchdog = bool(watchdog_enabled_setting);
-	}
-
-	bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT;
-	if(use_watchdog && send_reports)
-	{
-		LLWatchdog::getInstance()->init(watchdog_killer_callback);
-	}
-
-	LLNotificationsUI::LLNotificationManager::getInstance();
-		
-	if (gSavedSettings.getBOOL("WindowMaximized"))
-	{
-		gViewerWindow->mWindow->maximize();
-	}
-
-	if (!gNoRender)
-	{
-		//
-		// Initialize GL stuff
-		//
-
-		if (mForceGraphicsDetail)
-		{
-			LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false);
-		}
-				
-		// Set this flag in case we crash while initializing GL
-		gSavedSettings.setBOOL("RenderInitError", TRUE);
-		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
-	
-		gPipeline.init();
-		stop_glerror();
-		gViewerWindow->initGLDefaults();
-
-		gSavedSettings.setBOOL("RenderInitError", FALSE);
-		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
-	}
-
-	//If we have a startup crash, it's usually near GL initialization, so simulate that.
-	if(gCrashOnStartup)
-	{
-		LLAppViewer::instance()->forceErrorLLError();
-	}
-
-	LLUI::sWindow = gViewerWindow->getWindow();
-
-	// Show watch cursor
-	gViewerWindow->setCursor(UI_CURSOR_WAIT);
-
-	// Finish view initialization
-	gViewerWindow->initBase();
-
-	// show viewer window
-	//gViewerWindow->mWindow->show();
-
-	
-	return true;
-}
-
-void LLAppViewer::writeDebugInfo()
-{
-	std::string debug_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
-	llinfos << "Opening debug file " << debug_filename << llendl;
-	llofstream out_file(debug_filename);
-	LLSDSerialize::toPrettyXML(gDebugInfo, out_file);
-	out_file.close();
-}
-
-void LLAppViewer::cleanupSavedSettings()
-{
-	gSavedSettings.setBOOL("MouseSun", FALSE);
-
-	gSavedSettings.setBOOL("UseEnergy", TRUE);				// force toggle to turn off, since sends message to simulator
-
-	gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
-		
-	gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
-	
-	if (!gNoRender)
-	{
-		if (gDebugView)
-		{
-			gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
-		}
-	}
-
-	// save window position if not maximized
-	// as we don't track it in callbacks
-	if(NULL != gViewerWindow)
-	{
-		BOOL maximized = gViewerWindow->mWindow->getMaximized();
-		if (!maximized)
-		{
-			LLCoordScreen window_pos;
-
-			if (gViewerWindow->mWindow->getPosition(&window_pos))
-			{
-				gSavedSettings.setS32("WindowX", window_pos.mX);
-				gSavedSettings.setS32("WindowY", window_pos.mY);
-			}
-		}
-	}
-
-	gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale );
-
-	// Some things are cached in LLAgent.
-	if (gAgent.isInitialized())
-	{
-		gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance);
-	}
-}
-
-void LLAppViewer::removeCacheFiles(const std::string& file_mask)
-{
-	std::string mask = gDirUtilp->getDirDelimiter() + file_mask;
-	gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask);
-}
-
-void LLAppViewer::writeSystemInfo()
-{
-	gDebugInfo["SLLog"] = LLError::logFileName();
-
-	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
-	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
-	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
-	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
-	gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
-
-	gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
-
-	gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString();
-	gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily();
-	gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz();
-	gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec();
-	gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
-	gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
-	
-	gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB());
-	gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB
-	gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple();
-
-	// The user is not logged on yet, but record the current grid choice login url
-	// which may have been the intended grid. This can b
-	gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();
-
-	// *FIX:Mani - move this down in llappviewerwin32
-#ifdef LL_WINDOWS
-	DWORD thread_id = GetCurrentThreadId();
-	gDebugInfo["MainloopThreadID"] = (S32)thread_id;
-#endif
-
-	// "CrashNotHandled" is set here, while things are running well,
-	// in case of a freeze. If there is a freeze, the crash logger will be launched
-	// and can read this value from the debug_info.log.
-	// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
-	// then the value of "CrashNotHandled" will be set to true.
-	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
-
-	// Insert crash host url (url to post crash log to) if configured. This insures
-	// that the crash report will go to the proper location in the case of a 
-	// prior freeze.
-	std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
-	if(crashHostUrl != "")
-	{
-		gDebugInfo["CrashHostUrl"] = crashHostUrl;
-	}
-	
-	// Dump some debugging info
-	LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME")
-			<< " version " << LLVersionInfo::getShortVersion() << LL_ENDL;
-
-	// Dump the local time and time zone
-	time_t now;
-	time(&now);
-	char tbuffer[256];		/* Flawfinder: ignore */
-	strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now));
-	LL_INFOS("SystemInfo") << "Local time: " << tbuffer << LL_ENDL;
-
-	// query some system information
-	LL_INFOS("SystemInfo") << "CPU info:\n" << gSysCPU << LL_ENDL;
-	LL_INFOS("SystemInfo") << "Memory info:\n" << gSysMemory << LL_ENDL;
-	LL_INFOS("SystemInfo") << "OS: " << getOSInfo().getOSStringSimple() << LL_ENDL;
-	LL_INFOS("SystemInfo") << "OS info: " << getOSInfo() << LL_ENDL;
-
-	writeDebugInfo(); // Save out debug_info.log early, in case of crash.
-}
-
-void LLAppViewer::handleViewerCrash()
-{
-	llinfos << "Handle viewer crash entry." << llendl;
-
-	llinfos << "Last render pool type: " << LLPipeline::sCurRenderPoolType << llendl ;
-
-	//print out recorded call stacks if there are any.
-	LLError::LLCallStacks::print();
-
-	LLAppViewer* pApp = LLAppViewer::instance();
-	if (pApp->beingDebugged())
-	{
-		// This will drop us into the debugger.
-		abort();
-	}
-
-	if (LLApp::isCrashloggerDisabled())
-	{
-		abort();
-	}
-
-	// Returns whether a dialog was shown.
-	// Only do the logic in here once
-	if (pApp->mReportedCrash)
-	{
-		return;
-	}
-	pApp->mReportedCrash = TRUE;
-	
-	// Insert crash host url (url to post crash log to) if configured.
-	std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
-	if(crashHostUrl != "")
-	{
-		gDebugInfo["CrashHostUrl"] = crashHostUrl;
-	}
-	
-	//We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version
-	//to check against no matter what
-	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
-
-	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
-	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
-	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
-	gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
-
-	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-	if ( parcel && parcel->getMusicURL()[0])
-	{
-		gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
-	}	
-	if ( parcel && parcel->getMediaURL()[0])
-	{
-		gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
-	}
-	
-	
-	gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
-	gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
-	gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
-	gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
-	gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
-	gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
-	gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
-	gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
-	gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
-
-	char *minidump_file = pApp->getMiniDumpFilename();
-	if(minidump_file && minidump_file[0] != 0)
-	{
-		gDebugInfo["MinidumpPath"] = minidump_file;
-	}
-	
-	if(gLogoutInProgress)
-	{
-		gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
-	}
-	else
-	{
-		gDebugInfo["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH;
-	}
-
-	if(gAgent.getRegion())
-	{
-		gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
-		gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
-		
-		const LLVector3& loc = gAgent.getPositionAgent();
-		gDebugInfo["CurrentLocationX"] = loc.mV[0];
-		gDebugInfo["CurrentLocationY"] = loc.mV[1];
-		gDebugInfo["CurrentLocationZ"] = loc.mV[2];
-	}
-
-	if(LLAppViewer::instance()->mMainloopTimeout)
-	{
-		gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
-	}
-	
-	// The crash is being handled here so set this value to false.
-	// Otherwise the crash logger will think this crash was a freeze.
-	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
-    
-	//Write out the crash status file
-	//Use marker file style setup, as that's the simplest, especially since
-	//we're already in a crash situation	
-	if (gDirUtilp)
-	{
-		std::string crash_file_name;
-		if(gLLErrorActivated) crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LLERROR_MARKER_FILE_NAME);
-		else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME);
-		llinfos << "Creating crash marker file " << crash_file_name << llendl;
-		
-		LLAPRFile crash_file ;
-		crash_file.open(crash_file_name, LL_APR_W);
-		if (crash_file.getFileHandle())
-		{
-			LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL;
-		}
-		else
-		{
-			LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL;
-		}		
-	}
-	
-	if (gMessageSystem && gDirUtilp)
-	{
-		std::string filename;
-		filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "stats.log");
-		llofstream file(filename, llofstream::binary);
-		if(file.good())
-		{
-			llinfos << "Handle viewer crash generating stats log." << llendl;
-			gMessageSystem->summarizeLogs(file);
-			file.close();
-		}
-	}
-
-	if (gMessageSystem)
-	{
-		gMessageSystem->getCircuitInfo(gDebugInfo["CircuitInfo"]);
-		gMessageSystem->stopLogging();
-	}
-
-	if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo);
-
-	// Close the debug file
-	pApp->writeDebugInfo();
-
-	LLError::logToFile("");
-
-	// Remove the marker file, since otherwise we'll spawn a process that'll keep it locked
-	if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH)
-	{
-		pApp->removeMarkerFile(true);
-	}
-	else
-	{
-		pApp->removeMarkerFile(false);
-	}
-	
-#if LL_SEND_CRASH_REPORTS
-	// Call to pure virtual, handled by platform specific llappviewer instance.
-	pApp->handleCrashReporting(); 
-#endif
-    
-	return;
-}
-
-bool LLAppViewer::anotherInstanceRunning()
-{
-	// We create a marker file when the program starts and remove the file when it finishes.
-	// If the file is currently locked, that means another process is already running.
-
-	std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, MARKER_FILE_NAME);
-	LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
-
-	//Freeze case checks
-	if (LLAPRFile::isExist(marker_file, NULL, LL_APR_RB))
-	{
-		// File exists, try opening with write permissions
-		LLAPRFile outfile ;
-		outfile.open(marker_file, LL_APR_WB);
-		apr_file_t* fMarker = outfile.getFileHandle() ; 
-		if (!fMarker)
-		{
-			// Another instance is running. Skip the rest of these operations.
-			LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
-			return true;
-		}
-		if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
-		{
-			LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
-			return true;
-		}
-		// No other instances; we'll lock this file now & delete on quit.		
-	}
-	LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL;
-	return false;
-}
-
-void LLAppViewer::initMarkerFile()
-{
-	//First, check for the existence of other files.
-	//There are marker files for two different types of crashes
-	
-	mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
-	LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
-
-	//We've got 4 things to test for here
-	// - Other Process Running (SecondLife.exec_marker present, locked)
-	// - Freeze (SecondLife.exec_marker present, not locked)
-	// - LLError Crash (SecondLife.llerror_marker present)
-	// - Other Crash (SecondLife.error_marker present)
-	// These checks should also remove these files for the last 2 cases if they currently exist
-
-	//LLError/Error checks. Only one of these should ever happen at a time.
-	std::string logout_marker_file =  gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
-	std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
-	std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
-
-	if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB) && !anotherInstanceRunning())
-	{
-		gLastExecEvent = LAST_EXEC_FROZE;
-		LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL;
-	}    
-	if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB))
-	{
-		gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
-		LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
-		LLAPRFile::remove(logout_marker_file);
-	}
-	if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB))
-	{
-		if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
-		else gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
-		LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
-		LLAPRFile::remove(llerror_marker_file);
-	}
-	if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
-	{
-		if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
-		else gLastExecEvent = LAST_EXEC_OTHER_CRASH;
-		LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
-		LLAPRFile::remove(error_marker_file);
-	}
-
-	// No new markers if another instance is running.
-	if(anotherInstanceRunning()) 
-	{
-		return;
-	}
-	
-	// Create the marker file for this execution & lock it
-	apr_status_t s;
-	s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE);	
-
-	if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
-	{
-		LL_DEBUGS("MarkerFile") << "Marker file created." << LL_ENDL;
-	}
-	else
-	{
-		LL_INFOS("MarkerFile") << "Failed to create marker file." << LL_ENDL;
-		return;
-	}
-	if (apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) 
-	{
-		mMarkerFile.close() ;
-		LL_INFOS("MarkerFile") << "Marker file cannot be locked." << LL_ENDL;
-		return;
-	}
-
-	LL_DEBUGS("MarkerFile") << "Marker file locked." << LL_ENDL;
-}
-
-void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
-{
-	LL_DEBUGS("MarkerFile") << "removeMarkerFile()" << LL_ENDL;
-	if (mMarkerFile.getFileHandle())
-	{
-		mMarkerFile.close() ;
-		LLAPRFile::remove( mMarkerFileName );
-	}
-	if (mLogoutMarkerFile != NULL && !leave_logout_marker)
-	{
-		LLAPRFile::remove( mLogoutMarkerFileName );
-		mLogoutMarkerFile = NULL;
-	}
-}
-
-void LLAppViewer::forceQuit()
-{ 
-	LLApp::setQuitting(); 
-}
-
-//TODO: remove
-void LLAppViewer::fastQuit(S32 error_code)
-{
-	// finish pending transfers
-	flushVFSIO();
-	// let sim know we're logging out
-	sendLogoutRequest();
-	// flush network buffers by shutting down messaging system
-	end_messaging_system();
-	// figure out the error code
-	S32 final_error_code = error_code ? error_code : (S32)isError();
-	// this isn't a crash	
-	removeMarkerFile();
-	// get outta here
-	_exit(final_error_code);	
-}
-
-void LLAppViewer::requestQuit()
-{
-	llinfos << "requestQuit" << llendl;
-
-	LLViewerRegion* region = gAgent.getRegion();
-	
-	if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
-	{
-		// If we have a region, make some attempt to send a logout request first.
-		// This prevents the halfway-logged-in avatar from hanging around inworld for a couple minutes.
-		if(region)
-		{
-			sendLogoutRequest();
-		}
-		
-		// Quit immediately
-		forceQuit();
-		return;
-	}
-
-	// Try to send metrics back to the grid
-	metricsSend(!gDisconnected);
-	
-	LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
-	effectp->setPositionGlobal(gAgent.getPositionGlobal());
-	effectp->setColor(LLColor4U(gAgent.getEffectColor()));
-	LLHUDManager::getInstance()->sendEffects();
-	effectp->markDead() ;//remove it.
-
-	// Attempt to close all floaters that might be
-	// editing things.
-	if (gFloaterView)
-	{
-		// application is quitting
-		gFloaterView->closeAllChildren(true);
-	}
-
-	LLSideTray::getInstance()->notifyChildren(LLSD().with("request","quit"));
-
-	send_stats();
-
-	gLogoutTimer.reset();
-	mQuitRequested = true;
-}
-
-static bool finish_quit(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
-	if (option == 0)
-	{
-		LLAppViewer::instance()->requestQuit();
-	}
-	return false;
-}
-static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_quit);
-
-static bool switch_standard_skin_and_quit(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
-	if (option == 0)
-	{
-		gSavedSettings.setString("SessionSettingsFile", "");
-		LLAppViewer::instance()->requestQuit();
-	}
-	return false;
-}
-
-static LLNotificationFunctorRegistration standard_skin_quit_reg("SwitchToStandardSkinAndQuit", switch_standard_skin_and_quit);
-
-void LLAppViewer::userQuit()
-{
-	if (gDisconnected || gViewerWindow->getProgressView()->getVisible())
-	{
-		requestQuit();
-	}
-	else
-	{
-		LLNotificationsUtil::add("ConfirmQuit");
-	}
-}
-
-static bool finish_early_exit(const LLSD& notification, const LLSD& response)
-{
-	LLAppViewer::instance()->forceQuit();
-	return false;
-}
-
-void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
-{
-   	llwarns << "app_early_exit: " << name << llendl;
-	gDoDisconnect = TRUE;
-	LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit);
-}
-
-// case where we need the viewer to exit without any need for notifications
-void LLAppViewer::earlyExitNoNotify()
-{
-   	llwarns << "app_early_exit with no notification: " << llendl;
-	gDoDisconnect = TRUE;
-	finish_early_exit( LLSD(), LLSD() );
-}
-
-void LLAppViewer::abortQuit()
-{
-    llinfos << "abortQuit()" << llendl;
-	mQuitRequested = false;
-}
-
-void LLAppViewer::migrateCacheDirectory()
-{
-#if LL_WINDOWS || LL_DARWIN
-	// NOTE: (Nyx) as of 1.21, cache for mac is moving to /library/caches/SecondLife from
-	// /library/application support/SecondLife/cache This should clear/delete the old dir.
-
-	// As of 1.23 the Windows cache moved from
-	//   C:\Documents and Settings\James\Application Support\SecondLife\cache
-	// to
-	//   C:\Documents and Settings\James\Local Settings\Application Support\SecondLife
-	//
-	// The Windows Vista equivalent is from
-	//   C:\Users\James\AppData\Roaming\SecondLife\cache
-	// to
-	//   C:\Users\James\AppData\Local\SecondLife
-	//
-	// Note the absence of \cache on the second path.  James.
-
-	// Only do this once per fresh install of this version.
-	if (gSavedSettings.getBOOL("MigrateCacheDirectory"))
-	{
-		gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE);
-
-		std::string delimiter = gDirUtilp->getDirDelimiter();
-		std::string old_cache_dir = gDirUtilp->getOSUserAppDir() + delimiter + "cache";
-		std::string new_cache_dir = gDirUtilp->getCacheDir(true);
-
-		if (gDirUtilp->fileExists(old_cache_dir))
-		{
-			llinfos << "Migrating cache from " << old_cache_dir << " to " << new_cache_dir << llendl;
-
-			// Migrate inventory cache to avoid pain to inventory database after mass update
-			S32 file_count = 0;
-			std::string file_name;
-			std::string mask = delimiter + "*.*";
-			while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name))
-			{
-				if (file_name == "." || file_name == "..") continue;
-				std::string source_path = old_cache_dir + delimiter + file_name;
-				std::string dest_path = new_cache_dir + delimiter + file_name;
-				if (!LLFile::rename(source_path, dest_path))
-				{
-					file_count++;
-				}
-			}
-			llinfos << "Moved " << file_count << " files" << llendl;
-
-			// Nuke the old cache
-			gDirUtilp->setCacheDir(old_cache_dir);
-			purgeCache();
-			gDirUtilp->setCacheDir(new_cache_dir);
-
-#if LL_DARWIN
-			// Clean up Mac files not deleted by removing *.*
-			std::string ds_store = old_cache_dir + "/.DS_Store";
-			if (gDirUtilp->fileExists(ds_store))
-			{
-				LLFile::remove(ds_store);
-			}
-#endif
-			if (LLFile::rmdir(old_cache_dir) != 0)
-			{
-				llwarns << "could not delete old cache directory " << old_cache_dir << llendl;
-			}
-		}
-	}
-#endif // LL_WINDOWS || LL_DARWIN
-}
-
-void dumpVFSCaches()
-{
-	llinfos << "======= Static VFS ========" << llendl;
-	gStaticVFS->listFiles();
-#if LL_WINDOWS
-	llinfos << "======= Dumping static VFS to StaticVFSDump ========" << llendl;
-	WCHAR w_str[MAX_PATH];
-	GetCurrentDirectory(MAX_PATH, w_str);
-	S32 res = LLFile::mkdir("StaticVFSDump");
-	if (res == -1)
-	{
-		if (errno != EEXIST)
-		{
-			llwarns << "Couldn't create dir StaticVFSDump" << llendl;
-		}
-	}
-	SetCurrentDirectory(utf8str_to_utf16str("StaticVFSDump").c_str());
-	gStaticVFS->dumpFiles();
-	SetCurrentDirectory(w_str);
-#endif
-						
-	llinfos << "========= Dynamic VFS ====" << llendl;
-	gVFS->listFiles();
-#if LL_WINDOWS
-	llinfos << "========= Dumping dynamic VFS to VFSDump ====" << llendl;
-	res = LLFile::mkdir("VFSDump");
-	if (res == -1)
-	{
-		if (errno != EEXIST)
-		{
-			llwarns << "Couldn't create dir VFSDump" << llendl;
-		}
-	}
-	SetCurrentDirectory(utf8str_to_utf16str("VFSDump").c_str());
-	gVFS->dumpFiles();
-	SetCurrentDirectory(w_str);
-#endif
-}
-
-//static
-U32 LLAppViewer::getTextureCacheVersion() 
-{
-	//viewer texture cache version, change if the texture cache format changes.
-	const U32 TEXTURE_CACHE_VERSION = 7;
-
-	return TEXTURE_CACHE_VERSION ;
-}
-
-//static
-U32 LLAppViewer::getObjectCacheVersion() 
-{
-	// Viewer object cache version, change if object update
-	// format changes. JC
-	const U32 INDRA_OBJECT_CACHE_VERSION = 14;
-
-	return INDRA_OBJECT_CACHE_VERSION;
-}
-
-bool LLAppViewer::initCache()
-{
-	mPurgeCache = false;
-	BOOL read_only = mSecondInstance ? TRUE : FALSE;
-	LLAppViewer::getTextureCache()->setReadOnly(read_only) ;
-	LLVOCache::getInstance()->setReadOnly(read_only);
-
-	BOOL texture_cache_mismatch = FALSE ;
-	if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) 
-	{
-		texture_cache_mismatch = TRUE ;
-		if(!read_only) 
-		{
-			gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion());
-		}
-	}
-
-	if(!read_only)
-	{
-		// Purge cache if user requested it
-		if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
-			gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
-		{
-			gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
-		mPurgeCache = true;
-		}
-	
-		// We have moved the location of the cache directory over time.
-		migrateCacheDirectory();
-	
-		// Setup and verify the cache location
-		std::string cache_location = gSavedSettings.getString("CacheLocation");
-		std::string new_cache_location = gSavedSettings.getString("NewCacheLocation");
-		if (new_cache_location != cache_location)
-		{
-			gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
-			purgeCache(); // purge old cache
-			gSavedSettings.setString("CacheLocation", new_cache_location);
-			gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location));
-		}
-	}
-
-	if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")))
-	{
-		LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL;
-		gSavedSettings.setString("CacheLocation", "");
-		gSavedSettings.setString("CacheLocationTopFolder", "");
-	}
-	
-	if (mPurgeCache && !read_only)
-	{
-		LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
-		purgeCache();
-	}
-
-	LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));
-	
-	// Init the texture cache
-	// Allocate 80% of the cache size for textures	
-	const S32 MB = 1024*1024;
-	S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
-	const S64 MAX_CACHE_SIZE = 1024*MB;
-	cache_size = llmin(cache_size, MAX_CACHE_SIZE);
-	S64 texture_cache_size = ((cache_size * 8)/10);
-	S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
-	texture_cache_size -= extra;
-
-	LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()) ;
-
-	LLSplashScreen::update(LLTrans::getString("StartupInitializingVFS"));
-	
-	// Init the VFS
-	S64 vfs_size = cache_size - texture_cache_size;
-	const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB
-	vfs_size = llmin(vfs_size, MAX_VFS_SIZE);
-	vfs_size = (vfs_size / MB) * MB; // make sure it is MB aligned
-	U32 vfs_size_u32 = (U32)vfs_size;
-	U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB;
-	bool resize_vfs = (vfs_size_u32 != old_vfs_size);
-	if (resize_vfs)
-	{
-		gSavedSettings.setU32("VFSOldSize", vfs_size_u32/MB);
-	}
-	LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size/(1024*1024) << " MB" << LL_ENDL;
-	
-	// This has to happen BEFORE starting the vfs
-	//time_t	ltime;
-	srand(time(NULL));		// Flawfinder: ignore
-	U32 old_salt = gSavedSettings.getU32("VFSSalt");
-	U32 new_salt;
-	std::string old_vfs_data_file;
-	std::string old_vfs_index_file;
-	std::string new_vfs_data_file;
-	std::string new_vfs_index_file;
-	std::string static_vfs_index_file;
-	std::string static_vfs_data_file;
-
-	if (gSavedSettings.getBOOL("AllowMultipleViewers"))
-	{
-		// don't mess with renaming the VFS in this case
-		new_salt = old_salt;
-	}
-	else
-	{
-		do
-		{
-			new_salt = rand();
-		} while( new_salt == old_salt );
-	}
-
-	old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",old_salt);
-
-	// make sure this file exists
-	llstat s;
-	S32 stat_result = LLFile::stat(old_vfs_data_file, &s);
-	if (stat_result)
-	{
-		// doesn't exist, look for a data file
-		std::string mask;
-		mask = gDirUtilp->getDirDelimiter();
-		mask += VFS_DATA_FILE_BASE;
-		mask += "*";
-
-		std::string dir;
-		dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
-
-		std::string found_file;
-		if (gDirUtilp->getNextFileInDir(dir, mask, found_file))
-		{
-			old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file;
-
-			S32 start_pos = found_file.find_last_of('.');
-			if (start_pos > 0)
-			{
-				sscanf(found_file.substr(start_pos+1).c_str(), "%d", &old_salt);
-			}
-			LL_DEBUGS("AppCache") << "Default vfs data file not present, found: " << old_vfs_data_file << " Old salt: " << old_salt << llendl;
-		}
-	}
-
-	old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_INDEX_FILE_BASE) + llformat("%u",old_salt);
-
-	stat_result = LLFile::stat(old_vfs_index_file, &s);
-	if (stat_result)
-	{
-		// We've got a bad/missing index file, nukem!
-		LL_WARNS("AppCache") << "Bad or missing vfx index file " << old_vfs_index_file << LL_ENDL;
-		LL_WARNS("AppCache") << "Removing old vfs data file " << old_vfs_data_file << LL_ENDL;
-		LLFile::remove(old_vfs_data_file);
-		LLFile::remove(old_vfs_index_file);
-		
-		// Just in case, nuke any other old cache files in the directory.
-		std::string dir;
-		dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
-
-		std::string mask;
-		mask = gDirUtilp->getDirDelimiter();
-		mask += VFS_DATA_FILE_BASE;
-		mask += "*";
-
-		gDirUtilp->deleteFilesInDir(dir, mask);
-
-		mask = gDirUtilp->getDirDelimiter();
-		mask += VFS_INDEX_FILE_BASE;
-		mask += "*";
-
-		gDirUtilp->deleteFilesInDir(dir, mask);
-	}
-
-	new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",new_salt);
-	new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u",new_salt);
-
-	static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_data.db2");
-	static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_index.db2");
-
-	if (resize_vfs)
-	{
-		LL_DEBUGS("AppCache") << "Removing old vfs and re-sizing" << LL_ENDL;
-		
-		LLFile::remove(old_vfs_data_file);
-		LLFile::remove(old_vfs_index_file);
-	}
-	else if (old_salt != new_salt)
-	{
-		// move the vfs files to a new name before opening
-		LL_DEBUGS("AppCache") << "Renaming " << old_vfs_data_file << " to " << new_vfs_data_file << LL_ENDL;
-		LL_DEBUGS("AppCache") << "Renaming " << old_vfs_index_file << " to " << new_vfs_index_file << LL_ENDL;
-		LLFile::rename(old_vfs_data_file, new_vfs_data_file);
-		LLFile::rename(old_vfs_index_file, new_vfs_index_file);
-	}
-
-	// Startup the VFS...
-	gSavedSettings.setU32("VFSSalt", new_salt);
-
-	// Don't remove VFS after viewer crashes.  If user has corrupt data, they can reinstall. JC
-	gVFS = LLVFS::createLLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
-	if( !gVFS )
-	{
-		return false;
-	}
-
-	gStaticVFS = LLVFS::createLLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false);
-	if( !gStaticVFS )
-	{
-		return false;
-	}
-
-	BOOL success = gVFS->isValid() && gStaticVFS->isValid();
-	if( !success )
-	{
-		return false;
-	}
-	else
-	{
-		LLVFile::initClass();
-
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-		if (gSavedSettings.getBOOL("DumpVFSCaches"))
-		{
-			dumpVFSCaches();
-		}
-#endif
-		
-		return true;
-	}
-}
-
-void LLAppViewer::purgeCache()
-{
-	LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl;
-	LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
-	LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
-	std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
-	gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
-}
-
-std::string LLAppViewer::getSecondLifeTitle() const
-{
-	return LLTrans::getString("APP_NAME");
-}
-
-std::string LLAppViewer::getWindowTitle() const 
-{
-	return gWindowTitle;
-}
-
-// Callback from a dialog indicating user was logged out.  
-bool finish_disconnect(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
-	if (1 == option)
-	{
-        LLAppViewer::instance()->forceQuit();
-	}
-	return false;
-}
-
-// Callback from an early disconnect dialog, force an exit
-bool finish_forced_disconnect(const LLSD& notification, const LLSD& response)
-{
-	LLAppViewer::instance()->forceQuit();
-	return false;
-}
-
-
-void LLAppViewer::forceDisconnect(const std::string& mesg)
-{
-	if (gDoDisconnect)
-    {
-		// Already popped up one of these dialogs, don't
-		// do this again.
-		return;
-    }
-	
-	// *TODO: Translate the message if possible
-	std::string big_reason = LLAgent::sTeleportErrorMessages[mesg];
-	if ( big_reason.size() == 0 )
-	{
-		big_reason = mesg;
-	}
-
-	LLSD args;
-	gDoDisconnect = TRUE;
-
-	if (LLStartUp::getStartupState() < STATE_STARTED)
-	{
-		// Tell users what happened
-		args["ERROR_MESSAGE"] = big_reason;
-		LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect);
-	}
-	else
-	{
-		args["MESSAGE"] = big_reason;
-		LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect );
-	}
-}
-
-void LLAppViewer::badNetworkHandler()
-{
-	// Dump the packet
-	gMessageSystem->dumpPacketToLog();
-
-	// Flush all of our caches on exit in the case of disconnect due to
-	// invalid packets.
-
-	mPurgeOnExit = TRUE;
-
-	std::ostringstream message;
-	message <<
-		"The viewer has detected mangled network data indicative\n"
-		"of a bad upstream network connection or an incomplete\n"
-		"local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n"
-		" \n"
-		"Try uninstalling and reinstalling to see if this resolves \n"
-		"the issue. \n"
-		" \n"
-		"If the problem continues, see the Tech Support FAQ at: \n"
-		"www.secondlife.com/support";
-	forceDisconnect(message.str());
-	
-	LLApp::instance()->writeMiniDump();
-}
-
-// This routine may get called more than once during the shutdown process.
-// This can happen because we need to get the screenshot before the window
-// is destroyed.
-void LLAppViewer::saveFinalSnapshot()
-{
-	if (!mSavedFinalSnapshot && !gNoRender)
-	{
-		gSavedSettings.setVector3d("FocusPosOnLogout", gAgentCamera.calcFocusPositionTargetGlobal());
-		gSavedSettings.setVector3d("CameraPosOnLogout", gAgentCamera.calcCameraPositionTargetGlobal());
-		gViewerWindow->setCursor(UI_CURSOR_WAIT);
-		gAgentCamera.changeCameraToThirdPerson( FALSE );	// don't animate, need immediate switch
-		gSavedSettings.setBOOL("ShowParcelOwners", FALSE);
-		idle();
-
-		std::string snap_filename = gDirUtilp->getLindenUserDir();
-		snap_filename += gDirUtilp->getDirDelimiter();
-		snap_filename += SCREEN_LAST_FILENAME;
-		// use full pixel dimensions of viewer window (not post-scale dimensions)
-		gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, TRUE);
-		mSavedFinalSnapshot = TRUE;
-	}
-}
-
-void LLAppViewer::loadNameCache()
-{
-	// display names cache
-	std::string filename =
-		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
-	LL_INFOS("AvNameCache") << filename << LL_ENDL;
-	llifstream name_cache_stream(filename);
-	if(name_cache_stream.is_open())
-	{
-		LLAvatarNameCache::importFile(name_cache_stream);
-	}
-
-	if (!gCacheName) return;
-
-	std::string name_cache;
-	name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
-	llifstream cache_file(name_cache);
-	if(cache_file.is_open())
-	{
-		if(gCacheName->importFile(cache_file)) return;
-	}
-}
-
-void LLAppViewer::saveNameCache()
-	{
-	// display names cache
-	std::string filename =
-		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
-	llofstream name_cache_stream(filename);
-	if(name_cache_stream.is_open())
-	{
-		LLAvatarNameCache::exportFile(name_cache_stream);
-}
-
-	if (!gCacheName) return;
-
-	std::string name_cache;
-	name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
-	llofstream cache_file(name_cache);
-	if(cache_file.is_open())
-	{
-		gCacheName->exportFile(cache_file);
-	}
-}
-
-/*!	@brief		This class is an LLFrameTimer that can be created with
-				an elapsed time that starts counting up from the given value
-				rather than 0.0.
-				
-				Otherwise it behaves the same way as LLFrameTimer.
-*/
-class LLFrameStatsTimer : public LLFrameTimer
-{
-public:
-	LLFrameStatsTimer(F64 elapsed_already = 0.0)
-		: LLFrameTimer()
-		{
-			mStartTime -= elapsed_already;
-		}
-};
-
-static LLFastTimer::DeclareTimer FTM_AUDIO_UPDATE("Update Audio");
-static LLFastTimer::DeclareTimer FTM_CLEANUP("Cleanup");
-static LLFastTimer::DeclareTimer FTM_IDLE_CB("Idle Callbacks");
-static LLFastTimer::DeclareTimer FTM_LOD_UPDATE("Update LOD");
-static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist");
-static LLFastTimer::DeclareTimer FTM_REGION_UPDATE("Update Region");
-static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World");
-static LLFastTimer::DeclareTimer FTM_NETWORK("Network");
-
-///////////////////////////////////////////////////////
-// idle()
-//
-// Called every time the window is not doing anything.
-// Receive packets, update statistics, and schedule a redisplay.
-///////////////////////////////////////////////////////
-void LLAppViewer::idle()
-{
-	LLMemType mt_idle(LLMemType::MTYPE_IDLE);
-	pingMainloopTimeout("Main:Idle");
-	
-	// Update frame timers
-	static LLTimer idle_timer;
-
-	LLFrameTimer::updateFrameTime();
-	LLFrameTimer::updateFrameCount();
-	LLEventTimer::updateClass();
-	LLCriticalDamp::updateInterpolants();
-	LLMortician::updateClass();
-	F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
-
-	// Cap out-of-control frame times
-	// Too low because in menus, swapping, debugger, etc.
-	// Too high because idle called with no objects in view, etc.
-	const F32 MIN_FRAME_RATE = 1.f;
-	const F32 MAX_FRAME_RATE = 200.f;
-
-	F32 frame_rate_clamped = 1.f / dt_raw;
-	frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE, MAX_FRAME_RATE);
-	gFrameDTClamped = 1.f / frame_rate_clamped;
-
-	// Global frame timer
-	// Smoothly weight toward current frame
-	gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f;
-
-	F32 qas = gSavedSettings.getF32("QuitAfterSeconds");
-	if (qas > 0.f)
-	{
-		if (gRenderStartTime.getElapsedTimeF32() > qas)
-		{
-			LLAppViewer::instance()->forceQuit();
-		}
-	}
-
-	// debug setting to quit after N seconds of being AFK - 0 to never do this
-	F32 qas_afk = gSavedSettings.getF32("QuitAfterSecondsOfAFK");
-	if (qas_afk > 0.f)
-	{
-		// idle time is more than setting
-		if ( gAwayTriggerTimer.getElapsedTimeF32() > qas_afk )
-		{
-			// go ahead and just quit gracefully
-			LLAppViewer::instance()->requestQuit();
-		}
-	}
-
-	// Must wait until both have avatar object and mute list, so poll
-	// here.
-	request_initial_instant_messages();
-
-	///////////////////////////////////
-	//
-	// Special case idle if still starting up
-	//
-	if (LLStartUp::getStartupState() < STATE_STARTED)
-	{
-		// Skip rest if idle startup returns false (essentially, no world yet)
-		gGLActive = TRUE;
-		if (!idle_startup())
-		{
-			gGLActive = FALSE;
-			return;
-		}
-		gGLActive = FALSE;
-	}
-
-	
-    F32 yaw = 0.f;				// radians
-
-	if (!gDisconnected)
-	{
-		LLFastTimer t(FTM_NETWORK);
-		// Update spaceserver timeinfo
-	    LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC));
-    
-    
-	    //////////////////////////////////////
-	    //
-	    // Update simulator agent state
-	    //
-
-		if (gSavedSettings.getBOOL("RotateRight"))
-		{
-			gAgent.moveYaw(-1.f);
-		}
-
-		{
-			LLFastTimer t(FTM_AGENT_AUTOPILOT);
-			// Handle automatic walking towards points
-			gAgentPilot.updateTarget();
-			gAgent.autoPilot(&yaw);
-		}
-    
-	    static LLFrameTimer agent_update_timer;
-	    static U32 				last_control_flags;
-    
-	    //	When appropriate, update agent location to the simulator.
-	    F32 agent_update_time = agent_update_timer.getElapsedTimeF32();
-	    BOOL flags_changed = gAgent.controlFlagsDirty() || (last_control_flags != gAgent.getControlFlags());
-		    
-	    if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
-	    {
-		    LLFastTimer t(FTM_AGENT_UPDATE);
-		    // Send avatar and camera info
-		    last_control_flags = gAgent.getControlFlags();
-		    send_agent_update(TRUE);
-		    agent_update_timer.reset();
-	    }
-	}
-
-	//////////////////////////////////////
-	//
-	// Manage statistics
-	//
-	//
-	{
-		// Initialize the viewer_stats_timer with an already elapsed time
-		// of SEND_STATS_PERIOD so that the initial stats report will
-		// be sent immediately.
-		static LLFrameStatsTimer viewer_stats_timer(SEND_STATS_PERIOD);
-		reset_statistics();
-
-		// Update session stats every large chunk of time
-		// *FIX: (???) SAMANTHA
-		if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected)
-		{
-			llinfos << "Transmitting sessions stats" << llendl;
-			send_stats();
-			viewer_stats_timer.reset();
-		}
-
-		// Print the object debugging stats
-		static LLFrameTimer object_debug_timer;
-		if (object_debug_timer.getElapsedTimeF32() > 5.f)
-		{
-			object_debug_timer.reset();
-			if (gObjectList.mNumDeadObjectUpdates)
-			{
-				llinfos << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << llendl;
-				gObjectList.mNumDeadObjectUpdates = 0;
-			}
-			if (gObjectList.mNumUnknownKills)
-			{
-				llinfos << "Kills on unknown objects: " << gObjectList.mNumUnknownKills << llendl;
-				gObjectList.mNumUnknownKills = 0;
-			}
-			if (gObjectList.mNumUnknownUpdates)
-			{
-				llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl;
-				gObjectList.mNumUnknownUpdates = 0;
-			}
-
-			// ViewerMetrics FPS piggy-backing on the debug timer.
-			// The 5-second interval is nice for this purpose.  If the object debug
-			// bit moves or is disabled, please give this a suitable home.
-			LLViewerAssetStatsFF::record_fps_main(gFPSClamped);
-		}
-	}
-
-	if (!gDisconnected)
-	{
-		LLFastTimer t(FTM_NETWORK);
-	
-	    ////////////////////////////////////////////////
-	    //
-	    // Network processing
-	    //
-	    // NOTE: Starting at this point, we may still have pointers to "dead" objects
-	    // floating throughout the various object lists.
-	    //
-		idleNameCache();
-    
-		idleNetwork();
-	    	        
-
-		// Check for away from keyboard, kick idle agents.
-		idle_afk_check();
-
-		//  Update statistics for this frame
-		update_statistics(gFrameCount);
-	}
-
-	////////////////////////////////////////
-	//
-	// Handle the regular UI idle callbacks as well as
-	// hover callbacks
-	//
-
-	{
-// 		LLFastTimer t(FTM_IDLE_CB);
-
-		// Do event notifications if necessary.  Yes, we may want to move this elsewhere.
-		gEventNotifier.update();
-		
-		gIdleCallbacks.callFunctions();
-		gInventory.idleNotifyObservers();
-	}
-	
-	// Metrics logging (LLViewerAssetStats, etc.)
-	{
-		static LLTimer report_interval;
-
-		// *TODO:  Add configuration controls for this
-		if (report_interval.getElapsedTimeF32() >= app_metrics_interval)
-		{
-			metricsSend(! gDisconnected);
-			report_interval.reset();
-		}
-	}
-
-	if (gDisconnected)
-    {
-		return;
-    }
-
-	gViewerWindow->updateUI();
-
-	///////////////////////////////////////
-	// Agent and camera movement
-	//
-		LLCoordGL current_mouse = gViewerWindow->getCurrentMouse();
-
-	{
-		// After agent and camera moved, figure out if we need to
-		// deselect objects.
-		LLSelectMgr::getInstance()->deselectAllIfTooFar();
-
-	}
-
-	{
-		// Handle pending gesture processing
-		static LLFastTimer::DeclareTimer ftm("Agent Position");
-		LLFastTimer t(ftm);
-		LLGestureMgr::instance().update();
-
-		gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY);
-	}
-
-	{
-		LLFastTimer t(FTM_OBJECTLIST_UPDATE); 
-		
-        if (!(logoutRequestSent() && hasSavedFinalSnapshot()))
-		{
-			gObjectList.update(gAgent, *LLWorld::getInstance());
-		}
-	}
-	
-	//////////////////////////////////////
-	//
-	// Deletes objects...
-	// Has to be done after doing idleUpdates (which can kill objects)
-	//
-
-	{
-		LLFastTimer t(FTM_CLEANUP);
-		gObjectList.cleanDeadObjects();
-		LLDrawable::cleanupDeadDrawables();
-	}
-	
-	//
-	// After this point, in theory we should never see a dead object
-	// in the various object/drawable lists.
-	//
-
-	//////////////////////////////////////
-	//
-	// Update/send HUD effects
-	//
-	// At this point, HUD effects may clean up some references to
-	// dead objects.
-	//
-
-	{
-		static LLFastTimer::DeclareTimer ftm("HUD Effects");
-		LLFastTimer t(ftm);
-		LLSelectMgr::getInstance()->updateEffects();
-		LLHUDManager::getInstance()->cleanupEffects();
-		LLHUDManager::getInstance()->sendEffects();
-	}
-
-	////////////////////////////////////////
-	//
-	// Unpack layer data that we've received
-	//
-
-	{
-		LLFastTimer t(FTM_NETWORK);
-		gVLManager.unpackData();
-	}
-	
-	/////////////////////////
-	//
-	// Update surfaces, and surface textures as well.
-	//
-
-	LLWorld::getInstance()->updateVisibilities();
-	{
-		const F32 max_region_update_time = .001f; // 1ms
-		LLFastTimer t(FTM_REGION_UPDATE);
-		LLWorld::getInstance()->updateRegions(max_region_update_time);
-	}
-	
-	/////////////////////////
-	//
-	// Update weather effects
-	//
-	if (!gNoRender)
-	{
-		LLWorld::getInstance()->updateClouds(gFrameDTClamped);
-		gSky.propagateHeavenlyBodies(gFrameDTClamped);				// moves sun, moon, and planets
-
-		// Update wind vector 
-		LLVector3 wind_position_region;
-		static LLVector3 average_wind;
-
-		LLViewerRegion *regionp;
-		regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal());	// puts agent's local coords into wind_position	
-		if (regionp)
-		{
-			gWindVec = regionp->mWind.getVelocity(wind_position_region);
-
-			// Compute average wind and use to drive motion of water
-			
-			average_wind = regionp->mWind.getAverage();
-			F32 cloud_density = regionp->mCloudLayer.getDensityRegion(wind_position_region);
-			
-			gSky.setCloudDensityAtAgent(cloud_density);
-			gSky.setWind(average_wind);
-			//LLVOWater::setWind(average_wind);
-		}
-		else
-		{
-			gWindVec.setVec(0.0f, 0.0f, 0.0f);
-		}
-	}
-	
-	//////////////////////////////////////
-	//
-	// Sort and cull in the new renderer are moved to pipeline.cpp
-	// Here, particles are updated and drawables are moved.
-	//
-	
-	if (!gNoRender)
-	{
-		LLFastTimer t(FTM_WORLD_UPDATE);
-		gPipeline.updateMove();
-
-		LLWorld::getInstance()->updateParticles();
-	}
-
-	if (LLViewerJoystick::getInstance()->getOverrideCamera())
-	{
-		LLViewerJoystick::getInstance()->moveFlycam();
-	}
-	else
-	{
-		if (LLToolMgr::getInstance()->inBuildMode())
-		{
-			LLViewerJoystick::getInstance()->moveObjects();
-		}
-
-		gAgentCamera.updateCamera();
-	}
-
-	// update media focus
-	LLViewerMediaFocus::getInstance()->update();
-
-	// objects and camera should be in sync, do LOD calculations now
-	{
-		LLFastTimer t(FTM_LOD_UPDATE);
-		gObjectList.updateApparentAngles(gAgent);
-	}
-
-	{
-		LLFastTimer t(FTM_AUDIO_UPDATE);
-		
-		if (gAudiop)
-		{
-		    audio_update_volume(false);
-			audio_update_listener();
-			audio_update_wind(false);
-
-			// this line actually commits the changes we've made to source positions, etc.
-			const F32 max_audio_decode_time = 0.002f; // 2 ms decode time
-			gAudiop->idle(max_audio_decode_time);
-		}
-	}
-	
-	// Handle shutdown process, for example, 
-	// wait for floaters to close, send quit message,
-	// forcibly quit if it has taken too long
-	if (mQuitRequested)
-	{
-		gGLActive = TRUE;
-		idleShutdown();
-	}
-}
-
-void LLAppViewer::idleShutdown()
-{
-	// Wait for all modal alerts to get resolved
-	if (LLModalDialog::activeCount() > 0)
-	{
-		return;
-	}
-
-	// close IM interface
-	if(gIMMgr)
-	{
-		gIMMgr->disconnectAllSessions();
-	}
-	
-	// Wait for all floaters to get resolved
-	if (gFloaterView
-		&& !gFloaterView->allChildrenClosed())
-	{
-		return;
-	}
-
-	if (LLSideTray::getInstance()->notifyChildren(LLSD().with("request","wait_quit")))
-	{
-		return;
-	}
-
-
-	
-	// ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()
-	// *TODO: ugly
-	static bool saved_teleport_history = false;
-	if (!saved_teleport_history)
-	{
-		saved_teleport_history = true;
-		LLTeleportHistory::getInstance()->dump();
-		LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this
-		return;
-	}
-
-	static bool saved_snapshot = false;
-	if (!saved_snapshot)
-	{
-		saved_snapshot = true;
-		saveFinalSnapshot();
-		return;
-	}
-
-	const F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f;
-
-	S32 pending_uploads = gAssetStorage->getNumPendingUploads();
-	if (pending_uploads > 0
-		&& gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
-		&& !logoutRequestSent())
-	{
-		static S32 total_uploads = 0;
-		// Sometimes total upload count can change during logout.
-		total_uploads = llmax(total_uploads, pending_uploads);
-		gViewerWindow->setShowProgress(TRUE);
-		S32 finished_uploads = total_uploads - pending_uploads;
-		F32 percent = 100.f * finished_uploads / total_uploads;
-		gViewerWindow->setProgressPercent(percent);
-		gViewerWindow->setProgressString(LLTrans::getString("SavingSettings"));
-		return;
-	}
-
-	// All floaters are closed.  Tell server we want to quit.
-	if( !logoutRequestSent() )
-	{
-		sendLogoutRequest();
-
-		// Wait for a LogoutReply message
-		gViewerWindow->setShowProgress(TRUE);
-		gViewerWindow->setProgressPercent(100.f);
-		gViewerWindow->setProgressString(LLTrans::getString("LoggingOut"));
-		return;
-	}
-
-	// Make sure that we quit if we haven't received a reply from the server.
-	if( logoutRequestSent() 
-		&& gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime )
-	{
-		forceQuit();
-		return;
-	}
-}
-
-void LLAppViewer::sendLogoutRequest()
-{
-	if(!mLogoutRequestSent)
-	{
-		LLMessageSystem* msg = gMessageSystem;
-		msg->newMessageFast(_PREHASH_LogoutRequest);
-		msg->nextBlockFast(_PREHASH_AgentData);
-		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
-		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-		gAgent.sendReliableMessage();
-
-		gLogoutTimer.reset();
-		gLogoutMaxTime = LOGOUT_REQUEST_TIME;
-		mLogoutRequestSent = TRUE;
-		
-		if(LLVoiceClient::instanceExists())
-		{
-			LLVoiceClient::getInstance()->leaveChannel();
-		}
-
-		//Set internal status variables and marker files
-		gLogoutInProgress = TRUE;
-		mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
-		
-		LLAPRFile outfile ;
-		outfile.open(mLogoutMarkerFileName, LL_APR_W);
-		mLogoutMarkerFile =  outfile.getFileHandle() ;
-		if (mLogoutMarkerFile)
-		{
-			llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl;
-    		apr_file_close(mLogoutMarkerFile);
-		}
-		else
-		{
-			llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl;
-		}		
-	}
-}
-
-void LLAppViewer::idleNameCache()
-{
-	// Neither old nor new name cache can function before agent has a region
-	LLViewerRegion* region = gAgent.getRegion();
-	if (!region) return;
-
-	// deal with any queued name requests and replies.
-	gCacheName->processPending();
-
-	// Can't run the new cache until we have the list of capabilities
-	// for the agent region, and can therefore decide whether to use
-	// display names or fall back to the old name system.
-	if (!region->capabilitiesReceived()) return;
-
-	// Agent may have moved to a different region, so need to update cap URL
-	// for name lookups.  Can't do this in the cap grant code, as caps are
-	// granted to neighbor regions before the main agent gets there.  Can't
-	// do it in the move-into-region code because cap not guaranteed to be
-	// granted yet, for example on teleport.
-	bool had_capability = LLAvatarNameCache::hasNameLookupURL();
-	std::string name_lookup_url;
-	name_lookup_url.reserve(128); // avoid a memory allocation below
-	name_lookup_url = region->getCapability("GetDisplayNames");
-	bool have_capability = !name_lookup_url.empty();
-	if (have_capability)
-	{
-		// we have support for display names, use it
-	    U32 url_size = name_lookup_url.size();
-	    // capabilities require URLs with slashes before query params:
-	    // https://<host>:<port>/cap/<uuid>/?ids=<blah>
-	    // but the caps are granted like:
-	    // https://<host>:<port>/cap/<uuid>
-	    if (url_size > 0 && name_lookup_url[url_size-1] != '/')
-	    {
-		    name_lookup_url += '/';
-	    }
-		LLAvatarNameCache::setNameLookupURL(name_lookup_url);
-	}
-	else
-	{
-		// Display names not available on this region
-		LLAvatarNameCache::setNameLookupURL( std::string() );
-	}
-
-	// Error recovery - did we change state?
-	if (had_capability != have_capability)
-	{
-		// name tags are persistant on screen, so make sure they refresh
-		LLVOAvatar::invalidateNameTags();
-	}
-
-	LLAvatarNameCache::idle();
-}
-
-//
-// Handle messages, and all message related stuff
-//
-
-#define TIME_THROTTLE_MESSAGES
-
-#ifdef TIME_THROTTLE_MESSAGES
-#define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!)
-static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
-#endif
-
-static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Idle Network");
-
-void LLAppViewer::idleNetwork()
-{
-	LLMemType mt_in(LLMemType::MTYPE_IDLE_NETWORK);
-	pingMainloopTimeout("idleNetwork");
-	
-	gObjectList.mNumNewObjects = 0;
-	S32 total_decoded = 0;
-
-	if (!gSavedSettings.getBOOL("SpeedTest"))
-	{
-		LLFastTimer t(FTM_IDLE_NETWORK); // decode
-		
-		LLTimer check_message_timer;
-		//  Read all available packets from network 
-		const S64 frame_count = gFrameCount;  // U32->S64
-		F32 total_time = 0.0f;
-
-		while (gMessageSystem->checkAllMessages(frame_count, gServicePump)) 
-		{
-			if (gDoDisconnect)
-			{
-				// We're disconnecting, don't process any more messages from the server
-				// We're usually disconnecting due to either network corruption or a
-				// server going down, so this is OK.
-				break;
-			}
-			
-			total_decoded++;
-			gPacketsIn++;
-
-			if (total_decoded > MESSAGE_MAX_PER_FRAME)
-			{
-				break;
-			}
-
-#ifdef TIME_THROTTLE_MESSAGES
-			// Prevent slow packets from completely destroying the frame rate.
-			// This usually happens due to clumps of avatars taking huge amount
-			// of network processing time (which needs to be fixed, but this is
-			// a good limit anyway).
-			total_time = check_message_timer.getElapsedTimeF32();
-			if (total_time >= CheckMessagesMaxTime)
-				break;
-#endif
-		}
-
-		// Handle per-frame message system processing.
-		gMessageSystem->processAcks();
-
-#ifdef TIME_THROTTLE_MESSAGES
-		if (total_time >= CheckMessagesMaxTime)
-		{
-			// Increase CheckMessagesMaxTime so that we will eventually catch up
-			CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames
-		}
-		else
-		{
-			// Reset CheckMessagesMaxTime to default value
-			CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
-		}
-#endif
-		
-
-
-		// we want to clear the control after sending out all necessary agent updates
-		gAgent.resetControlFlags();
-				
-		// Decode enqueued messages...
-		S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
-
-		if( remaining_possible_decodes <= 0 )
-		{
-			llinfos << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << llendl;
-		}
-
-		if (gPrintMessagesThisFrame)
-		{
-			llinfos << "Decoded " << total_decoded << " msgs this frame!" << llendl;
-			gPrintMessagesThisFrame = FALSE;
-		}
-	}
-	LLViewerStats::getInstance()->mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
-
-	// Retransmit unacknowledged packets.
-	gXferManager->retransmitUnackedPackets();
-	gAssetStorage->checkForTimeouts();
-	gViewerThrottle.updateDynamicThrottle();
-
-	// Check that the circuit between the viewer and the agent's current
-	// region is still alive
-	LLViewerRegion *agent_region = gAgent.getRegion();
-	if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED))
-	{
-		LLUUID this_region_id = agent_region->getRegionID();
-		bool this_region_alive = agent_region->isAlive();
-		if ((mAgentRegionLastAlive && !this_region_alive) // newly dead
-		    && (mAgentRegionLastID == this_region_id)) // same region
-		{
-			forceDisconnect(LLTrans::getString("AgentLostConnection"));
-		}
-		mAgentRegionLastID = this_region_id;
-		mAgentRegionLastAlive = this_region_alive;
-	}
-}
-
-void LLAppViewer::disconnectViewer()
-{
-	if (gDisconnected)
-	{
-		return;
-	}
-	//
-	// Cleanup after quitting.
-	//	
-	// Save snapshot for next time, if we made it through initialization
-
-	llinfos << "Disconnecting viewer!" << llendl;
-
-	// Dump our frame statistics
-
-	// Remember if we were flying
-	gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() );
-
-	// Un-minimize all windows so they don't get saved minimized
-	if (!gNoRender)
-	{
-		if (gFloaterView)
-		{
-			gFloaterView->restoreAll();
-		}
-	}
-
-	if (LLSelectMgr::getInstance())
-	{
-		LLSelectMgr::getInstance()->deselectAll();
-	}
-
-	// save inventory if appropriate
-	gInventory.cache(gInventory.getRootFolderID(), gAgent.getID());
-	if (gInventory.getLibraryRootFolderID().notNull()
-		&& gInventory.getLibraryOwnerID().notNull())
-	{
-		gInventory.cache(
-			gInventory.getLibraryRootFolderID(),
-			gInventory.getLibraryOwnerID());
-	}
-
-	saveNameCache();
-
-	// close inventory interface, close all windows
-	LLFloaterInventory::cleanup();
-
-	gAgentWearables.cleanup();
-	gAgentCamera.cleanup();
-	// Also writes cached agent settings to gSavedSettings
-	gAgent.cleanup();
-
-	// This is where we used to call gObjectList.destroy() and then delete gWorldp.
-	// Now we just ask the LLWorld singleton to cleanly shut down.
-	if(LLWorld::instanceExists())
-	{
-		LLWorld::getInstance()->destroyClass();
-	}
-
-	// call all self-registered classes
-	LLDestroyClassList::instance().fireCallbacks();
-
-	cleanup_xfer_manager();
-	gDisconnected = TRUE;
-
-	// Pass the connection state to LLUrlEntryParcel not to attempt
-	// parcel info requests while disconnected.
-	LLUrlEntryParcel::setDisconnected(gDisconnected);
-}
-
-void LLAppViewer::forceErrorLLError()
-{
-   	llerrs << "This is an llerror" << llendl;
-}
-
-void LLAppViewer::forceErrorBreakpoint()
-{
-#ifdef LL_WINDOWS
-    DebugBreak();
-#endif
-    return;
-}
-
-void LLAppViewer::forceErrorBadMemoryAccess()
-{
-    S32* crash = NULL;
-    *crash = 0xDEADBEEF;  
-    return;
-}
-
-void LLAppViewer::forceErrorInfiniteLoop()
-{
-    while(true)
-    {
-        ;
-    }
-    return;
-}
- 
-void LLAppViewer::forceErrorSoftwareException()
-{
-    // *FIX: Any way to insure it won't be handled?
-    throw; 
-}
-
-void LLAppViewer::forceErrorDriverCrash()
-{
-	glDeleteTextures(1, NULL);
-}
-
-void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
-{
-	if(!mMainloopTimeout)
-	{
-		mMainloopTimeout = new LLWatchdogTimeout();
-		resumeMainloopTimeout(state, secs);
-	}
-}
-
-void LLAppViewer::destroyMainloopTimeout()
-{
-	if(mMainloopTimeout)
-	{
-		delete mMainloopTimeout;
-		mMainloopTimeout = NULL;
-	}
-}
-
-void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
-{
-	if(mMainloopTimeout)
-	{
-		if(secs < 0.0f)
-		{
-			secs = gSavedSettings.getF32("MainloopTimeoutDefault");
-		}
-		
-		mMainloopTimeout->setTimeout(secs);
-		mMainloopTimeout->start(state);
-	}
-}
-
-void LLAppViewer::pauseMainloopTimeout()
-{
-	if(mMainloopTimeout)
-	{
-		mMainloopTimeout->stop();
-	}
-}
-
-void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
-{
-//	if(!restoreErrorTrap())
-//	{
-//		llwarns << "!!!!!!!!!!!!! Its an error trap!!!!" << state << llendl;
-//	}
-	
-	if(mMainloopTimeout)
-	{
-		if(secs < 0.0f)
-		{
-			secs = gSavedSettings.getF32("MainloopTimeoutDefault");
-		}
-
-		mMainloopTimeout->setTimeout(secs);
-		mMainloopTimeout->ping(state);
-	}
-}
-
-void LLAppViewer::handleLoginComplete()
-{
-	gLoggedInTime.start();
-	initMainloopTimeout("Mainloop Init");
-
-	// Store some data to DebugInfo in case of a freeze.
-	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
-
-	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
-	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
-	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
-	gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
-
-	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-	if ( parcel && parcel->getMusicURL()[0])
-	{
-		gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
-	}	
-	if ( parcel && parcel->getMediaURL()[0])
-	{
-		gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
-	}
-	
-	gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
-	gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
-	gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
-	gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
-
-	if(gAgent.getRegion())
-	{
-		gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
-		gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
-	}
-
-	if(LLAppViewer::instance()->mMainloopTimeout)
-	{
-		gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
-	}
-
-	mOnLoginCompleted();
-
-	writeDebugInfo();
-}
-
-// *TODO - generalize this and move DSO wrangling to a helper class -brad
-void LLAppViewer::loadEventHostModule(S32 listen_port)
-{
-	std::string dso_name =
-#if LL_WINDOWS
-	    "lleventhost.dll";
-#elif LL_DARWIN
-	    "liblleventhost.dylib";
-#else
-	    "liblleventhost.so";
-#endif
-
-	std::string dso_path = gDirUtilp->findFile(dso_name,
-		gDirUtilp->getAppRODataDir(),
-		gDirUtilp->getExecutableDir());
-
-	if(dso_path == "")
-	{
-		llerrs << "QAModeEventHost requested but module \"" << dso_name << "\" not found!" << llendl;
-		return;
-	}
-
-	LL_INFOS("eventhost") << "Found lleventhost at '" << dso_path << "'" << LL_ENDL;
-#if ! defined(LL_WINDOWS)
-	{
-		std::string outfile("/tmp/lleventhost.file.out");
-		std::string command("file '" + dso_path + "' > '" + outfile + "' 2>&1");
-		int rc = system(command.c_str());
-		if (rc != 0)
-		{
-			LL_WARNS("eventhost") << command << " ==> " << rc << ':' << LL_ENDL;
-		}
-		else
-		{
-			LL_INFOS("eventhost") << command << ':' << LL_ENDL;
-		}
-		{
-			std::ifstream reader(outfile.c_str());
-			std::string line;
-			while (std::getline(reader, line))
-			{
-				size_t len = line.length();
-				if (len && line[len-1] == '\n')
-					line.erase(len-1);
-				LL_INFOS("eventhost") << line << LL_ENDL;
-			}
-		}
-		remove(outfile.c_str());
-	}
-#endif // LL_WINDOWS
-
-	apr_dso_handle_t * eventhost_dso_handle = NULL;
-	apr_pool_t * eventhost_dso_memory_pool = NULL;
-
-	//attempt to load the shared library
-	apr_pool_create(&eventhost_dso_memory_pool, NULL);
-	apr_status_t rv = apr_dso_load(&eventhost_dso_handle,
-		dso_path.c_str(),
-		eventhost_dso_memory_pool);
-	llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
-	llassert_always(eventhost_dso_handle != NULL);
-
-	int (*ll_plugin_start_func)(LLSD const &) = NULL;
-	rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start");
-
-	llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
-	llassert_always(ll_plugin_start_func != NULL);
-
-	LLSD args;
-	args["listen_port"] = listen_port;
-
-	int status = ll_plugin_start_func(args);
-
-	if(status != 0)
-	{
-		llerrs << "problem loading eventhost plugin, status: " << status << llendl;
-	}
-
-	mPlugins.insert(eventhost_dso_handle);
-}
-
-void LLAppViewer::launchUpdater()
-{
-		LLSD query_map = LLSD::emptyMap();
-	// *TODO place os string in a global constant
-#if LL_WINDOWS  
-	query_map["os"] = "win";
-#elif LL_DARWIN
-	query_map["os"] = "mac";
-#elif LL_LINUX
-	query_map["os"] = "lnx";
-#elif LL_SOLARIS
-	query_map["os"] = "sol";
-#endif
-	// *TODO change userserver to be grid on both viewer and sim, since
-	// userserver no longer exists.
-	query_map["userserver"] = LLGridManager::getInstance()->getGridLabel();
-	query_map["channel"] = LLVersionInfo::getChannel();
-	// *TODO constantize this guy
-	// *NOTE: This URL is also used in win_setup/lldownloader.cpp
-	LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
-	
-	if(LLAppViewer::sUpdaterInfo)
-	{
-		delete LLAppViewer::sUpdaterInfo;
-	}
-	LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ;
-
-	// if a sim name was passed in via command line parameter (typically through a SLURL)
-	if ( LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION )
-	{
-		// record the location to start at next time
-		gSavedSettings.setString( "NextLoginLocation", LLStartUp::getStartSLURL().getSLURLString()); 
-	};
-
-#if LL_WINDOWS
-	LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename();
-	if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty())
-	{
-		delete LLAppViewer::sUpdaterInfo ;
-		LLAppViewer::sUpdaterInfo = NULL ;
-
-		// We're hosed, bail
-		LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL;
-		return;
-	}
-
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe";
-
-	std::string updater_source = gDirUtilp->getAppRODataDir();
-	updater_source += gDirUtilp->getDirDelimiter();
-	updater_source += "updater.exe";
-
-	LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source
-			<< " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath
-			<< LL_ENDL;
-
-
-	if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE))
-	{
-		delete LLAppViewer::sUpdaterInfo ;
-		LLAppViewer::sUpdaterInfo = NULL ;
-
-		LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL;
-
-		return;
-	}
-
-	LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\"";
-
-	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL;
-
-	//Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird.
-	LLAppViewer::instance()->removeMarkerFile(); // In case updater fails
-
-	// *NOTE:Mani The updater is spawned as the last thing before the WinMain exit.
-	// see LLAppViewerWin32.cpp
-	
-#elif LL_DARWIN
-	LLAppViewer::sUpdaterInfo->mUpdateExePath = "'";
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir();
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \"";
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString();
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \"";
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle();
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -bundleid \"";
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += LL_VERSION_BUNDLE_ID;
-	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &";
-
-	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
-
-	// Run the auto-updater.
-	system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */
-
-#elif (LL_LINUX || LL_SOLARIS) && LL_GTK
-	// we tell the updater where to find the xml containing string
-	// translations which it can use for its own UI
-	std::string xml_strings_file = "strings.xml";
-	std::vector<std::string> xui_path_vec = LLUI::getXUIPaths();
-	std::string xml_search_paths;
-	std::vector<std::string>::const_iterator iter;
-	// build comma-delimited list of xml paths to pass to updater
-	for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); )
-	{
-		std::string this_skin_dir = gDirUtilp->getDefaultSkinDir()
-			+ gDirUtilp->getDirDelimiter()
-			+ (*iter);
-		llinfos << "Got a XUI path: " << this_skin_dir << llendl;
-		xml_search_paths.append(this_skin_dir);
-		++iter;
-		if (iter != xui_path_vec.end())
-			xml_search_paths.append(","); // comma-delimit
-	}
-	// build the overall command-line to run the updater correctly
-	LLAppViewer::sUpdaterInfo->mUpdateExePath = 
-		gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + 
-		" --url \"" + update_url.asString() + "\"" +
-		" --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" +
-		" --dest \"" + gDirUtilp->getAppRODataDir() + "\"" +
-		" --stringsdir \"" + xml_search_paths + "\"" +
-		" --stringsfile \"" + xml_strings_file + "\"";
-
-	LL_INFOS("AppInit") << "Calling updater: " 
-			    << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
-
-	// *TODO: we could use the gdk equivalent to ensure the updater
-	// gets started on the same screen.
-	GError *error = NULL;
-	if (!g_spawn_command_line_async(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), &error))
-	{
-		llerrs << "Failed to launch updater: "
-		       << error->message
-		       << llendl;
-	}
-	if (error) {
-		g_error_free(error);
-	}
-#else
-	OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK);
-#endif
-
-	// *REMOVE:Mani - Saving for reference...
-	// LLAppViewer::instance()->forceQuit();
-}
-
-
-//virtual
-void LLAppViewer::setMasterSystemAudioMute(bool mute)
-{
-	gSavedSettings.setBOOL("MuteAudio", mute);
-}
-
-//virtual
-bool LLAppViewer::getMasterSystemAudioMute()
-{
-	return gSavedSettings.getBOOL("MuteAudio");
-}
-
-//----------------------------------------------------------------------------
-// Metrics-related methods (static and otherwise)
-//----------------------------------------------------------------------------
-
-/**
- * LLViewerAssetStats collects data on a per-region (as defined by the agent's
- * location) so we need to tell it about region changes which become a kind of
- * hidden variable/global state in the collectors.  For collectors not running
- * on the main thread, we need to send a message to move the data over safely
- * and cheaply (amortized over a run).
- */
-void LLAppViewer::metricsUpdateRegion(U64 region_handle)
-{
-	if (0 != region_handle)
-	{
-		LLViewerAssetStatsFF::set_region_main(region_handle);
-		if (LLAppViewer::sTextureFetch)
-		{
-			// Send a region update message into 'thread1' to get the new region.
-			LLAppViewer::sTextureFetch->commandSetRegion(region_handle);
-		}
-		else
-		{
-			// No 'thread1', a.k.a. TextureFetch, so update directly
-			LLViewerAssetStatsFF::set_region_thread1(region_handle);
-		}
-	}
-}
-
-
-/**
- * Attempts to start a multi-threaded metrics report to be sent back to
- * the grid for consumption.
- */
-void LLAppViewer::metricsSend(bool enable_reporting)
-{
-	if (! gViewerAssetStatsMain)
-		return;
-
-	if (LLAppViewer::sTextureFetch)
-	{
-		LLViewerRegion * regionp = gAgent.getRegion();
-
-		if (enable_reporting && regionp)
-		{
-			std::string	caps_url = regionp->getCapability("ViewerMetrics");
-
-			// Make a copy of the main stats to send into another thread.
-			// Receiving thread takes ownership.
-			LLViewerAssetStats * main_stats(new LLViewerAssetStats(*gViewerAssetStatsMain));
-			
-			// Send a report request into 'thread1' to get the rest of the data
-			// and provide some additional parameters while here.
-			LLAppViewer::sTextureFetch->commandSendMetrics(caps_url,
-														   gAgentSessionID,
-														   gAgentID,
-														   main_stats);
-			main_stats = 0;		// Ownership transferred
-		}
-		else
-		{
-			LLAppViewer::sTextureFetch->commandDataBreak();
-		}
-	}
-
-	// Reset even if we can't report.  Rather than gather up a huge chunk of
-	// data, we'll keep to our sampling interval and retain the data
-	// resolution in time.
-	gViewerAssetStatsMain->reset();
-}
-
+	/** 
+ * @file llappviewer.cpp
+ * @brief The LLAppViewer class definitions
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llappviewer.h"
+
+// Viewer includes
+#include "llversioninfo.h"
+#include "llversionviewer.h"
+#include "llfeaturemanager.h"
+#include "lluictrlfactory.h"
+#include "lltexteditor.h"
+#include "llerrorcontrol.h"
+#include "lleventtimer.h"
+#include "llviewertexturelist.h"
+#include "llgroupmgr.h"
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llagentlanguage.h"
+#include "llagentwearables.h"
+#include "llwindow.h"
+#include "llviewerstats.h"
+#include "llviewerstatsrecorder.h"
+#include "llmd5.h"
+#include "llpumpio.h"
+#include "llmimetypes.h"
+#include "llslurl.h"
+#include "llstartup.h"
+#include "llfocusmgr.h"
+#include "llviewerjoystick.h"
+#include "llallocator.h"
+#include "llares.h" 
+#include "llcurl.h"
+#include "lltexturestats.h"
+#include "lltexturestats.h"
+#include "llviewerwindow.h"
+#include "llviewerdisplay.h"
+#include "llviewermedia.h"
+#include "llviewerparcelmedia.h"
+#include "llviewermediafocus.h"
+#include "llviewermessage.h"
+#include "llviewerobjectlist.h"
+#include "llworldmap.h"
+#include "llmutelist.h"
+#include "llviewerhelp.h"
+#include "lluicolortable.h"
+#include "llurldispatcher.h"
+#include "llurlhistory.h"
+//#include "llfirstuse.h"
+#include "llrender.h"
+#include "llteleporthistory.h"
+#include "lllocationhistory.h"
+#include "llfasttimerview.h"
+#include "llvoicechannel.h"
+#include "llvoavatarself.h"
+#include "llsidetray.h"
+#include "llfeaturemanager.h"
+#include "llurlmatch.h"
+#include "lltextutil.h"
+#include "lllogininstance.h"
+#include "llprogressview.h"
+
+#include "llweb.h"
+#include "llsecondlifeurls.h"
+#include "llupdaterservice.h"
+
+// Linden library includes
+#include "llavatarnamecache.h"
+#include "llimagej2c.h"
+#include "llmemory.h"
+#include "llprimitive.h"
+#include "llurlaction.h"
+#include "llurlentry.h"
+#include "llvfile.h"
+#include "llvfsthread.h"
+#include "llvolumemgr.h"
+#include "llxfermanager.h"
+
+#include "llnotificationmanager.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+
+// Third party library includes
+#include <boost/bind.hpp>
+
+
+#if LL_WINDOWS
+#	include <share.h> // For _SH_DENYWR in initMarkerFile
+#else
+#   include <sys/file.h> // For initMarkerFile support
+#endif
+
+#include "llapr.h"
+#include "apr_dso.h"
+#include <boost/lexical_cast.hpp>
+
+#include "llviewerkeyboard.h"
+#include "lllfsthread.h"
+#include "llworkerthread.h"
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
+#include "llimageworker.h"
+#include "llevents.h"
+
+// The files below handle dependencies from cleanup.
+#include "llkeyframemotion.h"
+#include "llworldmap.h"
+#include "llhudmanager.h"
+#include "lltoolmgr.h"
+#include "llassetstorage.h"
+#include "llpolymesh.h"
+#include "llcachename.h"
+#include "llaudioengine.h"
+#include "llstreamingaudio.h"
+#include "llviewermenu.h"
+#include "llselectmgr.h"
+#include "lltrans.h"
+#include "lltransutil.h"
+#include "lltracker.h"
+#include "llviewerparcelmgr.h"
+#include "llworldmapview.h"
+#include "llpostprocess.h"
+#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
+
+#include "lldebugview.h"
+#include "llconsole.h"
+#include "llcontainerview.h"
+#include "lltooltip.h"
+
+#include "llsdserialize.h"
+
+#include "llworld.h"
+#include "llhudeffecttrail.h"
+#include "llvectorperfoptions.h"
+#include "llslurl.h"
+#include "llwatchdog.h"
+
+// Included so that constants/settings might be initialized
+// in save_settings_to_globals()
+#include "llbutton.h"
+#include "llstatusbar.h"
+#include "llsurface.h"
+#include "llvosky.h"
+#include "llvotree.h"
+#include "llvoavatar.h"
+#include "llfolderview.h"
+#include "llagentpilot.h"
+#include "llvovolume.h"
+#include "llflexibleobject.h" 
+#include "llvosurfacepatch.h"
+#include "llviewerfloaterreg.h"
+#include "llcommandlineparser.h"
+#include "llfloatermemleak.h"
+#include "llfloaterreg.h"
+#include "llfloatersnapshot.h"
+#include "llfloaterinventory.h"
+
+// includes for idle() idleShutdown()
+#include "llviewercontrol.h"
+#include "lleventnotifier.h"
+#include "llcallbacklist.h"
+#include "pipeline.h"
+#include "llgesturemgr.h"
+#include "llsky.h"
+#include "llvlmanager.h"
+#include "llviewercamera.h"
+#include "lldrawpoolbump.h"
+#include "llvieweraudio.h"
+#include "llimview.h"
+#include "llviewerthrottle.h"
+#include "llparcel.h"
+#include "llavatariconctrl.h"
+#include "llgroupiconctrl.h"
+#include "llviewerassetstats.h"
+
+// Include for security api initialization
+#include "llsecapi.h"
+#include "llmachineid.h"
+
+#include "llmainlooprepeater.h"
+
+// *FIX: These extern globals should be cleaned up.
+// The globals either represent state/config/resource-storage of either 
+// this app, or another 'component' of the viewer. App globals should be 
+// moved into the app class, where as the other globals should be 
+// moved out of here.
+// If a global symbol reference seems valid, it will be included
+// via header files above.
+
+//----------------------------------------------------------------------------
+// llviewernetwork.h
+#include "llviewernetwork.h"
+// define a self-registering event API object
+#include "llappviewerlistener.h"
+
+#if (LL_LINUX || LL_SOLARIS) && LL_GTK
+#include "glib.h"
+#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
+
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
+
+////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
+//
+//----------------------------------------------------------------------------
+// viewer.cpp - these are only used in viewer, should be easily moved.
+
+#if LL_DARWIN
+extern void init_apple_menu(const char* product);
+#endif // LL_DARWIN
+
+extern BOOL gRandomizeFramerate;
+extern BOOL gPeriodicSlowFrame;
+extern BOOL gDebugGL;
+
+////////////////////////////////////////////////////////////
+// All from the last globals push...
+const F32 DEFAULT_AFK_TIMEOUT = 5.f * 60.f; // time with no input before user flagged as Away From Keyboard
+
+F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
+F32 gSimFrames;
+
+BOOL gShowObjectUpdates = FALSE;
+BOOL gUseQuickTime = TRUE;
+
+eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL;
+
+LLSD gDebugInfo;
+
+U32	gFrameCount = 0;
+U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
+LLPumpIO* gServicePump = NULL;
+
+U64 gFrameTime = 0;
+F32 gFrameTimeSeconds = 0.f;
+F32 gFrameIntervalSeconds = 0.f;
+F32 gFPSClamped = 10.f;						// Pretend we start at target rate.
+F32 gFrameDTClamped = 0.f;					// Time between adjacent checks to network for packets
+U64	gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds
+U32 gFrameStalls = 0;
+const F64 FRAME_STALL_THRESHOLD = 1.0;
+
+LLTimer gRenderStartTime;
+LLFrameTimer gForegroundTime;
+LLFrameTimer gLoggedInTime;
+LLTimer gLogoutTimer;
+static const F32 LOGOUT_REQUEST_TIME = 6.f;  // this will be cut short by the LogoutReply msg.
+F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
+
+BOOL				gDisconnected = FALSE;
+
+// used to restore texture state after a mode switch
+LLFrameTimer	gRestoreGLTimer;
+BOOL			gRestoreGL = FALSE;
+BOOL				gUseWireframe = FALSE;
+
+// VFS globals - see llappviewer.h
+LLVFS* gStaticVFS = NULL;
+
+LLMemoryInfo gSysMemory;
+U64 gMemoryAllocated = 0; // updated in display_stats() in llviewerdisplay.cpp
+
+std::string gLastVersionChannel;
+
+LLVector3			gWindVec(3.0, 3.0, 0.0);
+LLVector3			gRelativeWindVec(0.0, 0.0, 0.0);
+
+U32		gPacketsIn = 0;
+
+BOOL				gPrintMessagesThisFrame = FALSE;
+
+BOOL gRandomizeFramerate = FALSE;
+BOOL gPeriodicSlowFrame = FALSE;
+
+BOOL gCrashOnStartup = FALSE;
+BOOL gLLErrorActivated = FALSE;
+BOOL gLogoutInProgress = FALSE;
+
+////////////////////////////////////////////////////////////
+// Internal globals... that should be removed.
+static std::string gArgs;
+
+const std::string MARKER_FILE_NAME("SecondLife.exec_marker");
+const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker");
+const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker");
+const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker");
+static BOOL gDoDisconnect = FALSE;
+static std::string gLaunchFileOnQuit;
+
+// Used on Win32 for other apps to identify our window (eg, win_setup)
+const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
+
+//----------------------------------------------------------------------------
+
+// List of entries from strings.xml to always replace
+static std::set<std::string> default_trans_args;
+void init_default_trans_args()
+{
+	default_trans_args.insert("SECOND_LIFE"); // World
+	default_trans_args.insert("APP_NAME");
+	default_trans_args.insert("CAPITALIZED_APP_NAME");
+	default_trans_args.insert("SECOND_LIFE_GRID");
+	default_trans_args.insert("SUPPORT_SITE");
+}
+
+//----------------------------------------------------------------------------
+// File scope definitons
+const char *VFS_DATA_FILE_BASE = "data.db2.x.";
+const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
+
+
+struct SettingsFile : public LLInitParam::Block<SettingsFile>
+{
+	Mandatory<std::string>	name;
+	Optional<std::string>	file_name;
+	Optional<bool>			required,
+							persistent;
+	Optional<std::string>	file_name_setting;
+
+	SettingsFile()
+	:	name("name"),
+		file_name("file_name"),
+		required("required", false),
+		persistent("persistent", true),
+		file_name_setting("file_name_setting")
+	{}
+};
+
+struct SettingsGroup : public LLInitParam::Block<SettingsGroup>
+{
+	Mandatory<std::string>	name;
+	Mandatory<S32>			path_index;
+	Multiple<SettingsFile>	files;
+
+	SettingsGroup()
+	:	name("name"),
+		path_index("path_index"),
+		files("file")
+	{}
+};
+
+struct SettingsFiles : public LLInitParam::Block<SettingsFiles>
+{
+	Multiple<SettingsGroup>	groups;
+
+	SettingsFiles()
+	: groups("group")
+	{}
+};
+
+static std::string gWindowTitle;
+
+LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;
+
+//----------------------------------------------------------------------------
+// Metrics logging control constants
+//----------------------------------------------------------------------------
+static const F32 METRICS_INTERVAL_DEFAULT = 600.0;
+static const F32 METRICS_INTERVAL_QA = 30.0;
+static F32 app_metrics_interval = METRICS_INTERVAL_DEFAULT;
+static bool app_metrics_qa_mode = false;
+
+void idle_afk_check()
+{
+	// check idle timers
+	if (gSavedSettings.getS32("AFKTimeout") && (gAwayTriggerTimer.getElapsedTimeF32() > gSavedSettings.getS32("AFKTimeout")))
+	{
+		gAgent.setAFK();
+	}
+}
+
+// A callback set in LLAppViewer::init()
+static void ui_audio_callback(const LLUUID& uuid)
+{
+	if (gAudiop)
+	{
+		gAudiop->triggerSound(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
+	}
+}
+
+bool	create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base)
+{
+	if(!match || !base || base->getPlainText())
+		return false;
+
+	LLUUID match_id = match->getID();
+
+	LLIconCtrl* icon;
+
+	if(gAgent.isInGroup(match_id, TRUE))
+	{
+		LLGroupIconCtrl::Params icon_params;
+		icon_params.group_id = match_id;
+		icon_params.rect = LLRect(0, 16, 16, 0);
+		icon_params.visible = true;
+		icon = LLUICtrlFactory::instance().create<LLGroupIconCtrl>(icon_params);
+	}
+	else
+	{
+		LLAvatarIconCtrl::Params icon_params;
+		icon_params.avatar_id = match_id;
+		icon_params.rect = LLRect(0, 16, 16, 0);
+		icon_params.visible = true;
+		icon = LLUICtrlFactory::instance().create<LLAvatarIconCtrl>(icon_params);
+	}
+
+	LLInlineViewSegment::Params params;
+	params.force_newline = false;
+	params.view = icon;
+	params.left_pad = 4;
+	params.right_pad = 4;
+	params.top_pad = -2;
+	params.bottom_pad = 2;
+
+	base->appendWidget(params," ",false);
+	
+	return true;
+}
+
+void request_initial_instant_messages()
+{
+	static BOOL requested = FALSE;
+	if (!requested
+		&& gMessageSystem
+		&& LLMuteList::getInstance()->isLoaded()
+		&& isAgentAvatarValid())
+	{
+		// Auto-accepted inventory items may require the avatar object
+		// to build a correct name.  Likewise, inventory offers from
+		// muted avatars require the mute list to properly mute.
+		LLMessageSystem* msg = gMessageSystem;
+		msg->newMessageFast(_PREHASH_RetrieveInstantMessages);
+		msg->nextBlockFast(_PREHASH_AgentData);
+		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		gAgent.sendReliableMessage();
+		requested = TRUE;
+	}
+}
+
+// A settings system callback for CrashSubmitBehavior
+bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue)
+{
+	S32 cb = newvalue.asInteger();
+	const S32 NEVER_SUBMIT_REPORT = 2;
+	if(cb == NEVER_SUBMIT_REPORT)
+	{
+		LLAppViewer::instance()->destroyMainloopTimeout();
+	}
+	return true;
+}
+
+// Use these strictly for things that are constructed at startup,
+// or for things that are performance critical.  JC
+static void settings_to_globals()
+{
+	LLBUTTON_H_PAD		= gSavedSettings.getS32("ButtonHPad");
+	BTN_HEIGHT_SMALL	= gSavedSettings.getS32("ButtonHeightSmall");
+	BTN_HEIGHT			= gSavedSettings.getS32("ButtonHeight");
+
+	MENU_BAR_HEIGHT		= gSavedSettings.getS32("MenuBarHeight");
+	MENU_BAR_WIDTH		= gSavedSettings.getS32("MenuBarWidth");
+
+	LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
+	
+	LLImageGL::sGlobalUseAnisotropic	= gSavedSettings.getBOOL("RenderAnisotropic");
+	LLVOVolume::sLODFactor				= gSavedSettings.getF32("RenderVolumeLODFactor");
+	LLVOVolume::sDistanceFactor			= 1.f-LLVOVolume::sLODFactor * 0.1f;
+	LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
+	LLVOTree::sTreeFactor				= gSavedSettings.getF32("RenderTreeLODFactor");
+	LLVOAvatar::sLODFactor				= gSavedSettings.getF32("RenderAvatarLODFactor");
+	LLVOAvatar::sMaxVisible				= (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
+	LLVOAvatar::sVisibleInFirstPerson	= gSavedSettings.getBOOL("FirstPersonAvatarVisible");
+	// clamp auto-open time to some minimum usable value
+	LLFolderView::sAutoOpenTime			= llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
+	LLSelectMgr::sRectSelectInclusive	= gSavedSettings.getBOOL("RectangleSelectInclusive");
+	LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
+	LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
+
+	gAgentPilot.mNumRuns		= gSavedSettings.getS32("StatsNumRuns");
+	gAgentPilot.mQuitAfterRuns	= gSavedSettings.getBOOL("StatsQuitAfterRuns");
+	gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
+
+	gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
+	gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
+	LLWorldMapView::sMapScale = gSavedSettings.getF32("MapScale");
+}
+
+static void settings_modify()
+{
+	LLRenderTarget::sUseFBO				= gSavedSettings.getBOOL("RenderUseFBO");
+	LLVOAvatar::sUseImpostors			= gSavedSettings.getBOOL("RenderUseImpostors");
+	LLVOSurfacePatch::sLODFactor		= gSavedSettings.getF32("RenderTerrainLODFactor");
+	LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
+	gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
+	gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
+	gAuditTexture = gSavedSettings.getBOOL("AuditTexture");
+#if LL_VECTORIZE
+	if (gSysCPU.hasAltivec())
+	{
+		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
+		gSavedSettings.setU32("VectorizeProcessor", 0 );
+	}
+	else
+	if (gSysCPU.hasSSE2())
+	{
+		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
+		gSavedSettings.setU32("VectorizeProcessor", 2 );
+	}
+	else
+	if (gSysCPU.hasSSE())
+	{
+		gSavedSettings.setBOOL("VectorizeEnable", TRUE );
+		gSavedSettings.setU32("VectorizeProcessor", 1 );
+	}
+	else
+	{
+		// Don't bother testing or running if CPU doesn't support it. JC
+		gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
+		gSavedSettings.setBOOL("VectorizeEnable", FALSE );
+		gSavedSettings.setU32("VectorizeProcessor", 0 );
+		gSavedSettings.setBOOL("VectorizeSkin", FALSE);
+	}
+#else
+	// This build target doesn't support SSE, don't test/run.
+	gSavedSettings.setBOOL("VectorizePerfTest", FALSE );
+	gSavedSettings.setBOOL("VectorizeEnable", FALSE );
+	gSavedSettings.setU32("VectorizeProcessor", 0 );
+	gSavedSettings.setBOOL("VectorizeSkin", FALSE);
+
+	// disable fullscreen mode, unsupported
+	gSavedSettings.setBOOL("WindowFullScreen", FALSE);
+#endif
+}
+
+class LLFastTimerLogThread : public LLThread
+{
+public:
+	std::string mFile;
+
+	LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
+	{
+		std::string file_name = test_name + std::string(".slp");
+		mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
+	}
+
+	void run()
+	{
+		std::ofstream os(mFile.c_str());
+		
+		while (!LLAppViewer::instance()->isQuitting())
+		{
+			LLFastTimer::writeLog(os);
+			os.flush();
+			ms_sleep(32);
+		}
+
+		os.close();
+	}
+
+};
+
+//virtual
+bool LLAppViewer::initSLURLHandler()
+{
+	// does nothing unless subclassed
+	return false;
+}
+
+//virtual
+bool LLAppViewer::sendURLToOtherInstance(const std::string& url)
+{
+	// does nothing unless subclassed
+	return false;
+}
+
+//----------------------------------------------------------------------------
+// LLAppViewer definition
+
+// Static members.
+// The single viewer app.
+LLAppViewer* LLAppViewer::sInstance = NULL;
+
+const std::string LLAppViewer::sGlobalSettingsName = "Global"; 
+
+LLTextureCache* LLAppViewer::sTextureCache = NULL; 
+LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; 
+LLTextureFetch* LLAppViewer::sTextureFetch = NULL; 
+
+LLAppViewer::LLAppViewer() : 
+	mMarkerFile(),
+	mLogoutMarkerFile(NULL),
+	mReportedCrash(false),
+	mNumSessions(0),
+	mPurgeCache(false),
+	mPurgeOnExit(false),
+	mSecondInstance(false),
+	mSavedFinalSnapshot(false),
+	mForceGraphicsDetail(false),
+	mQuitRequested(false),
+	mLogoutRequestSent(false),
+	mYieldTime(-1),
+	mMainloopTimeout(NULL),
+	mAgentRegionLastAlive(false),
+	mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
+	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
+	mFastTimerLogThread(NULL),
+	mUpdater(new LLUpdaterService()),
+	mSettingsLocationList(NULL)
+{
+	if(NULL != sInstance)
+	{
+		llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
+	}
+
+	setupErrorHandling();
+	sInstance = this;
+	gLoggedInTime.stop();
+	
+	LLLoginInstance::instance().setUpdaterService(mUpdater.get());
+}
+
+LLAppViewer::~LLAppViewer()
+{
+	delete mSettingsLocationList;
+
+	LLLoginInstance::instance().setUpdaterService(0);
+	
+	destroyMainloopTimeout();
+
+	// If we got to this destructor somehow, the app didn't hang.
+	removeMarkerFile();
+}
+
+bool LLAppViewer::init()
+{
+	//
+	// Start of the application
+	//
+	// IMPORTANT! Do NOT put anything that will write
+	// into the log files during normal startup until AFTER
+	// we run the "program crashed last time" error handler below.
+	//
+	LLFastTimer::reset();
+
+	// Need to do this initialization before we do anything else, since anything
+	// that touches files should really go through the lldir API
+	gDirUtilp->initAppDirs("SecondLife");
+	// set skin search path to default, will be overridden later
+	// this allows simple skinned file lookups to work
+	gDirUtilp->setSkinFolder("default");
+
+	initLogging();
+	
+	//
+	// OK to write stuff to logs now, we've now crash reported if necessary
+	//
+	
+	init_default_trans_args();
+	
+	if (!initConfiguration())
+		return false;
+
+	// write Google Breakpad minidump files to our log directory
+	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
+	logdir += gDirUtilp->getDirDelimiter();
+	setMiniDumpDir(logdir);
+
+	// Although initLogging() is the right place to mess with
+	// setFatalFunction(), we can't query gSavedSettings until after
+	// initConfiguration().
+	S32 rc(gSavedSettings.getS32("QAModeTermCode"));
+	if (rc >= 0)
+	{
+		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use _exit()
+		// rather than exit() because normal cleanup depends too much on
+		// successful startup!
+		LLError::setFatalFunction(boost::bind(_exit, rc));
+	}
+
+    mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
+
+#if LL_RECORD_VIEWER_STATS
+	LLViewerStatsRecorder::initClass();
+#endif
+
+    // *NOTE:Mani - LLCurl::initClass is not thread safe. 
+    // Called before threads are created.
+    LLCurl::initClass();
+    LLMachineID::init();
+	
+	{
+		// Viewer metrics initialization
+		static LLCachedControl<bool> metrics_submode(gSavedSettings,
+													 "QAModeMetrics",
+													 false,
+													 "Enables QA features (logging, faster cycling) for metrics collector");
+
+		if (metrics_submode)
+		{
+			app_metrics_qa_mode = true;
+			app_metrics_interval = METRICS_INTERVAL_QA;
+		}
+		LLViewerAssetStatsFF::init();
+	}
+
+    initThreads();
+    writeSystemInfo();
+
+	// Initialize updater service (now that we have an io pump)
+	initUpdater();
+	if(isQuitting())
+	{
+		// Early out here because updater set the quitting flag.
+		return true;
+	}
+
+	//////////////////////////////////////////////////////////////////////////////
+	//////////////////////////////////////////////////////////////////////////////
+	//////////////////////////////////////////////////////////////////////////////
+	//////////////////////////////////////////////////////////////////////////////
+	// *FIX: The following code isn't grouped into functions yet.
+
+	// Statistics / debug timer initialization
+	init_statistics();
+	
+	//
+	// Various introspection concerning the libs we're using - particularly
+        // the libs involved in getting to a full login screen.
+	//
+	LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
+	LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL;
+
+	// Get the single value from the crash settings file, if it exists
+	std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
+	gCrashSettings.loadFromFile(crash_settings_filename);
+	if(gSavedSettings.getBOOL("IgnoreAllNotifications"))
+	{
+		gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ALWAYS_SEND);
+		gCrashSettings.saveToFile(crash_settings_filename, FALSE);
+	}
+
+	/////////////////////////////////////////////////
+	// OS-specific login dialogs
+	/////////////////////////////////////////////////
+
+	//test_cached_control();
+
+	// track number of times that app has run
+	mNumSessions = gSavedSettings.getS32("NumSessions");
+	mNumSessions++;
+	gSavedSettings.setS32("NumSessions", mNumSessions);
+
+	if (gSavedSettings.getBOOL("VerboseLogs"))
+	{
+		LLError::setPrintLocation(true);
+	}
+	
+	// Widget construction depends on LLUI being initialized
+	LLUI::settings_map_t settings_map;
+	settings_map["config"] = &gSavedSettings;
+	settings_map["ignores"] = &gWarningSettings;
+	settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
+	settings_map["account"] = &gSavedPerAccountSettings;
+
+	LLUI::initClass(settings_map,
+		LLUIImageList::getInstance(),
+		ui_audio_callback,
+		&LLUI::sGLScaleFactor);
+	
+	// Setup paths and LLTrans after LLUI::initClass has been called
+	LLUI::setupPaths();
+	LLTransUtil::parseStrings("strings.xml", default_trans_args);		
+	LLTransUtil::parseLanguageStrings("language_settings.xml");
+	
+	// LLKeyboard relies on LLUI to know what some accelerator keys are called.
+	LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
+
+	LLWeb::initClass();			  // do this after LLUI
+	
+	// Provide the text fields with callbacks for opening Urls
+	LLUrlAction::setOpenURLCallback(&LLWeb::loadURL);
+	LLUrlAction::setOpenURLInternalCallback(&LLWeb::loadURLInternal);
+	LLUrlAction::setOpenURLExternalCallback(&LLWeb::loadURLExternal);
+	LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
+
+	// Let code in llui access the viewer help floater
+	LLUI::sHelpImpl = LLViewerHelp::getInstance();
+
+	// Load translations for tooltips
+	LLFloater::initClass();
+
+	/////////////////////////////////////////////////
+	
+	LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
+	
+	LLViewerFloaterReg::registerFloaters();
+	
+	/////////////////////////////////////////////////
+	//
+	// Load settings files
+	//
+	//
+	LLGroupMgr::parseRoleActions("role_actions.xml");
+
+	LLAgent::parseTeleportMessages("teleport_strings.xml");
+
+	LLViewerJointMesh::updateVectorize();
+
+	// load MIME type -> media impl mappings
+	std::string mime_types_name;
+#if LL_DARWIN
+	mime_types_name = "mime_types_mac.xml";
+#elif LL_LINUX
+	mime_types_name = "mime_types_linux.xml";
+#else
+	mime_types_name = "mime_types.xml";
+#endif
+	LLMIMETypes::parseMIMETypes( mime_types_name ); 
+
+	// Copy settings to globals. *TODO: Remove or move to appropriage class initializers
+	settings_to_globals();
+	// Setup settings listeners
+	settings_setup_listeners();
+	// Modify settings based on system configuration and compile options
+	settings_modify();
+
+	// Find partition serial number (Windows) or hardware serial (Mac)
+	mSerialNumber = generateSerialNumber();
+
+	// do any necessary set-up for accepting incoming SLURLs from apps
+	initSLURLHandler();
+
+	if(false == initHardwareTest())
+	{
+		// Early out from user choice.
+		return false;
+	}
+
+	// Prepare for out-of-memory situations, during which we will crash on
+	// purpose and save a dump.
+#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
+	MemSetErrorHandler(first_mem_error_handler);
+#endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP
+
+	// *Note: this is where gViewerStats used to be created.
+
+	//
+	// Initialize the VFS, and gracefully handle initialization errors
+	//
+
+	if (!initCache())
+	{
+		std::ostringstream msg;
+		msg << LLTrans::getString("MBUnableToAccessFile");
+		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
+		return 1;
+	}
+	
+	// Initialize the repeater service.
+	LLMainLoopRepeater::instance().start();
+	
+	//
+	// Initialize the window
+	//
+	gGLActive = TRUE;
+	initWindow();
+
+	// initWindow also initializes the Feature List, so now we can initialize this global.
+	LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
+
+	// call all self-registered classes
+	LLInitClassList::instance().fireCallbacks();
+
+	LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts
+		
+	gGLManager.getGLInfo(gDebugInfo);
+	gGLManager.printGLInfoString();
+
+	// Load Default bindings
+	std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
+														gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
+														gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+
+
+	if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
+	{
+		std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
+															gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
+															gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+		if (!gViewerKeyboard.loadBindings(key_bindings_file))
+		{
+			LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
+		}
+	}
+
+	// If we don't have the right GL requirements, exit.
+	if (!gGLManager.mHasRequirements && !gNoRender)
+	{	
+		// can't use an alert here since we're exiting and
+		// all hell breaks lose.
+		OSMessageBox(
+			LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"),
+			LLStringUtil::null,
+			OSMB_OK);
+		return 0;
+	}
+
+	// alert the user if they are using unsupported hardware
+	if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
+	{
+		bool unsupported = false;
+		LLSD args;
+		std::string minSpecs;
+		
+		// get cpu data from xml
+		std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount"));
+		S32 minCPU = 0;
+		minCPUString >> minCPU;
+
+		// get RAM data from XML
+		std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount"));
+		U64 minRAM = 0;
+		minRAMString >> minRAM;
+		minRAM = minRAM * 1024 * 1024;
+
+		if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
+		{
+			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
+			minSpecs += "\n";
+			unsupported = true;
+		}
+		if(gSysCPU.getMHz() < minCPU)
+		{
+			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
+			minSpecs += "\n";
+			unsupported = true;
+		}
+		if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
+		{
+			minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
+			minSpecs += "\n";
+			unsupported = true;
+		}
+
+		if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
+		{
+			LLNotificationsUtil::add("UnknownGPU");
+		} 
+			
+		if(unsupported)
+		{
+			if(!gSavedSettings.controlExists("WarnUnsupportedHardware") 
+				|| gSavedSettings.getBOOL("WarnUnsupportedHardware"))
+			{
+				args["MINSPECS"] = minSpecs;
+				LLNotificationsUtil::add("UnsupportedHardware", args );
+			}
+
+		}
+	}
+
+
+	// save the graphics card
+	gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
+
+	// Save the current version to the prefs file
+	gSavedSettings.setString("LastRunVersion", 
+							 LLVersionInfo::getChannelAndVersion());
+
+	gSimLastTime = gRenderStartTime.getElapsedTimeF32();
+	gSimFrames = (F32)gFrameCount;
+
+	LLViewerJoystick::getInstance()->init(false);
+
+	try {
+		initializeSecHandler();
+	}
+	catch (LLProtectedDataException ex)
+	{
+	  LLNotificationsUtil::add("CorruptedProtectedDataStore");
+	}
+	LLHTTPClient::setCertVerifyCallback(secapiSSLCertVerifyCallback);
+
+
+	gGLActive = FALSE;
+	if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
+	{
+		loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort"));
+	}
+	
+	LLViewerMedia::initClass();
+	LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
+
+	//EXT-7013 - On windows for some locale (Japanese) standard 
+	//datetime formatting functions didn't support some parameters such as "weekday".
+	//Names for days and months localized in xml are also useful for Polish locale(STORM-107).
+	std::string language = LLControlGroup::getInstance(sGlobalSettingsName)->getString("Language");
+	if(language == "ja" || language == "pl")
+	{
+		LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames"));
+		LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames"));
+		LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames"));
+		LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames"));
+		LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat"));
+
+		LLStringOps::sAM = LLTrans::getString("dateTimeAM");
+		LLStringOps::sPM = LLTrans::getString("dateTimePM");
+	}
+
+	LLAgentLanguage::init();
+
+
+
+	return true;
+}
+
+static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");
+static LLFastTimer::DeclareTimer FTM_SLEEP("Sleep");
+static LLFastTimer::DeclareTimer FTM_TEXTURE_CACHE("Texture Cache");
+static LLFastTimer::DeclareTimer FTM_DECODE("Image Decode");
+static LLFastTimer::DeclareTimer FTM_VFS("VFS Thread");
+static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread");
+static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads");
+static LLFastTimer::DeclareTimer FTM_IDLE("Idle");
+static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
+static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares");
+static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service");
+static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback");
+static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot");
+static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update");
+
+bool LLAppViewer::mainLoop()
+{
+	LLMemType mt1(LLMemType::MTYPE_MAIN);
+	mMainloopTimeout = new LLWatchdogTimeout();
+	
+	//-------------------------------------------
+	// Run main loop until time to quit
+	//-------------------------------------------
+
+	// Create IO Pump to use for HTTP Requests.
+	gServicePump = new LLPumpIO(gAPRPoolp);
+	LLHTTPClient::setPump(*gServicePump);
+	LLCurl::setCAFile(gDirUtilp->getCAFile());
+	
+	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
+
+	LLVoiceChannel::initClass();
+	LLVoiceClient::getInstance()->init(gServicePump);
+	LLTimer frameTimer,idleTimer;
+	LLTimer debugTime;
+	LLFrameTimer memCheckTimer;
+	LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
+	joystick->setNeedsReset(true);
+
+    LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+    // As we do not (yet) send data on the mainloop LLEventPump that varies
+    // with each frame, no need to instantiate a new LLSD event object each
+    // time. Obviously, if that changes, just instantiate the LLSD at the
+    // point of posting.
+    LLSD newFrame;
+
+	const F32 memory_check_interval = 1.0f ; //second
+
+	// Handle messages
+	while (!LLApp::isExiting())
+	{
+		LLFastTimer::nextFrame(); // Should be outside of any timer instances
+
+		//clear call stack records
+		llclearcallstacks;
+
+		//check memory availability information
+		{
+			if(memory_check_interval < memCheckTimer.getElapsedTimeF32())
+			{
+				memCheckTimer.reset() ;
+
+				//update the availability of memory
+				LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
+			}
+			llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ;
+			llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ;
+		}
+
+		try
+		{
+			pingMainloopTimeout("Main:MiscNativeWindowEvents");
+
+			if (gViewerWindow)
+			{
+				LLFastTimer t2(FTM_MESSAGES);
+				gViewerWindow->mWindow->processMiscNativeEvents();
+			}
+		
+			pingMainloopTimeout("Main:GatherInput");
+			
+			if (gViewerWindow)
+			{
+				LLFastTimer t2(FTM_MESSAGES);
+				if (!restoreErrorTrap())
+				{
+					llwarns << " Someone took over my signal/exception handler (post messagehandling)!" << llendl;
+				}
+
+				gViewerWindow->mWindow->gatherInput();
+			}
+
+#if 1 && !LL_RELEASE_FOR_DOWNLOAD
+			// once per second debug info
+			if (debugTime.getElapsedTimeF32() > 1.f)
+			{
+				debugTime.reset();
+			}
+			
+#endif
+			//memory leaking simulation
+			LLFloaterMemLeak* mem_leak_instance =
+				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+			if(mem_leak_instance)
+			{
+				mem_leak_instance->idle() ;				
+			}			
+
+            // canonical per-frame event
+            mainloop.post(newFrame);
+
+			if (!LLApp::isExiting())
+			{
+				pingMainloopTimeout("Main:JoystickKeyboard");
+				
+				// Scan keyboard for movement keys.  Command keys and typing
+				// are handled by windows callbacks.  Don't do this until we're
+				// done initializing.  JC
+				if (gViewerWindow->mWindow->getVisible() 
+					&& gViewerWindow->getActive()
+					&& !gViewerWindow->mWindow->getMinimized()
+					&& LLStartUp::getStartupState() == STATE_STARTED
+					&& !gViewerWindow->getShowProgress()
+					&& !gFocusMgr.focusLocked())
+				{
+					LLMemType mjk(LLMemType::MTYPE_JOY_KEY);
+					joystick->scanJoystick();
+					gKeyboard->scanKeyboard();
+				}
+
+				// Update state based on messages, user input, object idle.
+				{
+					pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
+					
+					LLFastTimer t3(FTM_IDLE);
+					idle();
+
+					if (gAres != NULL && gAres->isInitialized())
+					{
+						LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP);
+						pingMainloopTimeout("Main:ServicePump");				
+						LLFastTimer t4(FTM_PUMP);
+						{
+							LLFastTimer t(FTM_PUMP_ARES);
+							gAres->process();
+						}
+						{
+							LLFastTimer t(FTM_PUMP_SERVICE);
+							// this pump is necessary to make the login screen show up
+							gServicePump->pump();
+
+							{
+								LLFastTimer t(FTM_SERVICE_CALLBACK);
+								gServicePump->callback();
+							}
+						}
+					}
+					
+					resumeMainloopTimeout();
+				}
+ 
+				if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
+				{
+					pauseMainloopTimeout();
+					saveFinalSnapshot();
+					disconnectViewer();
+					resumeMainloopTimeout();
+				}
+
+				// Render scene.
+				if (!LLApp::isExiting())
+				{
+					pingMainloopTimeout("Main:Display");
+					gGLActive = TRUE;
+					display();
+					pingMainloopTimeout("Main:Snapshot");
+					LLFloaterSnapshot::update(); // take snapshots
+					gGLActive = FALSE;
+				}
+
+			}
+
+			pingMainloopTimeout("Main:Sleep");
+			
+			pauseMainloopTimeout();
+
+			// Sleep and run background threads
+			{
+				LLMemType mt_sleep(LLMemType::MTYPE_SLEEP);
+				LLFastTimer t2(FTM_SLEEP);
+				
+				// yield some time to the os based on command line option
+				if(mYieldTime >= 0)
+				{
+					ms_sleep(mYieldTime);
+				}
+
+				// yield cooperatively when not running as foreground window
+				if (   gNoRender
+					   || (gViewerWindow && !gViewerWindow->mWindow->getVisible())
+						|| !gFocusMgr.getAppHasFocus())
+				{
+					// Sleep if we're not rendering, or the window is minimized.
+					S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000);
+					// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads
+					// of equal priority on Windows
+					if (milliseconds_to_sleep > 0)
+					{
+						ms_sleep(milliseconds_to_sleep);
+						// also pause worker threads during this wait period
+						LLAppViewer::getTextureCache()->pause();
+						LLAppViewer::getImageDecodeThread()->pause();
+					}
+				}
+				
+				if (mRandomizeFramerate)
+				{
+					ms_sleep(rand() % 200);
+				}
+
+				if (mPeriodicSlowFrame
+					&& (gFrameCount % 10 == 0))
+				{
+					llinfos << "Periodic slow frame - sleeping 500 ms" << llendl;
+					ms_sleep(500);
+				}
+
+				static const F64 FRAME_SLOW_THRESHOLD = 0.5; //2 frames per seconds				
+				const F64 max_idle_time = llmin(.005*10.0*gFrameTimeSeconds, 0.005); // 5 ms a second
+				idleTimer.reset();
+				bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ;
+				S32 total_work_pending = 0;
+				S32 total_io_pending = 0;				
+				while(!is_slow)//do not unpause threads if the frame rates are very low.
+				{
+					S32 work_pending = 0;
+					S32 io_pending = 0;
+					{
+						LLFastTimer ftm(FTM_TEXTURE_CACHE);
+ 						work_pending += LLAppViewer::getTextureCache()->update(1); // unpauses the texture cache thread
+					}
+					{
+						LLFastTimer ftm(FTM_DECODE);
+	 					work_pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
+					}
+					{
+						LLFastTimer ftm(FTM_DECODE);
+	 					work_pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+					}
+
+					{
+						LLFastTimer ftm(FTM_VFS);
+	 					io_pending += LLVFSThread::updateClass(1);
+					}
+					{
+						LLFastTimer ftm(FTM_LFS);
+	 					io_pending += LLLFSThread::updateClass(1);
+					}
+
+					if (io_pending > 1000)
+					{
+						ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
+					}
+
+					total_work_pending += work_pending ;
+					total_io_pending += io_pending ;
+					
+					if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)
+					{
+						break;
+					}
+				}
+
+				if(!total_work_pending) //pause texture fetching threads if nothing to process.
+				{
+					LLAppViewer::getTextureCache()->pause();
+					LLAppViewer::getImageDecodeThread()->pause();
+					LLAppViewer::getTextureFetch()->pause(); 
+				}
+				if(!total_io_pending) //pause file threads if nothing to process.
+				{
+					LLVFSThread::sLocal->pause(); 
+					LLLFSThread::sLocal->pause(); 
+				}									
+
+				if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
+					(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
+				{
+					gFrameStalls++;
+				}
+				frameTimer.reset();
+
+				resumeMainloopTimeout();
+	
+				pingMainloopTimeout("Main:End");
+			}	
+		}
+		catch(std::bad_alloc)
+		{			
+			{
+				llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ;
+				llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ;
+
+				LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
+
+				llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ;
+				llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ;
+			}
+
+			//stop memory leaking simulation
+			LLFloaterMemLeak* mem_leak_instance =
+				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+			if(mem_leak_instance)
+			{
+				mem_leak_instance->stop() ;				
+				llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
+			}
+			else
+			{
+				//output possible call stacks to log file.
+				LLError::LLCallStacks::print() ;
+
+				llerrs << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
+			}
+		}
+	}
+
+	// Save snapshot for next time, if we made it through initialization
+	if (STATE_STARTED == LLStartUp::getStartupState())
+	{
+		try
+		{
+			saveFinalSnapshot();
+		}
+		catch(std::bad_alloc)
+		{
+			llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
+
+			//stop memory leaking simulation
+			LLFloaterMemLeak* mem_leak_instance =
+				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
+			if(mem_leak_instance)
+			{
+				mem_leak_instance->stop() ;				
+			}	
+		}
+	}
+	
+	delete gServicePump;
+
+	destroyMainloopTimeout();
+
+	llinfos << "Exiting main_loop" << llendflush;
+
+	return true;
+}
+
+void LLAppViewer::flushVFSIO()
+{
+	while (1)
+	{
+		S32 pending = LLVFSThread::updateClass(0);
+		pending += LLLFSThread::updateClass(0);
+		if (!pending)
+		{
+			break;
+		}
+		llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
+		ms_sleep(100);
+	}
+}
+
+bool LLAppViewer::cleanup()
+{
+	// workaround for DEV-35406 crash on shutdown
+	LLEventPumps::instance().reset();
+
+	// remove any old breakpad minidump files from the log directory
+	if (! isError())
+	{
+		std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
+		logdir += gDirUtilp->getDirDelimiter();
+		gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
+	}
+
+	// *TODO - generalize this and move DSO wrangling to a helper class -brad
+	std::set<struct apr_dso_handle_t *>::const_iterator i;
+	for(i = mPlugins.begin(); i != mPlugins.end(); ++i)
+	{
+		int (*ll_plugin_stop_func)(void) = NULL;
+		apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop");
+		ll_plugin_stop_func();
+
+		rv = apr_dso_unload(*i);
+	}
+	mPlugins.clear();
+
+	//flag all elements as needing to be destroyed immediately
+	// to ensure shutdown order
+	LLMortician::setZealous(TRUE);
+
+	LLVoiceClient::getInstance()->terminate();
+	
+	disconnectViewer();
+
+	llinfos << "Viewer disconnected" << llendflush;
+
+	display_cleanup(); 
+
+	release_start_screen(); // just in case
+
+	LLError::logToFixedBuffer(NULL);
+
+	llinfos << "Cleaning Up" << llendflush;
+
+	// Must clean up texture references before viewer window is destroyed.
+	if(LLHUDManager::instanceExists())
+	{
+		LLHUDManager::getInstance()->updateEffects();
+		LLHUDObject::updateAll();
+		LLHUDManager::getInstance()->cleanupEffects();
+		LLHUDObject::cleanupHUDObjects();
+		llinfos << "HUD Objects cleaned up" << llendflush;
+	}
+
+	LLKeyframeDataCache::clear();
+	
+ 	// End TransferManager before deleting systems it depends on (Audio, VFS, AssetStorage)
+#if 0 // this seems to get us stuck in an infinite loop...
+	gTransferManager.cleanup();
+#endif
+	
+	// Note: this is where gWorldMap used to be deleted.
+
+	// Note: this is where gHUDManager used to be deleted.
+	if(LLHUDManager::instanceExists())
+	{
+		LLHUDManager::getInstance()->shutdownClass();
+	}
+
+	delete gAssetStorage;
+	gAssetStorage = NULL;
+
+	LLPolyMesh::freeAllMeshes();
+
+	LLStartUp::cleanupNameCache();
+
+	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
+
+	LLWorldMap::getInstance()->reset(); // release any images
+	
+	llinfos << "Global stuff deleted" << llendflush;
+
+	if (gAudiop)
+	{
+		// shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
+
+		LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
+		delete sai;
+		gAudiop->setStreamingAudioImpl(NULL);
+
+		// shut down the audio subsystem
+
+		bool want_longname = false;
+		if (gAudiop->getDriverName(want_longname) == "FMOD")
+		{
+			// This hack exists because fmod likes to occasionally
+			// crash or hang forever when shutting down, for no
+			// apparent reason.
+			llwarns << "Hack, skipping FMOD audio engine cleanup" << llendflush;
+		}
+		else
+		{
+			gAudiop->shutdown();
+		}
+
+		delete gAudiop;
+		gAudiop = NULL;
+	}
+
+	// Note: this is where LLFeatureManager::getInstance()-> used to be deleted.
+
+	// Patch up settings for next time
+	// Must do this before we delete the viewer window,
+	// such that we can suck rectangle information out of
+	// it.
+	cleanupSavedSettings();
+	llinfos << "Settings patched up" << llendflush;
+
+	// delete some of the files left around in the cache.
+	removeCacheFiles("*.wav");
+	removeCacheFiles("*.tmp");
+	removeCacheFiles("*.lso");
+	removeCacheFiles("*.out");
+	removeCacheFiles("*.dsf");
+	removeCacheFiles("*.bodypart");
+	removeCacheFiles("*.clothing");
+
+	llinfos << "Cache files removed" << llendflush;
+
+	// Wait for any pending VFS IO
+	flushVFSIO();
+	llinfos << "Shutting down Views" << llendflush;
+
+	// Destroy the UI
+	if( gViewerWindow)
+		gViewerWindow->shutdownViews();
+
+	llinfos << "Cleaning up Inventory" << llendflush;
+	
+	// Cleanup Inventory after the UI since it will delete any remaining observers
+	// (Deleted observers should have already removed themselves)
+	gInventory.cleanupInventory();
+
+	llinfos << "Cleaning up Selections" << llendflush;
+	
+	// Clean up selection managers after UI is destroyed, as UI may be observing them.
+	// Clean up before GL is shut down because we might be holding on to objects with texture references
+	LLSelectMgr::cleanupGlobals();
+	
+	llinfos << "Shutting down OpenGL" << llendflush;
+
+	// Shut down OpenGL
+	if( gViewerWindow)
+	{
+		gViewerWindow->shutdownGL();
+	
+		// Destroy window, and make sure we're not fullscreen
+		// This may generate window reshape and activation events.
+		// Therefore must do this before destroying the message system.
+		delete gViewerWindow;
+		gViewerWindow = NULL;
+		llinfos << "ViewerWindow deleted" << llendflush;
+	}
+
+	llinfos << "Cleaning up Keyboard & Joystick" << llendflush;
+	
+	// viewer UI relies on keyboard so keep it aound until viewer UI isa gone
+	delete gKeyboard;
+	gKeyboard = NULL;
+
+	// Turn off Space Navigator and similar devices
+	LLViewerJoystick::getInstance()->terminate();
+	
+	llinfos << "Cleaning up Objects" << llendflush;
+	
+	LLViewerObject::cleanupVOClasses();
+
+	LLWaterParamManager::cleanupClass();
+	LLWLParamManager::cleanupClass();
+	LLPostProcess::cleanupClass();
+
+	LLTracker::cleanupInstance();
+	
+	// *FIX: This is handled in LLAppViewerWin32::cleanup().
+	// I'm keeping the comment to remember its order in cleanup,
+	// in case of unforseen dependency.
+	//#if LL_WINDOWS
+	//	gDXHardware.cleanup();
+	//#endif // LL_WINDOWS
+
+	LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager();
+	if (!volume_manager->cleanup())
+	{
+		llwarns << "Remaining references in the volume manager!" << llendflush;
+	}
+	LLPrimitive::cleanupVolumeManager();
+
+	llinfos << "Additional Cleanup..." << llendflush;	
+	
+	LLViewerParcelMgr::cleanupGlobals();
+
+	// *Note: this is where gViewerStats used to be deleted.
+
+ 	//end_messaging_system();
+
+	LLFollowCamMgr::cleanupClass();
+	//LLVolumeMgr::cleanupClass();
+	LLPrimitive::cleanupVolumeManager();
+	LLWorldMapView::cleanupClass();
+	LLFolderViewItem::cleanupClass();
+	LLUI::cleanupClass();
+	
+	//
+	// Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles).
+	// Also after viewerwindow is deleted, since it may have image pointers (which have vfiles)
+	// Also after shutting down the messaging system since it has VFS dependencies
+
+	//
+	llinfos << "Cleaning up VFS" << llendflush;
+	LLVFile::cleanupClass();
+
+	llinfos << "Saving Data" << llendflush;
+	
+	// Store the time of our current logoff
+	gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
+
+	// Must do this after all panels have been deleted because panels that have persistent rects
+	// save their rects on delete.
+	gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
+	
+	LLUIColorTable::instance().saveUserSettings();
+
+	// PerAccountSettingsFile should be empty if no user has been logged on.
+	// *FIX:Mani This should get really saved in a "logoff" mode. 
+	if (gSavedSettings.getString("PerAccountSettingsFile").empty())
+	{
+		llinfos << "Not saving per-account settings; don't know the account name yet." << llendl;
+	}
+	else
+	{
+		gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
+		llinfos << "Saved settings" << llendflush;
+	}
+
+	std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
+	// save all settings, even if equals defaults
+	gCrashSettings.saveToFile(crash_settings_filename, FALSE);
+
+	std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings"));
+	gWarningSettings.saveToFile(warnings_settings_filename, TRUE);
+
+	// Save URL history file
+	LLURLHistory::saveFile("url_history.xml");
+
+	// save mute list. gMuteList used to also be deleted here too.
+	LLMuteList::getInstance()->cache(gAgent.getID());
+
+	if (mPurgeOnExit)
+	{
+		llinfos << "Purging all cache files on exit" << llendflush;
+		std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
+		gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
+	}
+
+	removeMarkerFile(); // Any crashes from here on we'll just have to ignore
+	
+	writeDebugInfo();
+
+	LLLocationHistory::getInstance()->save();
+
+	LLAvatarIconIDCache::getInstance()->save();
+	
+	LLViewerMedia::saveCookieFile();
+
+	// Stop the plugin read thread if it's running.
+	LLPluginProcessParent::setUseReadThread(false);
+
+	llinfos << "Shutting down Threads" << llendflush;
+
+	// Let threads finish
+	LLTimer idleTimer;
+	idleTimer.reset();
+	const F64 max_idle_time = 5.f; // 5 seconds
+	while(1)
+	{
+		S32 pending = 0;
+		pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread
+		pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
+		pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+		pending += LLVFSThread::updateClass(0);
+		pending += LLLFSThread::updateClass(0);
+		F64 idle_time = idleTimer.getElapsedTimeF64();
+		if(!pending)
+		{
+			break ; //done
+		}
+		else if(idle_time >= max_idle_time)
+		{
+			llwarns << "Quitting with pending background tasks." << llendl;
+			break;
+		}
+	}
+
+	// Delete workers first
+	// shotdown all worker threads before deleting them in case of co-dependencies
+	sTextureFetch->shutdown();
+	sTextureCache->shutdown();	
+	sImageDecodeThread->shutdown();
+	
+	sTextureFetch->shutDownTextureCacheThread() ;
+	sTextureFetch->shutDownImageDecodeThread() ;
+
+	delete sTextureCache;
+    sTextureCache = NULL;
+	delete sTextureFetch;
+    sTextureFetch = NULL;
+	delete sImageDecodeThread;
+    sImageDecodeThread = NULL;
+	delete mFastTimerLogThread;
+	mFastTimerLogThread = NULL;
+	
+	if (LLFastTimerView::sAnalyzePerformance)
+	{
+		llinfos << "Analyzing performance" << llendl;
+		
+		std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
+		std::string current_name  = LLFastTimer::sLogName + ".slp"; 
+		std::string report_name   = LLFastTimer::sLogName + "_report.csv";
+
+		LLFastTimerView::doAnalysis(
+			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
+			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
+			gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
+	}
+	LLMetricPerformanceTesterBasic::cleanClass() ;
+
+#if LL_RECORD_VIEWER_STATS
+	LLViewerStatsRecorder::cleanupClass();
+#endif
+
+	llinfos << "Cleaning up Media and Textures" << llendflush;
+
+	//Note:
+	//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
+	//because some new image might be generated during cleaning up media. --bao
+	LLViewerMedia::cleanupClass();
+	LLViewerParcelMedia::cleanupClass();
+	gTextureList.shutdown(); // shutdown again in case a callback added something
+	LLUIImageList::getInstance()->cleanUp();
+	
+	// This should eventually be done in LLAppViewer
+	LLImage::cleanupClass();
+	LLVFSThread::cleanupClass();
+	LLLFSThread::cleanupClass();
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	llinfos << "Auditing VFS" << llendl;
+	if(gVFS)
+	{
+		gVFS->audit();
+	}
+#endif
+
+	llinfos << "Misc Cleanup" << llendflush;
+	
+	// For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up.
+	// (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve
+	delete gStaticVFS;
+	gStaticVFS = NULL;
+	delete gVFS;
+	gVFS = NULL;
+	
+	gSavedSettings.cleanup();
+	LLUIColorTable::instance().clear();
+	gCrashSettings.cleanup();
+
+	LLWatchdog::getInstance()->cleanup();
+
+	LLViewerAssetStatsFF::cleanup();
+	
+	llinfos << "Shutting down message system" << llendflush;
+	end_messaging_system();
+
+	// *NOTE:Mani - The following call is not thread safe. 
+	LLCurl::cleanupClass();
+
+	// If we're exiting to launch an URL, do that here so the screen
+	// is at the right resolution before we launch IE.
+	if (!gLaunchFileOnQuit.empty())
+	{
+		llinfos << "Launch file on quit." << llendflush;
+#if LL_WINDOWS
+		// Indicate an application is starting.
+		SetCursor(LoadCursor(NULL, IDC_WAIT));
+#endif
+
+		// HACK: Attempt to wait until the screen res. switch is complete.
+		ms_sleep(1000);
+
+		LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
+		llinfos << "File launched." << llendflush;
+	}
+
+	LLMainLoopRepeater::instance().stop();
+
+	ll_close_fail_log();
+
+	MEM_TRACK_RELEASE
+
+    llinfos << "Goodbye!" << llendflush;
+
+	// return 0;
+	return true;
+}
+
+// A callback for llerrs to call during the watchdog error.
+void watchdog_llerrs_callback(const std::string &error_string)
+{
+	gLLErrorActivated = true;
+
+#ifdef LL_WINDOWS
+	RaiseException(0,0,0,0);
+#else
+	raise(SIGQUIT);
+#endif
+}
+
+// A callback for the watchdog to call.
+void watchdog_killer_callback()
+{
+	LLError::setFatalFunction(watchdog_llerrs_callback);
+	llerrs << "Watchdog killer event" << llendl;
+}
+
+bool LLAppViewer::initThreads()
+{
+#if MEM_TRACK_MEM
+	static const bool enable_threads = false;
+#else
+	static const bool enable_threads = true;
+#endif
+
+	LLVFSThread::initClass(enable_threads && false);
+	LLLFSThread::initClass(enable_threads && false);
+
+	// Image decoding
+	LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
+	LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
+	LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(),
+													sImageDecodeThread,
+													enable_threads && true,
+													app_metrics_qa_mode);
+	LLImage::initClass();
+
+	if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
+	{
+		LLFastTimer::sLogLock = new LLMutex(NULL);
+		mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName);
+		mFastTimerLogThread->start();
+	}
+
+	// *FIX: no error handling here!
+	return true;
+}
+
+void errorCallback(const std::string &error_string)
+{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
+#endif
+
+	//Set the ErrorActivated global so we know to create a marker file
+	gLLErrorActivated = true;
+	
+	LLError::crashAndLoop(error_string);
+}
+
+bool LLAppViewer::initLogging()
+{
+	//
+	// Set up logging defaults for the viewer
+	//
+	LLError::initForApplication(
+				gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
+	LLError::setFatalFunction(errorCallback);
+
+	// Remove the last ".old" log file.
+	std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+							     "SecondLife.old");
+	LLFile::remove(old_log_file);
+
+	// Rename current log file to ".old"
+	std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+							     "SecondLife.log");
+	LLFile::rename(log_file, old_log_file);
+
+	// Set the log file to SecondLife.log
+
+	LLError::logToFile(log_file);
+
+	// *FIX:Mani no error handling here!
+	return true;
+}
+
+bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
+					    bool set_defaults)
+{	
+	if (!mSettingsLocationList)
+	{
+		llerrs << "Invalid settings location list" << llendl;
+	}
+
+	LLControlGroup* global_settings = LLControlGroup::getInstance(sGlobalSettingsName);  
+	for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
+		it != end_it;
+		++it)
+	{
+		// skip settings groups that aren't the one we requested
+		if (it->name() != location_key) continue;
+
+		ELLPath path_index = (ELLPath)it->path_index();
+		if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST)
+		{
+			llerrs << "Out of range path index in app_settings/settings_files.xml" << llendl;
+			return false;
+		}
+
+		LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
+		for (file_it = it->files.begin(), end_file_it = it->files.end();
+			file_it != end_file_it;
+			++file_it)
+		{
+			llinfos << "Attempting to load settings for the group " << file_it->name()
+			    << " - from location " << location_key << llendl;
+
+			LLControlGroup* settings_group = LLControlGroup::getInstance(file_it->name);
+			if(!settings_group)
+			{
+				llwarns << "No matching settings group for name " << file_it->name() << llendl;
+				continue;
+			}
+
+			std::string full_settings_path;
+
+			if (file_it->file_name_setting.isProvided() 
+				&& global_settings->controlExists(file_it->file_name_setting))
+			{
+				// try to find filename stored in file_name_setting control
+				full_settings_path = global_settings->getString(file_it->file_name_setting);
+				if (!gDirUtilp->fileExists(full_settings_path))
+				{
+					// search in default path
+					full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path);
+				}
+			}
+			else
+			{
+				// by default, use specified file name
+				full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file_it->file_name());
+			}
+
+			if(settings_group->loadFromFile(full_settings_path, set_defaults, file_it->persistent))
+			{	// success!
+				llinfos << "Loaded settings file " << full_settings_path << llendl;
+			}
+			else
+			{	// failed to load
+				if(file_it->required)
+				{
+					llerrs << "Error: Cannot load required settings file from: " << full_settings_path << llendl;
+					return false;
+				}
+				else
+				{
+					// only complain if we actually have a filename at this point
+					if (!full_settings_path.empty())
+					{
+						llinfos << "Cannot load " << full_settings_path << " - No settings found." << llendl;
+					}
+				}
+			}
+		}
+	}
+
+	return true;
+}
+
+std::string LLAppViewer::getSettingsFilename(const std::string& location_key,
+											 const std::string& file)
+{
+	for(LLInitParam::ParamIterator<SettingsGroup>::const_iterator it = mSettingsLocationList->groups.begin(), end_it = mSettingsLocationList->groups.end();
+		it != end_it;
+		++it)
+	{
+		if (it->name() == location_key)
+		{
+			LLInitParam::ParamIterator<SettingsFile>::const_iterator file_it, end_file_it;
+			for (file_it = it->files.begin(), end_file_it = it->files.end();
+				file_it != end_file_it;
+				++file_it)
+			{
+				if (file_it->name() == file)
+				{
+					return file_it->file_name;
+				}
+			}
+		}
+	}
+
+	return std::string();
+}
+
+void LLAppViewer::loadColorSettings()
+{
+	LLUIColorTable::instance().loadFromSettings();
+}
+
+bool LLAppViewer::initConfiguration()
+{	
+	//Load settings files list
+	std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml");
+	//LLControlGroup settings_control("SettingsFiles");
+	//llinfos << "Loading settings file list " << settings_file_list << llendl;
+	//if (0 == settings_control.loadFromFile(settings_file_list))
+	//{
+ //       llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
+	//}
+
+	LLXMLNodePtr root;
+	BOOL success  = LLXMLNode::parseFile(settings_file_list, root, NULL);
+	if (!success)
+	{
+        llerrs << "Cannot load default configuration file " << settings_file_list << llendl;
+	}
+
+	mSettingsLocationList = new SettingsFiles();
+
+	LLXUIParser parser;
+	parser.readXUI(root, *mSettingsLocationList, settings_file_list);
+
+	if (!mSettingsLocationList->validateBlock())
+	{
+        llerrs << "Invalid settings file list " << settings_file_list << llendl;
+	}
+		
+	// The settings and command line parsing have a fragile
+	// order-of-operation:
+	// - load defaults from app_settings
+	// - set procedural settings values
+	// - read command line settings
+	// - selectively apply settings needed to load user settings.
+    // - load overrides from user_settings 
+	// - apply command line settings (to override the overrides)
+	// - load per account settings (happens in llstartup
+	
+	// - load defaults
+	bool set_defaults = true;
+	if(!loadSettingsFromDirectory("Default", set_defaults))
+	{
+		std::ostringstream msg;
+		msg << "Unable to load default settings file. The installation may be corrupted.";
+		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
+		return false;
+	}
+	
+	LLUI::setupPaths(); // setup paths for LLTrans based on settings files only
+	LLTransUtil::parseStrings("strings.xml", default_trans_args);
+	LLTransUtil::parseLanguageStrings("language_settings.xml");
+	// - set procedural settings
+	// Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet
+	gSavedSettings.setString("ClientSettingsFile", 
+        gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
+
+#ifndef	LL_RELEASE_FOR_DOWNLOAD
+	// provide developer build only overrides for these control variables that are not
+	// persisted to settings.xml
+	LLControlVariable* c = gSavedSettings.getControl("ShowConsoleWindow");
+	if (c)
+	{
+		c->setValue(true, false);
+	}
+	c = gSavedSettings.getControl("AllowMultipleViewers");
+	if (c)
+	{
+		c->setValue(true, false);
+	}
+#endif
+
+#ifndef	LL_RELEASE_FOR_DOWNLOAD
+	gSavedSettings.setBOOL("QAMode", TRUE );
+	gSavedSettings.setS32("WatchdogEnabled", 0);
+#endif
+	
+	gCrashSettings.getControl(CRASH_BEHAVIOR_SETTING)->getSignal()->connect(boost::bind(&handleCrashSubmitBehaviorChanged, _2));	
+
+	// These are warnings that appear on the first experience of that condition.
+	// They are already set in the settings_default.xml file, but still need to be added to LLFirstUse
+	// for disable/reset ability
+//	LLFirstUse::addConfigVariable("FirstBalanceIncrease");
+//	LLFirstUse::addConfigVariable("FirstBalanceDecrease");
+//	LLFirstUse::addConfigVariable("FirstSit");
+//	LLFirstUse::addConfigVariable("FirstMap");
+//	LLFirstUse::addConfigVariable("FirstGoTo");
+//	LLFirstUse::addConfigVariable("FirstBuild");
+//	LLFirstUse::addConfigVariable("FirstLeftClickNoHit");
+//	LLFirstUse::addConfigVariable("FirstTeleport");
+//	LLFirstUse::addConfigVariable("FirstOverrideKeys");
+//	LLFirstUse::addConfigVariable("FirstAttach");
+//	LLFirstUse::addConfigVariable("FirstAppearance");
+//	LLFirstUse::addConfigVariable("FirstInventory");
+//	LLFirstUse::addConfigVariable("FirstSandbox");
+//	LLFirstUse::addConfigVariable("FirstFlexible");
+//	LLFirstUse::addConfigVariable("FirstDebugMenus");
+//	LLFirstUse::addConfigVariable("FirstSculptedPrim");
+//	LLFirstUse::addConfigVariable("FirstVoice");
+//	LLFirstUse::addConfigVariable("FirstMedia");
+		
+	// - read command line settings.
+	LLControlGroupCLP clp;
+	std::string	cmd_line_config	= gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
+														  "cmd_line.xml");
+
+	clp.configure(cmd_line_config, &gSavedSettings);
+
+	if(!initParseCommandLine(clp))
+	{
+		llwarns	<< "Error parsing command line options.	Command	Line options ignored."  << llendl;
+		
+		llinfos	<< "Command	line usage:\n" << clp << llendl;
+
+		std::ostringstream msg;
+		msg << LLTrans::getString("MBCmdLineError") << clp.getErrorMessage();
+		OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK);
+		return false;
+	}
+	
+	// - selectively apply settings 
+
+	// If the user has specified a alternate settings file name.
+	// Load	it now before loading the user_settings/settings.xml
+	if(clp.hasOption("settings"))
+	{
+		std::string	user_settings_filename = 
+			gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, 
+										   clp.getOption("settings")[0]);		
+		gSavedSettings.setString("ClientSettingsFile", user_settings_filename);
+		llinfos	<< "Using command line specified settings filename: " 
+			<< user_settings_filename << llendl;
+	}
+
+	// - load overrides from user_settings 
+	loadSettingsFromDirectory("User");
+
+	if (gSavedSettings.getBOOL("FirstRunThisInstall"))
+	{
+		gSavedSettings.setString("SessionSettingsFile", "settings_minimal.xml");
+	}
+
+	if (clp.hasOption("sessionsettings"))
+	{
+		std::string session_settings_filename = clp.getOption("sessionsettings")[0];		
+		gSavedSettings.setString("SessionSettingsFile", session_settings_filename);
+		llinfos	<< "Using session settings filename: " 
+			<< session_settings_filename << llendl;
+	}
+	loadSettingsFromDirectory("Session");
+
+	if (clp.hasOption("usersessionsettings"))
+	{
+		std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0];		
+		gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename);
+		llinfos	<< "Using user session settings filename: " 
+			<< user_session_settings_filename << llendl;
+
+	}
+	loadSettingsFromDirectory("UserSession");
+
+	// - apply command line settings 
+	clp.notify(); 
+
+	// Register the core crash option as soon as we can
+	// if we want gdb post-mortem on cores we need to be up and running
+	// ASAP or we might miss init issue etc.
+	if(clp.hasOption("disablecrashlogger"))
+	{
+		llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl;
+		LLAppViewer::instance()->disableCrashlogger();
+	}
+
+	// Handle initialization from settings.
+	// Start up the debugging console before handling other options.
+	if (gSavedSettings.getBOOL("ShowConsoleWindow"))
+	{
+		initConsole();
+	}
+
+	if(clp.hasOption("help"))
+	{
+		std::ostringstream msg;
+		msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp;
+		llinfos	<< msg.str() << llendl;
+
+		OSMessageBox(
+			msg.str().c_str(),
+			LLStringUtil::null,
+			OSMB_OK);
+
+		return false;
+	}
+
+    if(clp.hasOption("set"))
+    {
+        const LLCommandLineParser::token_vector_t& set_values = clp.getOption("set");
+        if(0x1 & set_values.size())
+        {
+            llwarns << "Invalid '--set' parameter count." << llendl;
+        }
+        else
+        {
+            LLCommandLineParser::token_vector_t::const_iterator itr = set_values.begin();
+            for(; itr != set_values.end(); ++itr)
+            {
+                const std::string& name = *itr;
+                const std::string& value = *(++itr);
+				LLControlVariable* c = LLControlGroup::getInstance(sGlobalSettingsName)->getControl(name);
+                if(c)
+                {
+                    c->setValue(value, false);
+                }
+                else
+                {
+                    llwarns << "'--set' specified with unknown setting: '"
+                        << name << "'." << llendl;
+                }
+            }
+        }
+    }
+
+    if(clp.hasOption("channel"))
+    {
+		LLVersionInfo::resetChannel(clp.getOption("channel")[0]);
+	}
+	
+
+	// If we have specified crash on startup, set the global so we'll trigger the crash at the right time
+	if(clp.hasOption("crashonstartup"))
+	{
+		gCrashOnStartup = TRUE;
+	}
+
+	if (clp.hasOption("logperformance"))
+	{
+		LLFastTimer::sLog = TRUE;
+		LLFastTimer::sLogName = std::string("performance");
+	}
+	
+	if (clp.hasOption("logmetrics"))
+	{
+		LLFastTimer::sMetricLog = TRUE ;
+		// '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test
+		// In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...)
+		std::string test_name = clp.getOption("logmetrics")[0];
+		llinfos << "'--logmetrics' argument : " << test_name << llendl;
+		if (test_name == "")
+		{
+			llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl;
+			LLFastTimer::sLogName = DEFAULT_METRIC_NAME;
+		}
+		else
+		{
+			LLFastTimer::sLogName = test_name;
+		}
+	}
+
+	if (clp.hasOption("graphicslevel"))
+	{
+		const LLCommandLineParser::token_vector_t& value = clp.getOption("graphicslevel");
+        if(value.size() != 1)
+        {
+			llwarns << "Usage: -graphicslevel <0-3>" << llendl;
+        }
+        else
+        {
+			std::string detail = value.front();
+			mForceGraphicsDetail = TRUE;
+			
+			switch (detail.c_str()[0])
+			{
+				case '0': 
+					gSavedSettings.setU32("RenderQualityPerformance", 0);		
+					break;
+				case '1': 
+					gSavedSettings.setU32("RenderQualityPerformance", 1);		
+					break;
+				case '2': 
+					gSavedSettings.setU32("RenderQualityPerformance", 2);		
+					break;
+				case '3': 
+					gSavedSettings.setU32("RenderQualityPerformance", 3);		
+					break;
+				default:
+					mForceGraphicsDetail = FALSE;
+					llwarns << "Usage: -graphicslevel <0-3>" << llendl;
+					break;
+			}
+        }
+	}
+
+	if (clp.hasOption("analyzeperformance"))
+	{
+		LLFastTimerView::sAnalyzePerformance = TRUE;
+	}
+
+	if (clp.hasOption("replaysession"))
+	{
+		LLAgentPilot::sReplaySession = TRUE;
+	}
+
+	if (clp.hasOption("nonotifications"))
+	{
+		gSavedSettings.getControl("IgnoreAllNotifications")->setValue(true, false);
+	}
+	
+	if (clp.hasOption("debugsession"))
+	{
+		gDebugSession = TRUE;
+		gDebugGL = TRUE;
+
+		ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log"));
+	}
+
+	// Handle slurl use. NOTE: Don't let SL-55321 reappear.
+
+    // *FIX: This init code should be made more robust to prevent 
+    // the issue SL-55321 from returning. One thought is to allow 
+    // only select options to be set from command line when a slurl 
+    // is specified. More work on the settings system is needed to 
+    // achieve this. For now...
+
+    // *NOTE:Mani The command line parser parses tokens and is 
+    // setup to bail after parsing the '--url' option or the 
+    // first option specified without a '--option' flag (or
+    // any other option that uses the 'last_option' setting - 
+    // see LLControlGroupCLP::configure())
+
+    // What can happen is that someone can use IE (or potentially 
+    // other browsers) and do the rough equivalent of command 
+    // injection and steal passwords. Phoenix. SL-55321
+    if(clp.hasOption("url"))
+    {
+		LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0]));
+		if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION) 
+		{  
+			LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid());
+			
+		}  
+    }
+    else if(clp.hasOption("slurl"))
+    {
+		LLSLURL start_slurl(clp.getOption("slurl")[0]);
+		LLStartUp::setStartSLURL(start_slurl);
+    }
+
+    const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
+    if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
+    {   
+		// hack to force the skin to default.
+        gDirUtilp->setSkinFolder(skinfolder->getValue().asString());
+		//gDirUtilp->setSkinFolder("default");
+    }
+
+    mYieldTime = gSavedSettings.getS32("YieldTime");
+
+	// Read skin/branding settings if specified.
+	//if (! gDirUtilp->getSkinDir().empty() )
+	//{
+	//	std::string skin_def_file = gDirUtilp->findSkinnedFilename("skin.xml");
+	//	LLXmlTree skin_def_tree;
+
+	//	if (!skin_def_tree.parseFile(skin_def_file))
+	//	{
+	//		llerrs << "Failed to parse skin definition." << llendl;
+	//	}
+
+	//}
+
+#if LL_DARWIN
+	// Initialize apple menubar and various callbacks
+	init_apple_menu(LLTrans::getString("APP_NAME").c_str());
+
+#if __ppc__
+	// If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further.
+	// Only test PowerPC - all Intel Macs have SSE.
+	if(!gSysCPU.hasAltivec())
+	{
+		std::ostringstream msg;
+		msg << LLTrans::getString("MBRequiresAltiVec");
+		OSMessageBox(
+			msg.str(),
+			LLStringUtil::null,
+			OSMB_OK);
+		removeMarkerFile();
+		return false;
+	}
+#endif
+	
+#endif // LL_DARWIN
+
+	// Display splash screen.  Must be after above check for previous
+	// crash as this dialog is always frontmost.
+	std::string splash_msg;
+	LLStringUtil::format_map_t args;
+	args["[APP_NAME]"] = LLTrans::getString("SECOND_LIFE");
+	splash_msg = LLTrans::getString("StartupLoading", args);
+	LLSplashScreen::show();
+	LLSplashScreen::update(splash_msg);
+
+	//LLVolumeMgr::initClass();
+	LLVolumeMgr* volume_manager = new LLVolumeMgr();
+	volume_manager->useMutex();	// LLApp and LLMutex magic must be manually enabled
+	LLPrimitive::setVolumeManager(volume_manager);
+
+	// Note: this is where we used to initialize gFeatureManagerp.
+
+	gStartTime = totalTime();
+
+	//
+	// Set the name of the window
+	//
+	gWindowTitle = LLTrans::getString("APP_NAME");
+#if LL_DEBUG
+	gWindowTitle += std::string(" [DEBUG] ") + gArgs;
+#else
+	gWindowTitle += std::string(" ") + gArgs;
+#endif
+	LLStringUtil::truncate(gWindowTitle, 255);
+
+	//RN: if we received a URL, hand it off to the existing instance.
+	// don't call anotherInstanceRunning() when doing URL handoff, as
+	// it relies on checking a marker file which will not work when running
+	// out of different directories
+
+	if (LLStartUp::getStartSLURL().isValid())
+	{
+		if (sendURLToOtherInstance(LLStartUp::getStartSLURL().getSLURLString()))
+		{
+			// successfully handed off URL to existing instance, exit
+			return false;
+		}
+	}
+
+	if (!gSavedSettings.getBOOL("AllowMultipleViewers"))
+	{
+	    //
+	    // Check for another instance of the app running
+	    //
+
+		mSecondInstance = anotherInstanceRunning();
+		
+		if (mSecondInstance)
+		{
+			std::ostringstream msg;
+			msg << LLTrans::getString("MBAlreadyRunning");
+			OSMessageBox(
+				msg.str(),
+				LLStringUtil::null,
+				OSMB_OK);
+			return false;
+		}
+
+		initMarkerFile();
+        
+        checkForCrash();
+    }
+	else
+	{
+		mSecondInstance = anotherInstanceRunning();
+		
+		if (mSecondInstance)
+		{
+			// This is the second instance of SL. Turn off voice support,
+			// but make sure the setting is *not* persisted.
+			LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
+			if(disable_voice)
+			{
+				const BOOL DO_NOT_PERSIST = FALSE;
+				disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST);
+			}
+		}
+
+		initMarkerFile();
+        
+        if(!mSecondInstance)
+        {
+            checkForCrash();
+        }
+	}
+
+   	// need to do this here - need to have initialized global settings first
+	std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
+	if ( !nextLoginLocation.empty() )
+	{
+		LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
+	};
+
+	gLastRunVersion = gSavedSettings.getString("LastRunVersion");
+
+	loadColorSettings();
+
+	return true; // Config was successful.
+}
+
+namespace {
+    // *TODO - decide if there's a better place for these functions.
+    // do we need a file llupdaterui.cpp or something? -brad
+
+	void apply_update_callback(LLSD const & notification, LLSD const & response)
+	{
+		lldebugs << "LLUpdate user response: " << response << llendl;
+		if(response["OK_okcancelbuttons"].asBoolean())
+		{
+			llinfos << "LLUpdate restarting viewer" << llendl;
+			static const bool install_if_ready = true;
+			// *HACK - this lets us launch the installer immediately for now
+			LLUpdaterService().startChecking(install_if_ready);
+		}
+	}
+	
+	void apply_update_ok_callback(LLSD const & notification, LLSD const & response)
+	{
+		llinfos << "LLUpdate restarting viewer" << llendl;
+		static const bool install_if_ready = true;
+		// *HACK - this lets us launch the installer immediately for now
+		LLUpdaterService().startChecking(install_if_ready);
+	}
+	
+	void on_update_downloaded(LLSD const & data)
+	{
+		std::string notification_name;
+		void (*apply_callback)(LLSD const &, LLSD const &) = NULL;
+
+		if(data["required"].asBoolean())
+		{
+			if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT)
+			{
+				// The user never saw the progress bar.
+				apply_callback = &apply_update_ok_callback;
+				notification_name = "RequiredUpdateDownloadedVerboseDialog";
+			}
+			else if(LLStartUp::getStartupState() < STATE_WORLD_INIT)
+			{
+				// The user is logging in but blocked.
+				apply_callback = &apply_update_ok_callback;
+				notification_name = "RequiredUpdateDownloadedDialog";
+			}
+			else
+			{
+				// The user is already logged in; treat like an optional update.
+				apply_callback = &apply_update_callback;
+				notification_name = "DownloadBackgroundTip";
+			}
+		}
+		else
+		{
+			apply_callback = &apply_update_callback;
+			if(LLStartUp::getStartupState() < STATE_STARTED)
+			{
+				// CHOP-262 we need to use a different notification
+				// method prior to login.
+				notification_name = "DownloadBackgroundDialog";
+			}
+			else
+			{
+				notification_name = "DownloadBackgroundTip";
+			}
+		}
+
+		LLSD substitutions;
+		substitutions["VERSION"] = data["version"];
+
+		// truncate version at the rightmost '.' 
+		std::string version_short(data["version"]);
+		size_t short_length = version_short.rfind('.');
+		if (short_length != std::string::npos)
+		{
+			version_short.resize(short_length);
+		}
+
+		LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]");
+		relnotes_url.setArg("[VERSION_SHORT]", version_short);
+
+		// *TODO thread the update service's response through to this point
+		std::string const & channel = LLVersionInfo::getChannel();
+		boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free);
+
+		relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get());
+		relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL"));
+		substitutions["RELEASE_NOTES_FULL_URL"] = relnotes_url.getString();
+
+		LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback);
+	}
+
+	void install_error_callback(LLSD const & notification, LLSD const & response)
+	{
+		LLAppViewer::instance()->forceQuit();
+	}
+	
+    bool notify_update(LLSD const & evt)
+    {
+		std::string notification_name;
+		switch (evt["type"].asInteger())
+		{
+			case LLUpdaterService::DOWNLOAD_COMPLETE:
+				on_update_downloaded(evt);
+				break;
+			case LLUpdaterService::INSTALL_ERROR:
+				if(evt["required"].asBoolean()) {
+					LLNotificationsUtil::add("FailedRequiredUpdateInstall", LLSD(), LLSD(), &install_error_callback);
+				} else {
+					LLNotificationsUtil::add("FailedUpdateInstall");
+				}
+				break;
+			default:
+				break;
+		}
+
+		// let others also handle this event by default
+        return false;
+    }
+	
+	bool on_bandwidth_throttle(LLUpdaterService * updater, LLSD const & evt)
+	{
+		updater->setBandwidthLimit(evt.asInteger() * (1024/8));
+		return false; // Let others receive this event.
+	};
+};
+
+void LLAppViewer::initUpdater()
+{
+	// Initialize the updater service.
+	// Generate URL to the udpater service
+	// Get Channel
+	// Get Version
+	std::string url = gSavedSettings.getString("UpdaterServiceURL");
+	std::string channel = LLVersionInfo::getChannel();
+	std::string version = LLVersionInfo::getVersion();
+	std::string protocol_version = gSavedSettings.getString("UpdaterServiceProtocolVersion");
+	std::string service_path = gSavedSettings.getString("UpdaterServicePath");
+	U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod");
+
+	mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this));
+	mUpdater->initialize(protocol_version, 
+						 url, 
+						 service_path, 
+						 channel, 
+						 version);
+ 	mUpdater->setCheckPeriod(check_period);
+	mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8));
+	gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()->
+		connect(boost::bind(&on_bandwidth_throttle, mUpdater.get(), _2));
+	if(gSavedSettings.getU32("UpdaterServiceSetting"))
+	{
+		bool install_if_ready = true;
+		mUpdater->startChecking(install_if_ready);
+	}
+
+    LLEventPump & updater_pump = LLEventPumps::instance().obtain(LLUpdaterService::pumpName());
+    updater_pump.listen("notify_update", &notify_update);
+}
+
+void LLAppViewer::checkForCrash(void)
+{
+    
+#if LL_SEND_CRASH_REPORTS
+	if (gLastExecEvent == LAST_EXEC_FROZE)
+    {
+        llinfos << "Last execution froze, requesting to send crash report." << llendl;
+        //
+        // Pop up a freeze or crash warning dialog
+        //
+        S32 choice;
+        if(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) == CRASH_BEHAVIOR_ASK)
+        {
+            std::ostringstream msg;
+			msg << LLTrans::getString("MBFrozenCrashed");
+			std::string alert = LLTrans::getString("APP_NAME") + " " + LLTrans::getString("MBAlert");
+            choice = OSMessageBox(msg.str(),
+                                  alert,
+                                  OSMB_YESNO);
+        } 
+        else if(gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) == CRASH_BEHAVIOR_NEVER_SEND)
+        {
+            choice = OSBTN_NO;
+        }
+        else
+        {
+            choice = OSBTN_YES;
+        }
+
+        if (OSBTN_YES == choice)
+        {
+            llinfos << "Sending crash report." << llendl;
+            
+            bool report_freeze = true;
+            handleCrashReporting(report_freeze);
+        }
+        else
+        {
+            llinfos << "Not sending crash report." << llendl;
+        }
+    }
+#endif // LL_SEND_CRASH_REPORTS    
+    
+}
+
+bool LLAppViewer::initWindow()
+{
+	LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
+
+	// store setting in a global for easy access and modification
+	gNoRender = gSavedSettings.getBOOL("DisableRendering");
+
+	// always start windowed
+	BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
+	gViewerWindow = new LLViewerWindow(gWindowTitle, 
+		VIEWER_WINDOW_CLASSNAME,
+		gSavedSettings.getS32("WindowX"), gSavedSettings.getS32("WindowY"),
+		gSavedSettings.getS32("WindowWidth"), gSavedSettings.getS32("WindowHeight"),
+		gSavedSettings.getBOOL("WindowFullScreen"), ignorePixelDepth);
+
+	// Need to load feature table before cheking to start watchdog.
+	const S32 NEVER_SUBMIT_REPORT = 2;
+	bool use_watchdog = false;
+	int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled");
+	if(watchdog_enabled_setting == -1){
+		use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled");
+	}
+	else
+	{
+		// The user has explicitly set this setting; always use that value.
+		use_watchdog = bool(watchdog_enabled_setting);
+	}
+
+	bool send_reports = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING) != NEVER_SUBMIT_REPORT;
+	if(use_watchdog && send_reports)
+	{
+		LLWatchdog::getInstance()->init(watchdog_killer_callback);
+	}
+
+	LLNotificationsUI::LLNotificationManager::getInstance();
+		
+	if (gSavedSettings.getBOOL("WindowMaximized"))
+	{
+		gViewerWindow->mWindow->maximize();
+	}
+
+	if (!gNoRender)
+	{
+		//
+		// Initialize GL stuff
+		//
+
+		if (mForceGraphicsDetail)
+		{
+			LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false);
+		}
+				
+		// Set this flag in case we crash while initializing GL
+		gSavedSettings.setBOOL("RenderInitError", TRUE);
+		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
+	
+		gPipeline.init();
+		stop_glerror();
+		gViewerWindow->initGLDefaults();
+
+		gSavedSettings.setBOOL("RenderInitError", FALSE);
+		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
+	}
+
+	//If we have a startup crash, it's usually near GL initialization, so simulate that.
+	if(gCrashOnStartup)
+	{
+		LLAppViewer::instance()->forceErrorLLError();
+	}
+
+	LLUI::sWindow = gViewerWindow->getWindow();
+
+	// Show watch cursor
+	gViewerWindow->setCursor(UI_CURSOR_WAIT);
+
+	// Finish view initialization
+	gViewerWindow->initBase();
+
+	// show viewer window
+	//gViewerWindow->mWindow->show();
+
+	
+	return true;
+}
+
+void LLAppViewer::writeDebugInfo()
+{
+	std::string debug_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
+	llinfos << "Opening debug file " << debug_filename << llendl;
+	llofstream out_file(debug_filename);
+	LLSDSerialize::toPrettyXML(gDebugInfo, out_file);
+	out_file.close();
+}
+
+void LLAppViewer::cleanupSavedSettings()
+{
+	gSavedSettings.setBOOL("MouseSun", FALSE);
+
+	gSavedSettings.setBOOL("UseEnergy", TRUE);				// force toggle to turn off, since sends message to simulator
+
+	gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
+		
+	gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
+	
+	if (!gNoRender)
+	{
+		if (gDebugView)
+		{
+			gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
+		}
+	}
+
+	// save window position if not maximized
+	// as we don't track it in callbacks
+	if(NULL != gViewerWindow)
+	{
+		BOOL maximized = gViewerWindow->mWindow->getMaximized();
+		if (!maximized)
+		{
+			LLCoordScreen window_pos;
+
+			if (gViewerWindow->mWindow->getPosition(&window_pos))
+			{
+				gSavedSettings.setS32("WindowX", window_pos.mX);
+				gSavedSettings.setS32("WindowY", window_pos.mY);
+			}
+		}
+	}
+
+	gSavedSettings.setF32("MapScale", LLWorldMapView::sMapScale );
+
+	// Some things are cached in LLAgent.
+	if (gAgent.isInitialized())
+	{
+		gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance);
+	}
+}
+
+void LLAppViewer::removeCacheFiles(const std::string& file_mask)
+{
+	std::string mask = gDirUtilp->getDirDelimiter() + file_mask;
+	gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask);
+}
+
+void LLAppViewer::writeSystemInfo()
+{
+	gDebugInfo["SLLog"] = LLError::logFileName();
+
+	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
+	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
+	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
+	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
+	gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
+
+	gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
+
+	gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString();
+	gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily();
+	gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz();
+	gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec();
+	gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
+	gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
+	
+	gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB());
+	gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB
+	gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple();
+
+	// The user is not logged on yet, but record the current grid choice login url
+	// which may have been the intended grid. This can b
+	gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();
+
+	// *FIX:Mani - move this down in llappviewerwin32
+#ifdef LL_WINDOWS
+	DWORD thread_id = GetCurrentThreadId();
+	gDebugInfo["MainloopThreadID"] = (S32)thread_id;
+#endif
+
+	// "CrashNotHandled" is set here, while things are running well,
+	// in case of a freeze. If there is a freeze, the crash logger will be launched
+	// and can read this value from the debug_info.log.
+	// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
+	// then the value of "CrashNotHandled" will be set to true.
+	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
+
+	// Insert crash host url (url to post crash log to) if configured. This insures
+	// that the crash report will go to the proper location in the case of a 
+	// prior freeze.
+	std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
+	if(crashHostUrl != "")
+	{
+		gDebugInfo["CrashHostUrl"] = crashHostUrl;
+	}
+	
+	// Dump some debugging info
+	LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME")
+			<< " version " << LLVersionInfo::getShortVersion() << LL_ENDL;
+
+	// Dump the local time and time zone
+	time_t now;
+	time(&now);
+	char tbuffer[256];		/* Flawfinder: ignore */
+	strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now));
+	LL_INFOS("SystemInfo") << "Local time: " << tbuffer << LL_ENDL;
+
+	// query some system information
+	LL_INFOS("SystemInfo") << "CPU info:\n" << gSysCPU << LL_ENDL;
+	LL_INFOS("SystemInfo") << "Memory info:\n" << gSysMemory << LL_ENDL;
+	LL_INFOS("SystemInfo") << "OS: " << getOSInfo().getOSStringSimple() << LL_ENDL;
+	LL_INFOS("SystemInfo") << "OS info: " << getOSInfo() << LL_ENDL;
+
+	writeDebugInfo(); // Save out debug_info.log early, in case of crash.
+}
+
+void LLAppViewer::handleViewerCrash()
+{
+	llinfos << "Handle viewer crash entry." << llendl;
+
+	llinfos << "Last render pool type: " << LLPipeline::sCurRenderPoolType << llendl ;
+
+	//print out recorded call stacks if there are any.
+	LLError::LLCallStacks::print();
+
+	LLAppViewer* pApp = LLAppViewer::instance();
+	if (pApp->beingDebugged())
+	{
+		// This will drop us into the debugger.
+		abort();
+	}
+
+	if (LLApp::isCrashloggerDisabled())
+	{
+		abort();
+	}
+
+	// Returns whether a dialog was shown.
+	// Only do the logic in here once
+	if (pApp->mReportedCrash)
+	{
+		return;
+	}
+	pApp->mReportedCrash = TRUE;
+	
+	// Insert crash host url (url to post crash log to) if configured.
+	std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
+	if(crashHostUrl != "")
+	{
+		gDebugInfo["CrashHostUrl"] = crashHostUrl;
+	}
+	
+	//We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version
+	//to check against no matter what
+	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
+
+	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
+	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
+	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
+	gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
+
+	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if ( parcel && parcel->getMusicURL()[0])
+	{
+		gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
+	}	
+	if ( parcel && parcel->getMediaURL()[0])
+	{
+		gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
+	}
+	
+	
+	gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
+	gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
+	gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
+	gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
+	gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
+	gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
+	gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
+	gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
+	gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
+
+	char *minidump_file = pApp->getMiniDumpFilename();
+	if(minidump_file && minidump_file[0] != 0)
+	{
+		gDebugInfo["MinidumpPath"] = minidump_file;
+	}
+	
+	if(gLogoutInProgress)
+	{
+		gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
+	}
+	else
+	{
+		gDebugInfo["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH;
+	}
+
+	if(gAgent.getRegion())
+	{
+		gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
+		gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
+		
+		const LLVector3& loc = gAgent.getPositionAgent();
+		gDebugInfo["CurrentLocationX"] = loc.mV[0];
+		gDebugInfo["CurrentLocationY"] = loc.mV[1];
+		gDebugInfo["CurrentLocationZ"] = loc.mV[2];
+	}
+
+	if(LLAppViewer::instance()->mMainloopTimeout)
+	{
+		gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
+	}
+	
+	// The crash is being handled here so set this value to false.
+	// Otherwise the crash logger will think this crash was a freeze.
+	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
+    
+	//Write out the crash status file
+	//Use marker file style setup, as that's the simplest, especially since
+	//we're already in a crash situation	
+	if (gDirUtilp)
+	{
+		std::string crash_file_name;
+		if(gLLErrorActivated) crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LLERROR_MARKER_FILE_NAME);
+		else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME);
+		llinfos << "Creating crash marker file " << crash_file_name << llendl;
+		
+		LLAPRFile crash_file ;
+		crash_file.open(crash_file_name, LL_APR_W);
+		if (crash_file.getFileHandle())
+		{
+			LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL;
+		}
+		else
+		{
+			LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL;
+		}		
+	}
+	
+	if (gMessageSystem && gDirUtilp)
+	{
+		std::string filename;
+		filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "stats.log");
+		llofstream file(filename, llofstream::binary);
+		if(file.good())
+		{
+			llinfos << "Handle viewer crash generating stats log." << llendl;
+			gMessageSystem->summarizeLogs(file);
+			file.close();
+		}
+	}
+
+	if (gMessageSystem)
+	{
+		gMessageSystem->getCircuitInfo(gDebugInfo["CircuitInfo"]);
+		gMessageSystem->stopLogging();
+	}
+
+	if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo);
+
+	// Close the debug file
+	pApp->writeDebugInfo();
+
+	LLError::logToFile("");
+
+	// Remove the marker file, since otherwise we'll spawn a process that'll keep it locked
+	if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH)
+	{
+		pApp->removeMarkerFile(true);
+	}
+	else
+	{
+		pApp->removeMarkerFile(false);
+	}
+	
+#if LL_SEND_CRASH_REPORTS
+	// Call to pure virtual, handled by platform specific llappviewer instance.
+	pApp->handleCrashReporting(); 
+#endif
+    
+	return;
+}
+
+bool LLAppViewer::anotherInstanceRunning()
+{
+	// We create a marker file when the program starts and remove the file when it finishes.
+	// If the file is currently locked, that means another process is already running.
+
+	std::string marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, MARKER_FILE_NAME);
+	LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
+
+	//Freeze case checks
+	if (LLAPRFile::isExist(marker_file, NULL, LL_APR_RB))
+	{
+		// File exists, try opening with write permissions
+		LLAPRFile outfile ;
+		outfile.open(marker_file, LL_APR_WB);
+		apr_file_t* fMarker = outfile.getFileHandle() ; 
+		if (!fMarker)
+		{
+			// Another instance is running. Skip the rest of these operations.
+			LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
+			return true;
+		}
+		if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1)
+		{
+			LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL;
+			return true;
+		}
+		// No other instances; we'll lock this file now & delete on quit.		
+	}
+	LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL;
+	return false;
+}
+
+void LLAppViewer::initMarkerFile()
+{
+	//First, check for the existence of other files.
+	//There are marker files for two different types of crashes
+	
+	mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
+	LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
+
+	//We've got 4 things to test for here
+	// - Other Process Running (SecondLife.exec_marker present, locked)
+	// - Freeze (SecondLife.exec_marker present, not locked)
+	// - LLError Crash (SecondLife.llerror_marker present)
+	// - Other Crash (SecondLife.error_marker present)
+	// These checks should also remove these files for the last 2 cases if they currently exist
+
+	//LLError/Error checks. Only one of these should ever happen at a time.
+	std::string logout_marker_file =  gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
+	std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
+	std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
+
+	if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB) && !anotherInstanceRunning())
+	{
+		gLastExecEvent = LAST_EXEC_FROZE;
+		LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL;
+	}    
+	if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB))
+	{
+		gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
+		LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+		LLAPRFile::remove(logout_marker_file);
+	}
+	if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB))
+	{
+		if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
+		else gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
+		LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+		LLAPRFile::remove(llerror_marker_file);
+	}
+	if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
+	{
+		if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
+		else gLastExecEvent = LAST_EXEC_OTHER_CRASH;
+		LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
+		LLAPRFile::remove(error_marker_file);
+	}
+
+	// No new markers if another instance is running.
+	if(anotherInstanceRunning()) 
+	{
+		return;
+	}
+	
+	// Create the marker file for this execution & lock it
+	apr_status_t s;
+	s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE);	
+
+	if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
+	{
+		LL_DEBUGS("MarkerFile") << "Marker file created." << LL_ENDL;
+	}
+	else
+	{
+		LL_INFOS("MarkerFile") << "Failed to create marker file." << LL_ENDL;
+		return;
+	}
+	if (apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) 
+	{
+		mMarkerFile.close() ;
+		LL_INFOS("MarkerFile") << "Marker file cannot be locked." << LL_ENDL;
+		return;
+	}
+
+	LL_DEBUGS("MarkerFile") << "Marker file locked." << LL_ENDL;
+}
+
+void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
+{
+	LL_DEBUGS("MarkerFile") << "removeMarkerFile()" << LL_ENDL;
+	if (mMarkerFile.getFileHandle())
+	{
+		mMarkerFile.close() ;
+		LLAPRFile::remove( mMarkerFileName );
+	}
+	if (mLogoutMarkerFile != NULL && !leave_logout_marker)
+	{
+		LLAPRFile::remove( mLogoutMarkerFileName );
+		mLogoutMarkerFile = NULL;
+	}
+}
+
+void LLAppViewer::forceQuit()
+{ 
+	LLApp::setQuitting(); 
+}
+
+//TODO: remove
+void LLAppViewer::fastQuit(S32 error_code)
+{
+	// finish pending transfers
+	flushVFSIO();
+	// let sim know we're logging out
+	sendLogoutRequest();
+	// flush network buffers by shutting down messaging system
+	end_messaging_system();
+	// figure out the error code
+	S32 final_error_code = error_code ? error_code : (S32)isError();
+	// this isn't a crash	
+	removeMarkerFile();
+	// get outta here
+	_exit(final_error_code);	
+}
+
+void LLAppViewer::requestQuit()
+{
+	llinfos << "requestQuit" << llendl;
+
+	LLViewerRegion* region = gAgent.getRegion();
+	
+	if( (LLStartUp::getStartupState() < STATE_STARTED) || !region )
+	{
+		// If we have a region, make some attempt to send a logout request first.
+		// This prevents the halfway-logged-in avatar from hanging around inworld for a couple minutes.
+		if(region)
+		{
+			sendLogoutRequest();
+		}
+		
+		// Quit immediately
+		forceQuit();
+		return;
+	}
+
+	// Try to send metrics back to the grid
+	metricsSend(!gDisconnected);
+	
+	LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
+	effectp->setPositionGlobal(gAgent.getPositionGlobal());
+	effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+	LLHUDManager::getInstance()->sendEffects();
+	effectp->markDead() ;//remove it.
+
+	// Attempt to close all floaters that might be
+	// editing things.
+	if (gFloaterView)
+	{
+		// application is quitting
+		gFloaterView->closeAllChildren(true);
+	}
+
+	LLSideTray::getInstance()->notifyChildren(LLSD().with("request","quit"));
+
+	send_stats();
+
+	gLogoutTimer.reset();
+	mQuitRequested = true;
+}
+
+static bool finish_quit(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+	if (option == 0)
+	{
+		LLAppViewer::instance()->requestQuit();
+	}
+	return false;
+}
+static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_quit);
+
+static bool switch_standard_skin_and_quit(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+	if (option == 0)
+	{
+		gSavedSettings.setString("SessionSettingsFile", "");
+		LLAppViewer::instance()->requestQuit();
+	}
+	return false;
+}
+
+static LLNotificationFunctorRegistration standard_skin_quit_reg("SwitchToStandardSkinAndQuit", switch_standard_skin_and_quit);
+
+void LLAppViewer::userQuit()
+{
+	if (gDisconnected || gViewerWindow->getProgressView()->getVisible())
+	{
+		requestQuit();
+	}
+	else
+	{
+		LLNotificationsUtil::add("ConfirmQuit");
+	}
+}
+
+static bool finish_early_exit(const LLSD& notification, const LLSD& response)
+{
+	LLAppViewer::instance()->forceQuit();
+	return false;
+}
+
+void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
+{
+   	llwarns << "app_early_exit: " << name << llendl;
+	gDoDisconnect = TRUE;
+	LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit);
+}
+
+// case where we need the viewer to exit without any need for notifications
+void LLAppViewer::earlyExitNoNotify()
+{
+   	llwarns << "app_early_exit with no notification: " << llendl;
+	gDoDisconnect = TRUE;
+	finish_early_exit( LLSD(), LLSD() );
+}
+
+void LLAppViewer::abortQuit()
+{
+    llinfos << "abortQuit()" << llendl;
+	mQuitRequested = false;
+}
+
+void LLAppViewer::migrateCacheDirectory()
+{
+#if LL_WINDOWS || LL_DARWIN
+	// NOTE: (Nyx) as of 1.21, cache for mac is moving to /library/caches/SecondLife from
+	// /library/application support/SecondLife/cache This should clear/delete the old dir.
+
+	// As of 1.23 the Windows cache moved from
+	//   C:\Documents and Settings\James\Application Support\SecondLife\cache
+	// to
+	//   C:\Documents and Settings\James\Local Settings\Application Support\SecondLife
+	//
+	// The Windows Vista equivalent is from
+	//   C:\Users\James\AppData\Roaming\SecondLife\cache
+	// to
+	//   C:\Users\James\AppData\Local\SecondLife
+	//
+	// Note the absence of \cache on the second path.  James.
+
+	// Only do this once per fresh install of this version.
+	if (gSavedSettings.getBOOL("MigrateCacheDirectory"))
+	{
+		gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE);
+
+		std::string delimiter = gDirUtilp->getDirDelimiter();
+		std::string old_cache_dir = gDirUtilp->getOSUserAppDir() + delimiter + "cache";
+		std::string new_cache_dir = gDirUtilp->getCacheDir(true);
+
+		if (gDirUtilp->fileExists(old_cache_dir))
+		{
+			llinfos << "Migrating cache from " << old_cache_dir << " to " << new_cache_dir << llendl;
+
+			// Migrate inventory cache to avoid pain to inventory database after mass update
+			S32 file_count = 0;
+			std::string file_name;
+			std::string mask = delimiter + "*.*";
+			while (gDirUtilp->getNextFileInDir(old_cache_dir, mask, file_name))
+			{
+				if (file_name == "." || file_name == "..") continue;
+				std::string source_path = old_cache_dir + delimiter + file_name;
+				std::string dest_path = new_cache_dir + delimiter + file_name;
+				if (!LLFile::rename(source_path, dest_path))
+				{
+					file_count++;
+				}
+			}
+			llinfos << "Moved " << file_count << " files" << llendl;
+
+			// Nuke the old cache
+			gDirUtilp->setCacheDir(old_cache_dir);
+			purgeCache();
+			gDirUtilp->setCacheDir(new_cache_dir);
+
+#if LL_DARWIN
+			// Clean up Mac files not deleted by removing *.*
+			std::string ds_store = old_cache_dir + "/.DS_Store";
+			if (gDirUtilp->fileExists(ds_store))
+			{
+				LLFile::remove(ds_store);
+			}
+#endif
+			if (LLFile::rmdir(old_cache_dir) != 0)
+			{
+				llwarns << "could not delete old cache directory " << old_cache_dir << llendl;
+			}
+		}
+	}
+#endif // LL_WINDOWS || LL_DARWIN
+}
+
+void dumpVFSCaches()
+{
+	llinfos << "======= Static VFS ========" << llendl;
+	gStaticVFS->listFiles();
+#if LL_WINDOWS
+	llinfos << "======= Dumping static VFS to StaticVFSDump ========" << llendl;
+	WCHAR w_str[MAX_PATH];
+	GetCurrentDirectory(MAX_PATH, w_str);
+	S32 res = LLFile::mkdir("StaticVFSDump");
+	if (res == -1)
+	{
+		if (errno != EEXIST)
+		{
+			llwarns << "Couldn't create dir StaticVFSDump" << llendl;
+		}
+	}
+	SetCurrentDirectory(utf8str_to_utf16str("StaticVFSDump").c_str());
+	gStaticVFS->dumpFiles();
+	SetCurrentDirectory(w_str);
+#endif
+						
+	llinfos << "========= Dynamic VFS ====" << llendl;
+	gVFS->listFiles();
+#if LL_WINDOWS
+	llinfos << "========= Dumping dynamic VFS to VFSDump ====" << llendl;
+	res = LLFile::mkdir("VFSDump");
+	if (res == -1)
+	{
+		if (errno != EEXIST)
+		{
+			llwarns << "Couldn't create dir VFSDump" << llendl;
+		}
+	}
+	SetCurrentDirectory(utf8str_to_utf16str("VFSDump").c_str());
+	gVFS->dumpFiles();
+	SetCurrentDirectory(w_str);
+#endif
+}
+
+//static
+U32 LLAppViewer::getTextureCacheVersion() 
+{
+	//viewer texture cache version, change if the texture cache format changes.
+	const U32 TEXTURE_CACHE_VERSION = 7;
+
+	return TEXTURE_CACHE_VERSION ;
+}
+
+//static
+U32 LLAppViewer::getObjectCacheVersion() 
+{
+	// Viewer object cache version, change if object update
+	// format changes. JC
+	const U32 INDRA_OBJECT_CACHE_VERSION = 14;
+
+	return INDRA_OBJECT_CACHE_VERSION;
+}
+
+bool LLAppViewer::initCache()
+{
+	mPurgeCache = false;
+	BOOL read_only = mSecondInstance ? TRUE : FALSE;
+	LLAppViewer::getTextureCache()->setReadOnly(read_only) ;
+	LLVOCache::getInstance()->setReadOnly(read_only);
+
+	BOOL texture_cache_mismatch = FALSE ;
+	if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) 
+	{
+		texture_cache_mismatch = TRUE ;
+		if(!read_only) 
+		{
+			gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion());
+		}
+	}
+
+	if(!read_only)
+	{
+		// Purge cache if user requested it
+		if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
+			gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
+		{
+			gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
+		mPurgeCache = true;
+		}
+	
+		// We have moved the location of the cache directory over time.
+		migrateCacheDirectory();
+	
+		// Setup and verify the cache location
+		std::string cache_location = gSavedSettings.getString("CacheLocation");
+		std::string new_cache_location = gSavedSettings.getString("NewCacheLocation");
+		if (new_cache_location != cache_location)
+		{
+			gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
+			purgeCache(); // purge old cache
+			gSavedSettings.setString("CacheLocation", new_cache_location);
+			gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location));
+		}
+	}
+
+	if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")))
+	{
+		LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL;
+		gSavedSettings.setString("CacheLocation", "");
+		gSavedSettings.setString("CacheLocationTopFolder", "");
+	}
+	
+	if (mPurgeCache && !read_only)
+	{
+		LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
+		purgeCache();
+	}
+
+	LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));
+	
+	// Init the texture cache
+	// Allocate 80% of the cache size for textures	
+	const S32 MB = 1024*1024;
+	S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
+	const S64 MAX_CACHE_SIZE = 1024*MB;
+	cache_size = llmin(cache_size, MAX_CACHE_SIZE);
+	S64 texture_cache_size = ((cache_size * 8)/10);
+	S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
+	texture_cache_size -= extra;
+
+	LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()) ;
+
+	LLSplashScreen::update(LLTrans::getString("StartupInitializingVFS"));
+	
+	// Init the VFS
+	S64 vfs_size = cache_size - texture_cache_size;
+	const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB
+	vfs_size = llmin(vfs_size, MAX_VFS_SIZE);
+	vfs_size = (vfs_size / MB) * MB; // make sure it is MB aligned
+	U32 vfs_size_u32 = (U32)vfs_size;
+	U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB;
+	bool resize_vfs = (vfs_size_u32 != old_vfs_size);
+	if (resize_vfs)
+	{
+		gSavedSettings.setU32("VFSOldSize", vfs_size_u32/MB);
+	}
+	LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size/(1024*1024) << " MB" << LL_ENDL;
+	
+	// This has to happen BEFORE starting the vfs
+	//time_t	ltime;
+	srand(time(NULL));		// Flawfinder: ignore
+	U32 old_salt = gSavedSettings.getU32("VFSSalt");
+	U32 new_salt;
+	std::string old_vfs_data_file;
+	std::string old_vfs_index_file;
+	std::string new_vfs_data_file;
+	std::string new_vfs_index_file;
+	std::string static_vfs_index_file;
+	std::string static_vfs_data_file;
+
+	if (gSavedSettings.getBOOL("AllowMultipleViewers"))
+	{
+		// don't mess with renaming the VFS in this case
+		new_salt = old_salt;
+	}
+	else
+	{
+		do
+		{
+			new_salt = rand();
+		} while( new_salt == old_salt );
+	}
+
+	old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",old_salt);
+
+	// make sure this file exists
+	llstat s;
+	S32 stat_result = LLFile::stat(old_vfs_data_file, &s);
+	if (stat_result)
+	{
+		// doesn't exist, look for a data file
+		std::string mask;
+		mask = gDirUtilp->getDirDelimiter();
+		mask += VFS_DATA_FILE_BASE;
+		mask += "*";
+
+		std::string dir;
+		dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
+
+		std::string found_file;
+		if (gDirUtilp->getNextFileInDir(dir, mask, found_file))
+		{
+			old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file;
+
+			S32 start_pos = found_file.find_last_of('.');
+			if (start_pos > 0)
+			{
+				sscanf(found_file.substr(start_pos+1).c_str(), "%d", &old_salt);
+			}
+			LL_DEBUGS("AppCache") << "Default vfs data file not present, found: " << old_vfs_data_file << " Old salt: " << old_salt << llendl;
+		}
+	}
+
+	old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_INDEX_FILE_BASE) + llformat("%u",old_salt);
+
+	stat_result = LLFile::stat(old_vfs_index_file, &s);
+	if (stat_result)
+	{
+		// We've got a bad/missing index file, nukem!
+		LL_WARNS("AppCache") << "Bad or missing vfx index file " << old_vfs_index_file << LL_ENDL;
+		LL_WARNS("AppCache") << "Removing old vfs data file " << old_vfs_data_file << LL_ENDL;
+		LLFile::remove(old_vfs_data_file);
+		LLFile::remove(old_vfs_index_file);
+		
+		// Just in case, nuke any other old cache files in the directory.
+		std::string dir;
+		dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"");
+
+		std::string mask;
+		mask = gDirUtilp->getDirDelimiter();
+		mask += VFS_DATA_FILE_BASE;
+		mask += "*";
+
+		gDirUtilp->deleteFilesInDir(dir, mask);
+
+		mask = gDirUtilp->getDirDelimiter();
+		mask += VFS_INDEX_FILE_BASE;
+		mask += "*";
+
+		gDirUtilp->deleteFilesInDir(dir, mask);
+	}
+
+	new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,VFS_DATA_FILE_BASE) + llformat("%u",new_salt);
+	new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u",new_salt);
+
+	static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_data.db2");
+	static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"static_index.db2");
+
+	if (resize_vfs)
+	{
+		LL_DEBUGS("AppCache") << "Removing old vfs and re-sizing" << LL_ENDL;
+		
+		LLFile::remove(old_vfs_data_file);
+		LLFile::remove(old_vfs_index_file);
+	}
+	else if (old_salt != new_salt)
+	{
+		// move the vfs files to a new name before opening
+		LL_DEBUGS("AppCache") << "Renaming " << old_vfs_data_file << " to " << new_vfs_data_file << LL_ENDL;
+		LL_DEBUGS("AppCache") << "Renaming " << old_vfs_index_file << " to " << new_vfs_index_file << LL_ENDL;
+		LLFile::rename(old_vfs_data_file, new_vfs_data_file);
+		LLFile::rename(old_vfs_index_file, new_vfs_index_file);
+	}
+
+	// Startup the VFS...
+	gSavedSettings.setU32("VFSSalt", new_salt);
+
+	// Don't remove VFS after viewer crashes.  If user has corrupt data, they can reinstall. JC
+	gVFS = LLVFS::createLLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
+	if( !gVFS )
+	{
+		return false;
+	}
+
+	gStaticVFS = LLVFS::createLLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false);
+	if( !gStaticVFS )
+	{
+		return false;
+	}
+
+	BOOL success = gVFS->isValid() && gStaticVFS->isValid();
+	if( !success )
+	{
+		return false;
+	}
+	else
+	{
+		LLVFile::initClass();
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+		if (gSavedSettings.getBOOL("DumpVFSCaches"))
+		{
+			dumpVFSCaches();
+		}
+#endif
+		
+		return true;
+	}
+}
+
+void LLAppViewer::purgeCache()
+{
+	LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << llendl;
+	LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE);
+	LLVOCache::getInstance()->removeCache(LL_PATH_CACHE);
+	std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
+	gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
+}
+
+std::string LLAppViewer::getSecondLifeTitle() const
+{
+	return LLTrans::getString("APP_NAME");
+}
+
+std::string LLAppViewer::getWindowTitle() const 
+{
+	return gWindowTitle;
+}
+
+// Callback from a dialog indicating user was logged out.  
+bool finish_disconnect(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+	if (1 == option)
+	{
+        LLAppViewer::instance()->forceQuit();
+	}
+	return false;
+}
+
+// Callback from an early disconnect dialog, force an exit
+bool finish_forced_disconnect(const LLSD& notification, const LLSD& response)
+{
+	LLAppViewer::instance()->forceQuit();
+	return false;
+}
+
+
+void LLAppViewer::forceDisconnect(const std::string& mesg)
+{
+	if (gDoDisconnect)
+    {
+		// Already popped up one of these dialogs, don't
+		// do this again.
+		return;
+    }
+	
+	// *TODO: Translate the message if possible
+	std::string big_reason = LLAgent::sTeleportErrorMessages[mesg];
+	if ( big_reason.size() == 0 )
+	{
+		big_reason = mesg;
+	}
+
+	LLSD args;
+	gDoDisconnect = TRUE;
+
+	if (LLStartUp::getStartupState() < STATE_STARTED)
+	{
+		// Tell users what happened
+		args["ERROR_MESSAGE"] = big_reason;
+		LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect);
+	}
+	else
+	{
+		args["MESSAGE"] = big_reason;
+		LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect );
+	}
+}
+
+void LLAppViewer::badNetworkHandler()
+{
+	// Dump the packet
+	gMessageSystem->dumpPacketToLog();
+
+	// Flush all of our caches on exit in the case of disconnect due to
+	// invalid packets.
+
+	mPurgeOnExit = TRUE;
+
+	std::ostringstream message;
+	message <<
+		"The viewer has detected mangled network data indicative\n"
+		"of a bad upstream network connection or an incomplete\n"
+		"local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n"
+		" \n"
+		"Try uninstalling and reinstalling to see if this resolves \n"
+		"the issue. \n"
+		" \n"
+		"If the problem continues, see the Tech Support FAQ at: \n"
+		"www.secondlife.com/support";
+	forceDisconnect(message.str());
+	
+	LLApp::instance()->writeMiniDump();
+}
+
+// This routine may get called more than once during the shutdown process.
+// This can happen because we need to get the screenshot before the window
+// is destroyed.
+void LLAppViewer::saveFinalSnapshot()
+{
+	if (!mSavedFinalSnapshot && !gNoRender)
+	{
+		gSavedSettings.setVector3d("FocusPosOnLogout", gAgentCamera.calcFocusPositionTargetGlobal());
+		gSavedSettings.setVector3d("CameraPosOnLogout", gAgentCamera.calcCameraPositionTargetGlobal());
+		gViewerWindow->setCursor(UI_CURSOR_WAIT);
+		gAgentCamera.changeCameraToThirdPerson( FALSE );	// don't animate, need immediate switch
+		gSavedSettings.setBOOL("ShowParcelOwners", FALSE);
+		idle();
+
+		std::string snap_filename = gDirUtilp->getLindenUserDir();
+		snap_filename += gDirUtilp->getDirDelimiter();
+		snap_filename += SCREEN_LAST_FILENAME;
+		// use full pixel dimensions of viewer window (not post-scale dimensions)
+		gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, TRUE);
+		mSavedFinalSnapshot = TRUE;
+	}
+}
+
+void LLAppViewer::loadNameCache()
+{
+	// display names cache
+	std::string filename =
+		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+	LL_INFOS("AvNameCache") << filename << LL_ENDL;
+	llifstream name_cache_stream(filename);
+	if(name_cache_stream.is_open())
+	{
+		LLAvatarNameCache::importFile(name_cache_stream);
+	}
+
+	if (!gCacheName) return;
+
+	std::string name_cache;
+	name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
+	llifstream cache_file(name_cache);
+	if(cache_file.is_open())
+	{
+		if(gCacheName->importFile(cache_file)) return;
+	}
+}
+
+void LLAppViewer::saveNameCache()
+	{
+	// display names cache
+	std::string filename =
+		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+	llofstream name_cache_stream(filename);
+	if(name_cache_stream.is_open())
+	{
+		LLAvatarNameCache::exportFile(name_cache_stream);
+}
+
+	if (!gCacheName) return;
+
+	std::string name_cache;
+	name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache");
+	llofstream cache_file(name_cache);
+	if(cache_file.is_open())
+	{
+		gCacheName->exportFile(cache_file);
+	}
+}
+
+/*!	@brief		This class is an LLFrameTimer that can be created with
+				an elapsed time that starts counting up from the given value
+				rather than 0.0.
+				
+				Otherwise it behaves the same way as LLFrameTimer.
+*/
+class LLFrameStatsTimer : public LLFrameTimer
+{
+public:
+	LLFrameStatsTimer(F64 elapsed_already = 0.0)
+		: LLFrameTimer()
+		{
+			mStartTime -= elapsed_already;
+		}
+};
+
+static LLFastTimer::DeclareTimer FTM_AUDIO_UPDATE("Update Audio");
+static LLFastTimer::DeclareTimer FTM_CLEANUP("Cleanup");
+static LLFastTimer::DeclareTimer FTM_IDLE_CB("Idle Callbacks");
+static LLFastTimer::DeclareTimer FTM_LOD_UPDATE("Update LOD");
+static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist");
+static LLFastTimer::DeclareTimer FTM_REGION_UPDATE("Update Region");
+static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World");
+static LLFastTimer::DeclareTimer FTM_NETWORK("Network");
+
+///////////////////////////////////////////////////////
+// idle()
+//
+// Called every time the window is not doing anything.
+// Receive packets, update statistics, and schedule a redisplay.
+///////////////////////////////////////////////////////
+void LLAppViewer::idle()
+{
+	LLMemType mt_idle(LLMemType::MTYPE_IDLE);
+	pingMainloopTimeout("Main:Idle");
+	
+	// Update frame timers
+	static LLTimer idle_timer;
+
+	LLFrameTimer::updateFrameTime();
+	LLFrameTimer::updateFrameCount();
+	LLEventTimer::updateClass();
+	LLCriticalDamp::updateInterpolants();
+	LLMortician::updateClass();
+	F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
+
+	// Cap out-of-control frame times
+	// Too low because in menus, swapping, debugger, etc.
+	// Too high because idle called with no objects in view, etc.
+	const F32 MIN_FRAME_RATE = 1.f;
+	const F32 MAX_FRAME_RATE = 200.f;
+
+	F32 frame_rate_clamped = 1.f / dt_raw;
+	frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE, MAX_FRAME_RATE);
+	gFrameDTClamped = 1.f / frame_rate_clamped;
+
+	// Global frame timer
+	// Smoothly weight toward current frame
+	gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f;
+
+	F32 qas = gSavedSettings.getF32("QuitAfterSeconds");
+	if (qas > 0.f)
+	{
+		if (gRenderStartTime.getElapsedTimeF32() > qas)
+		{
+			LLAppViewer::instance()->forceQuit();
+		}
+	}
+
+	// debug setting to quit after N seconds of being AFK - 0 to never do this
+	F32 qas_afk = gSavedSettings.getF32("QuitAfterSecondsOfAFK");
+	if (qas_afk > 0.f)
+	{
+		// idle time is more than setting
+		if ( gAwayTriggerTimer.getElapsedTimeF32() > qas_afk )
+		{
+			// go ahead and just quit gracefully
+			LLAppViewer::instance()->requestQuit();
+		}
+	}
+
+	// Must wait until both have avatar object and mute list, so poll
+	// here.
+	request_initial_instant_messages();
+
+	///////////////////////////////////
+	//
+	// Special case idle if still starting up
+	//
+	if (LLStartUp::getStartupState() < STATE_STARTED)
+	{
+		// Skip rest if idle startup returns false (essentially, no world yet)
+		gGLActive = TRUE;
+		if (!idle_startup())
+		{
+			gGLActive = FALSE;
+			return;
+		}
+		gGLActive = FALSE;
+	}
+
+	
+    F32 yaw = 0.f;				// radians
+
+	if (!gDisconnected)
+	{
+		LLFastTimer t(FTM_NETWORK);
+		// Update spaceserver timeinfo
+	    LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC));
+    
+    
+	    //////////////////////////////////////
+	    //
+	    // Update simulator agent state
+	    //
+
+		if (gSavedSettings.getBOOL("RotateRight"))
+		{
+			gAgent.moveYaw(-1.f);
+		}
+
+		{
+			LLFastTimer t(FTM_AGENT_AUTOPILOT);
+			// Handle automatic walking towards points
+			gAgentPilot.updateTarget();
+			gAgent.autoPilot(&yaw);
+		}
+    
+	    static LLFrameTimer agent_update_timer;
+	    static U32 				last_control_flags;
+    
+	    //	When appropriate, update agent location to the simulator.
+	    F32 agent_update_time = agent_update_timer.getElapsedTimeF32();
+	    BOOL flags_changed = gAgent.controlFlagsDirty() || (last_control_flags != gAgent.getControlFlags());
+		    
+	    if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
+	    {
+		    LLFastTimer t(FTM_AGENT_UPDATE);
+		    // Send avatar and camera info
+		    last_control_flags = gAgent.getControlFlags();
+		    send_agent_update(TRUE);
+		    agent_update_timer.reset();
+	    }
+	}
+
+	//////////////////////////////////////
+	//
+	// Manage statistics
+	//
+	//
+	{
+		// Initialize the viewer_stats_timer with an already elapsed time
+		// of SEND_STATS_PERIOD so that the initial stats report will
+		// be sent immediately.
+		static LLFrameStatsTimer viewer_stats_timer(SEND_STATS_PERIOD);
+		reset_statistics();
+
+		// Update session stats every large chunk of time
+		// *FIX: (???) SAMANTHA
+		if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected)
+		{
+			llinfos << "Transmitting sessions stats" << llendl;
+			send_stats();
+			viewer_stats_timer.reset();
+		}
+
+		// Print the object debugging stats
+		static LLFrameTimer object_debug_timer;
+		if (object_debug_timer.getElapsedTimeF32() > 5.f)
+		{
+			object_debug_timer.reset();
+			if (gObjectList.mNumDeadObjectUpdates)
+			{
+				llinfos << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << llendl;
+				gObjectList.mNumDeadObjectUpdates = 0;
+			}
+			if (gObjectList.mNumUnknownKills)
+			{
+				llinfos << "Kills on unknown objects: " << gObjectList.mNumUnknownKills << llendl;
+				gObjectList.mNumUnknownKills = 0;
+			}
+			if (gObjectList.mNumUnknownUpdates)
+			{
+				llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl;
+				gObjectList.mNumUnknownUpdates = 0;
+			}
+
+			// ViewerMetrics FPS piggy-backing on the debug timer.
+			// The 5-second interval is nice for this purpose.  If the object debug
+			// bit moves or is disabled, please give this a suitable home.
+			LLViewerAssetStatsFF::record_fps_main(gFPSClamped);
+		}
+	}
+
+	if (!gDisconnected)
+	{
+		LLFastTimer t(FTM_NETWORK);
+	
+	    ////////////////////////////////////////////////
+	    //
+	    // Network processing
+	    //
+	    // NOTE: Starting at this point, we may still have pointers to "dead" objects
+	    // floating throughout the various object lists.
+	    //
+		idleNameCache();
+    
+		idleNetwork();
+	    	        
+
+		// Check for away from keyboard, kick idle agents.
+		idle_afk_check();
+
+		//  Update statistics for this frame
+		update_statistics(gFrameCount);
+	}
+
+	////////////////////////////////////////
+	//
+	// Handle the regular UI idle callbacks as well as
+	// hover callbacks
+	//
+
+	{
+// 		LLFastTimer t(FTM_IDLE_CB);
+
+		// Do event notifications if necessary.  Yes, we may want to move this elsewhere.
+		gEventNotifier.update();
+		
+		gIdleCallbacks.callFunctions();
+		gInventory.idleNotifyObservers();
+	}
+	
+	// Metrics logging (LLViewerAssetStats, etc.)
+	{
+		static LLTimer report_interval;
+
+		// *TODO:  Add configuration controls for this
+		if (report_interval.getElapsedTimeF32() >= app_metrics_interval)
+		{
+			metricsSend(! gDisconnected);
+			report_interval.reset();
+		}
+	}
+
+	if (gDisconnected)
+    {
+		return;
+    }
+
+	gViewerWindow->updateUI();
+
+	///////////////////////////////////////
+	// Agent and camera movement
+	//
+		LLCoordGL current_mouse = gViewerWindow->getCurrentMouse();
+
+	{
+		// After agent and camera moved, figure out if we need to
+		// deselect objects.
+		LLSelectMgr::getInstance()->deselectAllIfTooFar();
+
+	}
+
+	{
+		// Handle pending gesture processing
+		static LLFastTimer::DeclareTimer ftm("Agent Position");
+		LLFastTimer t(ftm);
+		LLGestureMgr::instance().update();
+
+		gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY);
+	}
+
+	{
+		LLFastTimer t(FTM_OBJECTLIST_UPDATE); 
+		
+        if (!(logoutRequestSent() && hasSavedFinalSnapshot()))
+		{
+			gObjectList.update(gAgent, *LLWorld::getInstance());
+		}
+	}
+	
+	//////////////////////////////////////
+	//
+	// Deletes objects...
+	// Has to be done after doing idleUpdates (which can kill objects)
+	//
+
+	{
+		LLFastTimer t(FTM_CLEANUP);
+		gObjectList.cleanDeadObjects();
+		LLDrawable::cleanupDeadDrawables();
+	}
+	
+	//
+	// After this point, in theory we should never see a dead object
+	// in the various object/drawable lists.
+	//
+
+	//////////////////////////////////////
+	//
+	// Update/send HUD effects
+	//
+	// At this point, HUD effects may clean up some references to
+	// dead objects.
+	//
+
+	{
+		static LLFastTimer::DeclareTimer ftm("HUD Effects");
+		LLFastTimer t(ftm);
+		LLSelectMgr::getInstance()->updateEffects();
+		LLHUDManager::getInstance()->cleanupEffects();
+		LLHUDManager::getInstance()->sendEffects();
+	}
+
+	////////////////////////////////////////
+	//
+	// Unpack layer data that we've received
+	//
+
+	{
+		LLFastTimer t(FTM_NETWORK);
+		gVLManager.unpackData();
+	}
+	
+	/////////////////////////
+	//
+	// Update surfaces, and surface textures as well.
+	//
+
+	LLWorld::getInstance()->updateVisibilities();
+	{
+		const F32 max_region_update_time = .001f; // 1ms
+		LLFastTimer t(FTM_REGION_UPDATE);
+		LLWorld::getInstance()->updateRegions(max_region_update_time);
+	}
+	
+	/////////////////////////
+	//
+	// Update weather effects
+	//
+	if (!gNoRender)
+	{
+		LLWorld::getInstance()->updateClouds(gFrameDTClamped);
+		gSky.propagateHeavenlyBodies(gFrameDTClamped);				// moves sun, moon, and planets
+
+		// Update wind vector 
+		LLVector3 wind_position_region;
+		static LLVector3 average_wind;
+
+		LLViewerRegion *regionp;
+		regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal());	// puts agent's local coords into wind_position	
+		if (regionp)
+		{
+			gWindVec = regionp->mWind.getVelocity(wind_position_region);
+
+			// Compute average wind and use to drive motion of water
+			
+			average_wind = regionp->mWind.getAverage();
+			F32 cloud_density = regionp->mCloudLayer.getDensityRegion(wind_position_region);
+			
+			gSky.setCloudDensityAtAgent(cloud_density);
+			gSky.setWind(average_wind);
+			//LLVOWater::setWind(average_wind);
+		}
+		else
+		{
+			gWindVec.setVec(0.0f, 0.0f, 0.0f);
+		}
+	}
+	
+	//////////////////////////////////////
+	//
+	// Sort and cull in the new renderer are moved to pipeline.cpp
+	// Here, particles are updated and drawables are moved.
+	//
+	
+	if (!gNoRender)
+	{
+		LLFastTimer t(FTM_WORLD_UPDATE);
+		gPipeline.updateMove();
+
+		LLWorld::getInstance()->updateParticles();
+	}
+
+	if (LLViewerJoystick::getInstance()->getOverrideCamera())
+	{
+		LLViewerJoystick::getInstance()->moveFlycam();
+	}
+	else
+	{
+		if (LLToolMgr::getInstance()->inBuildMode())
+		{
+			LLViewerJoystick::getInstance()->moveObjects();
+		}
+
+		gAgentCamera.updateCamera();
+	}
+
+	// update media focus
+	LLViewerMediaFocus::getInstance()->update();
+
+	// objects and camera should be in sync, do LOD calculations now
+	{
+		LLFastTimer t(FTM_LOD_UPDATE);
+		gObjectList.updateApparentAngles(gAgent);
+	}
+
+	{
+		LLFastTimer t(FTM_AUDIO_UPDATE);
+		
+		if (gAudiop)
+		{
+		    audio_update_volume(false);
+			audio_update_listener();
+			audio_update_wind(false);
+
+			// this line actually commits the changes we've made to source positions, etc.
+			const F32 max_audio_decode_time = 0.002f; // 2 ms decode time
+			gAudiop->idle(max_audio_decode_time);
+		}
+	}
+	
+	// Handle shutdown process, for example, 
+	// wait for floaters to close, send quit message,
+	// forcibly quit if it has taken too long
+	if (mQuitRequested)
+	{
+		gGLActive = TRUE;
+		idleShutdown();
+	}
+}
+
+void LLAppViewer::idleShutdown()
+{
+	// Wait for all modal alerts to get resolved
+	if (LLModalDialog::activeCount() > 0)
+	{
+		return;
+	}
+
+	// close IM interface
+	if(gIMMgr)
+	{
+		gIMMgr->disconnectAllSessions();
+	}
+	
+	// Wait for all floaters to get resolved
+	if (gFloaterView
+		&& !gFloaterView->allChildrenClosed())
+	{
+		return;
+	}
+
+	if (LLSideTray::getInstance()->notifyChildren(LLSD().with("request","wait_quit")))
+	{
+		return;
+	}
+
+
+	
+	// ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()
+	// *TODO: ugly
+	static bool saved_teleport_history = false;
+	if (!saved_teleport_history)
+	{
+		saved_teleport_history = true;
+		LLTeleportHistory::getInstance()->dump();
+		LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this
+		return;
+	}
+
+	static bool saved_snapshot = false;
+	if (!saved_snapshot)
+	{
+		saved_snapshot = true;
+		saveFinalSnapshot();
+		return;
+	}
+
+	const F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f;
+
+	S32 pending_uploads = gAssetStorage->getNumPendingUploads();
+	if (pending_uploads > 0
+		&& gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME
+		&& !logoutRequestSent())
+	{
+		static S32 total_uploads = 0;
+		// Sometimes total upload count can change during logout.
+		total_uploads = llmax(total_uploads, pending_uploads);
+		gViewerWindow->setShowProgress(TRUE);
+		S32 finished_uploads = total_uploads - pending_uploads;
+		F32 percent = 100.f * finished_uploads / total_uploads;
+		gViewerWindow->setProgressPercent(percent);
+		gViewerWindow->setProgressString(LLTrans::getString("SavingSettings"));
+		return;
+	}
+
+	// All floaters are closed.  Tell server we want to quit.
+	if( !logoutRequestSent() )
+	{
+		sendLogoutRequest();
+
+		// Wait for a LogoutReply message
+		gViewerWindow->setShowProgress(TRUE);
+		gViewerWindow->setProgressPercent(100.f);
+		gViewerWindow->setProgressString(LLTrans::getString("LoggingOut"));
+		return;
+	}
+
+	// Make sure that we quit if we haven't received a reply from the server.
+	if( logoutRequestSent() 
+		&& gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime )
+	{
+		forceQuit();
+		return;
+	}
+}
+
+void LLAppViewer::sendLogoutRequest()
+{
+	if(!mLogoutRequestSent)
+	{
+		LLMessageSystem* msg = gMessageSystem;
+		msg->newMessageFast(_PREHASH_LogoutRequest);
+		msg->nextBlockFast(_PREHASH_AgentData);
+		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		gAgent.sendReliableMessage();
+
+		gLogoutTimer.reset();
+		gLogoutMaxTime = LOGOUT_REQUEST_TIME;
+		mLogoutRequestSent = TRUE;
+		
+		if(LLVoiceClient::instanceExists())
+		{
+			LLVoiceClient::getInstance()->leaveChannel();
+		}
+
+		//Set internal status variables and marker files
+		gLogoutInProgress = TRUE;
+		mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
+		
+		LLAPRFile outfile ;
+		outfile.open(mLogoutMarkerFileName, LL_APR_W);
+		mLogoutMarkerFile =  outfile.getFileHandle() ;
+		if (mLogoutMarkerFile)
+		{
+			llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl;
+    		apr_file_close(mLogoutMarkerFile);
+		}
+		else
+		{
+			llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl;
+		}		
+	}
+}
+
+void LLAppViewer::idleNameCache()
+{
+	// Neither old nor new name cache can function before agent has a region
+	LLViewerRegion* region = gAgent.getRegion();
+	if (!region) return;
+
+	// deal with any queued name requests and replies.
+	gCacheName->processPending();
+
+	// Can't run the new cache until we have the list of capabilities
+	// for the agent region, and can therefore decide whether to use
+	// display names or fall back to the old name system.
+	if (!region->capabilitiesReceived()) return;
+
+	// Agent may have moved to a different region, so need to update cap URL
+	// for name lookups.  Can't do this in the cap grant code, as caps are
+	// granted to neighbor regions before the main agent gets there.  Can't
+	// do it in the move-into-region code because cap not guaranteed to be
+	// granted yet, for example on teleport.
+	bool had_capability = LLAvatarNameCache::hasNameLookupURL();
+	std::string name_lookup_url;
+	name_lookup_url.reserve(128); // avoid a memory allocation below
+	name_lookup_url = region->getCapability("GetDisplayNames");
+	bool have_capability = !name_lookup_url.empty();
+	if (have_capability)
+	{
+		// we have support for display names, use it
+	    U32 url_size = name_lookup_url.size();
+	    // capabilities require URLs with slashes before query params:
+	    // https://<host>:<port>/cap/<uuid>/?ids=<blah>
+	    // but the caps are granted like:
+	    // https://<host>:<port>/cap/<uuid>
+	    if (url_size > 0 && name_lookup_url[url_size-1] != '/')
+	    {
+		    name_lookup_url += '/';
+	    }
+		LLAvatarNameCache::setNameLookupURL(name_lookup_url);
+	}
+	else
+	{
+		// Display names not available on this region
+		LLAvatarNameCache::setNameLookupURL( std::string() );
+	}
+
+	// Error recovery - did we change state?
+	if (had_capability != have_capability)
+	{
+		// name tags are persistant on screen, so make sure they refresh
+		LLVOAvatar::invalidateNameTags();
+	}
+
+	LLAvatarNameCache::idle();
+}
+
+//
+// Handle messages, and all message related stuff
+//
+
+#define TIME_THROTTLE_MESSAGES
+
+#ifdef TIME_THROTTLE_MESSAGES
+#define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!)
+static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
+#endif
+
+static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Idle Network");
+
+void LLAppViewer::idleNetwork()
+{
+	LLMemType mt_in(LLMemType::MTYPE_IDLE_NETWORK);
+	pingMainloopTimeout("idleNetwork");
+	
+	gObjectList.mNumNewObjects = 0;
+	S32 total_decoded = 0;
+
+	if (!gSavedSettings.getBOOL("SpeedTest"))
+	{
+		LLFastTimer t(FTM_IDLE_NETWORK); // decode
+		
+		LLTimer check_message_timer;
+		//  Read all available packets from network 
+		const S64 frame_count = gFrameCount;  // U32->S64
+		F32 total_time = 0.0f;
+
+		while (gMessageSystem->checkAllMessages(frame_count, gServicePump)) 
+		{
+			if (gDoDisconnect)
+			{
+				// We're disconnecting, don't process any more messages from the server
+				// We're usually disconnecting due to either network corruption or a
+				// server going down, so this is OK.
+				break;
+			}
+			
+			total_decoded++;
+			gPacketsIn++;
+
+			if (total_decoded > MESSAGE_MAX_PER_FRAME)
+			{
+				break;
+			}
+
+#ifdef TIME_THROTTLE_MESSAGES
+			// Prevent slow packets from completely destroying the frame rate.
+			// This usually happens due to clumps of avatars taking huge amount
+			// of network processing time (which needs to be fixed, but this is
+			// a good limit anyway).
+			total_time = check_message_timer.getElapsedTimeF32();
+			if (total_time >= CheckMessagesMaxTime)
+				break;
+#endif
+		}
+
+		// Handle per-frame message system processing.
+		gMessageSystem->processAcks();
+
+#ifdef TIME_THROTTLE_MESSAGES
+		if (total_time >= CheckMessagesMaxTime)
+		{
+			// Increase CheckMessagesMaxTime so that we will eventually catch up
+			CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames
+		}
+		else
+		{
+			// Reset CheckMessagesMaxTime to default value
+			CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
+		}
+#endif
+		
+
+
+		// we want to clear the control after sending out all necessary agent updates
+		gAgent.resetControlFlags();
+				
+		// Decode enqueued messages...
+		S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
+
+		if( remaining_possible_decodes <= 0 )
+		{
+			llinfos << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << llendl;
+		}
+
+		if (gPrintMessagesThisFrame)
+		{
+			llinfos << "Decoded " << total_decoded << " msgs this frame!" << llendl;
+			gPrintMessagesThisFrame = FALSE;
+		}
+	}
+	LLViewerStats::getInstance()->mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
+
+	// Retransmit unacknowledged packets.
+	gXferManager->retransmitUnackedPackets();
+	gAssetStorage->checkForTimeouts();
+	gViewerThrottle.updateDynamicThrottle();
+
+	// Check that the circuit between the viewer and the agent's current
+	// region is still alive
+	LLViewerRegion *agent_region = gAgent.getRegion();
+	if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED))
+	{
+		LLUUID this_region_id = agent_region->getRegionID();
+		bool this_region_alive = agent_region->isAlive();
+		if ((mAgentRegionLastAlive && !this_region_alive) // newly dead
+		    && (mAgentRegionLastID == this_region_id)) // same region
+		{
+			forceDisconnect(LLTrans::getString("AgentLostConnection"));
+		}
+		mAgentRegionLastID = this_region_id;
+		mAgentRegionLastAlive = this_region_alive;
+	}
+}
+
+void LLAppViewer::disconnectViewer()
+{
+	if (gDisconnected)
+	{
+		return;
+	}
+	//
+	// Cleanup after quitting.
+	//	
+	// Save snapshot for next time, if we made it through initialization
+
+	llinfos << "Disconnecting viewer!" << llendl;
+
+	// Dump our frame statistics
+
+	// Remember if we were flying
+	gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() );
+
+	// Un-minimize all windows so they don't get saved minimized
+	if (!gNoRender)
+	{
+		if (gFloaterView)
+		{
+			gFloaterView->restoreAll();
+		}
+	}
+
+	if (LLSelectMgr::getInstance())
+	{
+		LLSelectMgr::getInstance()->deselectAll();
+	}
+
+	// save inventory if appropriate
+	gInventory.cache(gInventory.getRootFolderID(), gAgent.getID());
+	if (gInventory.getLibraryRootFolderID().notNull()
+		&& gInventory.getLibraryOwnerID().notNull())
+	{
+		gInventory.cache(
+			gInventory.getLibraryRootFolderID(),
+			gInventory.getLibraryOwnerID());
+	}
+
+	saveNameCache();
+
+	// close inventory interface, close all windows
+	LLFloaterInventory::cleanup();
+
+	gAgentWearables.cleanup();
+	gAgentCamera.cleanup();
+	// Also writes cached agent settings to gSavedSettings
+	gAgent.cleanup();
+
+	// This is where we used to call gObjectList.destroy() and then delete gWorldp.
+	// Now we just ask the LLWorld singleton to cleanly shut down.
+	if(LLWorld::instanceExists())
+	{
+		LLWorld::getInstance()->destroyClass();
+	}
+
+	// call all self-registered classes
+	LLDestroyClassList::instance().fireCallbacks();
+
+	cleanup_xfer_manager();
+	gDisconnected = TRUE;
+
+	// Pass the connection state to LLUrlEntryParcel not to attempt
+	// parcel info requests while disconnected.
+	LLUrlEntryParcel::setDisconnected(gDisconnected);
+}
+
+void LLAppViewer::forceErrorLLError()
+{
+   	llerrs << "This is an llerror" << llendl;
+}
+
+void LLAppViewer::forceErrorBreakpoint()
+{
+#ifdef LL_WINDOWS
+    DebugBreak();
+#endif
+    return;
+}
+
+void LLAppViewer::forceErrorBadMemoryAccess()
+{
+    S32* crash = NULL;
+    *crash = 0xDEADBEEF;  
+    return;
+}
+
+void LLAppViewer::forceErrorInfiniteLoop()
+{
+    while(true)
+    {
+        ;
+    }
+    return;
+}
+ 
+void LLAppViewer::forceErrorSoftwareException()
+{
+    // *FIX: Any way to insure it won't be handled?
+    throw; 
+}
+
+void LLAppViewer::forceErrorDriverCrash()
+{
+	glDeleteTextures(1, NULL);
+}
+
+void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
+{
+	if(!mMainloopTimeout)
+	{
+		mMainloopTimeout = new LLWatchdogTimeout();
+		resumeMainloopTimeout(state, secs);
+	}
+}
+
+void LLAppViewer::destroyMainloopTimeout()
+{
+	if(mMainloopTimeout)
+	{
+		delete mMainloopTimeout;
+		mMainloopTimeout = NULL;
+	}
+}
+
+void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
+{
+	if(mMainloopTimeout)
+	{
+		if(secs < 0.0f)
+		{
+			secs = gSavedSettings.getF32("MainloopTimeoutDefault");
+		}
+		
+		mMainloopTimeout->setTimeout(secs);
+		mMainloopTimeout->start(state);
+	}
+}
+
+void LLAppViewer::pauseMainloopTimeout()
+{
+	if(mMainloopTimeout)
+	{
+		mMainloopTimeout->stop();
+	}
+}
+
+void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
+{
+//	if(!restoreErrorTrap())
+//	{
+//		llwarns << "!!!!!!!!!!!!! Its an error trap!!!!" << state << llendl;
+//	}
+	
+	if(mMainloopTimeout)
+	{
+		if(secs < 0.0f)
+		{
+			secs = gSavedSettings.getF32("MainloopTimeoutDefault");
+		}
+
+		mMainloopTimeout->setTimeout(secs);
+		mMainloopTimeout->ping(state);
+	}
+}
+
+void LLAppViewer::handleLoginComplete()
+{
+	gLoggedInTime.start();
+	initMainloopTimeout("Mainloop Init");
+
+	// Store some data to DebugInfo in case of a freeze.
+	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
+
+	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
+	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
+	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
+	gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
+
+	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if ( parcel && parcel->getMusicURL()[0])
+	{
+		gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
+	}	
+	if ( parcel && parcel->getMediaURL()[0])
+	{
+		gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
+	}
+	
+	gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
+	gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
+	gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
+	gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
+
+	if(gAgent.getRegion())
+	{
+		gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
+		gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
+	}
+
+	if(LLAppViewer::instance()->mMainloopTimeout)
+	{
+		gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
+	}
+
+	mOnLoginCompleted();
+
+	writeDebugInfo();
+}
+
+// *TODO - generalize this and move DSO wrangling to a helper class -brad
+void LLAppViewer::loadEventHostModule(S32 listen_port)
+{
+	std::string dso_name =
+#if LL_WINDOWS
+	    "lleventhost.dll";
+#elif LL_DARWIN
+	    "liblleventhost.dylib";
+#else
+	    "liblleventhost.so";
+#endif
+
+	std::string dso_path = gDirUtilp->findFile(dso_name,
+		gDirUtilp->getAppRODataDir(),
+		gDirUtilp->getExecutableDir());
+
+	if(dso_path == "")
+	{
+		llerrs << "QAModeEventHost requested but module \"" << dso_name << "\" not found!" << llendl;
+		return;
+	}
+
+	LL_INFOS("eventhost") << "Found lleventhost at '" << dso_path << "'" << LL_ENDL;
+#if ! defined(LL_WINDOWS)
+	{
+		std::string outfile("/tmp/lleventhost.file.out");
+		std::string command("file '" + dso_path + "' > '" + outfile + "' 2>&1");
+		int rc = system(command.c_str());
+		if (rc != 0)
+		{
+			LL_WARNS("eventhost") << command << " ==> " << rc << ':' << LL_ENDL;
+		}
+		else
+		{
+			LL_INFOS("eventhost") << command << ':' << LL_ENDL;
+		}
+		{
+			std::ifstream reader(outfile.c_str());
+			std::string line;
+			while (std::getline(reader, line))
+			{
+				size_t len = line.length();
+				if (len && line[len-1] == '\n')
+					line.erase(len-1);
+				LL_INFOS("eventhost") << line << LL_ENDL;
+			}
+		}
+		remove(outfile.c_str());
+	}
+#endif // LL_WINDOWS
+
+	apr_dso_handle_t * eventhost_dso_handle = NULL;
+	apr_pool_t * eventhost_dso_memory_pool = NULL;
+
+	//attempt to load the shared library
+	apr_pool_create(&eventhost_dso_memory_pool, NULL);
+	apr_status_t rv = apr_dso_load(&eventhost_dso_handle,
+		dso_path.c_str(),
+		eventhost_dso_memory_pool);
+	llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
+	llassert_always(eventhost_dso_handle != NULL);
+
+	int (*ll_plugin_start_func)(LLSD const &) = NULL;
+	rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_start_func, eventhost_dso_handle, "ll_plugin_start");
+
+	llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
+	llassert_always(ll_plugin_start_func != NULL);
+
+	LLSD args;
+	args["listen_port"] = listen_port;
+
+	int status = ll_plugin_start_func(args);
+
+	if(status != 0)
+	{
+		llerrs << "problem loading eventhost plugin, status: " << status << llendl;
+	}
+
+	mPlugins.insert(eventhost_dso_handle);
+}
+
+void LLAppViewer::launchUpdater()
+{
+		LLSD query_map = LLSD::emptyMap();
+	// *TODO place os string in a global constant
+#if LL_WINDOWS  
+	query_map["os"] = "win";
+#elif LL_DARWIN
+	query_map["os"] = "mac";
+#elif LL_LINUX
+	query_map["os"] = "lnx";
+#elif LL_SOLARIS
+	query_map["os"] = "sol";
+#endif
+	// *TODO change userserver to be grid on both viewer and sim, since
+	// userserver no longer exists.
+	query_map["userserver"] = LLGridManager::getInstance()->getGridLabel();
+	query_map["channel"] = LLVersionInfo::getChannel();
+	// *TODO constantize this guy
+	// *NOTE: This URL is also used in win_setup/lldownloader.cpp
+	LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
+	
+	if(LLAppViewer::sUpdaterInfo)
+	{
+		delete LLAppViewer::sUpdaterInfo;
+	}
+	LLAppViewer::sUpdaterInfo = new LLAppViewer::LLUpdaterInfo() ;
+
+	// if a sim name was passed in via command line parameter (typically through a SLURL)
+	if ( LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION )
+	{
+		// record the location to start at next time
+		gSavedSettings.setString( "NextLoginLocation", LLStartUp::getStartSLURL().getSLURLString()); 
+	};
+
+#if LL_WINDOWS
+	LLAppViewer::sUpdaterInfo->mUpdateExePath = gDirUtilp->getTempFilename();
+	if (LLAppViewer::sUpdaterInfo->mUpdateExePath.empty())
+	{
+		delete LLAppViewer::sUpdaterInfo ;
+		LLAppViewer::sUpdaterInfo = NULL ;
+
+		// We're hosed, bail
+		LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL;
+		return;
+	}
+
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe";
+
+	std::string updater_source = gDirUtilp->getAppRODataDir();
+	updater_source += gDirUtilp->getDirDelimiter();
+	updater_source += "updater.exe";
+
+	LL_DEBUGS("AppInit") << "Calling CopyFile source: " << updater_source
+			<< " dest: " << LLAppViewer::sUpdaterInfo->mUpdateExePath
+			<< LL_ENDL;
+
+
+	if (!CopyFileA(updater_source.c_str(), LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), FALSE))
+	{
+		delete LLAppViewer::sUpdaterInfo ;
+		LLAppViewer::sUpdaterInfo = NULL ;
+
+		LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL;
+
+		return;
+	}
+
+	LLAppViewer::sUpdaterInfo->mParams << "-url \"" << update_url.asString() << "\"";
+
+	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << " " << LLAppViewer::sUpdaterInfo->mParams.str() << LL_ENDL;
+
+	//Explicitly remove the marker file, otherwise we pass the lock onto the child process and things get weird.
+	LLAppViewer::instance()->removeMarkerFile(); // In case updater fails
+
+	// *NOTE:Mani The updater is spawned as the last thing before the WinMain exit.
+	// see LLAppViewerWin32.cpp
+	
+#elif LL_DARWIN
+	LLAppViewer::sUpdaterInfo->mUpdateExePath = "'";
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += gDirUtilp->getAppRODataDir();
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += "/mac-updater.app/Contents/MacOS/mac-updater' -url \"";
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += update_url.asString();
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -name \"";
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += LLAppViewer::instance()->getSecondLifeTitle();
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" -bundleid \"";
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += LL_VERSION_BUNDLE_ID;
+	LLAppViewer::sUpdaterInfo->mUpdateExePath += "\" &";
+
+	LL_DEBUGS("AppInit") << "Calling updater: " << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
+
+	// Run the auto-updater.
+	system(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str()); /* Flawfinder: ignore */
+
+#elif (LL_LINUX || LL_SOLARIS) && LL_GTK
+	// we tell the updater where to find the xml containing string
+	// translations which it can use for its own UI
+	std::string xml_strings_file = "strings.xml";
+	std::vector<std::string> xui_path_vec = LLUI::getXUIPaths();
+	std::string xml_search_paths;
+	std::vector<std::string>::const_iterator iter;
+	// build comma-delimited list of xml paths to pass to updater
+	for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); )
+	{
+		std::string this_skin_dir = gDirUtilp->getDefaultSkinDir()
+			+ gDirUtilp->getDirDelimiter()
+			+ (*iter);
+		llinfos << "Got a XUI path: " << this_skin_dir << llendl;
+		xml_search_paths.append(this_skin_dir);
+		++iter;
+		if (iter != xui_path_vec.end())
+			xml_search_paths.append(","); // comma-delimit
+	}
+	// build the overall command-line to run the updater correctly
+	LLAppViewer::sUpdaterInfo->mUpdateExePath = 
+		gDirUtilp->getExecutableDir() + "/" + "linux-updater.bin" + 
+		" --url \"" + update_url.asString() + "\"" +
+		" --name \"" + LLAppViewer::instance()->getSecondLifeTitle() + "\"" +
+		" --dest \"" + gDirUtilp->getAppRODataDir() + "\"" +
+		" --stringsdir \"" + xml_search_paths + "\"" +
+		" --stringsfile \"" + xml_strings_file + "\"";
+
+	LL_INFOS("AppInit") << "Calling updater: " 
+			    << LLAppViewer::sUpdaterInfo->mUpdateExePath << LL_ENDL;
+
+	// *TODO: we could use the gdk equivalent to ensure the updater
+	// gets started on the same screen.
+	GError *error = NULL;
+	if (!g_spawn_command_line_async(LLAppViewer::sUpdaterInfo->mUpdateExePath.c_str(), &error))
+	{
+		llerrs << "Failed to launch updater: "
+		       << error->message
+		       << llendl;
+	}
+	if (error) {
+		g_error_free(error);
+	}
+#else
+	OSMessageBox(LLTrans::getString("MBNoAutoUpdate"), LLStringUtil::null, OSMB_OK);
+#endif
+
+	// *REMOVE:Mani - Saving for reference...
+	// LLAppViewer::instance()->forceQuit();
+}
+
+
+//virtual
+void LLAppViewer::setMasterSystemAudioMute(bool mute)
+{
+	gSavedSettings.setBOOL("MuteAudio", mute);
+}
+
+//virtual
+bool LLAppViewer::getMasterSystemAudioMute()
+{
+	return gSavedSettings.getBOOL("MuteAudio");
+}
+
+//----------------------------------------------------------------------------
+// Metrics-related methods (static and otherwise)
+//----------------------------------------------------------------------------
+
+/**
+ * LLViewerAssetStats collects data on a per-region (as defined by the agent's
+ * location) so we need to tell it about region changes which become a kind of
+ * hidden variable/global state in the collectors.  For collectors not running
+ * on the main thread, we need to send a message to move the data over safely
+ * and cheaply (amortized over a run).
+ */
+void LLAppViewer::metricsUpdateRegion(U64 region_handle)
+{
+	if (0 != region_handle)
+	{
+		LLViewerAssetStatsFF::set_region_main(region_handle);
+		if (LLAppViewer::sTextureFetch)
+		{
+			// Send a region update message into 'thread1' to get the new region.
+			LLAppViewer::sTextureFetch->commandSetRegion(region_handle);
+		}
+		else
+		{
+			// No 'thread1', a.k.a. TextureFetch, so update directly
+			LLViewerAssetStatsFF::set_region_thread1(region_handle);
+		}
+	}
+}
+
+
+/**
+ * Attempts to start a multi-threaded metrics report to be sent back to
+ * the grid for consumption.
+ */
+void LLAppViewer::metricsSend(bool enable_reporting)
+{
+	if (! gViewerAssetStatsMain)
+		return;
+
+	if (LLAppViewer::sTextureFetch)
+	{
+		LLViewerRegion * regionp = gAgent.getRegion();
+
+		if (enable_reporting && regionp)
+		{
+			std::string	caps_url = regionp->getCapability("ViewerMetrics");
+
+			// Make a copy of the main stats to send into another thread.
+			// Receiving thread takes ownership.
+			LLViewerAssetStats * main_stats(new LLViewerAssetStats(*gViewerAssetStatsMain));
+			
+			// Send a report request into 'thread1' to get the rest of the data
+			// and provide some additional parameters while here.
+			LLAppViewer::sTextureFetch->commandSendMetrics(caps_url,
+														   gAgentSessionID,
+														   gAgentID,
+														   main_stats);
+			main_stats = 0;		// Ownership transferred
+		}
+		else
+		{
+			LLAppViewer::sTextureFetch->commandDataBreak();
+		}
+	}
+
+	// Reset even if we can't report.  Rather than gather up a huge chunk of
+	// data, we'll keep to our sampling interval and retain the data
+	// resolution in time.
+	gViewerAssetStatsMain->reset();
+}
+
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 0c0df14ac1c9045f26d6ae51a23dc22a10011627..1fb83fe5673727d23c1feb1b341e44843887a656 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -1,1850 +1,1850 @@
-/** 
- * @file llbottomtray.cpp
- * @brief LLBottomTray class implementation
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h" // must be first include
-
-#define LLBOTTOMTRAY_CPP
-#include "llbottomtray.h"
-
-// library includes
-#include "llfloaterreg.h"
-#include "llflyoutbutton.h"
-#include "lllayoutstack.h"
-#include "llnotifications.h"
-#include "llnotificationsutil.h"
-#include "lltexteditor.h"
-
-// newview includes
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llavataractions.h"
-#include "llchiclet.h"
-#include "llfloatercamera.h"
-#include "llhints.h"
-#include "llimfloater.h" // for LLIMFloater
-#include "llnearbychatbar.h"
-#include "llsidetray.h"
-#include "llspeakbutton.h"
-#include "llsplitbutton.h"
-#include "llsyswellwindow.h"
-#include "lltoolmgr.h"
-#include "llviewerparcelmgr.h"
-
-#include "llviewerwindow.h"
-#include "llsdserialize.h"
-
-// Distance from mouse down on which drag'n'drop should be started.
-#define DRAG_START_DISTANCE 3
-
-static const std::string SORTING_DATA_FILE_NAME = "bottomtray_buttons_order.xml";
-
-LLDefaultChildRegistry::Register<LLBottomtrayButton> bottomtray_button("bottomtray_button");
-
-// LLBottomtrayButton methods
-
-// virtual
-BOOL LLBottomtrayButton::handleHover(S32 x, S32 y, MASK mask)
-{
-	if (mCanDrag)
-	{
-		// pass hover to bottomtray
-		S32 screenX, screenY;
-		localPointToScreen(x, y, &screenX, &screenY);
-		LLBottomTray::getInstance()->onDraggableButtonHover(screenX, screenY);
-
-		return TRUE;
-	}
-	else
-	{
-		return LLButton::handleHover(x, y, mask);
-	}
-}
-//virtual
-BOOL LLBottomtrayButton::handleMouseUp(S32 x, S32 y, MASK mask)
-{
-	if (mCanDrag)
-	{
-	S32 screenX, screenY;
-	localPointToScreen(x, y, &screenX, &screenY);
-	// pass mouse up to bottomtray
-	LLBottomTray::getInstance()->onDraggableButtonMouseUp(this, screenX, screenY);
-	}
-	return LLButton::handleMouseUp(x, y, mask);
-}
-//virtual
-BOOL LLBottomtrayButton::handleMouseDown(S32 x, S32 y, MASK mask)
-{
-	if (mCanDrag)
-	{
-	S32 screenX, screenY;
-	localPointToScreen(x, y, &screenX, &screenY);
-	// pass mouse up to bottomtray
-	LLBottomTray::getInstance()->onDraggableButtonMouseDown(this, screenX, screenY);
-	}
-	return LLButton::handleMouseDown(x, y, mask);
-}
-
-static void update_build_button_enable_state()
-{
-	bool can_edit = LLToolMgr::getInstance()->canEdit();
-
-	LLBottomTray::getInstance()->getChildView("build_btn")->setEnabled(can_edit);
-}
-
-// Build time optimization, generate extern template once in .cpp file
-template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();
-
-namespace
-{
-	const std::string& PANEL_CHICLET_NAME	= "chiclet_list_panel";
-
-	S32 get_panel_min_width(LLLayoutStack* stack, LLView* panel)
-	{
-		S32 minimal_width = 0;
-		llassert(stack);
-		if ( stack && panel && panel->getVisible() )
-		{
-			stack->getPanelMinSize(panel->getName(), &minimal_width);
-		}
-		return minimal_width;
-	}
-
-	S32 get_panel_max_width(LLLayoutStack* stack, LLPanel* panel)
-	{
-		S32 max_width = 0;
-		llassert(stack);
-		if ( stack && panel && panel->getVisible() )
-		{
-			stack->getPanelMaxSize(panel->getName(), &max_width);
-		}
-		return max_width;
-	}
-
-	S32 get_curr_width(LLUICtrl* ctrl)
-	{
-		S32 cur_width = 0;
-		if ( ctrl && ctrl->getVisible() )
-		{
-			cur_width = ctrl->getRect().getWidth();
-		}
-		return cur_width;
-	}
-}
-
-class LLBottomTrayLite
-	: public LLPanel
-{
-public:
-	LLBottomTrayLite()
-		: mNearbyChatBar(NULL),
-		mChatBarContainer(NULL),
-		  mGesturePanel(NULL)
-	{
-		mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
-		buildFromFile("panel_bottomtray_lite.xml");
-	}
-
-	BOOL postBuild()
-	{
-		mNearbyChatBar = findChild<LLNearbyChatBar>("chat_bar");
-		mChatBarContainer = getChild<LLLayoutPanel>("chat_bar_layout_panel");
-		mGesturePanel = getChild<LLPanel>("gesture_panel");
-
-		// Hide "show_nearby_chat" button 
-		if (mNearbyChatBar)
-		{
-			LLLineEditor* chat_box = mNearbyChatBar->getChatBox();
-			LLUICtrl* show_btn = mNearbyChatBar->getChild<LLUICtrl>("show_nearby_chat");
-			S32 delta_width = show_btn->getRect().getWidth();
-			show_btn->setVisible(FALSE);
-			chat_box->reshape(chat_box->getRect().getWidth() + delta_width, chat_box->getRect().getHeight());
-		}
-		return TRUE;
-	}
-
-	void onFocusLost()
-	{
-		if (gAgentCamera.cameraMouselook())
-		{
-			LLBottomTray::getInstance()->setVisible(FALSE);
-		}
-	}
-
-	LLNearbyChatBar*	mNearbyChatBar;
-	LLLayoutPanel*		mChatBarContainer;
-	LLPanel*			mGesturePanel;
-};
-
-LLBottomTray::LLBottomTray(const LLSD&)
-:	mChicletPanel(NULL),
-	mSpeakPanel(NULL),
-	mSpeakBtn(NULL),
-	mNearbyChatBar(NULL),
-	mChatBarContainer(NULL),
-	mNearbyCharResizeHandlePanel(NULL),
-	mToolbarStack(NULL),
-	mMovementButton(NULL),
-	mResizeState(RS_NORESIZE),
-	mBottomTrayContextMenu(NULL),
-	mCamButton(NULL),
-	mBottomTrayLite(NULL),
-	mIsInLiteMode(false),
-	mDragStarted(false),
-	mDraggedItem(NULL),
-	mLandingTab(NULL),
-	mCheckForDrag(false)
-{
-	// Firstly add ourself to IMSession observers, so we catch session events
-	// before chiclets do that.
-	LLIMMgr::getInstance()->addSessionObserver(this);
-
-	mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
-
-	buildFromFile("panel_bottomtray.xml");
-
-	LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraItem, _2));
-
-	//this is to fix a crash that occurs because LLBottomTray is a singleton
-	//and thus is deleted at the end of the viewers lifetime, but to be cleanly
-	//destroyed LLBottomTray requires some subsystems that are long gone
-	//LLUI::getRootView()->addChild(this);
-
-	{
-		mBottomTrayLite = new LLBottomTrayLite();
-		mBottomTrayLite->setFollowsAll();
-		mBottomTrayLite->setVisible(FALSE);
-	}
-
-	mImageDragIndication = LLUI::getUIImage(getString("DragIndicationImageName"));
-	mDesiredNearbyChatWidth = mNearbyChatBar ? mNearbyChatBar->getRect().getWidth() : 0;
-}
-
-LLBottomTray::~LLBottomTray()
-{
-	if (!LLSingleton<LLIMMgr>::destroyed())
-	{
-		LLIMMgr::getInstance()->removeSessionObserver(this);
-	}
-
-	if (mNearbyChatBar)
-	{
-		// store custom width of chatbar panel.
-		S32 custom_width = mChatBarContainer->getRect().getWidth();
-		gSavedSettings.setS32("ChatBarCustomWidth", custom_width);
-	}
-
-	// emulate previous floater behavior to be hidden on startup.
-	// override effect of save_visibility=true.
-	// this attribute is necessary to button.initial_callback=Button.SetFloaterToggle works properly:
-	//		i.g when floater changes its visibility - button changes its toggle state.
-	getChild<LLUICtrl>("build_btn")->setControlValue(false);
-	getChild<LLUICtrl>("search_btn")->setControlValue(false);
-	getChild<LLUICtrl>("world_map_btn")->setControlValue(false);
-}
-
-// *TODO Vadim: why void* ?
-void* LLBottomTray::createNearbyChatBar(void* userdata)
-{
-	return new LLNearbyChatBar();
-}
-
-LLNearbyChatBar* LLBottomTray::getNearbyChatBar()
-{
-	return mIsInLiteMode ? mBottomTrayLite->mNearbyChatBar : mNearbyChatBar;
-}
-
-LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
-{
-	LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id);
-
-	switch (im_chiclet_type)
-	{
-	case LLIMChiclet::TYPE_IM:
-		return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
-	case LLIMChiclet::TYPE_GROUP:
-		return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
-	case LLIMChiclet::TYPE_AD_HOC:
-		return getChicletPanel()->createChiclet<LLAdHocChiclet>(session_id);
-	case LLIMChiclet::TYPE_UNKNOWN:
-		break;
-	}
-
-	return NULL;
-}
-
-//virtual
-void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
-{
-	if (!getChicletPanel()) return;
-
-	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
-	if (!session) return;
-
-	// no need to spawn chiclets for participants in P2P calls called through Avaline
-	if (session->isP2P() && session->isOtherParticipantAvaline()) return;
-
-	if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;
-
-	LLIMChiclet* chiclet = createIMChiclet(session_id);
-	if(chiclet)
-	{
-		chiclet->setIMSessionName(name);
-		chiclet->setOtherParticipantId(other_participant_id);
-		
-		LLIMFloater::onIMChicletCreated(session_id);
-
-	}
-	else
-	{
-		llerrs << "Could not create chiclet" << llendl;
-	}
-}
-
-//virtual
-void LLBottomTray::sessionRemoved(const LLUUID& session_id)
-{
-	if(getChicletPanel())
-	{
-		// IM floater should be closed when session removed and associated chiclet closed
-		LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>(
-				"impanel", session_id);
-		if (iMfloater != NULL)
-		{
-			iMfloater->closeFloater();
-		}
-
-		getChicletPanel()->removeChiclet(session_id);
-	}
-}
-
-void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
-{
-	//this is only needed in case of outgoing ad-hoc/group chat sessions
-	LLChicletPanel* chiclet_panel = getChicletPanel();
-	if (chiclet_panel)
-	{
-		//it should be ad-hoc im chiclet or group im chiclet
-		LLChiclet* chiclet = chiclet_panel->findChiclet<LLChiclet>(old_session_id);
-		if (chiclet) chiclet->setSessionId(new_session_id);
-	}
-}
-
-S32 LLBottomTray::getTotalUnreadIMCount()
-{
-	return getChicletPanel()->getTotalUnreadIMCount();
-}
-
-// virtual
-void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, bool proximal)
-{
-	// Time it takes to connect to voice channel might be pretty long,
-	// so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED.
-	BOOL enable = FALSE;
-
-	switch (status)
-	{
-	// Do not add STATUS_VOICE_ENABLED because voice chat is 
-	// inactive until STATUS_JOINED
-	case STATUS_JOINED:
-		enable = TRUE;
-		break;
-	default:
-		enable = FALSE;
-		break;
-	}
-
-	// We have to enable/disable right and left parts of speak button separately (EXT-4648)
-	mSpeakBtn->setSpeakBtnEnabled(enable);
-	// skipped to avoid button blinking
-	if (status != STATUS_JOINING && status!= STATUS_LEFT_CHANNEL)
-	{
-		mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking());
-	}
-}
-
-void LLBottomTray::onMouselookModeOut()
-{
-	mIsInLiteMode = false;
-	mBottomTrayLite->setVisible(FALSE);
-	mNearbyChatBar->getChatBox()->setText(mBottomTrayLite->mNearbyChatBar->getChatBox()->getText());
-	setVisible(TRUE);
-}
-
-void LLBottomTray::onMouselookModeIn()
-{
-	setVisible(FALSE);
-
-	// Attach the lite bottom tray
-	if (getParent() && mBottomTrayLite->getParent() != getParent())
-		getParent()->addChild(mBottomTrayLite);
-
-	mBottomTrayLite->setShape(getLocalRect());
-	mBottomTrayLite->mNearbyChatBar->getChatBox()->setText(mNearbyChatBar->getChatBox()->getText());
-	mBottomTrayLite->mGesturePanel->setVisible(gSavedSettings.getBOOL("ShowGestureButton"));
-
-	mIsInLiteMode = true;
-}
-
-//virtual
-// setVisible used instead of onVisibilityChange, since LLAgent calls it on entering/leaving mouselook mode.
-// If bottom tray is already visible in mouselook mode, then onVisibilityChange will not be called from setVisible(true),
-void LLBottomTray::setVisible(BOOL visible)
-{
-	if (mIsInLiteMode)
-	{
-		mBottomTrayLite->setVisible(visible);
-	}
-	else 
-	{
-		LLPanel::setVisible(visible);
-	}
-}
-
-S32 LLBottomTray::notifyParent(const LLSD& info)
-{
-	if(info.has("well_empty")) // implementation of EXT-3397
-	{
-		const std::string chiclet_name = info["well_name"];
-
-		// only "im_well" or "notification_well" names are expected.
-		// They are set in panel_bottomtray.xml in <chiclet_im_well> & <chiclet_notification>
-		llassert("im_well" == chiclet_name || "notification_well" == chiclet_name);
-
-		BOOL should_be_visible = !info["well_empty"];
-		showWellButton("im_well" == chiclet_name ? RS_IM_WELL : RS_NOTIFICATION_WELL, should_be_visible);
-		return 1;
-	}
-
-	if (info.has("action") && info["action"] == "resize")
-	{
-		const std::string& name = info["view_name"];
-
-		// expected only resize of nearby chatbar
-		if (mChatBarContainer->getName() != name) return LLPanel::notifyParent(info);
-
-		const S32 new_width = info["new_width"];
-
-		processChatbarCustomization(new_width);
-
-		return 2;
-	}
-	return LLPanel::notifyParent(info);
-}
-
-void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask)
-{
-	// We should show BottomTrayContextMenu in last  turn
-	if (mBottomTrayContextMenu && !LLMenuGL::sMenuContainer->getVisibleMenu())
-	{
-		    //there are no other context menu (IM chiclet etc ), so we can show BottomTrayContextMenu
-
-		    updateContextMenu(x, y, mask);
-			mBottomTrayContextMenu->buildDrawLabels();
-			mBottomTrayContextMenu->updateParent(LLMenuGL::sMenuContainer);
-			LLMenuGL::showPopup(this, mBottomTrayContextMenu, x, y);
-		
-	}
-}
-
-void LLBottomTray::updateContextMenu(S32 x, S32 y, MASK mask)
-{
-	LLUICtrl* edit_box = mNearbyChatBar->getChild<LLUICtrl>("chat_box");
-
-	S32 local_x = x - mChatBarContainer->getRect().mLeft - edit_box->getRect().mLeft;
-	S32 local_y = y - mChatBarContainer->getRect().mBottom - edit_box->getRect().mBottom;
-
-	bool in_edit_box = edit_box->pointInView(local_x, local_y);
-
-	mBottomTrayContextMenu->setItemVisible("Separator", in_edit_box);
-	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Cut", in_edit_box);
-	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Copy", in_edit_box);
-	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Paste", in_edit_box);
-	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Delete", in_edit_box);
-	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Select_All", in_edit_box);
-}
-
-void LLBottomTray::showGestureButton(BOOL visible)
-{
-	setTrayButtonVisibleIfPossible(RS_BUTTON_GESTURES, visible);
-}
-
-void LLBottomTray::showMoveButton(BOOL visible)
-{
-	setTrayButtonVisibleIfPossible(RS_BUTTON_MOVEMENT, visible);
-}
-
-void LLBottomTray::showCameraButton(BOOL visible)
-{
-	setTrayButtonVisibleIfPossible(RS_BUTTON_CAMERA, visible);
-}
-
-void LLBottomTray::showSnapshotButton(BOOL visible)
-{
-	setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible);
-}
-
-void LLBottomTray::showSpeakButton(bool visible)
-{
-	// Show/hide the button
-	setTrayButtonVisible(RS_BUTTON_SPEAK, visible);
-
-	// and adjust other panels according to the occupied/freed space.
-	const S32 panel_width = mSpeakPanel->getRect().getWidth();
-	if (visible)
-	{
-		processWidthDecreased(-panel_width);
-	}
-	else
-	{
-		processWidthIncreased(panel_width);
-	}
-}
-
-void LLBottomTray::toggleMovementControls()
-{
-	if (mMovementButton)
-		mMovementButton->onCommit();
-}
-
-void LLBottomTray::toggleCameraControls()
-{
-	if (mCamButton)
-		mCamButton->onCommit();
-}
-
-BOOL LLBottomTray::postBuild()
-{
-	LLHints::registerHintTarget("bottom_tray", LLView::getHandle());
-	LLHints::registerHintTarget("dest_guide_btn", getChild<LLUICtrl>("destination_btn")->getHandle());
-	LLHints::registerHintTarget("avatar_picker_btn", getChild<LLUICtrl>("avatar_btn")->getHandle());
-
-	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("NearbyChatBar.Action", boost::bind(&LLBottomTray::onContextMenuItemClicked, this, _2));
-	LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("NearbyChatBar.EnableMenuItem", boost::bind(&LLBottomTray::onContextMenuItemEnabled, this, _2));
-
-	mBottomTrayContextMenu =  LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_bottomtray.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	gMenuHolder->addChild(mBottomTrayContextMenu);
-
-	mNearbyChatBar = findChild<LLNearbyChatBar>("chat_bar");
-	LLHints::registerHintTarget("chat_bar", mNearbyChatBar->LLView::getHandle());
-
-	mChatBarContainer = getChild<LLLayoutPanel>("chat_bar_layout_panel");
-	mNearbyCharResizeHandlePanel = getChild<LLPanel>("chat_bar_resize_handle_panel");
-
-	mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
-	mMovementButton = getChild<LLButton>("movement_btn");
-	LLHints::registerHintTarget("move_btn", mMovementButton->getHandle());
-	mCamButton = getChild<LLButton>("camera_btn");
-	setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
-
-	mSpeakPanel = getChild<LLPanel>("speak_panel");
-	mSpeakBtn = getChild<LLSpeakButton>("talk");
-
-	// Both parts of speak button should be initially disabled because
-	// it takes some time between logging in to world and connecting to voice channel.
-	mSpeakBtn->setSpeakBtnEnabled(false);
-	mSpeakBtn->setFlyoutBtnEnabled(false);
-
-	// Localization tool doesn't understand custom buttons like <talk_button>
-	mSpeakBtn->setSpeakToolTip( getString("SpeakBtnToolTip") );
-	mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") );
-
-	// Registering Chat Bar to receive Voice client status change notifications.
-	LLVoiceClient::getInstance()->addObserver(this);
-
-	mNearbyChatBar->getChatBox()->setContextMenu(NULL);
-
-	mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
-
-	initResizeStateContainers();
-
-	setButtonsControlsAndListeners();
-
-	initButtonsVisibility();
-
-	// update wells visibility:
-	showWellButton(RS_IM_WELL, !LLIMWellWindow::getInstance()->isWindowEmpty());
-	showWellButton(RS_NOTIFICATION_WELL, !LLNotificationWellWindow::getInstance()->isWindowEmpty());
-
-	loadButtonsOrder();
-
-	LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&update_build_button_enable_state));
-
-	return TRUE;
-}
-
-//Drag-n-drop
-
-void LLBottomTray::onDraggableButtonMouseDown(LLUICtrl* ctrl, S32 x, S32 y)
-{
-	if (ctrl == NULL) return;
-	LLView* parent_view = ctrl->getParent();
-	if(parent_view != NULL)
-	{
-		// we actually drag'n'drop panel (not button) in code, so have to find a parent
-		// of button which called this method on mouse down.
-		LLPanel* parent = dynamic_cast<LLPanel*>(parent_view);
-		// It may happen that we clicked not usual button, but button inside widget(speak, gesture)
-		// so we'll need to get a level higher to reach layout panel as a parent.
-		if(parent == NULL) parent = dynamic_cast<LLPanel*>(parent_view->getParent());
-		if (parent && parent->getVisible())
-		{
-			mDraggedItem = parent;
-			mCheckForDrag = true;
-			mStartX = x;
-			mStartY = y;
-		}
-	}
-}
-
-LLPanel* LLBottomTray::findChildPanelByLocalCoords(S32 x, S32 y)
-{
-	LLPanel* ctrl = 0;
-	S32 screenX, screenY;
-	const child_list_t* list = mToolbarStack->getChildList();
-
-	localPointToScreen(x, y, &screenX, &screenY);
-
-	// look for a child panel which contains the point (screenX, screenY) in it's rectangle
-	for (child_list_const_iter_t i = list->begin(); i != list->end(); ++i)
-	{
-		LLRect rect;
-		localRectToScreen((*i)->getRect(), &rect);
-
-		if (rect.pointInRect(screenX, screenY))
-		{
-			ctrl = dynamic_cast<LLPanel*>(*i);
-			break;
-		}
-	}
-
-	return ctrl;
-}
-
-void LLBottomTray::onDraggableButtonHover(S32 x, S32 y)
-{
-	// if mouse down on draggable item was done, check whether we should start DnD
-	if (mCheckForDrag)
-	{
-		// Start drag'n'drop if mouse cursor was dragged away frome mouse down location enough
-		if(sqrt((float)((mStartX-x)*(mStartX-x)+(mStartY-y)*(mStartY-y))) > DRAG_START_DISTANCE)
-		{
-			mDragStarted = true;
-			mCheckForDrag = false;
-		}
-	}
-	if (mDragStarted)
-	{
-		// Check whether the cursor is over draggable area, find which panel it is and set is as
-		// landing tab for drag'n'drop
-		if(isCursorOverDraggableArea(x, y))
-		{
-			LLPanel* panel = findChildPanelByLocalCoords(x,y);
-			if (panel && panel != mDraggedItem) mLandingTab = panel;
-			gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROWDRAG);
-		}
-		else
-		{
-			gViewerWindow->getWindow()->setCursor(UI_CURSOR_NO);
-		}
-	}
-	else
-	{
-		// Reset cursor in case you move your mouse from the drag handle to a button.
-		getWindow()->setCursor(UI_CURSOR_ARROW);
-
-	}
-}
-
-bool LLBottomTray::isCursorOverDraggableArea(S32 x, S32 y)
-{
-	// Draggable area lasts from the nearby chat input resize handle
-	// to the chiclet area (exlusively).
-	bool result = getRect().pointInRect(x, y);
-	result = result && mNearbyCharResizeHandlePanel->calcScreenRect().mRight < x;
-	result = result && mChicletPanel->calcScreenRect().mRight > x;
-	return result;
-}
-
-void LLBottomTray::updateButtonsOrdersAfterDnD()
-{
-	// *TODO: change implementation of this method to support simplify it
-	// (and according to future possible changes in the way button order is saved between sessions).
-	state_object_map_t::const_iterator it = mStateProcessedObjectMap.begin();
-	state_object_map_t::const_iterator it_end = mStateProcessedObjectMap.end();
-	EResizeState dragged_state = RS_NORESIZE;
-	EResizeState landing_state = RS_NORESIZE;
-	bool landing_state_found = false;
-	// Find states for dragged item and landing tab
-	for (; it != it_end; ++it)
-	{
-		if (it->second == mDraggedItem)
-		{
-			dragged_state = it->first;
-		}
-		else if (it->second == mLandingTab)
-		{
-			landing_state = it->first;
-			landing_state_found = true;
-		}
-	}
-
-	if (dragged_state == RS_NORESIZE)
-	{
-		llwarns << "Cannot determine what button is being dragged" << llendl;
-		llassert(dragged_state != RS_NORESIZE);
-		return;
-	}
-
-	lldebugs << "Will place " << resizeStateToString(dragged_state)
-		<< " before " << resizeStateToString(landing_state) << llendl;
-
-	// Update order of buttons according to drag'n'drop
-	mButtonsOrder.erase(std::find(mButtonsOrder.begin(), mButtonsOrder.end(), dragged_state));
-	if (!landing_state_found && mLandingTab == getChild<LLPanel>(PANEL_CHICLET_NAME))
-	{
-		mButtonsOrder.push_back(dragged_state);
-	}
-	else
-	{
-		if (!landing_state_found) landing_state = RS_BUTTON_SPEAK; // just a random fallback
-		mButtonsOrder.insert(std::find(mButtonsOrder.begin(), mButtonsOrder.end(), landing_state), dragged_state);
-	}
-
-	// Synchronize button process order with their order
-	resize_state_vec_t::const_iterator it1 = mButtonsOrder.begin();
-	const resize_state_vec_t::const_iterator it_end1 = mButtonsOrder.end();
-	resize_state_vec_t::iterator it2 = mButtonsProcessOrder.begin();
-	for (; it1 != it_end1; ++it1)
-	{
-		// Skip Speak because it is not in mButtonsProcessOrder(it's the reason why mButtonsOrder was introduced).
-		// If any other draggable items will be added to bottomtray later, they should also be skipped here.
-		if (*it1 != RS_BUTTON_SPEAK)
-		{
-			*it2 = *it1;
-			++it2;
-		}
-	}
-
-	saveButtonsOrder();
-}
-
-void LLBottomTray::saveButtonsOrder()
-{
-	std::string user_dir = gDirUtilp->getLindenUserDir();
-	if (user_dir.empty()) return;
-	
-	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
-	LLSD settings_llsd;
-	int i = 0;
-	const resize_state_vec_t::const_iterator it_end = mButtonsOrder.end();
-	// we use numbers as keys for map which is saved in file and contains resize states as its values
-	for (resize_state_vec_t::const_iterator it = mButtonsOrder.begin(); it != it_end; ++it, i++)
-	{
-		std::string str = llformat("%d", i);
-		settings_llsd[str] = *it;		
-	}
-	llofstream file;
-	file.open(filename);
-	LLSDSerialize::toPrettyXML(settings_llsd, file);
-}
-
-void LLBottomTray::loadButtonsOrder()
-{
-	// load per-resident sorting information
-	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
-
-	LLSD settings_llsd;
-	llifstream file;
-	file.open(filename);
-	if (!file.is_open()) return;
-	
-	LLSDSerialize::fromXML(settings_llsd, file);
-	
-
-	mButtonsOrder.clear();
-	mButtonsProcessOrder.clear();
-	int i = 0;
-	// getting button order from file
-	for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
-		iter != settings_llsd.endMap(); ++iter, ++i)
-	{
-		std::string str = llformat("%d", i);
-		EResizeState state = (EResizeState)settings_llsd[str].asInteger();
-		mButtonsOrder.push_back(state);
-		// RS_BUTTON_SPEAK is skipped, because it shouldn't be in mButtonsProcessOrder (it does not hide or shrink).
-		if (state != RS_BUTTON_SPEAK)
-		{
-			mButtonsProcessOrder.push_back(state);
-		}		
-	}
-
-	// There are other panels in layout stack order of which is not saved. Also, panels order of which is saved,
-	// are already in layout stack but in wrong order. The most convenient way to place them is moving them 
-	// to front one by one (because in this case we don't have to pass the panel before which we want to insert our
-	// panel to movePanel()). So panels are moved in order from the end of mButtonsOrder vector(reverse iterator is used).
-	const resize_state_vec_t::const_reverse_iterator it_end = mButtonsOrder.rend();
-	// placing panels in layout stack according to button order which we loaded in previous for
-	for (resize_state_vec_t::const_reverse_iterator it = mButtonsOrder.rbegin(); it != it_end; ++it, ++i)
-	{
-		LLPanel* panel_to_move = getButtonPanel(*it);
-		mToolbarStack->movePanel(panel_to_move, NULL, true); // prepend 		
-	}
-	// Nearbychat is not stored in order settings file, but it must be the first of the panels, so moving it
-	// (along with its drag handle) manually here.
-	mToolbarStack->movePanel(getChild<LLLayoutPanel>("chat_bar_resize_handle_panel"), NULL, true);
-	mToolbarStack->movePanel(mChatBarContainer, NULL, true);
-}
-
-void LLBottomTray::onDraggableButtonMouseUp(LLUICtrl* ctrl, S32 x, S32 y)
-{
-	//if mouse up happened over area where drop is possible, change order of buttons
-	if (mLandingTab != NULL && mDraggedItem != NULL && mDragStarted)
-	{
-		if(isCursorOverDraggableArea(x, y))
-		{
-			// change order of panels in layout stack
-			mToolbarStack->movePanel(mDraggedItem, (LLPanel*)mLandingTab);
-			// change order of buttons in order vectors
-			updateButtonsOrdersAfterDnD();
-		}
-	}
-	gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
-	mDragStarted = false;
-	mDraggedItem = NULL;
-	mLandingTab = NULL;
-	mCheckForDrag = false;
-}
-
-void LLBottomTray::draw()
-{
-	LLPanel::draw();
-	if (mLandingTab)
-	{
-		static S32 w = mImageDragIndication->getWidth();
-		static S32 h = mImageDragIndication->getHeight();
-		LLRect rect = mLandingTab->calcScreenRect();
-		mImageDragIndication->draw(rect.mLeft - w/2, rect.getHeight(), w, h);
-	}
-	getChild<LLButton>("show_profile_btn")->setToggleState(LLAvatarActions::profileVisible(gAgent.getID()));
-
-	LLPanel* panel = LLSideTray::getInstance()->getPanel("panel_people");
-	if (panel && panel->isInVisibleChain())
-	{
-		getChild<LLButton>("show_people_button")->setToggleState(true);
-	}
-	else
-	{
-		getChild<LLButton>("show_people_button")->setToggleState(false);
-	}
-
-	LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser"));
-	bool help_floater_visible = (help_browser && help_browser->isInVisibleChain());
-
-	getChild<LLButton>("show_help_btn")->setToggleState(help_floater_visible);
-
-
-}
-
-bool LLBottomTray::onContextMenuItemEnabled(const LLSD& userdata)
-{
-	std::string item = userdata.asString();
-	LLLineEditor* edit_box = mNearbyChatBar->findChild<LLLineEditor>("chat_box");
-	
-	if (item == "can_cut")
-	{
-		return edit_box->canCut();
-	}
-	else if (item == "can_copy")
-	{
-		return edit_box->canCopy();
-	}
-	else if (item == "can_paste")
-	{
-		return edit_box->canPaste();
-	}
-	else if (item == "can_delete")
-	{
-		return edit_box->canDoDelete();
-	}
-	else if (item == "can_select_all")
-	{
-		return edit_box->canSelectAll() && (edit_box->getLength()>0);
-	}
-	return true;
-}
-
-
-void LLBottomTray::onContextMenuItemClicked(const LLSD& userdata)
-{
-	std::string item = userdata.asString();
-	LLLineEditor* edit_box = mNearbyChatBar->findChild<LLLineEditor>("chat_box");
-
-	if (item == "cut")
-	{
-		edit_box->cut();
-	}
-	else if (item == "copy")
-	{
-		edit_box->copy();
-	}
-	else if (item == "paste")
-	{
-		edit_box->paste();
-		edit_box->setFocus(TRUE);
-	}
-	else if (item == "delete")
-	{
-		edit_box->doDelete();
-	}
-	else if (item == "select_all")
-	{
-		edit_box->selectAll();
-	}
-}
-
-void LLBottomTray::log(LLView* panel, const std::string& descr)
-{
-	if (NULL == panel) return;
-	LLView* layout = panel->getParent();
-	lldebugs << descr << ": "
-		<< "panel: " << panel->getName()
-		<< ", rect: " << panel->getRect()
- 
- 
-		<< "layout: " << layout->getName()
-		<< ", rect: " << layout->getRect()
-		<< llendl
-		; 
-}
-
-void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
-	static S32 debug_calling_number = 0;
-	lldebugs << "**************************************** " << ++debug_calling_number << llendl;
-
-	S32 current_width = getRect().getWidth();
-	S32 delta_width = width - current_width;
-	lldebugs << "Reshaping: " 
-		<< ", width: " << width
-		<< ", cur width: " << current_width
-		<< ", delta_width: " << delta_width
-		<< ", called_from_parent: " << called_from_parent
-		<< llendl;
-
-	if (mNearbyChatBar)			log(mNearbyChatBar, "before");
-	if (mChicletPanel)			log(mChicletPanel, "before");
-
-	// stores width size on which bottom tray is less than width required by its children. EXT-991
-	static S32 extra_shrink_width = 0;
-	bool should_be_reshaped = true;
-
-	if (mChicletPanel && mToolbarStack && mNearbyChatBar)
-	{
-		// Firstly, update layout stack to ensure we deal with correct panel sizes.
-		{
-			BOOL saved_anim = mToolbarStack->getAnimate();
-			// Set chiclet panel to be autoresized by default.
-			mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE);
-			// Disable animation to prevent layout updating in several frames.
-			mToolbarStack->setAnimate(FALSE);
-			// Force the updating of layout to reset panels collapse factor.
-			mToolbarStack->updateLayout();
-			// Restore animate state.
-			mToolbarStack->setAnimate(saved_anim);
-		}
-
-		// bottom tray is narrowed
-		if (delta_width < 0)
-		{
-			if (extra_shrink_width > 0)
-			{
-				// is world rect was extra shrunk and decreasing again only update this value
-				// to delta_width negative
-				extra_shrink_width -= delta_width; // use "-=" because delta_width is negative
-				should_be_reshaped = false;
-			}
-			else
-			{
-				extra_shrink_width = processWidthDecreased(delta_width);
-
-				// increase new width to extra_shrink_width value to not reshape less than bottom tray minimum
-				width += extra_shrink_width;
-			}
-		}
-		// bottom tray is widen
-		else
-		{
-			if (extra_shrink_width > delta_width)
-			{
-				// Less than minimum width is more than increasing (delta_width) 
-				// only reduce it value and make no reshape
-				extra_shrink_width -= delta_width;
-				should_be_reshaped = false;
-			}
-			else 
-			{
-				if (extra_shrink_width > 0)
-				{
-					// If we have some extra shrink width let's reduce delta_width & width
-					delta_width -= extra_shrink_width;
-					width -= extra_shrink_width;
-					extra_shrink_width = 0;
-				}
-				processWidthIncreased(delta_width);
-			}
-		}
-	}
-
-	if (should_be_reshaped)
-	{
-		lldebugs << "Reshape all children with width: " << width << llendl;
-		LLPanel::reshape(width, height, called_from_parent);
-	}
-
-	if (mNearbyChatBar)			log(mNearbyChatBar, "after");
-	if (mChicletPanel)			log(mChicletPanel, "after");
-
-
-	// Restore width of the chatbar on first reshape.
-	// we can not to do this from postBuild because reshape is called from parent view on startup
-	// creation after it and reset width according to resize logic.
-	static bool needs_restore_custom_state = true;
-	if (mChatBarContainer && needs_restore_custom_state)
-	{
-		// restore custom width of chatbar panel.
-		S32 new_width = gSavedSettings.getS32("ChatBarCustomWidth");
-		if (new_width > 0)
-		{
-			mDesiredNearbyChatWidth = new_width;
-			processChatbarCustomization(new_width);
-			mChatBarContainer->reshape(new_width, mChatBarContainer->getRect().getHeight());
-		}
-		needs_restore_custom_state = false;
-	}
-
-}
-
-S32 LLBottomTray::processWidthDecreased(S32 delta_width)
-{
-	bool still_should_be_processed = true;
-
-	const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
-	const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
-
-	// There are four steps of processing width decrease. If in one of them required width was reached,
-	// further are not needed.
-	// 1. Decreasing width of chiclet panel.
-	if (chiclet_panel_width > chiclet_panel_min_width)
-	{
-		// we have some space to decrease chiclet panel
-		S32 panel_delta_min = chiclet_panel_width - chiclet_panel_min_width;
-
-		S32 delta_panel = llmin(-delta_width, panel_delta_min);
-
-		lldebugs << "delta_width: " << delta_width
-			<< ", panel_delta_min: " << panel_delta_min
-			<< ", delta_panel: " << delta_panel
-			<< llendl;
-
-		// is chiclet panel width enough to process resizing?
-		delta_width += panel_delta_min;
-
-		still_should_be_processed = delta_width < 0;
-
-		mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - delta_panel, mChicletPanel->getParent()->getRect().getHeight());
-		log(mChicletPanel, "after processing panel decreasing via chiclet panel");
-
-		lldebugs << "RS_CHICLET_PANEL" 
-			<< ", delta_width: " << delta_width
-			<< llendl;
-	}
-
-	S32 buttons_freed_width = 0;
-	// 2. Decreasing width of buttons.
-	if (still_should_be_processed)
-	{
-		processShrinkButtons(delta_width, buttons_freed_width);
-	}
-	// 3. Decreasing width of nearby chat.
-	const S32 chatbar_panel_min_width = get_panel_min_width(mToolbarStack, mChatBarContainer);
-	const S32 chatbar_panel_width = mChatBarContainer->getRect().getWidth();
-	if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width)
-	{
-		// we have some space to decrease chatbar panel
-		S32 panel_delta_min = chatbar_panel_width - chatbar_panel_min_width;
-
-		S32 delta_panel = llmin(-delta_width, panel_delta_min);
-
-		// whether chatbar panel width is enough to process resizing?
-		delta_width += panel_delta_min;
-
-		still_should_be_processed = delta_width < 0;
-
-		// chatbar should only be shrunk here, not stretched
-		if(delta_panel > 0)
-		{
-			mChatBarContainer->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mChatBarContainer->getRect().getHeight());
-		}
-
-		log(mNearbyChatBar, "after processing panel decreasing via nearby chatbar panel");
-
-		lldebugs << "RS_CHATBAR_INPUT"
-			<< ", delta_panel: " << delta_panel
-			<< ", delta_width: " << delta_width
-			<< llendl;
-	}
-
-	S32 extra_shrink_width = 0;
-	// 4. Hiding buttons if needed.
-	if (still_should_be_processed)
-	{
-		processHideButtons(delta_width, buttons_freed_width);
-
-		if (delta_width < 0)
-		{
-			extra_shrink_width = -delta_width;
-			llwarns << "There is no enough width to reshape all children: " 
-				<< extra_shrink_width << llendl;
-		}
-
-		if (buttons_freed_width > 0)
-		{
-			S32 nearby_needed_width = mDesiredNearbyChatWidth - mNearbyChatBar->getRect().getWidth();
-			if (nearby_needed_width > 0)
-			{
-				S32 compensative_width = nearby_needed_width > buttons_freed_width ? buttons_freed_width : nearby_needed_width; 
-				log(mNearbyChatBar, "before applying compensative width");
-				mChatBarContainer->reshape(mChatBarContainer->getRect().getWidth() + compensative_width, mChatBarContainer->getRect().getHeight() );
-				log(mNearbyChatBar, "after applying compensative width");
-				lldebugs << buttons_freed_width << llendl;
-			}
-		}
-	}
-
-	return extra_shrink_width;
-}
-
-void LLBottomTray::processWidthIncreased(S32 delta_width)
-{
-	if (delta_width <= 0) return;
-
-	const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
-	static const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
-
-	const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;
-
-	// how many room we have to show hidden buttons
-	S32 total_available_width = delta_width + available_width_chiclet;
-
-	lldebugs << "Processing extending, available width:"
-		<< ", chiclets - " << available_width_chiclet
-		<< ", total - " << total_available_width
-		<< llendl;
-
-	S32 available_width = total_available_width;
-
-	processShowButtons(available_width);
-
-	// if we have to show/extend some buttons but resized delta width is not enough...
-	S32 processed_width = total_available_width - available_width;
-	if (processed_width > delta_width)
-	{
-		// ... let's shrink nearby chat & chiclet panels
-		S32 required_to_process_width = processed_width;
-
-		// 1. use delta width of resizing
-		required_to_process_width -= delta_width;
-
-		// 2. use width available via decreasing of chiclet panel
-		if (required_to_process_width > 0)
-		{
-			mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_to_process_width, mChicletPanel->getParent()->getRect().getHeight());
-			log(mChicletPanel, "after applying compensative width for chiclets: ");
-			lldebugs << required_to_process_width << llendl;
-		}
-
-	}
-
-	// shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels
-	delta_width -= processed_width;
-
-
-	// how many space can nearby chatbar take?
-	S32 chatbar_panel_width_ = mChatBarContainer->getRect().getWidth();
-	if (delta_width > 0 && chatbar_panel_width_ < mDesiredNearbyChatWidth)
-	{
-		S32 delta_panel_max = mDesiredNearbyChatWidth - chatbar_panel_width_;
-		S32 delta_panel = llmin(delta_width, delta_panel_max);
-		lldebugs << "Unprocesed delta width: " << delta_width
-			<< ", can be applied to chatbar: " << delta_panel_max
-			<< ", will be applied: " << delta_panel
-			<< llendl;
-
-		delta_width -= delta_panel_max;
-		mChatBarContainer->reshape(chatbar_panel_width_ + delta_panel, mChatBarContainer->getRect().getHeight());
-		log(mNearbyChatBar, "applied unprocessed delta width");
-	}
-	if (delta_width > 0)
-	{
-		processExtendButtons(delta_width);
-	}
-}
-
-void LLBottomTray::processShowButtons(S32& available_width)
-{
-	// process buttons from left to right
-	resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
-	const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
-
-	for (; it != it_end; ++it)
-	{
-		// is there available space?
-		if (available_width <= 0) break;
-
-		// try to show next button
-		processShowButton(*it, available_width);
-	}
-}
-
-bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32& available_width)
-{
-	lldebugs << "Trying to show object type: " << shown_object_type << llendl;
-
-	LLPanel* panel = getButtonPanel(shown_object_type);
-	if (NULL == panel)
-	{
-		lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
-		return false;
-	}
-	bool can_be_shown = canButtonBeShown(shown_object_type);
-	if (can_be_shown)
-	{
-		//validate if we have enough room to show this button
-		const S32 required_width = panel->getRect().getWidth();
-		can_be_shown = available_width >= required_width;
-		if (can_be_shown)
-		{
-			available_width -= required_width;
-
-			setTrayButtonVisible(shown_object_type, true);
-
-			lldebugs << "processed object type: " << shown_object_type
-				<< ", rest available width: " << available_width
-				<< llendl;
-			mResizeState &= ~shown_object_type;
-		}
-	}
-	return can_be_shown;
-}
-
-void LLBottomTray::processHideButtons(S32& required_width, S32& buttons_freed_width)
-{
-	// process buttons from right to left
-	resize_state_vec_t::const_reverse_iterator it = mButtonsProcessOrder.rbegin();
-	const resize_state_vec_t::const_reverse_iterator it_end = mButtonsProcessOrder.rend();
-
-	for (; it != it_end; ++it)
-	{
-		// is it still necessary to hide a button?
-		if (required_width >= 0) break;
-
-		// try to hide next button
-		processHideButton(*it, required_width, buttons_freed_width);
-	}
-}
-
-void LLBottomTray::processHideButton(EResizeState processed_object_type, S32& required_width, S32& buttons_freed_width)
-{
-	lldebugs << "Trying to hide object type: " << processed_object_type << llendl;
-	LLPanel* panel = getButtonPanel(processed_object_type);
-	if (NULL == panel)
-	{
-		lldebugs << "There is no object to process for state: " << processed_object_type << llendl;
-		return;
-	}
-
-	if (panel->getVisible())
-	{
-		required_width += panel->getRect().getWidth();
-
-		if (required_width > 0)
-		{
-			buttons_freed_width += required_width;
-		}
-
-		setTrayButtonVisible(processed_object_type, false);
-
-		mResizeState |= processed_object_type;
-
-		lldebugs << "processing object type: " << processed_object_type
-			<< ", buttons_freed_width: " << buttons_freed_width
-			<< llendl;
-	}
-}
-
-void LLBottomTray::processShrinkButtons(S32& required_width, S32& buttons_freed_width)
-{
-	// process buttons from right to left
-	resize_state_vec_t::const_reverse_iterator it = mButtonsProcessOrder.rbegin();
-	const resize_state_vec_t::const_reverse_iterator it_end = mButtonsProcessOrder.rend();
-
-	// iterate through buttons in the mButtonsProcessOrder first
-	for (; it != it_end; ++it)
-	{
-		// is it still necessary to hide a button?
-		if (required_width >= 0) break;
-
-		// try to shrink next button
-		processShrinkButton(*it, required_width);
-	}
-
-	// then shrink Speak button
-	if (required_width < 0)
-	{
-		S32 panel_min_width = 0;
-		std::string panel_name = mSpeakPanel->getName();
-		bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width);
-		if (!success)
-		{
-			lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
-		}
-		else
-		{
-			S32 panel_width = mSpeakPanel->getRect().getWidth();
-			S32 possible_shrink_width = panel_width - panel_min_width;
-
-			if (possible_shrink_width > 0)
-			{
-				mSpeakBtn->setLabelVisible(false);
-				mSpeakPanel->reshape(panel_width - possible_shrink_width, mSpeakPanel->getRect().getHeight());
-
-				required_width += possible_shrink_width;
-
-				if (required_width > 0)
-				{
-					buttons_freed_width += required_width;
-				}
-
-				lldebugs << "Shrunk Speak button panel: " << panel_name
-					<< ", shrunk width: " << possible_shrink_width
-					<< ", rest width to process: " << required_width
-					<< llendl;
-			}
-		}
-	}
-}
-
-void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32& required_width)
-{
-	LLPanel* panel = getButtonPanel(processed_object_type);
-	if (NULL == panel)
-	{
-		lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
-		return;
-	}
-
-	if (panel->getVisible())
-	{
-		S32 panel_width = panel->getRect().getWidth();
-		S32 panel_min_width = 0;
-		std::string panel_name = panel->getName();
-		bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width);
-		S32 possible_shrink_width = panel_width - panel_min_width;
-
-		if (!success)
-		{
-			lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
-		}
-		// we have some space to free by shrinking the button
-		else if (possible_shrink_width > 0)
-		{
-			// let calculate real width to shrink
-
-			// 1. apply all possible width
-			required_width += possible_shrink_width;
-
-			// 2. it it is too much... 
-			if (required_width > 0)
-			{
-				// reduce applied shrunk width to the excessive value.
-				possible_shrink_width -= required_width;
-				required_width = 0;
-			}
-			panel->reshape(panel_width - possible_shrink_width, panel->getRect().getHeight());
-
-			lldebugs << "Shrunk panel: " << panel_name
-				<< ", shrunk width: " << possible_shrink_width
-				<< ", rest width to process: " << required_width
-				<< llendl;
-		}
-	}
-}
-
-
-void LLBottomTray::processExtendButtons(S32& available_width)
-{
-	// do not allow extending any buttons if we have some buttons hidden via resize
-	if (mResizeState & RS_BUTTONS_CAN_BE_HIDDEN) return;
-
-	// process buttons from left to right
-	resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
-	const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
-
-	// iterate through buttons in the mButtonsProcessOrder first
-	for (; it != it_end; ++it)
-	{
-		// is there available space?
-		if (available_width <= 0) break;
-
-		// try to extend next button
-		processExtendButton(*it, available_width);
-	}
-
-	const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
-	static const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
-	const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;
-
-	// then try to extend Speak button
-	if (available_width > 0 || available_width_chiclet > 0)
-	{
-		S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK];
-		S32 panel_width = mSpeakPanel->getRect().getWidth();
-		S32 possible_extend_width = panel_max_width - panel_width;
-
-		if (possible_extend_width >= 0 && possible_extend_width <= available_width + available_width_chiclet)  // HACK: this button doesn't change size so possible_extend_width will be 0
-		{
-			mSpeakBtn->setLabelVisible(true);
-			mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight());
-			log(mSpeakBtn, "speak button is extended");
-
-			if( available_width > possible_extend_width)
-			{
-				available_width -= possible_extend_width;
-			}
-			else
-			{
-				S32 required_width = possible_extend_width - available_width;
-				available_width = 0;
-				mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_width, mChicletPanel->getParent()->getRect().getHeight());
-			}
-			lldebugs << "Extending Speak button panel: " << mSpeakPanel->getName()
-				<< ", extended width: " << possible_extend_width
-				<< ", rest width to process: " << available_width
-				<< llendl;
-		}
-	}
-}
-
-void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32& available_width)
-{
-	LLPanel* panel = getButtonPanel(processed_object_type);
-	if (NULL == panel)
-	{
-		lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
-		return;
-	}
-
-	if (!panel->getVisible()) return;
-
-	S32 panel_max_width = mObjectDefaultWidthMap[processed_object_type];
-	S32 panel_width = panel->getRect().getWidth();
-	S32 possible_extend_width = panel_max_width - panel_width;
-
-	if (possible_extend_width > 0)
-	{
-		// let calculate real width to extend
-
-		// 1. apply all possible width
-		available_width -= possible_extend_width;
-
-		// 2. it it is too much... 
-		if (available_width < 0)
-		{
-			// reduce applied extended width to the excessive value.
-			possible_extend_width += available_width;
-			available_width = 0;
-		}
-		panel->reshape(panel_width + possible_extend_width, panel->getRect().getHeight());
-
-		lldebugs << "Extending panel: " << panel->getName()
-			<< ", extended width: " << possible_extend_width
-			<< ", rest width to process: " << available_width
-			<< llendl;
-	}
-}
-
-bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const
-{
-	// 0. Check if passed button was previously hidden on resize
-	bool can_be_shown = mResizeState & processed_object_type;
-	if (can_be_shown)
-	{
-		// Yes, it was. Lets now check that all buttons before it (that can be hidden on resize)
-		// are already shown
-
-		// process buttons in direct order (from left to right)
-		resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
-		const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
-
-		// 1. Find and accumulate all buttons types before one passed into the method.
-		MASK buttons_before_mask = RS_NORESIZE;
-		for (; it != it_end; ++it)
-		{
-			const EResizeState button_type = *it;
-			if (button_type == processed_object_type) break;
-
-			buttons_before_mask |= button_type;
-		}
-
-		// 2. Check if some previous buttons are still hidden on resize
-		can_be_shown = !(buttons_before_mask & mResizeState);
-	}
-	return can_be_shown;
-}
-
-void LLBottomTray::initResizeStateContainers()
-{
-	// init map with objects should be processed for each type
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SPEAK, getChild<LLPanel>("speak_panel")));
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, getChild<LLPanel>("gesture_panel")));
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, getChild<LLPanel>("movement_panel")));
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, getChild<LLPanel>("cam_panel")));
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, getChild<LLPanel>("snapshot_panel")));
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_BUILD, getChild<LLPanel>("build_btn_panel")));
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SEARCH, getChild<LLPanel>("search_btn_panel")));
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_WORLD_MAP, getChild<LLPanel>("world_map_btn_panel")));
-	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MINI_MAP, getChild<LLPanel>("mini_map_btn_panel")));
-
-	// init an order of processed buttons
-	mButtonsProcessOrder.push_back(RS_BUTTON_GESTURES);
-	mButtonsProcessOrder.push_back(RS_BUTTON_MOVEMENT);
-	mButtonsProcessOrder.push_back(RS_BUTTON_CAMERA);
-	mButtonsProcessOrder.push_back(RS_BUTTON_SNAPSHOT);
-	mButtonsProcessOrder.push_back(RS_BUTTON_BUILD);
-	mButtonsProcessOrder.push_back(RS_BUTTON_SEARCH);
-	mButtonsProcessOrder.push_back(RS_BUTTON_WORLD_MAP);
-	mButtonsProcessOrder.push_back(RS_BUTTON_MINI_MAP);
-
-	mButtonsOrder.push_back(RS_BUTTON_SPEAK);
-	mButtonsOrder.insert(mButtonsOrder.end(), mButtonsProcessOrder.begin(), mButtonsProcessOrder.end());
-
-	// init default widths
-
-	// process buttons that can be hidden on resize...
-	resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
-	const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
-
-	for (; it != it_end; ++it)
-	{
-		const EResizeState button_type = *it;
-		// is there an appropriate object?
-		LLPanel* button_panel = getButtonPanel(button_type);
-		if (!button_panel) continue;
-
-		// set default width for it.
-		mObjectDefaultWidthMap[button_type] = button_panel->getRect().getWidth();
-	}
-
-	// ... and add Speak button because it also can be shrunk.
-	mObjectDefaultWidthMap[RS_BUTTON_SPEAK]	   = mSpeakPanel->getRect().getWidth();
-}
-
-// this method must be called before restoring of the chat entry field on startup
-// because it resets chatbar's width according to resize logic.
-void LLBottomTray::initButtonsVisibility()
-{
-	setVisibleAndFitWidths(RS_BUTTON_SPEAK, gSavedSettings.getBOOL("EnableVoiceChat"));
-	setVisibleAndFitWidths(RS_BUTTON_GESTURES, gSavedSettings.getBOOL("ShowGestureButton"));
-	setVisibleAndFitWidths(RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"));
-	setVisibleAndFitWidths(RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"));
-	setVisibleAndFitWidths(RS_BUTTON_SNAPSHOT, gSavedSettings.getBOOL("ShowSnapshotButton"));
-	setVisibleAndFitWidths(RS_BUTTON_BUILD, gSavedSettings.getBOOL("ShowBuildButton"));
-	setVisibleAndFitWidths(RS_BUTTON_SEARCH, gSavedSettings.getBOOL("ShowSearchButton"));
-	setVisibleAndFitWidths(RS_BUTTON_WORLD_MAP, gSavedSettings.getBOOL("ShowWorldMapButton"));
-	setVisibleAndFitWidths(RS_BUTTON_MINI_MAP, gSavedSettings.getBOOL("ShowMiniMapButton"));
-}
-
-void LLBottomTray::setButtonsControlsAndListeners()
-{
-	gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SPEAK, _2));
-	gSavedSettings.getControl("ShowGestureButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_GESTURES, _2));
-	gSavedSettings.getControl("ShowMoveButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MOVEMENT, _2));
-	gSavedSettings.getControl("ShowCameraButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_CAMERA, _2));
-	gSavedSettings.getControl("ShowSnapshotButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SNAPSHOT, _2));
-	gSavedSettings.getControl("ShowBuildButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_BUILD, _2));
-	gSavedSettings.getControl("ShowSearchButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SEARCH, _2));
-	gSavedSettings.getControl("ShowWorldMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_WORLD_MAP, _2));
-	gSavedSettings.getControl("ShowMiniMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MINI_MAP, _2));
-
-
-	LLButton* build_btn = getChild<LLButton>("build_btn");
-	// set control name for Build button. It is not enough to link it with Button.SetFloaterToggle in xml
-	std::string vis_control_name = LLFloaterReg::declareVisibilityControl("build");
-	// Set the button control value (toggle state) to the floater visibility control (Sets the value as well)
-	build_btn->setControlVariable(LLFloater::getControlGroup()->getControl(vis_control_name));
-}
-
-bool LLBottomTray::toggleShowButton(LLBottomTray::EResizeState button_type, const LLSD& new_visibility)
-{
-	if (LLBottomTray::instanceExists())
-	{
-		LLBottomTray::getInstance()->setTrayButtonVisibleIfPossible(button_type, new_visibility.asBoolean());
-	}
-	return true;
-}
-
-void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible)
-{
-	LLPanel* panel = getButtonPanel(shown_object_type);
-	if (NULL == panel)
-	{
-		lldebugs << "There is no object to show for state: " << shown_object_type << llendl;
-		return;
-	}
-
-	panel->setVisible(visible);
-}
-
-void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification)
-{
-	if (!setVisibleAndFitWidths(shown_object_type, visible) && visible && raise_notification)
-	{
-		LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown",
-								 LLSD(),
-								 LLSD(),
-								 LLNotificationFunctorRegistry::instance().DONOTHING);
-	}
-}
-
-bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible)
-{
-	// The Speak button is treated specially: if voice is enabled,
-	// the button should be displayed no matter how much space we've got.
-	if (object_type == RS_BUTTON_SPEAK)
-	{
-		showSpeakButton(visible);
-		return true;
-	}
-
-	LLPanel* cur_panel = getButtonPanel(object_type);
-	if (NULL == cur_panel)
-	{
-		lldebugs << "There is no object to process for state: " << object_type << llendl;
-		return false;
-	}
-
-	bool is_set = true;
-
-	if (visible)
-	{
-		// Assume that only chiclet panel can be auto-resized
-		const S32 available_width =
-			mChicletPanel->getParent()->getRect().getWidth() - mChicletPanel->getMinWidth();
-
-		S32 preferred_width = mObjectDefaultWidthMap[object_type];
-		S32 current_width = cur_panel->getRect().getWidth();
-		S32 result_width = 0;
-		bool decrease_width = false;
-
-		// Mark this button to be shown
-		mResizeState |= object_type;
-
-		if (preferred_width > 0 && available_width >= preferred_width)
-		{
-			result_width = preferred_width;
-		}
-		else if (available_width >= current_width)
-		{
-			result_width = current_width;
-		}
-		else
-		{
-			// Calculate the possible shrunk width as difference between current and minimal widths
-			const S32 chatbar_shrunk_width =
-				mChatBarContainer->getRect().getWidth() - get_panel_min_width(mToolbarStack, mChatBarContainer);
-
-			S32 sum_of_min_widths = get_panel_min_width(mToolbarStack, mSpeakPanel);
-			S32 sum_of_curr_widths = get_curr_width(mSpeakPanel);
-
-			resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
-			const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
-
-			for (; it != it_end; ++it)
-			{
-				LLPanel* cur_panel = getButtonPanel(*it);
-				sum_of_min_widths += get_panel_min_width(mToolbarStack, cur_panel);
-				sum_of_curr_widths += get_curr_width(cur_panel);
-			}
-
-			const S32 possible_shrunk_width =
-				chatbar_shrunk_width + (sum_of_curr_widths - sum_of_min_widths);
-
-			// Minimal width of current panel
-			S32 minimal_width = 0;
-			mToolbarStack->getPanelMinSize(cur_panel->getName(), &minimal_width);
-
-			if ( (available_width + possible_shrunk_width) >= minimal_width)
-			{
-				// There is enough space for minimal width, but set the result_width
-				// to preferred_width so buttons widths decreasing will be done in predefined order
-				result_width = (preferred_width > 0) ? preferred_width : current_width;
-				decrease_width = true;
-			}
-			else
-			{
-				// Nothing can be done, give up...
-				return false;
-			}
-		}
-
-		if (result_width != current_width)
-		{
-			cur_panel->reshape(result_width, cur_panel->getRect().getHeight());
-			current_width = result_width;
-		}
-
-		is_set = processShowButton(object_type, current_width);
-
-		// Shrink buttons if needed
-		if (is_set && decrease_width)
-		{
-			processWidthDecreased( -result_width);
-		}
-	}
-	else
-	{
-		const S32 delta_width = get_curr_width(cur_panel);
-
-		setTrayButtonVisible(object_type, false);
-
-		// Mark button NOT to show while future bottom tray extending
-		mResizeState &= ~object_type;
-
-		// Extend other buttons if need
-		if (delta_width)
-		{
-			processWidthIncreased(delta_width);
-		}
-	}
-	return is_set;
-}
-
-LLPanel* LLBottomTray::getButtonPanel(EResizeState button_type)
-{
-	// Don't use the operator[] because it inserts a NULL value if the key is not found.
-	if (mStateProcessedObjectMap.count(button_type) == 0)
-	{
-		llwarns << "Cannot find a panel for " << resizeStateToString(button_type) << llendl;
-		llassert(mStateProcessedObjectMap.count(button_type) == 1);
-		return NULL;
-	}
-
-	return mStateProcessedObjectMap[button_type];
-}
-
-void LLBottomTray::showWellButton(EResizeState object_type, bool visible)
-{
-	llassert( ((RS_NOTIFICATION_WELL | RS_IM_WELL) & object_type) == object_type );
-
-	const std::string panel_name = RS_IM_WELL == object_type ? "im_well_panel" : "notification_well_panel";
-
-	LLView * panel = getChild<LLView>(panel_name);
-
-	// if necessary visibility is set nothing to do here
-	if (panel->getVisible() == (BOOL)visible) return;
-
-	S32 panel_width = panel->getRect().getWidth();
-	panel->setVisible(visible);
-
-	if (visible)
-	{
-		// method assumes that input param is a negative value
-		processWidthDecreased(-panel_width);
-	}
-	else
-	{
-		processWidthIncreased(panel_width);
-	}
-}
-
-void LLBottomTray::processChatbarCustomization(S32 new_width)
-{
-	if (NULL == mNearbyChatBar) return;
-
-	const S32 delta_width = mChatBarContainer->getRect().getWidth() - new_width;
-
-	if (delta_width == 0) return;
-
-	mDesiredNearbyChatWidth = new_width;
-
-	LLView * chiclet_layout_panel = mChicletPanel->getParent();
-	const S32 chiclet_min_width = get_panel_min_width(mToolbarStack, chiclet_layout_panel);
-	const S32 chiclet_panel_width = chiclet_layout_panel->getRect().getWidth();
-	const S32 available_chiclet_shrink_width = chiclet_panel_width - chiclet_min_width;
-	llassert(available_chiclet_shrink_width >= 0);
-
-	if (delta_width > 0) // panel gets narrowly
-	{
-		S32 total_possible_width = delta_width + available_chiclet_shrink_width;
-		processShowButtons(total_possible_width);
-		processExtendButtons(total_possible_width);
-	}
-	// here (delta_width < 0) // panel gets wider
-	else //if (-delta_width > available_chiclet_shrink_width)
-	{
-		S32 required_width = delta_width + available_chiclet_shrink_width;
-		S32 buttons_freed_width = 0;
-		processShrinkButtons(required_width, buttons_freed_width);
-		processHideButtons(required_width, buttons_freed_width);
-	}
-}
-
-// static
-std::string LLBottomTray::resizeStateToString(EResizeState state)
-{
-	switch (state)
-	{
-	case RS_NORESIZE:				return "RS_NORESIZE";
-	case RS_CHICLET_PANEL:			return "RS_CHICLET_PANEL";
-	case RS_CHATBAR_INPUT:			return "RS_CHATBAR_INPUT";
-	case RS_BUTTON_SNAPSHOT:		return "RS_BUTTON_SNAPSHOT";
-	case RS_BUTTON_CAMERA:			return "RS_BUTTON_CAMERA";
-	case RS_BUTTON_MOVEMENT:		return "RS_BUTTON_MOVEMENT";
-	case RS_BUTTON_GESTURES:		return "RS_BUTTON_GESTURES";
-	case RS_BUTTON_SPEAK:			return "RS_BUTTON_SPEAK";
-	case RS_IM_WELL:				return "RS_IM_WELL";
-	case RS_NOTIFICATION_WELL:		return "RS_NOTIFICATION_WELL";
-	case RS_BUTTON_BUILD:			return "RS_BUTTON_BUILD";
-	case RS_BUTTON_SEARCH:			return "RS_BUTTON_SEARCH";
-	case RS_BUTTON_WORLD_MAP:		return "RS_BUTTON_WORLD_MAP";
-	case RS_BUTTON_MINI_MAP:		return "RS_BUTTON_MINI_MAP";
-	case RS_BUTTONS_CAN_BE_HIDDEN:	return "RS_BUTTONS_CAN_BE_HIDDEN";
-	// No default to track additions.
-	}
-	return "UNKNOWN_BUTTON";
-}
-
-//EOF
+/** 
+ * @file llbottomtray.cpp
+ * @brief LLBottomTray class implementation
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h" // must be first include
+
+#define LLBOTTOMTRAY_CPP
+#include "llbottomtray.h"
+
+// library includes
+#include "llfloaterreg.h"
+#include "llflyoutbutton.h"
+#include "lllayoutstack.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "lltexteditor.h"
+
+// newview includes
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llavataractions.h"
+#include "llchiclet.h"
+#include "llfloatercamera.h"
+#include "llhints.h"
+#include "llimfloater.h" // for LLIMFloater
+#include "llnearbychatbar.h"
+#include "llsidetray.h"
+#include "llspeakbutton.h"
+#include "llsplitbutton.h"
+#include "llsyswellwindow.h"
+#include "lltoolmgr.h"
+#include "llviewerparcelmgr.h"
+
+#include "llviewerwindow.h"
+#include "llsdserialize.h"
+
+// Distance from mouse down on which drag'n'drop should be started.
+#define DRAG_START_DISTANCE 3
+
+static const std::string SORTING_DATA_FILE_NAME = "bottomtray_buttons_order.xml";
+
+LLDefaultChildRegistry::Register<LLBottomtrayButton> bottomtray_button("bottomtray_button");
+
+// LLBottomtrayButton methods
+
+// virtual
+BOOL LLBottomtrayButton::handleHover(S32 x, S32 y, MASK mask)
+{
+	if (mCanDrag)
+	{
+		// pass hover to bottomtray
+		S32 screenX, screenY;
+		localPointToScreen(x, y, &screenX, &screenY);
+		LLBottomTray::getInstance()->onDraggableButtonHover(screenX, screenY);
+
+		return TRUE;
+	}
+	else
+	{
+		return LLButton::handleHover(x, y, mask);
+	}
+}
+//virtual
+BOOL LLBottomtrayButton::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+	if (mCanDrag)
+	{
+	S32 screenX, screenY;
+	localPointToScreen(x, y, &screenX, &screenY);
+	// pass mouse up to bottomtray
+	LLBottomTray::getInstance()->onDraggableButtonMouseUp(this, screenX, screenY);
+	}
+	return LLButton::handleMouseUp(x, y, mask);
+}
+//virtual
+BOOL LLBottomtrayButton::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+	if (mCanDrag)
+	{
+	S32 screenX, screenY;
+	localPointToScreen(x, y, &screenX, &screenY);
+	// pass mouse up to bottomtray
+	LLBottomTray::getInstance()->onDraggableButtonMouseDown(this, screenX, screenY);
+	}
+	return LLButton::handleMouseDown(x, y, mask);
+}
+
+static void update_build_button_enable_state()
+{
+	bool can_edit = LLToolMgr::getInstance()->canEdit();
+
+	LLBottomTray::getInstance()->getChildView("build_btn")->setEnabled(can_edit);
+}
+
+// Build time optimization, generate extern template once in .cpp file
+template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();
+
+namespace
+{
+	const std::string& PANEL_CHICLET_NAME	= "chiclet_list_panel";
+
+	S32 get_panel_min_width(LLLayoutStack* stack, LLView* panel)
+	{
+		S32 minimal_width = 0;
+		llassert(stack);
+		if ( stack && panel && panel->getVisible() )
+		{
+			stack->getPanelMinSize(panel->getName(), &minimal_width);
+		}
+		return minimal_width;
+	}
+
+	S32 get_panel_max_width(LLLayoutStack* stack, LLPanel* panel)
+	{
+		S32 max_width = 0;
+		llassert(stack);
+		if ( stack && panel && panel->getVisible() )
+		{
+			stack->getPanelMaxSize(panel->getName(), &max_width);
+		}
+		return max_width;
+	}
+
+	S32 get_curr_width(LLUICtrl* ctrl)
+	{
+		S32 cur_width = 0;
+		if ( ctrl && ctrl->getVisible() )
+		{
+			cur_width = ctrl->getRect().getWidth();
+		}
+		return cur_width;
+	}
+}
+
+class LLBottomTrayLite
+	: public LLPanel
+{
+public:
+	LLBottomTrayLite()
+		: mNearbyChatBar(NULL),
+		mChatBarContainer(NULL),
+		  mGesturePanel(NULL)
+	{
+		mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
+		buildFromFile("panel_bottomtray_lite.xml");
+	}
+
+	BOOL postBuild()
+	{
+		mNearbyChatBar = findChild<LLNearbyChatBar>("chat_bar");
+		mChatBarContainer = getChild<LLLayoutPanel>("chat_bar_layout_panel");
+		mGesturePanel = getChild<LLPanel>("gesture_panel");
+
+		// Hide "show_nearby_chat" button 
+		if (mNearbyChatBar)
+		{
+			LLLineEditor* chat_box = mNearbyChatBar->getChatBox();
+			LLUICtrl* show_btn = mNearbyChatBar->getChild<LLUICtrl>("show_nearby_chat");
+			S32 delta_width = show_btn->getRect().getWidth();
+			show_btn->setVisible(FALSE);
+			chat_box->reshape(chat_box->getRect().getWidth() + delta_width, chat_box->getRect().getHeight());
+		}
+		return TRUE;
+	}
+
+	void onFocusLost()
+	{
+		if (gAgentCamera.cameraMouselook())
+		{
+			LLBottomTray::getInstance()->setVisible(FALSE);
+		}
+	}
+
+	LLNearbyChatBar*	mNearbyChatBar;
+	LLLayoutPanel*		mChatBarContainer;
+	LLPanel*			mGesturePanel;
+};
+
+LLBottomTray::LLBottomTray(const LLSD&)
+:	mChicletPanel(NULL),
+	mSpeakPanel(NULL),
+	mSpeakBtn(NULL),
+	mNearbyChatBar(NULL),
+	mChatBarContainer(NULL),
+	mNearbyCharResizeHandlePanel(NULL),
+	mToolbarStack(NULL),
+	mMovementButton(NULL),
+	mResizeState(RS_NORESIZE),
+	mBottomTrayContextMenu(NULL),
+	mCamButton(NULL),
+	mBottomTrayLite(NULL),
+	mIsInLiteMode(false),
+	mDragStarted(false),
+	mDraggedItem(NULL),
+	mLandingTab(NULL),
+	mCheckForDrag(false)
+{
+	// Firstly add ourself to IMSession observers, so we catch session events
+	// before chiclets do that.
+	LLIMMgr::getInstance()->addSessionObserver(this);
+
+	mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
+
+	buildFromFile("panel_bottomtray.xml");
+
+	LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraItem, _2));
+
+	//this is to fix a crash that occurs because LLBottomTray is a singleton
+	//and thus is deleted at the end of the viewers lifetime, but to be cleanly
+	//destroyed LLBottomTray requires some subsystems that are long gone
+	//LLUI::getRootView()->addChild(this);
+
+	{
+		mBottomTrayLite = new LLBottomTrayLite();
+		mBottomTrayLite->setFollowsAll();
+		mBottomTrayLite->setVisible(FALSE);
+	}
+
+	mImageDragIndication = LLUI::getUIImage(getString("DragIndicationImageName"));
+	mDesiredNearbyChatWidth = mNearbyChatBar ? mNearbyChatBar->getRect().getWidth() : 0;
+}
+
+LLBottomTray::~LLBottomTray()
+{
+	if (!LLSingleton<LLIMMgr>::destroyed())
+	{
+		LLIMMgr::getInstance()->removeSessionObserver(this);
+	}
+
+	if (mNearbyChatBar)
+	{
+		// store custom width of chatbar panel.
+		S32 custom_width = mChatBarContainer->getRect().getWidth();
+		gSavedSettings.setS32("ChatBarCustomWidth", custom_width);
+	}
+
+	// emulate previous floater behavior to be hidden on startup.
+	// override effect of save_visibility=true.
+	// this attribute is necessary to button.initial_callback=Button.SetFloaterToggle works properly:
+	//		i.g when floater changes its visibility - button changes its toggle state.
+	getChild<LLUICtrl>("build_btn")->setControlValue(false);
+	getChild<LLUICtrl>("search_btn")->setControlValue(false);
+	getChild<LLUICtrl>("world_map_btn")->setControlValue(false);
+}
+
+// *TODO Vadim: why void* ?
+void* LLBottomTray::createNearbyChatBar(void* userdata)
+{
+	return new LLNearbyChatBar();
+}
+
+LLNearbyChatBar* LLBottomTray::getNearbyChatBar()
+{
+	return mIsInLiteMode ? mBottomTrayLite->mNearbyChatBar : mNearbyChatBar;
+}
+
+LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
+{
+	LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id);
+
+	switch (im_chiclet_type)
+	{
+	case LLIMChiclet::TYPE_IM:
+		return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
+	case LLIMChiclet::TYPE_GROUP:
+		return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
+	case LLIMChiclet::TYPE_AD_HOC:
+		return getChicletPanel()->createChiclet<LLAdHocChiclet>(session_id);
+	case LLIMChiclet::TYPE_UNKNOWN:
+		break;
+	}
+
+	return NULL;
+}
+
+//virtual
+void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id)
+{
+	if (!getChicletPanel()) return;
+
+	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
+	if (!session) return;
+
+	// no need to spawn chiclets for participants in P2P calls called through Avaline
+	if (session->isP2P() && session->isOtherParticipantAvaline()) return;
+
+	if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;
+
+	LLIMChiclet* chiclet = createIMChiclet(session_id);
+	if(chiclet)
+	{
+		chiclet->setIMSessionName(name);
+		chiclet->setOtherParticipantId(other_participant_id);
+		
+		LLIMFloater::onIMChicletCreated(session_id);
+
+	}
+	else
+	{
+		llerrs << "Could not create chiclet" << llendl;
+	}
+}
+
+//virtual
+void LLBottomTray::sessionRemoved(const LLUUID& session_id)
+{
+	if(getChicletPanel())
+	{
+		// IM floater should be closed when session removed and associated chiclet closed
+		LLIMFloater* iMfloater = LLFloaterReg::findTypedInstance<LLIMFloater>(
+				"impanel", session_id);
+		if (iMfloater != NULL)
+		{
+			iMfloater->closeFloater();
+		}
+
+		getChicletPanel()->removeChiclet(session_id);
+	}
+}
+
+void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
+{
+	//this is only needed in case of outgoing ad-hoc/group chat sessions
+	LLChicletPanel* chiclet_panel = getChicletPanel();
+	if (chiclet_panel)
+	{
+		//it should be ad-hoc im chiclet or group im chiclet
+		LLChiclet* chiclet = chiclet_panel->findChiclet<LLChiclet>(old_session_id);
+		if (chiclet) chiclet->setSessionId(new_session_id);
+	}
+}
+
+S32 LLBottomTray::getTotalUnreadIMCount()
+{
+	return getChicletPanel()->getTotalUnreadIMCount();
+}
+
+// virtual
+void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, bool proximal)
+{
+	// Time it takes to connect to voice channel might be pretty long,
+	// so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED.
+	BOOL enable = FALSE;
+
+	switch (status)
+	{
+	// Do not add STATUS_VOICE_ENABLED because voice chat is 
+	// inactive until STATUS_JOINED
+	case STATUS_JOINED:
+		enable = TRUE;
+		break;
+	default:
+		enable = FALSE;
+		break;
+	}
+
+	// We have to enable/disable right and left parts of speak button separately (EXT-4648)
+	mSpeakBtn->setSpeakBtnEnabled(enable);
+	// skipped to avoid button blinking
+	if (status != STATUS_JOINING && status!= STATUS_LEFT_CHANNEL)
+	{
+		mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking());
+	}
+}
+
+void LLBottomTray::onMouselookModeOut()
+{
+	mIsInLiteMode = false;
+	mBottomTrayLite->setVisible(FALSE);
+	mNearbyChatBar->getChatBox()->setText(mBottomTrayLite->mNearbyChatBar->getChatBox()->getText());
+	setVisible(TRUE);
+}
+
+void LLBottomTray::onMouselookModeIn()
+{
+	setVisible(FALSE);
+
+	// Attach the lite bottom tray
+	if (getParent() && mBottomTrayLite->getParent() != getParent())
+		getParent()->addChild(mBottomTrayLite);
+
+	mBottomTrayLite->setShape(getLocalRect());
+	mBottomTrayLite->mNearbyChatBar->getChatBox()->setText(mNearbyChatBar->getChatBox()->getText());
+	mBottomTrayLite->mGesturePanel->setVisible(gSavedSettings.getBOOL("ShowGestureButton"));
+
+	mIsInLiteMode = true;
+}
+
+//virtual
+// setVisible used instead of onVisibilityChange, since LLAgent calls it on entering/leaving mouselook mode.
+// If bottom tray is already visible in mouselook mode, then onVisibilityChange will not be called from setVisible(true),
+void LLBottomTray::setVisible(BOOL visible)
+{
+	if (mIsInLiteMode)
+	{
+		mBottomTrayLite->setVisible(visible);
+	}
+	else 
+	{
+		LLPanel::setVisible(visible);
+	}
+}
+
+S32 LLBottomTray::notifyParent(const LLSD& info)
+{
+	if(info.has("well_empty")) // implementation of EXT-3397
+	{
+		const std::string chiclet_name = info["well_name"];
+
+		// only "im_well" or "notification_well" names are expected.
+		// They are set in panel_bottomtray.xml in <chiclet_im_well> & <chiclet_notification>
+		llassert("im_well" == chiclet_name || "notification_well" == chiclet_name);
+
+		BOOL should_be_visible = !info["well_empty"];
+		showWellButton("im_well" == chiclet_name ? RS_IM_WELL : RS_NOTIFICATION_WELL, should_be_visible);
+		return 1;
+	}
+
+	if (info.has("action") && info["action"] == "resize")
+	{
+		const std::string& name = info["view_name"];
+
+		// expected only resize of nearby chatbar
+		if (mChatBarContainer->getName() != name) return LLPanel::notifyParent(info);
+
+		const S32 new_width = info["new_width"];
+
+		processChatbarCustomization(new_width);
+
+		return 2;
+	}
+	return LLPanel::notifyParent(info);
+}
+
+void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask)
+{
+	// We should show BottomTrayContextMenu in last  turn
+	if (mBottomTrayContextMenu && !LLMenuGL::sMenuContainer->getVisibleMenu())
+	{
+		    //there are no other context menu (IM chiclet etc ), so we can show BottomTrayContextMenu
+
+		    updateContextMenu(x, y, mask);
+			mBottomTrayContextMenu->buildDrawLabels();
+			mBottomTrayContextMenu->updateParent(LLMenuGL::sMenuContainer);
+			LLMenuGL::showPopup(this, mBottomTrayContextMenu, x, y);
+		
+	}
+}
+
+void LLBottomTray::updateContextMenu(S32 x, S32 y, MASK mask)
+{
+	LLUICtrl* edit_box = mNearbyChatBar->getChild<LLUICtrl>("chat_box");
+
+	S32 local_x = x - mChatBarContainer->getRect().mLeft - edit_box->getRect().mLeft;
+	S32 local_y = y - mChatBarContainer->getRect().mBottom - edit_box->getRect().mBottom;
+
+	bool in_edit_box = edit_box->pointInView(local_x, local_y);
+
+	mBottomTrayContextMenu->setItemVisible("Separator", in_edit_box);
+	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Cut", in_edit_box);
+	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Copy", in_edit_box);
+	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Paste", in_edit_box);
+	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Delete", in_edit_box);
+	mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Select_All", in_edit_box);
+}
+
+void LLBottomTray::showGestureButton(BOOL visible)
+{
+	setTrayButtonVisibleIfPossible(RS_BUTTON_GESTURES, visible);
+}
+
+void LLBottomTray::showMoveButton(BOOL visible)
+{
+	setTrayButtonVisibleIfPossible(RS_BUTTON_MOVEMENT, visible);
+}
+
+void LLBottomTray::showCameraButton(BOOL visible)
+{
+	setTrayButtonVisibleIfPossible(RS_BUTTON_CAMERA, visible);
+}
+
+void LLBottomTray::showSnapshotButton(BOOL visible)
+{
+	setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible);
+}
+
+void LLBottomTray::showSpeakButton(bool visible)
+{
+	// Show/hide the button
+	setTrayButtonVisible(RS_BUTTON_SPEAK, visible);
+
+	// and adjust other panels according to the occupied/freed space.
+	const S32 panel_width = mSpeakPanel->getRect().getWidth();
+	if (visible)
+	{
+		processWidthDecreased(-panel_width);
+	}
+	else
+	{
+		processWidthIncreased(panel_width);
+	}
+}
+
+void LLBottomTray::toggleMovementControls()
+{
+	if (mMovementButton)
+		mMovementButton->onCommit();
+}
+
+void LLBottomTray::toggleCameraControls()
+{
+	if (mCamButton)
+		mCamButton->onCommit();
+}
+
+BOOL LLBottomTray::postBuild()
+{
+	LLHints::registerHintTarget("bottom_tray", LLView::getHandle());
+	LLHints::registerHintTarget("dest_guide_btn", getChild<LLUICtrl>("destination_btn")->getHandle());
+	LLHints::registerHintTarget("avatar_picker_btn", getChild<LLUICtrl>("avatar_btn")->getHandle());
+
+	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("NearbyChatBar.Action", boost::bind(&LLBottomTray::onContextMenuItemClicked, this, _2));
+	LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("NearbyChatBar.EnableMenuItem", boost::bind(&LLBottomTray::onContextMenuItemEnabled, this, _2));
+
+	mBottomTrayContextMenu =  LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_bottomtray.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	gMenuHolder->addChild(mBottomTrayContextMenu);
+
+	mNearbyChatBar = findChild<LLNearbyChatBar>("chat_bar");
+	LLHints::registerHintTarget("chat_bar", mNearbyChatBar->LLView::getHandle());
+
+	mChatBarContainer = getChild<LLLayoutPanel>("chat_bar_layout_panel");
+	mNearbyCharResizeHandlePanel = getChild<LLPanel>("chat_bar_resize_handle_panel");
+
+	mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
+	mMovementButton = getChild<LLButton>("movement_btn");
+	LLHints::registerHintTarget("move_btn", mMovementButton->getHandle());
+	mCamButton = getChild<LLButton>("camera_btn");
+	setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
+
+	mSpeakPanel = getChild<LLPanel>("speak_panel");
+	mSpeakBtn = getChild<LLSpeakButton>("talk");
+
+	// Both parts of speak button should be initially disabled because
+	// it takes some time between logging in to world and connecting to voice channel.
+	mSpeakBtn->setSpeakBtnEnabled(false);
+	mSpeakBtn->setFlyoutBtnEnabled(false);
+
+	// Localization tool doesn't understand custom buttons like <talk_button>
+	mSpeakBtn->setSpeakToolTip( getString("SpeakBtnToolTip") );
+	mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") );
+
+	// Registering Chat Bar to receive Voice client status change notifications.
+	LLVoiceClient::getInstance()->addObserver(this);
+
+	mNearbyChatBar->getChatBox()->setContextMenu(NULL);
+
+	mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
+
+	initResizeStateContainers();
+
+	setButtonsControlsAndListeners();
+
+	initButtonsVisibility();
+
+	// update wells visibility:
+	showWellButton(RS_IM_WELL, !LLIMWellWindow::getInstance()->isWindowEmpty());
+	showWellButton(RS_NOTIFICATION_WELL, !LLNotificationWellWindow::getInstance()->isWindowEmpty());
+
+	loadButtonsOrder();
+
+	LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&update_build_button_enable_state));
+
+	return TRUE;
+}
+
+//Drag-n-drop
+
+void LLBottomTray::onDraggableButtonMouseDown(LLUICtrl* ctrl, S32 x, S32 y)
+{
+	if (ctrl == NULL) return;
+	LLView* parent_view = ctrl->getParent();
+	if(parent_view != NULL)
+	{
+		// we actually drag'n'drop panel (not button) in code, so have to find a parent
+		// of button which called this method on mouse down.
+		LLPanel* parent = dynamic_cast<LLPanel*>(parent_view);
+		// It may happen that we clicked not usual button, but button inside widget(speak, gesture)
+		// so we'll need to get a level higher to reach layout panel as a parent.
+		if(parent == NULL) parent = dynamic_cast<LLPanel*>(parent_view->getParent());
+		if (parent && parent->getVisible())
+		{
+			mDraggedItem = parent;
+			mCheckForDrag = true;
+			mStartX = x;
+			mStartY = y;
+		}
+	}
+}
+
+LLPanel* LLBottomTray::findChildPanelByLocalCoords(S32 x, S32 y)
+{
+	LLPanel* ctrl = 0;
+	S32 screenX, screenY;
+	const child_list_t* list = mToolbarStack->getChildList();
+
+	localPointToScreen(x, y, &screenX, &screenY);
+
+	// look for a child panel which contains the point (screenX, screenY) in it's rectangle
+	for (child_list_const_iter_t i = list->begin(); i != list->end(); ++i)
+	{
+		LLRect rect;
+		localRectToScreen((*i)->getRect(), &rect);
+
+		if (rect.pointInRect(screenX, screenY))
+		{
+			ctrl = dynamic_cast<LLPanel*>(*i);
+			break;
+		}
+	}
+
+	return ctrl;
+}
+
+void LLBottomTray::onDraggableButtonHover(S32 x, S32 y)
+{
+	// if mouse down on draggable item was done, check whether we should start DnD
+	if (mCheckForDrag)
+	{
+		// Start drag'n'drop if mouse cursor was dragged away frome mouse down location enough
+		if(sqrt((float)((mStartX-x)*(mStartX-x)+(mStartY-y)*(mStartY-y))) > DRAG_START_DISTANCE)
+		{
+			mDragStarted = true;
+			mCheckForDrag = false;
+		}
+	}
+	if (mDragStarted)
+	{
+		// Check whether the cursor is over draggable area, find which panel it is and set is as
+		// landing tab for drag'n'drop
+		if(isCursorOverDraggableArea(x, y))
+		{
+			LLPanel* panel = findChildPanelByLocalCoords(x,y);
+			if (panel && panel != mDraggedItem) mLandingTab = panel;
+			gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROWDRAG);
+		}
+		else
+		{
+			gViewerWindow->getWindow()->setCursor(UI_CURSOR_NO);
+		}
+	}
+	else
+	{
+		// Reset cursor in case you move your mouse from the drag handle to a button.
+		getWindow()->setCursor(UI_CURSOR_ARROW);
+
+	}
+}
+
+bool LLBottomTray::isCursorOverDraggableArea(S32 x, S32 y)
+{
+	// Draggable area lasts from the nearby chat input resize handle
+	// to the chiclet area (exlusively).
+	bool result = getRect().pointInRect(x, y);
+	result = result && mNearbyCharResizeHandlePanel->calcScreenRect().mRight < x;
+	result = result && mChicletPanel->calcScreenRect().mRight > x;
+	return result;
+}
+
+void LLBottomTray::updateButtonsOrdersAfterDnD()
+{
+	// *TODO: change implementation of this method to support simplify it
+	// (and according to future possible changes in the way button order is saved between sessions).
+	state_object_map_t::const_iterator it = mStateProcessedObjectMap.begin();
+	state_object_map_t::const_iterator it_end = mStateProcessedObjectMap.end();
+	EResizeState dragged_state = RS_NORESIZE;
+	EResizeState landing_state = RS_NORESIZE;
+	bool landing_state_found = false;
+	// Find states for dragged item and landing tab
+	for (; it != it_end; ++it)
+	{
+		if (it->second == mDraggedItem)
+		{
+			dragged_state = it->first;
+		}
+		else if (it->second == mLandingTab)
+		{
+			landing_state = it->first;
+			landing_state_found = true;
+		}
+	}
+
+	if (dragged_state == RS_NORESIZE)
+	{
+		llwarns << "Cannot determine what button is being dragged" << llendl;
+		llassert(dragged_state != RS_NORESIZE);
+		return;
+	}
+
+	lldebugs << "Will place " << resizeStateToString(dragged_state)
+		<< " before " << resizeStateToString(landing_state) << llendl;
+
+	// Update order of buttons according to drag'n'drop
+	mButtonsOrder.erase(std::find(mButtonsOrder.begin(), mButtonsOrder.end(), dragged_state));
+	if (!landing_state_found && mLandingTab == getChild<LLPanel>(PANEL_CHICLET_NAME))
+	{
+		mButtonsOrder.push_back(dragged_state);
+	}
+	else
+	{
+		if (!landing_state_found) landing_state = RS_BUTTON_SPEAK; // just a random fallback
+		mButtonsOrder.insert(std::find(mButtonsOrder.begin(), mButtonsOrder.end(), landing_state), dragged_state);
+	}
+
+	// Synchronize button process order with their order
+	resize_state_vec_t::const_iterator it1 = mButtonsOrder.begin();
+	const resize_state_vec_t::const_iterator it_end1 = mButtonsOrder.end();
+	resize_state_vec_t::iterator it2 = mButtonsProcessOrder.begin();
+	for (; it1 != it_end1; ++it1)
+	{
+		// Skip Speak because it is not in mButtonsProcessOrder(it's the reason why mButtonsOrder was introduced).
+		// If any other draggable items will be added to bottomtray later, they should also be skipped here.
+		if (*it1 != RS_BUTTON_SPEAK)
+		{
+			*it2 = *it1;
+			++it2;
+		}
+	}
+
+	saveButtonsOrder();
+}
+
+void LLBottomTray::saveButtonsOrder()
+{
+	std::string user_dir = gDirUtilp->getLindenUserDir();
+	if (user_dir.empty()) return;
+	
+	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
+	LLSD settings_llsd;
+	int i = 0;
+	const resize_state_vec_t::const_iterator it_end = mButtonsOrder.end();
+	// we use numbers as keys for map which is saved in file and contains resize states as its values
+	for (resize_state_vec_t::const_iterator it = mButtonsOrder.begin(); it != it_end; ++it, i++)
+	{
+		std::string str = llformat("%d", i);
+		settings_llsd[str] = *it;		
+	}
+	llofstream file;
+	file.open(filename);
+	LLSDSerialize::toPrettyXML(settings_llsd, file);
+}
+
+void LLBottomTray::loadButtonsOrder()
+{
+	// load per-resident sorting information
+	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
+
+	LLSD settings_llsd;
+	llifstream file;
+	file.open(filename);
+	if (!file.is_open()) return;
+	
+	LLSDSerialize::fromXML(settings_llsd, file);
+	
+
+	mButtonsOrder.clear();
+	mButtonsProcessOrder.clear();
+	int i = 0;
+	// getting button order from file
+	for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
+		iter != settings_llsd.endMap(); ++iter, ++i)
+	{
+		std::string str = llformat("%d", i);
+		EResizeState state = (EResizeState)settings_llsd[str].asInteger();
+		mButtonsOrder.push_back(state);
+		// RS_BUTTON_SPEAK is skipped, because it shouldn't be in mButtonsProcessOrder (it does not hide or shrink).
+		if (state != RS_BUTTON_SPEAK)
+		{
+			mButtonsProcessOrder.push_back(state);
+		}		
+	}
+
+	// There are other panels in layout stack order of which is not saved. Also, panels order of which is saved,
+	// are already in layout stack but in wrong order. The most convenient way to place them is moving them 
+	// to front one by one (because in this case we don't have to pass the panel before which we want to insert our
+	// panel to movePanel()). So panels are moved in order from the end of mButtonsOrder vector(reverse iterator is used).
+	const resize_state_vec_t::const_reverse_iterator it_end = mButtonsOrder.rend();
+	// placing panels in layout stack according to button order which we loaded in previous for
+	for (resize_state_vec_t::const_reverse_iterator it = mButtonsOrder.rbegin(); it != it_end; ++it, ++i)
+	{
+		LLPanel* panel_to_move = getButtonPanel(*it);
+		mToolbarStack->movePanel(panel_to_move, NULL, true); // prepend 		
+	}
+	// Nearbychat is not stored in order settings file, but it must be the first of the panels, so moving it
+	// (along with its drag handle) manually here.
+	mToolbarStack->movePanel(getChild<LLLayoutPanel>("chat_bar_resize_handle_panel"), NULL, true);
+	mToolbarStack->movePanel(mChatBarContainer, NULL, true);
+}
+
+void LLBottomTray::onDraggableButtonMouseUp(LLUICtrl* ctrl, S32 x, S32 y)
+{
+	//if mouse up happened over area where drop is possible, change order of buttons
+	if (mLandingTab != NULL && mDraggedItem != NULL && mDragStarted)
+	{
+		if(isCursorOverDraggableArea(x, y))
+		{
+			// change order of panels in layout stack
+			mToolbarStack->movePanel(mDraggedItem, (LLPanel*)mLandingTab);
+			// change order of buttons in order vectors
+			updateButtonsOrdersAfterDnD();
+		}
+	}
+	gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
+	mDragStarted = false;
+	mDraggedItem = NULL;
+	mLandingTab = NULL;
+	mCheckForDrag = false;
+}
+
+void LLBottomTray::draw()
+{
+	LLPanel::draw();
+	if (mLandingTab)
+	{
+		static S32 w = mImageDragIndication->getWidth();
+		static S32 h = mImageDragIndication->getHeight();
+		LLRect rect = mLandingTab->calcScreenRect();
+		mImageDragIndication->draw(rect.mLeft - w/2, rect.getHeight(), w, h);
+	}
+	getChild<LLButton>("show_profile_btn")->setToggleState(LLAvatarActions::profileVisible(gAgent.getID()));
+
+	LLPanel* panel = LLSideTray::getInstance()->getPanel("panel_people");
+	if (panel && panel->isInVisibleChain())
+	{
+		getChild<LLButton>("show_people_button")->setToggleState(true);
+	}
+	else
+	{
+		getChild<LLButton>("show_people_button")->setToggleState(false);
+	}
+
+	LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser"));
+	bool help_floater_visible = (help_browser && help_browser->isInVisibleChain());
+
+	getChild<LLButton>("show_help_btn")->setToggleState(help_floater_visible);
+
+
+}
+
+bool LLBottomTray::onContextMenuItemEnabled(const LLSD& userdata)
+{
+	std::string item = userdata.asString();
+	LLLineEditor* edit_box = mNearbyChatBar->findChild<LLLineEditor>("chat_box");
+	
+	if (item == "can_cut")
+	{
+		return edit_box->canCut();
+	}
+	else if (item == "can_copy")
+	{
+		return edit_box->canCopy();
+	}
+	else if (item == "can_paste")
+	{
+		return edit_box->canPaste();
+	}
+	else if (item == "can_delete")
+	{
+		return edit_box->canDoDelete();
+	}
+	else if (item == "can_select_all")
+	{
+		return edit_box->canSelectAll() && (edit_box->getLength()>0);
+	}
+	return true;
+}
+
+
+void LLBottomTray::onContextMenuItemClicked(const LLSD& userdata)
+{
+	std::string item = userdata.asString();
+	LLLineEditor* edit_box = mNearbyChatBar->findChild<LLLineEditor>("chat_box");
+
+	if (item == "cut")
+	{
+		edit_box->cut();
+	}
+	else if (item == "copy")
+	{
+		edit_box->copy();
+	}
+	else if (item == "paste")
+	{
+		edit_box->paste();
+		edit_box->setFocus(TRUE);
+	}
+	else if (item == "delete")
+	{
+		edit_box->doDelete();
+	}
+	else if (item == "select_all")
+	{
+		edit_box->selectAll();
+	}
+}
+
+void LLBottomTray::log(LLView* panel, const std::string& descr)
+{
+	if (NULL == panel) return;
+	LLView* layout = panel->getParent();
+	lldebugs << descr << ": "
+		<< "panel: " << panel->getName()
+		<< ", rect: " << panel->getRect()
+ 
+ 
+		<< "layout: " << layout->getName()
+		<< ", rect: " << layout->getRect()
+		<< llendl
+		; 
+}
+
+void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+	static S32 debug_calling_number = 0;
+	lldebugs << "**************************************** " << ++debug_calling_number << llendl;
+
+	S32 current_width = getRect().getWidth();
+	S32 delta_width = width - current_width;
+	lldebugs << "Reshaping: " 
+		<< ", width: " << width
+		<< ", cur width: " << current_width
+		<< ", delta_width: " << delta_width
+		<< ", called_from_parent: " << called_from_parent
+		<< llendl;
+
+	if (mNearbyChatBar)			log(mNearbyChatBar, "before");
+	if (mChicletPanel)			log(mChicletPanel, "before");
+
+	// stores width size on which bottom tray is less than width required by its children. EXT-991
+	static S32 extra_shrink_width = 0;
+	bool should_be_reshaped = true;
+
+	if (mChicletPanel && mToolbarStack && mNearbyChatBar)
+	{
+		// Firstly, update layout stack to ensure we deal with correct panel sizes.
+		{
+			BOOL saved_anim = mToolbarStack->getAnimate();
+			// Set chiclet panel to be autoresized by default.
+			mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE);
+			// Disable animation to prevent layout updating in several frames.
+			mToolbarStack->setAnimate(FALSE);
+			// Force the updating of layout to reset panels collapse factor.
+			mToolbarStack->updateLayout();
+			// Restore animate state.
+			mToolbarStack->setAnimate(saved_anim);
+		}
+
+		// bottom tray is narrowed
+		if (delta_width < 0)
+		{
+			if (extra_shrink_width > 0)
+			{
+				// is world rect was extra shrunk and decreasing again only update this value
+				// to delta_width negative
+				extra_shrink_width -= delta_width; // use "-=" because delta_width is negative
+				should_be_reshaped = false;
+			}
+			else
+			{
+				extra_shrink_width = processWidthDecreased(delta_width);
+
+				// increase new width to extra_shrink_width value to not reshape less than bottom tray minimum
+				width += extra_shrink_width;
+			}
+		}
+		// bottom tray is widen
+		else
+		{
+			if (extra_shrink_width > delta_width)
+			{
+				// Less than minimum width is more than increasing (delta_width) 
+				// only reduce it value and make no reshape
+				extra_shrink_width -= delta_width;
+				should_be_reshaped = false;
+			}
+			else 
+			{
+				if (extra_shrink_width > 0)
+				{
+					// If we have some extra shrink width let's reduce delta_width & width
+					delta_width -= extra_shrink_width;
+					width -= extra_shrink_width;
+					extra_shrink_width = 0;
+				}
+				processWidthIncreased(delta_width);
+			}
+		}
+	}
+
+	if (should_be_reshaped)
+	{
+		lldebugs << "Reshape all children with width: " << width << llendl;
+		LLPanel::reshape(width, height, called_from_parent);
+	}
+
+	if (mNearbyChatBar)			log(mNearbyChatBar, "after");
+	if (mChicletPanel)			log(mChicletPanel, "after");
+
+
+	// Restore width of the chatbar on first reshape.
+	// we can not to do this from postBuild because reshape is called from parent view on startup
+	// creation after it and reset width according to resize logic.
+	static bool needs_restore_custom_state = true;
+	if (mChatBarContainer && needs_restore_custom_state)
+	{
+		// restore custom width of chatbar panel.
+		S32 new_width = gSavedSettings.getS32("ChatBarCustomWidth");
+		if (new_width > 0)
+		{
+			mDesiredNearbyChatWidth = new_width;
+			processChatbarCustomization(new_width);
+			mChatBarContainer->reshape(new_width, mChatBarContainer->getRect().getHeight());
+		}
+		needs_restore_custom_state = false;
+	}
+
+}
+
+S32 LLBottomTray::processWidthDecreased(S32 delta_width)
+{
+	bool still_should_be_processed = true;
+
+	const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
+	const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+
+	// There are four steps of processing width decrease. If in one of them required width was reached,
+	// further are not needed.
+	// 1. Decreasing width of chiclet panel.
+	if (chiclet_panel_width > chiclet_panel_min_width)
+	{
+		// we have some space to decrease chiclet panel
+		S32 panel_delta_min = chiclet_panel_width - chiclet_panel_min_width;
+
+		S32 delta_panel = llmin(-delta_width, panel_delta_min);
+
+		lldebugs << "delta_width: " << delta_width
+			<< ", panel_delta_min: " << panel_delta_min
+			<< ", delta_panel: " << delta_panel
+			<< llendl;
+
+		// is chiclet panel width enough to process resizing?
+		delta_width += panel_delta_min;
+
+		still_should_be_processed = delta_width < 0;
+
+		mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - delta_panel, mChicletPanel->getParent()->getRect().getHeight());
+		log(mChicletPanel, "after processing panel decreasing via chiclet panel");
+
+		lldebugs << "RS_CHICLET_PANEL" 
+			<< ", delta_width: " << delta_width
+			<< llendl;
+	}
+
+	S32 buttons_freed_width = 0;
+	// 2. Decreasing width of buttons.
+	if (still_should_be_processed)
+	{
+		processShrinkButtons(delta_width, buttons_freed_width);
+	}
+	// 3. Decreasing width of nearby chat.
+	const S32 chatbar_panel_min_width = get_panel_min_width(mToolbarStack, mChatBarContainer);
+	const S32 chatbar_panel_width = mChatBarContainer->getRect().getWidth();
+	if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width)
+	{
+		// we have some space to decrease chatbar panel
+		S32 panel_delta_min = chatbar_panel_width - chatbar_panel_min_width;
+
+		S32 delta_panel = llmin(-delta_width, panel_delta_min);
+
+		// whether chatbar panel width is enough to process resizing?
+		delta_width += panel_delta_min;
+
+		still_should_be_processed = delta_width < 0;
+
+		// chatbar should only be shrunk here, not stretched
+		if(delta_panel > 0)
+		{
+			mChatBarContainer->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mChatBarContainer->getRect().getHeight());
+		}
+
+		log(mNearbyChatBar, "after processing panel decreasing via nearby chatbar panel");
+
+		lldebugs << "RS_CHATBAR_INPUT"
+			<< ", delta_panel: " << delta_panel
+			<< ", delta_width: " << delta_width
+			<< llendl;
+	}
+
+	S32 extra_shrink_width = 0;
+	// 4. Hiding buttons if needed.
+	if (still_should_be_processed)
+	{
+		processHideButtons(delta_width, buttons_freed_width);
+
+		if (delta_width < 0)
+		{
+			extra_shrink_width = -delta_width;
+			llwarns << "There is no enough width to reshape all children: " 
+				<< extra_shrink_width << llendl;
+		}
+
+		if (buttons_freed_width > 0)
+		{
+			S32 nearby_needed_width = mDesiredNearbyChatWidth - mNearbyChatBar->getRect().getWidth();
+			if (nearby_needed_width > 0)
+			{
+				S32 compensative_width = nearby_needed_width > buttons_freed_width ? buttons_freed_width : nearby_needed_width; 
+				log(mNearbyChatBar, "before applying compensative width");
+				mChatBarContainer->reshape(mChatBarContainer->getRect().getWidth() + compensative_width, mChatBarContainer->getRect().getHeight() );
+				log(mNearbyChatBar, "after applying compensative width");
+				lldebugs << buttons_freed_width << llendl;
+			}
+		}
+	}
+
+	return extra_shrink_width;
+}
+
+void LLBottomTray::processWidthIncreased(S32 delta_width)
+{
+	if (delta_width <= 0) return;
+
+	const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
+	static const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+
+	const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;
+
+	// how many room we have to show hidden buttons
+	S32 total_available_width = delta_width + available_width_chiclet;
+
+	lldebugs << "Processing extending, available width:"
+		<< ", chiclets - " << available_width_chiclet
+		<< ", total - " << total_available_width
+		<< llendl;
+
+	S32 available_width = total_available_width;
+
+	processShowButtons(available_width);
+
+	// if we have to show/extend some buttons but resized delta width is not enough...
+	S32 processed_width = total_available_width - available_width;
+	if (processed_width > delta_width)
+	{
+		// ... let's shrink nearby chat & chiclet panels
+		S32 required_to_process_width = processed_width;
+
+		// 1. use delta width of resizing
+		required_to_process_width -= delta_width;
+
+		// 2. use width available via decreasing of chiclet panel
+		if (required_to_process_width > 0)
+		{
+			mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_to_process_width, mChicletPanel->getParent()->getRect().getHeight());
+			log(mChicletPanel, "after applying compensative width for chiclets: ");
+			lldebugs << required_to_process_width << llendl;
+		}
+
+	}
+
+	// shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels
+	delta_width -= processed_width;
+
+
+	// how many space can nearby chatbar take?
+	S32 chatbar_panel_width_ = mChatBarContainer->getRect().getWidth();
+	if (delta_width > 0 && chatbar_panel_width_ < mDesiredNearbyChatWidth)
+	{
+		S32 delta_panel_max = mDesiredNearbyChatWidth - chatbar_panel_width_;
+		S32 delta_panel = llmin(delta_width, delta_panel_max);
+		lldebugs << "Unprocesed delta width: " << delta_width
+			<< ", can be applied to chatbar: " << delta_panel_max
+			<< ", will be applied: " << delta_panel
+			<< llendl;
+
+		delta_width -= delta_panel_max;
+		mChatBarContainer->reshape(chatbar_panel_width_ + delta_panel, mChatBarContainer->getRect().getHeight());
+		log(mNearbyChatBar, "applied unprocessed delta width");
+	}
+	if (delta_width > 0)
+	{
+		processExtendButtons(delta_width);
+	}
+}
+
+void LLBottomTray::processShowButtons(S32& available_width)
+{
+	// process buttons from left to right
+	resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+	const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
+
+	for (; it != it_end; ++it)
+	{
+		// is there available space?
+		if (available_width <= 0) break;
+
+		// try to show next button
+		processShowButton(*it, available_width);
+	}
+}
+
+bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32& available_width)
+{
+	lldebugs << "Trying to show object type: " << shown_object_type << llendl;
+
+	LLPanel* panel = getButtonPanel(shown_object_type);
+	if (NULL == panel)
+	{
+		lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
+		return false;
+	}
+	bool can_be_shown = canButtonBeShown(shown_object_type);
+	if (can_be_shown)
+	{
+		//validate if we have enough room to show this button
+		const S32 required_width = panel->getRect().getWidth();
+		can_be_shown = available_width >= required_width;
+		if (can_be_shown)
+		{
+			available_width -= required_width;
+
+			setTrayButtonVisible(shown_object_type, true);
+
+			lldebugs << "processed object type: " << shown_object_type
+				<< ", rest available width: " << available_width
+				<< llendl;
+			mResizeState &= ~shown_object_type;
+		}
+	}
+	return can_be_shown;
+}
+
+void LLBottomTray::processHideButtons(S32& required_width, S32& buttons_freed_width)
+{
+	// process buttons from right to left
+	resize_state_vec_t::const_reverse_iterator it = mButtonsProcessOrder.rbegin();
+	const resize_state_vec_t::const_reverse_iterator it_end = mButtonsProcessOrder.rend();
+
+	for (; it != it_end; ++it)
+	{
+		// is it still necessary to hide a button?
+		if (required_width >= 0) break;
+
+		// try to hide next button
+		processHideButton(*it, required_width, buttons_freed_width);
+	}
+}
+
+void LLBottomTray::processHideButton(EResizeState processed_object_type, S32& required_width, S32& buttons_freed_width)
+{
+	lldebugs << "Trying to hide object type: " << processed_object_type << llendl;
+	LLPanel* panel = getButtonPanel(processed_object_type);
+	if (NULL == panel)
+	{
+		lldebugs << "There is no object to process for state: " << processed_object_type << llendl;
+		return;
+	}
+
+	if (panel->getVisible())
+	{
+		required_width += panel->getRect().getWidth();
+
+		if (required_width > 0)
+		{
+			buttons_freed_width += required_width;
+		}
+
+		setTrayButtonVisible(processed_object_type, false);
+
+		mResizeState |= processed_object_type;
+
+		lldebugs << "processing object type: " << processed_object_type
+			<< ", buttons_freed_width: " << buttons_freed_width
+			<< llendl;
+	}
+}
+
+void LLBottomTray::processShrinkButtons(S32& required_width, S32& buttons_freed_width)
+{
+	// process buttons from right to left
+	resize_state_vec_t::const_reverse_iterator it = mButtonsProcessOrder.rbegin();
+	const resize_state_vec_t::const_reverse_iterator it_end = mButtonsProcessOrder.rend();
+
+	// iterate through buttons in the mButtonsProcessOrder first
+	for (; it != it_end; ++it)
+	{
+		// is it still necessary to hide a button?
+		if (required_width >= 0) break;
+
+		// try to shrink next button
+		processShrinkButton(*it, required_width);
+	}
+
+	// then shrink Speak button
+	if (required_width < 0)
+	{
+		S32 panel_min_width = 0;
+		std::string panel_name = mSpeakPanel->getName();
+		bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width);
+		if (!success)
+		{
+			lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
+		}
+		else
+		{
+			S32 panel_width = mSpeakPanel->getRect().getWidth();
+			S32 possible_shrink_width = panel_width - panel_min_width;
+
+			if (possible_shrink_width > 0)
+			{
+				mSpeakBtn->setLabelVisible(false);
+				mSpeakPanel->reshape(panel_width - possible_shrink_width, mSpeakPanel->getRect().getHeight());
+
+				required_width += possible_shrink_width;
+
+				if (required_width > 0)
+				{
+					buttons_freed_width += required_width;
+				}
+
+				lldebugs << "Shrunk Speak button panel: " << panel_name
+					<< ", shrunk width: " << possible_shrink_width
+					<< ", rest width to process: " << required_width
+					<< llendl;
+			}
+		}
+	}
+}
+
+void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32& required_width)
+{
+	LLPanel* panel = getButtonPanel(processed_object_type);
+	if (NULL == panel)
+	{
+		lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
+		return;
+	}
+
+	if (panel->getVisible())
+	{
+		S32 panel_width = panel->getRect().getWidth();
+		S32 panel_min_width = 0;
+		std::string panel_name = panel->getName();
+		bool success = mToolbarStack->getPanelMinSize(panel_name, &panel_min_width);
+		S32 possible_shrink_width = panel_width - panel_min_width;
+
+		if (!success)
+		{
+			lldebugs << "Panel was not found to get its min width: " << panel_name << llendl;
+		}
+		// we have some space to free by shrinking the button
+		else if (possible_shrink_width > 0)
+		{
+			// let calculate real width to shrink
+
+			// 1. apply all possible width
+			required_width += possible_shrink_width;
+
+			// 2. it it is too much... 
+			if (required_width > 0)
+			{
+				// reduce applied shrunk width to the excessive value.
+				possible_shrink_width -= required_width;
+				required_width = 0;
+			}
+			panel->reshape(panel_width - possible_shrink_width, panel->getRect().getHeight());
+
+			lldebugs << "Shrunk panel: " << panel_name
+				<< ", shrunk width: " << possible_shrink_width
+				<< ", rest width to process: " << required_width
+				<< llendl;
+		}
+	}
+}
+
+
+void LLBottomTray::processExtendButtons(S32& available_width)
+{
+	// do not allow extending any buttons if we have some buttons hidden via resize
+	if (mResizeState & RS_BUTTONS_CAN_BE_HIDDEN) return;
+
+	// process buttons from left to right
+	resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+	const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
+
+	// iterate through buttons in the mButtonsProcessOrder first
+	for (; it != it_end; ++it)
+	{
+		// is there available space?
+		if (available_width <= 0) break;
+
+		// try to extend next button
+		processExtendButton(*it, available_width);
+	}
+
+	const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
+	static const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+	const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width;
+
+	// then try to extend Speak button
+	if (available_width > 0 || available_width_chiclet > 0)
+	{
+		S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK];
+		S32 panel_width = mSpeakPanel->getRect().getWidth();
+		S32 possible_extend_width = panel_max_width - panel_width;
+
+		if (possible_extend_width >= 0 && possible_extend_width <= available_width + available_width_chiclet)  // HACK: this button doesn't change size so possible_extend_width will be 0
+		{
+			mSpeakBtn->setLabelVisible(true);
+			mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight());
+			log(mSpeakBtn, "speak button is extended");
+
+			if( available_width > possible_extend_width)
+			{
+				available_width -= possible_extend_width;
+			}
+			else
+			{
+				S32 required_width = possible_extend_width - available_width;
+				available_width = 0;
+				mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_width, mChicletPanel->getParent()->getRect().getHeight());
+			}
+			lldebugs << "Extending Speak button panel: " << mSpeakPanel->getName()
+				<< ", extended width: " << possible_extend_width
+				<< ", rest width to process: " << available_width
+				<< llendl;
+		}
+	}
+}
+
+void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32& available_width)
+{
+	LLPanel* panel = getButtonPanel(processed_object_type);
+	if (NULL == panel)
+	{
+		lldebugs << "There is no object to process for type: " << processed_object_type << llendl;
+		return;
+	}
+
+	if (!panel->getVisible()) return;
+
+	S32 panel_max_width = mObjectDefaultWidthMap[processed_object_type];
+	S32 panel_width = panel->getRect().getWidth();
+	S32 possible_extend_width = panel_max_width - panel_width;
+
+	if (possible_extend_width > 0)
+	{
+		// let calculate real width to extend
+
+		// 1. apply all possible width
+		available_width -= possible_extend_width;
+
+		// 2. it it is too much... 
+		if (available_width < 0)
+		{
+			// reduce applied extended width to the excessive value.
+			possible_extend_width += available_width;
+			available_width = 0;
+		}
+		panel->reshape(panel_width + possible_extend_width, panel->getRect().getHeight());
+
+		lldebugs << "Extending panel: " << panel->getName()
+			<< ", extended width: " << possible_extend_width
+			<< ", rest width to process: " << available_width
+			<< llendl;
+	}
+}
+
+bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const
+{
+	// 0. Check if passed button was previously hidden on resize
+	bool can_be_shown = mResizeState & processed_object_type;
+	if (can_be_shown)
+	{
+		// Yes, it was. Lets now check that all buttons before it (that can be hidden on resize)
+		// are already shown
+
+		// process buttons in direct order (from left to right)
+		resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+		const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
+
+		// 1. Find and accumulate all buttons types before one passed into the method.
+		MASK buttons_before_mask = RS_NORESIZE;
+		for (; it != it_end; ++it)
+		{
+			const EResizeState button_type = *it;
+			if (button_type == processed_object_type) break;
+
+			buttons_before_mask |= button_type;
+		}
+
+		// 2. Check if some previous buttons are still hidden on resize
+		can_be_shown = !(buttons_before_mask & mResizeState);
+	}
+	return can_be_shown;
+}
+
+void LLBottomTray::initResizeStateContainers()
+{
+	// init map with objects should be processed for each type
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SPEAK, getChild<LLPanel>("speak_panel")));
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, getChild<LLPanel>("gesture_panel")));
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, getChild<LLPanel>("movement_panel")));
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, getChild<LLPanel>("cam_panel")));
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, getChild<LLPanel>("snapshot_panel")));
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_BUILD, getChild<LLPanel>("build_btn_panel")));
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SEARCH, getChild<LLPanel>("search_btn_panel")));
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_WORLD_MAP, getChild<LLPanel>("world_map_btn_panel")));
+	mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MINI_MAP, getChild<LLPanel>("mini_map_btn_panel")));
+
+	// init an order of processed buttons
+	mButtonsProcessOrder.push_back(RS_BUTTON_GESTURES);
+	mButtonsProcessOrder.push_back(RS_BUTTON_MOVEMENT);
+	mButtonsProcessOrder.push_back(RS_BUTTON_CAMERA);
+	mButtonsProcessOrder.push_back(RS_BUTTON_SNAPSHOT);
+	mButtonsProcessOrder.push_back(RS_BUTTON_BUILD);
+	mButtonsProcessOrder.push_back(RS_BUTTON_SEARCH);
+	mButtonsProcessOrder.push_back(RS_BUTTON_WORLD_MAP);
+	mButtonsProcessOrder.push_back(RS_BUTTON_MINI_MAP);
+
+	mButtonsOrder.push_back(RS_BUTTON_SPEAK);
+	mButtonsOrder.insert(mButtonsOrder.end(), mButtonsProcessOrder.begin(), mButtonsProcessOrder.end());
+
+	// init default widths
+
+	// process buttons that can be hidden on resize...
+	resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+	const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
+
+	for (; it != it_end; ++it)
+	{
+		const EResizeState button_type = *it;
+		// is there an appropriate object?
+		LLPanel* button_panel = getButtonPanel(button_type);
+		if (!button_panel) continue;
+
+		// set default width for it.
+		mObjectDefaultWidthMap[button_type] = button_panel->getRect().getWidth();
+	}
+
+	// ... and add Speak button because it also can be shrunk.
+	mObjectDefaultWidthMap[RS_BUTTON_SPEAK]	   = mSpeakPanel->getRect().getWidth();
+}
+
+// this method must be called before restoring of the chat entry field on startup
+// because it resets chatbar's width according to resize logic.
+void LLBottomTray::initButtonsVisibility()
+{
+	setVisibleAndFitWidths(RS_BUTTON_SPEAK, gSavedSettings.getBOOL("EnableVoiceChat"));
+	setVisibleAndFitWidths(RS_BUTTON_GESTURES, gSavedSettings.getBOOL("ShowGestureButton"));
+	setVisibleAndFitWidths(RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"));
+	setVisibleAndFitWidths(RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"));
+	setVisibleAndFitWidths(RS_BUTTON_SNAPSHOT, gSavedSettings.getBOOL("ShowSnapshotButton"));
+	setVisibleAndFitWidths(RS_BUTTON_BUILD, gSavedSettings.getBOOL("ShowBuildButton"));
+	setVisibleAndFitWidths(RS_BUTTON_SEARCH, gSavedSettings.getBOOL("ShowSearchButton"));
+	setVisibleAndFitWidths(RS_BUTTON_WORLD_MAP, gSavedSettings.getBOOL("ShowWorldMapButton"));
+	setVisibleAndFitWidths(RS_BUTTON_MINI_MAP, gSavedSettings.getBOOL("ShowMiniMapButton"));
+}
+
+void LLBottomTray::setButtonsControlsAndListeners()
+{
+	gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SPEAK, _2));
+	gSavedSettings.getControl("ShowGestureButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_GESTURES, _2));
+	gSavedSettings.getControl("ShowMoveButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MOVEMENT, _2));
+	gSavedSettings.getControl("ShowCameraButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_CAMERA, _2));
+	gSavedSettings.getControl("ShowSnapshotButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SNAPSHOT, _2));
+	gSavedSettings.getControl("ShowBuildButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_BUILD, _2));
+	gSavedSettings.getControl("ShowSearchButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SEARCH, _2));
+	gSavedSettings.getControl("ShowWorldMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_WORLD_MAP, _2));
+	gSavedSettings.getControl("ShowMiniMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MINI_MAP, _2));
+
+
+	LLButton* build_btn = getChild<LLButton>("build_btn");
+	// set control name for Build button. It is not enough to link it with Button.SetFloaterToggle in xml
+	std::string vis_control_name = LLFloaterReg::declareVisibilityControl("build");
+	// Set the button control value (toggle state) to the floater visibility control (Sets the value as well)
+	build_btn->setControlVariable(LLFloater::getControlGroup()->getControl(vis_control_name));
+}
+
+bool LLBottomTray::toggleShowButton(LLBottomTray::EResizeState button_type, const LLSD& new_visibility)
+{
+	if (LLBottomTray::instanceExists())
+	{
+		LLBottomTray::getInstance()->setTrayButtonVisibleIfPossible(button_type, new_visibility.asBoolean());
+	}
+	return true;
+}
+
+void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible)
+{
+	LLPanel* panel = getButtonPanel(shown_object_type);
+	if (NULL == panel)
+	{
+		lldebugs << "There is no object to show for state: " << shown_object_type << llendl;
+		return;
+	}
+
+	panel->setVisible(visible);
+}
+
+void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification)
+{
+	if (!setVisibleAndFitWidths(shown_object_type, visible) && visible && raise_notification)
+	{
+		LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown",
+								 LLSD(),
+								 LLSD(),
+								 LLNotificationFunctorRegistry::instance().DONOTHING);
+	}
+}
+
+bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible)
+{
+	// The Speak button is treated specially: if voice is enabled,
+	// the button should be displayed no matter how much space we've got.
+	if (object_type == RS_BUTTON_SPEAK)
+	{
+		showSpeakButton(visible);
+		return true;
+	}
+
+	LLPanel* cur_panel = getButtonPanel(object_type);
+	if (NULL == cur_panel)
+	{
+		lldebugs << "There is no object to process for state: " << object_type << llendl;
+		return false;
+	}
+
+	bool is_set = true;
+
+	if (visible)
+	{
+		// Assume that only chiclet panel can be auto-resized
+		const S32 available_width =
+			mChicletPanel->getParent()->getRect().getWidth() - mChicletPanel->getMinWidth();
+
+		S32 preferred_width = mObjectDefaultWidthMap[object_type];
+		S32 current_width = cur_panel->getRect().getWidth();
+		S32 result_width = 0;
+		bool decrease_width = false;
+
+		// Mark this button to be shown
+		mResizeState |= object_type;
+
+		if (preferred_width > 0 && available_width >= preferred_width)
+		{
+			result_width = preferred_width;
+		}
+		else if (available_width >= current_width)
+		{
+			result_width = current_width;
+		}
+		else
+		{
+			// Calculate the possible shrunk width as difference between current and minimal widths
+			const S32 chatbar_shrunk_width =
+				mChatBarContainer->getRect().getWidth() - get_panel_min_width(mToolbarStack, mChatBarContainer);
+
+			S32 sum_of_min_widths = get_panel_min_width(mToolbarStack, mSpeakPanel);
+			S32 sum_of_curr_widths = get_curr_width(mSpeakPanel);
+
+			resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+			const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
+
+			for (; it != it_end; ++it)
+			{
+				LLPanel* cur_panel = getButtonPanel(*it);
+				sum_of_min_widths += get_panel_min_width(mToolbarStack, cur_panel);
+				sum_of_curr_widths += get_curr_width(cur_panel);
+			}
+
+			const S32 possible_shrunk_width =
+				chatbar_shrunk_width + (sum_of_curr_widths - sum_of_min_widths);
+
+			// Minimal width of current panel
+			S32 minimal_width = 0;
+			mToolbarStack->getPanelMinSize(cur_panel->getName(), &minimal_width);
+
+			if ( (available_width + possible_shrunk_width) >= minimal_width)
+			{
+				// There is enough space for minimal width, but set the result_width
+				// to preferred_width so buttons widths decreasing will be done in predefined order
+				result_width = (preferred_width > 0) ? preferred_width : current_width;
+				decrease_width = true;
+			}
+			else
+			{
+				// Nothing can be done, give up...
+				return false;
+			}
+		}
+
+		if (result_width != current_width)
+		{
+			cur_panel->reshape(result_width, cur_panel->getRect().getHeight());
+			current_width = result_width;
+		}
+
+		is_set = processShowButton(object_type, current_width);
+
+		// Shrink buttons if needed
+		if (is_set && decrease_width)
+		{
+			processWidthDecreased( -result_width);
+		}
+	}
+	else
+	{
+		const S32 delta_width = get_curr_width(cur_panel);
+
+		setTrayButtonVisible(object_type, false);
+
+		// Mark button NOT to show while future bottom tray extending
+		mResizeState &= ~object_type;
+
+		// Extend other buttons if need
+		if (delta_width)
+		{
+			processWidthIncreased(delta_width);
+		}
+	}
+	return is_set;
+}
+
+LLPanel* LLBottomTray::getButtonPanel(EResizeState button_type)
+{
+	// Don't use the operator[] because it inserts a NULL value if the key is not found.
+	if (mStateProcessedObjectMap.count(button_type) == 0)
+	{
+		llwarns << "Cannot find a panel for " << resizeStateToString(button_type) << llendl;
+		llassert(mStateProcessedObjectMap.count(button_type) == 1);
+		return NULL;
+	}
+
+	return mStateProcessedObjectMap[button_type];
+}
+
+void LLBottomTray::showWellButton(EResizeState object_type, bool visible)
+{
+	llassert( ((RS_NOTIFICATION_WELL | RS_IM_WELL) & object_type) == object_type );
+
+	const std::string panel_name = RS_IM_WELL == object_type ? "im_well_panel" : "notification_well_panel";
+
+	LLView * panel = getChild<LLView>(panel_name);
+
+	// if necessary visibility is set nothing to do here
+	if (panel->getVisible() == (BOOL)visible) return;
+
+	S32 panel_width = panel->getRect().getWidth();
+	panel->setVisible(visible);
+
+	if (visible)
+	{
+		// method assumes that input param is a negative value
+		processWidthDecreased(-panel_width);
+	}
+	else
+	{
+		processWidthIncreased(panel_width);
+	}
+}
+
+void LLBottomTray::processChatbarCustomization(S32 new_width)
+{
+	if (NULL == mNearbyChatBar) return;
+
+	const S32 delta_width = mChatBarContainer->getRect().getWidth() - new_width;
+
+	if (delta_width == 0) return;
+
+	mDesiredNearbyChatWidth = new_width;
+
+	LLView * chiclet_layout_panel = mChicletPanel->getParent();
+	const S32 chiclet_min_width = get_panel_min_width(mToolbarStack, chiclet_layout_panel);
+	const S32 chiclet_panel_width = chiclet_layout_panel->getRect().getWidth();
+	const S32 available_chiclet_shrink_width = chiclet_panel_width - chiclet_min_width;
+	llassert(available_chiclet_shrink_width >= 0);
+
+	if (delta_width > 0) // panel gets narrowly
+	{
+		S32 total_possible_width = delta_width + available_chiclet_shrink_width;
+		processShowButtons(total_possible_width);
+		processExtendButtons(total_possible_width);
+	}
+	// here (delta_width < 0) // panel gets wider
+	else //if (-delta_width > available_chiclet_shrink_width)
+	{
+		S32 required_width = delta_width + available_chiclet_shrink_width;
+		S32 buttons_freed_width = 0;
+		processShrinkButtons(required_width, buttons_freed_width);
+		processHideButtons(required_width, buttons_freed_width);
+	}
+}
+
+// static
+std::string LLBottomTray::resizeStateToString(EResizeState state)
+{
+	switch (state)
+	{
+	case RS_NORESIZE:				return "RS_NORESIZE";
+	case RS_CHICLET_PANEL:			return "RS_CHICLET_PANEL";
+	case RS_CHATBAR_INPUT:			return "RS_CHATBAR_INPUT";
+	case RS_BUTTON_SNAPSHOT:		return "RS_BUTTON_SNAPSHOT";
+	case RS_BUTTON_CAMERA:			return "RS_BUTTON_CAMERA";
+	case RS_BUTTON_MOVEMENT:		return "RS_BUTTON_MOVEMENT";
+	case RS_BUTTON_GESTURES:		return "RS_BUTTON_GESTURES";
+	case RS_BUTTON_SPEAK:			return "RS_BUTTON_SPEAK";
+	case RS_IM_WELL:				return "RS_IM_WELL";
+	case RS_NOTIFICATION_WELL:		return "RS_NOTIFICATION_WELL";
+	case RS_BUTTON_BUILD:			return "RS_BUTTON_BUILD";
+	case RS_BUTTON_SEARCH:			return "RS_BUTTON_SEARCH";
+	case RS_BUTTON_WORLD_MAP:		return "RS_BUTTON_WORLD_MAP";
+	case RS_BUTTON_MINI_MAP:		return "RS_BUTTON_MINI_MAP";
+	case RS_BUTTONS_CAN_BE_HIDDEN:	return "RS_BUTTONS_CAN_BE_HIDDEN";
+	// No default to track additions.
+	}
+	return "UNKNOWN_BUTTON";
+}
+
+//EOF
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 836ae9a0cfc49f7cbf88e0a214c0041828387736..162e465fef8d3573b35ffbc671243651267783cd 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -157,6 +157,16 @@ BOOL LLGestureComboList::handleKeyHere(KEY key, MASK mask)
 	return handled; 		
 }
 
+void LLGestureComboList::draw()
+{
+	LLUICtrl::draw();
+
+	if(mButton->getToggleState())
+	{
+		showList();
+	}
+}
+
 void LLGestureComboList::showList()
 {
 	LLRect rect = mList->getRect();
@@ -180,6 +190,7 @@ void LLGestureComboList::showList()
 	// Show the list and push the button down
 	mButton->setToggleState(TRUE);
 	mList->setVisible(TRUE);
+	sendChildToFront(mList);
 	LLUI::addPopup(mList);
 }
 
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index 033d1dd5a2c8d1962d23fb210888fad8774b5223..96ab45071b2251bae53191f2c49927379d4416aa 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -72,6 +72,8 @@ class LLGestureComboList
 	virtual void	hideList();
 	virtual BOOL	handleKeyHere(KEY key, MASK mask);
 
+	virtual void	draw();
+
 	S32				getCurrentIndex() const;
 	void			onItemSelected(const LLSD& data);
 	void			sortByName(bool ascending = true);
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index b472698a49b96f88327968e09f2708af5621f281..903cf4780df7658ab55538e2f517b0a6cfed8267 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -1,1183 +1,1183 @@
-/** 
- * @file llpanellogin.cpp
- * @brief Login dialog and logo display
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llpanellogin.h"
-
-#include "indra_constants.h"		// for key and mask constants
-#include "llfloaterreg.h"
-#include "llfontgl.h"
-#include "llmd5.h"
-#include "llsecondlifeurls.h"
-#include "v4color.h"
-
-#include "llappviewer.h"
-#include "llbutton.h"
-#include "llcheckboxctrl.h"
-#include "llcommandhandler.h"		// for secondlife:///app/login/
-#include "llcombobox.h"
-#include "llcurl.h"
-#include "llviewercontrol.h"
-#include "llfloaterpreference.h"
-#include "llfocusmgr.h"
-#include "lllineeditor.h"
-#include "llnotificationsutil.h"
-#include "llsecapi.h"
-#include "llstartup.h"
-#include "lltextbox.h"
-#include "llui.h"
-#include "lluiconstants.h"
-#include "llslurl.h"
-#include "llversioninfo.h"
-#include "llviewerhelp.h"
-#include "llviewertexturelist.h"
-#include "llviewermenu.h"			// for handle_preferences()
-#include "llviewernetwork.h"
-#include "llviewerwindow.h"			// to link into child list
-#include "lluictrlfactory.h"
-#include "llhttpclient.h"
-#include "llweb.h"
-#include "llmediactrl.h"
-#include "llrootview.h"
-
-#include "llfloatertos.h"
-#include "lltrans.h"
-#include "llglheaders.h"
-#include "llpanelloginlistener.h"
-
-#if LL_WINDOWS
-#pragma warning(disable: 4355)      // 'this' used in initializer list
-#endif  // LL_WINDOWS
-
-#include "llsdserialize.h"
-
-const S32 BLACK_BORDER_HEIGHT = 160;
-const S32 MAX_PASSWORD = 16;
-
-LLPanelLogin *LLPanelLogin::sInstance = NULL;
-BOOL LLPanelLogin::sCapslockDidNotification = FALSE;
-
-
-class LLLoginRefreshHandler : public LLCommandHandler
-{
-public:
-	// don't allow from external browsers
-	LLLoginRefreshHandler() : LLCommandHandler("login_refresh", UNTRUSTED_BLOCK) { }
-	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
-	{	
-		if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
-		{
-			LLPanelLogin::loadLoginPage();
-		}	
-		return true;
-	}
-};
-
-LLLoginRefreshHandler gLoginRefreshHandler;
-
-
-// helper class that trys to download a URL from a web site and calls a method 
-// on parent class indicating if the web server is working or not
-class LLIamHereLogin : public LLHTTPClient::Responder
-{
-	private:
-		LLIamHereLogin( LLPanelLogin* parent ) :
-		   mParent( parent )
-		{}
-
-		LLPanelLogin* mParent;
-
-	public:
-		static boost::intrusive_ptr< LLIamHereLogin > build( LLPanelLogin* parent )
-		{
-			return boost::intrusive_ptr< LLIamHereLogin >( new LLIamHereLogin( parent ) );
-		};
-
-		virtual void  setParent( LLPanelLogin* parentIn )
-		{
-			mParent = parentIn;
-		};
-
-		// We don't actually expect LLSD back, so need to override completedRaw
-		virtual void completedRaw(U32 status, const std::string& reason,
-								  const LLChannelDescriptors& channels,
-								  const LLIOPipe::buffer_ptr_t& buffer)
-		{
-			completed(status, reason, LLSD()); // will call result() or error()
-		}
-	
-		virtual void result( const LLSD& content )
-		{
-			if ( mParent )
-				mParent->setSiteIsAlive( true );
-		};
-
-		virtual void error( U32 status, const std::string& reason )
-		{
-			if ( mParent )
-				mParent->setSiteIsAlive( false );
-		};
-};
-
-// this is global and not a class member to keep crud out of the header file
-namespace {
-	boost::intrusive_ptr< LLIamHereLogin > gResponsePtr = 0;
-};
-
-
-//---------------------------------------------------------------------------
-// Public methods
-//---------------------------------------------------------------------------
-LLPanelLogin::LLPanelLogin(const LLRect &rect,
-						 BOOL show_server,
-						 void (*callback)(S32 option, void* user_data),
-						 void *cb_data)
-:	LLPanel(),
-	mLogoImage(),
-	mCallback(callback),
-	mCallbackData(cb_data),
-	mHtmlAvailable( TRUE ),
-	mListener(new LLPanelLoginListener(this))
-{
-	setBackgroundVisible(FALSE);
-	setBackgroundOpaque(TRUE);
-
-	// instance management
-	if (LLPanelLogin::sInstance)
-	{
-		llwarns << "Duplicate instance of login view deleted" << llendl;
-		// Don't leave bad pointer in gFocusMgr
-		gFocusMgr.setDefaultKeyboardFocus(NULL);
-
-		delete LLPanelLogin::sInstance;
-	}
-
-	mPasswordModified = FALSE;
-	LLPanelLogin::sInstance = this;
-
-	LLView* login_holder = gViewerWindow->getLoginPanelHolder();
-	if (login_holder)
-	{
-		login_holder->addChild(this);
-	}
-
-	// Logo
-	mLogoImage = LLUI::getUIImage("startup_logo");
-
-	buildFromFile( "panel_login.xml");
-	
-	// Legacy login web page is hidden under the menu bar.
-	// Adjust reg-in-client web browser widget to not be hidden.
-	if (gSavedSettings.getBOOL("RegInClient"))
-	{
-		reshape(rect.getWidth(), rect.getHeight() - MENU_BAR_HEIGHT);
-	}
-	else
-	{
-		reshape(rect.getWidth(), rect.getHeight());
-	}
-
-	getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
-
-	// change z sort of clickable text to be behind buttons
-	//sendChildToBack(getChildView("channel_text"));
-	sendChildToBack(getChildView("forgot_password_text"));
-
-	if(LLStartUp::getStartSLURL().getType() != LLSLURL::LOCATION)
-	{
-		LLSLURL slurl(gSavedSettings.getString("LoginLocation"));
-		LLStartUp::setStartSLURL(slurl);
-	}
-	updateLocationCombo(false);
-
-	gSavedSettings.getControl("SessionSettingsFile")->getSignal()->connect(boost::bind(&onModeChange));
-
-	LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");
-	server_choice_combo->setCommitCallback(onSelectServer, NULL);
-	server_choice_combo->setFocusLostCallback(boost::bind(onServerComboLostFocus, _1));
-	updateServerCombo();
-
-	childSetAction("connect_btn", onClickConnect, this);
-
-	getChild<LLPanel>("login")->setDefaultBtn("connect_btn");
-
-	std::string channel = LLVersionInfo::getChannel();
-	std::string version = llformat("%s (%d)",
-								   LLVersionInfo::getShortVersion().c_str(),
-								   LLVersionInfo::getBuild());
-	//LLTextBox* channel_text = getChild<LLTextBox>("channel_text");
-	//channel_text->setTextArg("[CHANNEL]", channel); // though not displayed
-	//channel_text->setTextArg("[VERSION]", version);
-	//channel_text->setClickedCallback(onClickVersion, this);
-	
-	LLTextBox* forgot_password_text = getChild<LLTextBox>("forgot_password_text");
-	forgot_password_text->setClickedCallback(onClickForgotPassword, NULL);
-
-	LLTextBox* create_new_account_text = getChild<LLTextBox>("create_new_account_text");
-	create_new_account_text->setClickedCallback(onClickNewAccount, NULL);
-
-	LLTextBox* need_help_text = getChild<LLTextBox>("login_help");
-	need_help_text->setClickedCallback(onClickHelp, NULL);
-	
-	// get the web browser control
-	LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
-	web_browser->addObserver(this);
-	
-	// Clear the browser's cache to avoid any potential for the cache messing up the login screen.
-	web_browser->clearCache();
-
-	reshapeBrowser();
-
-	// kick off a request to grab the url manually
-	gResponsePtr = LLIamHereLogin::build( this );
-
-	LLHTTPClient::head( LLGridManager::getInstance()->getLoginPage(), gResponsePtr );
-
-	// Show last logged in user favorites in "Start at" combo.
-	addUsersWithFavoritesToUsername();
-	getChild<LLComboBox>("username_combo")->setTextChangedCallback(boost::bind(&LLPanelLogin::addFavoritesToStartLocation, this));
-
-	updateLocationCombo(false);
-
-}
-
-void LLPanelLogin::addUsersWithFavoritesToUsername()
-{
-	LLComboBox* combo = getChild<LLComboBox>("username_combo");
-	if (!combo) return;
-	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
-	LLSD fav_llsd;
-	llifstream file;
-	file.open(filename);
-	if (!file.is_open()) return;
-	LLSDSerialize::fromXML(fav_llsd, file);
-	for (LLSD::map_const_iterator iter = fav_llsd.beginMap();
-		iter != fav_llsd.endMap(); ++iter)
-	{
-		combo->add(iter->first);
-	}
-}
-
-void LLPanelLogin::addFavoritesToStartLocation()
-{
-	LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
-	if (!combo) return;
-	int num_items = combo->getItemCount();
-	for (int i = num_items - 1; i > 2; i--)
-	{
-		combo->remove(i);
-	}
-	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
-	LLSD fav_llsd;
-	llifstream file;
-	file.open(filename);
-	if (!file.is_open()) return;
-	LLSDSerialize::fromXML(fav_llsd, file);
-	for (LLSD::map_const_iterator iter = fav_llsd.beginMap();
-		iter != fav_llsd.endMap(); ++iter)
-	{
-		if(iter->first != getChild<LLComboBox>("username_combo")->getSimple()) continue;
-		combo->addSeparator();
-		LLSD user_llsd = iter->second;
-		for (LLSD::array_const_iterator iter1 = user_llsd.beginArray();
-			iter1 != user_llsd.endArray(); ++iter1)
-		{
-			std::string label = (*iter1)["name"].asString();
-			std::string value = (*iter1)["slurl"].asString();
-			if(label != "" && value != "")
-			{
-				combo->add(label, value);
-			}
-		}
-		break;
-	}
-}
-
-// force the size to be correct (XML doesn't seem to be sufficient to do this)
-// (with some padding so the other login screen doesn't show through)
-void LLPanelLogin::reshapeBrowser()
-{
-	LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
-	LLRect rect = gViewerWindow->getWindowRectScaled();
-	LLRect html_rect;
-	html_rect.setCenterAndSize(
-		rect.getCenterX() - 2, rect.getCenterY() + 40,
-		rect.getWidth() + 6, rect.getHeight() - 78 );
-	web_browser->setRect( html_rect );
-	web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE );
-	reshape( rect.getWidth(), rect.getHeight(), 1 );
-}
-
-void LLPanelLogin::setSiteIsAlive( bool alive )
-{
-	LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
-	// if the contents of the site was retrieved
-	if ( alive )
-	{
-		if ( web_browser )
-		{
-			loadLoginPage();
-			
-			// mark as available
-			mHtmlAvailable = TRUE;
-		}
-	}
-	else
-	// the site is not available (missing page, server down, other badness)
-	{
-		if ( web_browser )
-		{
-			// hide browser control (revealing default one)
-			web_browser->setVisible( FALSE );
-
-			// mark as unavailable
-			mHtmlAvailable = FALSE;
-		}
-	}
-}
-
-
-LLPanelLogin::~LLPanelLogin()
-{
-	LLPanelLogin::sInstance = NULL;
-
-	// tell the responder we're not here anymore
-	if ( gResponsePtr )
-		gResponsePtr->setParent( 0 );
-
-	//// We know we're done with the image, so be rid of it.
-	//gTextureList.deleteImage( mLogoImage );
-
-	// Controls having keyboard focus by default
-	// must reset it on destroy. (EXT-2748)
-	gFocusMgr.setDefaultKeyboardFocus(NULL);
-}
-
-// virtual
-void LLPanelLogin::draw()
-{
-	glPushMatrix();
-	{
-		F32 image_aspect = 1.333333f;
-		F32 view_aspect = (F32)getRect().getWidth() / (F32)getRect().getHeight();
-		// stretch image to maintain aspect ratio
-		if (image_aspect > view_aspect)
-		{
-			glTranslatef(-0.5f * (image_aspect / view_aspect - 1.f) * getRect().getWidth(), 0.f, 0.f);
-			glScalef(image_aspect / view_aspect, 1.f, 1.f);
-		}
-
-		S32 width = getRect().getWidth();
-		S32 height = getRect().getHeight();
-
-		if ( mHtmlAvailable )
-		{
-			if (getChild<LLView>("login_widgets")->getVisible())
-			{
-				// draw a background box in black
-				gl_rect_2d( 0, height - 264, width, 264, LLColor4::black );
-				// draw the bottom part of the background image
-				// just the blue background to the native client UI
-				mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight());
-			}
-		}
-		else
-		{
-			// the HTML login page is not available so default to the original screen
-			S32 offscreen_part = height / 3;
-			mLogoImage->draw(0, -offscreen_part, width, height+offscreen_part);
-		};
-	}
-	glPopMatrix();
-
-	LLPanel::draw();
-}
-
-// virtual
-BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask)
-{
-	if ( KEY_F1 == key )
-	{
-		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
-		vhelp->showTopic(vhelp->f1HelpTopic());
-		return TRUE;
-	}
-
-	return LLPanel::handleKeyHere(key, mask);
-}
-
-// virtual 
-void LLPanelLogin::setFocus(BOOL b)
-{
-	if(b != hasFocus())
-	{
-		if(b)
-		{
-			LLPanelLogin::giveFocus();
-		}
-		else
-		{
-			LLPanel::setFocus(b);
-		}
-	}
-}
-
-// static
-void LLPanelLogin::giveFocus()
-{
-	if( sInstance )
-	{
-		// Grab focus and move cursor to first blank input field
-		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
-		std::string pass = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
-
-		BOOL have_username = !username.empty();
-		BOOL have_pass = !pass.empty();
-
-		LLLineEditor* edit = NULL;
-		LLComboBox* combo = NULL;
-		if (have_username && !have_pass)
-		{
-			// User saved his name but not his password.  Move
-			// focus to password field.
-			edit = sInstance->getChild<LLLineEditor>("password_edit");
-		}
-		else
-		{
-			// User doesn't have a name, so start there.
-			combo = sInstance->getChild<LLComboBox>("username_combo");
-		}
-
-		if (edit)
-		{
-			edit->setFocus(TRUE);
-			edit->selectAll();
-		}
-		else if (combo)
-		{
-			combo->setFocus(TRUE);
-		}
-	}
-}
-
-// static
-void LLPanelLogin::showLoginWidgets()
-{
-	// *NOTE: Mani - This may or may not be obselete code.
-	// It seems to be part of the defunct? reg-in-client project.
-	sInstance->getChildView("login_widgets")->setVisible( true);
-	LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-	sInstance->reshapeBrowser();
-	// *TODO: Append all the usual login parameters, like first_login=Y etc.
-	std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
-	web_browser->navigateTo( splash_screen_url, "text/html" );
-	LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo");
-	username_combo->setFocus(TRUE);
-}
-
-// static
-void LLPanelLogin::show(const LLRect &rect,
-						BOOL show_server,
-						void (*callback)(S32 option, void* user_data),
-						void* callback_data)
-{
-	new LLPanelLogin(rect, show_server, callback, callback_data);
-
-	if( !gFocusMgr.getKeyboardFocus() )
-	{
-		// Grab focus and move cursor to first enabled control
-		sInstance->setFocus(TRUE);
-	}
-
-	// Make sure that focus always goes here (and use the latest sInstance that was just created)
-	gFocusMgr.setDefaultKeyboardFocus(sInstance);
-}
-
-// static
-void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
-							 BOOL remember)
-{
-	if (!sInstance)
-	{
-		llwarns << "Attempted fillFields with no login view shown" << llendl;
-		return;
-	}
-	LL_INFOS("Credentials") << "Setting login fields to " << *credential << LL_ENDL;
-
-	LLSD identifier = credential->getIdentifier();
-	if((std::string)identifier["type"] == "agent") 
-	{
-		std::string firstname = identifier["first_name"].asString();
-		std::string lastname = identifier["last_name"].asString();
-	    std::string login_id = firstname;
-	    if (!lastname.empty() && lastname != "Resident")
-	    {
-		    // support traditional First Last name SLURLs
-		    login_id += " ";
-		    login_id += lastname;
-	    }
-		sInstance->getChild<LLComboBox>("username_combo")->setLabel(login_id);	
-	}
-	else if((std::string)identifier["type"] == "account")
-	{
-		sInstance->getChild<LLComboBox>("username_combo")->setLabel((std::string)identifier["account_name"]);		
-	}
-	else
-	{
-	  sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());	
-	}
-	sInstance->addFavoritesToStartLocation();
-	// if the password exists in the credential, set the password field with
-	// a filler to get some stars
-	LLSD authenticator = credential->getAuthenticator();
-	LL_INFOS("Credentials") << "Setting authenticator field " << authenticator["type"].asString() << LL_ENDL;
-	if(authenticator.isMap() && 
-	   authenticator.has("secret") && 
-	   (authenticator["secret"].asString().size() > 0))
-	{
-		
-		// This is a MD5 hex digest of a password.
-		// We don't actually use the password input field, 
-		// fill it with MAX_PASSWORD characters so we get a 
-		// nice row of asterixes.
-		const std::string filler("123456789!123456");
-		sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string("123456789!123456"));
-	}
-	else
-	{
-		sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string());		
-	}
-	sInstance->getChild<LLUICtrl>("remember_check")->setValue(remember);
-}
-
-
-// static
-void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
-							 BOOL& remember)
-{
-	if (!sInstance)
-	{
-		llwarns << "Attempted getFields with no login view shown" << llendl;
-		return;
-	}
-	
-	// load the credential so we can pass back the stored password or hash if the user did
-	// not modify the password field.
-	
-	credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
-
-	LLSD identifier = LLSD::emptyMap();
-	LLSD authenticator = LLSD::emptyMap();
-	
-	if(credential.notNull())
-	{
-		authenticator = credential->getAuthenticator();
-	}
-
-	std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
-	LLStringUtil::trim(username);
-	std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
-
-	LL_INFOS2("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL;
-	// determine if the username is a first/last form or not.
-	size_t separator_index = username.find_first_of(' ');
-	if (separator_index == username.npos
-		&& !LLGridManager::getInstance()->isSystemGrid())
-	{
-		LL_INFOS2("Credentials", "Authentication") << "account: " << username << LL_ENDL;
-		// single username, so this is a 'clear' identifier
-		identifier["type"] = CRED_IDENTIFIER_TYPE_ACCOUNT;
-		identifier["account_name"] = username;
-		
-		if (LLPanelLogin::sInstance->mPasswordModified)
-		{
-			authenticator = LLSD::emptyMap();
-			// password is plaintext
-			authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR;
-			authenticator["secret"] = password;
-		}
-	}
-	else
-	{
-		// Be lenient in terms of what separators we allow for two-word names
-		// and allow legacy users to login with firstname.lastname
-		separator_index = username.find_first_of(" ._");
-		std::string first = username.substr(0, separator_index);
-		std::string last;
-		if (separator_index != username.npos)
-		{
-			last = username.substr(separator_index+1, username.npos);
-		LLStringUtil::trim(last);
-		}
-		else
-		{
-			// ...on Linden grids, single username users as considered to have
-			// last name "Resident"
-			// *TODO: Make login.cgi support "account_name" like above
-			last = "Resident";
-		}
-		
-		if (last.find_first_of(' ') == last.npos)
-		{
-			LL_INFOS2("Credentials", "Authentication") << "agent: " << username << LL_ENDL;
-			// traditional firstname / lastname
-			identifier["type"] = CRED_IDENTIFIER_TYPE_AGENT;
-			identifier["first_name"] = first;
-			identifier["last_name"] = last;
-		
-			if (LLPanelLogin::sInstance->mPasswordModified)
-			{
-				authenticator = LLSD::emptyMap();
-				authenticator["type"] = CRED_AUTHENTICATOR_TYPE_HASH;
-				authenticator["algorithm"] = "md5";
-				LLMD5 pass((const U8 *)password.c_str());
-				char md5pass[33];               /* Flawfinder: ignore */
-				pass.hex_digest(md5pass);
-				authenticator["secret"] = md5pass;
-			}
-		}
-	}
-	credential = gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGrid(), identifier, authenticator);
-	remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
-}
-
-// static
-BOOL LLPanelLogin::isGridComboDirty()
-{
-	BOOL user_picked = FALSE;
-	if (!sInstance)
-	{
-		llwarns << "Attempted getServer with no login view shown" << llendl;
-	}
-	else
-	{
-		LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
-		user_picked = combo->isDirty();
-	}
-	return user_picked;
-}
-
-// static
-BOOL LLPanelLogin::areCredentialFieldsDirty()
-{
-	if (!sInstance)
-	{
-		llwarns << "Attempted getServer with no login view shown" << llendl;
-	}
-	else
-	{
-		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
-		LLStringUtil::trim(username);
-		std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
-		LLComboBox* combo = sInstance->getChild<LLComboBox>("username_combo");
-		if(combo && combo->isDirty())
-		{
-			return true;
-		}
-		LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("password_edit");
-		if(ctrl && ctrl->isDirty()) 
-		{
-			return true;
-		}
-	}
-	return false;	
-}
-
-
-// static
-void LLPanelLogin::updateLocationCombo( bool force_visible )
-{
-	if (!sInstance) 
-	{
-		return;
-	}	
-	
-	LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
-	
-	switch(LLStartUp::getStartSLURL().getType())
-	{
-		case LLSLURL::LOCATION:
-		{
-			
-			combo->setCurrentByIndex( 2 );	
-			combo->setTextEntry(LLStartUp::getStartSLURL().getLocationString());	
-			break;
-		}
-		case LLSLURL::HOME_LOCATION:
-			combo->setCurrentByIndex(1);
-			break;
-		default:
-			combo->setCurrentByIndex(0);
-			break;
-	}
-	
-	BOOL show_start = TRUE;
-	
-	if ( ! force_visible )
-		show_start = gSavedSettings.getBOOL("ShowStartLocation");
-	
-	sInstance->getChildView("start_location_combo")->setVisible( show_start);
-	sInstance->getChildView("start_location_text")->setVisible( show_start);
-	
-	BOOL show_server = gSavedSettings.getBOOL("ForceShowGrid");
-	sInstance->getChildView("server_combo_text")->setVisible( show_server);	
-	sInstance->getChildView("server_combo")->setVisible( show_server);
-}
-
-// static
-void LLPanelLogin::updateStartSLURL()
-{
-	if (!sInstance) return;
-	
-	LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
-	S32 index = combo->getCurrentIndex();
-	
-	switch (index)
-	{
-		case 0:
-		{
-			LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_LAST));
-			break;
-		}			
-		case 1:
-		{
-			LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME));
-			break;
-		}
-		default:
-		{
-			LLSLURL slurl = LLSLURL(combo->getValue().asString());
-			if(slurl.getType() == LLSLURL::LOCATION)
-			{
-				// we've changed the grid, so update the grid selection
-				LLStartUp::setStartSLURL(slurl);
-			}
-			break;
-		}			
-	}
-}
-
-
-void LLPanelLogin::setLocation(const LLSLURL& slurl)
-{
-	LLStartUp::setStartSLURL(slurl);
-	updateServer();
-}
-
-// static
-void LLPanelLogin::closePanel()
-{
-	if (sInstance)
-	{
-		LLPanelLogin::sInstance->getParent()->removeChild( LLPanelLogin::sInstance );
-
-		delete sInstance;
-		sInstance = NULL;
-	}
-}
-
-// static
-void LLPanelLogin::setAlwaysRefresh(bool refresh)
-{
-	if (LLStartUp::getStartupState() >= STATE_LOGIN_CLEANUP) return;
-
-	LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-
-	if (web_browser)
-	{
-		web_browser->setAlwaysRefresh(refresh);
-	}
-}
-
-
-
-void LLPanelLogin::loadLoginPage()
-{
-	if (!sInstance) return;
-	
-	std::ostringstream oStr;
-
-	std::string login_page = LLGridManager::getInstance()->getLoginPage();
-
-	oStr << login_page;
-	
-	// Use the right delimeter depending on how LLURI parses the URL
-	LLURI login_page_uri = LLURI(login_page);
-	
-	std::string first_query_delimiter = "&";
-	if (login_page_uri.queryMap().size() == 0)
-	{
-		first_query_delimiter = "?";
-	}
-
-	// Language
-	std::string language = LLUI::getLanguage();
-	oStr << first_query_delimiter<<"lang=" << language;
-	
-	// First Login?
-	if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
-	{
-		oStr << "&firstlogin=TRUE";
-	}
-
-	// Channel and Version
-	std::string version = llformat("%s (%d)",
-								   LLVersionInfo::getShortVersion().c_str(),
-								   LLVersionInfo::getBuild());
-
-	char* curl_channel = curl_escape(LLVersionInfo::getChannel().c_str(), 0);
-	char* curl_version = curl_escape(version.c_str(), 0);
-
-	oStr << "&channel=" << curl_channel;
-	oStr << "&version=" << curl_version;
-
-	curl_free(curl_channel);
-	curl_free(curl_version);
-
-	// Grid
-	char* curl_grid = curl_escape(LLGridManager::getInstance()->getGridLabel().c_str(), 0);
-	oStr << "&grid=" << curl_grid;
-	curl_free(curl_grid);
-	
-	// add OS info
-	char * os_info = curl_escape(LLAppViewer::instance()->getOSInfo().getOSStringSimple().c_str(), 0);
-	oStr << "&os=" << os_info;
-	curl_free(os_info);
-	
-	
-	gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
-	gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
-	
-	LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-
-	// navigate to the "real" page
-	if (gSavedSettings.getBOOL("RegInClient"))
-	{
-		web_browser->setFocus(TRUE);
-		login_page = sInstance->getString("reg_in_client_url");
-		web_browser->navigateTo(login_page, "text/html");
-	}
-	else
-	{
-		web_browser->navigateTo( oStr.str(), "text/html" );
-	}
-}
-
-void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event)
-{
-	if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
-	{
-		LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
-		if (web_browser)
-		{
-			// *HACK HACK HACK HACK!
-			/* Stuff a Tab key into the browser now so that the first field will
-			** get the focus!  The embedded javascript on the page that properly
-			** sets the initial focus in a real web browser is not working inside
-			** the viewer, so this is an UGLY HACK WORKAROUND for now.
-			*/
-			// Commented out as it's not reliable
-			//web_browser->handleKey(KEY_TAB, MASK_NONE, false);
-		}
-	}
-}
-
-//---------------------------------------------------------------------------
-// Protected methods
-//---------------------------------------------------------------------------
-
-// static
-void LLPanelLogin::onClickConnect(void *)
-{
-	if (sInstance && sInstance->mCallback)
-	{
-		// tell the responder we're not here anymore
-		if ( gResponsePtr )
-			gResponsePtr->setParent( 0 );
-
-		// JC - Make sure the fields all get committed.
-		sInstance->setFocus(FALSE);
-
-		LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
-		LLSD combo_val = combo->getSelectedValue();
-		if (combo_val.isUndefined())
-		{
-			combo_val = combo->getValue();
-		}
-		if(combo_val.isUndefined())
-		{
-			LLNotificationsUtil::add("StartRegionEmpty");
-			return;
-		}		
-		try
-		{
-			LLGridManager::getInstance()->setGridChoice(combo_val.asString());
-		}
-		catch (LLInvalidGridName ex)
-		{
-			LLSD args;
-			args["GRID"] = combo_val.asString();
-			LLNotificationsUtil::add("InvalidGrid", args);
-			return;
-		}
-		updateStartSLURL();
-		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
-
-		
-		if(username.empty())
-		{
-			// user must type in something into the username field
-			LLNotificationsUtil::add("MustHaveAccountToLogIn");
-		}
-		else
-		{
-			LLPointer<LLCredential> cred;
-			BOOL remember;
-			getFields(cred, remember);
-			std::string identifier_type;
-			cred->identifierType(identifier_type);
-			LLSD allowed_credential_types;
-			LLGridManager::getInstance()->getLoginIdentifierTypes(allowed_credential_types);
-			
-			// check the typed in credential type against the credential types expected by the server.
-			for(LLSD::array_iterator i = allowed_credential_types.beginArray();
-				i != allowed_credential_types.endArray();
-				i++)
-			{
-				
-				if(i->asString() == identifier_type)
-				{
-					// yay correct credential type
-					sInstance->mCallback(0, sInstance->mCallbackData);
-					return;
-				}
-			}
-			
-			// Right now, maingrid is the only thing that is picky about
-			// credential format, as it doesn't yet allow account (single username)
-			// format creds.  - Rox.  James, we wanna fix the message when we change
-			// this.
-			LLNotificationsUtil::add("InvalidCredentialFormat");			
-		}
-	}
-}
-
-/*
-// static
-bool LLPanelLogin::newAccountAlertCallback(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (0 == option)
-	{
-		llinfos << "Going to account creation URL" << llendl;
-		LLWeb::loadURLExternal( LLNotifications::instance().getGlobalString("CREATE_ACCOUNT_URL")); 
-	}
-	else
-	{
-		sInstance->setFocus(TRUE);
-	}
-	return false;
-}
-*/
-
-// static
-void LLPanelLogin::onClickNewAccount(void*)
-{
-	LLWeb::loadURLExternal(sInstance->getString("create_account_url"));
-}
-
-
-// static
-void LLPanelLogin::onClickVersion(void*)
-{
-	LLFloaterReg::showInstance("sl_about"); 
-}
-
-//static
-void LLPanelLogin::onClickForgotPassword(void*)
-{
-	if (sInstance )
-	{
-		LLWeb::loadURLExternal(sInstance->getString( "forgot_password_url" ));
-	}
-}
-
-//static
-void LLPanelLogin::onClickHelp(void*)
-{
-	if (sInstance)
-	{
-		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
-		vhelp->showTopic(vhelp->preLoginTopic());
-	}
-}
-
-// static
-void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
-{
-	LLPanelLogin *This = (LLPanelLogin *) user_data;
-	This->mPasswordModified = TRUE;
-	if (gKeyboard->getKeyDown(KEY_CAPSLOCK) && sCapslockDidNotification == FALSE)
-	{
-// *TODO: use another way to notify user about enabled caps lock, see EXT-6858
-		sCapslockDidNotification = TRUE;
-	}
-}
-
-
-void LLPanelLogin::updateServer()
-{
-	try 
-	{
-
-		updateServerCombo();	
-		// if they've selected another grid, we should load the credentials
-		// for that grid and set them to the UI.
-		if(sInstance && !sInstance->areCredentialFieldsDirty())
-		{
-			LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());	
-			bool remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
-			sInstance->setFields(credential, remember);
-		}
-		// grid changed so show new splash screen (possibly)
-		loadLoginPage();
-		updateLocationCombo(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION);
-	}
-	catch (LLInvalidGridName ex)
-	{
-		// do nothing
-	}
-}
-
-void LLPanelLogin::updateServerCombo()
-{
-	if (!sInstance) 
-	{
-		return;	
-	}
-	// We add all of the possible values, sorted, and then add a bar and the current value at the top
-	LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");	
-	server_choice_combo->removeall();
-
-	std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids(!gSavedSettings.getBOOL("ShowBetaGrids"));
-
-	for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
-		 grid_choice != known_grids.end();
-		 grid_choice++)
-	{
-		if (!grid_choice->first.empty())
-		{
-			server_choice_combo->add(grid_choice->second, grid_choice->first);
-		}
-	}
-	server_choice_combo->sortByName();
-	
-	server_choice_combo->addSeparator(ADD_TOP);
-	
-	server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(), 
-		LLGridManager::getInstance()->getGrid(), ADD_TOP);	
-	
-	server_choice_combo->selectFirstItem();	
-}
-
-// static
-void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
-{
-	// *NOTE: The paramters for this method are ignored. 
-	// LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
-	// calls this method.
-	LL_INFOS("AppInit") << "onSelectServer" << LL_ENDL;
-	// The user twiddled with the grid choice ui.
-	// apply the selection to the grid setting.
-	LLPointer<LLCredential> credential;
-	
-	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
-	LLSD combo_val = combo->getSelectedValue();
-	if (combo_val.isUndefined())
-	{
-		combo_val = combo->getValue();
-	}
-	
-	combo = sInstance->getChild<LLComboBox>("start_location_combo");	
-	combo->setCurrentByIndex(1);
-	LLStartUp::setStartSLURL(LLSLURL(gSavedSettings.getString("LoginLocation")));
-	LLGridManager::getInstance()->setGridChoice(combo_val.asString());
-	// This new selection will override preset uris
-	// from the command line.
-	updateServer();
-	updateLocationCombo(false);
-	updateLoginPanelLinks();
-}
-
-void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe)
-{
-	if (!sInstance)
-	{
-		return;
-	}
-
-	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
-	if(fe == combo)
-	{
-		onSelectServer(combo, NULL);	
-	}
-}
-
-void LLPanelLogin::updateLoginPanelLinks()
-{
-	LLSD grid_data;
-	LLGridManager::getInstance()->getGridInfo(grid_data);
-	bool system_grid = grid_data.has(GRID_IS_SYSTEM_GRID_VALUE);
-	
-	// need to call through sInstance, as it's called from onSelectServer, which
-	// is static.
-	sInstance->getChildView("create_new_account_text")->setVisible( system_grid);
-	sInstance->getChildView("forgot_password_text")->setVisible( system_grid);
-}
-
-//static
-void LLPanelLogin::onModeChange()
-{
-	LLNotificationsUtil::add("ModeChange", LLSD(), LLSD(), boost::bind(&onModeChangeConfirm, _1, _2));
-}
-
-//static
-void LLPanelLogin::onModeChangeConfirm(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	switch (option)
-	{
-	case 0:
-		LLAppViewer::instance()->requestQuit();
-		break;
-	case 1:
-		// do nothing
-		break;
-	default:
-		break;
-	}
-}
+/** 
+ * @file llpanellogin.cpp
+ * @brief Login dialog and logo display
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanellogin.h"
+
+#include "indra_constants.h"		// for key and mask constants
+#include "llfloaterreg.h"
+#include "llfontgl.h"
+#include "llmd5.h"
+#include "llsecondlifeurls.h"
+#include "v4color.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcommandhandler.h"		// for secondlife:///app/login/
+#include "llcombobox.h"
+#include "llcurl.h"
+#include "llviewercontrol.h"
+#include "llfloaterpreference.h"
+#include "llfocusmgr.h"
+#include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llsecapi.h"
+#include "llstartup.h"
+#include "lltextbox.h"
+#include "llui.h"
+#include "lluiconstants.h"
+#include "llslurl.h"
+#include "llversioninfo.h"
+#include "llviewerhelp.h"
+#include "llviewertexturelist.h"
+#include "llviewermenu.h"			// for handle_preferences()
+#include "llviewernetwork.h"
+#include "llviewerwindow.h"			// to link into child list
+#include "lluictrlfactory.h"
+#include "llhttpclient.h"
+#include "llweb.h"
+#include "llmediactrl.h"
+#include "llrootview.h"
+
+#include "llfloatertos.h"
+#include "lltrans.h"
+#include "llglheaders.h"
+#include "llpanelloginlistener.h"
+
+#if LL_WINDOWS
+#pragma warning(disable: 4355)      // 'this' used in initializer list
+#endif  // LL_WINDOWS
+
+#include "llsdserialize.h"
+
+const S32 BLACK_BORDER_HEIGHT = 160;
+const S32 MAX_PASSWORD = 16;
+
+LLPanelLogin *LLPanelLogin::sInstance = NULL;
+BOOL LLPanelLogin::sCapslockDidNotification = FALSE;
+
+
+class LLLoginRefreshHandler : public LLCommandHandler
+{
+public:
+	// don't allow from external browsers
+	LLLoginRefreshHandler() : LLCommandHandler("login_refresh", UNTRUSTED_BLOCK) { }
+	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
+	{	
+		if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
+		{
+			LLPanelLogin::loadLoginPage();
+		}	
+		return true;
+	}
+};
+
+LLLoginRefreshHandler gLoginRefreshHandler;
+
+
+// helper class that trys to download a URL from a web site and calls a method 
+// on parent class indicating if the web server is working or not
+class LLIamHereLogin : public LLHTTPClient::Responder
+{
+	private:
+		LLIamHereLogin( LLPanelLogin* parent ) :
+		   mParent( parent )
+		{}
+
+		LLPanelLogin* mParent;
+
+	public:
+		static boost::intrusive_ptr< LLIamHereLogin > build( LLPanelLogin* parent )
+		{
+			return boost::intrusive_ptr< LLIamHereLogin >( new LLIamHereLogin( parent ) );
+		};
+
+		virtual void  setParent( LLPanelLogin* parentIn )
+		{
+			mParent = parentIn;
+		};
+
+		// We don't actually expect LLSD back, so need to override completedRaw
+		virtual void completedRaw(U32 status, const std::string& reason,
+								  const LLChannelDescriptors& channels,
+								  const LLIOPipe::buffer_ptr_t& buffer)
+		{
+			completed(status, reason, LLSD()); // will call result() or error()
+		}
+	
+		virtual void result( const LLSD& content )
+		{
+			if ( mParent )
+				mParent->setSiteIsAlive( true );
+		};
+
+		virtual void error( U32 status, const std::string& reason )
+		{
+			if ( mParent )
+				mParent->setSiteIsAlive( false );
+		};
+};
+
+// this is global and not a class member to keep crud out of the header file
+namespace {
+	boost::intrusive_ptr< LLIamHereLogin > gResponsePtr = 0;
+};
+
+
+//---------------------------------------------------------------------------
+// Public methods
+//---------------------------------------------------------------------------
+LLPanelLogin::LLPanelLogin(const LLRect &rect,
+						 BOOL show_server,
+						 void (*callback)(S32 option, void* user_data),
+						 void *cb_data)
+:	LLPanel(),
+	mLogoImage(),
+	mCallback(callback),
+	mCallbackData(cb_data),
+	mHtmlAvailable( TRUE ),
+	mListener(new LLPanelLoginListener(this))
+{
+	setBackgroundVisible(FALSE);
+	setBackgroundOpaque(TRUE);
+
+	// instance management
+	if (LLPanelLogin::sInstance)
+	{
+		llwarns << "Duplicate instance of login view deleted" << llendl;
+		// Don't leave bad pointer in gFocusMgr
+		gFocusMgr.setDefaultKeyboardFocus(NULL);
+
+		delete LLPanelLogin::sInstance;
+	}
+
+	mPasswordModified = FALSE;
+	LLPanelLogin::sInstance = this;
+
+	LLView* login_holder = gViewerWindow->getLoginPanelHolder();
+	if (login_holder)
+	{
+		login_holder->addChild(this);
+	}
+
+	// Logo
+	mLogoImage = LLUI::getUIImage("startup_logo");
+
+	buildFromFile( "panel_login.xml");
+	
+	// Legacy login web page is hidden under the menu bar.
+	// Adjust reg-in-client web browser widget to not be hidden.
+	if (gSavedSettings.getBOOL("RegInClient"))
+	{
+		reshape(rect.getWidth(), rect.getHeight() - MENU_BAR_HEIGHT);
+	}
+	else
+	{
+		reshape(rect.getWidth(), rect.getHeight());
+	}
+
+	getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);
+
+	// change z sort of clickable text to be behind buttons
+	//sendChildToBack(getChildView("channel_text"));
+	sendChildToBack(getChildView("forgot_password_text"));
+
+	if(LLStartUp::getStartSLURL().getType() != LLSLURL::LOCATION)
+	{
+		LLSLURL slurl(gSavedSettings.getString("LoginLocation"));
+		LLStartUp::setStartSLURL(slurl);
+	}
+	updateLocationCombo(false);
+
+	gSavedSettings.getControl("SessionSettingsFile")->getSignal()->connect(boost::bind(&onModeChange));
+
+	LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");
+	server_choice_combo->setCommitCallback(onSelectServer, NULL);
+	server_choice_combo->setFocusLostCallback(boost::bind(onServerComboLostFocus, _1));
+	updateServerCombo();
+
+	childSetAction("connect_btn", onClickConnect, this);
+
+	getChild<LLPanel>("login")->setDefaultBtn("connect_btn");
+
+	std::string channel = LLVersionInfo::getChannel();
+	std::string version = llformat("%s (%d)",
+								   LLVersionInfo::getShortVersion().c_str(),
+								   LLVersionInfo::getBuild());
+	//LLTextBox* channel_text = getChild<LLTextBox>("channel_text");
+	//channel_text->setTextArg("[CHANNEL]", channel); // though not displayed
+	//channel_text->setTextArg("[VERSION]", version);
+	//channel_text->setClickedCallback(onClickVersion, this);
+	
+	LLTextBox* forgot_password_text = getChild<LLTextBox>("forgot_password_text");
+	forgot_password_text->setClickedCallback(onClickForgotPassword, NULL);
+
+	LLTextBox* create_new_account_text = getChild<LLTextBox>("create_new_account_text");
+	create_new_account_text->setClickedCallback(onClickNewAccount, NULL);
+
+	LLTextBox* need_help_text = getChild<LLTextBox>("login_help");
+	need_help_text->setClickedCallback(onClickHelp, NULL);
+	
+	// get the web browser control
+	LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
+	web_browser->addObserver(this);
+	
+	// Clear the browser's cache to avoid any potential for the cache messing up the login screen.
+	web_browser->clearCache();
+
+	reshapeBrowser();
+
+	// kick off a request to grab the url manually
+	gResponsePtr = LLIamHereLogin::build( this );
+
+	LLHTTPClient::head( LLGridManager::getInstance()->getLoginPage(), gResponsePtr );
+
+	// Show last logged in user favorites in "Start at" combo.
+	addUsersWithFavoritesToUsername();
+	getChild<LLComboBox>("username_combo")->setTextChangedCallback(boost::bind(&LLPanelLogin::addFavoritesToStartLocation, this));
+
+	updateLocationCombo(false);
+
+}
+
+void LLPanelLogin::addUsersWithFavoritesToUsername()
+{
+	LLComboBox* combo = getChild<LLComboBox>("username_combo");
+	if (!combo) return;
+	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
+	LLSD fav_llsd;
+	llifstream file;
+	file.open(filename);
+	if (!file.is_open()) return;
+	LLSDSerialize::fromXML(fav_llsd, file);
+	for (LLSD::map_const_iterator iter = fav_llsd.beginMap();
+		iter != fav_llsd.endMap(); ++iter)
+	{
+		combo->add(iter->first);
+	}
+}
+
+void LLPanelLogin::addFavoritesToStartLocation()
+{
+	LLComboBox* combo = getChild<LLComboBox>("start_location_combo");
+	if (!combo) return;
+	int num_items = combo->getItemCount();
+	for (int i = num_items - 1; i > 2; i--)
+	{
+		combo->remove(i);
+	}
+	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
+	LLSD fav_llsd;
+	llifstream file;
+	file.open(filename);
+	if (!file.is_open()) return;
+	LLSDSerialize::fromXML(fav_llsd, file);
+	for (LLSD::map_const_iterator iter = fav_llsd.beginMap();
+		iter != fav_llsd.endMap(); ++iter)
+	{
+		if(iter->first != getChild<LLComboBox>("username_combo")->getSimple()) continue;
+		combo->addSeparator();
+		LLSD user_llsd = iter->second;
+		for (LLSD::array_const_iterator iter1 = user_llsd.beginArray();
+			iter1 != user_llsd.endArray(); ++iter1)
+		{
+			std::string label = (*iter1)["name"].asString();
+			std::string value = (*iter1)["slurl"].asString();
+			if(label != "" && value != "")
+			{
+				combo->add(label, value);
+			}
+		}
+		break;
+	}
+}
+
+// force the size to be correct (XML doesn't seem to be sufficient to do this)
+// (with some padding so the other login screen doesn't show through)
+void LLPanelLogin::reshapeBrowser()
+{
+	LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
+	LLRect rect = gViewerWindow->getWindowRectScaled();
+	LLRect html_rect;
+	html_rect.setCenterAndSize(
+		rect.getCenterX() - 2, rect.getCenterY() + 40,
+		rect.getWidth() + 6, rect.getHeight() - 78 );
+	web_browser->setRect( html_rect );
+	web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE );
+	reshape( rect.getWidth(), rect.getHeight(), 1 );
+}
+
+void LLPanelLogin::setSiteIsAlive( bool alive )
+{
+	LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
+	// if the contents of the site was retrieved
+	if ( alive )
+	{
+		if ( web_browser )
+		{
+			loadLoginPage();
+			
+			// mark as available
+			mHtmlAvailable = TRUE;
+		}
+	}
+	else
+	// the site is not available (missing page, server down, other badness)
+	{
+		if ( web_browser )
+		{
+			// hide browser control (revealing default one)
+			web_browser->setVisible( FALSE );
+
+			// mark as unavailable
+			mHtmlAvailable = FALSE;
+		}
+	}
+}
+
+
+LLPanelLogin::~LLPanelLogin()
+{
+	LLPanelLogin::sInstance = NULL;
+
+	// tell the responder we're not here anymore
+	if ( gResponsePtr )
+		gResponsePtr->setParent( 0 );
+
+	//// We know we're done with the image, so be rid of it.
+	//gTextureList.deleteImage( mLogoImage );
+
+	// Controls having keyboard focus by default
+	// must reset it on destroy. (EXT-2748)
+	gFocusMgr.setDefaultKeyboardFocus(NULL);
+}
+
+// virtual
+void LLPanelLogin::draw()
+{
+	glPushMatrix();
+	{
+		F32 image_aspect = 1.333333f;
+		F32 view_aspect = (F32)getRect().getWidth() / (F32)getRect().getHeight();
+		// stretch image to maintain aspect ratio
+		if (image_aspect > view_aspect)
+		{
+			glTranslatef(-0.5f * (image_aspect / view_aspect - 1.f) * getRect().getWidth(), 0.f, 0.f);
+			glScalef(image_aspect / view_aspect, 1.f, 1.f);
+		}
+
+		S32 width = getRect().getWidth();
+		S32 height = getRect().getHeight();
+
+		if ( mHtmlAvailable )
+		{
+			if (getChild<LLView>("login_widgets")->getVisible())
+			{
+				// draw a background box in black
+				gl_rect_2d( 0, height - 264, width, 264, LLColor4::black );
+				// draw the bottom part of the background image
+				// just the blue background to the native client UI
+				mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight());
+			}
+		}
+		else
+		{
+			// the HTML login page is not available so default to the original screen
+			S32 offscreen_part = height / 3;
+			mLogoImage->draw(0, -offscreen_part, width, height+offscreen_part);
+		};
+	}
+	glPopMatrix();
+
+	LLPanel::draw();
+}
+
+// virtual
+BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask)
+{
+	if ( KEY_F1 == key )
+	{
+		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+		vhelp->showTopic(vhelp->f1HelpTopic());
+		return TRUE;
+	}
+
+	return LLPanel::handleKeyHere(key, mask);
+}
+
+// virtual 
+void LLPanelLogin::setFocus(BOOL b)
+{
+	if(b != hasFocus())
+	{
+		if(b)
+		{
+			LLPanelLogin::giveFocus();
+		}
+		else
+		{
+			LLPanel::setFocus(b);
+		}
+	}
+}
+
+// static
+void LLPanelLogin::giveFocus()
+{
+	if( sInstance )
+	{
+		// Grab focus and move cursor to first blank input field
+		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
+		std::string pass = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+
+		BOOL have_username = !username.empty();
+		BOOL have_pass = !pass.empty();
+
+		LLLineEditor* edit = NULL;
+		LLComboBox* combo = NULL;
+		if (have_username && !have_pass)
+		{
+			// User saved his name but not his password.  Move
+			// focus to password field.
+			edit = sInstance->getChild<LLLineEditor>("password_edit");
+		}
+		else
+		{
+			// User doesn't have a name, so start there.
+			combo = sInstance->getChild<LLComboBox>("username_combo");
+		}
+
+		if (edit)
+		{
+			edit->setFocus(TRUE);
+			edit->selectAll();
+		}
+		else if (combo)
+		{
+			combo->setFocus(TRUE);
+		}
+	}
+}
+
+// static
+void LLPanelLogin::showLoginWidgets()
+{
+	// *NOTE: Mani - This may or may not be obselete code.
+	// It seems to be part of the defunct? reg-in-client project.
+	sInstance->getChildView("login_widgets")->setVisible( true);
+	LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
+	sInstance->reshapeBrowser();
+	// *TODO: Append all the usual login parameters, like first_login=Y etc.
+	std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage();
+	web_browser->navigateTo( splash_screen_url, "text/html" );
+	LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo");
+	username_combo->setFocus(TRUE);
+}
+
+// static
+void LLPanelLogin::show(const LLRect &rect,
+						BOOL show_server,
+						void (*callback)(S32 option, void* user_data),
+						void* callback_data)
+{
+	new LLPanelLogin(rect, show_server, callback, callback_data);
+
+	if( !gFocusMgr.getKeyboardFocus() )
+	{
+		// Grab focus and move cursor to first enabled control
+		sInstance->setFocus(TRUE);
+	}
+
+	// Make sure that focus always goes here (and use the latest sInstance that was just created)
+	gFocusMgr.setDefaultKeyboardFocus(sInstance);
+}
+
+// static
+void LLPanelLogin::setFields(LLPointer<LLCredential> credential,
+							 BOOL remember)
+{
+	if (!sInstance)
+	{
+		llwarns << "Attempted fillFields with no login view shown" << llendl;
+		return;
+	}
+	LL_INFOS("Credentials") << "Setting login fields to " << *credential << LL_ENDL;
+
+	LLSD identifier = credential->getIdentifier();
+	if((std::string)identifier["type"] == "agent") 
+	{
+		std::string firstname = identifier["first_name"].asString();
+		std::string lastname = identifier["last_name"].asString();
+	    std::string login_id = firstname;
+	    if (!lastname.empty() && lastname != "Resident")
+	    {
+		    // support traditional First Last name SLURLs
+		    login_id += " ";
+		    login_id += lastname;
+	    }
+		sInstance->getChild<LLComboBox>("username_combo")->setLabel(login_id);	
+	}
+	else if((std::string)identifier["type"] == "account")
+	{
+		sInstance->getChild<LLComboBox>("username_combo")->setLabel((std::string)identifier["account_name"]);		
+	}
+	else
+	{
+	  sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string());	
+	}
+	sInstance->addFavoritesToStartLocation();
+	// if the password exists in the credential, set the password field with
+	// a filler to get some stars
+	LLSD authenticator = credential->getAuthenticator();
+	LL_INFOS("Credentials") << "Setting authenticator field " << authenticator["type"].asString() << LL_ENDL;
+	if(authenticator.isMap() && 
+	   authenticator.has("secret") && 
+	   (authenticator["secret"].asString().size() > 0))
+	{
+		
+		// This is a MD5 hex digest of a password.
+		// We don't actually use the password input field, 
+		// fill it with MAX_PASSWORD characters so we get a 
+		// nice row of asterixes.
+		const std::string filler("123456789!123456");
+		sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string("123456789!123456"));
+	}
+	else
+	{
+		sInstance->getChild<LLUICtrl>("password_edit")->setValue(std::string());		
+	}
+	sInstance->getChild<LLUICtrl>("remember_check")->setValue(remember);
+}
+
+
+// static
+void LLPanelLogin::getFields(LLPointer<LLCredential>& credential,
+							 BOOL& remember)
+{
+	if (!sInstance)
+	{
+		llwarns << "Attempted getFields with no login view shown" << llendl;
+		return;
+	}
+	
+	// load the credential so we can pass back the stored password or hash if the user did
+	// not modify the password field.
+	
+	credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());
+
+	LLSD identifier = LLSD::emptyMap();
+	LLSD authenticator = LLSD::emptyMap();
+	
+	if(credential.notNull())
+	{
+		authenticator = credential->getAuthenticator();
+	}
+
+	std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
+	LLStringUtil::trim(username);
+	std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+
+	LL_INFOS2("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL;
+	// determine if the username is a first/last form or not.
+	size_t separator_index = username.find_first_of(' ');
+	if (separator_index == username.npos
+		&& !LLGridManager::getInstance()->isSystemGrid())
+	{
+		LL_INFOS2("Credentials", "Authentication") << "account: " << username << LL_ENDL;
+		// single username, so this is a 'clear' identifier
+		identifier["type"] = CRED_IDENTIFIER_TYPE_ACCOUNT;
+		identifier["account_name"] = username;
+		
+		if (LLPanelLogin::sInstance->mPasswordModified)
+		{
+			authenticator = LLSD::emptyMap();
+			// password is plaintext
+			authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR;
+			authenticator["secret"] = password;
+		}
+	}
+	else
+	{
+		// Be lenient in terms of what separators we allow for two-word names
+		// and allow legacy users to login with firstname.lastname
+		separator_index = username.find_first_of(" ._");
+		std::string first = username.substr(0, separator_index);
+		std::string last;
+		if (separator_index != username.npos)
+		{
+			last = username.substr(separator_index+1, username.npos);
+		LLStringUtil::trim(last);
+		}
+		else
+		{
+			// ...on Linden grids, single username users as considered to have
+			// last name "Resident"
+			// *TODO: Make login.cgi support "account_name" like above
+			last = "Resident";
+		}
+		
+		if (last.find_first_of(' ') == last.npos)
+		{
+			LL_INFOS2("Credentials", "Authentication") << "agent: " << username << LL_ENDL;
+			// traditional firstname / lastname
+			identifier["type"] = CRED_IDENTIFIER_TYPE_AGENT;
+			identifier["first_name"] = first;
+			identifier["last_name"] = last;
+		
+			if (LLPanelLogin::sInstance->mPasswordModified)
+			{
+				authenticator = LLSD::emptyMap();
+				authenticator["type"] = CRED_AUTHENTICATOR_TYPE_HASH;
+				authenticator["algorithm"] = "md5";
+				LLMD5 pass((const U8 *)password.c_str());
+				char md5pass[33];               /* Flawfinder: ignore */
+				pass.hex_digest(md5pass);
+				authenticator["secret"] = md5pass;
+			}
+		}
+	}
+	credential = gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGrid(), identifier, authenticator);
+	remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+}
+
+// static
+BOOL LLPanelLogin::isGridComboDirty()
+{
+	BOOL user_picked = FALSE;
+	if (!sInstance)
+	{
+		llwarns << "Attempted getServer with no login view shown" << llendl;
+	}
+	else
+	{
+		LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
+		user_picked = combo->isDirty();
+	}
+	return user_picked;
+}
+
+// static
+BOOL LLPanelLogin::areCredentialFieldsDirty()
+{
+	if (!sInstance)
+	{
+		llwarns << "Attempted getServer with no login view shown" << llendl;
+	}
+	else
+	{
+		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
+		LLStringUtil::trim(username);
+		std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString();
+		LLComboBox* combo = sInstance->getChild<LLComboBox>("username_combo");
+		if(combo && combo->isDirty())
+		{
+			return true;
+		}
+		LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("password_edit");
+		if(ctrl && ctrl->isDirty()) 
+		{
+			return true;
+		}
+	}
+	return false;	
+}
+
+
+// static
+void LLPanelLogin::updateLocationCombo( bool force_visible )
+{
+	if (!sInstance) 
+	{
+		return;
+	}	
+	
+	LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
+	
+	switch(LLStartUp::getStartSLURL().getType())
+	{
+		case LLSLURL::LOCATION:
+		{
+			
+			combo->setCurrentByIndex( 2 );	
+			combo->setTextEntry(LLStartUp::getStartSLURL().getLocationString());	
+			break;
+		}
+		case LLSLURL::HOME_LOCATION:
+			combo->setCurrentByIndex(1);
+			break;
+		default:
+			combo->setCurrentByIndex(0);
+			break;
+	}
+	
+	BOOL show_start = TRUE;
+	
+	if ( ! force_visible )
+		show_start = gSavedSettings.getBOOL("ShowStartLocation");
+	
+	sInstance->getChildView("start_location_combo")->setVisible( show_start);
+	sInstance->getChildView("start_location_text")->setVisible( show_start);
+	
+	BOOL show_server = gSavedSettings.getBOOL("ForceShowGrid");
+	sInstance->getChildView("server_combo_text")->setVisible( show_server);	
+	sInstance->getChildView("server_combo")->setVisible( show_server);
+}
+
+// static
+void LLPanelLogin::updateStartSLURL()
+{
+	if (!sInstance) return;
+	
+	LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
+	S32 index = combo->getCurrentIndex();
+	
+	switch (index)
+	{
+		case 0:
+		{
+			LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_LAST));
+			break;
+		}			
+		case 1:
+		{
+			LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME));
+			break;
+		}
+		default:
+		{
+			LLSLURL slurl = LLSLURL(combo->getValue().asString());
+			if(slurl.getType() == LLSLURL::LOCATION)
+			{
+				// we've changed the grid, so update the grid selection
+				LLStartUp::setStartSLURL(slurl);
+			}
+			break;
+		}			
+	}
+}
+
+
+void LLPanelLogin::setLocation(const LLSLURL& slurl)
+{
+	LLStartUp::setStartSLURL(slurl);
+	updateServer();
+}
+
+// static
+void LLPanelLogin::closePanel()
+{
+	if (sInstance)
+	{
+		LLPanelLogin::sInstance->getParent()->removeChild( LLPanelLogin::sInstance );
+
+		delete sInstance;
+		sInstance = NULL;
+	}
+}
+
+// static
+void LLPanelLogin::setAlwaysRefresh(bool refresh)
+{
+	if (LLStartUp::getStartupState() >= STATE_LOGIN_CLEANUP) return;
+
+	LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
+
+	if (web_browser)
+	{
+		web_browser->setAlwaysRefresh(refresh);
+	}
+}
+
+
+
+void LLPanelLogin::loadLoginPage()
+{
+	if (!sInstance) return;
+	
+	std::ostringstream oStr;
+
+	std::string login_page = LLGridManager::getInstance()->getLoginPage();
+
+	oStr << login_page;
+	
+	// Use the right delimeter depending on how LLURI parses the URL
+	LLURI login_page_uri = LLURI(login_page);
+	
+	std::string first_query_delimiter = "&";
+	if (login_page_uri.queryMap().size() == 0)
+	{
+		first_query_delimiter = "?";
+	}
+
+	// Language
+	std::string language = LLUI::getLanguage();
+	oStr << first_query_delimiter<<"lang=" << language;
+	
+	// First Login?
+	if (gSavedSettings.getBOOL("FirstLoginThisInstall"))
+	{
+		oStr << "&firstlogin=TRUE";
+	}
+
+	// Channel and Version
+	std::string version = llformat("%s (%d)",
+								   LLVersionInfo::getShortVersion().c_str(),
+								   LLVersionInfo::getBuild());
+
+	char* curl_channel = curl_escape(LLVersionInfo::getChannel().c_str(), 0);
+	char* curl_version = curl_escape(version.c_str(), 0);
+
+	oStr << "&channel=" << curl_channel;
+	oStr << "&version=" << curl_version;
+
+	curl_free(curl_channel);
+	curl_free(curl_version);
+
+	// Grid
+	char* curl_grid = curl_escape(LLGridManager::getInstance()->getGridLabel().c_str(), 0);
+	oStr << "&grid=" << curl_grid;
+	curl_free(curl_grid);
+	
+	// add OS info
+	char * os_info = curl_escape(LLAppViewer::instance()->getOSInfo().getOSStringSimple().c_str(), 0);
+	oStr << "&os=" << os_info;
+	curl_free(os_info);
+	
+	
+	gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());
+	gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor());
+	
+	LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
+
+	// navigate to the "real" page
+	if (gSavedSettings.getBOOL("RegInClient"))
+	{
+		web_browser->setFocus(TRUE);
+		login_page = sInstance->getString("reg_in_client_url");
+		web_browser->navigateTo(login_page, "text/html");
+	}
+	else
+	{
+		web_browser->navigateTo( oStr.str(), "text/html" );
+	}
+}
+
+void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event)
+{
+	if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
+	{
+		LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
+		if (web_browser)
+		{
+			// *HACK HACK HACK HACK!
+			/* Stuff a Tab key into the browser now so that the first field will
+			** get the focus!  The embedded javascript on the page that properly
+			** sets the initial focus in a real web browser is not working inside
+			** the viewer, so this is an UGLY HACK WORKAROUND for now.
+			*/
+			// Commented out as it's not reliable
+			//web_browser->handleKey(KEY_TAB, MASK_NONE, false);
+		}
+	}
+}
+
+//---------------------------------------------------------------------------
+// Protected methods
+//---------------------------------------------------------------------------
+
+// static
+void LLPanelLogin::onClickConnect(void *)
+{
+	if (sInstance && sInstance->mCallback)
+	{
+		// tell the responder we're not here anymore
+		if ( gResponsePtr )
+			gResponsePtr->setParent( 0 );
+
+		// JC - Make sure the fields all get committed.
+		sInstance->setFocus(FALSE);
+
+		LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
+		LLSD combo_val = combo->getSelectedValue();
+		if (combo_val.isUndefined())
+		{
+			combo_val = combo->getValue();
+		}
+		if(combo_val.isUndefined())
+		{
+			LLNotificationsUtil::add("StartRegionEmpty");
+			return;
+		}		
+		try
+		{
+			LLGridManager::getInstance()->setGridChoice(combo_val.asString());
+		}
+		catch (LLInvalidGridName ex)
+		{
+			LLSD args;
+			args["GRID"] = combo_val.asString();
+			LLNotificationsUtil::add("InvalidGrid", args);
+			return;
+		}
+		updateStartSLURL();
+		std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString();
+
+		
+		if(username.empty())
+		{
+			// user must type in something into the username field
+			LLNotificationsUtil::add("MustHaveAccountToLogIn");
+		}
+		else
+		{
+			LLPointer<LLCredential> cred;
+			BOOL remember;
+			getFields(cred, remember);
+			std::string identifier_type;
+			cred->identifierType(identifier_type);
+			LLSD allowed_credential_types;
+			LLGridManager::getInstance()->getLoginIdentifierTypes(allowed_credential_types);
+			
+			// check the typed in credential type against the credential types expected by the server.
+			for(LLSD::array_iterator i = allowed_credential_types.beginArray();
+				i != allowed_credential_types.endArray();
+				i++)
+			{
+				
+				if(i->asString() == identifier_type)
+				{
+					// yay correct credential type
+					sInstance->mCallback(0, sInstance->mCallbackData);
+					return;
+				}
+			}
+			
+			// Right now, maingrid is the only thing that is picky about
+			// credential format, as it doesn't yet allow account (single username)
+			// format creds.  - Rox.  James, we wanna fix the message when we change
+			// this.
+			LLNotificationsUtil::add("InvalidCredentialFormat");			
+		}
+	}
+}
+
+/*
+// static
+bool LLPanelLogin::newAccountAlertCallback(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (0 == option)
+	{
+		llinfos << "Going to account creation URL" << llendl;
+		LLWeb::loadURLExternal( LLNotifications::instance().getGlobalString("CREATE_ACCOUNT_URL")); 
+	}
+	else
+	{
+		sInstance->setFocus(TRUE);
+	}
+	return false;
+}
+*/
+
+// static
+void LLPanelLogin::onClickNewAccount(void*)
+{
+	LLWeb::loadURLExternal(sInstance->getString("create_account_url"));
+}
+
+
+// static
+void LLPanelLogin::onClickVersion(void*)
+{
+	LLFloaterReg::showInstance("sl_about"); 
+}
+
+//static
+void LLPanelLogin::onClickForgotPassword(void*)
+{
+	if (sInstance )
+	{
+		LLWeb::loadURLExternal(sInstance->getString( "forgot_password_url" ));
+	}
+}
+
+//static
+void LLPanelLogin::onClickHelp(void*)
+{
+	if (sInstance)
+	{
+		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+		vhelp->showTopic(vhelp->preLoginTopic());
+	}
+}
+
+// static
+void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
+{
+	LLPanelLogin *This = (LLPanelLogin *) user_data;
+	This->mPasswordModified = TRUE;
+	if (gKeyboard->getKeyDown(KEY_CAPSLOCK) && sCapslockDidNotification == FALSE)
+	{
+// *TODO: use another way to notify user about enabled caps lock, see EXT-6858
+		sCapslockDidNotification = TRUE;
+	}
+}
+
+
+void LLPanelLogin::updateServer()
+{
+	try 
+	{
+
+		updateServerCombo();	
+		// if they've selected another grid, we should load the credentials
+		// for that grid and set them to the UI.
+		if(sInstance && !sInstance->areCredentialFieldsDirty())
+		{
+			LLPointer<LLCredential> credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGrid());	
+			bool remember = sInstance->getChild<LLUICtrl>("remember_check")->getValue();
+			sInstance->setFields(credential, remember);
+		}
+		// grid changed so show new splash screen (possibly)
+		loadLoginPage();
+		updateLocationCombo(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION);
+	}
+	catch (LLInvalidGridName ex)
+	{
+		// do nothing
+	}
+}
+
+void LLPanelLogin::updateServerCombo()
+{
+	if (!sInstance) 
+	{
+		return;	
+	}
+	// We add all of the possible values, sorted, and then add a bar and the current value at the top
+	LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");	
+	server_choice_combo->removeall();
+
+	std::map<std::string, std::string> known_grids = LLGridManager::getInstance()->getKnownGrids(!gSavedSettings.getBOOL("ShowBetaGrids"));
+
+	for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin();
+		 grid_choice != known_grids.end();
+		 grid_choice++)
+	{
+		if (!grid_choice->first.empty())
+		{
+			server_choice_combo->add(grid_choice->second, grid_choice->first);
+		}
+	}
+	server_choice_combo->sortByName();
+	
+	server_choice_combo->addSeparator(ADD_TOP);
+	
+	server_choice_combo->add(LLGridManager::getInstance()->getGridLabel(), 
+		LLGridManager::getInstance()->getGrid(), ADD_TOP);	
+	
+	server_choice_combo->selectFirstItem();	
+}
+
+// static
+void LLPanelLogin::onSelectServer(LLUICtrl*, void*)
+{
+	// *NOTE: The paramters for this method are ignored. 
+	// LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe, void*)
+	// calls this method.
+	LL_INFOS("AppInit") << "onSelectServer" << LL_ENDL;
+	// The user twiddled with the grid choice ui.
+	// apply the selection to the grid setting.
+	LLPointer<LLCredential> credential;
+	
+	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
+	LLSD combo_val = combo->getSelectedValue();
+	if (combo_val.isUndefined())
+	{
+		combo_val = combo->getValue();
+	}
+	
+	combo = sInstance->getChild<LLComboBox>("start_location_combo");	
+	combo->setCurrentByIndex(1);
+	LLStartUp::setStartSLURL(LLSLURL(gSavedSettings.getString("LoginLocation")));
+	LLGridManager::getInstance()->setGridChoice(combo_val.asString());
+	// This new selection will override preset uris
+	// from the command line.
+	updateServer();
+	updateLocationCombo(false);
+	updateLoginPanelLinks();
+}
+
+void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe)
+{
+	if (!sInstance)
+	{
+		return;
+	}
+
+	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
+	if(fe == combo)
+	{
+		onSelectServer(combo, NULL);	
+	}
+}
+
+void LLPanelLogin::updateLoginPanelLinks()
+{
+	LLSD grid_data;
+	LLGridManager::getInstance()->getGridInfo(grid_data);
+	bool system_grid = grid_data.has(GRID_IS_SYSTEM_GRID_VALUE);
+	
+	// need to call through sInstance, as it's called from onSelectServer, which
+	// is static.
+	sInstance->getChildView("create_new_account_text")->setVisible( system_grid);
+	sInstance->getChildView("forgot_password_text")->setVisible( system_grid);
+}
+
+//static
+void LLPanelLogin::onModeChange()
+{
+	LLNotificationsUtil::add("ModeChange", LLSD(), LLSD(), boost::bind(&onModeChangeConfirm, _1, _2));
+}
+
+//static
+void LLPanelLogin::onModeChangeConfirm(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	switch (option)
+	{
+	case 0:
+		LLAppViewer::instance()->requestQuit();
+		break;
+	case 1:
+		// do nothing
+		break;
+	default:
+		break;
+	}
+}
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 8aaa7f0e13b3aa5acd9136ccbd0535ca5bf8f4d8..a9bb01ac70a9b606856ac4dc6367c1f5aa9e9091 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -96,6 +96,7 @@ bool	LLSideTray::instanceCreated	()
 
 class LLSideTrayTab: public LLPanel
 {
+	LOG_CLASS(LLSideTrayTab);
 	friend class LLUICtrlFactory;
 	friend class LLSideTray;
 public:
@@ -122,6 +123,8 @@ class LLSideTrayTab: public LLPanel
 	void			undock(LLFloater* floater_tab);
 
 	LLSideTray*		getSideTray();
+
+	void			onFloaterClose(LLSD::Boolean app_quitting);
 	
 public:
 	virtual ~LLSideTrayTab();
@@ -140,6 +143,8 @@ class LLSideTrayTab: public LLPanel
 	void			onOpen		(const LLSD& key);
 	
 	void			toggleTabDocked();
+	void			setDocked(bool dock);
+	bool			isDocked() const;
 
 	BOOL			handleScrollWheel(S32 x, S32 y, S32 clicks);
 
@@ -151,6 +156,7 @@ class LLSideTrayTab: public LLPanel
 	std::string	mDescription;
 	
 	LLView*	mMainPanel;
+	boost::signals2::connection mFloaterCloseConn;
 };
 
 LLSideTrayTab::LLSideTrayTab(const Params& p)
@@ -271,6 +277,35 @@ void LLSideTrayTab::toggleTabDocked()
 	LLFloaterReg::toggleInstance("side_bar_tab", tab_name);
 }
 
+// Same as toggleTabDocked() apart from making sure that we do exactly what we want.
+void LLSideTrayTab::setDocked(bool dock)
+{
+	if (isDocked() == dock)
+	{
+		llwarns << "Tab " << getName() << " is already " << (dock ? "docked" : "undocked") << llendl;
+		return;
+	}
+
+	toggleTabDocked();
+}
+
+bool LLSideTrayTab::isDocked() const
+{
+	return dynamic_cast<LLSideTray*>(getParent()) != NULL;
+}
+
+void LLSideTrayTab::onFloaterClose(LLSD::Boolean app_quitting)
+{
+	// If user presses Ctrl-Shift-W, handle that gracefully by docking all
+	// undocked tabs before their floaters get destroyed (STORM-1016).
+
+	// Don't dock on quit for the current dock state to be correctly saved.
+	if (app_quitting) return;
+
+	lldebugs << "Forcibly docking tab " << getName() << llendl;
+	setDocked(true);
+}
+
 BOOL LLSideTrayTab::handleScrollWheel(S32 x, S32 y, S32 clicks)
 {
 	// Let children handle the event
@@ -294,6 +329,7 @@ void LLSideTrayTab::dock(LLFloater* floater_tab)
 		return;
 	}
 
+	mFloaterCloseConn.disconnect();
 	setRect(side_tray->getLocalRect());
 	reshape(getRect().getWidth(), getRect().getHeight());
 
@@ -342,6 +378,7 @@ void LLSideTrayTab::undock(LLFloater* floater_tab)
 	}
 
 	floater_tab->addChild(this);
+	mFloaterCloseConn = floater_tab->setCloseCallback(boost::bind(&LLSideTrayTab::onFloaterClose, this, _2));
 	floater_tab->setTitle(mTabTitle);
 	floater_tab->setName(getName());
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index add24e521626a8ddbe1fa34f0ce082309302ba79..75cf2efc69f511a21a4a24f0f76d480ae42d8a34 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1,8174 +1,8183 @@
-/** 
- * @file llviewermenu.cpp
- * @brief Builds menus out of items.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llviewermenu.h" 
-
-// linden library includes
-#include "llavatarnamecache.h"	// IDEVO
-#include "llfloaterreg.h"
-#include "llcombobox.h"
-#include "llinventorypanel.h"
-#include "llnotifications.h"
-#include "llnotificationsutil.h"
-
-// newview includes
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llagentwearables.h"
-#include "llagentpilot.h"
-#include "llbottomtray.h"
-#include "llcompilequeue.h"
-#include "llconsole.h"
-#include "lldebugview.h"
-#include "llfilepicker.h"
-#include "llfirstuse.h"
-#include "llfloaterbuy.h"
-#include "llfloaterbuycontents.h"
-#include "llbuycurrencyhtml.h"
-#include "llfloatergodtools.h"
-#include "llfloaterinventory.h"
-#include "llfloaterland.h"
-#include "llfloaterpay.h"
-#include "llfloaterreporter.h"
-#include "llfloatersearch.h"
-#include "llfloaterscriptdebug.h"
-#include "llfloatersnapshot.h"
-#include "llfloatertools.h"
-#include "llfloaterworldmap.h"
-#include "llavataractions.h"
-#include "lllandmarkactions.h"
-#include "llgroupmgr.h"
-#include "lltooltip.h"
-#include "llhints.h"
-#include "llhudeffecttrail.h"
-#include "llhudmanager.h"
-#include "llimview.h"
-#include "llinventorybridge.h"
-#include "llinventorydefines.h"
-#include "llinventoryfunctions.h"
-#include "llpanellogin.h"
-#include "llpanelblockedlist.h"
-#include "llmenucommands.h"
-#include "llmoveview.h"
-#include "llparcel.h"
-#include "llrootview.h"
-#include "llselectmgr.h"
-#include "llsidetray.h"
-#include "llstatusbar.h"
-#include "lltextureview.h"
-#include "lltoolcomp.h"
-#include "lltoolmgr.h"
-#include "lltoolpie.h"
-#include "lltoolselectland.h"
-#include "lltrans.h"
-#include "llviewergenericmessage.h"
-#include "llviewerhelp.h"
-#include "llviewermenufile.h"	// init_menu_file()
-#include "llviewermessage.h"
-#include "llviewernetwork.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerstats.h"
-#include "llvoavatarself.h"
-#include "llworldmap.h"
-#include "pipeline.h"
-#include "llviewerjoystick.h"
-#include "llwlanimator.h"
-#include "llwlparammanager.h"
-#include "llfloatercamera.h"
-#include "lluilistener.h"
-#include "llappearancemgr.h"
-#include "lltrans.h"
-#include "lleconomy.h"
-#include "boost/unordered_map.hpp"
-
-using namespace LLVOAvatarDefines;
-
-static boost::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels;
-
-BOOL enable_land_build(void*);
-BOOL enable_object_build(void*);
-
-LLVOAvatar* find_avatar_from_object( LLViewerObject* object );
-LLVOAvatar* find_avatar_from_object( const LLUUID& object_id );
-
-void handle_test_load_url(void*);
-
-//
-// Evil hackish imported globals
-
-//extern BOOL	gHideSelectedObjects;
-//extern BOOL gAllowSelectAvatar;
-//extern BOOL gDebugAvatarRotation;
-extern BOOL gDebugClicks;
-extern BOOL gDebugWindowProc;
-//extern BOOL gDebugTextEditorTips;
-//extern BOOL gDebugSelectMgr;
-
-//
-// Globals
-//
-
-LLMenuBarGL		*gMenuBarView = NULL;
-LLViewerMenuHolderGL	*gMenuHolder = NULL;
-LLMenuGL		*gPopupMenuView = NULL;
-LLMenuGL		*gEditMenu = NULL;
-LLMenuBarGL		*gLoginMenuBarView = NULL;
-
-// Pie menus
-LLContextMenu	*gMenuAvatarSelf	= NULL;
-LLContextMenu	*gMenuAvatarOther = NULL;
-LLContextMenu	*gMenuObject = NULL;
-LLContextMenu	*gMenuAttachmentSelf = NULL;
-LLContextMenu	*gMenuAttachmentOther = NULL;
-LLContextMenu	*gMenuLand	= NULL;
-
-const std::string SAVE_INTO_INVENTORY("Save Object Back to My Inventory");
-const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents");
-
-LLMenuGL* gAttachSubMenu = NULL;
-LLMenuGL* gDetachSubMenu = NULL;
-LLMenuGL* gTakeOffClothes = NULL;
-LLContextMenu* gAttachScreenPieMenu = NULL;
-LLContextMenu* gAttachPieMenu = NULL;
-LLContextMenu* gAttachBodyPartPieMenus[8];
-LLContextMenu* gDetachPieMenu = NULL;
-LLContextMenu* gDetachScreenPieMenu = NULL;
-LLContextMenu* gDetachBodyPartPieMenus[8];
-
-LLMenuItemCallGL* gAFKMenu = NULL;
-LLMenuItemCallGL* gBusyMenu = NULL;
-
-//
-// Local prototypes
-
-// File Menu
-const char* upload_pick(void* data);
-void handle_compress_image(void*);
-
-
-// Edit menu
-void handle_dump_group_info(void *);
-void handle_dump_capabilities_info(void *);
-
-// Advanced->Consoles menu
-void handle_region_dump_settings(void*);
-void handle_region_dump_temp_asset_data(void*);
-void handle_region_clear_temp_asset_data(void*);
-
-// Object pie menu
-BOOL sitting_on_selection();
-
-void near_sit_object();
-//void label_sit_or_stand(std::string& label, void*);
-// buy and take alias into the same UI positions, so these
-// declarations handle this mess.
-BOOL is_selection_buy_not_take();
-S32 selection_price();
-BOOL enable_take();
-void handle_take();
-void handle_object_show_inspector();
-void handle_avatar_show_inspector();
-bool confirm_take(const LLSD& notification, const LLSD& response);
-
-void handle_buy_object(LLSaleInfo sale_info);
-void handle_buy_contents(LLSaleInfo sale_info);
-
-// Land pie menu
-void near_sit_down_point(BOOL success, void *);
-
-// Avatar pie menu
-
-// Debug menu
-
-
-void velocity_interpolate( void* );
-
-void handle_rebake_textures(void*);
-BOOL check_admin_override(void*);
-void handle_admin_override_toggle(void*);
-#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-void handle_toggle_hacked_godmode(void*);
-BOOL check_toggle_hacked_godmode(void*);
-bool enable_toggle_hacked_godmode(void*);
-#endif
-
-void toggle_show_xui_names(void *);
-BOOL check_show_xui_names(void *);
-
-// Debug UI
-
-void handle_buy_currency_test(void*);
-
-void handle_god_mode(void*);
-
-// God menu
-void handle_leave_god_mode(void*);
-
-
-void handle_reset_view();
-
-void handle_duplicate_in_place(void*);
-
-
-void handle_object_owner_self(void*);
-void handle_object_owner_permissive(void*);
-void handle_object_lock(void*);
-void handle_object_asset_ids(void*);
-void force_take_copy(void*);
-#ifdef _CORY_TESTING
-void force_export_copy(void*);
-void force_import_geometry(void*);
-#endif
-
-void handle_force_parcel_owner_to_me(void*);
-void handle_force_parcel_to_content(void*);
-void handle_claim_public_land(void*);
-
-void handle_god_request_avatar_geometry(void *);	// Hack for easy testing of new avatar geometry
-void reload_vertex_shader(void *);
-void handle_disconnect_viewer(void *);
-
-void force_error_breakpoint(void *);
-void force_error_llerror(void *);
-void force_error_bad_memory_access(void *);
-void force_error_infinite_loop(void *);
-void force_error_software_exception(void *);
-void force_error_driver_crash(void *);
-
-void handle_force_delete(void*);
-void print_object_info(void*);
-void print_agent_nvpairs(void*);
-void toggle_debug_menus(void*);
-void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status);
-void dump_select_mgr(void*);
-
-void dump_inventory(void*);
-void toggle_visibility(void*);
-BOOL get_visibility(void*);
-
-// Avatar Pie menu
-void request_friendship(const LLUUID& agent_id);
-
-// Tools menu
-void handle_selected_texture_info(void*);
-
-void handle_dump_followcam(void*);
-void handle_viewer_enable_message_log(void*);
-void handle_viewer_disable_message_log(void*);
-
-BOOL enable_buy_land(void*);
-
-// Help menu
-
-void handle_test_male(void *);
-void handle_test_female(void *);
-void handle_toggle_pg(void*);
-void handle_dump_attachments(void *);
-void handle_dump_avatar_local_textures(void*);
-void handle_debug_avatar_textures(void*);
-void handle_grab_baked_texture(void*);
-BOOL enable_grab_baked_texture(void*);
-void handle_dump_region_object_cache(void*);
-
-BOOL enable_save_into_inventory(void*);
-BOOL enable_save_into_task_inventory(void*);
-
-BOOL enable_detach(const LLSD& = LLSD());
-void menu_toggle_attached_lights(void* user_data);
-void menu_toggle_attached_particles(void* user_data);
-
-class LLMenuParcelObserver : public LLParcelObserver
-{
-public:
-	LLMenuParcelObserver();
-	~LLMenuParcelObserver();
-	virtual void changed();
-};
-
-static LLMenuParcelObserver* gMenuParcelObserver = NULL;
-
-static LLUIListener sUIListener;
-
-LLMenuParcelObserver::LLMenuParcelObserver()
-{
-	LLViewerParcelMgr::getInstance()->addObserver(this);
-}
-
-LLMenuParcelObserver::~LLMenuParcelObserver()
-{
-	LLViewerParcelMgr::getInstance()->removeObserver(this);
-}
-
-void LLMenuParcelObserver::changed()
-{
-	gMenuHolder->childSetEnabled("Land Buy Pass", LLPanelLandGeneral::enableBuyPass(NULL));
-	
-	BOOL buyable = enable_buy_land(NULL);
-	gMenuHolder->childSetEnabled("Land Buy", buyable);
-	gMenuHolder->childSetEnabled("Buy Land...", buyable);
-}
-
-
-void initialize_menus();
-
-//-----------------------------------------------------------------------------
-// Initialize main menus
-//
-// HOW TO NAME MENUS:
-//
-// First Letter Of Each Word Is Capitalized, Even At Or And
-//
-// Items that lead to dialog boxes end in "..."
-//
-// Break up groups of more than 6 items with separators
-//-----------------------------------------------------------------------------
-
-void set_underclothes_menu_options()
-{
-	if (gMenuHolder && gAgent.isTeen())
-	{
-		gMenuHolder->getChild<LLView>("Self Underpants")->setVisible(FALSE);
-		gMenuHolder->getChild<LLView>("Self Undershirt")->setVisible(FALSE);
-	}
-	if (gMenuBarView && gAgent.isTeen())
-	{
-		gMenuBarView->getChild<LLView>("Menu Underpants")->setVisible(FALSE);
-		gMenuBarView->getChild<LLView>("Menu Undershirt")->setVisible(FALSE);
-	}
-}
-
-void init_menus()
-{
-	S32 top = gViewerWindow->getRootView()->getRect().getHeight();
-
-	// Initialize actions
-	initialize_menus();
-
-	///
-	/// Popup menu
-	///
-	/// The popup menu is now populated by the show_context_menu()
-	/// method.
-	
-	LLMenuGL::Params menu_params;
-	menu_params.name = "Popup";
-	menu_params.visible = false;
-	gPopupMenuView = LLUICtrlFactory::create<LLMenuGL>(menu_params);
-	gMenuHolder->addChild( gPopupMenuView );
-
-	///
-	/// Context menus
-	///
-
-	const widget_registry_t& registry =
-		LLViewerMenuHolderGL::child_registry_t::instance();
-	gEditMenu = LLUICtrlFactory::createFromFile<LLMenuGL>("menu_edit.xml", gMenuHolder, registry);
-	gMenuAvatarSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
-		"menu_avatar_self.xml", gMenuHolder, registry);
-	gMenuAvatarOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
-		"menu_avatar_other.xml", gMenuHolder, registry);
-
-	gDetachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach HUD", true);
-	gDetachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach", true);
-
-	gMenuObject = LLUICtrlFactory::createFromFile<LLContextMenu>(
-		"menu_object.xml", gMenuHolder, registry);
-
-	gAttachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach HUD");
-	gAttachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach");
-
-	gMenuAttachmentSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
-		"menu_attachment_self.xml", gMenuHolder, registry);
-	gMenuAttachmentOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
-		"menu_attachment_other.xml", gMenuHolder, registry);
-
-	gMenuLand = LLUICtrlFactory::createFromFile<LLContextMenu>(
-		"menu_land.xml", gMenuHolder, registry);
-
-	///
-	/// set up the colors
-	///
-	LLColor4 color;
-
-	LLColor4 context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor");
-	
-	gMenuAvatarSelf->setBackgroundColor( context_menu_color );
-	gMenuAvatarOther->setBackgroundColor( context_menu_color );
-	gMenuObject->setBackgroundColor( context_menu_color );
-	gMenuAttachmentSelf->setBackgroundColor( context_menu_color );
-	gMenuAttachmentOther->setBackgroundColor( context_menu_color );
-
-	gMenuLand->setBackgroundColor( context_menu_color );
-
-	color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" );
-	gPopupMenuView->setBackgroundColor( color );
-
-	// If we are not in production, use a different color to make it apparent.
-	if (LLGridManager::getInstance()->isInProductionGrid())
-	{
-		color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
-	}
-	else
-	{
-		color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
-	}
-	gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	gMenuBarView->setRect(LLRect(0, top, 0, top - MENU_BAR_HEIGHT));
-	gMenuBarView->setBackgroundColor( color );
-
-	LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder");
-	menu_bar_holder->addChild(gMenuBarView);
-  
-    gViewerWindow->setMenuBackgroundColor(false, 
-        LLGridManager::getInstance()->isInProductionGrid());
-
-	// Assume L$10 for now, the server will tell us the real cost at login
-	// *TODO:Also fix cost in llfolderview.cpp for Inventory menus
-	const std::string upload_cost("10");
-	gMenuHolder->childSetLabelArg("Upload Image", "[COST]", upload_cost);
-	gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", upload_cost);
-	gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", upload_cost);
-	gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", upload_cost);
-
-	gAFKMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Away", TRUE);
-	gBusyMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Busy", TRUE);
-	gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE);
-	gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE);
-
-#if !MEM_TRACK_MEM
-	// Don't display the Memory console menu if the feature is turned off
-	LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", TRUE);
-	if (memoryMenu)
-	{
-		memoryMenu->setVisible(FALSE);
-	}
-#endif
-
-	gMenuBarView->createJumpKeys();
-
-	// Let land based option enable when parcel changes
-	gMenuParcelObserver = new LLMenuParcelObserver();
-
-	gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	gLoginMenuBarView->arrangeAndClear();
-	LLRect menuBarRect = gLoginMenuBarView->getRect();
-	menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight());
-	gLoginMenuBarView->setRect(menuBarRect);
-	gLoginMenuBarView->setBackgroundColor( color );
-	menu_bar_holder->addChild(gLoginMenuBarView);
-	
-	// tooltips are on top of EVERYTHING, including menus
-	gViewerWindow->getRootView()->sendChildToFront(gToolTipView);
-}
-
-///////////////////
-// SHOW CONSOLES //
-///////////////////
-
-
-class LLAdvancedToggleConsole : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string console_type = userdata.asString();
-		if ("texture" == console_type)
-		{
-			toggle_visibility( (void*)gTextureView );
-		}
-		else if ("debug" == console_type)
-		{
-			toggle_visibility( (void*)static_cast<LLUICtrl*>(gDebugView->mDebugConsolep));
-		}
-		else if (gTextureSizeView && "texture size" == console_type)
-		{
-			toggle_visibility( (void*)gTextureSizeView );
-		}
-		else if (gTextureCategoryView && "texture category" == console_type)
-		{
-			toggle_visibility( (void*)gTextureCategoryView );
-		}
-		else if ("fast timers" == console_type)
-		{
-			toggle_visibility( (void*)gDebugView->mFastTimerView );
-		}
-#if MEM_TRACK_MEM
-		else if ("memory view" == console_type)
-		{
-			toggle_visibility( (void*)gDebugView->mMemoryView );
-		}
-#endif
-		return true;
-	}
-};
-class LLAdvancedCheckConsole : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string console_type = userdata.asString();
-		bool new_value = false;
-		if ("texture" == console_type)
-		{
-			new_value = get_visibility( (void*)gTextureView );
-		}
-		else if ("debug" == console_type)
-		{
-			new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) );
-		}
-		else if (gTextureSizeView && "texture size" == console_type)
-		{
-			new_value = get_visibility( (void*)gTextureSizeView );
-		}
-		else if (gTextureCategoryView && "texture category" == console_type)
-		{
-			new_value = get_visibility( (void*)gTextureCategoryView );
-		}
-		else if ("fast timers" == console_type)
-		{
-			new_value = get_visibility( (void*)gDebugView->mFastTimerView );
-		}
-#if MEM_TRACK_MEM
-		else if ("memory view" == console_type)
-		{
-			new_value = get_visibility( (void*)gDebugView->mMemoryView );
-		}
-#endif
-		
-		return new_value;
-	}
-};
-
-
-//////////////////////////
-// DUMP INFO TO CONSOLE //
-//////////////////////////
-
-
-class LLAdvancedDumpInfoToConsole : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string info_type = userdata.asString();
-		if ("region" == info_type)
-		{
-			handle_region_dump_settings(NULL);
-		}
-		else if ("group" == info_type)
-		{
-			handle_dump_group_info(NULL);
-		}
-		else if ("capabilities" == info_type)
-		{
-			handle_dump_capabilities_info(NULL);
-		}
-		return true;
-	}
-};
-
-
-//////////////
-// HUD INFO //
-//////////////
-
-
-class LLAdvancedToggleHUDInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string info_type = userdata.asString();
-
-		if ("camera" == info_type)
-		{
-			gDisplayCameraPos = !(gDisplayCameraPos);
-		}
-		else if ("wind" == info_type)
-		{
-			gDisplayWindInfo = !(gDisplayWindInfo);
-		}
-		else if ("fov" == info_type)
-		{
-			gDisplayFOV = !(gDisplayFOV);
-		}
-		else if ("badge" == info_type)
-		{
-			gDisplayBadge = !(gDisplayBadge);
-		}
-		return true;
-	}
-};
-
-class LLAdvancedCheckHUDInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string info_type = userdata.asString();
-		bool new_value = false;
-		if ("camera" == info_type)
-		{
-			new_value = gDisplayCameraPos;
-		}
-		else if ("wind" == info_type)
-		{
-			new_value = gDisplayWindInfo;
-		}
-		else if ("fov" == info_type)
-		{
-			new_value = gDisplayFOV;
-		}
-		else if ("badge" == info_type)
-		{
-			new_value = gDisplayBadge;
-		}
-		return new_value;
-	}
-};
-
-
-//////////////
-// FLYING   //
-//////////////
-
-class LLAdvancedAgentFlyingInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD&)
-	{
-		return gAgent.getFlying();
-	}
-};
-
-
-///////////////////////
-// CLEAR GROUP CACHE //
-///////////////////////
-
-class LLAdvancedClearGroupCache : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLGroupMgr::debugClearAllGroups(NULL);
-		return true;
-	}
-};
-
-
-
-
-/////////////////
-// RENDER TYPE //
-/////////////////
-U32 render_type_from_string(std::string render_type)
-{
-	if ("simple" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_SIMPLE;
-	}
-	else if ("alpha" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_ALPHA;
-	}
-	else if ("tree" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_TREE;
-	}
-	else if ("character" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_AVATAR;
-	}
-	else if ("surfacePath" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_TERRAIN;
-	}
-	else if ("sky" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_SKY;
-	}
-	else if ("water" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_WATER;
-	}
-	else if ("ground" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_GROUND;
-	}
-	else if ("volume" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_VOLUME;
-	}
-	else if ("grass" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_GRASS;
-	}
-	else if ("clouds" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_CLOUDS;
-	}
-	else if ("particles" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_PARTICLES;
-	}
-	else if ("bump" == render_type)
-	{
-		return LLPipeline::RENDER_TYPE_BUMP;
-	}
-	else
-	{
-		return 0;
-	}
-}
-
-
-class LLAdvancedToggleRenderType : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		U32 render_type = render_type_from_string( userdata.asString() );
-		if ( render_type != 0 )
-		{
-			LLPipeline::toggleRenderTypeControl( (void*)render_type );
-		}
-		return true;
-	}
-};
-
-
-class LLAdvancedCheckRenderType : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		U32 render_type = render_type_from_string( userdata.asString() );
-		bool new_value = false;
-
-		if ( render_type != 0 )
-		{
-			new_value = LLPipeline::hasRenderTypeControl( (void*)render_type );
-		}
-
-		return new_value;
-	}
-};
-
-
-/////////////
-// FEATURE //
-/////////////
-U32 feature_from_string(std::string feature)
-{ 
-	if ("ui" == feature)
-	{ 
-		return LLPipeline::RENDER_DEBUG_FEATURE_UI;
-	}
-	else if ("selected" == feature)
-	{
-		return LLPipeline::RENDER_DEBUG_FEATURE_SELECTED;
-	}
-	else if ("highlighted" == feature)
-	{
-		return LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED;
-	}
-	else if ("dynamic textures" == feature)
-	{
-		return LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES;
-	}
-	else if ("foot shadows" == feature)
-	{
-		return LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS;
-	}
-	else if ("fog" == feature)
-	{
-		return LLPipeline::RENDER_DEBUG_FEATURE_FOG;
-	}
-	else if ("fr info" == feature)
-	{
-		return LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO;
-	}
-	else if ("flexible" == feature)
-	{
-		return LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE;
-	}
-	else
-	{
-		return 0;
-	}
-};
-
-
-class LLAdvancedToggleFeature : public view_listener_t{
-	bool handleEvent(const LLSD& userdata)
-	{
-		U32 feature = feature_from_string( userdata.asString() );
-		if ( feature != 0 )
-		{
-			LLPipeline::toggleRenderDebugFeature( (void*)feature );
-		}
-		return true;
-	}
-};
-
-class LLAdvancedCheckFeature : public view_listener_t
-{bool handleEvent(const LLSD& userdata)
-{
-	U32 feature = feature_from_string( userdata.asString() );
-	bool new_value = false;
-
-	if ( feature != 0 )
-	{
-		new_value = LLPipeline::toggleRenderDebugFeatureControl( (void*)feature );
-	}
-
-	return new_value;
-}
-};
-
-void toggle_destination_and_avatar_picker(const LLSD& show)
-{
-	S32 panel_idx = show.isDefined() ? show.asInteger() : -1;
-	LLView* container = gViewerWindow->getRootView()->getChildView("avatar_picker_and_destination_guide_container");
-	LLMediaCtrl* destinations = container->findChild<LLMediaCtrl>("destination_guide_contents");
-	LLMediaCtrl* avatar_picker = container->findChild<LLMediaCtrl>("avatar_picker_contents");
-	LLButton* avatar_btn = gViewerWindow->getRootView()->getChildView("bottom_tray")->getChild<LLButton>("avatar_btn");
-	LLButton* destination_btn = gViewerWindow->getRootView()->getChildView("bottom_tray")->getChild<LLButton>("destination_btn");
-
-	switch(panel_idx)
-	{
-	case 0:
-		container->setVisible(true);
-		destinations->setVisible(true);
-		avatar_picker->setVisible(false);
-		LLFirstUse::notUsingDestinationGuide(false);
-		avatar_btn->setToggleState(false);
-		destination_btn->setToggleState(true);
-		break;
-	case 1:
-		container->setVisible(true);
-		destinations->setVisible(false);
-		avatar_picker->setVisible(true);
-		avatar_btn->setToggleState(true);
-		destination_btn->setToggleState(false);
-		break;
-	default:
-		container->setVisible(false);
-		destinations->setVisible(false);
-		avatar_picker->setVisible(false);
-		avatar_btn->setToggleState(false);
-		destination_btn->setToggleState(false);
-		break;
-	}
-};
-
-
-//////////////////
-// INFO DISPLAY //
-//////////////////
-U32 info_display_from_string(std::string info_display)
-{
-	if ("verify" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_VERIFY;
-	}
-	else if ("bboxes" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_BBOXES;
-	}
-	else if ("points" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_POINTS;
-	}
-	else if ("octree" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_OCTREE;
-	}
-	else if ("shadow frusta" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA;
-	}
-	else if ("occlusion" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_OCCLUSION;
-	}
-	else if ("render batches" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_BATCH_SIZE;
-	}
-	else if ("update type" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_UPDATE_TYPE;
-	}
-	else if ("texture anim" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM;
-	}
-	else if ("texture priority" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY;
-	}
-	else if ("shame" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_SHAME;
-	}
-	else if ("texture area" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_TEXTURE_AREA;
-	}
-	else if ("face area" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_FACE_AREA;
-	}
-	else if ("lights" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_LIGHTS;
-	}
-	else if ("particles" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_PARTICLES;
-	}
-	else if ("composition" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_COMPOSITION;
-	}
-	else if ("glow" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_GLOW;
-	}
-	else if ("collision skeleton" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME;
-	}
-	else if ("raycast" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_RAYCAST;
-	}
-	else if ("agent target" == info_display)
-	{
-		return LLPipeline::RENDER_DEBUG_AGENT_TARGET;
-	}
-	else
-	{
-		return 0;
-	}
-};
-
-class LLAdvancedToggleInfoDisplay : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		U32 info_display = info_display_from_string( userdata.asString() );
-
-		if ( info_display != 0 )
-		{
-			LLPipeline::toggleRenderDebug( (void*)info_display );
-		}
-
-		return true;
-	}
-};
-
-
-class LLAdvancedCheckInfoDisplay : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		U32 info_display = info_display_from_string( userdata.asString() );
-		bool new_value = false;
-
-		if ( info_display != 0 )
-		{
-			new_value = LLPipeline::toggleRenderDebugControl( (void*)info_display );
-		}
-
-		return new_value;
-	}
-};
-
-
-///////////////////////////
-//// RANDOMIZE FRAMERATE //
-///////////////////////////
-
-
-class LLAdvancedToggleRandomizeFramerate : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gRandomizeFramerate = !(gRandomizeFramerate);
-		return true;
-	}
-};
-
-class LLAdvancedCheckRandomizeFramerate : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gRandomizeFramerate;
-		return new_value;
-	}
-};
-
-void run_vectorize_perf_test(void *)
-{
-	gSavedSettings.setBOOL("VectorizePerfTest", TRUE);
-}
-
-
-////////////////////////////////
-// RUN Vectorized Perform Test//
-////////////////////////////////
-
-
-class LLAdvancedVectorizePerfTest : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		run_vectorize_perf_test(NULL);
-		return true;
-	}
-};
-
-///////////////////////////
-//// PERIODIC SLOW FRAME //
-///////////////////////////
-
-
-class LLAdvancedTogglePeriodicSlowFrame : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gPeriodicSlowFrame = !(gPeriodicSlowFrame);
-		return true;
-	}
-};
-
-class LLAdvancedCheckPeriodicSlowFrame : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gPeriodicSlowFrame;
-		return new_value;
-	}
-};
-
-
-
-////////////////
-// FRAME TEST //
-////////////////
-
-
-class LLAdvancedToggleFrameTest : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLPipeline::sRenderFrameTest = !(LLPipeline::sRenderFrameTest);
-		return true;
-	}
-};
-
-class LLAdvancedCheckFrameTest : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLPipeline::sRenderFrameTest;
-		return new_value;
-	}
-};
-
-
-///////////////////////////
-// SELECTED TEXTURE INFO //
-///////////////////////////
-
-
-class LLAdvancedSelectedTextureInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_selected_texture_info(NULL);
-		return true;
-	}
-};
-
-//////////////////////
-// TOGGLE WIREFRAME //
-//////////////////////
-
-class LLAdvancedToggleWireframe : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gUseWireframe = !(gUseWireframe);
-		LLPipeline::updateRenderDeferred();
-		gPipeline.resetVertexBuffers();
-		return true;
-	}
-};
-
-class LLAdvancedCheckWireframe : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gUseWireframe;
-		return new_value;
-	}
-};
-	
-//////////////////////
-// TEXTURE ATLAS //
-//////////////////////
-
-class LLAdvancedToggleTextureAtlas : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLViewerTexture::sUseTextureAtlas = !LLViewerTexture::sUseTextureAtlas;
-		gSavedSettings.setBOOL("EnableTextureAtlas", LLViewerTexture::sUseTextureAtlas) ;
-		return true;
-	}
-};
-
-class LLAdvancedCheckTextureAtlas : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLViewerTexture::sUseTextureAtlas; // <-- make this using LLCacheControl
-		return new_value;
-	}
-};
-
-//////////////////////////
-// DUMP SCRIPTED CAMERA //
-//////////////////////////
-	
-class LLAdvancedDumpScriptedCamera : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_dump_followcam(NULL);
-		return true;
-}
-};
-
-
-
-//////////////////////////////
-// DUMP REGION OBJECT CACHE //
-//////////////////////////////
-
-
-class LLAdvancedDumpRegionObjectCache : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-{
-		handle_dump_region_object_cache(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedBuyCurrencyTest : public view_listener_t
-	{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_buy_currency_test(NULL);
-		return true;
-	}
-};
-
-
-/////////////////////
-// DUMP SELECT MGR //
-/////////////////////
-
-
-class LLAdvancedDumpSelectMgr : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		dump_select_mgr(NULL);
-		return true;
-	}
-};
-
-
-
-////////////////////
-// DUMP INVENTORY //
-////////////////////
-
-
-class LLAdvancedDumpInventory : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		dump_inventory(NULL);
-		return true;
-	}
-};
-
-
-
-////////////////////////////////
-// PRINT SELECTED OBJECT INFO //
-////////////////////////////////
-
-
-class LLAdvancedPrintSelectedObjectInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		print_object_info(NULL);
-		return true;
-	}
-};
-
-
-
-//////////////////////
-// PRINT AGENT INFO //
-//////////////////////
-
-
-class LLAdvancedPrintAgentInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		print_agent_nvpairs(NULL);
-		return true;
-	}
-};
-
-
-
-////////////////////////////////
-// PRINT TEXTURE MEMORY STATS //
-////////////////////////////////
-
-
-class LLAdvancedPrintTextureMemoryStats : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		output_statistics(NULL);
-		return true;
-	}
-};
-
-//////////////////
-// DEBUG CLICKS //
-//////////////////
-
-
-class LLAdvancedToggleDebugClicks : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gDebugClicks = !(gDebugClicks);
-		return true;
-	}
-};
-
-class LLAdvancedCheckDebugClicks : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gDebugClicks;
-		return new_value;
-	}
-};
-
-
-
-/////////////////
-// DEBUG VIEWS //
-/////////////////
-
-
-class LLAdvancedToggleDebugViews : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLView::sDebugRects = !(LLView::sDebugRects);
-		return true;
-	}
-};
-
-class LLAdvancedCheckDebugViews : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLView::sDebugRects;
-		return new_value;
-	}
-};
-
-
-
-///////////////////////
-// XUI NAME TOOLTIPS //
-///////////////////////
-
-
-class LLAdvancedToggleXUINameTooltips : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		toggle_show_xui_names(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedCheckXUINameTooltips : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = check_show_xui_names(NULL);
-		return new_value;
-	}
-};
-
-
-
-////////////////////////
-// DEBUG MOUSE EVENTS //
-////////////////////////
-
-
-class LLAdvancedToggleDebugMouseEvents : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLView::sDebugMouseHandling = !(LLView::sDebugMouseHandling);
-		return true;
-	}
-};
-
-class LLAdvancedCheckDebugMouseEvents : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLView::sDebugMouseHandling;
-		return new_value;
-	}
-};
-
-
-
-////////////////
-// DEBUG KEYS //
-////////////////
-
-
-class LLAdvancedToggleDebugKeys : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLView::sDebugKeys = !(LLView::sDebugKeys);
-		return true;
-	}
-};
-	
-class LLAdvancedCheckDebugKeys : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLView::sDebugKeys;
-		return new_value;
-	}
-};
-	
-
-
-///////////////////////
-// DEBUG WINDOW PROC //
-///////////////////////
-
-
-class LLAdvancedToggleDebugWindowProc : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gDebugWindowProc = !(gDebugWindowProc);
-		return true;
-	}
-};
-
-class LLAdvancedCheckDebugWindowProc : public view_listener_t
-	{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gDebugWindowProc;
-		return new_value;
-	}
-};
-
-// ------------------------------XUI MENU ---------------------------
-
-class LLAdvancedSendTestIms : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLIMModel::instance().testMessages();
-		return true;
-}
-};
-
-
-///////////////
-// XUI NAMES //
-///////////////
-
-
-class LLAdvancedToggleXUINames : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		toggle_show_xui_names(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedCheckXUINames : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = check_show_xui_names(NULL);
-		return new_value;
-	}
-};
-
-
-////////////////////////
-// GRAB BAKED TEXTURE //
-////////////////////////
-
-
-class LLAdvancedGrabBakedTexture : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string texture_type = userdata.asString();
-		if ("iris" == texture_type)
-		{
-			handle_grab_baked_texture( (void*)BAKED_EYES );
-		}
-		else if ("head" == texture_type)
-		{
-			handle_grab_baked_texture( (void*)BAKED_HEAD );
-		}
-		else if ("upper" == texture_type)
-		{
-			handle_grab_baked_texture( (void*)BAKED_UPPER );
-		}
-		else if ("lower" == texture_type)
-		{
-			handle_grab_baked_texture( (void*)BAKED_LOWER );
-		}
-		else if ("skirt" == texture_type)
-		{
-			handle_grab_baked_texture( (void*)BAKED_SKIRT );
-		}
-		else if ("hair" == texture_type)
-		{
-			handle_grab_baked_texture( (void*)BAKED_HAIR );
-		}
-
-		return true;
-	}
-};
-
-class LLAdvancedEnableGrabBakedTexture : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-{
-		std::string texture_type = userdata.asString();
-		bool new_value = false;
-
-		if ("iris" == texture_type)
-		{
-			new_value = enable_grab_baked_texture( (void*)BAKED_EYES );
-		}
-		else if ("head" == texture_type)
-		{
-			new_value = enable_grab_baked_texture( (void*)BAKED_HEAD );
-		}
-		else if ("upper" == texture_type)
-		{
-			new_value = enable_grab_baked_texture( (void*)BAKED_UPPER );
-		}
-		else if ("lower" == texture_type)
-		{
-			new_value = enable_grab_baked_texture( (void*)BAKED_LOWER );
-		}
-		else if ("skirt" == texture_type)
-		{
-			new_value = enable_grab_baked_texture( (void*)BAKED_SKIRT );
-		}
-		else if ("hair" == texture_type)
-		{
-			new_value = enable_grab_baked_texture( (void*)BAKED_HAIR );
-		}
-	
-		return new_value;
-}
-};
-
-///////////////////////
-// APPEARANCE TO XML //
-///////////////////////
-
-
-class LLAdvancedAppearanceToXML : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar::dumpArchetypeXML(NULL);
-		return true;
-	}
-};
-
-
-
-///////////////////////////////
-// TOGGLE CHARACTER GEOMETRY //
-///////////////////////////////
-
-
-class LLAdvancedToggleCharacterGeometry : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_god_request_avatar_geometry(NULL);
-		return true;
-}
-};
-
-
-	/////////////////////////////
-// TEST MALE / TEST FEMALE //
-/////////////////////////////
-
-class LLAdvancedTestMale : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_test_male(NULL);
-		return true;
-	}
-};
-
-
-class LLAdvancedTestFemale : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_test_female(NULL);
-		return true;
-	}
-};
-
-
-
-///////////////
-// TOGGLE PG //
-///////////////
-
-
-class LLAdvancedTogglePG : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_toggle_pg(NULL);
-		return true;
-	}
-};
-
-
-class LLAdvancedForceParamsToDefault : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLAgent::clearVisualParams(NULL);
-		return true;
-	}
-};
-
-
-
-//////////////////////////
-// RELOAD VERTEX SHADER //
-//////////////////////////
-
-
-class LLAdvancedReloadVertexShader : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		reload_vertex_shader(NULL);
-		return true;
-	}
-};
-
-
-
-////////////////////
-// ANIMATION INFO //
-////////////////////
-
-
-class LLAdvancedToggleAnimationInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar::sShowAnimationDebug = !(LLVOAvatar::sShowAnimationDebug);
-		return true;
-	}
-};
-
-class LLAdvancedCheckAnimationInfo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLVOAvatar::sShowAnimationDebug;
-		return new_value;
-	}
-};
-
-
-//////////////////
-// SHOW LOOK AT //
-//////////////////
-
-
-class LLAdvancedToggleShowLookAt : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLHUDEffectLookAt::sDebugLookAt = !(LLHUDEffectLookAt::sDebugLookAt);
-		return true;
-	}
-};
-
-class LLAdvancedCheckShowLookAt : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLHUDEffectLookAt::sDebugLookAt;
-		return new_value;
-	}
-};
-
-
-
-///////////////////
-// SHOW POINT AT //
-///////////////////
-
-
-class LLAdvancedToggleShowPointAt : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLHUDEffectPointAt::sDebugPointAt = !(LLHUDEffectPointAt::sDebugPointAt);
-		return true;
-	}
-};
-
-class LLAdvancedCheckShowPointAt : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLHUDEffectPointAt::sDebugPointAt;
-		return new_value;
-	}
-};
-
-
-
-/////////////////////////
-// DEBUG JOINT UPDATES //
-/////////////////////////
-
-
-class LLAdvancedToggleDebugJointUpdates : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar::sJointDebug = !(LLVOAvatar::sJointDebug);
-		return true;
-	}
-};
-
-class LLAdvancedCheckDebugJointUpdates : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLVOAvatar::sJointDebug;
-		return new_value;
-	}
-};
-
-
-
-/////////////////
-// DISABLE LOD //
-/////////////////
-
-
-class LLAdvancedToggleDisableLOD : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLViewerJoint::sDisableLOD = !(LLViewerJoint::sDisableLOD);
-		return true;
-	}
-};
-		
-class LLAdvancedCheckDisableLOD : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLViewerJoint::sDisableLOD;
-		return new_value;
-	}
-};
-
-
-
-/////////////////////////
-// DEBUG CHARACTER VIS //
-/////////////////////////
-
-
-class LLAdvancedToggleDebugCharacterVis : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar::sDebugInvisible = !(LLVOAvatar::sDebugInvisible);
-		return true;
-	}
-};
-
-class LLAdvancedCheckDebugCharacterVis : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLVOAvatar::sDebugInvisible;
-		return new_value;
-	}
-};
-
-
-//////////////////////
-// DUMP ATTACHMENTS //
-//////////////////////
-
-	
-class LLAdvancedDumpAttachments : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_dump_attachments(NULL);
-		return true;
-	}
-};
-
-
-	
-/////////////////////
-// REBAKE TEXTURES //
-/////////////////////
-	
-	
-class LLAdvancedRebakeTextures : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_rebake_textures(NULL);
-		return true;
-	}
-};
-	
-	
-#if 1 //ndef LL_RELEASE_FOR_DOWNLOAD
-///////////////////////////
-// DEBUG AVATAR TEXTURES //
-///////////////////////////
-
-
-class LLAdvancedDebugAvatarTextures : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if (gAgent.isGodlike())
-		{
-			handle_debug_avatar_textures(NULL);
-		}
-		return true;
-	}
-};
-
-////////////////////////////////
-// DUMP AVATAR LOCAL TEXTURES //
-////////////////////////////////
-
-
-class LLAdvancedDumpAvatarLocalTextures : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-		handle_dump_avatar_local_textures(NULL);
-#endif
-		return true;
-	}
-};
-
-#endif
-	
-/////////////////
-// MESSAGE LOG //
-/////////////////
-
-
-class LLAdvancedEnableMessageLog : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_viewer_enable_message_log(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedDisableMessageLog : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_viewer_disable_message_log(NULL);
-		return true;
-	}
-};
-
-/////////////////
-// DROP PACKET //
-/////////////////
-
-
-class LLAdvancedDropPacket : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gMessageSystem->mPacketRing.dropPackets(1);
-		return true;
-	}
-};
-
-
-
-/////////////////
-// AGENT PILOT //
-/////////////////
-
-
-class LLAdvancedAgentPilot : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string command = userdata.asString();
-		if ("start playback" == command)
-		{
-			LLAgentPilot::startPlayback(NULL);
-		}
-		else if ("stop playback" == command)
-		{
-			LLAgentPilot::stopPlayback(NULL);
-		}
-		else if ("start record" == command)
-		{
-			LLAgentPilot::startRecord(NULL);
-		}
-		else if ("stop record" == command)
-		{
-			LLAgentPilot::saveRecord(NULL);
-		}
-
-		return true;
-	}		
-};
-
-
-
-//////////////////////
-// AGENT PILOT LOOP //
-//////////////////////
-
-
-class LLAdvancedToggleAgentPilotLoop : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLAgentPilot::sLoop = !(LLAgentPilot::sLoop);
-		return true;
-	}
-};
-
-class LLAdvancedCheckAgentPilotLoop : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLAgentPilot::sLoop;
-		return new_value;
-	}
-};
-
-
-/////////////////////////
-// SHOW OBJECT UPDATES //
-/////////////////////////
-
-
-class LLAdvancedToggleShowObjectUpdates : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gShowObjectUpdates = !(gShowObjectUpdates);
-		return true;
-	}
-};
-
-class LLAdvancedCheckShowObjectUpdates : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gShowObjectUpdates;
-		return new_value;
-	}
-};
-
-
-
-////////////////////
-// COMPRESS IMAGE //
-////////////////////
-
-
-class LLAdvancedCompressImage : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_compress_image(NULL);
-		return true;
-	}
-};
-
-
-
-/////////////////////////
-// SHOW DEBUG SETTINGS //
-/////////////////////////
-
-
-class LLAdvancedShowDebugSettings : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLFloaterReg::showInstance("settings_debug",userdata);
-		return true;
-	}
-};
-
-
-
-////////////////////////
-// VIEW ADMIN OPTIONS //
-////////////////////////
-
-class LLAdvancedEnableViewAdminOptions : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// Don't enable in god mode since the admin menu is shown anyway.
-		// Only enable if the user has set the appropriate debug setting.
-		bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu");
-		return new_value;
-	}
-};
-
-class LLAdvancedToggleViewAdminOptions : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_admin_override_toggle(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedCheckViewAdminOptions : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = check_admin_override(NULL) || gAgent.isGodlike();
-		return new_value;
-	}
-};
-
-/////////////////////////////////////
-// Enable Object Object Occlusion ///
-/////////////////////////////////////
-class LLAdvancedEnableObjectObjectOcclusion: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-	
-		bool new_value = gGLManager.mHasOcclusionQuery; // && LLFeatureManager::getInstance()->isFeatureAvailable(userdata.asString());
-		return new_value;
-}
-};
-
-/////////////////////////////////////
-// Enable Framebuffer Objects	  ///
-/////////////////////////////////////
-class LLAdvancedEnableRenderFBO: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gGLManager.mHasFramebufferObject;
-		return new_value;
-	}
-};
-
-/////////////////////////////////////
-// Enable Deferred Rendering	  ///
-/////////////////////////////////////
-class LLAdvancedEnableRenderDeferred: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gSavedSettings.getBOOL("RenderUseFBO") && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT > 0) &&
-			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
-		return new_value;
-	}
-};
-
-/////////////////////////////////////
-// Enable Deferred Rendering sub-options
-/////////////////////////////////////
-class LLAdvancedEnableRenderDeferredOptions: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gSavedSettings.getBOOL("RenderUseFBO") && gSavedSettings.getBOOL("RenderDeferred");
-		return new_value;
-	}
-};
-
-
-
-//////////////////
-// ADMIN STATUS //
-//////////////////
-
-
-class LLAdvancedRequestAdminStatus : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_god_mode(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedLeaveAdminStatus : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_leave_god_mode(NULL);
-		return true;
-	}
-};
-
-//////////////////////////
-// Advanced > Debugging //
-//////////////////////////
-
-
-class LLAdvancedForceErrorBreakpoint : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		force_error_breakpoint(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedForceErrorLlerror : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		force_error_llerror(NULL);
-		return true;
-	}
-};
-class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		force_error_bad_memory_access(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedForceErrorInfiniteLoop : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		force_error_infinite_loop(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedForceErrorSoftwareException : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		force_error_software_exception(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedForceErrorDriverCrash : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		force_error_driver_crash(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedForceErrorDisconnectViewer : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_disconnect_viewer(NULL);
-		return true;
-}
-};
-
-
-#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-
-class LLAdvancedHandleToggleHackedGodmode : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_toggle_hacked_godmode(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedCheckToggleHackedGodmode : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		check_toggle_hacked_godmode(NULL);
-		return true;
-	}
-};
-
-class LLAdvancedEnableToggleHackedGodmode : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = enable_toggle_hacked_godmode(NULL);
-		return new_value;
-	}
-};
-#endif
-
-
-//
-////-------------------------------------------------------------------
-//// Advanced menu
-////-------------------------------------------------------------------
-
-//////////////////
-// ADMIN MENU   //
-//////////////////
-
-// Admin > Object
-class LLAdminForceTakeCopy : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		force_take_copy(NULL);
-		return true;
-	}
-};
-
-class LLAdminHandleObjectOwnerSelf : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_object_owner_self(NULL);
-		return true;
-	}
-};
-class LLAdminHandleObjectOwnerPermissive : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_object_owner_permissive(NULL);
-		return true;
-	}
-};
-
-class LLAdminHandleForceDelete : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_force_delete(NULL);
-		return true;
-	}
-};
-
-class LLAdminHandleObjectLock : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_object_lock(NULL);
-		return true;
-	}
-};
-
-class LLAdminHandleObjectAssetIDs: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_object_asset_ids(NULL);
-		return true;
-	}	
-};
-
-//Admin >Parcel
-class LLAdminHandleForceParcelOwnerToMe: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_force_parcel_owner_to_me(NULL);
-		return true;
-	}
-};
-class LLAdminHandleForceParcelToContent: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_force_parcel_to_content(NULL);
-		return true;
-	}
-};
-class LLAdminHandleClaimPublicLand: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_claim_public_land(NULL);
-		return true;
-	}
-};
-
-// Admin > Region
-class LLAdminHandleRegionDumpTempAssetData: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_region_dump_temp_asset_data(NULL);
-		return true;
-	}
-};
-//Admin (Top Level)
-
-class LLAdminOnSaveState: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLPanelRegionTools::onSaveState(NULL);
-		return true;
-}
-};
-
-
-//-----------------------------------------------------------------------------
-// cleanup_menus()
-//-----------------------------------------------------------------------------
-void cleanup_menus()
-{
-	delete gMenuParcelObserver;
-	gMenuParcelObserver = NULL;
-
-	delete gMenuAvatarSelf;
-	gMenuAvatarSelf = NULL;
-
-	delete gMenuAvatarOther;
-	gMenuAvatarOther = NULL;
-
-	delete gMenuObject;
-	gMenuObject = NULL;
-
-	delete gMenuAttachmentSelf;
-	gMenuAttachmentSelf = NULL;
-
-	delete gMenuAttachmentOther;
-	gMenuAttachmentSelf = NULL;
-
-	delete gMenuLand;
-	gMenuLand = NULL;
-
-	delete gMenuBarView;
-	gMenuBarView = NULL;
-
-	delete gPopupMenuView;
-	gPopupMenuView = NULL;
-
-	delete gMenuHolder;
-	gMenuHolder = NULL;
-}
-
-//-----------------------------------------------------------------------------
-// Object pie menu
-//-----------------------------------------------------------------------------
-
-class LLObjectReportAbuse : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-		if (objectp)
-		{
-			LLFloaterReporter::showFromObject(objectp->getID());
-		}
-		return true;
-	}
-};
-
-// Enabled it you clicked an object
-class LLObjectEnableReportAbuse : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0;
-		return new_value;
-	}
-};
-
-void handle_object_touch()
-{
-		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-		if (!object) return;
-
-		LLPickInfo pick = LLToolPie::getInstance()->getPick();
-
-		LLMessageSystem	*msg = gMessageSystem;
-
-		msg->newMessageFast(_PREHASH_ObjectGrab);
-		msg->nextBlockFast( _PREHASH_AgentData);
-		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-		msg->nextBlockFast( _PREHASH_ObjectData);
-		msg->addU32Fast(    _PREHASH_LocalID, object->mLocalID);
-		msg->addVector3Fast(_PREHASH_GrabOffset, LLVector3::zero );
-		msg->nextBlock("SurfaceInfo");
-		msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
-		msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
-		msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
-		msg->addVector3("Position", pick.mIntersection);
-		msg->addVector3("Normal", pick.mNormal);
-		msg->addVector3("Binormal", pick.mBinormal);
-		msg->sendMessage( object->getRegion()->getHost());
-
-		// *NOTE: Hope the packets arrive safely and in order or else
-		// there will be some problems.
-		// *TODO: Just fix this bad assumption.
-		msg->newMessageFast(_PREHASH_ObjectDeGrab);
-		msg->nextBlockFast(_PREHASH_AgentData);
-		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-		msg->nextBlockFast(_PREHASH_ObjectData);
-		msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
-		msg->nextBlock("SurfaceInfo");
-		msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
-		msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
-		msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
-		msg->addVector3("Position", pick.mIntersection);
-		msg->addVector3("Normal", pick.mNormal);
-		msg->addVector3("Binormal", pick.mBinormal);
-		msg->sendMessage(object->getRegion()->getHost());
-}
-
-static void init_default_item_label(const std::string& item_name)
-{
-	boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
-	if (it == sDefaultItemLabels.end())
-	{
-		// *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value
-		//       (doesn't seem to matter much ATM).
-		LLStringExplicit default_label = gMenuHolder->childGetValue(item_name).asString();
-		if (!default_label.empty())
-		{
-			sDefaultItemLabels.insert(std::pair<std::string, LLStringExplicit>(item_name, default_label));
-		}
-	}
-}
-
-static LLStringExplicit get_default_item_label(const std::string& item_name)
-{
-	LLStringExplicit res("");
-	boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
-	if (it != sDefaultItemLabels.end())
-	{
-		res = it->second;
-	}
-
-	return res;
-}
-
-
-bool enable_object_touch(LLUICtrl* ctrl)
-{
-	LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-
-	bool new_value = obj && obj->flagHandleTouch();
-
-	std::string item_name = ctrl->getName();
-	init_default_item_label(item_name);
-
-	// Update label based on the node touch name if available.
-	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-	if (node && node->mValid && !node->mTouchName.empty())
-	{
-		gMenuHolder->childSetText(item_name, node->mTouchName);
-	}
-	else
-	{
-		gMenuHolder->childSetText(item_name, get_default_item_label(item_name));
-	}
-
-	return new_value;
-};
-
-//void label_touch(std::string& label, void*)
-//{
-//	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-//	if (node && node->mValid && !node->mTouchName.empty())
-//	{
-//		label.assign(node->mTouchName);
-//	}
-//	else
-//	{
-//		label.assign("Touch");
-//	}
-//}
-
-void handle_object_open()
-{
-	LLFloaterReg::showInstance("openobject");
-}
-
-bool enable_object_open()
-{
-	// Look for contents in root object, which is all the LLFloaterOpenObject
-	// understands.
-	LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-	if (!obj) return false;
-
-	LLViewerObject* root = obj->getRootEdit();
-	if (!root) return false;
-
-	return root->allowOpen();
-}
-
-
-class LLViewJoystickFlycam : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_toggle_flycam();
-		return true;
-	}
-};
-
-class LLViewCheckJoystickFlycam : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera();
-		return new_value;
-	}
-};
-
-void handle_toggle_flycam()
-{
-	LLViewerJoystick::getInstance()->toggleFlycam();
-}
-
-class LLObjectBuild : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
-		{
-			// zoom in if we're looking at the avatar
-			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
-			gAgentCamera.cameraZoomIn(0.666f);
-			gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
-			gViewerWindow->moveCursorToCenter();
-		}
-		else if ( gSavedSettings.getBOOL("EditCameraMovement") )
-		{
-			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
-			gViewerWindow->moveCursorToCenter();
-		}
-
-		LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
-		LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
-
-		// Could be first use
-		//LLFirstUse::useBuild();
-		return true;
-	}
-};
-
-
-void handle_object_edit()
-{
-	LLViewerParcelMgr::getInstance()->deselectLand();
-
-	if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
-	{
-		LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->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
-			gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
-			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-		}
-		else
-		{
-			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-			LLViewerObject* selected_objectp = selection->getFirstRootObject();
-			if (selected_objectp)
-			{
-			  // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
-			  gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
-			  gAgentCamera.cameraZoomIn(0.666f);
-			  gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
-			  gViewerWindow->moveCursorToCenter();
-			}
-		}
-	}
-	
-	LLFloaterReg::showInstance("build");
-	
-	LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
-	gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() );
-	
-	LLViewerJoystick::getInstance()->moveObjects(true);
-	LLViewerJoystick::getInstance()->setNeedsReset(true);
-	
-	// Could be first use
-	//LLFirstUse::useBuild();
-	return;
-}
-
-void handle_object_inspect()
-{
-	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-	LLViewerObject* selected_objectp = selection->getFirstRootObject();
-	if (selected_objectp)
-	{
-		LLSD key;
-		key["task"] = "task";
-		LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
-	}
-	
-	/*
-	// Old floater properties
-	LLFloaterReg::showInstance("inspect", LLSD());
-	*/
-}
-
-//---------------------------------------------------------------------------
-// Land pie menu
-//---------------------------------------------------------------------------
-class LLLandBuild : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLViewerParcelMgr::getInstance()->deselectLand();
-
-		if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
-		{
-			// zoom in if we're looking at the avatar
-			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
-			gAgentCamera.cameraZoomIn(0.666f);
-			gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
-			gViewerWindow->moveCursorToCenter();
-		}
-		else if ( gSavedSettings.getBOOL("EditCameraMovement")  )
-		{
-			// otherwise just move focus
-			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
-			gViewerWindow->moveCursorToCenter();
-		}
-
-
-		LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
-		LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
-
-		// Could be first use
-		//LLFirstUse::useBuild();
-		return true;
-	}
-};
-
-class LLLandBuyPass : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLPanelLandGeneral::onClickBuyPass((void *)FALSE);
-		return true;
-	}
-};
-
-class LLLandEnableBuyPass : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLPanelLandGeneral::enableBuyPass(NULL);
-		return new_value;
-	}
-};
-
-// BUG: Should really check if CLICK POINT is in a parcel where you can build.
-BOOL enable_land_build(void*)
-{
-	if (gAgent.isGodlike()) return TRUE;
-	if (gAgent.inPrelude()) return FALSE;
-
-	BOOL can_build = FALSE;
-	LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-	if (agent_parcel)
-	{
-		can_build = agent_parcel->getAllowModify();
-	}
-	return can_build;
-}
-
-// BUG: Should really check if OBJECT is in a parcel where you can build.
-BOOL enable_object_build(void*)
-{
-	if (gAgent.isGodlike()) return TRUE;
-	if (gAgent.inPrelude()) return FALSE;
-
-	BOOL can_build = FALSE;
-	LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-	if (agent_parcel)
-	{
-		can_build = agent_parcel->getAllowModify();
-	}
-	return can_build;
-}
-
-bool enable_object_edit()
-{
-	// *HACK:  The new "prelude" Help Islands have a build sandbox area,
-	// so users need the Edit and Create pie menu options when they are
-	// there.  Eventually this needs to be replaced with code that only 
-	// lets you edit objects if you have permission to do so (edit perms,
-	// group edit, god).  See also lltoolbar.cpp.  JC
-	bool enable = false;
-	if (gAgent.inPrelude())
-	{
-		enable = LLViewerParcelMgr::getInstance()->allowAgentBuild()
-			|| LLSelectMgr::getInstance()->getSelection()->isAttachment();
-	} 
-	else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound())
-	{
-		enable = true;
-	}
-
-	return enable;
-}
-
-// mutually exclusive - show either edit option or build in menu
-bool enable_object_build()
-{
-	return !enable_object_edit();
-}
-
-class LLSelfRemoveAllAttachments : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLAgentWearables::userRemoveAllAttachments();
-		return true;
-	}
-};
-
-class LLSelfEnableRemoveAllAttachments : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = false;
-		if (isAgentAvatarValid())
-		{
-			for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); 
-				 iter != gAgentAvatarp->mAttachmentPoints.end(); )
-			{
-				LLVOAvatar::attachment_map_t::iterator curiter = iter++;
-				LLViewerJointAttachment* attachment = curiter->second;
-				if (attachment->getNumObjects() > 0)
-				{
-					new_value = true;
-					break;
-				}
-			}
-		}
-		return new_value;
-	}
-};
-
-BOOL enable_has_attachments(void*)
-{
-
-	return FALSE;
-}
-
-//---------------------------------------------------------------------------
-// Avatar pie menu
-//---------------------------------------------------------------------------
-//void handle_follow(void *userdata)
-//{
-//	// follow a given avatar by ID
-//	LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-//	if (objectp)
-//	{
-//		gAgent.startFollowPilot(objectp->getID());
-//	}
-//}
-
-bool enable_object_mute()
-{
-	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-	if (!object) return false;
-
-	LLVOAvatar* avatar = find_avatar_from_object(object); 
-	if (avatar)
-	{
-		// It's an avatar
-		LLNameValue *lastname = avatar->getNVPair("LastName");
-		bool is_linden =
-			lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
-		bool is_self = avatar->isSelf();
-		return !is_linden && !is_self;
-	}
-	else
-	{
-		// Just a regular object
-		return LLSelectMgr::getInstance()->getSelection()->
-			contains( object, SELECT_ALL_TES );
-	}
-}
-
-class LLObjectMute : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-		if (!object) return true;
-		
-		LLUUID id;
-		std::string name;
-		LLMute::EType type;
-		LLVOAvatar* avatar = find_avatar_from_object(object); 
-		if (avatar)
-		{
-			id = avatar->getID();
-
-			LLNameValue *firstname = avatar->getNVPair("FirstName");
-			LLNameValue *lastname = avatar->getNVPair("LastName");
-			if (firstname && lastname)
-			{
-				name = LLCacheName::buildFullName(
-					firstname->getString(), lastname->getString());
-			}
-			
-			type = LLMute::AGENT;
-		}
-		else
-		{
-			// it's an object
-			id = object->getID();
-
-			LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-			if (node)
-			{
-				name = node->mName;
-			}
-			
-			type = LLMute::OBJECT;
-		}
-		
-		LLMute mute(id, name, type);
-		if (LLMuteList::getInstance()->isMuted(mute.mID))
-		{
-			LLMuteList::getInstance()->remove(mute);
-		}
-		else
-		{
-			LLMuteList::getInstance()->add(mute);
-			LLPanelBlockedList::showPanelAndSelect(mute.mID);
-		}
-		
-		return true;
-	}
-};
-
-bool handle_go_to()
-{
-	// try simulator autopilot
-	std::vector<std::string> strings;
-	std::string val;
-	LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
-	val = llformat("%g", pos.mdV[VX]);
-	strings.push_back(val);
-	val = llformat("%g", pos.mdV[VY]);
-	strings.push_back(val);
-	val = llformat("%g", pos.mdV[VZ]);
-	strings.push_back(val);
-	send_generic_message("autopilot", strings);
-
-	LLViewerParcelMgr::getInstance()->deselectLand();
-
-	if (isAgentAvatarValid() && !gSavedSettings.getBOOL("AutoPilotLocksCamera"))
-	{
-		gAgentCamera.setFocusGlobal(gAgentCamera.getFocusTargetGlobal(), gAgentAvatarp->getID());
-	}
-	else 
-	{
-		// Snap camera back to behind avatar
-		gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
-	}
-
-	// Could be first use
-	//LLFirstUse::useGoTo();
-	return true;
-}
-
-class LLGoToObject : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		return handle_go_to();
-	}
-};
-
-class LLAvatarReportAbuse : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
-		if(avatar)
-		{
-			LLFloaterReporter::showFromObject(avatar->getID());
-		}
-		return true;
-	}
-};
-
-
-//---------------------------------------------------------------------------
-// Parcel freeze, eject, etc.
-//---------------------------------------------------------------------------
-bool callback_freeze(const LLSD& notification, const LLSD& response)
-{
-	LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
-	if (0 == option || 1 == option)
-	{
-		U32 flags = 0x0;
-		if (1 == option)
-		{
-			// unfreeze
-			flags |= 0x1;
-		}
-
-		LLMessageSystem* msg = gMessageSystem;
-		LLViewerObject* avatar = gObjectList.findObject(avatar_id);
-
-		if (avatar)
-		{
-			msg->newMessage("FreezeUser");
-			msg->nextBlock("AgentData");
-			msg->addUUID("AgentID", gAgent.getID());
-			msg->addUUID("SessionID", gAgent.getSessionID());
-			msg->nextBlock("Data");
-			msg->addUUID("TargetID", avatar_id );
-			msg->addU32("Flags", flags );
-			msg->sendReliable( avatar->getRegion()->getHost() );
-		}
-	}
-	return false;
-}
-
-
-void handle_avatar_freeze(const LLSD& avatar_id)
-{
-		// Use avatar_id if available, otherwise default to right-click avatar
-		LLVOAvatar* avatar = NULL;
-		if (avatar_id.asUUID().notNull())
-		{
-			avatar = find_avatar_from_object(avatar_id.asUUID());
-		}
-		else
-		{
-			avatar = find_avatar_from_object(
-				LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
-		}
-
-		if( avatar )
-		{
-			std::string fullname = avatar->getFullname();
-			LLSD payload;
-			payload["avatar_id"] = avatar->getID();
-
-			if (!fullname.empty())
-			{
-				LLSD args;
-				args["AVATAR_NAME"] = fullname;
-				LLNotificationsUtil::add("FreezeAvatarFullname",
-							args,
-							payload,
-							callback_freeze);
-			}
-			else
-			{
-				LLNotificationsUtil::add("FreezeAvatar",
-							LLSD(),
-							payload,
-							callback_freeze);
-			}
-		}
-}
-
-class LLAvatarVisibleDebug : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		return gAgent.isGodlike();
-	}
-};
-
-class LLAvatarDebug : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
-		if( avatar )
-		{
-			if (avatar->isSelf())
-			{
-				((LLVOAvatarSelf *)avatar)->dumpLocalTextures();
-			}
-			llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl;
-			std::vector<std::string> strings;
-			strings.push_back(avatar->getID().asString());
-			LLUUID invoice;
-			send_generic_message("dumptempassetdata", strings, invoice);
-			LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) );
-		}
-		return true;
-	}
-};
-
-bool callback_eject(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (2 == option)
-	{
-		// Cancel button.
-		return false;
-	}
-	LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
-	bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean();
-
-	if (0 == option)
-	{
-		// Eject button
-		LLMessageSystem* msg = gMessageSystem;
-		LLViewerObject* avatar = gObjectList.findObject(avatar_id);
-
-		if (avatar)
-		{
-			U32 flags = 0x0;
-			msg->newMessage("EjectUser");
-			msg->nextBlock("AgentData");
-			msg->addUUID("AgentID", gAgent.getID() );
-			msg->addUUID("SessionID", gAgent.getSessionID() );
-			msg->nextBlock("Data");
-			msg->addUUID("TargetID", avatar_id );
-			msg->addU32("Flags", flags );
-			msg->sendReliable( avatar->getRegion()->getHost() );
-		}
-	}
-	else if (ban_enabled)
-	{
-		// This is tricky. It is similar to say if it is not an 'Eject' button,
-		// and it is also not an 'Cancle' button, and ban_enabled==ture, 
-		// it should be the 'Eject and Ban' button.
-		LLMessageSystem* msg = gMessageSystem;
-		LLViewerObject* avatar = gObjectList.findObject(avatar_id);
-
-		if (avatar)
-		{
-			U32 flags = 0x1;
-			msg->newMessage("EjectUser");
-			msg->nextBlock("AgentData");
-			msg->addUUID("AgentID", gAgent.getID() );
-			msg->addUUID("SessionID", gAgent.getSessionID() );
-			msg->nextBlock("Data");
-			msg->addUUID("TargetID", avatar_id );
-			msg->addU32("Flags", flags );
-			msg->sendReliable( avatar->getRegion()->getHost() );
-		}
-	}
-	return false;
-}
-
-void handle_avatar_eject(const LLSD& avatar_id)
-{
-		// Use avatar_id if available, otherwise default to right-click avatar
-		LLVOAvatar* avatar = NULL;
-		if (avatar_id.asUUID().notNull())
-		{
-			avatar = find_avatar_from_object(avatar_id.asUUID());
-		}
-		else
-		{
-			avatar = find_avatar_from_object(
-				LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
-		}
-
-		if( avatar )
-		{
-			LLSD payload;
-			payload["avatar_id"] = avatar->getID();
-			std::string fullname = avatar->getFullname();
-
-			const LLVector3d& pos = avatar->getPositionGlobal();
-			LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel();
-			
-			if (LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED))
-			{
-                payload["ban_enabled"] = true;
-				if (!fullname.empty())
-				{
-    				LLSD args;
-    				args["AVATAR_NAME"] = fullname;
-    				LLNotificationsUtil::add("EjectAvatarFullname",
-    							args,
-    							payload,
-    							callback_eject);
-				}
-				else
-				{
-    				LLNotificationsUtil::add("EjectAvatarFullname",
-    							LLSD(),
-    							payload,
-    							callback_eject);
-				}
-			}
-			else
-			{
-                payload["ban_enabled"] = false;
-				if (!fullname.empty())
-				{
-    				LLSD args;
-    				args["AVATAR_NAME"] = fullname;
-    				LLNotificationsUtil::add("EjectAvatarFullnameNoBan",
-    							args,
-    							payload,
-    							callback_eject);
-				}
-				else
-				{
-    				LLNotificationsUtil::add("EjectAvatarNoBan",
-    							LLSD(),
-    							payload,
-    							callback_eject);
-				}
-			}
-		}
-}
-
-bool enable_freeze_eject(const LLSD& avatar_id)
-{
-	// Use avatar_id if available, otherwise default to right-click avatar
-	LLVOAvatar* avatar = NULL;
-	if (avatar_id.asUUID().notNull())
-	{
-		avatar = find_avatar_from_object(avatar_id.asUUID());
-	}
-	else
-	{
-		avatar = find_avatar_from_object(
-			LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
-	}
-	if (!avatar) return false;
-
-	// Gods can always freeze
-	if (gAgent.isGodlike()) return true;
-
-	// Estate owners / managers can freeze
-	// Parcel owners can also freeze
-	const LLVector3& pos = avatar->getPositionRegion();
-	const LLVector3d& pos_global = avatar->getPositionGlobal();
-	LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel();
-	LLViewerRegion* region = avatar->getRegion();
-	if (!region) return false;
-				
-	bool new_value = region->isOwnedSelf(pos);
-	if (!new_value || region->isOwnedGroup(pos))
-	{
-		new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN);
-	}
-	return new_value;
-}
-
-
-void login_done(S32 which, void *user)
-{
-	llinfos << "Login done " << which << llendl;
-
-	LLPanelLogin::closePanel();
-}
-
-
-bool callback_leave_group(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (option == 0)
-	{
-		LLMessageSystem *msg = gMessageSystem;
-
-		msg->newMessageFast(_PREHASH_LeaveGroupRequest);
-		msg->nextBlockFast(_PREHASH_AgentData);
-		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
-		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-		msg->nextBlockFast(_PREHASH_GroupData);
-		msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() );
-		gAgent.sendReliableMessage();
-	}
-	return false;
-}
-
-void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm, PermissionBit bit, const char* txt)
-{
-	LLAggregatePermissions::EValue val = ag_perm.getValue(bit);
-	std::string buffer;
-	switch(val)
-	{
-	  case LLAggregatePermissions::AP_NONE:
-		buffer = llformat( "* %s None\n", txt);
-		break;
-	  case LLAggregatePermissions::AP_SOME:
-		buffer = llformat( "* %s Some\n", txt);
-		break;
-	  case LLAggregatePermissions::AP_ALL:
-		buffer = llformat( "* %s All\n", txt);
-		break;
-	  case LLAggregatePermissions::AP_EMPTY:
-	  default:
-		break;
-	}
-	string.append(buffer);
-}
-
-bool enable_buy_object()
-{
-    // In order to buy, there must only be 1 purchaseable object in
-    // the selection manger.
-	if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false;
-    LLViewerObject* obj = NULL;
-    LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-	if(node)
-    {
-        obj = node->getObject();
-        if(!obj) return false;
-
-		if( for_sale_selection(node) )
-		{
-			// *NOTE: Is this needed?  This checks to see if anyone owns the
-			// object, dating back to when we had "public" objects owned by
-			// no one.  JC
-			if(obj->permAnyOwner()) return true;
-		}
-    }
-	return false;
-}
-
-// Note: This will only work if the selected object's data has been
-// received by the viewer and cached in the selection manager.
-void handle_buy_object(LLSaleInfo sale_info)
-{
-	if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
-	{
-		LLNotificationsUtil::add("UnableToBuyWhileDownloading");
-		return;
-	}
-
-	LLUUID owner_id;
-	std::string owner_name;
-	BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
-	if (!owners_identical)
-	{
-		LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners");
-		return;
-	}
-
-	LLPermissions perm;
-	BOOL valid = LLSelectMgr::getInstance()->selectGetPermissions(perm);
-	LLAggregatePermissions ag_perm;
-	valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm);
-	if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID()))
-	{
-		LLNotificationsUtil::add("ObjectNotForSale");
-		return;
-	}
-
-	LLFloaterBuy::show(sale_info);
-}
-
-
-void handle_buy_contents(LLSaleInfo sale_info)
-{
-	LLFloaterBuyContents::show(sale_info);
-}
-
-void handle_region_dump_temp_asset_data(void*)
-{
-	llinfos << "Dumping temporary asset data to simulator logs" << llendl;
-	std::vector<std::string> strings;
-	LLUUID invoice;
-	send_generic_message("dumptempassetdata", strings, invoice);
-}
-
-void handle_region_clear_temp_asset_data(void*)
-{
-	llinfos << "Clearing temporary asset data" << llendl;
-	std::vector<std::string> strings;
-	LLUUID invoice;
-	send_generic_message("cleartempassetdata", strings, invoice);
-}
-
-void handle_region_dump_settings(void*)
-{
-	LLViewerRegion* regionp = gAgent.getRegion();
-	if (regionp)
-	{
-		llinfos << "Damage:    " << (regionp->getAllowDamage() ? "on" : "off") << llendl;
-		llinfos << "Landmark:  " << (regionp->getAllowLandmark() ? "on" : "off") << llendl;
-		llinfos << "SetHome:   " << (regionp->getAllowSetHome() ? "on" : "off") << llendl;
-		llinfos << "ResetHome: " << (regionp->getResetHomeOnTeleport() ? "on" : "off") << llendl;
-		llinfos << "SunFixed:  " << (regionp->getSunFixed() ? "on" : "off") << llendl;
-		llinfos << "BlockFly:  " << (regionp->getBlockFly() ? "on" : "off") << llendl;
-		llinfos << "AllowP2P:  " << (regionp->getAllowDirectTeleport() ? "on" : "off") << llendl;
-		llinfos << "Water:     " << (regionp->getWaterHeight()) << llendl;
-	}
-}
-
-void handle_dump_group_info(void *)
-{
-	gAgent.dumpGroupInfo();
-}
-
-void handle_dump_capabilities_info(void *)
-{
-	LLViewerRegion* regionp = gAgent.getRegion();
-	if (regionp)
-	{
-		regionp->logActiveCapabilities();
-	}
-}
-
-void handle_dump_region_object_cache(void*)
-{
-	LLViewerRegion* regionp = gAgent.getRegion();
-	if (regionp)
-	{
-		regionp->dumpCache();
-	}
-}
-
-void handle_dump_focus()
-{
-	LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
-
-	llinfos << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << llendl;
-}
-
-class LLSelfStandUp : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gAgent.standUp();
-		return true;
-	}
-};
-
-bool enable_standup_self()
-{
-    return isAgentAvatarValid() && gAgentAvatarp->isSitting();
-}
-
-class LLSelfSitDown : public view_listener_t
-    {
-        bool handleEvent(const LLSD& userdata)
-        {
-            gAgent.sitDown();
-            return true;
-        }
-    };
-
-bool enable_sitdown_self()
-{
-    return isAgentAvatarValid() && !gAgentAvatarp->isSitting() && !gAgent.getFlying();
-}
-
-// Used from the login screen to aid in UI work on side tray
-void handle_show_side_tray()
-{
-	LLSideTray* side_tray = LLSideTray::getInstance();
-	LLView* root = gViewerWindow->getRootView();
-	// automatically removes and re-adds if there already
-	root->addChild(side_tray);
-}
-
-// Toggle one of "People" panel tabs in side tray.
-class LLTogglePanelPeopleTab : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string panel_name = userdata.asString();
-
-		LLSD param;
-		param["people_panel_tab_name"] = panel_name;
-
-		static LLPanel* friends_panel = NULL;
-		static LLPanel* groups_panel = NULL;
-		static LLPanel* nearby_panel = NULL;
-
-		if (panel_name == "friends_panel")
-		{
-			return togglePeoplePanel(friends_panel, panel_name, param);
-		}
-		else if (panel_name == "groups_panel")
-		{
-			return togglePeoplePanel(groups_panel, panel_name, param);
-		}
-		else if (panel_name == "nearby_panel")
-		{
-			return togglePeoplePanel(nearby_panel, panel_name, param);
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	static bool togglePeoplePanel(LLPanel* &panel, const std::string& panel_name, const LLSD& param)
-	{
-		if(!panel)
-		{
-			panel = LLSideTray::getInstance()->getPanel(panel_name);
-			if(!panel)
-				return false;
-		}
-
-		LLSideTray::getInstance()->togglePanel(panel, "panel_people", param);
-
-		return true;
-	}
-};
-
-BOOL check_admin_override(void*)
-{
-	return gAgent.getAdminOverride();
-}
-
-void handle_admin_override_toggle(void*)
-{
-	gAgent.setAdminOverride(!gAgent.getAdminOverride());
-
-	// The above may have affected which debug menus are visible
-	show_debug_menus();
-}
-
-void handle_god_mode(void*)
-{
-	gAgent.requestEnterGodMode();
-}
-
-void handle_leave_god_mode(void*)
-{
-	gAgent.requestLeaveGodMode();
-}
-
-void set_god_level(U8 god_level)
-{
-	U8 old_god_level = gAgent.getGodLevel();
-	gAgent.setGodLevel( god_level );
-	LLViewerParcelMgr::getInstance()->notifyObservers();
-
-	// God mode changes region visibility
-	LLWorldMap::getInstance()->reloadItems(true);
-
-	// inventory in items may change in god mode
-	gObjectList.dirtyAllObjectInventory();
-
-        if(gViewerWindow)
-        {
-            gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT,
-            LLGridManager::getInstance()->isInProductionGrid());
-        }
-    
-        LLSD args;
-	if(god_level > GOD_NOT)
-	{
-		args["LEVEL"] = llformat("%d",(S32)god_level);
-		LLNotificationsUtil::add("EnteringGodMode", args);
-	}
-	else
-	{
-		args["LEVEL"] = llformat("%d",(S32)old_god_level);
-		LLNotificationsUtil::add("LeavingGodMode", args);
-	}
-
-	// changing god-level can affect which menus we see
-	show_debug_menus();
-
-	// changing god-level can invalidate search results
-	LLFloaterSearch *search = dynamic_cast<LLFloaterSearch*>(LLFloaterReg::getInstance("search"));
-	if (search)
-	{
-		search->godLevelChanged(god_level);
-	}
-}
-
-#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-void handle_toggle_hacked_godmode(void*)
-{
-	gHackGodmode = !gHackGodmode;
-	set_god_level(gHackGodmode ? GOD_MAINTENANCE : GOD_NOT);
-}
-
-BOOL check_toggle_hacked_godmode(void*)
-{
-	return gHackGodmode;
-}
-
-bool enable_toggle_hacked_godmode(void*)
-{
-  return !LLGridManager::getInstance()->isInProductionGrid();
-}
-#endif
-
-void process_grant_godlike_powers(LLMessageSystem* msg, void**)
-{
-	LLUUID agent_id;
-	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
-	LLUUID session_id;
-	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
-	if((agent_id == gAgent.getID()) && (session_id == gAgent.getSessionID()))
-	{
-		U8 god_level;
-		msg->getU8Fast(_PREHASH_GrantData, _PREHASH_GodLevel, god_level);
-		set_god_level(god_level);
-	}
-	else
-	{
-		llwarns << "Grant godlike for wrong agent " << agent_id << llendl;
-	}
-}
-
-/*
-class LLHaveCallingcard : public LLInventoryCollectFunctor
-{
-public:
-	LLHaveCallingcard(const LLUUID& agent_id);
-	virtual ~LLHaveCallingcard() {}
-	virtual bool operator()(LLInventoryCategory* cat,
-							LLInventoryItem* item);
-	BOOL isThere() const { return mIsThere;}
-protected:
-	LLUUID mID;
-	BOOL mIsThere;
-};
-
-LLHaveCallingcard::LLHaveCallingcard(const LLUUID& agent_id) :
-	mID(agent_id),
-	mIsThere(FALSE)
-{
-}
-
-bool LLHaveCallingcard::operator()(LLInventoryCategory* cat,
-								   LLInventoryItem* item)
-{
-	if(item)
-	{
-		if((item->getType() == LLAssetType::AT_CALLINGCARD)
-		   && (item->getCreatorUUID() == mID))
-		{
-			mIsThere = TRUE;
-		}
-	}
-	return FALSE;
-}
-*/
-
-BOOL is_agent_mappable(const LLUUID& agent_id)
-{
-	const LLRelationship* buddy_info = NULL;
-	bool is_friend = LLAvatarActions::isFriend(agent_id);
-
-	if (is_friend)
-		buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id);
-
-	return (buddy_info &&
-		buddy_info->isOnline() &&
-		buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)
-		);
-}
-
-
-// Enable a menu item when you don't have someone's card.
-class LLAvatarEnableAddFriend : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
-		bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID());
-		return new_value;
-	}
-};
-
-void request_friendship(const LLUUID& dest_id)
-{
-	LLViewerObject* dest = gObjectList.findObject(dest_id);
-	if(dest && dest->isAvatar())
-	{
-		std::string full_name;
-		LLNameValue* nvfirst = dest->getNVPair("FirstName");
-		LLNameValue* nvlast = dest->getNVPair("LastName");
-		if(nvfirst && nvlast)
-		{
-			full_name = LLCacheName::buildFullName(
-				nvfirst->getString(), nvlast->getString());
-		}
-		if (!full_name.empty())
-		{
-			LLAvatarActions::requestFriendshipDialog(dest_id, full_name);
-		}
-		else
-		{
-			LLNotificationsUtil::add("CantOfferFriendship");
-		}
-	}
-}
-
-
-class LLEditEnableCustomizeAvatar : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gAgentWearables.areWearablesLoaded();
-		return new_value;
-	}
-};
-
-class LLEnableEditShape : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0);
-	}
-};
-
-bool is_object_sittable()
-{
-	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-
-	if (object && object->getPCode() == LL_PCODE_VOLUME)
-	{
-		return true;
-	}
-	else
-	{
-		return false;
-	}
-}
-
-
-// only works on pie menu
-void handle_object_sit_or_stand()
-{
-	LLPickInfo pick = LLToolPie::getInstance()->getPick();
-	LLViewerObject *object = pick.getObject();;
-	if (!object || pick.mPickType == LLPickInfo::PICK_FLORA)
-	{
-		return;
-	}
-
-	if (sitting_on_selection())
-	{
-		gAgent.standUp();
-		return;
-	}
-
-	// get object selection offset 
-
-	if (object && object->getPCode() == LL_PCODE_VOLUME)
-	{
-
-		gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
-		gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-		gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-		gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-		gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
-		gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
-		gMessageSystem->addVector3Fast(_PREHASH_Offset, pick.mObjectOffset);
-
-		object->getRegion()->sendReliableMessage();
-	}
-}
-
-void near_sit_down_point(BOOL success, void *)
-{
-	if (success)
-	{
-		gAgent.setFlying(FALSE);
-		gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
-
-		// Might be first sit
-		//LLFirstUse::useSit();
-	}
-}
-
-class LLLandSit : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gAgent.standUp();
-		LLViewerParcelMgr::getInstance()->deselectLand();
-
-		LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal;
-		
-		LLQuaternion target_rot;
-		if (isAgentAvatarValid())
-		{
-			target_rot = gAgentAvatarp->getRotation();
-		}
-		else
-		{
-			target_rot = gAgent.getFrameAgent().getQuaternion();
-		}
-		gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, NULL, 0.7f);
-		return true;
-	}
-};
-
-//-------------------------------------------------------------------
-// Help menu functions
-//-------------------------------------------------------------------
-
-//
-// Major mode switching
-//
-void reset_view_final( BOOL proceed );
-
-void handle_reset_view()
-{
-	if (gAgentCamera.cameraCustomizeAvatar())
-	{
-		// switching to outfit selector should automagically save any currently edited wearable
-		LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "my_outfits"));
-	}
-
-	gAgentCamera.switchCameraPreset(CAMERA_PRESET_REAR_VIEW);
-	reset_view_final( TRUE );
-	LLFloaterCamera::resetCameraMode();
-}
-
-class LLViewResetView : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		handle_reset_view();
-		return true;
-	}
-};
-
-// Note: extra parameters allow this function to be called from dialog.
-void reset_view_final( BOOL proceed ) 
-{
-	if( !proceed )
-	{
-		return;
-	}
-
-	gAgentCamera.resetView(TRUE, TRUE);
-	gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
-}
-
-class LLViewLookAtLastChatter : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gAgentCamera.lookAtLastChat();
-		return true;
-	}
-};
-
-class LLViewMouselook : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if (!gAgentCamera.cameraMouselook())
-		{
-			gAgentCamera.changeCameraToMouselook();
-		}
-		else
-		{
-			gAgentCamera.changeCameraToDefault();
-		}
-		return true;
-	}
-};
-
-class LLViewDefaultUISize : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gSavedSettings.setF32("UIScaleFactor", 1.0f);
-		gSavedSettings.setBOOL("UIAutoScale", FALSE);	
-		gViewerWindow->reshape(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
-		return true;
-	}
-};
-
-class LLEditDuplicate : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if(LLEditMenuHandler::gEditMenuHandler)
-		{
-			LLEditMenuHandler::gEditMenuHandler->duplicate();
-		}
-		return true;
-	}
-};
-
-class LLEditEnableDuplicate : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate();
-		return new_value;
-	}
-};
-
-void handle_duplicate_in_place(void*)
-{
-	llinfos << "handle_duplicate_in_place" << llendl;
-
-	LLVector3 offset(0.f, 0.f, 0.f);
-	LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE);
-}
-
-/* dead code 30-apr-2008
-void handle_deed_object_to_group(void*)
-{
-	LLUUID group_id;
-	
-	LLSelectMgr::getInstance()->selectGetGroup(group_id);
-	LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE);
-	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT);
-}
-
-BOOL enable_deed_object_to_group(void*)
-{
-	if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) return FALSE;
-	LLPermissions perm;
-	LLUUID group_id;
-
-	if (LLSelectMgr::getInstance()->selectGetGroup(group_id) &&
-		gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) &&
-		LLSelectMgr::getInstance()->selectGetPermissions(perm) &&
-		perm.deedToGroup(gAgent.getID(), group_id))
-	{
-		return TRUE;
-	}
-	return FALSE;
-}
-
-*/
-
-
-/*
- * No longer able to support viewer side manipulations in this way
- *
-void god_force_inv_owner_permissive(LLViewerObject* object,
-									LLInventoryObject::object_list_t* inventory,
-									S32 serial_num,
-									void*)
-{
-	typedef std::vector<LLPointer<LLViewerInventoryItem> > item_array_t;
-	item_array_t items;
-
-	LLInventoryObject::object_list_t::const_iterator inv_it = inventory->begin();
-	LLInventoryObject::object_list_t::const_iterator inv_end = inventory->end();
-	for ( ; inv_it != inv_end; ++inv_it)
-	{
-		if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY))
-		{
-			LLInventoryObject* obj = *inv_it;
-			LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem((LLViewerInventoryItem*)obj);
-			LLPermissions perm(new_item->getPermissions());
-			perm.setMaskBase(PERM_ALL);
-			perm.setMaskOwner(PERM_ALL);
-			new_item->setPermissions(perm);
-			items.push_back(new_item);
-		}
-	}
-	item_array_t::iterator end = items.end();
-	item_array_t::iterator it;
-	for(it = items.begin(); it != end; ++it)
-	{
-		// since we have the inventory item in the callback, it should not
-		// invalidate iteration through the selection manager.
-		object->updateInventory((*it), TASK_INVENTORY_ITEM_KEY, false);
-	}
-}
-*/
-
-void handle_object_owner_permissive(void*)
-{
-	// only send this if they're a god.
-	if(gAgent.isGodlike())
-	{
-		// do the objects.
-		LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE);
-		LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE);
-	}
-}
-
-void handle_object_owner_self(void*)
-{
-	// only send this if they're a god.
-	if(gAgent.isGodlike())
-	{
-		LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID(), TRUE);
-	}
-}
-
-// Shortcut to set owner permissions to not editable.
-void handle_object_lock(void*)
-{
-	LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY);
-}
-
-void handle_object_asset_ids(void*)
-{
-	// only send this if they're a god.
-	if (gAgent.isGodlike())
-	{
-		LLSelectMgr::getInstance()->sendGodlikeRequest("objectinfo", "assetids");
-	}
-}
-
-void handle_force_parcel_owner_to_me(void*)
-{
-	LLViewerParcelMgr::getInstance()->sendParcelGodForceOwner( gAgent.getID() );
-}
-
-void handle_force_parcel_to_content(void*)
-{
-	LLViewerParcelMgr::getInstance()->sendParcelGodForceToContent();
-}
-
-void handle_claim_public_land(void*)
-{
-	if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion())
-	{
-		LLNotificationsUtil::add("ClaimPublicLand");
-		return;
-	}
-
-	LLVector3d west_south_global;
-	LLVector3d east_north_global;
-	LLViewerParcelMgr::getInstance()->getSelection(west_south_global, east_north_global);
-	LLVector3 west_south = gAgent.getPosAgentFromGlobal(west_south_global);
-	LLVector3 east_north = gAgent.getPosAgentFromGlobal(east_north_global);
-
-	LLMessageSystem* msg = gMessageSystem;
-	msg->newMessage("GodlikeMessage");
-	msg->nextBlock("AgentData");
-	msg->addUUID("AgentID", gAgent.getID());
-	msg->addUUID("SessionID", gAgent.getSessionID());
-	msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
-	msg->nextBlock("MethodData");
-	msg->addString("Method", "claimpublicland");
-	msg->addUUID("Invoice", LLUUID::null);
-	std::string buffer;
-	buffer = llformat( "%f", west_south.mV[VX]);
-	msg->nextBlock("ParamList");
-	msg->addString("Parameter", buffer);
-	buffer = llformat( "%f", west_south.mV[VY]);
-	msg->nextBlock("ParamList");
-	msg->addString("Parameter", buffer);
-	buffer = llformat( "%f", east_north.mV[VX]);
-	msg->nextBlock("ParamList");
-	msg->addString("Parameter", buffer);
-	buffer = llformat( "%f", east_north.mV[VY]);
-	msg->nextBlock("ParamList");
-	msg->addString("Parameter", buffer);
-	gAgent.sendReliableMessage();
-}
-
-
-
-// HACK for easily testing new avatar geometry
-void handle_god_request_avatar_geometry(void *)
-{
-	if (gAgent.isGodlike())
-	{
-		LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", "");
-	}
-}
-
-
-void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
-{
-	if(gAgentCamera.cameraMouselook())
-	{
-		gAgentCamera.changeCameraToDefault();
-	}
-	//gInventoryView->setPanelOpen(TRUE);
-
-	std::string error;
-	LLDynamicArray<LLViewerObject*> derez_objects;
-	
-	// Check conditions that we can't deal with, building a list of
-	// everything that we'll actually be derezzing.
-	LLViewerRegion* first_region = NULL;
-	for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
-		 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
-	{
-		LLSelectNode* node = *iter;
-		LLViewerObject* object = node->getObject();
-		LLViewerRegion* region = object->getRegion();
-		if (!first_region)
-		{
-			first_region = region;
-		}
-		else
-		{
-			if(region != first_region)
-			{
-				// Derez doesn't work at all if the some of the objects
-				// are in regions besides the first object selected.
-				
-				// ...crosses region boundaries
-				error = "AcquireErrorObjectSpan";
-				break;
-			}
-		}
-		if (object->isAvatar())
-		{
-			// ...don't acquire avatars
-			continue;
-		}
-
-		// If AssetContainers are being sent back, they will appear as 
-		// boxes in the owner's inventory.
-		if (object->getNVPair("AssetContainer")
-			&& dest != DRD_RETURN_TO_OWNER)
-		{
-			// this object is an asset container, derez its contents, not it
-			llwarns << "Attempt to derez deprecated AssetContainer object type not supported." << llendl;
-			/*
-			object->requestInventory(container_inventory_arrived, 
-				(void *)(BOOL)(DRD_TAKE_INTO_AGENT_INVENTORY == dest));
-			*/
-			continue;
-		}
-		BOOL can_derez_current = FALSE;
-		switch(dest)
-		{
-		case DRD_TAKE_INTO_AGENT_INVENTORY:
-		case DRD_TRASH:
-			if( (node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify())
-				|| (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE)) )
-			{
-				can_derez_current = TRUE;
-			}
-			break;
-
-		case DRD_RETURN_TO_OWNER:
-			can_derez_current = TRUE;
-			break;
-
-		default:
-			if((node->mPermissions->allowTransferTo(gAgent.getID())
-				&& object->permCopy())
-			   || gAgent.isGodlike())
-			{
-				can_derez_current = TRUE;
-			}
-			break;
-		}
-		if(can_derez_current)
-		{
-			derez_objects.put(object);
-		}
-	}
-
-	// This constant is based on (1200 - HEADER_SIZE) / 4 bytes per
-	// root.  I lopped off a few (33) to provide a bit
-	// pad. HEADER_SIZE is currently 67 bytes, most of which is UUIDs.
-	// This gives us a maximum of 63500 root objects - which should
-	// satisfy anybody.
-	const S32 MAX_ROOTS_PER_PACKET = 250;
-	const S32 MAX_PACKET_COUNT = 254;
-	F32 packets = ceil((F32)derez_objects.count() / (F32)MAX_ROOTS_PER_PACKET);
-	if(packets > (F32)MAX_PACKET_COUNT)
-	{
-		error = "AcquireErrorTooManyObjects";
-	}
-
-	if(error.empty() && derez_objects.count() > 0)
-	{
-		U8 d = (U8)dest;
-		LLUUID tid;
-		tid.generate();
-		U8 packet_count = (U8)packets;
-		S32 object_index = 0;
-		S32 objects_in_packet = 0;
-		LLMessageSystem* msg = gMessageSystem;
-		for(U8 packet_number = 0;
-			packet_number < packet_count;
-			++packet_number)
-		{
-			msg->newMessageFast(_PREHASH_DeRezObject);
-			msg->nextBlockFast(_PREHASH_AgentData);
-			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-			msg->nextBlockFast(_PREHASH_AgentBlock);
-			msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
-			msg->addU8Fast(_PREHASH_Destination, d);	
-			msg->addUUIDFast(_PREHASH_DestinationID, dest_id);
-			msg->addUUIDFast(_PREHASH_TransactionID, tid);
-			msg->addU8Fast(_PREHASH_PacketCount, packet_count);
-			msg->addU8Fast(_PREHASH_PacketNumber, packet_number);
-			objects_in_packet = 0;
-			while((object_index < derez_objects.count())
-				  && (objects_in_packet++ < MAX_ROOTS_PER_PACKET))
-
-			{
-				LLViewerObject* object = derez_objects.get(object_index++);
-				msg->nextBlockFast(_PREHASH_ObjectData);
-				msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID());
-				// VEFFECT: DerezObject
-				LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
-				effectp->setPositionGlobal(object->getPositionGlobal());
-				effectp->setColor(LLColor4U(gAgent.getEffectColor()));
-			}
-			msg->sendReliable(first_region->getHost());
-		}
-		make_ui_sound("UISndObjectRezOut");
-
-		// Busy count decremented by inventory update, so only increment
-		// if will be causing an update.
-		if (dest != DRD_RETURN_TO_OWNER)
-		{
-			gViewerWindow->getWindow()->incBusyCount();
-		}
-	}
-	else if(!error.empty())
-	{
-		LLNotificationsUtil::add(error);
-	}
-}
-
-void handle_take_copy()
-{
-	if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
-
-	const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
-	derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
-}
-
-// You can return an object to its owner if it is on your land.
-class LLObjectReturn : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
-		
-		mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
-
-		LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2));
-		return true;
-	}
-
-	bool onReturnToOwner(const LLSD& notification, const LLSD& response)
-	{
-		S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-		if (0 == option)
-		{
-			// Ignore category ID for this derez destination.
-			derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null);
-		}
-
-		// drop reference to current selection
-		mObjectSelection = NULL;
-		return false;
-	}
-
-protected:
-	LLObjectSelectionHandle mObjectSelection;
-};
-
-
-// Allow return to owner if one or more of the selected items is
-// over land you own.
-class LLObjectEnableReturn : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
-		{
-			// Do not enable if nothing selected
-			return false;
-		}
-#ifdef HACKED_GODLIKE_VIEWER
-		bool new_value = true;
-#else
-		bool new_value = false;
-		if (gAgent.isGodlike())
-		{
-			new_value = true;
-		}
-		else
-		{
-			LLViewerRegion* region = gAgent.getRegion();
-			if (region)
-			{
-				// Estate owners and managers can always return objects.
-				if (region->canManageEstate())
-				{
-					new_value = true;
-				}
-				else
-				{
-					struct f : public LLSelectedObjectFunctor
-					{
-						virtual bool apply(LLViewerObject* obj)
-						{
-							return 
-								obj->permModify() ||
-								obj->isReturnable();
-						}
-					} func;
-					const bool firstonly = true;
-					new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
-				}
-			}
-		}
-#endif
-		return new_value;
-	}
-};
-
-void force_take_copy(void*)
-{
-	if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
-	const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
-	derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id);
-}
-
-void handle_take()
-{
-	// we want to use the folder this was derezzed from if it's
-	// available. Otherwise, derez to the normal place.
-	if(LLSelectMgr::getInstance()->getSelection()->isEmpty())
-	{
-		return;
-	}
-	
-	BOOL you_own_everything = TRUE;
-	BOOL locked_but_takeable_object = FALSE;
-	LLUUID category_id;
-	
-	for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
-		 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
-	{
-		LLSelectNode* node = *iter;
-		LLViewerObject* object = node->getObject();
-		if(object)
-		{
-			if(!object->permYouOwner())
-			{
-				you_own_everything = FALSE;
-			}
-
-			if(!object->permMove())
-			{
-				locked_but_takeable_object = TRUE;
-			}
-		}
-		if(node->mFolderID.notNull())
-		{
-			if(category_id.isNull())
-			{
-				category_id = node->mFolderID;
-			}
-			else if(category_id != node->mFolderID)
-			{
-				// we have found two potential destinations. break out
-				// now and send to the default location.
-				category_id.setNull();
-				break;
-			}
-		}
-	}
-	if(category_id.notNull())
-	{
-		// there is an unambiguous destination. See if this agent has
-		// such a location and it is not in the trash or library
-		if(!gInventory.getCategory(category_id))
-		{
-			// nope, set to NULL.
-			category_id.setNull();
-		}
-		if(category_id.notNull())
-		{
-		        // check trash
-			const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
-			if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash))
-			{
-				category_id.setNull();
-			}
-
-			// check library
-			if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID()))
-			{
-				category_id.setNull();
-			}
-
-		}
-	}
-	if(category_id.isNull())
-	{
-		category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
-	}
-	LLSD payload;
-	payload["folder_id"] = category_id;
-
-	LLNotification::Params params("ConfirmObjectTakeLock");
-	params.payload(payload);
-	params.functor.function(confirm_take);
-
-	if(locked_but_takeable_object ||
-	   !you_own_everything)
-	{
-		if(locked_but_takeable_object && you_own_everything)
-		{
-			params.name("ConfirmObjectTakeLock");
-		}
-		else if(!locked_but_takeable_object && !you_own_everything)
-		{
-			params.name("ConfirmObjectTakeNoOwn");
-		}
-		else
-		{
-			params.name("ConfirmObjectTakeLockNoOwn");
-		}
-	
-		LLNotifications::instance().add(params);
-	}
-	else
-	{
-		LLNotifications::instance().forceResponse(params, 0);
-	}
-}
-
-void handle_object_show_inspector()
-{
-	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-	LLViewerObject* objectp = selection->getFirstRootObject(TRUE);
- 	if (!objectp)
- 	{
- 		return;
- 	}
-
-	LLSD params;
-	params["object_id"] = objectp->getID();
-	LLFloaterReg::showInstance("inspect_object", params);
-}
-
-void handle_avatar_show_inspector()
-{
-	LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
-	if(avatar)
-	{
-		LLSD params;
-		params["avatar_id"] = avatar->getID();
-		LLFloaterReg::showInstance("inspect_avatar", params);
-	}
-}
-
-
-
-bool confirm_take(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if(enable_take() && (option == 0))
-	{
-		derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID());
-	}
-	return false;
-}
-
-// You can take an item when it is public and transferrable, or when
-// you own it. We err on the side of enabling the item when at least
-// one item selected can be copied to inventory.
-BOOL enable_take()
-{
-	if (sitting_on_selection())
-	{
-		return FALSE;
-	}
-
-	for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
-		 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
-	{
-		LLSelectNode* node = *iter;
-		LLViewerObject* object = node->getObject();
-		if (object->isAvatar())
-		{
-			// ...don't acquire avatars
-			continue;
-		}
-
-#ifdef HACKED_GODLIKE_VIEWER
-		return TRUE;
-#else
-# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (!LLGridManager::getInstance()->isInProductionGrid() 
-            && gAgent.isGodlike())
-		{
-			return TRUE;
-		}
-# endif
-		if((node->mPermissions->allowTransferTo(gAgent.getID())
-			&& object->permModify())
-		   || (node->mPermissions->getOwner() == gAgent.getID()))
-		{
-			return TRUE;
-		}
-#endif
-	}
-	return FALSE;
-}
-
-
-void handle_buy_or_take()
-{
-	if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
-	{
-		return;
-	}
-
-	if (is_selection_buy_not_take())
-	{
-		S32 total_price = selection_price();
-
-		if (total_price <= gStatusBar->getBalance() || total_price == 0)
-		{
-			handle_buy();
-		}
-		else
-		{
-			LLStringUtil::format_map_t args;
-			args["AMOUNT"] = llformat("%d", total_price);
-			LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "BuyingCosts", args ), total_price );
-		}
-	}
-	else
-	{
-		handle_take();
-	}
-}
-
-bool visible_buy_object()
-{
-	return is_selection_buy_not_take() && enable_buy_object();
-}
-
-bool visible_take_object()
-{
-	return !is_selection_buy_not_take() && enable_take();
-}
-
-bool tools_visible_buy_object()
-{
-	return is_selection_buy_not_take();
-}
-
-bool tools_visible_take_object()
-{
-	return !is_selection_buy_not_take();
-}
-
-class LLToolsEnableBuyOrTake : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool is_buy = is_selection_buy_not_take();
-		bool new_value = is_buy ? enable_buy_object() : enable_take();
-		return new_value;
-	}
-};
-
-// This is a small helper function to determine if we have a buy or a
-// take in the selection. This method is to help with the aliasing
-// problems of putting buy and take in the same pie menu space. After
-// a fair amont of discussion, it was determined to prefer buy over
-// take. The reasoning follows from the fact that when users walk up
-// to buy something, they will click on one or more items. Thus, if
-// anything is for sale, it becomes a buy operation, and the server
-// will group all of the buy items, and copyable/modifiable items into
-// one package and give the end user as much as the permissions will
-// allow. If the user wanted to take something, they will select fewer
-// and fewer items until only 'takeable' items are left. The one
-// exception is if you own everything in the selection that is for
-// sale, in this case, you can't buy stuff from yourself, so you can
-// take it.
-// return value = TRUE if selection is a 'buy'.
-//                FALSE if selection is a 'take'
-BOOL is_selection_buy_not_take()
-{
-	for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
-		 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
-	{
-		LLSelectNode* node = *iter;
-		LLViewerObject* obj = node->getObject();
-		if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
-		{
-			// you do not own the object and it is for sale, thus,
-			// it's a buy
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-S32 selection_price()
-{
-	S32 total_price = 0;
-	for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
-		 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
-	{
-		LLSelectNode* node = *iter;
-		LLViewerObject* obj = node->getObject();
-		if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
-		{
-			// you do not own the object and it is for sale.
-			// Add its price.
-			total_price += node->mSaleInfo.getSalePrice();
-		}
-	}
-
-	return total_price;
-}
-/*
-bool callback_show_buy_currency(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (0 == option)
-	{
-		llinfos << "Loading page " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL") << llendl;
-		LLWeb::loadURL(LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL"));
-	}
-	return false;
-}
-*/
-
-void show_buy_currency(const char* extra)
-{
-	// Don't show currency web page for branded clients.
-/*
-	std::ostringstream mesg;
-	if (extra != NULL)
-	{	
-		mesg << extra << "\n \n";
-	}
-	mesg << "Go to " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")<< "\nfor information on purchasing currency?";
-*/
-	LLSD args;
-	if (extra != NULL)
-	{
-		args["EXTRA"] = extra;
-	}
-	LLNotificationsUtil::add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency);
-}
-
-void handle_buy()
-{
-	if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
-
-	LLSaleInfo sale_info;
-	BOOL valid = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
-	if (!valid) return;
-
-	S32 price = sale_info.getSalePrice();
-	
-	if (price > 0 && price > gStatusBar->getBalance())
-	{
-		LLStringUtil::format_map_t args;
-		args["AMOUNT"] = llformat("%d", price);
-		LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("this_object_costs", args), price );
-		return;
-	}
-
-	if (sale_info.getSaleType() == LLSaleInfo::FS_CONTENTS)
-	{
-		handle_buy_contents(sale_info);
-	}
-	else
-	{
-		handle_buy_object(sale_info);
-	}
-}
-
-bool anyone_copy_selection(LLSelectNode* nodep)
-{
-	bool perm_copy = (bool)(nodep->getObject()->permCopy());
-	bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY);
-	return perm_copy && all_copy;
-}
-
-bool for_sale_selection(LLSelectNode* nodep)
-{
-	return nodep->mSaleInfo.isForSale()
-		&& nodep->mPermissions->getMaskOwner() & PERM_TRANSFER
-		&& (nodep->mPermissions->getMaskOwner() & PERM_COPY
-			|| nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
-}
-
-BOOL sitting_on_selection()
-{
-	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-	if (!node)
-	{
-		return FALSE;
-	}
-
-	if (!node->mValid)
-	{
-		return FALSE;
-	}
-
-	LLViewerObject* root_object = node->getObject();
-	if (!root_object)
-	{
-		return FALSE;
-	}
-
-	// Need to determine if avatar is sitting on this object
-	if (!isAgentAvatarValid()) return FALSE;
-
-	return (gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == root_object);
-}
-
-class LLToolsSaveToInventory : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if(enable_save_into_inventory(NULL))
-		{
-			derez_objects(DRD_SAVE_INTO_AGENT_INVENTORY, LLUUID::null);
-		}
-		return true;
-	}
-};
-
-class LLToolsSaveToObjectInventory : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-		if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
-		{
-			// *TODO: check to see if the fromtaskid object exists.
-			derez_objects(DRD_SAVE_INTO_TASK_INVENTORY, node->mFromTaskID);
-		}
-		return true;
-	}
-};
-
-// Round the position of all root objects to the grid
-class LLToolsSnapObjectXY : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		F64 snap_size = (F64)gSavedSettings.getF32("GridResolution");
-
-		for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
-			 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
-		{
-			LLSelectNode* node = *iter;
-			LLViewerObject* obj = node->getObject();
-			if (obj->permModify())
-			{
-				LLVector3d pos_global = obj->getPositionGlobal();
-				F64 round_x = fmod(pos_global.mdV[VX], snap_size);
-				if (round_x < snap_size * 0.5)
-				{
-					// closer to round down
-					pos_global.mdV[VX] -= round_x;
-				}
-				else
-				{
-					// closer to round up
-					pos_global.mdV[VX] -= round_x;
-					pos_global.mdV[VX] += snap_size;
-				}
-
-				F64 round_y = fmod(pos_global.mdV[VY], snap_size);
-				if (round_y < snap_size * 0.5)
-				{
-					pos_global.mdV[VY] -= round_y;
-				}
-				else
-				{
-					pos_global.mdV[VY] -= round_y;
-					pos_global.mdV[VY] += snap_size;
-				}
-
-				obj->setPositionGlobal(pos_global, FALSE);
-			}
-		}
-		LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
-		return true;
-	}
-};
-
-// Determine if the option to cycle between linked prims is shown
-class LLToolsEnableSelectNextPart : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = (gSavedSettings.getBOOL("EditLinkedParts") &&
-				 !LLSelectMgr::getInstance()->getSelection()->isEmpty());
-		return new_value;
-	}
-};
-
-// Cycle selection through linked children in selected object.
-// FIXME: Order of children list is not always the same as sim's idea of link order. This may confuse
-// resis. Need link position added to sim messages to address this.
-class LLToolsSelectNextPart : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
-		if (gSavedSettings.getBOOL("EditLinkedParts") && object_count)
-		{
-			LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
-			if (selected && selected->getRootEdit())
-			{
-				bool fwd = (userdata.asString() == "next");
-				bool prev = (userdata.asString() == "previous");
-				bool ifwd = (userdata.asString() == "includenext");
-				bool iprev = (userdata.asString() == "includeprevious");
-				LLViewerObject* to_select = NULL;
-				LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren();
-				children.push_front(selected->getRootEdit());	// need root in the list too
-
-				for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter)
-				{
-					if ((*iter)->isSelected())
-					{
-						if (object_count > 1 && (fwd || prev))	// multiple selection, find first or last selected if not include
-						{
-							to_select = *iter;
-							if (fwd)
-							{
-								// stop searching if going forward; repeat to get last hit if backward
-								break;
-							}
-						}
-						else if ((object_count == 1) || (ifwd || iprev))	// single selection or include
-						{
-							if (fwd || ifwd)
-							{
-								++iter;
-								while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected())))
-								{
-									++iter;	// skip sitting avatars and selected if include
-								}
-							}
-							else // backward
-							{
-								iter = (iter == children.begin() ? children.end() : iter);
-								--iter;
-								while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected())))
-								{
-									--iter;	// skip sitting avatars and selected if include
-								}
-							}
-							iter = (iter == children.end() ? children.begin() : iter);
-							to_select = *iter;
-							break;
-						}
-					}
-				}
-
-				if (to_select)
-				{
-					if (gFocusMgr.childHasKeyboardFocus(gFloaterTools))
-					{
-						gFocusMgr.setKeyboardFocus(NULL);	// force edit toolbox to commit any changes
-					}
-					if (fwd || prev)
-					{
-						LLSelectMgr::getInstance()->deselectAll();
-					}
-					LLSelectMgr::getInstance()->selectObjectOnly(to_select);
-					return true;
-				}
-			}
-		}
-		return true;
-	}
-};
-
-class LLToolsStopAllAnimations : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gAgent.stopCurrentAnimations();
-		return true;
-	}
-};
-
-class LLToolsReleaseKeys : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gAgent.forceReleaseControls();
-
-		return true;
-	}
-};
-
-class LLToolsEnableReleaseKeys : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		return gAgent.anyControlGrabbed();
-	}
-};
-
-
-class LLEditEnableCut : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut();
-		return new_value;
-	}
-};
-
-class LLEditCut : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if( LLEditMenuHandler::gEditMenuHandler )
-		{
-			LLEditMenuHandler::gEditMenuHandler->cut();
-		}
-		return true;
-	}
-};
-
-class LLEditEnableCopy : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy();
-		return new_value;
-	}
-};
-
-class LLEditCopy : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if( LLEditMenuHandler::gEditMenuHandler )
-		{
-			LLEditMenuHandler::gEditMenuHandler->copy();
-		}
-		return true;
-	}
-};
-
-class LLEditEnablePaste : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste();
-		return new_value;
-	}
-};
-
-class LLEditPaste : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if( LLEditMenuHandler::gEditMenuHandler )
-		{
-			LLEditMenuHandler::gEditMenuHandler->paste();
-		}
-		return true;
-	}
-};
-
-class LLEditEnableDelete : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete();
-		return new_value;
-	}
-};
-
-class LLEditDelete : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// If a text field can do a deletion, it gets precedence over deleting
-		// an object in the world.
-		if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete())
-		{
-			LLEditMenuHandler::gEditMenuHandler->doDelete();
-		}
-
-		// and close any pie/context menus when done
-		gMenuHolder->hideMenus();
-
-		// When deleting an object we may not actually be done
-		// Keep selection so we know what to delete when confirmation is needed about the delete
-		gMenuObject->hide();
-		return true;
-	}
-};
-
-bool enable_object_delete()
-{
-	bool new_value = 
-#ifdef HACKED_GODLIKE_VIEWER
-	TRUE;
-#else
-# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-	(!LLGridManager::getInstance()->isInProductionGrid()
-     && gAgent.isGodlike()) ||
-# endif
-	LLSelectMgr::getInstance()->canDoDelete();
-#endif
-	return new_value;
-}
-
-void handle_object_delete()
-{
-
-		if (LLSelectMgr::getInstance())
-		{
-			LLSelectMgr::getInstance()->doDelete();
-		}
-
-		// and close any pie/context menus when done
-		gMenuHolder->hideMenus();
-
-		// When deleting an object we may not actually be done
-		// Keep selection so we know what to delete when confirmation is needed about the delete
-		gMenuObject->hide();
-		return;
-}
-
-void handle_force_delete(void*)
-{
-	LLSelectMgr::getInstance()->selectForceDelete();
-}
-
-class LLViewEnableJoystickFlycam : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled"));
-		return new_value;
-	}
-};
-
-class LLViewEnableLastChatter : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// *TODO: add check that last chatter is in range
-		bool new_value = (gAgentCamera.cameraThirdPerson() && gAgent.getLastChatter().notNull());
-		return new_value;
-	}
-};
-
-class LLEditEnableDeselect : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect();
-		return new_value;
-	}
-};
-
-class LLEditDeselect : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if( LLEditMenuHandler::gEditMenuHandler )
-		{
-			LLEditMenuHandler::gEditMenuHandler->deselect();
-		}
-		return true;
-	}
-};
-
-class LLEditEnableSelectAll : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll();
-		return new_value;
-	}
-};
-
-
-class LLEditSelectAll : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if( LLEditMenuHandler::gEditMenuHandler )
-		{
-			LLEditMenuHandler::gEditMenuHandler->selectAll();
-		}
-		return true;
-	}
-};
-
-
-class LLEditEnableUndo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo();
-		return new_value;
-	}
-};
-
-class LLEditUndo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() )
-		{
-			LLEditMenuHandler::gEditMenuHandler->undo();
-		}
-		return true;
-	}
-};
-
-class LLEditEnableRedo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo();
-		return new_value;
-	}
-};
-
-class LLEditRedo : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() )
-		{
-			LLEditMenuHandler::gEditMenuHandler->redo();
-		}
-		return true;
-	}
-};
-
-
-
-void print_object_info(void*)
-{
-	LLSelectMgr::getInstance()->selectionDump();
-}
-
-void print_agent_nvpairs(void*)
-{
-	LLViewerObject *objectp;
-
-	llinfos << "Agent Name Value Pairs" << llendl;
-
-	objectp = gObjectList.findObject(gAgentID);
-	if (objectp)
-	{
-		objectp->printNameValuePairs();
-	}
-	else
-	{
-		llinfos << "Can't find agent object" << llendl;
-	}
-
-	llinfos << "Camera at " << gAgentCamera.getCameraPositionGlobal() << llendl;
-}
-
-void show_debug_menus()
-{
-	// this might get called at login screen where there is no menu so only toggle it if one exists
-	if ( gMenuBarView )
-	{
-		BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
-		BOOL qamode = gSavedSettings.getBOOL("QAMode");
-
-		gMenuBarView->setItemVisible("Advanced", debug);
-// 		gMenuBarView->setItemEnabled("Advanced", debug); // Don't disable Advanced keyboard shortcuts when hidden
-		
-		gMenuBarView->setItemVisible("Debug", qamode);
-		gMenuBarView->setItemEnabled("Debug", qamode);
-
-		gMenuBarView->setItemVisible("Develop", qamode);
-		gMenuBarView->setItemEnabled("Develop", qamode);
-
-		// Server ('Admin') menu hidden when not in godmode.
-		const bool show_server_menu = (gAgent.getGodLevel() > GOD_NOT || (debug && gAgent.getAdminOverride()));
-		gMenuBarView->setItemVisible("Admin", show_server_menu);
-		gMenuBarView->setItemEnabled("Admin", show_server_menu);
-	}
-	if (gLoginMenuBarView)
-	{
-		BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
-		gLoginMenuBarView->setItemVisible("Debug", debug);
-		gLoginMenuBarView->setItemEnabled("Debug", debug);
-	}
-}
-
-void toggle_debug_menus(void*)
-{
-	BOOL visible = ! gSavedSettings.getBOOL("UseDebugMenus");
-	gSavedSettings.setBOOL("UseDebugMenus", visible);
-	show_debug_menus();
-}
-
-
-// LLUUID gExporterRequestID;
-// std::string gExportDirectory;
-
-// LLUploadDialog *gExportDialog = NULL;
-
-// void handle_export_selected( void * )
-// {
-// 	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-// 	if (selection->isEmpty())
-// 	{
-// 		return;
-// 	}
-// 	llinfos << "Exporting selected objects:" << llendl;
-
-// 	gExporterRequestID.generate();
-// 	gExportDirectory = "";
-
-// 	LLMessageSystem* msg = gMessageSystem;
-// 	msg->newMessageFast(_PREHASH_ObjectExportSelected);
-// 	msg->nextBlockFast(_PREHASH_AgentData);
-// 	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-// 	msg->addUUIDFast(_PREHASH_RequestID, gExporterRequestID);
-// 	msg->addS16Fast(_PREHASH_VolumeDetail, 4);
-
-// 	for (LLObjectSelection::root_iterator iter = selection->root_begin();
-// 		 iter != selection->root_end(); iter++)
-// 	{
-// 		LLSelectNode* node = *iter;
-// 		LLViewerObject* object = node->getObject();
-// 		msg->nextBlockFast(_PREHASH_ObjectData);
-// 		msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
-// 		llinfos << "Object: " << object->getID() << llendl;
-// 	}
-// 	msg->sendReliable(gAgent.getRegion()->getHost());
-
-// 	gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects...");
-// }
-//
-
-
-class LLWorldSetHomeLocation : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// we just send the message and let the server check for failure cases
-		// server will echo back a "Home position set." alert if it succeeds
-		// and the home location screencapture happens when that alert is recieved
-		gAgent.setStartPosition(START_LOCATION_ID_HOME);
-		return true;
-	}
-};
-
-class LLWorldTeleportHome : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gAgent.teleportHome();
-		return true;
-	}
-};
-
-class LLWorldAlwaysRun : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// as well as altering the default walk-vs-run state,
-		// we also change the *current* walk-vs-run state.
-		if (gAgent.getAlwaysRun())
-		{
-			gAgent.clearAlwaysRun();
-			gAgent.clearRunning();
-		}
-		else
-		{
-			gAgent.setAlwaysRun();
-			gAgent.setRunning();
-		}
-
-		// tell the simulator.
-		gAgent.sendWalkRun(gAgent.getAlwaysRun());
-
-		// Update Movement Controls according to AlwaysRun mode
-		LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun());
-
-		return true;
-	}
-};
-
-class LLWorldCheckAlwaysRun : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gAgent.getAlwaysRun();
-		return new_value;
-	}
-};
-
-class LLWorldSetAway : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if (gAgent.getAFK())
-		{
-			gAgent.clearAFK();
-		}
-		else
-		{
-			gAgent.setAFK();
-		}
-		return true;
-	}
-};
-
-class LLWorldSetBusy : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if (gAgent.getBusy())
-		{
-			gAgent.clearBusy();
-		}
-		else
-		{
-			gAgent.setBusy();
-			LLNotificationsUtil::add("BusyModeSet");
-		}
-		return true;
-	}
-};
-
-class LLWorldCreateLandmark : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "create_landmark"));
-
-		return true;
-	}
-};
-
-class LLWorldPlaceProfile : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "agent"));
-
-		return true;
-	}
-};
-
-void handle_look_at_selection(const LLSD& param)
-{
-	const F32 PADDING_FACTOR = 1.75f;
-	BOOL zoom = (param.asString() == "zoom");
-	if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
-	{
-		gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-
-		LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
-		F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
-		F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
-
-		LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent();
-		obj_to_cam.normVec();
-
-		LLUUID object_id;
-		if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())
-		{
-			object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID;
-		}
-		if (zoom)
-		{
-			// Make sure we are not increasing the distance between the camera and object
-			LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal();
-			distance = llmin(distance, (F32) orig_distance.length());
-				
-			gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), 
-										LLSelectMgr::getInstance()->getSelectionCenterGlobal(), 
-										object_id );
-			
-		}
-		else
-		{
-			gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id );
-		}	
-	}
-}
-
-void handle_zoom_to_object(LLUUID object_id)
-{
-	const F32 PADDING_FACTOR = 2.f;
-
-	LLViewerObject* object = gObjectList.findObject(object_id);
-
-	if (object)
-	{
-		gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-
-		LLBBox bbox = object->getBoundingBoxAgent() ;
-		F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
-		F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
-
-		LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent();
-		obj_to_cam.normVec();
-
-
-			LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
-
-			gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance), 
-											object_center_global, 
-											object_id );
-	}
-}
-
-class LLAvatarInviteToGroup : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
-		if(avatar)
-		{
-			LLAvatarActions::inviteToGroup(avatar->getID());
-		}
-		return true;
-	}
-};
-
-class LLAvatarAddFriend : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
-		if(avatar && !LLAvatarActions::isFriend(avatar->getID()))
-		{
-			request_friendship(avatar->getID());
-		}
-		return true;
-	}
-};
-
-class LLAvatarAddContact : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
-		if(avatar)
-		{
-			create_inventory_callingcard(avatar->getID());
-		}
-		return true;
-	}
-};
-
-bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (option == 0)
-	{
-		gAgent.clearBusy();
-	}
-
-	LLViewerObject* objectp = selection->getPrimaryObject();
-
-	// Show avatar's name if paying attachment
-	if (objectp && objectp->isAttachment())
-	{
-		while (objectp && !objectp->isAvatar())
-		{
-			objectp = (LLViewerObject*)objectp->getParent();
-		}
-	}
-
-	if (objectp)
-	{
-		if (objectp->isAvatar())
-		{
-			const bool is_group = false;
-			LLFloaterPayUtil::payDirectly(&give_money,
-									  objectp->getID(),
-									  is_group);
-		}
-		else
-		{
-			LLFloaterPayUtil::payViaObject(&give_money, selection);
-		}
-	}
-	return false;
-}
-
-void handle_give_money_dialog()
-{
-	LLNotification::Params params("BusyModePay");
-	params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection()));
-
-	if (gAgent.getBusy())
-	{
-		// warn users of being in busy mode during a transaction
-		LLNotifications::instance().add(params);
-	}
-	else
-	{
-		LLNotifications::instance().forceResponse(params, 1);
-	}
-}
-
-bool enable_pay_avatar()
-{
-	LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-	LLVOAvatar* avatar = find_avatar_from_object(obj);
-	return (avatar != NULL);
-}
-
-bool enable_pay_object()
-{
-	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-	if( object )
-	{
-		LLViewerObject *parent = (LLViewerObject *)object->getParent();
-		if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney()))
-		{
-			return true;
-		}
-	}
-	return false;
-}
-
-bool enable_object_stand_up()
-{
-	// 'Object Stand Up' menu item is enabled when agent is sitting on selection
-	return sitting_on_selection();
-}
-
-bool enable_object_sit(LLUICtrl* ctrl)
-{
-	// 'Object Sit' menu item is enabled when agent is not sitting on selection
-	bool sitting_on_sel = sitting_on_selection();
-	if (!sitting_on_sel)
-	{
-		std::string item_name = ctrl->getName();
-
-		// init default labels
-		init_default_item_label(item_name);
-
-		// Update label
-		LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-		if (node && node->mValid && !node->mSitName.empty())
-		{
-			gMenuHolder->childSetText(item_name, node->mSitName);
-		}
-		else
-		{
-			gMenuHolder->childSetText(item_name, get_default_item_label(item_name));
-		}
-	}
-	return !sitting_on_sel && is_object_sittable();
-}
-
-void dump_select_mgr(void*)
-{
-	LLSelectMgr::getInstance()->dump();
-}
-
-void dump_inventory(void*)
-{
-	gInventory.dumpInventory();
-}
-
-
-void handle_dump_followcam(void*)
-{
-	LLFollowCamMgr::dump();
-}
-
-void handle_viewer_enable_message_log(void*)
-{
-	gMessageSystem->startLogging();
-}
-
-void handle_viewer_disable_message_log(void*)
-{
-	gMessageSystem->stopLogging();
-}
-
-void handle_customize_avatar()
-{
-	LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "my_outfits"));
-}
-
-void handle_edit_outfit()
-{
-	LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit"));
-}
-
-void handle_edit_shape()
-{
-	LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_shape"));
-}
-
-void handle_report_abuse()
-{
-	// Prevent menu from appearing in screen shot.
-	gMenuHolder->hideMenus();
-	LLFloaterReporter::showFromMenu(COMPLAINT_REPORT);
-}
-
-void handle_buy_currency()
-{
-	LLBuyCurrencyHTML::openCurrencyFloater();
-}
-
-class LLFloaterVisible : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string floater_name = userdata.asString();
-		bool new_value = false;
-		{
-			new_value = LLFloaterReg::instanceVisible(floater_name);
-		}
-		return new_value;
-	}
-};
-
-class LLShowHelp : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string help_topic = userdata.asString();
-		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
-		vhelp->showTopic(help_topic);
-		return true;
-	}
-};
-
-class LLToggleHelp : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser"));
-		if (help_browser && help_browser->isInVisibleChain())
-		{
-			help_browser->closeFloater();
-		}
-		else
-		{
-			std::string help_topic = userdata.asString();
-			LLViewerHelp* vhelp = LLViewerHelp::getInstance();
-			vhelp->showTopic(help_topic);
-		}
-		return true;
-	}
-};
-
-class LLShowSidetrayPanel : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string panel_name = userdata.asString();
-
-		LLPanel* panel = LLSideTray::getInstance()->getPanel(panel_name);
-		if (panel)
-		{
-			if (panel->isInVisibleChain())
-			{
-				LLSideTray::getInstance()->hidePanel(panel_name);
-			}
-			else
-			{
-				LLSideTray::getInstance()->showPanel(panel_name);
-			}
-		}
-		return true;
-	}
-};
-
-class LLSidetrayPanelVisible : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string panel_name = userdata.asString();
-		// Toggle the panel
-		if (LLSideTray::getInstance()->isPanelActive(panel_name))
-		{
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-		
-	}
-};
-
-
-bool callback_show_url(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (0 == option)
-	{
-		LLWeb::loadURL(notification["payload"]["url"].asString());
-	}
-	return false;
-}
-
-class LLPromptShowURL : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string param = userdata.asString();
-		std::string::size_type offset = param.find(",");
-		if (offset != param.npos)
-		{
-			std::string alert = param.substr(0, offset);
-			std::string url = param.substr(offset+1);
-
-			if(gSavedSettings.getBOOL("UseExternalBrowser"))
-			{ 
-    			LLSD payload;
-    			payload["url"] = url;
-    			LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_url);
-			}
-			else
-			{
-		        LLWeb::loadURL(url);
-			}
-		}
-		else
-		{
-			llinfos << "PromptShowURL invalid parameters! Expecting \"ALERT,URL\"." << llendl;
-		}
-		return true;
-	}
-};
-
-bool callback_show_file(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (0 == option)
-	{
-		LLWeb::loadURL(notification["payload"]["url"]);
-	}
-	return false;
-}
-
-class LLPromptShowFile : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string param = userdata.asString();
-		std::string::size_type offset = param.find(",");
-		if (offset != param.npos)
-		{
-			std::string alert = param.substr(0, offset);
-			std::string file = param.substr(offset+1);
-
-			LLSD payload;
-			payload["url"] = file;
-			LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_file);
-		}
-		else
-		{
-			llinfos << "PromptShowFile invalid parameters! Expecting \"ALERT,FILE\"." << llendl;
-		}
-		return true;
-	}
-};
-
-class LLShowAgentProfile : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLUUID agent_id;
-		if (userdata.asString() == "agent")
-		{
-			agent_id = gAgent.getID();
-		}
-		else if (userdata.asString() == "hit object")
-		{
-			LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-			if (objectp)
-			{
-				agent_id = objectp->getID();
-			}
-		}
-		else
-		{
-			agent_id = userdata.asUUID();
-		}
-
-		LLVOAvatar* avatar = find_avatar_from_object(agent_id);
-		if (avatar)
-		{
-			LLAvatarActions::showProfile(avatar->getID());
-		}
-		return true;
-	}
-};
-
-class LLToggleAgentProfile : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLUUID agent_id;
-		if (userdata.asString() == "agent")
-		{
-			agent_id = gAgent.getID();
-		}
-		else if (userdata.asString() == "hit object")
-		{
-			LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-			if (objectp)
-			{
-				agent_id = objectp->getID();
-			}
-		}
-		else
-		{
-			agent_id = userdata.asUUID();
-		}
-
-		LLVOAvatar* avatar = find_avatar_from_object(agent_id);
-		if (avatar)
-		{
-			if (!LLAvatarActions::profileVisible(avatar->getID()))
-			{
-				LLAvatarActions::showProfile(avatar->getID());
-			}
-			else
-			{
-				LLAvatarActions::hideProfile(avatar->getID());
-			}
-		}
-		return true;
-	}
-};
-
-class LLLandEdit : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		if (gAgentCamera.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") )
-		{
-			// zoom in if we're looking at the avatar
-			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
-			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
-
-			gAgentCamera.cameraOrbitOver( F_PI * 0.25f );
-			gViewerWindow->moveCursorToCenter();
-		}
-		else if ( gSavedSettings.getBOOL("EditCameraMovement") )
-		{
-			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
-			gViewerWindow->moveCursorToCenter();
-		}
-
-
-		LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal );
-
-		LLFloaterReg::showInstance("build");
-
-		// Switch to land edit toolset
-		LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolSelectLand::getInstance() );
-		return true;
-	}
-};
-
-class LLWorldEnableBuyLand : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
-								LLViewerParcelMgr::getInstance()->selectionEmpty()
-									? LLViewerParcelMgr::getInstance()->getAgentParcel()
-									: LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(),
-								false);
-		return new_value;
-	}
-};
-
-BOOL enable_buy_land(void*)
-{
-	return LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
-				LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false);
-}
-
-void handle_buy_land()
-{
-	LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
-	if (vpm->selectionEmpty())
-	{
-		vpm->selectParcelAt(gAgent.getPositionGlobal());
-	}
-	vpm->startBuyLand();
-}
-
-class LLObjectAttachToAvatar : public view_listener_t
-{
-public:
-	LLObjectAttachToAvatar(bool replace) : mReplace(replace) {}
-	static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; }
-
-private:
-	bool handleEvent(const LLSD& userdata)
-	{
-		setObjectSelection(LLSelectMgr::getInstance()->getSelection());
-		LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject();
-		if (selectedObject)
-		{
-			S32 index = userdata.asInteger();
-			LLViewerJointAttachment* attachment_point = NULL;
-			if (index > 0)
-				attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL);
-			confirmReplaceAttachment(0, attachment_point);
-		}
-		return true;
-	}
-
-	static void onNearAttachObject(BOOL success, void *user_data);
-	void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point);
-
-	struct CallbackData
-	{
-		CallbackData(LLViewerJointAttachment* point, bool replace) : mAttachmentPoint(point), mReplace(replace) {}
-
-		LLViewerJointAttachment*	mAttachmentPoint;
-		bool						mReplace;
-	};
-
-protected:
-	static LLObjectSelectionHandle sObjectSelection;
-	bool mReplace;
-};
-
-LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection;
-
-// static
-void LLObjectAttachToAvatar::onNearAttachObject(BOOL success, void *user_data)
-{
-	if (!user_data) return;
-	CallbackData* cb_data = static_cast<CallbackData*>(user_data);
-
-	if (success)
-	{
-		const LLViewerJointAttachment *attachment = cb_data->mAttachmentPoint;
-		
-		U8 attachment_id = 0;
-		if (attachment)
-		{
-			for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
-				 iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter)
-			{
-				if (iter->second == attachment)
-				{
-					attachment_id = iter->first;
-					break;
-				}
-			}
-		}
-		else
-		{
-			// interpret 0 as "default location"
-			attachment_id = 0;
-		}
-		LLSelectMgr::getInstance()->sendAttach(attachment_id, cb_data->mReplace);
-	}		
-	LLObjectAttachToAvatar::setObjectSelection(NULL);
-
-	delete cb_data;
-}
-
-// static
-void LLObjectAttachToAvatar::confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point)
-{
-	if (option == 0/*YES*/)
-	{
-		LLViewerObject* selectedObject = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
-		if (selectedObject)
-		{
-			const F32 MIN_STOP_DISTANCE = 1.f;	// meters
-			const F32 ARM_LENGTH = 0.5f;		// meters
-			const F32 SCALE_FUDGE = 1.5f;
-
-			F32 stop_distance = SCALE_FUDGE * selectedObject->getMaxScale() + ARM_LENGTH;
-			if (stop_distance < MIN_STOP_DISTANCE)
-			{
-				stop_distance = MIN_STOP_DISTANCE;
-			}
-
-			LLVector3 walkToSpot = selectedObject->getPositionAgent();
-			
-			// make sure we stop in front of the object
-			LLVector3 delta = walkToSpot - gAgent.getPositionAgent();
-			delta.normVec();
-			delta = delta * 0.5f;
-			walkToSpot -= delta;
-
-			// The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak.
-			CallbackData* user_data = new CallbackData(attachment_point, mReplace);
-			gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance);
-			gAgentCamera.clearFocusObject();
-		}
-	}
-}
-
-void callback_attachment_drop(const LLSD& notification, const LLSD& response)
-{
-	// Ensure user confirmed the drop
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (option != 0) return;
-
-	// Called when the user clicked on an object attached to them
-	// and selected "Drop".
-	LLUUID object_id = notification["payload"]["object_id"].asUUID();
-	LLViewerObject *object = gObjectList.findObject(object_id);
-	
-	if (!object)
-	{
-		llwarns << "handle_drop_attachment() - no object to drop" << llendl;
-		return;
-	}
-
-	LLViewerObject *parent = (LLViewerObject*)object->getParent();
-	while (parent)
-	{
-		if(parent->isAvatar())
-		{
-			break;
-		}
-		object = parent;
-		parent = (LLViewerObject*)parent->getParent();
-	}
-
-	if (!object)
-	{
-		llwarns << "handle_detach() - no object to detach" << llendl;
-		return;
-	}
-
-	if (object->isAvatar())
-	{
-		llwarns << "Trying to detach avatar from avatar." << llendl;
-		return;
-	}
-	
-	// reselect the object
-	LLSelectMgr::getInstance()->selectObjectAndFamily(object);
-
-	LLSelectMgr::getInstance()->sendDropAttachment();
-
-	return;
-}
-
-class LLAttachmentDrop : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLSD payload;
-		LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-
-		if (object) 
-		{
-			payload["object_id"] = object->getID();
-		}
-		else
-		{
-			llwarns << "Drop object not found" << llendl;
-			return true;
-		}
-
-		LLNotificationsUtil::add("AttachmentDrop", LLSD(), payload, &callback_attachment_drop);
-		return true;
-	}
-};
-
-// called from avatar pie menu
-class LLAttachmentDetachFromPoint : public view_listener_t
-{
-	bool handleEvent(const LLSD& user_data)
-	{
-		const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
-		if (attachment->getNumObjects() > 0)
-		{
-			gMessageSystem->newMessage("ObjectDetach");
-			gMessageSystem->nextBlockFast(_PREHASH_AgentData);
-			gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
-			gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-			
-			for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin();
-				 iter != attachment->mAttachedObjects.end();
-				 iter++)
-			{
-				LLViewerObject *attached_object = (*iter);
-				gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
-				gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
-			}
-			gMessageSystem->sendReliable( gAgent.getRegionHost() );
-		}
-		return true;
-	}
-};
-
-static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
-{
-	std::string label;
-	LLMenuItemGL* menu = dynamic_cast<LLMenuItemGL*>(ctrl);
-	if (menu)
-	{
-		const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL);
-		if (attachment)
-		{
-			label = data["label"].asString();
-			for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin();
-				 attachment_iter != attachment->mAttachedObjects.end();
-				 ++attachment_iter)
-			{
-				const LLViewerObject* attached_object = (*attachment_iter);
-				if (attached_object)
-				{
-					LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
-					if (itemp)
-					{
-						label += std::string(" (") + itemp->getName() + std::string(")");
-						break;
-					}
-				}
-			}
-		}
-		menu->setLabel(label);
-	}
-	return true;
-}
-
-class LLAttachmentDetach : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// Called when the user clicked on an object attached to them
-		// and selected "Detach".
-		LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-		if (!object)
-		{
-			llwarns << "handle_detach() - no object to detach" << llendl;
-			return true;
-		}
-
-		LLViewerObject *parent = (LLViewerObject*)object->getParent();
-		while (parent)
-		{
-			if(parent->isAvatar())
-			{
-				break;
-			}
-			object = parent;
-			parent = (LLViewerObject*)parent->getParent();
-		}
-
-		if (!object)
-		{
-			llwarns << "handle_detach() - no object to detach" << llendl;
-			return true;
-		}
-
-		if (object->isAvatar())
-		{
-			llwarns << "Trying to detach avatar from avatar." << llendl;
-			return true;
-		}
-
-		// The sendDetach() method works on the list of selected
-		// 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.
-		//RN: I thought it was more useful to detach everything that was selected
-		if (LLSelectMgr::getInstance()->getSelection()->isAttachment())
-		{
-			LLSelectMgr::getInstance()->sendDetach();
-		}
-		return true;
-	}
-};
-
-//Adding an observer for a Jira 2422 and needs to be a fetch observer
-//for Jira 3119
-class LLWornItemFetchedObserver : public LLInventoryFetchItemsObserver
-{
-public:
-	LLWornItemFetchedObserver(const LLUUID& worn_item_id) :
-		LLInventoryFetchItemsObserver(worn_item_id)
-	{}
-	virtual ~LLWornItemFetchedObserver() {}
-
-protected:
-	virtual void done()
-	{
-		gMenuAttachmentSelf->buildDrawLabels();
-		gInventory.removeObserver(this);
-		delete this;
-	}
-};
-
-// You can only drop items on parcels where you can build.
-class LLAttachmentEnableDrop : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		BOOL can_build   = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild());
-
-		//Add an inventory observer to only allow dropping the newly attached item
-		//once it exists in your inventory.  Look at Jira 2422.
-		//-jwolk
-
-		// A bug occurs when you wear/drop an item before it actively is added to your inventory
-		// if this is the case (you're on a slow sim, etc.) a copy of the object,
-		// well, a newly created object with the same properties, is placed
-		// in your inventory.  Therefore, we disable the drop option until the
-		// item is in your inventory
-
-		LLViewerObject*              object         = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-		LLViewerJointAttachment*     attachment     = NULL;
-		LLInventoryItem*             item           = NULL;
-
-		// Do not enable drop if all faces of object are not enabled
-		if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
-		{
-    		S32 attachmentID  = ATTACHMENT_ID_FROM_STATE(object->getState());
-			attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
-
-			if (attachment)
-			{
-				for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
-					 attachment_iter != attachment->mAttachedObjects.end();
-					 ++attachment_iter)
-				{
-					// make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
-					// so check to see if the item is in the inventory already
-					item = gInventory.getItem((*attachment_iter)->getAttachmentItemID());
-					if (!item)
-					{
-						// Item does not exist, make an observer to enable the pie menu 
-						// when the item finishes fetching worst case scenario 
-						// if a fetch is already out there (being sent from a slow sim)
-						// we refetch and there are 2 fetches
-						LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID());		
-						worn_item_fetched->startFetch();
-						gInventory.addObserver(worn_item_fetched);
-					}
-				}
-			}
-		}
-		
-		//now check to make sure that the item is actually in the inventory before we enable dropping it
-		bool new_value = enable_detach() && can_build && item;
-
-		return new_value;
-	}
-};
-
-BOOL enable_detach(const LLSD&)
-{
-	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-	
-	// Only enable detach if all faces of object are selected
-	if (!object ||
-		!object->isAttachment() ||
-		!LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
-	{
-		return FALSE;
-	}
-
-	// Find the avatar who owns this attachment
-	LLViewerObject* avatar = object;
-	while (avatar)
-	{
-		// ...if it's you, good to detach
-		if (avatar->getID() == gAgent.getID())
-		{
-			return TRUE;
-		}
-
-		avatar = (LLViewerObject*)avatar->getParent();
-	}
-
-	return FALSE;
-}
-
-class LLAttachmentEnableDetach : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = enable_detach();
-		return new_value;
-	}
-};
-
-// Used to tell if the selected object can be attached to your avatar.
-BOOL object_selected_and_point_valid()
-{
-	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-	for (LLObjectSelection::root_iterator iter = selection->root_begin();
-		 iter != selection->root_end(); iter++)
-	{
-		LLSelectNode* node = *iter;
-		LLViewerObject* object = node->getObject();
-		LLViewerObject::const_child_list_t& child_list = object->getChildren();
-		for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
-			 iter != child_list.end(); iter++)
-		{
-			LLViewerObject* child = *iter;
-			if (child->isAvatar())
-			{
-				return FALSE;
-			}
-		}
-	}
-
-	return (selection->getRootObjectCount() == 1) && 
-		(selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && 
-		selection->getFirstRootObject()->permYouOwner() &&
-		selection->getFirstRootObject()->flagObjectMove() &&
-		!((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && 
-		(selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL);
-}
-
-
-BOOL object_is_wearable()
-{
-	if (!object_selected_and_point_valid())
-	{
-		return FALSE;
-	}
-	if (sitting_on_selection())
-	{
-		return FALSE;
-	}
-	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-	for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
-		 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
-	{
-		LLSelectNode* node = *iter;		
-		if (node->mPermissions->getOwner() == gAgent.getID())
-		{
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-
-class LLAttachmentPointFilled : public view_listener_t
-{
-	bool handleEvent(const LLSD& user_data)
-	{
-		bool enable = false;
-		LLVOAvatar::attachment_map_t::iterator found_it = gAgentAvatarp->mAttachmentPoints.find(user_data.asInteger());
-		if (found_it != gAgentAvatarp->mAttachmentPoints.end())
-		{
-			enable = found_it->second->getNumObjects() > 0;
-		}
-		return enable;
-	}
-};
-
-class LLAvatarSendIM : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
-		if(avatar)
-		{
-			LLAvatarActions::startIM(avatar->getID());
-		}
-		return true;
-	}
-};
-
-class LLAvatarCall : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
-		if(avatar)
-		{
-			LLAvatarActions::startCall(avatar->getID());
-		}
-		return true;
-	}
-};
-
-namespace
-{
-	struct QueueObjects : public LLSelectedObjectFunctor
-	{
-		BOOL scripted;
-		BOOL modifiable;
-		LLFloaterScriptQueue* mQueue;
-		QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {}
-		virtual bool apply(LLViewerObject* obj)
-		{
-			scripted = obj->flagScripted();
-			modifiable = obj->permModify();
-
-			if( scripted && modifiable )
-			{
-				mQueue->addObject(obj->getID());
-				return false;
-			}
-			else
-			{
-				return true; // fail: stop applying
-			}
-		}
-	};
-}
-
-void queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
-{
-	QueueObjects func(q);
-	LLSelectMgr *mgr = LLSelectMgr::getInstance();
-	LLObjectSelectionHandle selectHandle = mgr->getSelection();
-	bool fail = selectHandle->applyToObjects(&func);
-	if(fail)
-	{
-		if ( !func.scripted )
-		{
-			std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts";
-			LLNotificationsUtil::add(noscriptmsg);
-		}
-		else if ( !func.modifiable )
-		{
-			std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission";
-			LLNotificationsUtil::add(nomodmsg);
-		}
-		else
-		{
-			llerrs << "Bad logic." << llendl;
-		}
-	}
-	else
-	{
-		if (!q->start())
-		{
-			llwarns << "Unexpected script compile failure." << llendl;
-		}
-	}
-}
-
-class LLToolsSelectedScriptAction : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string action = userdata.asString();
-		bool mono = false;
-		std::string msg, name;
-		if (action == "compile mono")
-		{
-			name = "compile_queue";
-			mono = true;
-			msg = "Recompile";
-		}
-		if (action == "compile lsl")
-		{
-			name = "compile_queue";
-			msg = "Recompile";
-		}
-		else if (action == "reset")
-		{
-			name = "reset_queue";
-			msg = "Reset";
-		}
-		else if (action == "start")
-		{
-			name = "start_queue";
-			msg = "Running";
-		}
-		else if (action == "stop")
-		{
-			name = "stop_queue";
-			msg = "RunningNot";
-		}
-		LLUUID id; id.generate();
-		
-		LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance<LLFloaterScriptQueue>(name, LLSD(id));
-		if (queue)
-		{
-			queue->setMono(mono);
-			queue_actions(queue, msg);
-		}
-		else
-		{
-			llwarns << "Failed to generate LLFloaterScriptQueue with action: " << action << llendl;
-		}
-		return true;
-	}
-};
-
-void handle_selected_texture_info(void*)
-{
-	for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
-   		iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
-	{
-		LLSelectNode* node = *iter;
-	   	
-   		std::string msg;
-   		msg.assign("Texture info for: ");
-   		msg.append(node->mName);
-
-		LLSD args;
-		args["MESSAGE"] = msg;
-		LLNotificationsUtil::add("SystemMessage", args);
-	   
-   		U8 te_count = node->getObject()->getNumTEs();
-   		// map from texture ID to list of faces using it
-   		typedef std::map< LLUUID, std::vector<U8> > map_t;
-   		map_t faces_per_texture;
-   		for (U8 i = 0; i < te_count; i++)
-   		{
-   			if (!node->isTESelected(i)) continue;
-	   
-   			LLViewerTexture* img = node->getObject()->getTEImage(i);
-   			LLUUID image_id = img->getID();
-   			faces_per_texture[image_id].push_back(i);
-   		}
-   		// Per-texture, dump which faces are using it.
-   		map_t::iterator it;
-   		for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
-   		{
-   			LLUUID image_id = it->first;
-   			U8 te = it->second[0];
-   			LLViewerTexture* img = node->getObject()->getTEImage(te);
-   			S32 height = img->getHeight();
-   			S32 width = img->getWidth();
-   			S32 components = img->getComponents();
-   			msg = llformat("%dx%d %s on face ",
-   								width,
-   								height,
-   								(components == 4 ? "alpha" : "opaque"));
-   			for (U8 i = 0; i < it->second.size(); ++i)
-   			{
-   				msg.append( llformat("%d ", (S32)(it->second[i])));
-   			}
-
-			LLSD args;
-			args["MESSAGE"] = msg;
-			LLNotificationsUtil::add("SystemMessage", args);
-   		}
-	}
-}
-
-void handle_test_male(void*)
-{
-	LLAppearanceMgr::instance().wearOutfitByName("Male Shape & Outfit");
-	//gGestureList.requestResetFromServer( TRUE );
-}
-
-void handle_test_female(void*)
-{
-	LLAppearanceMgr::instance().wearOutfitByName("Female Shape & Outfit");
-	//gGestureList.requestResetFromServer( FALSE );
-}
-
-void handle_toggle_pg(void*)
-{
-	gAgent.setTeen( !gAgent.isTeen() );
-
-	LLFloaterWorldMap::reloadIcons(NULL);
-
-	llinfos << "PG status set to " << (S32)gAgent.isTeen() << llendl;
-}
-
-void handle_dump_attachments(void*)
-{
-	if(!isAgentAvatarValid()) return;
-
-	for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); 
-		 iter != gAgentAvatarp->mAttachmentPoints.end(); )
-	{
-		LLVOAvatar::attachment_map_t::iterator curiter = iter++;
-		LLViewerJointAttachment* attachment = curiter->second;
-		S32 key = curiter->first;
-		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
-			 attachment_iter != attachment->mAttachedObjects.end();
-			 ++attachment_iter)
-		{
-			LLViewerObject *attached_object = (*attachment_iter);
-			BOOL visible = (attached_object != NULL &&
-							attached_object->mDrawable.notNull() && 
-							!attached_object->mDrawable->isRenderType(0));
-			LLVector3 pos;
-			if (visible) pos = attached_object->mDrawable->getPosition();
-			llinfos << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID()
-					<< (attached_object ? " present " : " absent ")
-					<< (visible ? "visible " : "invisible ")
-					<<  " at " << pos
-					<< " and " << (visible ? attached_object->getPosition() : LLVector3::zero)
-					<< llendl;
-		}
-	}
-}
-
-
-// these are used in the gl menus to set control values, generically.
-class LLToggleControl : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string control_name = userdata.asString();
-		BOOL checked = gSavedSettings.getBOOL( control_name );
-		gSavedSettings.setBOOL( control_name, !checked );
-		return true;
-	}
-};
-
-class LLCheckControl : public view_listener_t
-{
-	bool handleEvent( const LLSD& userdata)
-	{
-		std::string callback_data = userdata.asString();
-		bool new_value = gSavedSettings.getBOOL(callback_data);
-		return new_value;
-	}
-};
-
-// not so generic
-
-class LLAdvancedCheckRenderShadowOption: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string control_name = userdata.asString();
-		S32 current_shadow_level = gSavedSettings.getS32(control_name);
-		if (current_shadow_level == 0) // is off
-		{
-			return false;
-		}
-		else // is on
-		{
-			return true;
-		}
-	}
-};
-
-class LLAdvancedClickRenderShadowOption: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string control_name = userdata.asString();
-		S32 current_shadow_level = gSavedSettings.getS32(control_name);
-		if (current_shadow_level == 0) // upgrade to level 2
-		{
-			gSavedSettings.setS32(control_name, 2);
-		}
-		else // downgrade to level 0
-		{
-			gSavedSettings.setS32(control_name, 0);
-		}
-		return true;
-	}
-};
-
-void menu_toggle_attached_lights(void* user_data)
-{
-	LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
-}
-
-void menu_toggle_attached_particles(void* user_data)
-{
-	LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
-}
-
-class LLAdvancedHandleAttachedLightParticles: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string control_name = userdata.asString();
-
-		// toggle the control
-		gSavedSettings.setBOOL(control_name,
-				       !gSavedSettings.getBOOL(control_name));
-
-		// update internal flags
-		if (control_name == "RenderAttachedLights")
-		{
-			menu_toggle_attached_lights(NULL);
-		}
-		else if (control_name == "RenderAttachedParticles")
-		{
-			menu_toggle_attached_particles(NULL);
-		}
-		return true;
-	}
-};
-
-class LLSomethingSelected : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty());
-		return new_value;
-	}
-};
-
-class LLSomethingSelectedNoHUD : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-		bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD);
-		return new_value;
-	}
-};
-
-static bool is_editable_selected()
-{
-	return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL);
-}
-
-class LLEditableSelected : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		return is_editable_selected();
-	}
-};
-
-class LLEditableSelectedMono : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = false;
-		LLViewerRegion* region = gAgent.getRegion();
-		if(region && gMenuHolder)
-		{
-			bool have_cap = (! region->getCapability("UpdateScriptTask").empty());
-			new_value = is_editable_selected() && have_cap;
-		}
-		return new_value;
-	}
-};
-
-bool enable_object_take_copy()
-{
-	bool all_valid = false;
-	if (LLSelectMgr::getInstance())
-	{
-		if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
-		{
-		all_valid = true;
-#ifndef HACKED_GODLIKE_VIEWER
-# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-		if (LLGridManager::getInstance()->isInProductionGrid()
-            || !gAgent.isGodlike())
-# endif
-		{
-			struct f : public LLSelectedObjectFunctor
-			{
-				virtual bool apply(LLViewerObject* obj)
-				{
-					return (!obj->permCopy() || obj->isAttachment());
-				}
-			} func;
-			const bool firstonly = true;
-			bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
-			all_valid = !any_invalid;
-		}
-#endif // HACKED_GODLIKE_VIEWER
-		}
-	}
-
-	return all_valid;
-}
-
-
-class LLHasAsset : public LLInventoryCollectFunctor
-{
-public:
-	LLHasAsset(const LLUUID& id) : mAssetID(id), mHasAsset(FALSE) {}
-	virtual ~LLHasAsset() {}
-	virtual bool operator()(LLInventoryCategory* cat,
-							LLInventoryItem* item);
-	BOOL hasAsset() const { return mHasAsset; }
-
-protected:
-	LLUUID mAssetID;
-	BOOL mHasAsset;
-};
-
-bool LLHasAsset::operator()(LLInventoryCategory* cat,
-							LLInventoryItem* item)
-{
-	if(item && item->getAssetUUID() == mAssetID)
-	{
-		mHasAsset = TRUE;
-	}
-	return FALSE;
-}
-
-BOOL enable_save_into_inventory(void*)
-{
-	// *TODO: clean this up
-	// find the last root
-	LLSelectNode* last_node = NULL;
-	for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
-		 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
-	{
-		last_node = *iter;
-	}
-
-#ifdef HACKED_GODLIKE_VIEWER
-	return TRUE;
-#else
-# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-	if (!LLGridManager::getInstance()->isInProductionGrid()
-        && gAgent.isGodlike())
-	{
-		return TRUE;
-	}
-# endif
-	// check all pre-req's for save into inventory.
-	if(last_node && last_node->mValid && !last_node->mItemID.isNull()
-	   && (last_node->mPermissions->getOwner() == gAgent.getID())
-	   && (gInventory.getItem(last_node->mItemID) != NULL))
-	{
-		LLViewerObject* obj = last_node->getObject();
-		if( obj && !obj->isAttachment() )
-		{
-			return TRUE;
-		}
-	}
-#endif
-	return FALSE;
-}
-
-class LLToolsEnableSaveToInventory : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = enable_save_into_inventory(NULL);
-		return new_value;
-	}
-};
-
-BOOL enable_save_into_task_inventory(void*)
-{
-	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
-	if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
-	{
-		// *TODO: check to see if the fromtaskid object exists.
-		LLViewerObject* obj = node->getObject();
-		if( obj && !obj->isAttachment() )
-		{
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-class LLToolsEnableSaveToObjectInventory : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = enable_save_into_task_inventory(NULL);
-		return new_value;
-	}
-};
-
-
-class LLViewEnableMouselook : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// You can't go directly from customize avatar to mouselook.
-		// TODO: write code with appropriate dialogs to handle this transition.
-		bool new_value = (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && !gSavedSettings.getBOOL("FreezeTime"));
-		return new_value;
-	}
-};
-
-class LLToolsEnableToolNotPie : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() );
-		return new_value;
-	}
-};
-
-class LLWorldEnableCreateLandmark : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		return !LLLandmarkActions::landmarkAlreadyExists();
-	}
-};
-
-class LLWorldEnableSetHomeLocation : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gAgent.isGodlike() || 
-			(gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome());
-		return new_value;
-	}
-};
-
-class LLWorldEnableTeleportHome : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLViewerRegion* regionp = gAgent.getRegion();
-		bool agent_on_prelude = (regionp && regionp->isPrelude());
-		bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude;
-		return enable_teleport_home;
-	}
-};
-
-BOOL enable_god_full(void*)
-{
-	return gAgent.getGodLevel() >= GOD_FULL;
-}
-
-BOOL enable_god_liaison(void*)
-{
-	return gAgent.getGodLevel() >= GOD_LIAISON;
-}
-
-bool is_god_customer_service()
-{
-	return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE;
-}
-
-BOOL enable_god_basic(void*)
-{
-	return gAgent.getGodLevel() > GOD_NOT;
-}
-
-
-void toggle_show_xui_names(void *)
-{
-	gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames"));
-}
-
-BOOL check_show_xui_names(void *)
-{
-	return gSavedSettings.getBOOL("DebugShowXUINames");
-}
-
-class LLToolsSelectOnlyMyObjects : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		BOOL cur_val = gSavedSettings.getBOOL("SelectOwnedOnly");
-
-		gSavedSettings.setBOOL("SelectOwnedOnly", ! cur_val );
-
-		return true;
-	}
-};
-
-class LLToolsSelectOnlyMovableObjects : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		BOOL cur_val = gSavedSettings.getBOOL("SelectMovableOnly");
-
-		gSavedSettings.setBOOL("SelectMovableOnly", ! cur_val );
-
-		return true;
-	}
-};
-
-class LLToolsSelectBySurrounding : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive;
-
-		gSavedSettings.setBOOL("RectangleSelectInclusive", LLSelectMgr::sRectSelectInclusive);
-		return true;
-	}
-};
-
-class LLToolsShowHiddenSelection : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// TomY TODO Merge these
-		LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections;
-
-		gSavedSettings.setBOOL("RenderHiddenSelections", LLSelectMgr::sRenderHiddenSelections);
-		return true;
-	}
-};
-
-class LLToolsShowSelectionLightRadius : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		// TomY TODO merge these
-		LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius;
-
-		gSavedSettings.setBOOL("RenderLightRadius", LLSelectMgr::sRenderLightRadius);
-		return true;
-	}
-};
-
-class LLToolsEditLinkedParts : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		BOOL select_individuals = !gSavedSettings.getBOOL("EditLinkedParts");
-		gSavedSettings.setBOOL( "EditLinkedParts", select_individuals );
-		if (select_individuals)
-		{
-			LLSelectMgr::getInstance()->demoteSelectionToIndividuals();
-		}
-		else
-		{
-			LLSelectMgr::getInstance()->promoteSelectionToRoot();
-		}
-		return true;
-	}
-};
-
-void reload_vertex_shader(void *)
-{
-	//THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought	- DaveP
-}
-
-void handle_dump_avatar_local_textures(void*)
-{
-	gAgentAvatarp->dumpLocalTextures();
-}
-
-void handle_dump_timers()
-{
-	LLFastTimer::dumpCurTimes();
-}
-
-void handle_debug_avatar_textures(void*)
-{
-	LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
-	if (objectp)
-	{
-		LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) );
-	}
-}
-
-void handle_grab_baked_texture(void* data)
-{
-	EBakedTextureIndex baked_tex_index = (EBakedTextureIndex)((intptr_t)data);
-	if (!isAgentAvatarValid()) return;
-
-	const LLUUID& asset_id = gAgentAvatarp->grabBakedTexture(baked_tex_index);
-	LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << llendl;
-	LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE;
-	LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE;
-	const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type));
-	if(folder_id.notNull())
-	{
-		std::string name;
-		name = "Baked " + LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture";
-
-		LLUUID item_id;
-		item_id.generate();
-		LLPermissions perm;
-		perm.init(gAgentID,
-				  gAgentID,
-				  LLUUID::null,
-				  LLUUID::null);
-		U32 next_owner_perm = PERM_MOVE | PERM_TRANSFER;
-		perm.initMasks(PERM_ALL,
-					   PERM_ALL,
-					   PERM_NONE,
-					   PERM_NONE,
-					   next_owner_perm);
-		time_t creation_date_now = time_corrected();
-		LLPointer<LLViewerInventoryItem> item
-			= new LLViewerInventoryItem(item_id,
-										folder_id,
-										perm,
-										asset_id,
-										asset_type,
-										inv_type,
-										name,
-										LLStringUtil::null,
-										LLSaleInfo::DEFAULT,
-										LLInventoryItemFlags::II_FLAGS_NONE,
-										creation_date_now);
-
-		item->updateServer(TRUE);
-		gInventory.updateItem(item);
-		gInventory.notifyObservers();
-
-		// Show the preview panel for textures to let
-		// user know that the image is now in inventory.
-		LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
-		if(active_panel)
-		{
-			LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
-
-			active_panel->setSelection(item_id, TAKE_FOCUS_NO);
-			active_panel->openSelected();
-			//LLFloaterInventory::dumpSelectionInformation((void*)view);
-			// restore keyboard focus
-			gFocusMgr.setKeyboardFocus(focus_ctrl);
-		}
-	}
-	else
-	{
-		llwarns << "Can't find a folder to put it in" << llendl;
-	}
-}
-
-BOOL enable_grab_baked_texture(void* data)
-{
-	EBakedTextureIndex index = (EBakedTextureIndex)((intptr_t)data);
-	if (isAgentAvatarValid())
-	{
-		return gAgentAvatarp->canGrabBakedTexture(index);
-	}
-	return FALSE;
-}
-
-// Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing.
-// Returns NULL on failure.
-LLVOAvatar* find_avatar_from_object( LLViewerObject* object )
-{
-	if (object)
-	{
-		if( object->isAttachment() )
-		{
-			do
-			{
-				object = (LLViewerObject*) object->getParent();
-			}
-			while( object && !object->isAvatar() );
-		}
-		else if( !object->isAvatar() )
-		{
-			object = NULL;
-		}
-	}
-
-	return (LLVOAvatar*) object;
-}
-
-
-// Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing.
-// Returns NULL on failure.
-LLVOAvatar* find_avatar_from_object( const LLUUID& object_id )
-{
-	return find_avatar_from_object( gObjectList.findObject(object_id) );
-}
-
-
-void handle_disconnect_viewer(void *)
-{
-	LLAppViewer::instance()->forceDisconnect(LLTrans::getString("TestingDisconnect"));
-}
-
-void force_error_breakpoint(void *)
-{
-    LLAppViewer::instance()->forceErrorBreakpoint();
-}
-
-void force_error_llerror(void *)
-{
-    LLAppViewer::instance()->forceErrorLLError();
-}
-
-void force_error_bad_memory_access(void *)
-{
-    LLAppViewer::instance()->forceErrorBadMemoryAccess();
-}
-
-void force_error_infinite_loop(void *)
-{
-    LLAppViewer::instance()->forceErrorInfiniteLoop();
-}
-
-void force_error_software_exception(void *)
-{
-    LLAppViewer::instance()->forceErrorSoftwareException();
-}
-
-void force_error_driver_crash(void *)
-{
-    LLAppViewer::instance()->forceErrorDriverCrash();
-}
-
-class LLToolsUseSelectionForGrid : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLSelectMgr::getInstance()->clearGridObjects();
-		struct f : public LLSelectedObjectFunctor
-		{
-			virtual bool apply(LLViewerObject* objectp)
-			{
-				LLSelectMgr::getInstance()->addGridObject(objectp);
-				return true;
-			}
-		} func;
-		LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);
-		LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT);
-		if (gFloaterTools)
-		{
-			gFloaterTools->mComboGridMode->setCurrentByIndex((S32)GRID_MODE_REF_OBJECT);
-		}
-		return true;
-	}
-};
-
-void handle_test_load_url(void*)
-{
-	LLWeb::loadURL("");
-	LLWeb::loadURL("hacker://www.google.com/");
-	LLWeb::loadURL("http");
-	LLWeb::loadURL("http://www.google.com/");
-}
-
-//
-// LLViewerMenuHolderGL
-//
-static LLDefaultChildRegistry::Register<LLViewerMenuHolderGL> r("menu_holder");
-
-LLViewerMenuHolderGL::LLViewerMenuHolderGL(const LLViewerMenuHolderGL::Params& p)
-: LLMenuHolderGL(p)
-{}
-
-BOOL LLViewerMenuHolderGL::hideMenus()
-{
-	BOOL handled = LLMenuHolderGL::hideMenus();
-
-	// drop pie menu selection
-	mParcelSelection = NULL;
-	mObjectSelection = NULL;
-
-	if (gMenuBarView)
-	{
-		gMenuBarView->clearHoverItem();
-		gMenuBarView->resetMenuTrigger();
-	}
-
-	return handled;
-}
-
-void LLViewerMenuHolderGL::setParcelSelection(LLSafeHandle<LLParcelSelection> selection) 
-{ 
-	mParcelSelection = selection; 
-}
-
-void LLViewerMenuHolderGL::setObjectSelection(LLSafeHandle<LLObjectSelection> selection) 
-{ 
-	mObjectSelection = selection; 
-}
-
-
-const LLRect LLViewerMenuHolderGL::getMenuRect() const
-{
-	return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT);
-}
-
-void handle_web_browser_test(const LLSD& param)
-{
-	std::string url = param.asString();
-	if (url.empty())
-	{
-		url = "about:blank";
-	}
-	LLWeb::loadURLInternal(url);
-}
-
-void handle_web_content_test(const LLSD& param)
-{
-	std::string url = param.asString();
-	LLWeb::loadWebURLInternal(url);
-}
-
-void handle_buy_currency_test(void*)
-{
-	std::string url =
-		"http://sarahd-sl-13041.webdev.lindenlab.com/app/lindex/index.php?agent_id=[AGENT_ID]&secure_session_id=[SESSION_ID]&lang=[LANGUAGE]";
-
-	LLStringUtil::format_map_t replace;
-	replace["[AGENT_ID]"] = gAgent.getID().asString();
-	replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString();
-	replace["[LANGUAGE]"] = LLUI::getLanguage();
-	LLStringUtil::format(url, replace);
-
-	llinfos << "buy currency url " << url << llendl;
-
-	LLFloaterReg::showInstance("buy_currency_html", LLSD(url));
-}
-
-void handle_rebake_textures(void*)
-{
-	if (!isAgentAvatarValid()) return;
-
-	// Slam pending upload count to "unstick" things
-	bool slam_for_debug = true;
-	gAgentAvatarp->forceBakeAllTextures(slam_for_debug);
-}
-
-void toggle_visibility(void* user_data)
-{
-	LLView* viewp = (LLView*)user_data;
-	viewp->setVisible(!viewp->getVisible());
-}
-
-BOOL get_visibility(void* user_data)
-{
-	LLView* viewp = (LLView*)user_data;
-	return viewp->getVisible();
-}
-
-// TomY TODO: Get rid of these?
-class LLViewShowHoverTips : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips"));
-		return true;
-	}
-};
-
-class LLViewCheckShowHoverTips : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gSavedSettings.getBOOL("ShowHoverTips");
-		return new_value;
-	}
-};
-
-// TomY TODO: Get rid of these?
-class LLViewHighlightTransparent : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha;
-		return true;
-	}
-};
-
-class LLViewCheckHighlightTransparent : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLDrawPoolAlpha::sShowDebugAlpha;
-		return new_value;
-	}
-};
-
-class LLViewBeaconWidth : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string width = userdata.asString();
-		if(width == "1")
-		{
-			gSavedSettings.setS32("DebugBeaconLineWidth", 1);
-		}
-		else if(width == "4")
-		{
-			gSavedSettings.setS32("DebugBeaconLineWidth", 4);
-		}
-		else if(width == "16")
-		{
-			gSavedSettings.setS32("DebugBeaconLineWidth", 16);
-		}
-		else if(width == "32")
-		{
-			gSavedSettings.setS32("DebugBeaconLineWidth", 32);
-		}
-
-		return true;
-	}
-};
-
-
-class LLViewToggleBeacon : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string beacon = userdata.asString();
-		if (beacon == "scriptsbeacon")
-		{
-			LLPipeline::toggleRenderScriptedBeacons(NULL);
-			gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) );
-			// toggle the other one off if it's on
-			if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL))
-			{
-				LLPipeline::toggleRenderScriptedTouchBeacons(NULL);
-				gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) );
-			}
-		}
-		else if (beacon == "physicalbeacon")
-		{
-			LLPipeline::toggleRenderPhysicalBeacons(NULL);
-			gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons(NULL) );
-		}
-		else if (beacon == "soundsbeacon")
-		{
-			LLPipeline::toggleRenderSoundBeacons(NULL);
-			gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons(NULL) );
-		}
-		else if (beacon == "particlesbeacon")
-		{
-			LLPipeline::toggleRenderParticleBeacons(NULL);
-			gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons(NULL) );
-		}
-		else if (beacon == "scripttouchbeacon")
-		{
-			LLPipeline::toggleRenderScriptedTouchBeacons(NULL);
-			gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) );
-			// toggle the other one off if it's on
-			if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL))
-			{
-				LLPipeline::toggleRenderScriptedBeacons(NULL);
-				gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) );
-			}
-		}
-		else if (beacon == "renderbeacons")
-		{
-			LLPipeline::toggleRenderBeacons(NULL);
-			gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) );
-			// toggle the other one on if it's not
-			if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL))
-			{
-				LLPipeline::toggleRenderHighlights(NULL);
-				gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) );
-			}
-		}
-		else if (beacon == "renderhighlights")
-		{
-			LLPipeline::toggleRenderHighlights(NULL);
-			gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) );
-			// toggle the other one on if it's not
-			if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL))
-			{
-				LLPipeline::toggleRenderBeacons(NULL);
-				gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) );
-			}
-		}
-
-		return true;
-	}
-};
-
-class LLViewCheckBeaconEnabled : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string beacon = userdata.asString();
-		bool new_value = false;
-		if (beacon == "scriptsbeacon")
-		{
-			new_value = gSavedSettings.getBOOL( "scriptsbeacon");
-			LLPipeline::setRenderScriptedBeacons(new_value);
-		}
-		else if (beacon == "physicalbeacon")
-		{
-			new_value = gSavedSettings.getBOOL( "physicalbeacon");
-			LLPipeline::setRenderPhysicalBeacons(new_value);
-		}
-		else if (beacon == "soundsbeacon")
-		{
-			new_value = gSavedSettings.getBOOL( "soundsbeacon");
-			LLPipeline::setRenderSoundBeacons(new_value);
-		}
-		else if (beacon == "particlesbeacon")
-		{
-			new_value = gSavedSettings.getBOOL( "particlesbeacon");
-			LLPipeline::setRenderParticleBeacons(new_value);
-		}
-		else if (beacon == "scripttouchbeacon")
-		{
-			new_value = gSavedSettings.getBOOL( "scripttouchbeacon");
-			LLPipeline::setRenderScriptedTouchBeacons(new_value);
-		}
-		else if (beacon == "renderbeacons")
-		{
-			new_value = gSavedSettings.getBOOL( "renderbeacons");
-			LLPipeline::setRenderBeacons(new_value);
-		}
-		else if (beacon == "renderhighlights")
-		{
-			new_value = gSavedSettings.getBOOL( "renderhighlights");
-			LLPipeline::setRenderHighlights(new_value);
-		}
-		return new_value;
-	}
-};
-
-class LLViewToggleRenderType : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string type = userdata.asString();
-		if (type == "hideparticles")
-		{
-			LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
-		}
-		return true;
-	}
-};
-
-class LLViewCheckRenderType : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string type = userdata.asString();
-		bool new_value = false;
-		if (type == "hideparticles")
-		{
-			new_value = LLPipeline::toggleRenderTypeControlNegated((void *)LLPipeline::RENDER_TYPE_PARTICLES);
-		}
-		return new_value;
-	}
-};
-
-class LLViewShowHUDAttachments : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
-		return true;
-	}
-};
-
-class LLViewCheckHUDAttachments : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = LLPipeline::sShowHUDAttachments;
-		return new_value;
-	}
-};
-
-class LLEditEnableTakeOff : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string clothing = userdata.asString();
-		LLWearableType::EType type = LLWearableType::typeNameToType(clothing);
-		if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT)
-			return LLAgentWearables::selfHasWearable(type);
-		return false;
-	}
-};
-
-class LLEditTakeOff : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string clothing = userdata.asString();
-		if (clothing == "all")
-			LLWearableBridge::removeAllClothesFromAvatar();
-		else
-		{
-			LLWearableType::EType type = LLWearableType::typeNameToType(clothing);
-			if (type >= LLWearableType::WT_SHAPE 
-				&& type < LLWearableType::WT_COUNT
-				&& (gAgentWearables.getWearableCount(type) > 0))
-			{
-				// MULTI-WEARABLES: assuming user wanted to remove top shirt.
-				U32 wearable_index = gAgentWearables.getWearableCount(type) - 1;
-				LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(gAgentWearables.getWearableInventoryItem(type,wearable_index));
-				LLWearableBridge::removeItemFromAvatar(item);
-			}
-				
-		}
-		return true;
-	}
-};
-
-class LLToolsSelectTool : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string tool_name = userdata.asString();
-		if (tool_name == "focus")
-		{
-			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(1);
-		}
-		else if (tool_name == "move")
-		{
-			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(2);
-		}
-		else if (tool_name == "edit")
-		{
-			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(3);
-		}
-		else if (tool_name == "create")
-		{
-			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(4);
-		}
-		else if (tool_name == "land")
-		{
-			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(5);
-		}
-		return true;
-	}
-};
-
-/// WINDLIGHT callbacks
-class LLWorldEnvSettings : public view_listener_t
-{	
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string tod = userdata.asString();
-		LLVector3 sun_direction;
-		
-		if (tod == "editor")
-		{
-			// if not there or is hidden, show it
-			LLFloaterReg::toggleInstance("env_settings");
-			return true;
-		}
-		
-		if (tod == "sunrise")
-		{
-			// set the value, turn off animation
-			LLWLParamManager::instance()->mAnimator.setDayTime(0.25);
-			LLWLParamManager::instance()->mAnimator.mIsRunning = false;
-			LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
-			// then call update once
-			LLWLParamManager::instance()->mAnimator.update(
-				LLWLParamManager::instance()->mCurParams);
-		}
-		else if (tod == "noon")
-		{
-			// set the value, turn off animation
-			LLWLParamManager::instance()->mAnimator.setDayTime(0.567);
-			LLWLParamManager::instance()->mAnimator.mIsRunning = false;
-			LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
-			// then call update once
-			LLWLParamManager::instance()->mAnimator.update(
-				LLWLParamManager::instance()->mCurParams);
-		}
-		else if (tod == "sunset")
-		{
-			// set the value, turn off animation
-			LLWLParamManager::instance()->mAnimator.setDayTime(0.75);
-			LLWLParamManager::instance()->mAnimator.mIsRunning = false;
-			LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
-			// then call update once
-			LLWLParamManager::instance()->mAnimator.update(
-				LLWLParamManager::instance()->mCurParams);
-		}
-		else if (tod == "midnight")
-		{
-			// set the value, turn off animation
-			LLWLParamManager::instance()->mAnimator.setDayTime(0.0);
-			LLWLParamManager::instance()->mAnimator.mIsRunning = false;
-			LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
-
-			// then call update once
-			LLWLParamManager::instance()->mAnimator.update(
-				LLWLParamManager::instance()->mCurParams);
-		}
-		else
-		{
-			LLWLParamManager::instance()->mAnimator.mIsRunning = true;
-			LLWLParamManager::instance()->mAnimator.mUseLindenTime = true;	
-		}
-		return true;
-	}
-};
-
-/// Water Menu callbacks
-class LLWorldWaterSettings : public view_listener_t
-{	
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLFloaterReg::toggleInstance("env_water");
-		return true;
-	}
-};
-
-/// Post-Process callbacks
-class LLWorldPostProcess : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLFloaterReg::showInstance("env_post_process");
-		return true;
-	}
-};
-
-/// Day Cycle callbacks
-class LLWorldDayCycle : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLFloaterReg::showInstance("env_day_cycle");
-		return true;
-	}
-};
-
-class LLWorldToggleMovementControls : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLBottomTray::getInstance()->toggleMovementControls();
-		return true;
-	}
-};
-
-class LLWorldToggleCameraControls : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLBottomTray::getInstance()->toggleCameraControls();
-		return true;
-	}
-};
-
-void handle_flush_name_caches()
-{
-	// Toggle display names on and off to flush
-	bool use_display_names = LLAvatarNameCache::useDisplayNames();
-	LLAvatarNameCache::setUseDisplayNames(!use_display_names);
-	LLAvatarNameCache::setUseDisplayNames(use_display_names);
-
-	if (gCacheName) gCacheName->clear();
-}
-
-class LLUploadCostCalculator : public view_listener_t
-{
-	std::string mCostStr;
-
-	bool handleEvent(const LLSD& userdata)
-	{
-		std::string menu_name = userdata.asString();
-		gMenuHolder->childSetLabelArg(menu_name, "[COST]", mCostStr);
-
-		return true;
-	}
-
-	void calculateCost();
-
-public:
-	LLUploadCostCalculator()
-	{
-		calculateCost();
-	}
-};
-
-class LLToggleUIHints : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool ui_hints_enabled = gSavedSettings.getBOOL("EnableUIHints");
-		// toggle
-		ui_hints_enabled = !ui_hints_enabled;
-		gSavedSettings.setBOOL("EnableUIHints", ui_hints_enabled);
-		return true;
-	}
-};
-
-void LLUploadCostCalculator::calculateCost()
-{
-	S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
-
-	// getPriceUpload() returns -1 if no data available yet.
-	if(upload_cost >= 0)
-	{
-		mCostStr = llformat("%d", upload_cost);
-	}
-	else
-	{
-		mCostStr = llformat("%d", gSavedSettings.getU32("DefaultUploadCost"));
-	}
-}
-
-void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y)
-{
-	static LLMenuGL*	show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml",
-			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	if(gMenuHolder->hasVisibleMenu())
-	{
-		gMenuHolder->hideMenus();
-	}
-	show_navbar_context_menu->buildDrawLabels();
-	show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer);
-	LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y);
-}
-
-void show_topinfobar_context_menu(LLView* ctrl, S32 x, S32 y)
-{
-	static LLMenuGL* show_topbarinfo_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_topinfobar.xml",
-			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-
-	LLMenuItemGL* landmark_item = show_topbarinfo_context_menu->getChild<LLMenuItemGL>("Landmark");
-	if (!LLLandmarkActions::landmarkAlreadyExists())
-	{
-		landmark_item->setLabel(LLTrans::getString("AddLandmarkNavBarMenu"));
-	}
-	else
-	{
-		landmark_item->setLabel(LLTrans::getString("EditLandmarkNavBarMenu"));
-	}
-
-	if(gMenuHolder->hasVisibleMenu())
-	{
-		gMenuHolder->hideMenus();
-	}
-
-	show_topbarinfo_context_menu->buildDrawLabels();
-	show_topbarinfo_context_menu->updateParent(LLMenuGL::sMenuContainer);
-	LLMenuGL::showPopup(ctrl, show_topbarinfo_context_menu, x, y);
-}
-
-void initialize_edit_menu()
-{
-	view_listener_t::addMenu(new LLEditUndo(), "Edit.Undo");
-	view_listener_t::addMenu(new LLEditRedo(), "Edit.Redo");
-	view_listener_t::addMenu(new LLEditCut(), "Edit.Cut");
-	view_listener_t::addMenu(new LLEditCopy(), "Edit.Copy");
-	view_listener_t::addMenu(new LLEditPaste(), "Edit.Paste");
-	view_listener_t::addMenu(new LLEditDelete(), "Edit.Delete");
-	view_listener_t::addMenu(new LLEditSelectAll(), "Edit.SelectAll");
-	view_listener_t::addMenu(new LLEditDeselect(), "Edit.Deselect");
-	view_listener_t::addMenu(new LLEditDuplicate(), "Edit.Duplicate");
-	view_listener_t::addMenu(new LLEditTakeOff(), "Edit.TakeOff");
-	view_listener_t::addMenu(new LLEditEnableUndo(), "Edit.EnableUndo");
-	view_listener_t::addMenu(new LLEditEnableRedo(), "Edit.EnableRedo");
-	view_listener_t::addMenu(new LLEditEnableCut(), "Edit.EnableCut");
-	view_listener_t::addMenu(new LLEditEnableCopy(), "Edit.EnableCopy");
-	view_listener_t::addMenu(new LLEditEnablePaste(), "Edit.EnablePaste");
-	view_listener_t::addMenu(new LLEditEnableDelete(), "Edit.EnableDelete");
-	view_listener_t::addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll");
-	view_listener_t::addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect");
-	view_listener_t::addMenu(new LLEditEnableDuplicate(), "Edit.EnableDuplicate");
-
-}
-
-void initialize_menus()
-{
-	// A parameterized event handler used as ctrl-8/9/0 zoom controls below.
-	class LLZoomer : public view_listener_t
-	{
-	public:
-		// The "mult" parameter says whether "val" is a multiplier or used to set the value.
-		LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {}
-		bool handleEvent(const LLSD& userdata)
-		{
-			F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal;
-			LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad);
-			gSavedSettings.setF32("CameraAngle", LLViewerCamera::getInstance()->getView()); // setView may have clamped it.
-			return true;
-		}
-	private:
-		F32 mVal;
-		bool mMult;
-	};
-	
-	LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
-	LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
-	
-	// Generic enable and visible
-	// Don't prepend MenuName.Foo because these can be used in any menu.
-	enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service));
-
-	view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts");
-
-	// Agent
-	commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying));
-	enable.add("Agent.enableFlying", boost::bind(&LLAgent::enableFlying));
-
-	// File menu
-	init_menu_file();
-
-	view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
-	view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
-	view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape");
-	commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
-	commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
-	commit.add("EditShape", boost::bind(&handle_edit_shape));
-
-	// View menu
-	view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
-	view_listener_t::addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam");
-	view_listener_t::addMenu(new LLViewResetView(), "View.ResetView");
-	view_listener_t::addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter");
-	view_listener_t::addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips");
-	view_listener_t::addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent");
-	view_listener_t::addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType");
-	view_listener_t::addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments");
-	view_listener_t::addMenu(new LLZoomer(1.2f), "View.ZoomOut");
-	view_listener_t::addMenu(new LLZoomer(1/1.2f), "View.ZoomIn");
-	view_listener_t::addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault");
-	view_listener_t::addMenu(new LLViewDefaultUISize(), "View.DefaultUISize");
-
-	view_listener_t::addMenu(new LLViewEnableMouselook(), "View.EnableMouselook");
-	view_listener_t::addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam");
-	view_listener_t::addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter");
-
-	view_listener_t::addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam");
-	view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips");
-	view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent");
-	view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType");
-	view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
-
-	// Me > Movement
-	view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
-	
-	// World menu
-	commit.add("World.Chat", boost::bind(&handle_chat, (void*)NULL));
-	view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
-	view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
-	view_listener_t::addMenu(new LLWorldPlaceProfile(), "World.PlaceProfile");
-	view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation");
-	view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome");
-	view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway");
-	view_listener_t::addMenu(new LLWorldSetBusy(), "World.SetBusy");
-
-	view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark");
-	view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation");
-	view_listener_t::addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome");
-	view_listener_t::addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand");
-
-	view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun");
-	
-	view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings");
-	view_listener_t::addMenu(new LLWorldWaterSettings(), "World.WaterSettings");
-	view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess");
-	view_listener_t::addMenu(new LLWorldDayCycle(), "World.DayCycle");
-
-	view_listener_t::addMenu(new LLWorldToggleMovementControls(), "World.Toggle.MovementControls");
-	view_listener_t::addMenu(new LLWorldToggleCameraControls(), "World.Toggle.CameraControls");
-
-	// Tools menu
-	view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
-	view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
-	view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
-	view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
-	view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
-	view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
-	view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts");
-	view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY");
-	view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid");
-	view_listener_t::addMenu(new LLToolsSelectNextPart(), "Tools.SelectNextPart");
-	commit.add("Tools.Link", boost::bind(&LLSelectMgr::linkObjects, LLSelectMgr::getInstance()));
-	commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance()));
-	view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations");
-	view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");
-	view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys");	
-	commit.add("Tools.LookAtSelection", boost::bind(&handle_look_at_selection, _2));
-	commit.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take));
-	commit.add("Tools.TakeCopy", boost::bind(&handle_take_copy));
-	view_listener_t::addMenu(new LLToolsSaveToInventory(), "Tools.SaveToInventory");
-	view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory");
-	view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction");
-
-	view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie");
-	view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart");
-	enable.add("Tools.EnableLink", boost::bind(&LLSelectMgr::enableLinkObjects, LLSelectMgr::getInstance()));
-	enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance()));
-	view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
-	enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
-	enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object));
-	enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object));
-	view_listener_t::addMenu(new LLToolsEnableSaveToInventory(), "Tools.EnableSaveToInventory");
-	view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
-
-	// Help menu
-	// most items use the ShowFloater method
-
-	// Advanced menu
-	view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
-	view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole");
-	view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole");
-	
-	// Advanced > HUD Info
-	view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo");
-	view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo");
-
-	// Advanced Other Settings	
-	view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache");
-	
-	// Advanced > Render > Types
-	view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType");
-	view_listener_t::addMenu(new LLAdvancedCheckRenderType(), "Advanced.CheckRenderType");
-
-	//// Advanced > Render > Features
-	view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature");
-	view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature");
-	// Advanced > Render > Info Displays
-	view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay");
-	view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay");
-	view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo");
-	view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe");
-	view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
-	// Develop > Render
-	view_listener_t::addMenu(new LLAdvancedToggleTextureAtlas(), "Advanced.ToggleTextureAtlas");
-	view_listener_t::addMenu(new LLAdvancedCheckTextureAtlas(), "Advanced.CheckTextureAtlas");
-	view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion");
-	view_listener_t::addMenu(new LLAdvancedEnableRenderFBO(), "Advanced.EnableRenderFBO");
-	view_listener_t::addMenu(new LLAdvancedEnableRenderDeferred(), "Advanced.EnableRenderDeferred");
-	view_listener_t::addMenu(new LLAdvancedEnableRenderDeferredOptions(), "Advanced.EnableRenderDeferredOptions");
-	view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");
-	view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
-	view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
-	view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame");
-	view_listener_t::addMenu(new LLAdvancedVectorizePerfTest(), "Advanced.VectorizePerfTest");
-	view_listener_t::addMenu(new LLAdvancedToggleFrameTest(), "Advanced.ToggleFrameTest");
-	view_listener_t::addMenu(new LLAdvancedCheckFrameTest(), "Advanced.CheckFrameTest");
-	view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles");
-	view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption");
-	view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption");
-	
-
-	#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
-	view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode");
-	view_listener_t::addMenu(new LLAdvancedCheckToggleHackedGodmode(), "Advanced.CheckToggleHackedGodmode");
-	view_listener_t::addMenu(new LLAdvancedEnableToggleHackedGodmode(), "Advanced.EnableToggleHackedGodmode");
-	#endif
-
-	// Advanced > World
-	view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera");
-	view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache");
-
-	// Advanced > UI
-	commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test,	_2));	// sigh! this one opens the MEDIA browser
-	commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2));	// this one opens the Web Content floater
-	view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest");
-	view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr");
-	view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory");
-	commit.add("Advanced.DumpTimers", boost::bind(&handle_dump_timers) );
-	commit.add("Advanced.DumpFocusHolder", boost::bind(&handle_dump_focus) );
-	view_listener_t::addMenu(new LLAdvancedPrintSelectedObjectInfo(), "Advanced.PrintSelectedObjectInfo");
-	view_listener_t::addMenu(new LLAdvancedPrintAgentInfo(), "Advanced.PrintAgentInfo");
-	view_listener_t::addMenu(new LLAdvancedPrintTextureMemoryStats(), "Advanced.PrintTextureMemoryStats");
-	view_listener_t::addMenu(new LLAdvancedToggleDebugClicks(), "Advanced.ToggleDebugClicks");
-	view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks");
-	view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews");
-	view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews");
-	view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips");
-	view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips");
-	view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents");
-	view_listener_t::addMenu(new LLAdvancedCheckDebugMouseEvents(), "Advanced.CheckDebugMouseEvents");
-	view_listener_t::addMenu(new LLAdvancedToggleDebugKeys(), "Advanced.ToggleDebugKeys");
-	view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys");
-	view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc");
-	view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc");
-	commit.add("Advanced.ShowSideTray", boost::bind(&handle_show_side_tray));
-
-	// Advanced > XUI
-	commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance()));
-	view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
-	view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
-	view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
-	commit.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches));
-
-	// Advanced > Character > Grab Baked Texture
-	view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture");
-	view_listener_t::addMenu(new LLAdvancedEnableGrabBakedTexture(), "Advanced.EnableGrabBakedTexture");
-
-	// Advanced > Character > Character Tests
-	view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML");
-	view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry");
-
-	view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale");
-	view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale");
-	view_listener_t::addMenu(new LLAdvancedTogglePG(), "Advanced.TogglePG");
-	
-	// Advanced > Character (toplevel)
-	view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault");
-	view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader");
-	view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo");
-	view_listener_t::addMenu(new LLAdvancedCheckAnimationInfo(), "Advanced.CheckAnimationInfo");
-	view_listener_t::addMenu(new LLAdvancedToggleShowLookAt(), "Advanced.ToggleShowLookAt");
-	view_listener_t::addMenu(new LLAdvancedCheckShowLookAt(), "Advanced.CheckShowLookAt");
-	view_listener_t::addMenu(new LLAdvancedToggleShowPointAt(), "Advanced.ToggleShowPointAt");
-	view_listener_t::addMenu(new LLAdvancedCheckShowPointAt(), "Advanced.CheckShowPointAt");
-	view_listener_t::addMenu(new LLAdvancedToggleDebugJointUpdates(), "Advanced.ToggleDebugJointUpdates");
-	view_listener_t::addMenu(new LLAdvancedCheckDebugJointUpdates(), "Advanced.CheckDebugJointUpdates");
-	view_listener_t::addMenu(new LLAdvancedToggleDisableLOD(), "Advanced.ToggleDisableLOD");
-	view_listener_t::addMenu(new LLAdvancedCheckDisableLOD(), "Advanced.CheckDisableLOD");
-	view_listener_t::addMenu(new LLAdvancedToggleDebugCharacterVis(), "Advanced.ToggleDebugCharacterVis");
-	view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis");
-	view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments");
-	view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures");
-	view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures");
-	view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures");
-	// Advanced > Network
-	view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog");
-	view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog");
-	view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket");
-
-	// Advanced > Recorder
-	view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot");
-	view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop");
-	view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop");
-
-	// Advanced > Debugging
-	view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint");
-	view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror");
-	view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess");
-	view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
-	view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException");
-	view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash");
-	view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer");
-
-	// Advanced (toplevel)
-	view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates");
-	view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates");
-	view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage");
-	view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");
-	view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions");
-	view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions");
-	view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions");
-	view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus");
-	view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus");
-
-
-	// Admin >Object
-	view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
-	view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf");
-	view_listener_t::addMenu(new LLAdminHandleObjectOwnerPermissive(), "Admin.HandleObjectOwnerPermissive");
-	view_listener_t::addMenu(new LLAdminHandleForceDelete(), "Admin.HandleForceDelete");
-	view_listener_t::addMenu(new LLAdminHandleObjectLock(), "Admin.HandleObjectLock");
-	view_listener_t::addMenu(new LLAdminHandleObjectAssetIDs(), "Admin.HandleObjectAssetIDs");
-
-	// Admin >Parcel 
-	view_listener_t::addMenu(new LLAdminHandleForceParcelOwnerToMe(), "Admin.HandleForceParcelOwnerToMe");
-	view_listener_t::addMenu(new LLAdminHandleForceParcelToContent(), "Admin.HandleForceParcelToContent");
-	view_listener_t::addMenu(new LLAdminHandleClaimPublicLand(), "Admin.HandleClaimPublicLand");
-
-	// Admin >Region
-	view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData");
-	// Admin top level
-	view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState");
-
-	// Self context menu
-	view_listener_t::addMenu(new LLSelfStandUp(), "Self.StandUp");
-	enable.add("Self.EnableStandUp", boost::bind(&enable_standup_self));
-	view_listener_t::addMenu(new LLSelfSitDown(), "Self.SitDown");
-	enable.add("Self.EnableSitDown", boost::bind(&enable_sitdown_self));
-	view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments");
-
-	view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments");
-
-	// we don't use boost::bind directly to delay side tray construction
-	view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab");
-
-	 // Avatar pie menu
-	view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");
-	view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
-	view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact");
-	commit.add("Avatar.Freeze", boost::bind(&handle_avatar_freeze, LLSD()));
-	view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug");
-	view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
-	view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
-	commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
-	commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector));
-	view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
-	view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
-	enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall));
-	view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
-	
-	view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
-	enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2));
-
-	// Object pie menu
-	view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
-	commit.add("Object.Touch", boost::bind(&handle_object_touch));
-	commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));
-	commit.add("Object.Delete", boost::bind(&handle_object_delete));
-	view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar");
-	view_listener_t::addMenu(new LLObjectAttachToAvatar(false), "Object.AttachAddToAvatar");
-	view_listener_t::addMenu(new LLObjectReturn(), "Object.Return");
-	view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse");
-	view_listener_t::addMenu(new LLObjectMute(), "Object.Mute");
-
-	enable.add("Object.VisibleTake", boost::bind(&visible_take_object));
-	enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object));
-
-	commit.add("Object.Buy", boost::bind(&handle_buy));
-	commit.add("Object.Edit", boost::bind(&handle_object_edit));
-	commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
-	commit.add("Object.Open", boost::bind(&handle_object_open));
-	commit.add("Object.Take", boost::bind(&handle_take));
-	commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
-	enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
-	enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1));
-	enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
-	enable.add("Object.EnableWear", boost::bind(&object_selected_and_point_valid));
-
-	enable.add("Object.EnableStandUp", boost::bind(&enable_object_stand_up));
-	enable.add("Object.EnableSit", boost::bind(&enable_object_sit, _1));
-
-	view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn");
-	view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
-
-	enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));
-	enable.add("Object.EnableMute", boost::bind(&enable_object_mute));
-	enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));
-	commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom"));
-
-	// Attachment pie menu
-	enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2));
-	view_listener_t::addMenu(new LLAttachmentDrop(), "Attachment.Drop");
-	view_listener_t::addMenu(new LLAttachmentDetachFromPoint(), "Attachment.DetachFromPoint");
-	view_listener_t::addMenu(new LLAttachmentDetach(), "Attachment.Detach");
-	view_listener_t::addMenu(new LLAttachmentPointFilled(), "Attachment.PointFilled");
-	view_listener_t::addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop");
-	view_listener_t::addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach");
-
-	// Land pie menu
-	view_listener_t::addMenu(new LLLandBuild(), "Land.Build");
-	view_listener_t::addMenu(new LLLandSit(), "Land.Sit");
-	view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass");
-	view_listener_t::addMenu(new LLLandEdit(), "Land.Edit");
-
-	view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass");
-	commit.add("Land.Buy", boost::bind(&handle_buy_land));
-
-	// Generic actions
-	commit.add("ReportAbuse", boost::bind(&handle_report_abuse));
-	commit.add("BuyCurrency", boost::bind(&handle_buy_currency));
-	view_listener_t::addMenu(new LLShowHelp(), "ShowHelp");
-	view_listener_t::addMenu(new LLToggleHelp(), "ToggleHelp");
-	view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL");
-	view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile");
-	view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile");
-	view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");
-	view_listener_t::addMenu(new LLCheckControl(), "CheckControl");
-	view_listener_t::addMenu(new LLGoToObject(), "GoToObject");
-	commit.add("PayObject", boost::bind(&handle_give_money_dialog));
-
-	enable.add("EnablePayObject", boost::bind(&enable_pay_object));
-	enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar));
-	enable.add("EnableEdit", boost::bind(&enable_object_edit));
-	enable.add("VisibleBuild", boost::bind(&enable_object_build));
-
-	view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible");
-	view_listener_t::addMenu(new LLShowSidetrayPanel(), "ShowSidetrayPanel");
-	view_listener_t::addMenu(new LLSidetrayPanelVisible(), "SidetrayPanelVisible");
-	view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected");
-	view_listener_t::addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD");
-	view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected");
-	view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono");
-
-	view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints");
-
-	commit.add("Destination.show", boost::bind(&toggle_destination_and_avatar_picker, 0));
-	commit.add("Avatar.show", boost::bind(&toggle_destination_and_avatar_picker, 1));
-}
+/** 
+ * @file llviewermenu.cpp
+ * @brief Builds menus out of items.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llviewermenu.h" 
+
+// linden library includes
+#include "llavatarnamecache.h"	// IDEVO
+#include "llfloaterreg.h"
+#include "llcombobox.h"
+#include "llinventorypanel.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+
+// newview includes
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llagentwearables.h"
+#include "llagentpilot.h"
+#include "llbottomtray.h"
+#include "llcompilequeue.h"
+#include "llconsole.h"
+#include "lldebugview.h"
+#include "llfilepicker.h"
+#include "llfirstuse.h"
+#include "llfloaterbuy.h"
+#include "llfloaterbuycontents.h"
+#include "llbuycurrencyhtml.h"
+#include "llfloatergodtools.h"
+#include "llfloaterinventory.h"
+#include "llfloaterland.h"
+#include "llfloaterpay.h"
+#include "llfloaterreporter.h"
+#include "llfloatersearch.h"
+#include "llfloaterscriptdebug.h"
+#include "llfloatersnapshot.h"
+#include "llfloatertools.h"
+#include "llfloaterworldmap.h"
+#include "llavataractions.h"
+#include "lllandmarkactions.h"
+#include "llgroupmgr.h"
+#include "lltooltip.h"
+#include "llhints.h"
+#include "llhudeffecttrail.h"
+#include "llhudmanager.h"
+#include "llimview.h"
+#include "llinventorybridge.h"
+#include "llinventorydefines.h"
+#include "llinventoryfunctions.h"
+#include "llpanellogin.h"
+#include "llpanelblockedlist.h"
+#include "llmenucommands.h"
+#include "llmoveview.h"
+#include "llparcel.h"
+#include "llrootview.h"
+#include "llselectmgr.h"
+#include "llsidetray.h"
+#include "llstatusbar.h"
+#include "lltextureview.h"
+#include "lltoolcomp.h"
+#include "lltoolmgr.h"
+#include "lltoolpie.h"
+#include "lltoolselectland.h"
+#include "lltrans.h"
+#include "llviewergenericmessage.h"
+#include "llviewerhelp.h"
+#include "llviewermenufile.h"	// init_menu_file()
+#include "llviewermessage.h"
+#include "llviewernetwork.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerstats.h"
+#include "llvoavatarself.h"
+#include "llworldmap.h"
+#include "pipeline.h"
+#include "llviewerjoystick.h"
+#include "llwlanimator.h"
+#include "llwlparammanager.h"
+#include "llfloatercamera.h"
+#include "lluilistener.h"
+#include "llappearancemgr.h"
+#include "lltrans.h"
+#include "lleconomy.h"
+#include "boost/unordered_map.hpp"
+
+using namespace LLVOAvatarDefines;
+
+static boost::unordered_map<std::string, LLStringExplicit> sDefaultItemLabels;
+
+BOOL enable_land_build(void*);
+BOOL enable_object_build(void*);
+
+LLVOAvatar* find_avatar_from_object( LLViewerObject* object );
+LLVOAvatar* find_avatar_from_object( const LLUUID& object_id );
+
+void handle_test_load_url(void*);
+
+//
+// Evil hackish imported globals
+
+//extern BOOL	gHideSelectedObjects;
+//extern BOOL gAllowSelectAvatar;
+//extern BOOL gDebugAvatarRotation;
+extern BOOL gDebugClicks;
+extern BOOL gDebugWindowProc;
+//extern BOOL gDebugTextEditorTips;
+//extern BOOL gDebugSelectMgr;
+
+//
+// Globals
+//
+
+LLMenuBarGL		*gMenuBarView = NULL;
+LLViewerMenuHolderGL	*gMenuHolder = NULL;
+LLMenuGL		*gPopupMenuView = NULL;
+LLMenuGL		*gEditMenu = NULL;
+LLMenuBarGL		*gLoginMenuBarView = NULL;
+
+// Pie menus
+LLContextMenu	*gMenuAvatarSelf	= NULL;
+LLContextMenu	*gMenuAvatarOther = NULL;
+LLContextMenu	*gMenuObject = NULL;
+LLContextMenu	*gMenuAttachmentSelf = NULL;
+LLContextMenu	*gMenuAttachmentOther = NULL;
+LLContextMenu	*gMenuLand	= NULL;
+
+const std::string SAVE_INTO_INVENTORY("Save Object Back to My Inventory");
+const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents");
+
+LLMenuGL* gAttachSubMenu = NULL;
+LLMenuGL* gDetachSubMenu = NULL;
+LLMenuGL* gTakeOffClothes = NULL;
+LLContextMenu* gAttachScreenPieMenu = NULL;
+LLContextMenu* gAttachPieMenu = NULL;
+LLContextMenu* gAttachBodyPartPieMenus[8];
+LLContextMenu* gDetachPieMenu = NULL;
+LLContextMenu* gDetachScreenPieMenu = NULL;
+LLContextMenu* gDetachBodyPartPieMenus[8];
+
+LLMenuItemCallGL* gAFKMenu = NULL;
+LLMenuItemCallGL* gBusyMenu = NULL;
+
+//
+// Local prototypes
+
+// File Menu
+const char* upload_pick(void* data);
+void handle_compress_image(void*);
+
+
+// Edit menu
+void handle_dump_group_info(void *);
+void handle_dump_capabilities_info(void *);
+
+// Advanced->Consoles menu
+void handle_region_dump_settings(void*);
+void handle_region_dump_temp_asset_data(void*);
+void handle_region_clear_temp_asset_data(void*);
+
+// Object pie menu
+BOOL sitting_on_selection();
+
+void near_sit_object();
+//void label_sit_or_stand(std::string& label, void*);
+// buy and take alias into the same UI positions, so these
+// declarations handle this mess.
+BOOL is_selection_buy_not_take();
+S32 selection_price();
+BOOL enable_take();
+void handle_take();
+void handle_object_show_inspector();
+void handle_avatar_show_inspector();
+bool confirm_take(const LLSD& notification, const LLSD& response);
+
+void handle_buy_object(LLSaleInfo sale_info);
+void handle_buy_contents(LLSaleInfo sale_info);
+
+// Land pie menu
+void near_sit_down_point(BOOL success, void *);
+
+// Avatar pie menu
+
+// Debug menu
+
+
+void velocity_interpolate( void* );
+
+void handle_rebake_textures(void*);
+BOOL check_admin_override(void*);
+void handle_admin_override_toggle(void*);
+#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+void handle_toggle_hacked_godmode(void*);
+BOOL check_toggle_hacked_godmode(void*);
+bool enable_toggle_hacked_godmode(void*);
+#endif
+
+void toggle_show_xui_names(void *);
+BOOL check_show_xui_names(void *);
+
+// Debug UI
+
+void handle_buy_currency_test(void*);
+
+void handle_god_mode(void*);
+
+// God menu
+void handle_leave_god_mode(void*);
+
+
+void handle_reset_view();
+
+void handle_duplicate_in_place(void*);
+
+
+void handle_object_owner_self(void*);
+void handle_object_owner_permissive(void*);
+void handle_object_lock(void*);
+void handle_object_asset_ids(void*);
+void force_take_copy(void*);
+#ifdef _CORY_TESTING
+void force_export_copy(void*);
+void force_import_geometry(void*);
+#endif
+
+void handle_force_parcel_owner_to_me(void*);
+void handle_force_parcel_to_content(void*);
+void handle_claim_public_land(void*);
+
+void handle_god_request_avatar_geometry(void *);	// Hack for easy testing of new avatar geometry
+void reload_vertex_shader(void *);
+void handle_disconnect_viewer(void *);
+
+void force_error_breakpoint(void *);
+void force_error_llerror(void *);
+void force_error_bad_memory_access(void *);
+void force_error_infinite_loop(void *);
+void force_error_software_exception(void *);
+void force_error_driver_crash(void *);
+
+void handle_force_delete(void*);
+void print_object_info(void*);
+void print_agent_nvpairs(void*);
+void toggle_debug_menus(void*);
+void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status);
+void dump_select_mgr(void*);
+
+void dump_inventory(void*);
+void toggle_visibility(void*);
+BOOL get_visibility(void*);
+
+// Avatar Pie menu
+void request_friendship(const LLUUID& agent_id);
+
+// Tools menu
+void handle_selected_texture_info(void*);
+
+void handle_dump_followcam(void*);
+void handle_viewer_enable_message_log(void*);
+void handle_viewer_disable_message_log(void*);
+
+BOOL enable_buy_land(void*);
+
+// Help menu
+
+void handle_test_male(void *);
+void handle_test_female(void *);
+void handle_toggle_pg(void*);
+void handle_dump_attachments(void *);
+void handle_dump_avatar_local_textures(void*);
+void handle_debug_avatar_textures(void*);
+void handle_grab_baked_texture(void*);
+BOOL enable_grab_baked_texture(void*);
+void handle_dump_region_object_cache(void*);
+
+BOOL enable_save_into_inventory(void*);
+BOOL enable_save_into_task_inventory(void*);
+
+BOOL enable_detach(const LLSD& = LLSD());
+void menu_toggle_attached_lights(void* user_data);
+void menu_toggle_attached_particles(void* user_data);
+
+class LLMenuParcelObserver : public LLParcelObserver
+{
+public:
+	LLMenuParcelObserver();
+	~LLMenuParcelObserver();
+	virtual void changed();
+};
+
+static LLMenuParcelObserver* gMenuParcelObserver = NULL;
+
+static LLUIListener sUIListener;
+
+LLMenuParcelObserver::LLMenuParcelObserver()
+{
+	LLViewerParcelMgr::getInstance()->addObserver(this);
+}
+
+LLMenuParcelObserver::~LLMenuParcelObserver()
+{
+	LLViewerParcelMgr::getInstance()->removeObserver(this);
+}
+
+void LLMenuParcelObserver::changed()
+{
+	gMenuHolder->childSetEnabled("Land Buy Pass", LLPanelLandGeneral::enableBuyPass(NULL));
+	
+	BOOL buyable = enable_buy_land(NULL);
+	gMenuHolder->childSetEnabled("Land Buy", buyable);
+	gMenuHolder->childSetEnabled("Buy Land...", buyable);
+}
+
+
+void initialize_menus();
+
+//-----------------------------------------------------------------------------
+// Initialize main menus
+//
+// HOW TO NAME MENUS:
+//
+// First Letter Of Each Word Is Capitalized, Even At Or And
+//
+// Items that lead to dialog boxes end in "..."
+//
+// Break up groups of more than 6 items with separators
+//-----------------------------------------------------------------------------
+
+void set_underclothes_menu_options()
+{
+	if (gMenuHolder && gAgent.isTeen())
+	{
+		gMenuHolder->getChild<LLView>("Self Underpants")->setVisible(FALSE);
+		gMenuHolder->getChild<LLView>("Self Undershirt")->setVisible(FALSE);
+	}
+	if (gMenuBarView && gAgent.isTeen())
+	{
+		gMenuBarView->getChild<LLView>("Menu Underpants")->setVisible(FALSE);
+		gMenuBarView->getChild<LLView>("Menu Undershirt")->setVisible(FALSE);
+	}
+}
+
+void init_menus()
+{
+	S32 top = gViewerWindow->getRootView()->getRect().getHeight();
+
+	// Initialize actions
+	initialize_menus();
+
+	///
+	/// Popup menu
+	///
+	/// The popup menu is now populated by the show_context_menu()
+	/// method.
+	
+	LLMenuGL::Params menu_params;
+	menu_params.name = "Popup";
+	menu_params.visible = false;
+	gPopupMenuView = LLUICtrlFactory::create<LLMenuGL>(menu_params);
+	gMenuHolder->addChild( gPopupMenuView );
+
+	///
+	/// Context menus
+	///
+
+	const widget_registry_t& registry =
+		LLViewerMenuHolderGL::child_registry_t::instance();
+	gEditMenu = LLUICtrlFactory::createFromFile<LLMenuGL>("menu_edit.xml", gMenuHolder, registry);
+	gMenuAvatarSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
+		"menu_avatar_self.xml", gMenuHolder, registry);
+	gMenuAvatarOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
+		"menu_avatar_other.xml", gMenuHolder, registry);
+
+	gDetachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach HUD", true);
+	gDetachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Detach", true);
+
+	gMenuObject = LLUICtrlFactory::createFromFile<LLContextMenu>(
+		"menu_object.xml", gMenuHolder, registry);
+
+	gAttachScreenPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach HUD");
+	gAttachPieMenu = gMenuHolder->getChild<LLContextMenu>("Object Attach");
+
+	gMenuAttachmentSelf = LLUICtrlFactory::createFromFile<LLContextMenu>(
+		"menu_attachment_self.xml", gMenuHolder, registry);
+	gMenuAttachmentOther = LLUICtrlFactory::createFromFile<LLContextMenu>(
+		"menu_attachment_other.xml", gMenuHolder, registry);
+
+	gMenuLand = LLUICtrlFactory::createFromFile<LLContextMenu>(
+		"menu_land.xml", gMenuHolder, registry);
+
+	///
+	/// set up the colors
+	///
+	LLColor4 color;
+
+	LLColor4 context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor");
+	
+	gMenuAvatarSelf->setBackgroundColor( context_menu_color );
+	gMenuAvatarOther->setBackgroundColor( context_menu_color );
+	gMenuObject->setBackgroundColor( context_menu_color );
+	gMenuAttachmentSelf->setBackgroundColor( context_menu_color );
+	gMenuAttachmentOther->setBackgroundColor( context_menu_color );
+
+	gMenuLand->setBackgroundColor( context_menu_color );
+
+	color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" );
+	gPopupMenuView->setBackgroundColor( color );
+
+	// If we are not in production, use a different color to make it apparent.
+	if (LLGridManager::getInstance()->isInProductionGrid())
+	{
+		color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
+	}
+	else
+	{
+		color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
+	}
+	gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	gMenuBarView->setRect(LLRect(0, top, 0, top - MENU_BAR_HEIGHT));
+	gMenuBarView->setBackgroundColor( color );
+
+	LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder");
+	menu_bar_holder->addChild(gMenuBarView);
+  
+    gViewerWindow->setMenuBackgroundColor(false, 
+        LLGridManager::getInstance()->isInProductionGrid());
+
+	// Assume L$10 for now, the server will tell us the real cost at login
+	// *TODO:Also fix cost in llfolderview.cpp for Inventory menus
+	const std::string upload_cost("10");
+	gMenuHolder->childSetLabelArg("Upload Image", "[COST]", upload_cost);
+	gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", upload_cost);
+	gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", upload_cost);
+	gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", upload_cost);
+
+	gAFKMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Away", TRUE);
+	gBusyMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Busy", TRUE);
+	gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE);
+	gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE);
+
+#if !MEM_TRACK_MEM
+	// Don't display the Memory console menu if the feature is turned off
+	LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild<LLMenuItemCheckGL>("Memory", TRUE);
+	if (memoryMenu)
+	{
+		memoryMenu->setVisible(FALSE);
+	}
+#endif
+
+	gMenuBarView->createJumpKeys();
+
+	// Let land based option enable when parcel changes
+	gMenuParcelObserver = new LLMenuParcelObserver();
+
+	gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile<LLMenuBarGL>("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	gLoginMenuBarView->arrangeAndClear();
+	LLRect menuBarRect = gLoginMenuBarView->getRect();
+	menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight());
+	gLoginMenuBarView->setRect(menuBarRect);
+	gLoginMenuBarView->setBackgroundColor( color );
+	menu_bar_holder->addChild(gLoginMenuBarView);
+	
+	// tooltips are on top of EVERYTHING, including menus
+	gViewerWindow->getRootView()->sendChildToFront(gToolTipView);
+}
+
+///////////////////
+// SHOW CONSOLES //
+///////////////////
+
+
+class LLAdvancedToggleConsole : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string console_type = userdata.asString();
+		if ("texture" == console_type)
+		{
+			toggle_visibility( (void*)gTextureView );
+		}
+		else if ("debug" == console_type)
+		{
+			toggle_visibility( (void*)static_cast<LLUICtrl*>(gDebugView->mDebugConsolep));
+		}
+		else if (gTextureSizeView && "texture size" == console_type)
+		{
+			toggle_visibility( (void*)gTextureSizeView );
+		}
+		else if (gTextureCategoryView && "texture category" == console_type)
+		{
+			toggle_visibility( (void*)gTextureCategoryView );
+		}
+		else if ("fast timers" == console_type)
+		{
+			toggle_visibility( (void*)gDebugView->mFastTimerView );
+		}
+#if MEM_TRACK_MEM
+		else if ("memory view" == console_type)
+		{
+			toggle_visibility( (void*)gDebugView->mMemoryView );
+		}
+#endif
+		return true;
+	}
+};
+class LLAdvancedCheckConsole : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string console_type = userdata.asString();
+		bool new_value = false;
+		if ("texture" == console_type)
+		{
+			new_value = get_visibility( (void*)gTextureView );
+		}
+		else if ("debug" == console_type)
+		{
+			new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) );
+		}
+		else if (gTextureSizeView && "texture size" == console_type)
+		{
+			new_value = get_visibility( (void*)gTextureSizeView );
+		}
+		else if (gTextureCategoryView && "texture category" == console_type)
+		{
+			new_value = get_visibility( (void*)gTextureCategoryView );
+		}
+		else if ("fast timers" == console_type)
+		{
+			new_value = get_visibility( (void*)gDebugView->mFastTimerView );
+		}
+#if MEM_TRACK_MEM
+		else if ("memory view" == console_type)
+		{
+			new_value = get_visibility( (void*)gDebugView->mMemoryView );
+		}
+#endif
+		
+		return new_value;
+	}
+};
+
+
+//////////////////////////
+// DUMP INFO TO CONSOLE //
+//////////////////////////
+
+
+class LLAdvancedDumpInfoToConsole : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string info_type = userdata.asString();
+		if ("region" == info_type)
+		{
+			handle_region_dump_settings(NULL);
+		}
+		else if ("group" == info_type)
+		{
+			handle_dump_group_info(NULL);
+		}
+		else if ("capabilities" == info_type)
+		{
+			handle_dump_capabilities_info(NULL);
+		}
+		return true;
+	}
+};
+
+
+//////////////
+// HUD INFO //
+//////////////
+
+
+class LLAdvancedToggleHUDInfo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string info_type = userdata.asString();
+
+		if ("camera" == info_type)
+		{
+			gDisplayCameraPos = !(gDisplayCameraPos);
+		}
+		else if ("wind" == info_type)
+		{
+			gDisplayWindInfo = !(gDisplayWindInfo);
+		}
+		else if ("fov" == info_type)
+		{
+			gDisplayFOV = !(gDisplayFOV);
+		}
+		else if ("badge" == info_type)
+		{
+			gDisplayBadge = !(gDisplayBadge);
+		}
+		return true;
+	}
+};
+
+class LLAdvancedCheckHUDInfo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string info_type = userdata.asString();
+		bool new_value = false;
+		if ("camera" == info_type)
+		{
+			new_value = gDisplayCameraPos;
+		}
+		else if ("wind" == info_type)
+		{
+			new_value = gDisplayWindInfo;
+		}
+		else if ("fov" == info_type)
+		{
+			new_value = gDisplayFOV;
+		}
+		else if ("badge" == info_type)
+		{
+			new_value = gDisplayBadge;
+		}
+		return new_value;
+	}
+};
+
+
+//////////////
+// FLYING   //
+//////////////
+
+class LLAdvancedAgentFlyingInfo : public view_listener_t
+{
+	bool handleEvent(const LLSD&)
+	{
+		return gAgent.getFlying();
+	}
+};
+
+
+///////////////////////
+// CLEAR GROUP CACHE //
+///////////////////////
+
+class LLAdvancedClearGroupCache : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLGroupMgr::debugClearAllGroups(NULL);
+		return true;
+	}
+};
+
+
+
+
+/////////////////
+// RENDER TYPE //
+/////////////////
+U32 render_type_from_string(std::string render_type)
+{
+	if ("simple" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_SIMPLE;
+	}
+	else if ("alpha" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_ALPHA;
+	}
+	else if ("tree" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_TREE;
+	}
+	else if ("character" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_AVATAR;
+	}
+	else if ("surfacePath" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_TERRAIN;
+	}
+	else if ("sky" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_SKY;
+	}
+	else if ("water" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_WATER;
+	}
+	else if ("ground" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_GROUND;
+	}
+	else if ("volume" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_VOLUME;
+	}
+	else if ("grass" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_GRASS;
+	}
+	else if ("clouds" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_CLOUDS;
+	}
+	else if ("particles" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_PARTICLES;
+	}
+	else if ("bump" == render_type)
+	{
+		return LLPipeline::RENDER_TYPE_BUMP;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+
+class LLAdvancedToggleRenderType : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		U32 render_type = render_type_from_string( userdata.asString() );
+		if ( render_type != 0 )
+		{
+			LLPipeline::toggleRenderTypeControl( (void*)render_type );
+		}
+		return true;
+	}
+};
+
+
+class LLAdvancedCheckRenderType : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		U32 render_type = render_type_from_string( userdata.asString() );
+		bool new_value = false;
+
+		if ( render_type != 0 )
+		{
+			new_value = LLPipeline::hasRenderTypeControl( (void*)render_type );
+		}
+
+		return new_value;
+	}
+};
+
+
+/////////////
+// FEATURE //
+/////////////
+U32 feature_from_string(std::string feature)
+{ 
+	if ("ui" == feature)
+	{ 
+		return LLPipeline::RENDER_DEBUG_FEATURE_UI;
+	}
+	else if ("selected" == feature)
+	{
+		return LLPipeline::RENDER_DEBUG_FEATURE_SELECTED;
+	}
+	else if ("highlighted" == feature)
+	{
+		return LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED;
+	}
+	else if ("dynamic textures" == feature)
+	{
+		return LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES;
+	}
+	else if ("foot shadows" == feature)
+	{
+		return LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS;
+	}
+	else if ("fog" == feature)
+	{
+		return LLPipeline::RENDER_DEBUG_FEATURE_FOG;
+	}
+	else if ("fr info" == feature)
+	{
+		return LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO;
+	}
+	else if ("flexible" == feature)
+	{
+		return LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE;
+	}
+	else
+	{
+		return 0;
+	}
+};
+
+
+class LLAdvancedToggleFeature : public view_listener_t{
+	bool handleEvent(const LLSD& userdata)
+	{
+		U32 feature = feature_from_string( userdata.asString() );
+		if ( feature != 0 )
+		{
+			LLPipeline::toggleRenderDebugFeature( (void*)feature );
+		}
+		return true;
+	}
+};
+
+class LLAdvancedCheckFeature : public view_listener_t
+{bool handleEvent(const LLSD& userdata)
+{
+	U32 feature = feature_from_string( userdata.asString() );
+	bool new_value = false;
+
+	if ( feature != 0 )
+	{
+		new_value = LLPipeline::toggleRenderDebugFeatureControl( (void*)feature );
+	}
+
+	return new_value;
+}
+};
+
+void toggle_destination_and_avatar_picker(const LLSD& show)
+{
+	S32 panel_idx = show.isDefined() ? show.asInteger() : -1;
+	LLView* container = gViewerWindow->getRootView()->getChildView("avatar_picker_and_destination_guide_container");
+	LLMediaCtrl* destinations = container->findChild<LLMediaCtrl>("destination_guide_contents");
+	LLMediaCtrl* avatar_picker = container->findChild<LLMediaCtrl>("avatar_picker_contents");
+	LLButton* avatar_btn = gViewerWindow->getRootView()->getChildView("bottom_tray")->getChild<LLButton>("avatar_btn");
+	LLButton* destination_btn = gViewerWindow->getRootView()->getChildView("bottom_tray")->getChild<LLButton>("destination_btn");
+
+	switch(panel_idx)
+	{
+	case 0:
+		if (!destinations->getVisible())
+		{
+			container->setVisible(true);
+			destinations->setVisible(true);
+			avatar_picker->setVisible(false);
+			LLFirstUse::notUsingDestinationGuide(false);
+			avatar_btn->setToggleState(false);
+			destination_btn->setToggleState(true);
+			return;
+		}
+		break;
+	case 1:
+		if (!avatar_picker->getVisible())
+		{	
+			container->setVisible(true);
+			destinations->setVisible(false);
+			avatar_picker->setVisible(true);
+			avatar_btn->setToggleState(true);
+			destination_btn->setToggleState(false);
+			return;
+		}
+		break;
+	default:
+		break;
+	}
+
+	container->setVisible(false);
+	destinations->setVisible(false);
+	avatar_picker->setVisible(false);
+	avatar_btn->setToggleState(false);
+	destination_btn->setToggleState(false);
+};
+
+
+//////////////////
+// INFO DISPLAY //
+//////////////////
+U32 info_display_from_string(std::string info_display)
+{
+	if ("verify" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_VERIFY;
+	}
+	else if ("bboxes" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_BBOXES;
+	}
+	else if ("points" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_POINTS;
+	}
+	else if ("octree" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_OCTREE;
+	}
+	else if ("shadow frusta" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA;
+	}
+	else if ("occlusion" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_OCCLUSION;
+	}
+	else if ("render batches" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_BATCH_SIZE;
+	}
+	else if ("update type" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_UPDATE_TYPE;
+	}
+	else if ("texture anim" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM;
+	}
+	else if ("texture priority" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY;
+	}
+	else if ("shame" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_SHAME;
+	}
+	else if ("texture area" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_TEXTURE_AREA;
+	}
+	else if ("face area" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_FACE_AREA;
+	}
+	else if ("lights" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_LIGHTS;
+	}
+	else if ("particles" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_PARTICLES;
+	}
+	else if ("composition" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_COMPOSITION;
+	}
+	else if ("glow" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_GLOW;
+	}
+	else if ("collision skeleton" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME;
+	}
+	else if ("raycast" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_RAYCAST;
+	}
+	else if ("agent target" == info_display)
+	{
+		return LLPipeline::RENDER_DEBUG_AGENT_TARGET;
+	}
+	else
+	{
+		return 0;
+	}
+};
+
+class LLAdvancedToggleInfoDisplay : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		U32 info_display = info_display_from_string( userdata.asString() );
+
+		if ( info_display != 0 )
+		{
+			LLPipeline::toggleRenderDebug( (void*)info_display );
+		}
+
+		return true;
+	}
+};
+
+
+class LLAdvancedCheckInfoDisplay : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		U32 info_display = info_display_from_string( userdata.asString() );
+		bool new_value = false;
+
+		if ( info_display != 0 )
+		{
+			new_value = LLPipeline::toggleRenderDebugControl( (void*)info_display );
+		}
+
+		return new_value;
+	}
+};
+
+
+///////////////////////////
+//// RANDOMIZE FRAMERATE //
+///////////////////////////
+
+
+class LLAdvancedToggleRandomizeFramerate : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gRandomizeFramerate = !(gRandomizeFramerate);
+		return true;
+	}
+};
+
+class LLAdvancedCheckRandomizeFramerate : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gRandomizeFramerate;
+		return new_value;
+	}
+};
+
+void run_vectorize_perf_test(void *)
+{
+	gSavedSettings.setBOOL("VectorizePerfTest", TRUE);
+}
+
+
+////////////////////////////////
+// RUN Vectorized Perform Test//
+////////////////////////////////
+
+
+class LLAdvancedVectorizePerfTest : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		run_vectorize_perf_test(NULL);
+		return true;
+	}
+};
+
+///////////////////////////
+//// PERIODIC SLOW FRAME //
+///////////////////////////
+
+
+class LLAdvancedTogglePeriodicSlowFrame : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gPeriodicSlowFrame = !(gPeriodicSlowFrame);
+		return true;
+	}
+};
+
+class LLAdvancedCheckPeriodicSlowFrame : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gPeriodicSlowFrame;
+		return new_value;
+	}
+};
+
+
+
+////////////////
+// FRAME TEST //
+////////////////
+
+
+class LLAdvancedToggleFrameTest : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLPipeline::sRenderFrameTest = !(LLPipeline::sRenderFrameTest);
+		return true;
+	}
+};
+
+class LLAdvancedCheckFrameTest : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLPipeline::sRenderFrameTest;
+		return new_value;
+	}
+};
+
+
+///////////////////////////
+// SELECTED TEXTURE INFO //
+///////////////////////////
+
+
+class LLAdvancedSelectedTextureInfo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_selected_texture_info(NULL);
+		return true;
+	}
+};
+
+//////////////////////
+// TOGGLE WIREFRAME //
+//////////////////////
+
+class LLAdvancedToggleWireframe : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gUseWireframe = !(gUseWireframe);
+		LLPipeline::updateRenderDeferred();
+		gPipeline.resetVertexBuffers();
+		return true;
+	}
+};
+
+class LLAdvancedCheckWireframe : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gUseWireframe;
+		return new_value;
+	}
+};
+	
+//////////////////////
+// TEXTURE ATLAS //
+//////////////////////
+
+class LLAdvancedToggleTextureAtlas : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLViewerTexture::sUseTextureAtlas = !LLViewerTexture::sUseTextureAtlas;
+		gSavedSettings.setBOOL("EnableTextureAtlas", LLViewerTexture::sUseTextureAtlas) ;
+		return true;
+	}
+};
+
+class LLAdvancedCheckTextureAtlas : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLViewerTexture::sUseTextureAtlas; // <-- make this using LLCacheControl
+		return new_value;
+	}
+};
+
+//////////////////////////
+// DUMP SCRIPTED CAMERA //
+//////////////////////////
+	
+class LLAdvancedDumpScriptedCamera : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_dump_followcam(NULL);
+		return true;
+}
+};
+
+
+
+//////////////////////////////
+// DUMP REGION OBJECT CACHE //
+//////////////////////////////
+
+
+class LLAdvancedDumpRegionObjectCache : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+{
+		handle_dump_region_object_cache(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedBuyCurrencyTest : public view_listener_t
+	{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_buy_currency_test(NULL);
+		return true;
+	}
+};
+
+
+/////////////////////
+// DUMP SELECT MGR //
+/////////////////////
+
+
+class LLAdvancedDumpSelectMgr : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		dump_select_mgr(NULL);
+		return true;
+	}
+};
+
+
+
+////////////////////
+// DUMP INVENTORY //
+////////////////////
+
+
+class LLAdvancedDumpInventory : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		dump_inventory(NULL);
+		return true;
+	}
+};
+
+
+
+////////////////////////////////
+// PRINT SELECTED OBJECT INFO //
+////////////////////////////////
+
+
+class LLAdvancedPrintSelectedObjectInfo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		print_object_info(NULL);
+		return true;
+	}
+};
+
+
+
+//////////////////////
+// PRINT AGENT INFO //
+//////////////////////
+
+
+class LLAdvancedPrintAgentInfo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		print_agent_nvpairs(NULL);
+		return true;
+	}
+};
+
+
+
+////////////////////////////////
+// PRINT TEXTURE MEMORY STATS //
+////////////////////////////////
+
+
+class LLAdvancedPrintTextureMemoryStats : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		output_statistics(NULL);
+		return true;
+	}
+};
+
+//////////////////
+// DEBUG CLICKS //
+//////////////////
+
+
+class LLAdvancedToggleDebugClicks : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gDebugClicks = !(gDebugClicks);
+		return true;
+	}
+};
+
+class LLAdvancedCheckDebugClicks : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gDebugClicks;
+		return new_value;
+	}
+};
+
+
+
+/////////////////
+// DEBUG VIEWS //
+/////////////////
+
+
+class LLAdvancedToggleDebugViews : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLView::sDebugRects = !(LLView::sDebugRects);
+		return true;
+	}
+};
+
+class LLAdvancedCheckDebugViews : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLView::sDebugRects;
+		return new_value;
+	}
+};
+
+
+
+///////////////////////
+// XUI NAME TOOLTIPS //
+///////////////////////
+
+
+class LLAdvancedToggleXUINameTooltips : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		toggle_show_xui_names(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedCheckXUINameTooltips : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = check_show_xui_names(NULL);
+		return new_value;
+	}
+};
+
+
+
+////////////////////////
+// DEBUG MOUSE EVENTS //
+////////////////////////
+
+
+class LLAdvancedToggleDebugMouseEvents : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLView::sDebugMouseHandling = !(LLView::sDebugMouseHandling);
+		return true;
+	}
+};
+
+class LLAdvancedCheckDebugMouseEvents : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLView::sDebugMouseHandling;
+		return new_value;
+	}
+};
+
+
+
+////////////////
+// DEBUG KEYS //
+////////////////
+
+
+class LLAdvancedToggleDebugKeys : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLView::sDebugKeys = !(LLView::sDebugKeys);
+		return true;
+	}
+};
+	
+class LLAdvancedCheckDebugKeys : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLView::sDebugKeys;
+		return new_value;
+	}
+};
+	
+
+
+///////////////////////
+// DEBUG WINDOW PROC //
+///////////////////////
+
+
+class LLAdvancedToggleDebugWindowProc : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gDebugWindowProc = !(gDebugWindowProc);
+		return true;
+	}
+};
+
+class LLAdvancedCheckDebugWindowProc : public view_listener_t
+	{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gDebugWindowProc;
+		return new_value;
+	}
+};
+
+// ------------------------------XUI MENU ---------------------------
+
+class LLAdvancedSendTestIms : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLIMModel::instance().testMessages();
+		return true;
+}
+};
+
+
+///////////////
+// XUI NAMES //
+///////////////
+
+
+class LLAdvancedToggleXUINames : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		toggle_show_xui_names(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedCheckXUINames : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = check_show_xui_names(NULL);
+		return new_value;
+	}
+};
+
+
+////////////////////////
+// GRAB BAKED TEXTURE //
+////////////////////////
+
+
+class LLAdvancedGrabBakedTexture : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string texture_type = userdata.asString();
+		if ("iris" == texture_type)
+		{
+			handle_grab_baked_texture( (void*)BAKED_EYES );
+		}
+		else if ("head" == texture_type)
+		{
+			handle_grab_baked_texture( (void*)BAKED_HEAD );
+		}
+		else if ("upper" == texture_type)
+		{
+			handle_grab_baked_texture( (void*)BAKED_UPPER );
+		}
+		else if ("lower" == texture_type)
+		{
+			handle_grab_baked_texture( (void*)BAKED_LOWER );
+		}
+		else if ("skirt" == texture_type)
+		{
+			handle_grab_baked_texture( (void*)BAKED_SKIRT );
+		}
+		else if ("hair" == texture_type)
+		{
+			handle_grab_baked_texture( (void*)BAKED_HAIR );
+		}
+
+		return true;
+	}
+};
+
+class LLAdvancedEnableGrabBakedTexture : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+{
+		std::string texture_type = userdata.asString();
+		bool new_value = false;
+
+		if ("iris" == texture_type)
+		{
+			new_value = enable_grab_baked_texture( (void*)BAKED_EYES );
+		}
+		else if ("head" == texture_type)
+		{
+			new_value = enable_grab_baked_texture( (void*)BAKED_HEAD );
+		}
+		else if ("upper" == texture_type)
+		{
+			new_value = enable_grab_baked_texture( (void*)BAKED_UPPER );
+		}
+		else if ("lower" == texture_type)
+		{
+			new_value = enable_grab_baked_texture( (void*)BAKED_LOWER );
+		}
+		else if ("skirt" == texture_type)
+		{
+			new_value = enable_grab_baked_texture( (void*)BAKED_SKIRT );
+		}
+		else if ("hair" == texture_type)
+		{
+			new_value = enable_grab_baked_texture( (void*)BAKED_HAIR );
+		}
+	
+		return new_value;
+}
+};
+
+///////////////////////
+// APPEARANCE TO XML //
+///////////////////////
+
+
+class LLAdvancedAppearanceToXML : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar::dumpArchetypeXML(NULL);
+		return true;
+	}
+};
+
+
+
+///////////////////////////////
+// TOGGLE CHARACTER GEOMETRY //
+///////////////////////////////
+
+
+class LLAdvancedToggleCharacterGeometry : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_god_request_avatar_geometry(NULL);
+		return true;
+}
+};
+
+
+	/////////////////////////////
+// TEST MALE / TEST FEMALE //
+/////////////////////////////
+
+class LLAdvancedTestMale : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_test_male(NULL);
+		return true;
+	}
+};
+
+
+class LLAdvancedTestFemale : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_test_female(NULL);
+		return true;
+	}
+};
+
+
+
+///////////////
+// TOGGLE PG //
+///////////////
+
+
+class LLAdvancedTogglePG : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_toggle_pg(NULL);
+		return true;
+	}
+};
+
+
+class LLAdvancedForceParamsToDefault : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLAgent::clearVisualParams(NULL);
+		return true;
+	}
+};
+
+
+
+//////////////////////////
+// RELOAD VERTEX SHADER //
+//////////////////////////
+
+
+class LLAdvancedReloadVertexShader : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		reload_vertex_shader(NULL);
+		return true;
+	}
+};
+
+
+
+////////////////////
+// ANIMATION INFO //
+////////////////////
+
+
+class LLAdvancedToggleAnimationInfo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar::sShowAnimationDebug = !(LLVOAvatar::sShowAnimationDebug);
+		return true;
+	}
+};
+
+class LLAdvancedCheckAnimationInfo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLVOAvatar::sShowAnimationDebug;
+		return new_value;
+	}
+};
+
+
+//////////////////
+// SHOW LOOK AT //
+//////////////////
+
+
+class LLAdvancedToggleShowLookAt : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLHUDEffectLookAt::sDebugLookAt = !(LLHUDEffectLookAt::sDebugLookAt);
+		return true;
+	}
+};
+
+class LLAdvancedCheckShowLookAt : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLHUDEffectLookAt::sDebugLookAt;
+		return new_value;
+	}
+};
+
+
+
+///////////////////
+// SHOW POINT AT //
+///////////////////
+
+
+class LLAdvancedToggleShowPointAt : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLHUDEffectPointAt::sDebugPointAt = !(LLHUDEffectPointAt::sDebugPointAt);
+		return true;
+	}
+};
+
+class LLAdvancedCheckShowPointAt : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLHUDEffectPointAt::sDebugPointAt;
+		return new_value;
+	}
+};
+
+
+
+/////////////////////////
+// DEBUG JOINT UPDATES //
+/////////////////////////
+
+
+class LLAdvancedToggleDebugJointUpdates : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar::sJointDebug = !(LLVOAvatar::sJointDebug);
+		return true;
+	}
+};
+
+class LLAdvancedCheckDebugJointUpdates : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLVOAvatar::sJointDebug;
+		return new_value;
+	}
+};
+
+
+
+/////////////////
+// DISABLE LOD //
+/////////////////
+
+
+class LLAdvancedToggleDisableLOD : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLViewerJoint::sDisableLOD = !(LLViewerJoint::sDisableLOD);
+		return true;
+	}
+};
+		
+class LLAdvancedCheckDisableLOD : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLViewerJoint::sDisableLOD;
+		return new_value;
+	}
+};
+
+
+
+/////////////////////////
+// DEBUG CHARACTER VIS //
+/////////////////////////
+
+
+class LLAdvancedToggleDebugCharacterVis : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar::sDebugInvisible = !(LLVOAvatar::sDebugInvisible);
+		return true;
+	}
+};
+
+class LLAdvancedCheckDebugCharacterVis : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLVOAvatar::sDebugInvisible;
+		return new_value;
+	}
+};
+
+
+//////////////////////
+// DUMP ATTACHMENTS //
+//////////////////////
+
+	
+class LLAdvancedDumpAttachments : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_dump_attachments(NULL);
+		return true;
+	}
+};
+
+
+	
+/////////////////////
+// REBAKE TEXTURES //
+/////////////////////
+	
+	
+class LLAdvancedRebakeTextures : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_rebake_textures(NULL);
+		return true;
+	}
+};
+	
+	
+#if 1 //ndef LL_RELEASE_FOR_DOWNLOAD
+///////////////////////////
+// DEBUG AVATAR TEXTURES //
+///////////////////////////
+
+
+class LLAdvancedDebugAvatarTextures : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (gAgent.isGodlike())
+		{
+			handle_debug_avatar_textures(NULL);
+		}
+		return true;
+	}
+};
+
+////////////////////////////////
+// DUMP AVATAR LOCAL TEXTURES //
+////////////////////////////////
+
+
+class LLAdvancedDumpAvatarLocalTextures : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+		handle_dump_avatar_local_textures(NULL);
+#endif
+		return true;
+	}
+};
+
+#endif
+	
+/////////////////
+// MESSAGE LOG //
+/////////////////
+
+
+class LLAdvancedEnableMessageLog : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_viewer_enable_message_log(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedDisableMessageLog : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_viewer_disable_message_log(NULL);
+		return true;
+	}
+};
+
+/////////////////
+// DROP PACKET //
+/////////////////
+
+
+class LLAdvancedDropPacket : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gMessageSystem->mPacketRing.dropPackets(1);
+		return true;
+	}
+};
+
+
+
+/////////////////
+// AGENT PILOT //
+/////////////////
+
+
+class LLAdvancedAgentPilot : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string command = userdata.asString();
+		if ("start playback" == command)
+		{
+			LLAgentPilot::startPlayback(NULL);
+		}
+		else if ("stop playback" == command)
+		{
+			LLAgentPilot::stopPlayback(NULL);
+		}
+		else if ("start record" == command)
+		{
+			LLAgentPilot::startRecord(NULL);
+		}
+		else if ("stop record" == command)
+		{
+			LLAgentPilot::saveRecord(NULL);
+		}
+
+		return true;
+	}		
+};
+
+
+
+//////////////////////
+// AGENT PILOT LOOP //
+//////////////////////
+
+
+class LLAdvancedToggleAgentPilotLoop : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLAgentPilot::sLoop = !(LLAgentPilot::sLoop);
+		return true;
+	}
+};
+
+class LLAdvancedCheckAgentPilotLoop : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLAgentPilot::sLoop;
+		return new_value;
+	}
+};
+
+
+/////////////////////////
+// SHOW OBJECT UPDATES //
+/////////////////////////
+
+
+class LLAdvancedToggleShowObjectUpdates : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gShowObjectUpdates = !(gShowObjectUpdates);
+		return true;
+	}
+};
+
+class LLAdvancedCheckShowObjectUpdates : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gShowObjectUpdates;
+		return new_value;
+	}
+};
+
+
+
+////////////////////
+// COMPRESS IMAGE //
+////////////////////
+
+
+class LLAdvancedCompressImage : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_compress_image(NULL);
+		return true;
+	}
+};
+
+
+
+/////////////////////////
+// SHOW DEBUG SETTINGS //
+/////////////////////////
+
+
+class LLAdvancedShowDebugSettings : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLFloaterReg::showInstance("settings_debug",userdata);
+		return true;
+	}
+};
+
+
+
+////////////////////////
+// VIEW ADMIN OPTIONS //
+////////////////////////
+
+class LLAdvancedEnableViewAdminOptions : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// Don't enable in god mode since the admin menu is shown anyway.
+		// Only enable if the user has set the appropriate debug setting.
+		bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu");
+		return new_value;
+	}
+};
+
+class LLAdvancedToggleViewAdminOptions : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_admin_override_toggle(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedCheckViewAdminOptions : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = check_admin_override(NULL) || gAgent.isGodlike();
+		return new_value;
+	}
+};
+
+/////////////////////////////////////
+// Enable Object Object Occlusion ///
+/////////////////////////////////////
+class LLAdvancedEnableObjectObjectOcclusion: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+	
+		bool new_value = gGLManager.mHasOcclusionQuery; // && LLFeatureManager::getInstance()->isFeatureAvailable(userdata.asString());
+		return new_value;
+}
+};
+
+/////////////////////////////////////
+// Enable Framebuffer Objects	  ///
+/////////////////////////////////////
+class LLAdvancedEnableRenderFBO: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gGLManager.mHasFramebufferObject;
+		return new_value;
+	}
+};
+
+/////////////////////////////////////
+// Enable Deferred Rendering	  ///
+/////////////////////////////////////
+class LLAdvancedEnableRenderDeferred: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gSavedSettings.getBOOL("RenderUseFBO") && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT > 0) &&
+			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
+		return new_value;
+	}
+};
+
+/////////////////////////////////////
+// Enable Deferred Rendering sub-options
+/////////////////////////////////////
+class LLAdvancedEnableRenderDeferredOptions: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gSavedSettings.getBOOL("RenderUseFBO") && gSavedSettings.getBOOL("RenderDeferred");
+		return new_value;
+	}
+};
+
+
+
+//////////////////
+// ADMIN STATUS //
+//////////////////
+
+
+class LLAdvancedRequestAdminStatus : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_god_mode(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedLeaveAdminStatus : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_leave_god_mode(NULL);
+		return true;
+	}
+};
+
+//////////////////////////
+// Advanced > Debugging //
+//////////////////////////
+
+
+class LLAdvancedForceErrorBreakpoint : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		force_error_breakpoint(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedForceErrorLlerror : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		force_error_llerror(NULL);
+		return true;
+	}
+};
+class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		force_error_bad_memory_access(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedForceErrorInfiniteLoop : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		force_error_infinite_loop(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedForceErrorSoftwareException : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		force_error_software_exception(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedForceErrorDriverCrash : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		force_error_driver_crash(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedForceErrorDisconnectViewer : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_disconnect_viewer(NULL);
+		return true;
+}
+};
+
+
+#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+
+class LLAdvancedHandleToggleHackedGodmode : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_toggle_hacked_godmode(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedCheckToggleHackedGodmode : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		check_toggle_hacked_godmode(NULL);
+		return true;
+	}
+};
+
+class LLAdvancedEnableToggleHackedGodmode : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = enable_toggle_hacked_godmode(NULL);
+		return new_value;
+	}
+};
+#endif
+
+
+//
+////-------------------------------------------------------------------
+//// Advanced menu
+////-------------------------------------------------------------------
+
+//////////////////
+// ADMIN MENU   //
+//////////////////
+
+// Admin > Object
+class LLAdminForceTakeCopy : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		force_take_copy(NULL);
+		return true;
+	}
+};
+
+class LLAdminHandleObjectOwnerSelf : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_object_owner_self(NULL);
+		return true;
+	}
+};
+class LLAdminHandleObjectOwnerPermissive : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_object_owner_permissive(NULL);
+		return true;
+	}
+};
+
+class LLAdminHandleForceDelete : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_force_delete(NULL);
+		return true;
+	}
+};
+
+class LLAdminHandleObjectLock : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_object_lock(NULL);
+		return true;
+	}
+};
+
+class LLAdminHandleObjectAssetIDs: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_object_asset_ids(NULL);
+		return true;
+	}	
+};
+
+//Admin >Parcel
+class LLAdminHandleForceParcelOwnerToMe: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_force_parcel_owner_to_me(NULL);
+		return true;
+	}
+};
+class LLAdminHandleForceParcelToContent: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_force_parcel_to_content(NULL);
+		return true;
+	}
+};
+class LLAdminHandleClaimPublicLand: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_claim_public_land(NULL);
+		return true;
+	}
+};
+
+// Admin > Region
+class LLAdminHandleRegionDumpTempAssetData: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_region_dump_temp_asset_data(NULL);
+		return true;
+	}
+};
+//Admin (Top Level)
+
+class LLAdminOnSaveState: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLPanelRegionTools::onSaveState(NULL);
+		return true;
+}
+};
+
+
+//-----------------------------------------------------------------------------
+// cleanup_menus()
+//-----------------------------------------------------------------------------
+void cleanup_menus()
+{
+	delete gMenuParcelObserver;
+	gMenuParcelObserver = NULL;
+
+	delete gMenuAvatarSelf;
+	gMenuAvatarSelf = NULL;
+
+	delete gMenuAvatarOther;
+	gMenuAvatarOther = NULL;
+
+	delete gMenuObject;
+	gMenuObject = NULL;
+
+	delete gMenuAttachmentSelf;
+	gMenuAttachmentSelf = NULL;
+
+	delete gMenuAttachmentOther;
+	gMenuAttachmentSelf = NULL;
+
+	delete gMenuLand;
+	gMenuLand = NULL;
+
+	delete gMenuBarView;
+	gMenuBarView = NULL;
+
+	delete gPopupMenuView;
+	gPopupMenuView = NULL;
+
+	delete gMenuHolder;
+	gMenuHolder = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Object pie menu
+//-----------------------------------------------------------------------------
+
+class LLObjectReportAbuse : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+		if (objectp)
+		{
+			LLFloaterReporter::showFromObject(objectp->getID());
+		}
+		return true;
+	}
+};
+
+// Enabled it you clicked an object
+class LLObjectEnableReportAbuse : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0;
+		return new_value;
+	}
+};
+
+void handle_object_touch()
+{
+		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+		if (!object) return;
+
+		LLPickInfo pick = LLToolPie::getInstance()->getPick();
+
+		LLMessageSystem	*msg = gMessageSystem;
+
+		msg->newMessageFast(_PREHASH_ObjectGrab);
+		msg->nextBlockFast( _PREHASH_AgentData);
+		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		msg->nextBlockFast( _PREHASH_ObjectData);
+		msg->addU32Fast(    _PREHASH_LocalID, object->mLocalID);
+		msg->addVector3Fast(_PREHASH_GrabOffset, LLVector3::zero );
+		msg->nextBlock("SurfaceInfo");
+		msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
+		msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
+		msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
+		msg->addVector3("Position", pick.mIntersection);
+		msg->addVector3("Normal", pick.mNormal);
+		msg->addVector3("Binormal", pick.mBinormal);
+		msg->sendMessage( object->getRegion()->getHost());
+
+		// *NOTE: Hope the packets arrive safely and in order or else
+		// there will be some problems.
+		// *TODO: Just fix this bad assumption.
+		msg->newMessageFast(_PREHASH_ObjectDeGrab);
+		msg->nextBlockFast(_PREHASH_AgentData);
+		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		msg->nextBlockFast(_PREHASH_ObjectData);
+		msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
+		msg->nextBlock("SurfaceInfo");
+		msg->addVector3("UVCoord", LLVector3(pick.mUVCoords));
+		msg->addVector3("STCoord", LLVector3(pick.mSTCoords));
+		msg->addS32Fast(_PREHASH_FaceIndex, pick.mObjectFace);
+		msg->addVector3("Position", pick.mIntersection);
+		msg->addVector3("Normal", pick.mNormal);
+		msg->addVector3("Binormal", pick.mBinormal);
+		msg->sendMessage(object->getRegion()->getHost());
+}
+
+static void init_default_item_label(const std::string& item_name)
+{
+	boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
+	if (it == sDefaultItemLabels.end())
+	{
+		// *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value
+		//       (doesn't seem to matter much ATM).
+		LLStringExplicit default_label = gMenuHolder->childGetValue(item_name).asString();
+		if (!default_label.empty())
+		{
+			sDefaultItemLabels.insert(std::pair<std::string, LLStringExplicit>(item_name, default_label));
+		}
+	}
+}
+
+static LLStringExplicit get_default_item_label(const std::string& item_name)
+{
+	LLStringExplicit res("");
+	boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name);
+	if (it != sDefaultItemLabels.end())
+	{
+		res = it->second;
+	}
+
+	return res;
+}
+
+
+bool enable_object_touch(LLUICtrl* ctrl)
+{
+	LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+
+	bool new_value = obj && obj->flagHandleTouch();
+
+	std::string item_name = ctrl->getName();
+	init_default_item_label(item_name);
+
+	// Update label based on the node touch name if available.
+	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+	if (node && node->mValid && !node->mTouchName.empty())
+	{
+		gMenuHolder->childSetText(item_name, node->mTouchName);
+	}
+	else
+	{
+		gMenuHolder->childSetText(item_name, get_default_item_label(item_name));
+	}
+
+	return new_value;
+};
+
+//void label_touch(std::string& label, void*)
+//{
+//	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+//	if (node && node->mValid && !node->mTouchName.empty())
+//	{
+//		label.assign(node->mTouchName);
+//	}
+//	else
+//	{
+//		label.assign("Touch");
+//	}
+//}
+
+void handle_object_open()
+{
+	LLFloaterReg::showInstance("openobject");
+}
+
+bool enable_object_open()
+{
+	// Look for contents in root object, which is all the LLFloaterOpenObject
+	// understands.
+	LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+	if (!obj) return false;
+
+	LLViewerObject* root = obj->getRootEdit();
+	if (!root) return false;
+
+	return root->allowOpen();
+}
+
+
+class LLViewJoystickFlycam : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_toggle_flycam();
+		return true;
+	}
+};
+
+class LLViewCheckJoystickFlycam : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera();
+		return new_value;
+	}
+};
+
+void handle_toggle_flycam()
+{
+	LLViewerJoystick::getInstance()->toggleFlycam();
+}
+
+class LLObjectBuild : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
+		{
+			// zoom in if we're looking at the avatar
+			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gAgentCamera.cameraZoomIn(0.666f);
+			gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
+			gViewerWindow->moveCursorToCenter();
+		}
+		else if ( gSavedSettings.getBOOL("EditCameraMovement") )
+		{
+			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gViewerWindow->moveCursorToCenter();
+		}
+
+		LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+		LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
+
+		// Could be first use
+		//LLFirstUse::useBuild();
+		return true;
+	}
+};
+
+
+void handle_object_edit()
+{
+	LLViewerParcelMgr::getInstance()->deselectLand();
+
+	if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit())
+	{
+		LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->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
+			gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
+			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+		}
+		else
+		{
+			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+			LLViewerObject* selected_objectp = selection->getFirstRootObject();
+			if (selected_objectp)
+			{
+			  // zoom in on object center instead of where we clicked, as we need to see the manipulator handles
+			  gAgentCamera.setFocusGlobal(selected_objectp->getPositionGlobal(), selected_objectp->getID());
+			  gAgentCamera.cameraZoomIn(0.666f);
+			  gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
+			  gViewerWindow->moveCursorToCenter();
+			}
+		}
+	}
+	
+	LLFloaterReg::showInstance("build");
+	
+	LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+	gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() );
+	
+	LLViewerJoystick::getInstance()->moveObjects(true);
+	LLViewerJoystick::getInstance()->setNeedsReset(true);
+	
+	// Could be first use
+	//LLFirstUse::useBuild();
+	return;
+}
+
+void handle_object_inspect()
+{
+	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+	LLViewerObject* selected_objectp = selection->getFirstRootObject();
+	if (selected_objectp)
+	{
+		LLSD key;
+		key["task"] = "task";
+		LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+	}
+	
+	/*
+	// Old floater properties
+	LLFloaterReg::showInstance("inspect", LLSD());
+	*/
+}
+
+//---------------------------------------------------------------------------
+// Land pie menu
+//---------------------------------------------------------------------------
+class LLLandBuild : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLViewerParcelMgr::getInstance()->deselectLand();
+
+		if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") )
+		{
+			// zoom in if we're looking at the avatar
+			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gAgentCamera.cameraZoomIn(0.666f);
+			gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD );
+			gViewerWindow->moveCursorToCenter();
+		}
+		else if ( gSavedSettings.getBOOL("EditCameraMovement")  )
+		{
+			// otherwise just move focus
+			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gViewerWindow->moveCursorToCenter();
+		}
+
+
+		LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
+		LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() );
+
+		// Could be first use
+		//LLFirstUse::useBuild();
+		return true;
+	}
+};
+
+class LLLandBuyPass : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLPanelLandGeneral::onClickBuyPass((void *)FALSE);
+		return true;
+	}
+};
+
+class LLLandEnableBuyPass : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLPanelLandGeneral::enableBuyPass(NULL);
+		return new_value;
+	}
+};
+
+// BUG: Should really check if CLICK POINT is in a parcel where you can build.
+BOOL enable_land_build(void*)
+{
+	if (gAgent.isGodlike()) return TRUE;
+	if (gAgent.inPrelude()) return FALSE;
+
+	BOOL can_build = FALSE;
+	LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if (agent_parcel)
+	{
+		can_build = agent_parcel->getAllowModify();
+	}
+	return can_build;
+}
+
+// BUG: Should really check if OBJECT is in a parcel where you can build.
+BOOL enable_object_build(void*)
+{
+	if (gAgent.isGodlike()) return TRUE;
+	if (gAgent.inPrelude()) return FALSE;
+
+	BOOL can_build = FALSE;
+	LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if (agent_parcel)
+	{
+		can_build = agent_parcel->getAllowModify();
+	}
+	return can_build;
+}
+
+bool enable_object_edit()
+{
+	// *HACK:  The new "prelude" Help Islands have a build sandbox area,
+	// so users need the Edit and Create pie menu options when they are
+	// there.  Eventually this needs to be replaced with code that only 
+	// lets you edit objects if you have permission to do so (edit perms,
+	// group edit, god).  See also lltoolbar.cpp.  JC
+	bool enable = false;
+	if (gAgent.inPrelude())
+	{
+		enable = LLViewerParcelMgr::getInstance()->allowAgentBuild()
+			|| LLSelectMgr::getInstance()->getSelection()->isAttachment();
+	} 
+	else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound())
+	{
+		enable = true;
+	}
+
+	return enable;
+}
+
+// mutually exclusive - show either edit option or build in menu
+bool enable_object_build()
+{
+	return !enable_object_edit();
+}
+
+class LLSelfRemoveAllAttachments : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLAgentWearables::userRemoveAllAttachments();
+		return true;
+	}
+};
+
+class LLSelfEnableRemoveAllAttachments : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = false;
+		if (isAgentAvatarValid())
+		{
+			for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); 
+				 iter != gAgentAvatarp->mAttachmentPoints.end(); )
+			{
+				LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+				LLViewerJointAttachment* attachment = curiter->second;
+				if (attachment->getNumObjects() > 0)
+				{
+					new_value = true;
+					break;
+				}
+			}
+		}
+		return new_value;
+	}
+};
+
+BOOL enable_has_attachments(void*)
+{
+
+	return FALSE;
+}
+
+//---------------------------------------------------------------------------
+// Avatar pie menu
+//---------------------------------------------------------------------------
+//void handle_follow(void *userdata)
+//{
+//	// follow a given avatar by ID
+//	LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+//	if (objectp)
+//	{
+//		gAgent.startFollowPilot(objectp->getID());
+//	}
+//}
+
+bool enable_object_mute()
+{
+	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+	if (!object) return false;
+
+	LLVOAvatar* avatar = find_avatar_from_object(object); 
+	if (avatar)
+	{
+		// It's an avatar
+		LLNameValue *lastname = avatar->getNVPair("LastName");
+		bool is_linden =
+			lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden");
+		bool is_self = avatar->isSelf();
+		return !is_linden && !is_self;
+	}
+	else
+	{
+		// Just a regular object
+		return LLSelectMgr::getInstance()->getSelection()->
+			contains( object, SELECT_ALL_TES );
+	}
+}
+
+class LLObjectMute : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+		if (!object) return true;
+		
+		LLUUID id;
+		std::string name;
+		LLMute::EType type;
+		LLVOAvatar* avatar = find_avatar_from_object(object); 
+		if (avatar)
+		{
+			id = avatar->getID();
+
+			LLNameValue *firstname = avatar->getNVPair("FirstName");
+			LLNameValue *lastname = avatar->getNVPair("LastName");
+			if (firstname && lastname)
+			{
+				name = LLCacheName::buildFullName(
+					firstname->getString(), lastname->getString());
+			}
+			
+			type = LLMute::AGENT;
+		}
+		else
+		{
+			// it's an object
+			id = object->getID();
+
+			LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+			if (node)
+			{
+				name = node->mName;
+			}
+			
+			type = LLMute::OBJECT;
+		}
+		
+		LLMute mute(id, name, type);
+		if (LLMuteList::getInstance()->isMuted(mute.mID))
+		{
+			LLMuteList::getInstance()->remove(mute);
+		}
+		else
+		{
+			LLMuteList::getInstance()->add(mute);
+			LLPanelBlockedList::showPanelAndSelect(mute.mID);
+		}
+		
+		return true;
+	}
+};
+
+bool handle_go_to()
+{
+	// try simulator autopilot
+	std::vector<std::string> strings;
+	std::string val;
+	LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
+	val = llformat("%g", pos.mdV[VX]);
+	strings.push_back(val);
+	val = llformat("%g", pos.mdV[VY]);
+	strings.push_back(val);
+	val = llformat("%g", pos.mdV[VZ]);
+	strings.push_back(val);
+	send_generic_message("autopilot", strings);
+
+	LLViewerParcelMgr::getInstance()->deselectLand();
+
+	if (isAgentAvatarValid() && !gSavedSettings.getBOOL("AutoPilotLocksCamera"))
+	{
+		gAgentCamera.setFocusGlobal(gAgentCamera.getFocusTargetGlobal(), gAgentAvatarp->getID());
+	}
+	else 
+	{
+		// Snap camera back to behind avatar
+		gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE);
+	}
+
+	// Could be first use
+	//LLFirstUse::useGoTo();
+	return true;
+}
+
+class LLGoToObject : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return handle_go_to();
+	}
+};
+
+class LLAvatarReportAbuse : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+		if(avatar)
+		{
+			LLFloaterReporter::showFromObject(avatar->getID());
+		}
+		return true;
+	}
+};
+
+
+//---------------------------------------------------------------------------
+// Parcel freeze, eject, etc.
+//---------------------------------------------------------------------------
+bool callback_freeze(const LLSD& notification, const LLSD& response)
+{
+	LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+	if (0 == option || 1 == option)
+	{
+		U32 flags = 0x0;
+		if (1 == option)
+		{
+			// unfreeze
+			flags |= 0x1;
+		}
+
+		LLMessageSystem* msg = gMessageSystem;
+		LLViewerObject* avatar = gObjectList.findObject(avatar_id);
+
+		if (avatar)
+		{
+			msg->newMessage("FreezeUser");
+			msg->nextBlock("AgentData");
+			msg->addUUID("AgentID", gAgent.getID());
+			msg->addUUID("SessionID", gAgent.getSessionID());
+			msg->nextBlock("Data");
+			msg->addUUID("TargetID", avatar_id );
+			msg->addU32("Flags", flags );
+			msg->sendReliable( avatar->getRegion()->getHost() );
+		}
+	}
+	return false;
+}
+
+
+void handle_avatar_freeze(const LLSD& avatar_id)
+{
+		// Use avatar_id if available, otherwise default to right-click avatar
+		LLVOAvatar* avatar = NULL;
+		if (avatar_id.asUUID().notNull())
+		{
+			avatar = find_avatar_from_object(avatar_id.asUUID());
+		}
+		else
+		{
+			avatar = find_avatar_from_object(
+				LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+		}
+
+		if( avatar )
+		{
+			std::string fullname = avatar->getFullname();
+			LLSD payload;
+			payload["avatar_id"] = avatar->getID();
+
+			if (!fullname.empty())
+			{
+				LLSD args;
+				args["AVATAR_NAME"] = fullname;
+				LLNotificationsUtil::add("FreezeAvatarFullname",
+							args,
+							payload,
+							callback_freeze);
+			}
+			else
+			{
+				LLNotificationsUtil::add("FreezeAvatar",
+							LLSD(),
+							payload,
+							callback_freeze);
+			}
+		}
+}
+
+class LLAvatarVisibleDebug : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return gAgent.isGodlike();
+	}
+};
+
+class LLAvatarDebug : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+		if( avatar )
+		{
+			if (avatar->isSelf())
+			{
+				((LLVOAvatarSelf *)avatar)->dumpLocalTextures();
+			}
+			llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl;
+			std::vector<std::string> strings;
+			strings.push_back(avatar->getID().asString());
+			LLUUID invoice;
+			send_generic_message("dumptempassetdata", strings, invoice);
+			LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) );
+		}
+		return true;
+	}
+};
+
+bool callback_eject(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (2 == option)
+	{
+		// Cancel button.
+		return false;
+	}
+	LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+	bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean();
+
+	if (0 == option)
+	{
+		// Eject button
+		LLMessageSystem* msg = gMessageSystem;
+		LLViewerObject* avatar = gObjectList.findObject(avatar_id);
+
+		if (avatar)
+		{
+			U32 flags = 0x0;
+			msg->newMessage("EjectUser");
+			msg->nextBlock("AgentData");
+			msg->addUUID("AgentID", gAgent.getID() );
+			msg->addUUID("SessionID", gAgent.getSessionID() );
+			msg->nextBlock("Data");
+			msg->addUUID("TargetID", avatar_id );
+			msg->addU32("Flags", flags );
+			msg->sendReliable( avatar->getRegion()->getHost() );
+		}
+	}
+	else if (ban_enabled)
+	{
+		// This is tricky. It is similar to say if it is not an 'Eject' button,
+		// and it is also not an 'Cancle' button, and ban_enabled==ture, 
+		// it should be the 'Eject and Ban' button.
+		LLMessageSystem* msg = gMessageSystem;
+		LLViewerObject* avatar = gObjectList.findObject(avatar_id);
+
+		if (avatar)
+		{
+			U32 flags = 0x1;
+			msg->newMessage("EjectUser");
+			msg->nextBlock("AgentData");
+			msg->addUUID("AgentID", gAgent.getID() );
+			msg->addUUID("SessionID", gAgent.getSessionID() );
+			msg->nextBlock("Data");
+			msg->addUUID("TargetID", avatar_id );
+			msg->addU32("Flags", flags );
+			msg->sendReliable( avatar->getRegion()->getHost() );
+		}
+	}
+	return false;
+}
+
+void handle_avatar_eject(const LLSD& avatar_id)
+{
+		// Use avatar_id if available, otherwise default to right-click avatar
+		LLVOAvatar* avatar = NULL;
+		if (avatar_id.asUUID().notNull())
+		{
+			avatar = find_avatar_from_object(avatar_id.asUUID());
+		}
+		else
+		{
+			avatar = find_avatar_from_object(
+				LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+		}
+
+		if( avatar )
+		{
+			LLSD payload;
+			payload["avatar_id"] = avatar->getID();
+			std::string fullname = avatar->getFullname();
+
+			const LLVector3d& pos = avatar->getPositionGlobal();
+			LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel();
+			
+			if (LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED))
+			{
+                payload["ban_enabled"] = true;
+				if (!fullname.empty())
+				{
+    				LLSD args;
+    				args["AVATAR_NAME"] = fullname;
+    				LLNotificationsUtil::add("EjectAvatarFullname",
+    							args,
+    							payload,
+    							callback_eject);
+				}
+				else
+				{
+    				LLNotificationsUtil::add("EjectAvatarFullname",
+    							LLSD(),
+    							payload,
+    							callback_eject);
+				}
+			}
+			else
+			{
+                payload["ban_enabled"] = false;
+				if (!fullname.empty())
+				{
+    				LLSD args;
+    				args["AVATAR_NAME"] = fullname;
+    				LLNotificationsUtil::add("EjectAvatarFullnameNoBan",
+    							args,
+    							payload,
+    							callback_eject);
+				}
+				else
+				{
+    				LLNotificationsUtil::add("EjectAvatarNoBan",
+    							LLSD(),
+    							payload,
+    							callback_eject);
+				}
+			}
+		}
+}
+
+bool enable_freeze_eject(const LLSD& avatar_id)
+{
+	// Use avatar_id if available, otherwise default to right-click avatar
+	LLVOAvatar* avatar = NULL;
+	if (avatar_id.asUUID().notNull())
+	{
+		avatar = find_avatar_from_object(avatar_id.asUUID());
+	}
+	else
+	{
+		avatar = find_avatar_from_object(
+			LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+	}
+	if (!avatar) return false;
+
+	// Gods can always freeze
+	if (gAgent.isGodlike()) return true;
+
+	// Estate owners / managers can freeze
+	// Parcel owners can also freeze
+	const LLVector3& pos = avatar->getPositionRegion();
+	const LLVector3d& pos_global = avatar->getPositionGlobal();
+	LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel();
+	LLViewerRegion* region = avatar->getRegion();
+	if (!region) return false;
+				
+	bool new_value = region->isOwnedSelf(pos);
+	if (!new_value || region->isOwnedGroup(pos))
+	{
+		new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN);
+	}
+	return new_value;
+}
+
+
+void login_done(S32 which, void *user)
+{
+	llinfos << "Login done " << which << llendl;
+
+	LLPanelLogin::closePanel();
+}
+
+
+bool callback_leave_group(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (option == 0)
+	{
+		LLMessageSystem *msg = gMessageSystem;
+
+		msg->newMessageFast(_PREHASH_LeaveGroupRequest);
+		msg->nextBlockFast(_PREHASH_AgentData);
+		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		msg->nextBlockFast(_PREHASH_GroupData);
+		msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() );
+		gAgent.sendReliableMessage();
+	}
+	return false;
+}
+
+void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm, PermissionBit bit, const char* txt)
+{
+	LLAggregatePermissions::EValue val = ag_perm.getValue(bit);
+	std::string buffer;
+	switch(val)
+	{
+	  case LLAggregatePermissions::AP_NONE:
+		buffer = llformat( "* %s None\n", txt);
+		break;
+	  case LLAggregatePermissions::AP_SOME:
+		buffer = llformat( "* %s Some\n", txt);
+		break;
+	  case LLAggregatePermissions::AP_ALL:
+		buffer = llformat( "* %s All\n", txt);
+		break;
+	  case LLAggregatePermissions::AP_EMPTY:
+	  default:
+		break;
+	}
+	string.append(buffer);
+}
+
+bool enable_buy_object()
+{
+    // In order to buy, there must only be 1 purchaseable object in
+    // the selection manger.
+	if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false;
+    LLViewerObject* obj = NULL;
+    LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+	if(node)
+    {
+        obj = node->getObject();
+        if(!obj) return false;
+
+		if( for_sale_selection(node) )
+		{
+			// *NOTE: Is this needed?  This checks to see if anyone owns the
+			// object, dating back to when we had "public" objects owned by
+			// no one.  JC
+			if(obj->permAnyOwner()) return true;
+		}
+    }
+	return false;
+}
+
+// Note: This will only work if the selected object's data has been
+// received by the viewer and cached in the selection manager.
+void handle_buy_object(LLSaleInfo sale_info)
+{
+	if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
+	{
+		LLNotificationsUtil::add("UnableToBuyWhileDownloading");
+		return;
+	}
+
+	LLUUID owner_id;
+	std::string owner_name;
+	BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
+	if (!owners_identical)
+	{
+		LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners");
+		return;
+	}
+
+	LLPermissions perm;
+	BOOL valid = LLSelectMgr::getInstance()->selectGetPermissions(perm);
+	LLAggregatePermissions ag_perm;
+	valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm);
+	if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID()))
+	{
+		LLNotificationsUtil::add("ObjectNotForSale");
+		return;
+	}
+
+	LLFloaterBuy::show(sale_info);
+}
+
+
+void handle_buy_contents(LLSaleInfo sale_info)
+{
+	LLFloaterBuyContents::show(sale_info);
+}
+
+void handle_region_dump_temp_asset_data(void*)
+{
+	llinfos << "Dumping temporary asset data to simulator logs" << llendl;
+	std::vector<std::string> strings;
+	LLUUID invoice;
+	send_generic_message("dumptempassetdata", strings, invoice);
+}
+
+void handle_region_clear_temp_asset_data(void*)
+{
+	llinfos << "Clearing temporary asset data" << llendl;
+	std::vector<std::string> strings;
+	LLUUID invoice;
+	send_generic_message("cleartempassetdata", strings, invoice);
+}
+
+void handle_region_dump_settings(void*)
+{
+	LLViewerRegion* regionp = gAgent.getRegion();
+	if (regionp)
+	{
+		llinfos << "Damage:    " << (regionp->getAllowDamage() ? "on" : "off") << llendl;
+		llinfos << "Landmark:  " << (regionp->getAllowLandmark() ? "on" : "off") << llendl;
+		llinfos << "SetHome:   " << (regionp->getAllowSetHome() ? "on" : "off") << llendl;
+		llinfos << "ResetHome: " << (regionp->getResetHomeOnTeleport() ? "on" : "off") << llendl;
+		llinfos << "SunFixed:  " << (regionp->getSunFixed() ? "on" : "off") << llendl;
+		llinfos << "BlockFly:  " << (regionp->getBlockFly() ? "on" : "off") << llendl;
+		llinfos << "AllowP2P:  " << (regionp->getAllowDirectTeleport() ? "on" : "off") << llendl;
+		llinfos << "Water:     " << (regionp->getWaterHeight()) << llendl;
+	}
+}
+
+void handle_dump_group_info(void *)
+{
+	gAgent.dumpGroupInfo();
+}
+
+void handle_dump_capabilities_info(void *)
+{
+	LLViewerRegion* regionp = gAgent.getRegion();
+	if (regionp)
+	{
+		regionp->logActiveCapabilities();
+	}
+}
+
+void handle_dump_region_object_cache(void*)
+{
+	LLViewerRegion* regionp = gAgent.getRegion();
+	if (regionp)
+	{
+		regionp->dumpCache();
+	}
+}
+
+void handle_dump_focus()
+{
+	LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+
+	llinfos << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << llendl;
+}
+
+class LLSelfStandUp : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gAgent.standUp();
+		return true;
+	}
+};
+
+bool enable_standup_self()
+{
+    return isAgentAvatarValid() && gAgentAvatarp->isSitting();
+}
+
+class LLSelfSitDown : public view_listener_t
+    {
+        bool handleEvent(const LLSD& userdata)
+        {
+            gAgent.sitDown();
+            return true;
+        }
+    };
+
+bool enable_sitdown_self()
+{
+    return isAgentAvatarValid() && !gAgentAvatarp->isSitting() && !gAgent.getFlying();
+}
+
+// Used from the login screen to aid in UI work on side tray
+void handle_show_side_tray()
+{
+	LLSideTray* side_tray = LLSideTray::getInstance();
+	LLView* root = gViewerWindow->getRootView();
+	// automatically removes and re-adds if there already
+	root->addChild(side_tray);
+}
+
+// Toggle one of "People" panel tabs in side tray.
+class LLTogglePanelPeopleTab : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string panel_name = userdata.asString();
+
+		LLSD param;
+		param["people_panel_tab_name"] = panel_name;
+
+		static LLPanel* friends_panel = NULL;
+		static LLPanel* groups_panel = NULL;
+		static LLPanel* nearby_panel = NULL;
+
+		if (panel_name == "friends_panel")
+		{
+			return togglePeoplePanel(friends_panel, panel_name, param);
+		}
+		else if (panel_name == "groups_panel")
+		{
+			return togglePeoplePanel(groups_panel, panel_name, param);
+		}
+		else if (panel_name == "nearby_panel")
+		{
+			return togglePeoplePanel(nearby_panel, panel_name, param);
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	static bool togglePeoplePanel(LLPanel* &panel, const std::string& panel_name, const LLSD& param)
+	{
+		if(!panel)
+		{
+			panel = LLSideTray::getInstance()->getPanel(panel_name);
+			if(!panel)
+				return false;
+		}
+
+		LLSideTray::getInstance()->togglePanel(panel, "panel_people", param);
+
+		return true;
+	}
+};
+
+BOOL check_admin_override(void*)
+{
+	return gAgent.getAdminOverride();
+}
+
+void handle_admin_override_toggle(void*)
+{
+	gAgent.setAdminOverride(!gAgent.getAdminOverride());
+
+	// The above may have affected which debug menus are visible
+	show_debug_menus();
+}
+
+void handle_god_mode(void*)
+{
+	gAgent.requestEnterGodMode();
+}
+
+void handle_leave_god_mode(void*)
+{
+	gAgent.requestLeaveGodMode();
+}
+
+void set_god_level(U8 god_level)
+{
+	U8 old_god_level = gAgent.getGodLevel();
+	gAgent.setGodLevel( god_level );
+	LLViewerParcelMgr::getInstance()->notifyObservers();
+
+	// God mode changes region visibility
+	LLWorldMap::getInstance()->reloadItems(true);
+
+	// inventory in items may change in god mode
+	gObjectList.dirtyAllObjectInventory();
+
+        if(gViewerWindow)
+        {
+            gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT,
+            LLGridManager::getInstance()->isInProductionGrid());
+        }
+    
+        LLSD args;
+	if(god_level > GOD_NOT)
+	{
+		args["LEVEL"] = llformat("%d",(S32)god_level);
+		LLNotificationsUtil::add("EnteringGodMode", args);
+	}
+	else
+	{
+		args["LEVEL"] = llformat("%d",(S32)old_god_level);
+		LLNotificationsUtil::add("LeavingGodMode", args);
+	}
+
+	// changing god-level can affect which menus we see
+	show_debug_menus();
+
+	// changing god-level can invalidate search results
+	LLFloaterSearch *search = dynamic_cast<LLFloaterSearch*>(LLFloaterReg::getInstance("search"));
+	if (search)
+	{
+		search->godLevelChanged(god_level);
+	}
+}
+
+#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+void handle_toggle_hacked_godmode(void*)
+{
+	gHackGodmode = !gHackGodmode;
+	set_god_level(gHackGodmode ? GOD_MAINTENANCE : GOD_NOT);
+}
+
+BOOL check_toggle_hacked_godmode(void*)
+{
+	return gHackGodmode;
+}
+
+bool enable_toggle_hacked_godmode(void*)
+{
+  return !LLGridManager::getInstance()->isInProductionGrid();
+}
+#endif
+
+void process_grant_godlike_powers(LLMessageSystem* msg, void**)
+{
+	LLUUID agent_id;
+	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+	LLUUID session_id;
+	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id);
+	if((agent_id == gAgent.getID()) && (session_id == gAgent.getSessionID()))
+	{
+		U8 god_level;
+		msg->getU8Fast(_PREHASH_GrantData, _PREHASH_GodLevel, god_level);
+		set_god_level(god_level);
+	}
+	else
+	{
+		llwarns << "Grant godlike for wrong agent " << agent_id << llendl;
+	}
+}
+
+/*
+class LLHaveCallingcard : public LLInventoryCollectFunctor
+{
+public:
+	LLHaveCallingcard(const LLUUID& agent_id);
+	virtual ~LLHaveCallingcard() {}
+	virtual bool operator()(LLInventoryCategory* cat,
+							LLInventoryItem* item);
+	BOOL isThere() const { return mIsThere;}
+protected:
+	LLUUID mID;
+	BOOL mIsThere;
+};
+
+LLHaveCallingcard::LLHaveCallingcard(const LLUUID& agent_id) :
+	mID(agent_id),
+	mIsThere(FALSE)
+{
+}
+
+bool LLHaveCallingcard::operator()(LLInventoryCategory* cat,
+								   LLInventoryItem* item)
+{
+	if(item)
+	{
+		if((item->getType() == LLAssetType::AT_CALLINGCARD)
+		   && (item->getCreatorUUID() == mID))
+		{
+			mIsThere = TRUE;
+		}
+	}
+	return FALSE;
+}
+*/
+
+BOOL is_agent_mappable(const LLUUID& agent_id)
+{
+	const LLRelationship* buddy_info = NULL;
+	bool is_friend = LLAvatarActions::isFriend(agent_id);
+
+	if (is_friend)
+		buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id);
+
+	return (buddy_info &&
+		buddy_info->isOnline() &&
+		buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)
+		);
+}
+
+
+// Enable a menu item when you don't have someone's card.
+class LLAvatarEnableAddFriend : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
+		bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID());
+		return new_value;
+	}
+};
+
+void request_friendship(const LLUUID& dest_id)
+{
+	LLViewerObject* dest = gObjectList.findObject(dest_id);
+	if(dest && dest->isAvatar())
+	{
+		std::string full_name;
+		LLNameValue* nvfirst = dest->getNVPair("FirstName");
+		LLNameValue* nvlast = dest->getNVPair("LastName");
+		if(nvfirst && nvlast)
+		{
+			full_name = LLCacheName::buildFullName(
+				nvfirst->getString(), nvlast->getString());
+		}
+		if (!full_name.empty())
+		{
+			LLAvatarActions::requestFriendshipDialog(dest_id, full_name);
+		}
+		else
+		{
+			LLNotificationsUtil::add("CantOfferFriendship");
+		}
+	}
+}
+
+
+class LLEditEnableCustomizeAvatar : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gAgentWearables.areWearablesLoaded();
+		return new_value;
+	}
+};
+
+class LLEnableEditShape : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0);
+	}
+};
+
+bool is_object_sittable()
+{
+	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+
+	if (object && object->getPCode() == LL_PCODE_VOLUME)
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+
+// only works on pie menu
+void handle_object_sit_or_stand()
+{
+	LLPickInfo pick = LLToolPie::getInstance()->getPick();
+	LLViewerObject *object = pick.getObject();;
+	if (!object || pick.mPickType == LLPickInfo::PICK_FLORA)
+	{
+		return;
+	}
+
+	if (sitting_on_selection())
+	{
+		gAgent.standUp();
+		return;
+	}
+
+	// get object selection offset 
+
+	if (object && object->getPCode() == LL_PCODE_VOLUME)
+	{
+
+		gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit);
+		gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+		gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+		gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+		gMessageSystem->nextBlockFast(_PREHASH_TargetObject);
+		gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID);
+		gMessageSystem->addVector3Fast(_PREHASH_Offset, pick.mObjectOffset);
+
+		object->getRegion()->sendReliableMessage();
+	}
+}
+
+void near_sit_down_point(BOOL success, void *)
+{
+	if (success)
+	{
+		gAgent.setFlying(FALSE);
+		gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
+
+		// Might be first sit
+		//LLFirstUse::useSit();
+	}
+}
+
+class LLLandSit : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gAgent.standUp();
+		LLViewerParcelMgr::getInstance()->deselectLand();
+
+		LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal;
+		
+		LLQuaternion target_rot;
+		if (isAgentAvatarValid())
+		{
+			target_rot = gAgentAvatarp->getRotation();
+		}
+		else
+		{
+			target_rot = gAgent.getFrameAgent().getQuaternion();
+		}
+		gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, NULL, 0.7f);
+		return true;
+	}
+};
+
+//-------------------------------------------------------------------
+// Help menu functions
+//-------------------------------------------------------------------
+
+//
+// Major mode switching
+//
+void reset_view_final( BOOL proceed );
+
+void handle_reset_view()
+{
+	if (gAgentCamera.cameraCustomizeAvatar())
+	{
+		// switching to outfit selector should automagically save any currently edited wearable
+		LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "my_outfits"));
+	}
+
+	gAgentCamera.switchCameraPreset(CAMERA_PRESET_REAR_VIEW);
+	reset_view_final( TRUE );
+	LLFloaterCamera::resetCameraMode();
+}
+
+class LLViewResetView : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		handle_reset_view();
+		return true;
+	}
+};
+
+// Note: extra parameters allow this function to be called from dialog.
+void reset_view_final( BOOL proceed ) 
+{
+	if( !proceed )
+	{
+		return;
+	}
+
+	gAgentCamera.resetView(TRUE, TRUE);
+	gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
+}
+
+class LLViewLookAtLastChatter : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gAgentCamera.lookAtLastChat();
+		return true;
+	}
+};
+
+class LLViewMouselook : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (!gAgentCamera.cameraMouselook())
+		{
+			gAgentCamera.changeCameraToMouselook();
+		}
+		else
+		{
+			gAgentCamera.changeCameraToDefault();
+		}
+		return true;
+	}
+};
+
+class LLViewDefaultUISize : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gSavedSettings.setF32("UIScaleFactor", 1.0f);
+		gSavedSettings.setBOOL("UIAutoScale", FALSE);	
+		gViewerWindow->reshape(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
+		return true;
+	}
+};
+
+class LLEditDuplicate : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if(LLEditMenuHandler::gEditMenuHandler)
+		{
+			LLEditMenuHandler::gEditMenuHandler->duplicate();
+		}
+		return true;
+	}
+};
+
+class LLEditEnableDuplicate : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDuplicate();
+		return new_value;
+	}
+};
+
+void handle_duplicate_in_place(void*)
+{
+	llinfos << "handle_duplicate_in_place" << llendl;
+
+	LLVector3 offset(0.f, 0.f, 0.f);
+	LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE);
+}
+
+/* dead code 30-apr-2008
+void handle_deed_object_to_group(void*)
+{
+	LLUUID group_id;
+	
+	LLSelectMgr::getInstance()->selectGetGroup(group_id);
+	LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE);
+	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT);
+}
+
+BOOL enable_deed_object_to_group(void*)
+{
+	if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) return FALSE;
+	LLPermissions perm;
+	LLUUID group_id;
+
+	if (LLSelectMgr::getInstance()->selectGetGroup(group_id) &&
+		gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) &&
+		LLSelectMgr::getInstance()->selectGetPermissions(perm) &&
+		perm.deedToGroup(gAgent.getID(), group_id))
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+*/
+
+
+/*
+ * No longer able to support viewer side manipulations in this way
+ *
+void god_force_inv_owner_permissive(LLViewerObject* object,
+									LLInventoryObject::object_list_t* inventory,
+									S32 serial_num,
+									void*)
+{
+	typedef std::vector<LLPointer<LLViewerInventoryItem> > item_array_t;
+	item_array_t items;
+
+	LLInventoryObject::object_list_t::const_iterator inv_it = inventory->begin();
+	LLInventoryObject::object_list_t::const_iterator inv_end = inventory->end();
+	for ( ; inv_it != inv_end; ++inv_it)
+	{
+		if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY))
+		{
+			LLInventoryObject* obj = *inv_it;
+			LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem((LLViewerInventoryItem*)obj);
+			LLPermissions perm(new_item->getPermissions());
+			perm.setMaskBase(PERM_ALL);
+			perm.setMaskOwner(PERM_ALL);
+			new_item->setPermissions(perm);
+			items.push_back(new_item);
+		}
+	}
+	item_array_t::iterator end = items.end();
+	item_array_t::iterator it;
+	for(it = items.begin(); it != end; ++it)
+	{
+		// since we have the inventory item in the callback, it should not
+		// invalidate iteration through the selection manager.
+		object->updateInventory((*it), TASK_INVENTORY_ITEM_KEY, false);
+	}
+}
+*/
+
+void handle_object_owner_permissive(void*)
+{
+	// only send this if they're a god.
+	if(gAgent.isGodlike())
+	{
+		// do the objects.
+		LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE);
+		LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE);
+	}
+}
+
+void handle_object_owner_self(void*)
+{
+	// only send this if they're a god.
+	if(gAgent.isGodlike())
+	{
+		LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID(), TRUE);
+	}
+}
+
+// Shortcut to set owner permissions to not editable.
+void handle_object_lock(void*)
+{
+	LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY);
+}
+
+void handle_object_asset_ids(void*)
+{
+	// only send this if they're a god.
+	if (gAgent.isGodlike())
+	{
+		LLSelectMgr::getInstance()->sendGodlikeRequest("objectinfo", "assetids");
+	}
+}
+
+void handle_force_parcel_owner_to_me(void*)
+{
+	LLViewerParcelMgr::getInstance()->sendParcelGodForceOwner( gAgent.getID() );
+}
+
+void handle_force_parcel_to_content(void*)
+{
+	LLViewerParcelMgr::getInstance()->sendParcelGodForceToContent();
+}
+
+void handle_claim_public_land(void*)
+{
+	if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion())
+	{
+		LLNotificationsUtil::add("ClaimPublicLand");
+		return;
+	}
+
+	LLVector3d west_south_global;
+	LLVector3d east_north_global;
+	LLViewerParcelMgr::getInstance()->getSelection(west_south_global, east_north_global);
+	LLVector3 west_south = gAgent.getPosAgentFromGlobal(west_south_global);
+	LLVector3 east_north = gAgent.getPosAgentFromGlobal(east_north_global);
+
+	LLMessageSystem* msg = gMessageSystem;
+	msg->newMessage("GodlikeMessage");
+	msg->nextBlock("AgentData");
+	msg->addUUID("AgentID", gAgent.getID());
+	msg->addUUID("SessionID", gAgent.getSessionID());
+	msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
+	msg->nextBlock("MethodData");
+	msg->addString("Method", "claimpublicland");
+	msg->addUUID("Invoice", LLUUID::null);
+	std::string buffer;
+	buffer = llformat( "%f", west_south.mV[VX]);
+	msg->nextBlock("ParamList");
+	msg->addString("Parameter", buffer);
+	buffer = llformat( "%f", west_south.mV[VY]);
+	msg->nextBlock("ParamList");
+	msg->addString("Parameter", buffer);
+	buffer = llformat( "%f", east_north.mV[VX]);
+	msg->nextBlock("ParamList");
+	msg->addString("Parameter", buffer);
+	buffer = llformat( "%f", east_north.mV[VY]);
+	msg->nextBlock("ParamList");
+	msg->addString("Parameter", buffer);
+	gAgent.sendReliableMessage();
+}
+
+
+
+// HACK for easily testing new avatar geometry
+void handle_god_request_avatar_geometry(void *)
+{
+	if (gAgent.isGodlike())
+	{
+		LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", "");
+	}
+}
+
+
+void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
+{
+	if(gAgentCamera.cameraMouselook())
+	{
+		gAgentCamera.changeCameraToDefault();
+	}
+	//gInventoryView->setPanelOpen(TRUE);
+
+	std::string error;
+	LLDynamicArray<LLViewerObject*> derez_objects;
+	
+	// Check conditions that we can't deal with, building a list of
+	// everything that we'll actually be derezzing.
+	LLViewerRegion* first_region = NULL;
+	for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
+		 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* object = node->getObject();
+		LLViewerRegion* region = object->getRegion();
+		if (!first_region)
+		{
+			first_region = region;
+		}
+		else
+		{
+			if(region != first_region)
+			{
+				// Derez doesn't work at all if the some of the objects
+				// are in regions besides the first object selected.
+				
+				// ...crosses region boundaries
+				error = "AcquireErrorObjectSpan";
+				break;
+			}
+		}
+		if (object->isAvatar())
+		{
+			// ...don't acquire avatars
+			continue;
+		}
+
+		// If AssetContainers are being sent back, they will appear as 
+		// boxes in the owner's inventory.
+		if (object->getNVPair("AssetContainer")
+			&& dest != DRD_RETURN_TO_OWNER)
+		{
+			// this object is an asset container, derez its contents, not it
+			llwarns << "Attempt to derez deprecated AssetContainer object type not supported." << llendl;
+			/*
+			object->requestInventory(container_inventory_arrived, 
+				(void *)(BOOL)(DRD_TAKE_INTO_AGENT_INVENTORY == dest));
+			*/
+			continue;
+		}
+		BOOL can_derez_current = FALSE;
+		switch(dest)
+		{
+		case DRD_TAKE_INTO_AGENT_INVENTORY:
+		case DRD_TRASH:
+			if( (node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify())
+				|| (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE)) )
+			{
+				can_derez_current = TRUE;
+			}
+			break;
+
+		case DRD_RETURN_TO_OWNER:
+			can_derez_current = TRUE;
+			break;
+
+		default:
+			if((node->mPermissions->allowTransferTo(gAgent.getID())
+				&& object->permCopy())
+			   || gAgent.isGodlike())
+			{
+				can_derez_current = TRUE;
+			}
+			break;
+		}
+		if(can_derez_current)
+		{
+			derez_objects.put(object);
+		}
+	}
+
+	// This constant is based on (1200 - HEADER_SIZE) / 4 bytes per
+	// root.  I lopped off a few (33) to provide a bit
+	// pad. HEADER_SIZE is currently 67 bytes, most of which is UUIDs.
+	// This gives us a maximum of 63500 root objects - which should
+	// satisfy anybody.
+	const S32 MAX_ROOTS_PER_PACKET = 250;
+	const S32 MAX_PACKET_COUNT = 254;
+	F32 packets = ceil((F32)derez_objects.count() / (F32)MAX_ROOTS_PER_PACKET);
+	if(packets > (F32)MAX_PACKET_COUNT)
+	{
+		error = "AcquireErrorTooManyObjects";
+	}
+
+	if(error.empty() && derez_objects.count() > 0)
+	{
+		U8 d = (U8)dest;
+		LLUUID tid;
+		tid.generate();
+		U8 packet_count = (U8)packets;
+		S32 object_index = 0;
+		S32 objects_in_packet = 0;
+		LLMessageSystem* msg = gMessageSystem;
+		for(U8 packet_number = 0;
+			packet_number < packet_count;
+			++packet_number)
+		{
+			msg->newMessageFast(_PREHASH_DeRezObject);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->nextBlockFast(_PREHASH_AgentBlock);
+			msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
+			msg->addU8Fast(_PREHASH_Destination, d);	
+			msg->addUUIDFast(_PREHASH_DestinationID, dest_id);
+			msg->addUUIDFast(_PREHASH_TransactionID, tid);
+			msg->addU8Fast(_PREHASH_PacketCount, packet_count);
+			msg->addU8Fast(_PREHASH_PacketNumber, packet_number);
+			objects_in_packet = 0;
+			while((object_index < derez_objects.count())
+				  && (objects_in_packet++ < MAX_ROOTS_PER_PACKET))
+
+			{
+				LLViewerObject* object = derez_objects.get(object_index++);
+				msg->nextBlockFast(_PREHASH_ObjectData);
+				msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID());
+				// VEFFECT: DerezObject
+				LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE);
+				effectp->setPositionGlobal(object->getPositionGlobal());
+				effectp->setColor(LLColor4U(gAgent.getEffectColor()));
+			}
+			msg->sendReliable(first_region->getHost());
+		}
+		make_ui_sound("UISndObjectRezOut");
+
+		// Busy count decremented by inventory update, so only increment
+		// if will be causing an update.
+		if (dest != DRD_RETURN_TO_OWNER)
+		{
+			gViewerWindow->getWindow()->incBusyCount();
+		}
+	}
+	else if(!error.empty())
+	{
+		LLNotificationsUtil::add(error);
+	}
+}
+
+void handle_take_copy()
+{
+	if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
+
+	const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+	derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
+}
+
+// You can return an object to its owner if it is on your land.
+class LLObjectReturn : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true;
+		
+		mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
+
+		LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2));
+		return true;
+	}
+
+	bool onReturnToOwner(const LLSD& notification, const LLSD& response)
+	{
+		S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+		if (0 == option)
+		{
+			// Ignore category ID for this derez destination.
+			derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null);
+		}
+
+		// drop reference to current selection
+		mObjectSelection = NULL;
+		return false;
+	}
+
+protected:
+	LLObjectSelectionHandle mObjectSelection;
+};
+
+
+// Allow return to owner if one or more of the selected items is
+// over land you own.
+class LLObjectEnableReturn : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+		{
+			// Do not enable if nothing selected
+			return false;
+		}
+#ifdef HACKED_GODLIKE_VIEWER
+		bool new_value = true;
+#else
+		bool new_value = false;
+		if (gAgent.isGodlike())
+		{
+			new_value = true;
+		}
+		else
+		{
+			LLViewerRegion* region = gAgent.getRegion();
+			if (region)
+			{
+				// Estate owners and managers can always return objects.
+				if (region->canManageEstate())
+				{
+					new_value = true;
+				}
+				else
+				{
+					struct f : public LLSelectedObjectFunctor
+					{
+						virtual bool apply(LLViewerObject* obj)
+						{
+							return 
+								obj->permModify() ||
+								obj->isReturnable();
+						}
+					} func;
+					const bool firstonly = true;
+					new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
+				}
+			}
+		}
+#endif
+		return new_value;
+	}
+};
+
+void force_take_copy(void*)
+{
+	if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
+	const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+	derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id);
+}
+
+void handle_take()
+{
+	// we want to use the folder this was derezzed from if it's
+	// available. Otherwise, derez to the normal place.
+	if(LLSelectMgr::getInstance()->getSelection()->isEmpty())
+	{
+		return;
+	}
+	
+	BOOL you_own_everything = TRUE;
+	BOOL locked_but_takeable_object = FALSE;
+	LLUUID category_id;
+	
+	for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+		 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* object = node->getObject();
+		if(object)
+		{
+			if(!object->permYouOwner())
+			{
+				you_own_everything = FALSE;
+			}
+
+			if(!object->permMove())
+			{
+				locked_but_takeable_object = TRUE;
+			}
+		}
+		if(node->mFolderID.notNull())
+		{
+			if(category_id.isNull())
+			{
+				category_id = node->mFolderID;
+			}
+			else if(category_id != node->mFolderID)
+			{
+				// we have found two potential destinations. break out
+				// now and send to the default location.
+				category_id.setNull();
+				break;
+			}
+		}
+	}
+	if(category_id.notNull())
+	{
+		// there is an unambiguous destination. See if this agent has
+		// such a location and it is not in the trash or library
+		if(!gInventory.getCategory(category_id))
+		{
+			// nope, set to NULL.
+			category_id.setNull();
+		}
+		if(category_id.notNull())
+		{
+		        // check trash
+			const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+			if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash))
+			{
+				category_id.setNull();
+			}
+
+			// check library
+			if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID()))
+			{
+				category_id.setNull();
+			}
+
+		}
+	}
+	if(category_id.isNull())
+	{
+		category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+	}
+	LLSD payload;
+	payload["folder_id"] = category_id;
+
+	LLNotification::Params params("ConfirmObjectTakeLock");
+	params.payload(payload);
+	params.functor.function(confirm_take);
+
+	if(locked_but_takeable_object ||
+	   !you_own_everything)
+	{
+		if(locked_but_takeable_object && you_own_everything)
+		{
+			params.name("ConfirmObjectTakeLock");
+		}
+		else if(!locked_but_takeable_object && !you_own_everything)
+		{
+			params.name("ConfirmObjectTakeNoOwn");
+		}
+		else
+		{
+			params.name("ConfirmObjectTakeLockNoOwn");
+		}
+	
+		LLNotifications::instance().add(params);
+	}
+	else
+	{
+		LLNotifications::instance().forceResponse(params, 0);
+	}
+}
+
+void handle_object_show_inspector()
+{
+	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+	LLViewerObject* objectp = selection->getFirstRootObject(TRUE);
+ 	if (!objectp)
+ 	{
+ 		return;
+ 	}
+
+	LLSD params;
+	params["object_id"] = objectp->getID();
+	LLFloaterReg::showInstance("inspect_object", params);
+}
+
+void handle_avatar_show_inspector()
+{
+	LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+	if(avatar)
+	{
+		LLSD params;
+		params["avatar_id"] = avatar->getID();
+		LLFloaterReg::showInstance("inspect_avatar", params);
+	}
+}
+
+
+
+bool confirm_take(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if(enable_take() && (option == 0))
+	{
+		derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID());
+	}
+	return false;
+}
+
+// You can take an item when it is public and transferrable, or when
+// you own it. We err on the side of enabling the item when at least
+// one item selected can be copied to inventory.
+BOOL enable_take()
+{
+	if (sitting_on_selection())
+	{
+		return FALSE;
+	}
+
+	for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
+		 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* object = node->getObject();
+		if (object->isAvatar())
+		{
+			// ...don't acquire avatars
+			continue;
+		}
+
+#ifdef HACKED_GODLIKE_VIEWER
+		return TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+		if (!LLGridManager::getInstance()->isInProductionGrid() 
+            && gAgent.isGodlike())
+		{
+			return TRUE;
+		}
+# endif
+		if((node->mPermissions->allowTransferTo(gAgent.getID())
+			&& object->permModify())
+		   || (node->mPermissions->getOwner() == gAgent.getID()))
+		{
+			return TRUE;
+		}
+#endif
+	}
+	return FALSE;
+}
+
+
+void handle_buy_or_take()
+{
+	if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+	{
+		return;
+	}
+
+	if (is_selection_buy_not_take())
+	{
+		S32 total_price = selection_price();
+
+		if (total_price <= gStatusBar->getBalance() || total_price == 0)
+		{
+			handle_buy();
+		}
+		else
+		{
+			LLStringUtil::format_map_t args;
+			args["AMOUNT"] = llformat("%d", total_price);
+			LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "BuyingCosts", args ), total_price );
+		}
+	}
+	else
+	{
+		handle_take();
+	}
+}
+
+bool visible_buy_object()
+{
+	return is_selection_buy_not_take() && enable_buy_object();
+}
+
+bool visible_take_object()
+{
+	return !is_selection_buy_not_take() && enable_take();
+}
+
+bool tools_visible_buy_object()
+{
+	return is_selection_buy_not_take();
+}
+
+bool tools_visible_take_object()
+{
+	return !is_selection_buy_not_take();
+}
+
+class LLToolsEnableBuyOrTake : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool is_buy = is_selection_buy_not_take();
+		bool new_value = is_buy ? enable_buy_object() : enable_take();
+		return new_value;
+	}
+};
+
+// This is a small helper function to determine if we have a buy or a
+// take in the selection. This method is to help with the aliasing
+// problems of putting buy and take in the same pie menu space. After
+// a fair amont of discussion, it was determined to prefer buy over
+// take. The reasoning follows from the fact that when users walk up
+// to buy something, they will click on one or more items. Thus, if
+// anything is for sale, it becomes a buy operation, and the server
+// will group all of the buy items, and copyable/modifiable items into
+// one package and give the end user as much as the permissions will
+// allow. If the user wanted to take something, they will select fewer
+// and fewer items until only 'takeable' items are left. The one
+// exception is if you own everything in the selection that is for
+// sale, in this case, you can't buy stuff from yourself, so you can
+// take it.
+// return value = TRUE if selection is a 'buy'.
+//                FALSE if selection is a 'take'
+BOOL is_selection_buy_not_take()
+{
+	for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+		 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* obj = node->getObject();
+		if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
+		{
+			// you do not own the object and it is for sale, thus,
+			// it's a buy
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+S32 selection_price()
+{
+	S32 total_price = 0;
+	for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+		 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* obj = node->getObject();
+		if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale()))
+		{
+			// you do not own the object and it is for sale.
+			// Add its price.
+			total_price += node->mSaleInfo.getSalePrice();
+		}
+	}
+
+	return total_price;
+}
+/*
+bool callback_show_buy_currency(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (0 == option)
+	{
+		llinfos << "Loading page " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL") << llendl;
+		LLWeb::loadURL(LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL"));
+	}
+	return false;
+}
+*/
+
+void show_buy_currency(const char* extra)
+{
+	// Don't show currency web page for branded clients.
+/*
+	std::ostringstream mesg;
+	if (extra != NULL)
+	{	
+		mesg << extra << "\n \n";
+	}
+	mesg << "Go to " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")<< "\nfor information on purchasing currency?";
+*/
+	LLSD args;
+	if (extra != NULL)
+	{
+		args["EXTRA"] = extra;
+	}
+	LLNotificationsUtil::add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency);
+}
+
+void handle_buy()
+{
+	if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
+
+	LLSaleInfo sale_info;
+	BOOL valid = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
+	if (!valid) return;
+
+	S32 price = sale_info.getSalePrice();
+	
+	if (price > 0 && price > gStatusBar->getBalance())
+	{
+		LLStringUtil::format_map_t args;
+		args["AMOUNT"] = llformat("%d", price);
+		LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("this_object_costs", args), price );
+		return;
+	}
+
+	if (sale_info.getSaleType() == LLSaleInfo::FS_CONTENTS)
+	{
+		handle_buy_contents(sale_info);
+	}
+	else
+	{
+		handle_buy_object(sale_info);
+	}
+}
+
+bool anyone_copy_selection(LLSelectNode* nodep)
+{
+	bool perm_copy = (bool)(nodep->getObject()->permCopy());
+	bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY);
+	return perm_copy && all_copy;
+}
+
+bool for_sale_selection(LLSelectNode* nodep)
+{
+	return nodep->mSaleInfo.isForSale()
+		&& nodep->mPermissions->getMaskOwner() & PERM_TRANSFER
+		&& (nodep->mPermissions->getMaskOwner() & PERM_COPY
+			|| nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY);
+}
+
+BOOL sitting_on_selection()
+{
+	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+	if (!node)
+	{
+		return FALSE;
+	}
+
+	if (!node->mValid)
+	{
+		return FALSE;
+	}
+
+	LLViewerObject* root_object = node->getObject();
+	if (!root_object)
+	{
+		return FALSE;
+	}
+
+	// Need to determine if avatar is sitting on this object
+	if (!isAgentAvatarValid()) return FALSE;
+
+	return (gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == root_object);
+}
+
+class LLToolsSaveToInventory : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if(enable_save_into_inventory(NULL))
+		{
+			derez_objects(DRD_SAVE_INTO_AGENT_INVENTORY, LLUUID::null);
+		}
+		return true;
+	}
+};
+
+class LLToolsSaveToObjectInventory : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+		if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
+		{
+			// *TODO: check to see if the fromtaskid object exists.
+			derez_objects(DRD_SAVE_INTO_TASK_INVENTORY, node->mFromTaskID);
+		}
+		return true;
+	}
+};
+
+// Round the position of all root objects to the grid
+class LLToolsSnapObjectXY : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		F64 snap_size = (F64)gSavedSettings.getF32("GridResolution");
+
+		for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+			 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+		{
+			LLSelectNode* node = *iter;
+			LLViewerObject* obj = node->getObject();
+			if (obj->permModify())
+			{
+				LLVector3d pos_global = obj->getPositionGlobal();
+				F64 round_x = fmod(pos_global.mdV[VX], snap_size);
+				if (round_x < snap_size * 0.5)
+				{
+					// closer to round down
+					pos_global.mdV[VX] -= round_x;
+				}
+				else
+				{
+					// closer to round up
+					pos_global.mdV[VX] -= round_x;
+					pos_global.mdV[VX] += snap_size;
+				}
+
+				F64 round_y = fmod(pos_global.mdV[VY], snap_size);
+				if (round_y < snap_size * 0.5)
+				{
+					pos_global.mdV[VY] -= round_y;
+				}
+				else
+				{
+					pos_global.mdV[VY] -= round_y;
+					pos_global.mdV[VY] += snap_size;
+				}
+
+				obj->setPositionGlobal(pos_global, FALSE);
+			}
+		}
+		LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
+		return true;
+	}
+};
+
+// Determine if the option to cycle between linked prims is shown
+class LLToolsEnableSelectNextPart : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = (gSavedSettings.getBOOL("EditLinkedParts") &&
+				 !LLSelectMgr::getInstance()->getSelection()->isEmpty());
+		return new_value;
+	}
+};
+
+// Cycle selection through linked children in selected object.
+// FIXME: Order of children list is not always the same as sim's idea of link order. This may confuse
+// resis. Need link position added to sim messages to address this.
+class LLToolsSelectNextPart : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+		if (gSavedSettings.getBOOL("EditLinkedParts") && object_count)
+		{
+			LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+			if (selected && selected->getRootEdit())
+			{
+				bool fwd = (userdata.asString() == "next");
+				bool prev = (userdata.asString() == "previous");
+				bool ifwd = (userdata.asString() == "includenext");
+				bool iprev = (userdata.asString() == "includeprevious");
+				LLViewerObject* to_select = NULL;
+				LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren();
+				children.push_front(selected->getRootEdit());	// need root in the list too
+
+				for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter)
+				{
+					if ((*iter)->isSelected())
+					{
+						if (object_count > 1 && (fwd || prev))	// multiple selection, find first or last selected if not include
+						{
+							to_select = *iter;
+							if (fwd)
+							{
+								// stop searching if going forward; repeat to get last hit if backward
+								break;
+							}
+						}
+						else if ((object_count == 1) || (ifwd || iprev))	// single selection or include
+						{
+							if (fwd || ifwd)
+							{
+								++iter;
+								while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected())))
+								{
+									++iter;	// skip sitting avatars and selected if include
+								}
+							}
+							else // backward
+							{
+								iter = (iter == children.begin() ? children.end() : iter);
+								--iter;
+								while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected())))
+								{
+									--iter;	// skip sitting avatars and selected if include
+								}
+							}
+							iter = (iter == children.end() ? children.begin() : iter);
+							to_select = *iter;
+							break;
+						}
+					}
+				}
+
+				if (to_select)
+				{
+					if (gFocusMgr.childHasKeyboardFocus(gFloaterTools))
+					{
+						gFocusMgr.setKeyboardFocus(NULL);	// force edit toolbox to commit any changes
+					}
+					if (fwd || prev)
+					{
+						LLSelectMgr::getInstance()->deselectAll();
+					}
+					LLSelectMgr::getInstance()->selectObjectOnly(to_select);
+					return true;
+				}
+			}
+		}
+		return true;
+	}
+};
+
+class LLToolsStopAllAnimations : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gAgent.stopCurrentAnimations();
+		return true;
+	}
+};
+
+class LLToolsReleaseKeys : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gAgent.forceReleaseControls();
+
+		return true;
+	}
+};
+
+class LLToolsEnableReleaseKeys : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return gAgent.anyControlGrabbed();
+	}
+};
+
+
+class LLEditEnableCut : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut();
+		return new_value;
+	}
+};
+
+class LLEditCut : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if( LLEditMenuHandler::gEditMenuHandler )
+		{
+			LLEditMenuHandler::gEditMenuHandler->cut();
+		}
+		return true;
+	}
+};
+
+class LLEditEnableCopy : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy();
+		return new_value;
+	}
+};
+
+class LLEditCopy : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if( LLEditMenuHandler::gEditMenuHandler )
+		{
+			LLEditMenuHandler::gEditMenuHandler->copy();
+		}
+		return true;
+	}
+};
+
+class LLEditEnablePaste : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste();
+		return new_value;
+	}
+};
+
+class LLEditPaste : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if( LLEditMenuHandler::gEditMenuHandler )
+		{
+			LLEditMenuHandler::gEditMenuHandler->paste();
+		}
+		return true;
+	}
+};
+
+class LLEditEnableDelete : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete();
+		return new_value;
+	}
+};
+
+class LLEditDelete : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// If a text field can do a deletion, it gets precedence over deleting
+		// an object in the world.
+		if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete())
+		{
+			LLEditMenuHandler::gEditMenuHandler->doDelete();
+		}
+
+		// and close any pie/context menus when done
+		gMenuHolder->hideMenus();
+
+		// When deleting an object we may not actually be done
+		// Keep selection so we know what to delete when confirmation is needed about the delete
+		gMenuObject->hide();
+		return true;
+	}
+};
+
+bool enable_object_delete()
+{
+	bool new_value = 
+#ifdef HACKED_GODLIKE_VIEWER
+	TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+	(!LLGridManager::getInstance()->isInProductionGrid()
+     && gAgent.isGodlike()) ||
+# endif
+	LLSelectMgr::getInstance()->canDoDelete();
+#endif
+	return new_value;
+}
+
+void handle_object_delete()
+{
+
+		if (LLSelectMgr::getInstance())
+		{
+			LLSelectMgr::getInstance()->doDelete();
+		}
+
+		// and close any pie/context menus when done
+		gMenuHolder->hideMenus();
+
+		// When deleting an object we may not actually be done
+		// Keep selection so we know what to delete when confirmation is needed about the delete
+		gMenuObject->hide();
+		return;
+}
+
+void handle_force_delete(void*)
+{
+	LLSelectMgr::getInstance()->selectForceDelete();
+}
+
+class LLViewEnableJoystickFlycam : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled"));
+		return new_value;
+	}
+};
+
+class LLViewEnableLastChatter : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// *TODO: add check that last chatter is in range
+		bool new_value = (gAgentCamera.cameraThirdPerson() && gAgent.getLastChatter().notNull());
+		return new_value;
+	}
+};
+
+class LLEditEnableDeselect : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect();
+		return new_value;
+	}
+};
+
+class LLEditDeselect : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if( LLEditMenuHandler::gEditMenuHandler )
+		{
+			LLEditMenuHandler::gEditMenuHandler->deselect();
+		}
+		return true;
+	}
+};
+
+class LLEditEnableSelectAll : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll();
+		return new_value;
+	}
+};
+
+
+class LLEditSelectAll : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if( LLEditMenuHandler::gEditMenuHandler )
+		{
+			LLEditMenuHandler::gEditMenuHandler->selectAll();
+		}
+		return true;
+	}
+};
+
+
+class LLEditEnableUndo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo();
+		return new_value;
+	}
+};
+
+class LLEditUndo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() )
+		{
+			LLEditMenuHandler::gEditMenuHandler->undo();
+		}
+		return true;
+	}
+};
+
+class LLEditEnableRedo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo();
+		return new_value;
+	}
+};
+
+class LLEditRedo : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() )
+		{
+			LLEditMenuHandler::gEditMenuHandler->redo();
+		}
+		return true;
+	}
+};
+
+
+
+void print_object_info(void*)
+{
+	LLSelectMgr::getInstance()->selectionDump();
+}
+
+void print_agent_nvpairs(void*)
+{
+	LLViewerObject *objectp;
+
+	llinfos << "Agent Name Value Pairs" << llendl;
+
+	objectp = gObjectList.findObject(gAgentID);
+	if (objectp)
+	{
+		objectp->printNameValuePairs();
+	}
+	else
+	{
+		llinfos << "Can't find agent object" << llendl;
+	}
+
+	llinfos << "Camera at " << gAgentCamera.getCameraPositionGlobal() << llendl;
+}
+
+void show_debug_menus()
+{
+	// this might get called at login screen where there is no menu so only toggle it if one exists
+	if ( gMenuBarView )
+	{
+		BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
+		BOOL qamode = gSavedSettings.getBOOL("QAMode");
+
+		gMenuBarView->setItemVisible("Advanced", debug);
+// 		gMenuBarView->setItemEnabled("Advanced", debug); // Don't disable Advanced keyboard shortcuts when hidden
+		
+		gMenuBarView->setItemVisible("Debug", qamode);
+		gMenuBarView->setItemEnabled("Debug", qamode);
+
+		gMenuBarView->setItemVisible("Develop", qamode);
+		gMenuBarView->setItemEnabled("Develop", qamode);
+
+		// Server ('Admin') menu hidden when not in godmode.
+		const bool show_server_menu = (gAgent.getGodLevel() > GOD_NOT || (debug && gAgent.getAdminOverride()));
+		gMenuBarView->setItemVisible("Admin", show_server_menu);
+		gMenuBarView->setItemEnabled("Admin", show_server_menu);
+	}
+	if (gLoginMenuBarView)
+	{
+		BOOL debug = gSavedSettings.getBOOL("UseDebugMenus");
+		gLoginMenuBarView->setItemVisible("Debug", debug);
+		gLoginMenuBarView->setItemEnabled("Debug", debug);
+	}
+}
+
+void toggle_debug_menus(void*)
+{
+	BOOL visible = ! gSavedSettings.getBOOL("UseDebugMenus");
+	gSavedSettings.setBOOL("UseDebugMenus", visible);
+	show_debug_menus();
+}
+
+
+// LLUUID gExporterRequestID;
+// std::string gExportDirectory;
+
+// LLUploadDialog *gExportDialog = NULL;
+
+// void handle_export_selected( void * )
+// {
+// 	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+// 	if (selection->isEmpty())
+// 	{
+// 		return;
+// 	}
+// 	llinfos << "Exporting selected objects:" << llendl;
+
+// 	gExporterRequestID.generate();
+// 	gExportDirectory = "";
+
+// 	LLMessageSystem* msg = gMessageSystem;
+// 	msg->newMessageFast(_PREHASH_ObjectExportSelected);
+// 	msg->nextBlockFast(_PREHASH_AgentData);
+// 	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+// 	msg->addUUIDFast(_PREHASH_RequestID, gExporterRequestID);
+// 	msg->addS16Fast(_PREHASH_VolumeDetail, 4);
+
+// 	for (LLObjectSelection::root_iterator iter = selection->root_begin();
+// 		 iter != selection->root_end(); iter++)
+// 	{
+// 		LLSelectNode* node = *iter;
+// 		LLViewerObject* object = node->getObject();
+// 		msg->nextBlockFast(_PREHASH_ObjectData);
+// 		msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
+// 		llinfos << "Object: " << object->getID() << llendl;
+// 	}
+// 	msg->sendReliable(gAgent.getRegion()->getHost());
+
+// 	gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects...");
+// }
+//
+
+
+class LLWorldSetHomeLocation : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// we just send the message and let the server check for failure cases
+		// server will echo back a "Home position set." alert if it succeeds
+		// and the home location screencapture happens when that alert is recieved
+		gAgent.setStartPosition(START_LOCATION_ID_HOME);
+		return true;
+	}
+};
+
+class LLWorldTeleportHome : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gAgent.teleportHome();
+		return true;
+	}
+};
+
+class LLWorldAlwaysRun : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// as well as altering the default walk-vs-run state,
+		// we also change the *current* walk-vs-run state.
+		if (gAgent.getAlwaysRun())
+		{
+			gAgent.clearAlwaysRun();
+			gAgent.clearRunning();
+		}
+		else
+		{
+			gAgent.setAlwaysRun();
+			gAgent.setRunning();
+		}
+
+		// tell the simulator.
+		gAgent.sendWalkRun(gAgent.getAlwaysRun());
+
+		// Update Movement Controls according to AlwaysRun mode
+		LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun());
+
+		return true;
+	}
+};
+
+class LLWorldCheckAlwaysRun : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gAgent.getAlwaysRun();
+		return new_value;
+	}
+};
+
+class LLWorldSetAway : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (gAgent.getAFK())
+		{
+			gAgent.clearAFK();
+		}
+		else
+		{
+			gAgent.setAFK();
+		}
+		return true;
+	}
+};
+
+class LLWorldSetBusy : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (gAgent.getBusy())
+		{
+			gAgent.clearBusy();
+		}
+		else
+		{
+			gAgent.setBusy();
+			LLNotificationsUtil::add("BusyModeSet");
+		}
+		return true;
+	}
+};
+
+class LLWorldCreateLandmark : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "create_landmark"));
+
+		return true;
+	}
+};
+
+class LLWorldPlaceProfile : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLSideTray::getInstance()->showPanel("panel_places", LLSD().with("type", "agent"));
+
+		return true;
+	}
+};
+
+void handle_look_at_selection(const LLSD& param)
+{
+	const F32 PADDING_FACTOR = 1.75f;
+	BOOL zoom = (param.asString() == "zoom");
+	if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
+	{
+		gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+
+		LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
+		F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
+		F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
+
+		LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent();
+		obj_to_cam.normVec();
+
+		LLUUID object_id;
+		if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())
+		{
+			object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID;
+		}
+		if (zoom)
+		{
+			// Make sure we are not increasing the distance between the camera and object
+			LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal();
+			distance = llmin(distance, (F32) orig_distance.length());
+				
+			gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), 
+										LLSelectMgr::getInstance()->getSelectionCenterGlobal(), 
+										object_id );
+			
+		}
+		else
+		{
+			gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id );
+		}	
+	}
+}
+
+void handle_zoom_to_object(LLUUID object_id)
+{
+	const F32 PADDING_FACTOR = 2.f;
+
+	LLViewerObject* object = gObjectList.findObject(object_id);
+
+	if (object)
+	{
+		gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+
+		LLBBox bbox = object->getBoundingBoxAgent() ;
+		F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView());
+		F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view);
+
+		LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent();
+		obj_to_cam.normVec();
+
+
+			LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
+
+			gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance), 
+											object_center_global, 
+											object_id );
+	}
+}
+
+class LLAvatarInviteToGroup : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+		if(avatar)
+		{
+			LLAvatarActions::inviteToGroup(avatar->getID());
+		}
+		return true;
+	}
+};
+
+class LLAvatarAddFriend : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+		if(avatar && !LLAvatarActions::isFriend(avatar->getID()))
+		{
+			request_friendship(avatar->getID());
+		}
+		return true;
+	}
+};
+
+class LLAvatarAddContact : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+		if(avatar)
+		{
+			create_inventory_callingcard(avatar->getID());
+		}
+		return true;
+	}
+};
+
+bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (option == 0)
+	{
+		gAgent.clearBusy();
+	}
+
+	LLViewerObject* objectp = selection->getPrimaryObject();
+
+	// Show avatar's name if paying attachment
+	if (objectp && objectp->isAttachment())
+	{
+		while (objectp && !objectp->isAvatar())
+		{
+			objectp = (LLViewerObject*)objectp->getParent();
+		}
+	}
+
+	if (objectp)
+	{
+		if (objectp->isAvatar())
+		{
+			const bool is_group = false;
+			LLFloaterPayUtil::payDirectly(&give_money,
+									  objectp->getID(),
+									  is_group);
+		}
+		else
+		{
+			LLFloaterPayUtil::payViaObject(&give_money, selection);
+		}
+	}
+	return false;
+}
+
+void handle_give_money_dialog()
+{
+	LLNotification::Params params("BusyModePay");
+	params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection()));
+
+	if (gAgent.getBusy())
+	{
+		// warn users of being in busy mode during a transaction
+		LLNotifications::instance().add(params);
+	}
+	else
+	{
+		LLNotifications::instance().forceResponse(params, 1);
+	}
+}
+
+bool enable_pay_avatar()
+{
+	LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+	LLVOAvatar* avatar = find_avatar_from_object(obj);
+	return (avatar != NULL);
+}
+
+bool enable_pay_object()
+{
+	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+	if( object )
+	{
+		LLViewerObject *parent = (LLViewerObject *)object->getParent();
+		if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney()))
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
+bool enable_object_stand_up()
+{
+	// 'Object Stand Up' menu item is enabled when agent is sitting on selection
+	return sitting_on_selection();
+}
+
+bool enable_object_sit(LLUICtrl* ctrl)
+{
+	// 'Object Sit' menu item is enabled when agent is not sitting on selection
+	bool sitting_on_sel = sitting_on_selection();
+	if (!sitting_on_sel)
+	{
+		std::string item_name = ctrl->getName();
+
+		// init default labels
+		init_default_item_label(item_name);
+
+		// Update label
+		LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+		if (node && node->mValid && !node->mSitName.empty())
+		{
+			gMenuHolder->childSetText(item_name, node->mSitName);
+		}
+		else
+		{
+			gMenuHolder->childSetText(item_name, get_default_item_label(item_name));
+		}
+	}
+	return !sitting_on_sel && is_object_sittable();
+}
+
+void dump_select_mgr(void*)
+{
+	LLSelectMgr::getInstance()->dump();
+}
+
+void dump_inventory(void*)
+{
+	gInventory.dumpInventory();
+}
+
+
+void handle_dump_followcam(void*)
+{
+	LLFollowCamMgr::dump();
+}
+
+void handle_viewer_enable_message_log(void*)
+{
+	gMessageSystem->startLogging();
+}
+
+void handle_viewer_disable_message_log(void*)
+{
+	gMessageSystem->stopLogging();
+}
+
+void handle_customize_avatar()
+{
+	LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "my_outfits"));
+}
+
+void handle_edit_outfit()
+{
+	LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_outfit"));
+}
+
+void handle_edit_shape()
+{
+	LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD().with("type", "edit_shape"));
+}
+
+void handle_report_abuse()
+{
+	// Prevent menu from appearing in screen shot.
+	gMenuHolder->hideMenus();
+	LLFloaterReporter::showFromMenu(COMPLAINT_REPORT);
+}
+
+void handle_buy_currency()
+{
+	LLBuyCurrencyHTML::openCurrencyFloater();
+}
+
+class LLFloaterVisible : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string floater_name = userdata.asString();
+		bool new_value = false;
+		{
+			new_value = LLFloaterReg::instanceVisible(floater_name);
+		}
+		return new_value;
+	}
+};
+
+class LLShowHelp : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string help_topic = userdata.asString();
+		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+		vhelp->showTopic(help_topic);
+		return true;
+	}
+};
+
+class LLToggleHelp : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser"));
+		if (help_browser && help_browser->isInVisibleChain())
+		{
+			help_browser->closeFloater();
+		}
+		else
+		{
+			std::string help_topic = userdata.asString();
+			LLViewerHelp* vhelp = LLViewerHelp::getInstance();
+			vhelp->showTopic(help_topic);
+		}
+		return true;
+	}
+};
+
+class LLShowSidetrayPanel : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string panel_name = userdata.asString();
+
+		LLPanel* panel = LLSideTray::getInstance()->getPanel(panel_name);
+		if (panel)
+		{
+			if (panel->isInVisibleChain())
+			{
+				LLSideTray::getInstance()->hidePanel(panel_name);
+			}
+			else
+			{
+				LLSideTray::getInstance()->showPanel(panel_name);
+			}
+		}
+		return true;
+	}
+};
+
+class LLSidetrayPanelVisible : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string panel_name = userdata.asString();
+		// Toggle the panel
+		if (LLSideTray::getInstance()->isPanelActive(panel_name))
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+		
+	}
+};
+
+
+bool callback_show_url(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (0 == option)
+	{
+		LLWeb::loadURL(notification["payload"]["url"].asString());
+	}
+	return false;
+}
+
+class LLPromptShowURL : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string param = userdata.asString();
+		std::string::size_type offset = param.find(",");
+		if (offset != param.npos)
+		{
+			std::string alert = param.substr(0, offset);
+			std::string url = param.substr(offset+1);
+
+			if(gSavedSettings.getBOOL("UseExternalBrowser"))
+			{ 
+    			LLSD payload;
+    			payload["url"] = url;
+    			LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_url);
+			}
+			else
+			{
+		        LLWeb::loadURL(url);
+			}
+		}
+		else
+		{
+			llinfos << "PromptShowURL invalid parameters! Expecting \"ALERT,URL\"." << llendl;
+		}
+		return true;
+	}
+};
+
+bool callback_show_file(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (0 == option)
+	{
+		LLWeb::loadURL(notification["payload"]["url"]);
+	}
+	return false;
+}
+
+class LLPromptShowFile : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string param = userdata.asString();
+		std::string::size_type offset = param.find(",");
+		if (offset != param.npos)
+		{
+			std::string alert = param.substr(0, offset);
+			std::string file = param.substr(offset+1);
+
+			LLSD payload;
+			payload["url"] = file;
+			LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_file);
+		}
+		else
+		{
+			llinfos << "PromptShowFile invalid parameters! Expecting \"ALERT,FILE\"." << llendl;
+		}
+		return true;
+	}
+};
+
+class LLShowAgentProfile : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLUUID agent_id;
+		if (userdata.asString() == "agent")
+		{
+			agent_id = gAgent.getID();
+		}
+		else if (userdata.asString() == "hit object")
+		{
+			LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+			if (objectp)
+			{
+				agent_id = objectp->getID();
+			}
+		}
+		else
+		{
+			agent_id = userdata.asUUID();
+		}
+
+		LLVOAvatar* avatar = find_avatar_from_object(agent_id);
+		if (avatar)
+		{
+			LLAvatarActions::showProfile(avatar->getID());
+		}
+		return true;
+	}
+};
+
+class LLToggleAgentProfile : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLUUID agent_id;
+		if (userdata.asString() == "agent")
+		{
+			agent_id = gAgent.getID();
+		}
+		else if (userdata.asString() == "hit object")
+		{
+			LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+			if (objectp)
+			{
+				agent_id = objectp->getID();
+			}
+		}
+		else
+		{
+			agent_id = userdata.asUUID();
+		}
+
+		LLVOAvatar* avatar = find_avatar_from_object(agent_id);
+		if (avatar)
+		{
+			if (!LLAvatarActions::profileVisible(avatar->getID()))
+			{
+				LLAvatarActions::showProfile(avatar->getID());
+			}
+			else
+			{
+				LLAvatarActions::hideProfile(avatar->getID());
+			}
+		}
+		return true;
+	}
+};
+
+class LLLandEdit : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		if (gAgentCamera.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") )
+		{
+			// zoom in if we're looking at the avatar
+			gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+
+			gAgentCamera.cameraOrbitOver( F_PI * 0.25f );
+			gViewerWindow->moveCursorToCenter();
+		}
+		else if ( gSavedSettings.getBOOL("EditCameraMovement") )
+		{
+			gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick());
+			gViewerWindow->moveCursorToCenter();
+		}
+
+
+		LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal );
+
+		LLFloaterReg::showInstance("build");
+
+		// Switch to land edit toolset
+		LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolSelectLand::getInstance() );
+		return true;
+	}
+};
+
+class LLWorldEnableBuyLand : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
+								LLViewerParcelMgr::getInstance()->selectionEmpty()
+									? LLViewerParcelMgr::getInstance()->getAgentParcel()
+									: LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(),
+								false);
+		return new_value;
+	}
+};
+
+BOOL enable_buy_land(void*)
+{
+	return LLViewerParcelMgr::getInstance()->canAgentBuyParcel(
+				LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false);
+}
+
+void handle_buy_land()
+{
+	LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance();
+	if (vpm->selectionEmpty())
+	{
+		vpm->selectParcelAt(gAgent.getPositionGlobal());
+	}
+	vpm->startBuyLand();
+}
+
+class LLObjectAttachToAvatar : public view_listener_t
+{
+public:
+	LLObjectAttachToAvatar(bool replace) : mReplace(replace) {}
+	static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; }
+
+private:
+	bool handleEvent(const LLSD& userdata)
+	{
+		setObjectSelection(LLSelectMgr::getInstance()->getSelection());
+		LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject();
+		if (selectedObject)
+		{
+			S32 index = userdata.asInteger();
+			LLViewerJointAttachment* attachment_point = NULL;
+			if (index > 0)
+				attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL);
+			confirmReplaceAttachment(0, attachment_point);
+		}
+		return true;
+	}
+
+	static void onNearAttachObject(BOOL success, void *user_data);
+	void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point);
+
+	struct CallbackData
+	{
+		CallbackData(LLViewerJointAttachment* point, bool replace) : mAttachmentPoint(point), mReplace(replace) {}
+
+		LLViewerJointAttachment*	mAttachmentPoint;
+		bool						mReplace;
+	};
+
+protected:
+	static LLObjectSelectionHandle sObjectSelection;
+	bool mReplace;
+};
+
+LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection;
+
+// static
+void LLObjectAttachToAvatar::onNearAttachObject(BOOL success, void *user_data)
+{
+	if (!user_data) return;
+	CallbackData* cb_data = static_cast<CallbackData*>(user_data);
+
+	if (success)
+	{
+		const LLViewerJointAttachment *attachment = cb_data->mAttachmentPoint;
+		
+		U8 attachment_id = 0;
+		if (attachment)
+		{
+			for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
+				 iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter)
+			{
+				if (iter->second == attachment)
+				{
+					attachment_id = iter->first;
+					break;
+				}
+			}
+		}
+		else
+		{
+			// interpret 0 as "default location"
+			attachment_id = 0;
+		}
+		LLSelectMgr::getInstance()->sendAttach(attachment_id, cb_data->mReplace);
+	}		
+	LLObjectAttachToAvatar::setObjectSelection(NULL);
+
+	delete cb_data;
+}
+
+// static
+void LLObjectAttachToAvatar::confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point)
+{
+	if (option == 0/*YES*/)
+	{
+		LLViewerObject* selectedObject = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
+		if (selectedObject)
+		{
+			const F32 MIN_STOP_DISTANCE = 1.f;	// meters
+			const F32 ARM_LENGTH = 0.5f;		// meters
+			const F32 SCALE_FUDGE = 1.5f;
+
+			F32 stop_distance = SCALE_FUDGE * selectedObject->getMaxScale() + ARM_LENGTH;
+			if (stop_distance < MIN_STOP_DISTANCE)
+			{
+				stop_distance = MIN_STOP_DISTANCE;
+			}
+
+			LLVector3 walkToSpot = selectedObject->getPositionAgent();
+			
+			// make sure we stop in front of the object
+			LLVector3 delta = walkToSpot - gAgent.getPositionAgent();
+			delta.normVec();
+			delta = delta * 0.5f;
+			walkToSpot -= delta;
+
+			// The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak.
+			CallbackData* user_data = new CallbackData(attachment_point, mReplace);
+			gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance);
+			gAgentCamera.clearFocusObject();
+		}
+	}
+}
+
+void callback_attachment_drop(const LLSD& notification, const LLSD& response)
+{
+	// Ensure user confirmed the drop
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (option != 0) return;
+
+	// Called when the user clicked on an object attached to them
+	// and selected "Drop".
+	LLUUID object_id = notification["payload"]["object_id"].asUUID();
+	LLViewerObject *object = gObjectList.findObject(object_id);
+	
+	if (!object)
+	{
+		llwarns << "handle_drop_attachment() - no object to drop" << llendl;
+		return;
+	}
+
+	LLViewerObject *parent = (LLViewerObject*)object->getParent();
+	while (parent)
+	{
+		if(parent->isAvatar())
+		{
+			break;
+		}
+		object = parent;
+		parent = (LLViewerObject*)parent->getParent();
+	}
+
+	if (!object)
+	{
+		llwarns << "handle_detach() - no object to detach" << llendl;
+		return;
+	}
+
+	if (object->isAvatar())
+	{
+		llwarns << "Trying to detach avatar from avatar." << llendl;
+		return;
+	}
+	
+	// reselect the object
+	LLSelectMgr::getInstance()->selectObjectAndFamily(object);
+
+	LLSelectMgr::getInstance()->sendDropAttachment();
+
+	return;
+}
+
+class LLAttachmentDrop : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLSD payload;
+		LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+
+		if (object) 
+		{
+			payload["object_id"] = object->getID();
+		}
+		else
+		{
+			llwarns << "Drop object not found" << llendl;
+			return true;
+		}
+
+		LLNotificationsUtil::add("AttachmentDrop", LLSD(), payload, &callback_attachment_drop);
+		return true;
+	}
+};
+
+// called from avatar pie menu
+class LLAttachmentDetachFromPoint : public view_listener_t
+{
+	bool handleEvent(const LLSD& user_data)
+	{
+		const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
+		if (attachment->getNumObjects() > 0)
+		{
+			gMessageSystem->newMessage("ObjectDetach");
+			gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+			gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+			gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			
+			for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin();
+				 iter != attachment->mAttachedObjects.end();
+				 iter++)
+			{
+				LLViewerObject *attached_object = (*iter);
+				gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+				gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
+			}
+			gMessageSystem->sendReliable( gAgent.getRegionHost() );
+		}
+		return true;
+	}
+};
+
+static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
+{
+	std::string label;
+	LLMenuItemGL* menu = dynamic_cast<LLMenuItemGL*>(ctrl);
+	if (menu)
+	{
+		const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL);
+		if (attachment)
+		{
+			label = data["label"].asString();
+			for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin();
+				 attachment_iter != attachment->mAttachedObjects.end();
+				 ++attachment_iter)
+			{
+				const LLViewerObject* attached_object = (*attachment_iter);
+				if (attached_object)
+				{
+					LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID());
+					if (itemp)
+					{
+						label += std::string(" (") + itemp->getName() + std::string(")");
+						break;
+					}
+				}
+			}
+		}
+		menu->setLabel(label);
+	}
+	return true;
+}
+
+class LLAttachmentDetach : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// Called when the user clicked on an object attached to them
+		// and selected "Detach".
+		LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+		if (!object)
+		{
+			llwarns << "handle_detach() - no object to detach" << llendl;
+			return true;
+		}
+
+		LLViewerObject *parent = (LLViewerObject*)object->getParent();
+		while (parent)
+		{
+			if(parent->isAvatar())
+			{
+				break;
+			}
+			object = parent;
+			parent = (LLViewerObject*)parent->getParent();
+		}
+
+		if (!object)
+		{
+			llwarns << "handle_detach() - no object to detach" << llendl;
+			return true;
+		}
+
+		if (object->isAvatar())
+		{
+			llwarns << "Trying to detach avatar from avatar." << llendl;
+			return true;
+		}
+
+		// The sendDetach() method works on the list of selected
+		// 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.
+		//RN: I thought it was more useful to detach everything that was selected
+		if (LLSelectMgr::getInstance()->getSelection()->isAttachment())
+		{
+			LLSelectMgr::getInstance()->sendDetach();
+		}
+		return true;
+	}
+};
+
+//Adding an observer for a Jira 2422 and needs to be a fetch observer
+//for Jira 3119
+class LLWornItemFetchedObserver : public LLInventoryFetchItemsObserver
+{
+public:
+	LLWornItemFetchedObserver(const LLUUID& worn_item_id) :
+		LLInventoryFetchItemsObserver(worn_item_id)
+	{}
+	virtual ~LLWornItemFetchedObserver() {}
+
+protected:
+	virtual void done()
+	{
+		gMenuAttachmentSelf->buildDrawLabels();
+		gInventory.removeObserver(this);
+		delete this;
+	}
+};
+
+// You can only drop items on parcels where you can build.
+class LLAttachmentEnableDrop : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		BOOL can_build   = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild());
+
+		//Add an inventory observer to only allow dropping the newly attached item
+		//once it exists in your inventory.  Look at Jira 2422.
+		//-jwolk
+
+		// A bug occurs when you wear/drop an item before it actively is added to your inventory
+		// if this is the case (you're on a slow sim, etc.) a copy of the object,
+		// well, a newly created object with the same properties, is placed
+		// in your inventory.  Therefore, we disable the drop option until the
+		// item is in your inventory
+
+		LLViewerObject*              object         = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+		LLViewerJointAttachment*     attachment     = NULL;
+		LLInventoryItem*             item           = NULL;
+
+		// Do not enable drop if all faces of object are not enabled
+		if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
+		{
+    		S32 attachmentID  = ATTACHMENT_ID_FROM_STATE(object->getState());
+			attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
+
+			if (attachment)
+			{
+				for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+					 attachment_iter != attachment->mAttachedObjects.end();
+					 ++attachment_iter)
+				{
+					// make sure item is in your inventory (it could be a delayed attach message being sent from the sim)
+					// so check to see if the item is in the inventory already
+					item = gInventory.getItem((*attachment_iter)->getAttachmentItemID());
+					if (!item)
+					{
+						// Item does not exist, make an observer to enable the pie menu 
+						// when the item finishes fetching worst case scenario 
+						// if a fetch is already out there (being sent from a slow sim)
+						// we refetch and there are 2 fetches
+						LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID());		
+						worn_item_fetched->startFetch();
+						gInventory.addObserver(worn_item_fetched);
+					}
+				}
+			}
+		}
+		
+		//now check to make sure that the item is actually in the inventory before we enable dropping it
+		bool new_value = enable_detach() && can_build && item;
+
+		return new_value;
+	}
+};
+
+BOOL enable_detach(const LLSD&)
+{
+	LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+	
+	// Only enable detach if all faces of object are selected
+	if (!object ||
+		!object->isAttachment() ||
+		!LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
+	{
+		return FALSE;
+	}
+
+	// Find the avatar who owns this attachment
+	LLViewerObject* avatar = object;
+	while (avatar)
+	{
+		// ...if it's you, good to detach
+		if (avatar->getID() == gAgent.getID())
+		{
+			return TRUE;
+		}
+
+		avatar = (LLViewerObject*)avatar->getParent();
+	}
+
+	return FALSE;
+}
+
+class LLAttachmentEnableDetach : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = enable_detach();
+		return new_value;
+	}
+};
+
+// Used to tell if the selected object can be attached to your avatar.
+BOOL object_selected_and_point_valid()
+{
+	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+	for (LLObjectSelection::root_iterator iter = selection->root_begin();
+		 iter != selection->root_end(); iter++)
+	{
+		LLSelectNode* node = *iter;
+		LLViewerObject* object = node->getObject();
+		LLViewerObject::const_child_list_t& child_list = object->getChildren();
+		for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+			 iter != child_list.end(); iter++)
+		{
+			LLViewerObject* child = *iter;
+			if (child->isAvatar())
+			{
+				return FALSE;
+			}
+		}
+	}
+
+	return (selection->getRootObjectCount() == 1) && 
+		(selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && 
+		selection->getFirstRootObject()->permYouOwner() &&
+		selection->getFirstRootObject()->flagObjectMove() &&
+		!((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && 
+		(selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL);
+}
+
+
+BOOL object_is_wearable()
+{
+	if (!object_selected_and_point_valid())
+	{
+		return FALSE;
+	}
+	if (sitting_on_selection())
+	{
+		return FALSE;
+	}
+	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+	for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
+		 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
+	{
+		LLSelectNode* node = *iter;		
+		if (node->mPermissions->getOwner() == gAgent.getID())
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+
+class LLAttachmentPointFilled : public view_listener_t
+{
+	bool handleEvent(const LLSD& user_data)
+	{
+		bool enable = false;
+		LLVOAvatar::attachment_map_t::iterator found_it = gAgentAvatarp->mAttachmentPoints.find(user_data.asInteger());
+		if (found_it != gAgentAvatarp->mAttachmentPoints.end())
+		{
+			enable = found_it->second->getNumObjects() > 0;
+		}
+		return enable;
+	}
+};
+
+class LLAvatarSendIM : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+		if(avatar)
+		{
+			LLAvatarActions::startIM(avatar->getID());
+		}
+		return true;
+	}
+};
+
+class LLAvatarCall : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
+		if(avatar)
+		{
+			LLAvatarActions::startCall(avatar->getID());
+		}
+		return true;
+	}
+};
+
+namespace
+{
+	struct QueueObjects : public LLSelectedObjectFunctor
+	{
+		BOOL scripted;
+		BOOL modifiable;
+		LLFloaterScriptQueue* mQueue;
+		QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {}
+		virtual bool apply(LLViewerObject* obj)
+		{
+			scripted = obj->flagScripted();
+			modifiable = obj->permModify();
+
+			if( scripted && modifiable )
+			{
+				mQueue->addObject(obj->getID());
+				return false;
+			}
+			else
+			{
+				return true; // fail: stop applying
+			}
+		}
+	};
+}
+
+void queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
+{
+	QueueObjects func(q);
+	LLSelectMgr *mgr = LLSelectMgr::getInstance();
+	LLObjectSelectionHandle selectHandle = mgr->getSelection();
+	bool fail = selectHandle->applyToObjects(&func);
+	if(fail)
+	{
+		if ( !func.scripted )
+		{
+			std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts";
+			LLNotificationsUtil::add(noscriptmsg);
+		}
+		else if ( !func.modifiable )
+		{
+			std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission";
+			LLNotificationsUtil::add(nomodmsg);
+		}
+		else
+		{
+			llerrs << "Bad logic." << llendl;
+		}
+	}
+	else
+	{
+		if (!q->start())
+		{
+			llwarns << "Unexpected script compile failure." << llendl;
+		}
+	}
+}
+
+class LLToolsSelectedScriptAction : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string action = userdata.asString();
+		bool mono = false;
+		std::string msg, name;
+		if (action == "compile mono")
+		{
+			name = "compile_queue";
+			mono = true;
+			msg = "Recompile";
+		}
+		if (action == "compile lsl")
+		{
+			name = "compile_queue";
+			msg = "Recompile";
+		}
+		else if (action == "reset")
+		{
+			name = "reset_queue";
+			msg = "Reset";
+		}
+		else if (action == "start")
+		{
+			name = "start_queue";
+			msg = "Running";
+		}
+		else if (action == "stop")
+		{
+			name = "stop_queue";
+			msg = "RunningNot";
+		}
+		LLUUID id; id.generate();
+		
+		LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance<LLFloaterScriptQueue>(name, LLSD(id));
+		if (queue)
+		{
+			queue->setMono(mono);
+			queue_actions(queue, msg);
+		}
+		else
+		{
+			llwarns << "Failed to generate LLFloaterScriptQueue with action: " << action << llendl;
+		}
+		return true;
+	}
+};
+
+void handle_selected_texture_info(void*)
+{
+	for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin();
+   		iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++)
+	{
+		LLSelectNode* node = *iter;
+	   	
+   		std::string msg;
+   		msg.assign("Texture info for: ");
+   		msg.append(node->mName);
+
+		LLSD args;
+		args["MESSAGE"] = msg;
+		LLNotificationsUtil::add("SystemMessage", args);
+	   
+   		U8 te_count = node->getObject()->getNumTEs();
+   		// map from texture ID to list of faces using it
+   		typedef std::map< LLUUID, std::vector<U8> > map_t;
+   		map_t faces_per_texture;
+   		for (U8 i = 0; i < te_count; i++)
+   		{
+   			if (!node->isTESelected(i)) continue;
+	   
+   			LLViewerTexture* img = node->getObject()->getTEImage(i);
+   			LLUUID image_id = img->getID();
+   			faces_per_texture[image_id].push_back(i);
+   		}
+   		// Per-texture, dump which faces are using it.
+   		map_t::iterator it;
+   		for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
+   		{
+   			LLUUID image_id = it->first;
+   			U8 te = it->second[0];
+   			LLViewerTexture* img = node->getObject()->getTEImage(te);
+   			S32 height = img->getHeight();
+   			S32 width = img->getWidth();
+   			S32 components = img->getComponents();
+   			msg = llformat("%dx%d %s on face ",
+   								width,
+   								height,
+   								(components == 4 ? "alpha" : "opaque"));
+   			for (U8 i = 0; i < it->second.size(); ++i)
+   			{
+   				msg.append( llformat("%d ", (S32)(it->second[i])));
+   			}
+
+			LLSD args;
+			args["MESSAGE"] = msg;
+			LLNotificationsUtil::add("SystemMessage", args);
+   		}
+	}
+}
+
+void handle_test_male(void*)
+{
+	LLAppearanceMgr::instance().wearOutfitByName("Male Shape & Outfit");
+	//gGestureList.requestResetFromServer( TRUE );
+}
+
+void handle_test_female(void*)
+{
+	LLAppearanceMgr::instance().wearOutfitByName("Female Shape & Outfit");
+	//gGestureList.requestResetFromServer( FALSE );
+}
+
+void handle_toggle_pg(void*)
+{
+	gAgent.setTeen( !gAgent.isTeen() );
+
+	LLFloaterWorldMap::reloadIcons(NULL);
+
+	llinfos << "PG status set to " << (S32)gAgent.isTeen() << llendl;
+}
+
+void handle_dump_attachments(void*)
+{
+	if(!isAgentAvatarValid()) return;
+
+	for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); 
+		 iter != gAgentAvatarp->mAttachmentPoints.end(); )
+	{
+		LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+		LLViewerJointAttachment* attachment = curiter->second;
+		S32 key = curiter->first;
+		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+			 attachment_iter != attachment->mAttachedObjects.end();
+			 ++attachment_iter)
+		{
+			LLViewerObject *attached_object = (*attachment_iter);
+			BOOL visible = (attached_object != NULL &&
+							attached_object->mDrawable.notNull() && 
+							!attached_object->mDrawable->isRenderType(0));
+			LLVector3 pos;
+			if (visible) pos = attached_object->mDrawable->getPosition();
+			llinfos << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID()
+					<< (attached_object ? " present " : " absent ")
+					<< (visible ? "visible " : "invisible ")
+					<<  " at " << pos
+					<< " and " << (visible ? attached_object->getPosition() : LLVector3::zero)
+					<< llendl;
+		}
+	}
+}
+
+
+// these are used in the gl menus to set control values, generically.
+class LLToggleControl : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string control_name = userdata.asString();
+		BOOL checked = gSavedSettings.getBOOL( control_name );
+		gSavedSettings.setBOOL( control_name, !checked );
+		return true;
+	}
+};
+
+class LLCheckControl : public view_listener_t
+{
+	bool handleEvent( const LLSD& userdata)
+	{
+		std::string callback_data = userdata.asString();
+		bool new_value = gSavedSettings.getBOOL(callback_data);
+		return new_value;
+	}
+};
+
+// not so generic
+
+class LLAdvancedCheckRenderShadowOption: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string control_name = userdata.asString();
+		S32 current_shadow_level = gSavedSettings.getS32(control_name);
+		if (current_shadow_level == 0) // is off
+		{
+			return false;
+		}
+		else // is on
+		{
+			return true;
+		}
+	}
+};
+
+class LLAdvancedClickRenderShadowOption: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string control_name = userdata.asString();
+		S32 current_shadow_level = gSavedSettings.getS32(control_name);
+		if (current_shadow_level == 0) // upgrade to level 2
+		{
+			gSavedSettings.setS32(control_name, 2);
+		}
+		else // downgrade to level 0
+		{
+			gSavedSettings.setS32(control_name, 0);
+		}
+		return true;
+	}
+};
+
+void menu_toggle_attached_lights(void* user_data)
+{
+	LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
+}
+
+void menu_toggle_attached_particles(void* user_data)
+{
+	LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
+}
+
+class LLAdvancedHandleAttachedLightParticles: public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string control_name = userdata.asString();
+
+		// toggle the control
+		gSavedSettings.setBOOL(control_name,
+				       !gSavedSettings.getBOOL(control_name));
+
+		// update internal flags
+		if (control_name == "RenderAttachedLights")
+		{
+			menu_toggle_attached_lights(NULL);
+		}
+		else if (control_name == "RenderAttachedParticles")
+		{
+			menu_toggle_attached_particles(NULL);
+		}
+		return true;
+	}
+};
+
+class LLSomethingSelected : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty());
+		return new_value;
+	}
+};
+
+class LLSomethingSelectedNoHUD : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+		bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD);
+		return new_value;
+	}
+};
+
+static bool is_editable_selected()
+{
+	return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL);
+}
+
+class LLEditableSelected : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return is_editable_selected();
+	}
+};
+
+class LLEditableSelectedMono : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = false;
+		LLViewerRegion* region = gAgent.getRegion();
+		if(region && gMenuHolder)
+		{
+			bool have_cap = (! region->getCapability("UpdateScriptTask").empty());
+			new_value = is_editable_selected() && have_cap;
+		}
+		return new_value;
+	}
+};
+
+bool enable_object_take_copy()
+{
+	bool all_valid = false;
+	if (LLSelectMgr::getInstance())
+	{
+		if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
+		{
+		all_valid = true;
+#ifndef HACKED_GODLIKE_VIEWER
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+		if (LLGridManager::getInstance()->isInProductionGrid()
+            || !gAgent.isGodlike())
+# endif
+		{
+			struct f : public LLSelectedObjectFunctor
+			{
+				virtual bool apply(LLViewerObject* obj)
+				{
+					return (!obj->permCopy() || obj->isAttachment());
+				}
+			} func;
+			const bool firstonly = true;
+			bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
+			all_valid = !any_invalid;
+		}
+#endif // HACKED_GODLIKE_VIEWER
+		}
+	}
+
+	return all_valid;
+}
+
+
+class LLHasAsset : public LLInventoryCollectFunctor
+{
+public:
+	LLHasAsset(const LLUUID& id) : mAssetID(id), mHasAsset(FALSE) {}
+	virtual ~LLHasAsset() {}
+	virtual bool operator()(LLInventoryCategory* cat,
+							LLInventoryItem* item);
+	BOOL hasAsset() const { return mHasAsset; }
+
+protected:
+	LLUUID mAssetID;
+	BOOL mHasAsset;
+};
+
+bool LLHasAsset::operator()(LLInventoryCategory* cat,
+							LLInventoryItem* item)
+{
+	if(item && item->getAssetUUID() == mAssetID)
+	{
+		mHasAsset = TRUE;
+	}
+	return FALSE;
+}
+
+BOOL enable_save_into_inventory(void*)
+{
+	// *TODO: clean this up
+	// find the last root
+	LLSelectNode* last_node = NULL;
+	for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+		 iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+	{
+		last_node = *iter;
+	}
+
+#ifdef HACKED_GODLIKE_VIEWER
+	return TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+	if (!LLGridManager::getInstance()->isInProductionGrid()
+        && gAgent.isGodlike())
+	{
+		return TRUE;
+	}
+# endif
+	// check all pre-req's for save into inventory.
+	if(last_node && last_node->mValid && !last_node->mItemID.isNull()
+	   && (last_node->mPermissions->getOwner() == gAgent.getID())
+	   && (gInventory.getItem(last_node->mItemID) != NULL))
+	{
+		LLViewerObject* obj = last_node->getObject();
+		if( obj && !obj->isAttachment() )
+		{
+			return TRUE;
+		}
+	}
+#endif
+	return FALSE;
+}
+
+class LLToolsEnableSaveToInventory : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = enable_save_into_inventory(NULL);
+		return new_value;
+	}
+};
+
+BOOL enable_save_into_task_inventory(void*)
+{
+	LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+	if(node && (node->mValid) && (!node->mFromTaskID.isNull()))
+	{
+		// *TODO: check to see if the fromtaskid object exists.
+		LLViewerObject* obj = node->getObject();
+		if( obj && !obj->isAttachment() )
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+class LLToolsEnableSaveToObjectInventory : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = enable_save_into_task_inventory(NULL);
+		return new_value;
+	}
+};
+
+
+class LLViewEnableMouselook : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// You can't go directly from customize avatar to mouselook.
+		// TODO: write code with appropriate dialogs to handle this transition.
+		bool new_value = (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && !gSavedSettings.getBOOL("FreezeTime"));
+		return new_value;
+	}
+};
+
+class LLToolsEnableToolNotPie : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() );
+		return new_value;
+	}
+};
+
+class LLWorldEnableCreateLandmark : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		return !LLLandmarkActions::landmarkAlreadyExists();
+	}
+};
+
+class LLWorldEnableSetHomeLocation : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gAgent.isGodlike() || 
+			(gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome());
+		return new_value;
+	}
+};
+
+class LLWorldEnableTeleportHome : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLViewerRegion* regionp = gAgent.getRegion();
+		bool agent_on_prelude = (regionp && regionp->isPrelude());
+		bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude;
+		return enable_teleport_home;
+	}
+};
+
+BOOL enable_god_full(void*)
+{
+	return gAgent.getGodLevel() >= GOD_FULL;
+}
+
+BOOL enable_god_liaison(void*)
+{
+	return gAgent.getGodLevel() >= GOD_LIAISON;
+}
+
+bool is_god_customer_service()
+{
+	return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE;
+}
+
+BOOL enable_god_basic(void*)
+{
+	return gAgent.getGodLevel() > GOD_NOT;
+}
+
+
+void toggle_show_xui_names(void *)
+{
+	gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames"));
+}
+
+BOOL check_show_xui_names(void *)
+{
+	return gSavedSettings.getBOOL("DebugShowXUINames");
+}
+
+class LLToolsSelectOnlyMyObjects : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		BOOL cur_val = gSavedSettings.getBOOL("SelectOwnedOnly");
+
+		gSavedSettings.setBOOL("SelectOwnedOnly", ! cur_val );
+
+		return true;
+	}
+};
+
+class LLToolsSelectOnlyMovableObjects : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		BOOL cur_val = gSavedSettings.getBOOL("SelectMovableOnly");
+
+		gSavedSettings.setBOOL("SelectMovableOnly", ! cur_val );
+
+		return true;
+	}
+};
+
+class LLToolsSelectBySurrounding : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive;
+
+		gSavedSettings.setBOOL("RectangleSelectInclusive", LLSelectMgr::sRectSelectInclusive);
+		return true;
+	}
+};
+
+class LLToolsShowHiddenSelection : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// TomY TODO Merge these
+		LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections;
+
+		gSavedSettings.setBOOL("RenderHiddenSelections", LLSelectMgr::sRenderHiddenSelections);
+		return true;
+	}
+};
+
+class LLToolsShowSelectionLightRadius : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		// TomY TODO merge these
+		LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius;
+
+		gSavedSettings.setBOOL("RenderLightRadius", LLSelectMgr::sRenderLightRadius);
+		return true;
+	}
+};
+
+class LLToolsEditLinkedParts : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		BOOL select_individuals = !gSavedSettings.getBOOL("EditLinkedParts");
+		gSavedSettings.setBOOL( "EditLinkedParts", select_individuals );
+		if (select_individuals)
+		{
+			LLSelectMgr::getInstance()->demoteSelectionToIndividuals();
+		}
+		else
+		{
+			LLSelectMgr::getInstance()->promoteSelectionToRoot();
+		}
+		return true;
+	}
+};
+
+void reload_vertex_shader(void *)
+{
+	//THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought	- DaveP
+}
+
+void handle_dump_avatar_local_textures(void*)
+{
+	gAgentAvatarp->dumpLocalTextures();
+}
+
+void handle_dump_timers()
+{
+	LLFastTimer::dumpCurTimes();
+}
+
+void handle_debug_avatar_textures(void*)
+{
+	LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+	if (objectp)
+	{
+		LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) );
+	}
+}
+
+void handle_grab_baked_texture(void* data)
+{
+	EBakedTextureIndex baked_tex_index = (EBakedTextureIndex)((intptr_t)data);
+	if (!isAgentAvatarValid()) return;
+
+	const LLUUID& asset_id = gAgentAvatarp->grabBakedTexture(baked_tex_index);
+	LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << llendl;
+	LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE;
+	LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE;
+	const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type));
+	if(folder_id.notNull())
+	{
+		std::string name;
+		name = "Baked " + LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture";
+
+		LLUUID item_id;
+		item_id.generate();
+		LLPermissions perm;
+		perm.init(gAgentID,
+				  gAgentID,
+				  LLUUID::null,
+				  LLUUID::null);
+		U32 next_owner_perm = PERM_MOVE | PERM_TRANSFER;
+		perm.initMasks(PERM_ALL,
+					   PERM_ALL,
+					   PERM_NONE,
+					   PERM_NONE,
+					   next_owner_perm);
+		time_t creation_date_now = time_corrected();
+		LLPointer<LLViewerInventoryItem> item
+			= new LLViewerInventoryItem(item_id,
+										folder_id,
+										perm,
+										asset_id,
+										asset_type,
+										inv_type,
+										name,
+										LLStringUtil::null,
+										LLSaleInfo::DEFAULT,
+										LLInventoryItemFlags::II_FLAGS_NONE,
+										creation_date_now);
+
+		item->updateServer(TRUE);
+		gInventory.updateItem(item);
+		gInventory.notifyObservers();
+
+		// Show the preview panel for textures to let
+		// user know that the image is now in inventory.
+		LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
+		if(active_panel)
+		{
+			LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus();
+
+			active_panel->setSelection(item_id, TAKE_FOCUS_NO);
+			active_panel->openSelected();
+			//LLFloaterInventory::dumpSelectionInformation((void*)view);
+			// restore keyboard focus
+			gFocusMgr.setKeyboardFocus(focus_ctrl);
+		}
+	}
+	else
+	{
+		llwarns << "Can't find a folder to put it in" << llendl;
+	}
+}
+
+BOOL enable_grab_baked_texture(void* data)
+{
+	EBakedTextureIndex index = (EBakedTextureIndex)((intptr_t)data);
+	if (isAgentAvatarValid())
+	{
+		return gAgentAvatarp->canGrabBakedTexture(index);
+	}
+	return FALSE;
+}
+
+// Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing.
+// Returns NULL on failure.
+LLVOAvatar* find_avatar_from_object( LLViewerObject* object )
+{
+	if (object)
+	{
+		if( object->isAttachment() )
+		{
+			do
+			{
+				object = (LLViewerObject*) object->getParent();
+			}
+			while( object && !object->isAvatar() );
+		}
+		else if( !object->isAvatar() )
+		{
+			object = NULL;
+		}
+	}
+
+	return (LLVOAvatar*) object;
+}
+
+
+// Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing.
+// Returns NULL on failure.
+LLVOAvatar* find_avatar_from_object( const LLUUID& object_id )
+{
+	return find_avatar_from_object( gObjectList.findObject(object_id) );
+}
+
+
+void handle_disconnect_viewer(void *)
+{
+	LLAppViewer::instance()->forceDisconnect(LLTrans::getString("TestingDisconnect"));
+}
+
+void force_error_breakpoint(void *)
+{
+    LLAppViewer::instance()->forceErrorBreakpoint();
+}
+
+void force_error_llerror(void *)
+{
+    LLAppViewer::instance()->forceErrorLLError();
+}
+
+void force_error_bad_memory_access(void *)
+{
+    LLAppViewer::instance()->forceErrorBadMemoryAccess();
+}
+
+void force_error_infinite_loop(void *)
+{
+    LLAppViewer::instance()->forceErrorInfiniteLoop();
+}
+
+void force_error_software_exception(void *)
+{
+    LLAppViewer::instance()->forceErrorSoftwareException();
+}
+
+void force_error_driver_crash(void *)
+{
+    LLAppViewer::instance()->forceErrorDriverCrash();
+}
+
+class LLToolsUseSelectionForGrid : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLSelectMgr::getInstance()->clearGridObjects();
+		struct f : public LLSelectedObjectFunctor
+		{
+			virtual bool apply(LLViewerObject* objectp)
+			{
+				LLSelectMgr::getInstance()->addGridObject(objectp);
+				return true;
+			}
+		} func;
+		LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);
+		LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT);
+		if (gFloaterTools)
+		{
+			gFloaterTools->mComboGridMode->setCurrentByIndex((S32)GRID_MODE_REF_OBJECT);
+		}
+		return true;
+	}
+};
+
+void handle_test_load_url(void*)
+{
+	LLWeb::loadURL("");
+	LLWeb::loadURL("hacker://www.google.com/");
+	LLWeb::loadURL("http");
+	LLWeb::loadURL("http://www.google.com/");
+}
+
+//
+// LLViewerMenuHolderGL
+//
+static LLDefaultChildRegistry::Register<LLViewerMenuHolderGL> r("menu_holder");
+
+LLViewerMenuHolderGL::LLViewerMenuHolderGL(const LLViewerMenuHolderGL::Params& p)
+: LLMenuHolderGL(p)
+{}
+
+BOOL LLViewerMenuHolderGL::hideMenus()
+{
+	BOOL handled = LLMenuHolderGL::hideMenus();
+
+	// drop pie menu selection
+	mParcelSelection = NULL;
+	mObjectSelection = NULL;
+
+	if (gMenuBarView)
+	{
+		gMenuBarView->clearHoverItem();
+		gMenuBarView->resetMenuTrigger();
+	}
+
+	return handled;
+}
+
+void LLViewerMenuHolderGL::setParcelSelection(LLSafeHandle<LLParcelSelection> selection) 
+{ 
+	mParcelSelection = selection; 
+}
+
+void LLViewerMenuHolderGL::setObjectSelection(LLSafeHandle<LLObjectSelection> selection) 
+{ 
+	mObjectSelection = selection; 
+}
+
+
+const LLRect LLViewerMenuHolderGL::getMenuRect() const
+{
+	return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT);
+}
+
+void handle_web_browser_test(const LLSD& param)
+{
+	std::string url = param.asString();
+	if (url.empty())
+	{
+		url = "about:blank";
+	}
+	LLWeb::loadURLInternal(url);
+}
+
+void handle_web_content_test(const LLSD& param)
+{
+	std::string url = param.asString();
+	LLWeb::loadWebURLInternal(url);
+}
+
+void handle_buy_currency_test(void*)
+{
+	std::string url =
+		"http://sarahd-sl-13041.webdev.lindenlab.com/app/lindex/index.php?agent_id=[AGENT_ID]&secure_session_id=[SESSION_ID]&lang=[LANGUAGE]";
+
+	LLStringUtil::format_map_t replace;
+	replace["[AGENT_ID]"] = gAgent.getID().asString();
+	replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString();
+	replace["[LANGUAGE]"] = LLUI::getLanguage();
+	LLStringUtil::format(url, replace);
+
+	llinfos << "buy currency url " << url << llendl;
+
+	LLFloaterReg::showInstance("buy_currency_html", LLSD(url));
+}
+
+void handle_rebake_textures(void*)
+{
+	if (!isAgentAvatarValid()) return;
+
+	// Slam pending upload count to "unstick" things
+	bool slam_for_debug = true;
+	gAgentAvatarp->forceBakeAllTextures(slam_for_debug);
+}
+
+void toggle_visibility(void* user_data)
+{
+	LLView* viewp = (LLView*)user_data;
+	viewp->setVisible(!viewp->getVisible());
+}
+
+BOOL get_visibility(void* user_data)
+{
+	LLView* viewp = (LLView*)user_data;
+	return viewp->getVisible();
+}
+
+// TomY TODO: Get rid of these?
+class LLViewShowHoverTips : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips"));
+		return true;
+	}
+};
+
+class LLViewCheckShowHoverTips : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = gSavedSettings.getBOOL("ShowHoverTips");
+		return new_value;
+	}
+};
+
+// TomY TODO: Get rid of these?
+class LLViewHighlightTransparent : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha;
+		return true;
+	}
+};
+
+class LLViewCheckHighlightTransparent : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLDrawPoolAlpha::sShowDebugAlpha;
+		return new_value;
+	}
+};
+
+class LLViewBeaconWidth : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string width = userdata.asString();
+		if(width == "1")
+		{
+			gSavedSettings.setS32("DebugBeaconLineWidth", 1);
+		}
+		else if(width == "4")
+		{
+			gSavedSettings.setS32("DebugBeaconLineWidth", 4);
+		}
+		else if(width == "16")
+		{
+			gSavedSettings.setS32("DebugBeaconLineWidth", 16);
+		}
+		else if(width == "32")
+		{
+			gSavedSettings.setS32("DebugBeaconLineWidth", 32);
+		}
+
+		return true;
+	}
+};
+
+
+class LLViewToggleBeacon : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string beacon = userdata.asString();
+		if (beacon == "scriptsbeacon")
+		{
+			LLPipeline::toggleRenderScriptedBeacons(NULL);
+			gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) );
+			// toggle the other one off if it's on
+			if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL))
+			{
+				LLPipeline::toggleRenderScriptedTouchBeacons(NULL);
+				gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) );
+			}
+		}
+		else if (beacon == "physicalbeacon")
+		{
+			LLPipeline::toggleRenderPhysicalBeacons(NULL);
+			gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons(NULL) );
+		}
+		else if (beacon == "soundsbeacon")
+		{
+			LLPipeline::toggleRenderSoundBeacons(NULL);
+			gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons(NULL) );
+		}
+		else if (beacon == "particlesbeacon")
+		{
+			LLPipeline::toggleRenderParticleBeacons(NULL);
+			gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons(NULL) );
+		}
+		else if (beacon == "scripttouchbeacon")
+		{
+			LLPipeline::toggleRenderScriptedTouchBeacons(NULL);
+			gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) );
+			// toggle the other one off if it's on
+			if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL))
+			{
+				LLPipeline::toggleRenderScriptedBeacons(NULL);
+				gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) );
+			}
+		}
+		else if (beacon == "renderbeacons")
+		{
+			LLPipeline::toggleRenderBeacons(NULL);
+			gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) );
+			// toggle the other one on if it's not
+			if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL))
+			{
+				LLPipeline::toggleRenderHighlights(NULL);
+				gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) );
+			}
+		}
+		else if (beacon == "renderhighlights")
+		{
+			LLPipeline::toggleRenderHighlights(NULL);
+			gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) );
+			// toggle the other one on if it's not
+			if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL))
+			{
+				LLPipeline::toggleRenderBeacons(NULL);
+				gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) );
+			}
+		}
+
+		return true;
+	}
+};
+
+class LLViewCheckBeaconEnabled : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string beacon = userdata.asString();
+		bool new_value = false;
+		if (beacon == "scriptsbeacon")
+		{
+			new_value = gSavedSettings.getBOOL( "scriptsbeacon");
+			LLPipeline::setRenderScriptedBeacons(new_value);
+		}
+		else if (beacon == "physicalbeacon")
+		{
+			new_value = gSavedSettings.getBOOL( "physicalbeacon");
+			LLPipeline::setRenderPhysicalBeacons(new_value);
+		}
+		else if (beacon == "soundsbeacon")
+		{
+			new_value = gSavedSettings.getBOOL( "soundsbeacon");
+			LLPipeline::setRenderSoundBeacons(new_value);
+		}
+		else if (beacon == "particlesbeacon")
+		{
+			new_value = gSavedSettings.getBOOL( "particlesbeacon");
+			LLPipeline::setRenderParticleBeacons(new_value);
+		}
+		else if (beacon == "scripttouchbeacon")
+		{
+			new_value = gSavedSettings.getBOOL( "scripttouchbeacon");
+			LLPipeline::setRenderScriptedTouchBeacons(new_value);
+		}
+		else if (beacon == "renderbeacons")
+		{
+			new_value = gSavedSettings.getBOOL( "renderbeacons");
+			LLPipeline::setRenderBeacons(new_value);
+		}
+		else if (beacon == "renderhighlights")
+		{
+			new_value = gSavedSettings.getBOOL( "renderhighlights");
+			LLPipeline::setRenderHighlights(new_value);
+		}
+		return new_value;
+	}
+};
+
+class LLViewToggleRenderType : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string type = userdata.asString();
+		if (type == "hideparticles")
+		{
+			LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
+		}
+		return true;
+	}
+};
+
+class LLViewCheckRenderType : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string type = userdata.asString();
+		bool new_value = false;
+		if (type == "hideparticles")
+		{
+			new_value = LLPipeline::toggleRenderTypeControlNegated((void *)LLPipeline::RENDER_TYPE_PARTICLES);
+		}
+		return new_value;
+	}
+};
+
+class LLViewShowHUDAttachments : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments;
+		return true;
+	}
+};
+
+class LLViewCheckHUDAttachments : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool new_value = LLPipeline::sShowHUDAttachments;
+		return new_value;
+	}
+};
+
+class LLEditEnableTakeOff : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string clothing = userdata.asString();
+		LLWearableType::EType type = LLWearableType::typeNameToType(clothing);
+		if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT)
+			return LLAgentWearables::selfHasWearable(type);
+		return false;
+	}
+};
+
+class LLEditTakeOff : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string clothing = userdata.asString();
+		if (clothing == "all")
+			LLWearableBridge::removeAllClothesFromAvatar();
+		else
+		{
+			LLWearableType::EType type = LLWearableType::typeNameToType(clothing);
+			if (type >= LLWearableType::WT_SHAPE 
+				&& type < LLWearableType::WT_COUNT
+				&& (gAgentWearables.getWearableCount(type) > 0))
+			{
+				// MULTI-WEARABLES: assuming user wanted to remove top shirt.
+				U32 wearable_index = gAgentWearables.getWearableCount(type) - 1;
+				LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(gAgentWearables.getWearableInventoryItem(type,wearable_index));
+				LLWearableBridge::removeItemFromAvatar(item);
+			}
+				
+		}
+		return true;
+	}
+};
+
+class LLToolsSelectTool : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string tool_name = userdata.asString();
+		if (tool_name == "focus")
+		{
+			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(1);
+		}
+		else if (tool_name == "move")
+		{
+			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(2);
+		}
+		else if (tool_name == "edit")
+		{
+			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(3);
+		}
+		else if (tool_name == "create")
+		{
+			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(4);
+		}
+		else if (tool_name == "land")
+		{
+			LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(5);
+		}
+		return true;
+	}
+};
+
+/// WINDLIGHT callbacks
+class LLWorldEnvSettings : public view_listener_t
+{	
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string tod = userdata.asString();
+		LLVector3 sun_direction;
+		
+		if (tod == "editor")
+		{
+			// if not there or is hidden, show it
+			LLFloaterReg::toggleInstance("env_settings");
+			return true;
+		}
+		
+		if (tod == "sunrise")
+		{
+			// set the value, turn off animation
+			LLWLParamManager::instance()->mAnimator.setDayTime(0.25);
+			LLWLParamManager::instance()->mAnimator.mIsRunning = false;
+			LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
+
+			// then call update once
+			LLWLParamManager::instance()->mAnimator.update(
+				LLWLParamManager::instance()->mCurParams);
+		}
+		else if (tod == "noon")
+		{
+			// set the value, turn off animation
+			LLWLParamManager::instance()->mAnimator.setDayTime(0.567);
+			LLWLParamManager::instance()->mAnimator.mIsRunning = false;
+			LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
+
+			// then call update once
+			LLWLParamManager::instance()->mAnimator.update(
+				LLWLParamManager::instance()->mCurParams);
+		}
+		else if (tod == "sunset")
+		{
+			// set the value, turn off animation
+			LLWLParamManager::instance()->mAnimator.setDayTime(0.75);
+			LLWLParamManager::instance()->mAnimator.mIsRunning = false;
+			LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
+
+			// then call update once
+			LLWLParamManager::instance()->mAnimator.update(
+				LLWLParamManager::instance()->mCurParams);
+		}
+		else if (tod == "midnight")
+		{
+			// set the value, turn off animation
+			LLWLParamManager::instance()->mAnimator.setDayTime(0.0);
+			LLWLParamManager::instance()->mAnimator.mIsRunning = false;
+			LLWLParamManager::instance()->mAnimator.mUseLindenTime = false;
+
+			// then call update once
+			LLWLParamManager::instance()->mAnimator.update(
+				LLWLParamManager::instance()->mCurParams);
+		}
+		else
+		{
+			LLWLParamManager::instance()->mAnimator.mIsRunning = true;
+			LLWLParamManager::instance()->mAnimator.mUseLindenTime = true;	
+		}
+		return true;
+	}
+};
+
+/// Water Menu callbacks
+class LLWorldWaterSettings : public view_listener_t
+{	
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLFloaterReg::toggleInstance("env_water");
+		return true;
+	}
+};
+
+/// Post-Process callbacks
+class LLWorldPostProcess : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLFloaterReg::showInstance("env_post_process");
+		return true;
+	}
+};
+
+/// Day Cycle callbacks
+class LLWorldDayCycle : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLFloaterReg::showInstance("env_day_cycle");
+		return true;
+	}
+};
+
+class LLWorldToggleMovementControls : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLBottomTray::getInstance()->toggleMovementControls();
+		return true;
+	}
+};
+
+class LLWorldToggleCameraControls : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		LLBottomTray::getInstance()->toggleCameraControls();
+		return true;
+	}
+};
+
+void handle_flush_name_caches()
+{
+	// Toggle display names on and off to flush
+	bool use_display_names = LLAvatarNameCache::useDisplayNames();
+	LLAvatarNameCache::setUseDisplayNames(!use_display_names);
+	LLAvatarNameCache::setUseDisplayNames(use_display_names);
+
+	if (gCacheName) gCacheName->clear();
+}
+
+class LLUploadCostCalculator : public view_listener_t
+{
+	std::string mCostStr;
+
+	bool handleEvent(const LLSD& userdata)
+	{
+		std::string menu_name = userdata.asString();
+		gMenuHolder->childSetLabelArg(menu_name, "[COST]", mCostStr);
+
+		return true;
+	}
+
+	void calculateCost();
+
+public:
+	LLUploadCostCalculator()
+	{
+		calculateCost();
+	}
+};
+
+class LLToggleUIHints : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+		bool ui_hints_enabled = gSavedSettings.getBOOL("EnableUIHints");
+		// toggle
+		ui_hints_enabled = !ui_hints_enabled;
+		gSavedSettings.setBOOL("EnableUIHints", ui_hints_enabled);
+		return true;
+	}
+};
+
+void LLUploadCostCalculator::calculateCost()
+{
+	S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+
+	// getPriceUpload() returns -1 if no data available yet.
+	if(upload_cost >= 0)
+	{
+		mCostStr = llformat("%d", upload_cost);
+	}
+	else
+	{
+		mCostStr = llformat("%d", gSavedSettings.getU32("DefaultUploadCost"));
+	}
+}
+
+void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y)
+{
+	static LLMenuGL*	show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml",
+			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	if(gMenuHolder->hasVisibleMenu())
+	{
+		gMenuHolder->hideMenus();
+	}
+	show_navbar_context_menu->buildDrawLabels();
+	show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer);
+	LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y);
+}
+
+void show_topinfobar_context_menu(LLView* ctrl, S32 x, S32 y)
+{
+	static LLMenuGL* show_topbarinfo_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_topinfobar.xml",
+			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
+	LLMenuItemGL* landmark_item = show_topbarinfo_context_menu->getChild<LLMenuItemGL>("Landmark");
+	if (!LLLandmarkActions::landmarkAlreadyExists())
+	{
+		landmark_item->setLabel(LLTrans::getString("AddLandmarkNavBarMenu"));
+	}
+	else
+	{
+		landmark_item->setLabel(LLTrans::getString("EditLandmarkNavBarMenu"));
+	}
+
+	if(gMenuHolder->hasVisibleMenu())
+	{
+		gMenuHolder->hideMenus();
+	}
+
+	show_topbarinfo_context_menu->buildDrawLabels();
+	show_topbarinfo_context_menu->updateParent(LLMenuGL::sMenuContainer);
+	LLMenuGL::showPopup(ctrl, show_topbarinfo_context_menu, x, y);
+}
+
+void initialize_edit_menu()
+{
+	view_listener_t::addMenu(new LLEditUndo(), "Edit.Undo");
+	view_listener_t::addMenu(new LLEditRedo(), "Edit.Redo");
+	view_listener_t::addMenu(new LLEditCut(), "Edit.Cut");
+	view_listener_t::addMenu(new LLEditCopy(), "Edit.Copy");
+	view_listener_t::addMenu(new LLEditPaste(), "Edit.Paste");
+	view_listener_t::addMenu(new LLEditDelete(), "Edit.Delete");
+	view_listener_t::addMenu(new LLEditSelectAll(), "Edit.SelectAll");
+	view_listener_t::addMenu(new LLEditDeselect(), "Edit.Deselect");
+	view_listener_t::addMenu(new LLEditDuplicate(), "Edit.Duplicate");
+	view_listener_t::addMenu(new LLEditTakeOff(), "Edit.TakeOff");
+	view_listener_t::addMenu(new LLEditEnableUndo(), "Edit.EnableUndo");
+	view_listener_t::addMenu(new LLEditEnableRedo(), "Edit.EnableRedo");
+	view_listener_t::addMenu(new LLEditEnableCut(), "Edit.EnableCut");
+	view_listener_t::addMenu(new LLEditEnableCopy(), "Edit.EnableCopy");
+	view_listener_t::addMenu(new LLEditEnablePaste(), "Edit.EnablePaste");
+	view_listener_t::addMenu(new LLEditEnableDelete(), "Edit.EnableDelete");
+	view_listener_t::addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll");
+	view_listener_t::addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect");
+	view_listener_t::addMenu(new LLEditEnableDuplicate(), "Edit.EnableDuplicate");
+
+}
+
+void initialize_menus()
+{
+	// A parameterized event handler used as ctrl-8/9/0 zoom controls below.
+	class LLZoomer : public view_listener_t
+	{
+	public:
+		// The "mult" parameter says whether "val" is a multiplier or used to set the value.
+		LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {}
+		bool handleEvent(const LLSD& userdata)
+		{
+			F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal;
+			LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad);
+			gSavedSettings.setF32("CameraAngle", LLViewerCamera::getInstance()->getView()); // setView may have clamped it.
+			return true;
+		}
+	private:
+		F32 mVal;
+		bool mMult;
+	};
+	
+	LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
+	LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
+	
+	// Generic enable and visible
+	// Don't prepend MenuName.Foo because these can be used in any menu.
+	enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service));
+
+	view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts");
+
+	// Agent
+	commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying));
+	enable.add("Agent.enableFlying", boost::bind(&LLAgent::enableFlying));
+
+	// File menu
+	init_menu_file();
+
+	view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff");
+	view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar");
+	view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape");
+	commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar));
+	commit.add("EditOutfit", boost::bind(&handle_edit_outfit));
+	commit.add("EditShape", boost::bind(&handle_edit_shape));
+
+	// View menu
+	view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook");
+	view_listener_t::addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam");
+	view_listener_t::addMenu(new LLViewResetView(), "View.ResetView");
+	view_listener_t::addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter");
+	view_listener_t::addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips");
+	view_listener_t::addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent");
+	view_listener_t::addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType");
+	view_listener_t::addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments");
+	view_listener_t::addMenu(new LLZoomer(1.2f), "View.ZoomOut");
+	view_listener_t::addMenu(new LLZoomer(1/1.2f), "View.ZoomIn");
+	view_listener_t::addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault");
+	view_listener_t::addMenu(new LLViewDefaultUISize(), "View.DefaultUISize");
+
+	view_listener_t::addMenu(new LLViewEnableMouselook(), "View.EnableMouselook");
+	view_listener_t::addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam");
+	view_listener_t::addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter");
+
+	view_listener_t::addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam");
+	view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips");
+	view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent");
+	view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType");
+	view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
+
+	// Me > Movement
+	view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
+	
+	// World menu
+	commit.add("World.Chat", boost::bind(&handle_chat, (void*)NULL));
+	view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
+	view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
+	view_listener_t::addMenu(new LLWorldPlaceProfile(), "World.PlaceProfile");
+	view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation");
+	view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome");
+	view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway");
+	view_listener_t::addMenu(new LLWorldSetBusy(), "World.SetBusy");
+
+	view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark");
+	view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation");
+	view_listener_t::addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome");
+	view_listener_t::addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand");
+
+	view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun");
+	
+	view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings");
+	view_listener_t::addMenu(new LLWorldWaterSettings(), "World.WaterSettings");
+	view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess");
+	view_listener_t::addMenu(new LLWorldDayCycle(), "World.DayCycle");
+
+	view_listener_t::addMenu(new LLWorldToggleMovementControls(), "World.Toggle.MovementControls");
+	view_listener_t::addMenu(new LLWorldToggleCameraControls(), "World.Toggle.CameraControls");
+
+	// Tools menu
+	view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
+	view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
+	view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
+	view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
+	view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
+	view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
+	view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts");
+	view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY");
+	view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid");
+	view_listener_t::addMenu(new LLToolsSelectNextPart(), "Tools.SelectNextPart");
+	commit.add("Tools.Link", boost::bind(&LLSelectMgr::linkObjects, LLSelectMgr::getInstance()));
+	commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance()));
+	view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations");
+	view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");
+	view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys");	
+	commit.add("Tools.LookAtSelection", boost::bind(&handle_look_at_selection, _2));
+	commit.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take));
+	commit.add("Tools.TakeCopy", boost::bind(&handle_take_copy));
+	view_listener_t::addMenu(new LLToolsSaveToInventory(), "Tools.SaveToInventory");
+	view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory");
+	view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction");
+
+	view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie");
+	view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart");
+	enable.add("Tools.EnableLink", boost::bind(&LLSelectMgr::enableLinkObjects, LLSelectMgr::getInstance()));
+	enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance()));
+	view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake");
+	enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy));
+	enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object));
+	enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object));
+	view_listener_t::addMenu(new LLToolsEnableSaveToInventory(), "Tools.EnableSaveToInventory");
+	view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory");
+
+	// Help menu
+	// most items use the ShowFloater method
+
+	// Advanced menu
+	view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole");
+	view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole");
+	view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole");
+	
+	// Advanced > HUD Info
+	view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo");
+	view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo");
+
+	// Advanced Other Settings	
+	view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache");
+	
+	// Advanced > Render > Types
+	view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType");
+	view_listener_t::addMenu(new LLAdvancedCheckRenderType(), "Advanced.CheckRenderType");
+
+	//// Advanced > Render > Features
+	view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature");
+	view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature");
+	// Advanced > Render > Info Displays
+	view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay");
+	view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay");
+	view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo");
+	view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe");
+	view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
+	// Develop > Render
+	view_listener_t::addMenu(new LLAdvancedToggleTextureAtlas(), "Advanced.ToggleTextureAtlas");
+	view_listener_t::addMenu(new LLAdvancedCheckTextureAtlas(), "Advanced.CheckTextureAtlas");
+	view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion");
+	view_listener_t::addMenu(new LLAdvancedEnableRenderFBO(), "Advanced.EnableRenderFBO");
+	view_listener_t::addMenu(new LLAdvancedEnableRenderDeferred(), "Advanced.EnableRenderDeferred");
+	view_listener_t::addMenu(new LLAdvancedEnableRenderDeferredOptions(), "Advanced.EnableRenderDeferredOptions");
+	view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");
+	view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
+	view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
+	view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame");
+	view_listener_t::addMenu(new LLAdvancedVectorizePerfTest(), "Advanced.VectorizePerfTest");
+	view_listener_t::addMenu(new LLAdvancedToggleFrameTest(), "Advanced.ToggleFrameTest");
+	view_listener_t::addMenu(new LLAdvancedCheckFrameTest(), "Advanced.CheckFrameTest");
+	view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles");
+	view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption");
+	view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption");
+	
+
+	#ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+	view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode");
+	view_listener_t::addMenu(new LLAdvancedCheckToggleHackedGodmode(), "Advanced.CheckToggleHackedGodmode");
+	view_listener_t::addMenu(new LLAdvancedEnableToggleHackedGodmode(), "Advanced.EnableToggleHackedGodmode");
+	#endif
+
+	// Advanced > World
+	view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera");
+	view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache");
+
+	// Advanced > UI
+	commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test,	_2));	// sigh! this one opens the MEDIA browser
+	commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2));	// this one opens the Web Content floater
+	view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest");
+	view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr");
+	view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory");
+	commit.add("Advanced.DumpTimers", boost::bind(&handle_dump_timers) );
+	commit.add("Advanced.DumpFocusHolder", boost::bind(&handle_dump_focus) );
+	view_listener_t::addMenu(new LLAdvancedPrintSelectedObjectInfo(), "Advanced.PrintSelectedObjectInfo");
+	view_listener_t::addMenu(new LLAdvancedPrintAgentInfo(), "Advanced.PrintAgentInfo");
+	view_listener_t::addMenu(new LLAdvancedPrintTextureMemoryStats(), "Advanced.PrintTextureMemoryStats");
+	view_listener_t::addMenu(new LLAdvancedToggleDebugClicks(), "Advanced.ToggleDebugClicks");
+	view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks");
+	view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews");
+	view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews");
+	view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips");
+	view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips");
+	view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents");
+	view_listener_t::addMenu(new LLAdvancedCheckDebugMouseEvents(), "Advanced.CheckDebugMouseEvents");
+	view_listener_t::addMenu(new LLAdvancedToggleDebugKeys(), "Advanced.ToggleDebugKeys");
+	view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys");
+	view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc");
+	view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc");
+	commit.add("Advanced.ShowSideTray", boost::bind(&handle_show_side_tray));
+
+	// Advanced > XUI
+	commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance()));
+	view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames");
+	view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames");
+	view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs");
+	commit.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches));
+
+	// Advanced > Character > Grab Baked Texture
+	view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture");
+	view_listener_t::addMenu(new LLAdvancedEnableGrabBakedTexture(), "Advanced.EnableGrabBakedTexture");
+
+	// Advanced > Character > Character Tests
+	view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML");
+	view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry");
+
+	view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale");
+	view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale");
+	view_listener_t::addMenu(new LLAdvancedTogglePG(), "Advanced.TogglePG");
+	
+	// Advanced > Character (toplevel)
+	view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault");
+	view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader");
+	view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo");
+	view_listener_t::addMenu(new LLAdvancedCheckAnimationInfo(), "Advanced.CheckAnimationInfo");
+	view_listener_t::addMenu(new LLAdvancedToggleShowLookAt(), "Advanced.ToggleShowLookAt");
+	view_listener_t::addMenu(new LLAdvancedCheckShowLookAt(), "Advanced.CheckShowLookAt");
+	view_listener_t::addMenu(new LLAdvancedToggleShowPointAt(), "Advanced.ToggleShowPointAt");
+	view_listener_t::addMenu(new LLAdvancedCheckShowPointAt(), "Advanced.CheckShowPointAt");
+	view_listener_t::addMenu(new LLAdvancedToggleDebugJointUpdates(), "Advanced.ToggleDebugJointUpdates");
+	view_listener_t::addMenu(new LLAdvancedCheckDebugJointUpdates(), "Advanced.CheckDebugJointUpdates");
+	view_listener_t::addMenu(new LLAdvancedToggleDisableLOD(), "Advanced.ToggleDisableLOD");
+	view_listener_t::addMenu(new LLAdvancedCheckDisableLOD(), "Advanced.CheckDisableLOD");
+	view_listener_t::addMenu(new LLAdvancedToggleDebugCharacterVis(), "Advanced.ToggleDebugCharacterVis");
+	view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis");
+	view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments");
+	view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures");
+	view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures");
+	view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures");
+	// Advanced > Network
+	view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog");
+	view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog");
+	view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket");
+
+	// Advanced > Recorder
+	view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot");
+	view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop");
+	view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop");
+
+	// Advanced > Debugging
+	view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint");
+	view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror");
+	view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess");
+	view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
+	view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException");
+	view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash");
+	view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer");
+
+	// Advanced (toplevel)
+	view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates");
+	view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates");
+	view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage");
+	view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings");
+	view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions");
+	view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions");
+	view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions");
+	view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus");
+	view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus");
+
+
+	// Admin >Object
+	view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
+	view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf");
+	view_listener_t::addMenu(new LLAdminHandleObjectOwnerPermissive(), "Admin.HandleObjectOwnerPermissive");
+	view_listener_t::addMenu(new LLAdminHandleForceDelete(), "Admin.HandleForceDelete");
+	view_listener_t::addMenu(new LLAdminHandleObjectLock(), "Admin.HandleObjectLock");
+	view_listener_t::addMenu(new LLAdminHandleObjectAssetIDs(), "Admin.HandleObjectAssetIDs");
+
+	// Admin >Parcel 
+	view_listener_t::addMenu(new LLAdminHandleForceParcelOwnerToMe(), "Admin.HandleForceParcelOwnerToMe");
+	view_listener_t::addMenu(new LLAdminHandleForceParcelToContent(), "Admin.HandleForceParcelToContent");
+	view_listener_t::addMenu(new LLAdminHandleClaimPublicLand(), "Admin.HandleClaimPublicLand");
+
+	// Admin >Region
+	view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData");
+	// Admin top level
+	view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState");
+
+	// Self context menu
+	view_listener_t::addMenu(new LLSelfStandUp(), "Self.StandUp");
+	enable.add("Self.EnableStandUp", boost::bind(&enable_standup_self));
+	view_listener_t::addMenu(new LLSelfSitDown(), "Self.SitDown");
+	enable.add("Self.EnableSitDown", boost::bind(&enable_sitdown_self));
+	view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments");
+
+	view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments");
+
+	// we don't use boost::bind directly to delay side tray construction
+	view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab");
+
+	 // Avatar pie menu
+	view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");
+	view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
+	view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact");
+	commit.add("Avatar.Freeze", boost::bind(&handle_avatar_freeze, LLSD()));
+	view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug");
+	view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug");
+	view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
+	commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
+	commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector));
+	view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
+	view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call");
+	enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall));
+	view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
+	
+	view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
+	enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2));
+
+	// Object pie menu
+	view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
+	commit.add("Object.Touch", boost::bind(&handle_object_touch));
+	commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand));
+	commit.add("Object.Delete", boost::bind(&handle_object_delete));
+	view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar");
+	view_listener_t::addMenu(new LLObjectAttachToAvatar(false), "Object.AttachAddToAvatar");
+	view_listener_t::addMenu(new LLObjectReturn(), "Object.Return");
+	view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse");
+	view_listener_t::addMenu(new LLObjectMute(), "Object.Mute");
+
+	enable.add("Object.VisibleTake", boost::bind(&visible_take_object));
+	enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object));
+
+	commit.add("Object.Buy", boost::bind(&handle_buy));
+	commit.add("Object.Edit", boost::bind(&handle_object_edit));
+	commit.add("Object.Inspect", boost::bind(&handle_object_inspect));
+	commit.add("Object.Open", boost::bind(&handle_object_open));
+	commit.add("Object.Take", boost::bind(&handle_take));
+	commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector));
+	enable.add("Object.EnableOpen", boost::bind(&enable_object_open));
+	enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1));
+	enable.add("Object.EnableDelete", boost::bind(&enable_object_delete));
+	enable.add("Object.EnableWear", boost::bind(&object_selected_and_point_valid));
+
+	enable.add("Object.EnableStandUp", boost::bind(&enable_object_stand_up));
+	enable.add("Object.EnableSit", boost::bind(&enable_object_sit, _1));
+
+	view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn");
+	view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
+
+	enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));
+	enable.add("Object.EnableMute", boost::bind(&enable_object_mute));
+	enable.add("Object.EnableBuy", boost::bind(&enable_buy_object));
+	commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom"));
+
+	// Attachment pie menu
+	enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2));
+	view_listener_t::addMenu(new LLAttachmentDrop(), "Attachment.Drop");
+	view_listener_t::addMenu(new LLAttachmentDetachFromPoint(), "Attachment.DetachFromPoint");
+	view_listener_t::addMenu(new LLAttachmentDetach(), "Attachment.Detach");
+	view_listener_t::addMenu(new LLAttachmentPointFilled(), "Attachment.PointFilled");
+	view_listener_t::addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop");
+	view_listener_t::addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach");
+
+	// Land pie menu
+	view_listener_t::addMenu(new LLLandBuild(), "Land.Build");
+	view_listener_t::addMenu(new LLLandSit(), "Land.Sit");
+	view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass");
+	view_listener_t::addMenu(new LLLandEdit(), "Land.Edit");
+
+	view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass");
+	commit.add("Land.Buy", boost::bind(&handle_buy_land));
+
+	// Generic actions
+	commit.add("ReportAbuse", boost::bind(&handle_report_abuse));
+	commit.add("BuyCurrency", boost::bind(&handle_buy_currency));
+	view_listener_t::addMenu(new LLShowHelp(), "ShowHelp");
+	view_listener_t::addMenu(new LLToggleHelp(), "ToggleHelp");
+	view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL");
+	view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile");
+	view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile");
+	view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");
+	view_listener_t::addMenu(new LLCheckControl(), "CheckControl");
+	view_listener_t::addMenu(new LLGoToObject(), "GoToObject");
+	commit.add("PayObject", boost::bind(&handle_give_money_dialog));
+
+	enable.add("EnablePayObject", boost::bind(&enable_pay_object));
+	enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar));
+	enable.add("EnableEdit", boost::bind(&enable_object_edit));
+	enable.add("VisibleBuild", boost::bind(&enable_object_build));
+
+	view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible");
+	view_listener_t::addMenu(new LLShowSidetrayPanel(), "ShowSidetrayPanel");
+	view_listener_t::addMenu(new LLSidetrayPanelVisible(), "SidetrayPanelVisible");
+	view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected");
+	view_listener_t::addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD");
+	view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected");
+	view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono");
+
+	view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints");
+
+	commit.add("Destination.show", boost::bind(&toggle_destination_and_avatar_picker, 0));
+	commit.add("Avatar.show", boost::bind(&toggle_destination_and_avatar_picker, 1));
+}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 2843e4e9ae0bc1f479e31d9031806e8008e01c43..147163a9c0b7f2dd1b2e2917c0ea00747590719a 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1,5034 +1,5034 @@
-/** 
- * @file llviewerwindow.cpp
- * @brief Implementation of the LLViewerWindow class.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llviewerwindow.h"
-
-#if LL_WINDOWS
-#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
-#endif
-
-// system library includes
-#include <stdio.h>
-#include <iostream>
-#include <fstream>
-#include <algorithm>
-
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llfloaterreg.h"
-#include "llpanellogin.h"
-#include "llviewerkeyboard.h"
-#include "llviewermenu.h"
-
-#include "llviewquery.h"
-#include "llxmltree.h"
-#include "llslurl.h"
-//#include "llviewercamera.h"
-#include "llrender.h"
-
-#include "llvoiceclient.h"	// for push-to-talk button handling
-
-//
-// TODO: Many of these includes are unnecessary.  Remove them.
-//
-
-// linden library includes
-#include "llaudioengine.h"		// mute on minimize
-#include "indra_constants.h"
-#include "llassetstorage.h"
-#include "llerrorcontrol.h"
-#include "llfontgl.h"
-#include "llmousehandler.h"
-#include "llrect.h"
-#include "llsky.h"
-#include "llstring.h"
-#include "llui.h"
-#include "lluuid.h"
-#include "llview.h"
-#include "llxfermanager.h"
-#include "message.h"
-#include "object_flags.h"
-#include "lltimer.h"
-#include "timing.h"
-#include "llviewermenu.h"
-#include "lltooltip.h"
-#include "llmediaentry.h"
-#include "llurldispatcher.h"
-
-// newview includes
-#include "llagent.h"
-#include "llbox.h"
-#include "llconsole.h"
-#include "llviewercontrol.h"
-#include "llcylinder.h"
-#include "lldebugview.h"
-#include "lldir.h"
-#include "lldrawable.h"
-#include "lldrawpoolalpha.h"
-#include "lldrawpoolbump.h"
-#include "lldrawpoolwater.h"
-#include "llmaniptranslate.h"
-#include "llface.h"
-#include "llfeaturemanager.h"
-#include "llfilepicker.h"
-#include "llfirstuse.h"
-#include "llfloater.h"
-#include "llfloaterbuildoptions.h"
-#include "llfloaterbuyland.h"
-#include "llfloatercamera.h"
-#include "llfloaterland.h"
-#include "llfloaterinspect.h"
-#include "llfloatermap.h"
-#include "llfloaternamedesc.h"
-#include "llfloaterpreference.h"
-#include "llfloatersnapshot.h"
-#include "llfloatertools.h"
-#include "llfloaterworldmap.h"
-#include "llfocusmgr.h"
-#include "llfontfreetype.h"
-#include "llgesturemgr.h"
-#include "llglheaders.h"
-#include "lltooltip.h"
-#include "llhudmanager.h"
-#include "llhudobject.h"
-#include "llhudview.h"
-#include "llimagebmp.h"
-#include "llimagej2c.h"
-#include "llimageworker.h"
-#include "llkeyboard.h"
-#include "lllineeditor.h"
-#include "llmenugl.h"
-#include "llmodaldialog.h"
-#include "llmorphview.h"
-#include "llmoveview.h"
-#include "llnavigationbar.h"
-#include "llpopupview.h"
-#include "llpreviewtexture.h"
-#include "llprogressview.h"
-#include "llresmgr.h"
-#include "llsidetray.h"
-#include "llselectmgr.h"
-#include "llrootview.h"
-#include "llrendersphere.h"
-#include "llstartup.h"
-#include "llstatusbar.h"
-#include "llstatview.h"
-#include "llsurface.h"
-#include "llsurfacepatch.h"
-#include "lltexlayer.h"
-#include "lltextbox.h"
-#include "lltexturecache.h"
-#include "lltexturefetch.h"
-#include "lltextureview.h"
-#include "lltool.h"
-#include "lltoolcomp.h"
-#include "lltooldraganddrop.h"
-#include "lltoolface.h"
-#include "lltoolfocus.h"
-#include "lltoolgrab.h"
-#include "lltoolmgr.h"
-#include "lltoolmorph.h"
-#include "lltoolpie.h"
-#include "lltoolselectland.h"
-#include "lltrans.h"
-#include "lluictrlfactory.h"
-#include "llurldispatcher.h"		// SLURL from other app instance
-#include "llversioninfo.h"
-#include "llvieweraudio.h"
-#include "llviewercamera.h"
-#include "llviewergesture.h"
-#include "llviewertexturelist.h"
-#include "llviewerinventory.h"
-#include "llviewerkeyboard.h"
-#include "llviewermedia.h"
-#include "llviewermediafocus.h"
-#include "llviewermenu.h"
-#include "llviewermessage.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerregion.h"
-#include "llviewershadermgr.h"
-#include "llviewerstats.h"
-#include "llvoavatarself.h"
-#include "llvovolume.h"
-#include "llworld.h"
-#include "llworldmapview.h"
-#include "pipeline.h"
-#include "llappviewer.h"
-#include "llviewerdisplay.h"
-#include "llspatialpartition.h"
-#include "llviewerjoystick.h"
-#include "llviewernetwork.h"
-#include "llpostprocess.h"
-#include "llbottomtray.h"
-#include "llnearbychatbar.h"
-#include "llagentui.h"
-#include "llwearablelist.h"
-
-#include "llnotifications.h"
-#include "llnotificationsutil.h"
-#include "llnotificationmanager.h"
-
-#include "llfloaternotificationsconsole.h"
-
-#include "llnearbychat.h"
-#include "llviewerwindowlistener.h"
-#include "llpaneltopinfobar.h"
-
-#if LL_WINDOWS
-#include <tchar.h> // For Unicode conversion methods
-#endif
-
-//
-// Globals
-//
-void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
-
-extern BOOL gDebugClicks;
-extern BOOL gDisplaySwapBuffers;
-extern BOOL gDepthDirty;
-extern BOOL gResizeScreenTexture;
-
-LLViewerWindow	*gViewerWindow = NULL;
-
-LLFrameTimer	gAwayTimer;
-LLFrameTimer	gAwayTriggerTimer;
-
-BOOL			gShowOverlayTitle = FALSE;
-
-LLViewerObject*  gDebugRaycastObject = NULL;
-LLVector3       gDebugRaycastIntersection;
-LLVector2       gDebugRaycastTexCoord;
-LLVector3       gDebugRaycastNormal;
-LLVector3       gDebugRaycastBinormal;
-S32				gDebugRaycastFaceHit;
-
-// HUD display lines in lower right
-BOOL				gDisplayWindInfo = FALSE;
-BOOL				gDisplayCameraPos = FALSE;
-BOOL				gDisplayFOV = FALSE;
-BOOL				gDisplayBadge = FALSE;
-
-S32 CHAT_BAR_HEIGHT = 28; 
-S32 OVERLAY_BAR_HEIGHT = 20;
-
-const U8 NO_FACE = 255;
-BOOL gQuietSnapshot = FALSE;
-
-const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before coming back
-const F32 MAX_FAST_FRAME_TIME = 0.5f;
-const F32 FAST_FRAME_INCREMENT = 0.1f;
-
-const F32 MIN_DISPLAY_SCALE = 0.75f;
-
-std::string	LLViewerWindow::sSnapshotBaseName;
-std::string	LLViewerWindow::sSnapshotDir;
-
-std::string	LLViewerWindow::sMovieBaseName;
-
-class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole>
-{
-public:
-	virtual void recordMessage(LLError::ELevel level,
-								const std::string& message)
-	{
-		//FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread
-
-		// only log warnings to chat console
-		//if (level == LLError::LEVEL_WARN)
-		//{
-			//LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat");
-			//if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat"))
-			//{
-			//	LLChat chat;
-			//	chat.mText = message;
-			//	chat.mSourceType = CHAT_SOURCE_SYSTEM;
-
-			//	chat_floater->addChat(chat, FALSE, FALSE);
-			//}
-		//}
-	}
-};
-
-////////////////////////////////////////////////////////////////////////////
-//
-// LLDebugText
-//
-
-class LLDebugText
-{
-private:
-	struct Line
-	{
-		Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {}
-		std::string text;
-		S32 x,y;
-	};
-
-	LLViewerWindow *mWindow;
-	
-	typedef std::vector<Line> line_list_t;
-	line_list_t mLineList;
-	LLColor4 mTextColor;
-	
-	void addText(S32 x, S32 y, const std::string &text) 
-	{
-		mLineList.push_back(Line(text, x, y));
-	}
-	
-	void clearText() { mLineList.clear(); }
-	
-public:
-	LLDebugText(LLViewerWindow* window) : mWindow(window) {}
-
-	void update()
-	{
-		static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ;
-
-		std::string wind_vel_text;
-		std::string wind_vector_text;
-		std::string rwind_vel_text;
-		std::string rwind_vector_text;
-		std::string audio_text;
-
-		static const std::string beacon_particle = LLTrans::getString("BeaconParticle");
-		static const std::string beacon_physical = LLTrans::getString("BeaconPhysical");
-		static const std::string beacon_scripted = LLTrans::getString("BeaconScripted");
-		static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch");
-		static const std::string beacon_sound = LLTrans::getString("BeaconSound");
-		static const std::string beacon_media = LLTrans::getString("BeaconMedia");
-		static const std::string particle_hiding = LLTrans::getString("ParticleHiding");
-
-		// Draw the statistics in a light gray
-		// and in a thin font
-		mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
-
-		// Draw stuff growing up from right lower corner of screen
-		U32 xpos = mWindow->getWindowWidthScaled() - 350;
-		U32 ypos = 64;
-		const U32 y_inc = 20;
-
-		clearText();
-		
-		if (gSavedSettings.getBOOL("DebugShowTime"))
-		{
-			const U32 y_inc2 = 15;
-			for (std::map<S32,LLFrameTimer>::reverse_iterator iter = gDebugTimers.rbegin();
-				 iter != gDebugTimers.rend(); ++iter)
-			{
-				S32 idx = iter->first;
-				LLFrameTimer& timer = iter->second;
-				F32 time = timer.getElapsedTimeF32();
-				S32 hours = (S32)(time / (60*60));
-				S32 mins = (S32)((time - hours*(60*60)) / 60);
-				S32 secs = (S32)((time - hours*(60*60) - mins*60));
-				std::string label = gDebugTimerLabel[idx];
-				if (label.empty()) label = llformat("Debug: %d", idx);
-				addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2;
-			}
-			
-			F32 time = gFrameTimeSeconds;
-			S32 hours = (S32)(time / (60*60));
-			S32 mins = (S32)((time - hours*(60*60)) / 60);
-			S32 secs = (S32)((time - hours*(60*60) - mins*60));
-			addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
-		}
-		
-#if LL_WINDOWS
-		if (gSavedSettings.getBOOL("DebugShowMemory"))
-		{
-			addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getWorkingSetSize() / 1024)); 
-			ypos += y_inc;
-		}
-#endif
-
-		if (gDisplayCameraPos)
-		{
-			std::string camera_view_text;
-			std::string camera_center_text;
-			std::string agent_view_text;
-			std::string agent_left_text;
-			std::string agent_center_text;
-			std::string agent_root_center_text;
-
-			LLVector3d tvector; // Temporary vector to hold data for printing.
-
-			// Update camera center, camera view, wind info every other frame
-			tvector = gAgent.getPositionGlobal();
-			agent_center_text = llformat("AgentCenter  %f %f %f",
-										 (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-
-			if (isAgentAvatarValid())
-			{
-				tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition());
-				agent_root_center_text = llformat("AgentRootCenter %f %f %f",
-												  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-			}
-			else
-			{
-				agent_root_center_text = "---";
-			}
-
-
-			tvector = LLVector4(gAgent.getFrameAgent().getAtAxis());
-			agent_view_text = llformat("AgentAtAxis  %f %f %f",
-									   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-
-			tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis());
-			agent_left_text = llformat("AgentLeftAxis  %f %f %f",
-									   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-
-			tvector = gAgentCamera.getCameraPositionGlobal();
-			camera_center_text = llformat("CameraCenter %f %f %f",
-										  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-
-			tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis());
-			camera_view_text = llformat("CameraAtAxis    %f %f %f",
-										(F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
-		
-			addText(xpos, ypos, agent_center_text);  ypos += y_inc;
-			addText(xpos, ypos, agent_root_center_text);  ypos += y_inc;
-			addText(xpos, ypos, agent_view_text);  ypos += y_inc;
-			addText(xpos, ypos, agent_left_text);  ypos += y_inc;
-			addText(xpos, ypos, camera_center_text);  ypos += y_inc;
-			addText(xpos, ypos, camera_view_text);  ypos += y_inc;
-		}
-
-		if (gDisplayWindInfo)
-		{
-			wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec());
-			wind_vector_text = llformat("Wind vector   %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]);
-			rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec());
-			rwind_vector_text = llformat("RWind vec   %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]);
-
-			addText(xpos, ypos, wind_vel_text);  ypos += y_inc;
-			addText(xpos, ypos, wind_vector_text);  ypos += y_inc;
-			addText(xpos, ypos, rwind_vel_text);  ypos += y_inc;
-			addText(xpos, ypos, rwind_vector_text);  ypos += y_inc;
-		}
-		if (gDisplayWindInfo)
-		{
-			if (gAudiop)
-			{
-				audio_text= llformat("Audio for wind: %d", gAudiop->isWindEnabled());
-			}
-			addText(xpos, ypos, audio_text);  ypos += y_inc;
-		}
-		if (gDisplayFOV)
-		{
-			addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
-			ypos += y_inc;
-		}
-		if (gDisplayBadge)
-		{
-			addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
-			ypos += y_inc * 2;
-		}
-		
-		/*if (LLViewerJoystick::getInstance()->getOverrideCamera())
-		{
-			addText(xpos + 200, ypos, llformat("Flycam"));
-			ypos += y_inc;
-		}*/
-		
-		if (gSavedSettings.getBOOL("DebugShowRenderInfo"))
-		{
-			if (gPipeline.getUseVertexShaders() == 0)
-			{
-				addText(xpos, ypos, "Shaders Disabled");
-				ypos += y_inc;
-			}
-			addText(xpos, ypos, llformat("%d MB Vertex Data", LLVertexBuffer::sAllocatedBytes/(1024*1024)));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Mapped Buffers", LLVertexBuffer::sMappedCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Vertex Buffer Binds", LLVertexBuffer::sBindCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Vertex Buffer Sets", LLVertexBuffer::sSetCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount));
-            ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps));
-			ypos += y_inc;
-
-			gPipeline.mTextureMatrixOps = 0;
-			gPipeline.mMatrixOpCount = 0;
-
-			if (gPipeline.mBatchCount > 0)
-			{
-				addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, 
-					gPipeline.mTrianglesDrawn/gPipeline.mBatchCount));
-
-				gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize;
-				gPipeline.mMaxBatchSize = 0;
-				gPipeline.mBatchCount = 0;
-			}
-            ypos += y_inc;
-
-			addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls));
-			LLRender::sUICalls = LLRender::sUIVerts = 0;
-			ypos += y_inc;
-
-			addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount));
-			
-			ypos += y_inc;
-
-
-			addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars));
-			
-			ypos += y_inc;
-
-			addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount));
-			
-			ypos += y_inc;
-
-			LLVertexBuffer::sBindCount = LLImageGL::sBindCount = 
-				LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = 
-				gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0;
-		}
-		if (gSavedSettings.getBOOL("DebugShowRenderMatrices"))
-		{
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[8], gGLProjection[9], gGLProjection[10], gGLProjection[11]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[4], gGLProjection[5], gGLProjection[6], gGLProjection[7]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[0], gGLProjection[1], gGLProjection[2], gGLProjection[3]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, "Projection Matrix");
-			ypos += y_inc;
-
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[12], gGLModelView[13], gGLModelView[14], gGLModelView[15]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[8], gGLModelView[9], gGLModelView[10], gGLModelView[11]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[4], gGLModelView[5], gGLModelView[6], gGLModelView[7]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[0], gGLModelView[1], gGLModelView[2], gGLModelView[3]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, "View Matrix");
-			ypos += y_inc;
-		}
-		if (gSavedSettings.getBOOL("DebugShowColor"))
-		{
-			U8 color[4];
-			LLCoordGL coord = gViewerWindow->getCurrentMouse();
-			glReadPixels(coord.mX, coord.mY, 1,1,GL_RGBA, GL_UNSIGNED_BYTE, color);
-			addText(xpos, ypos, llformat("%d %d %d %d", color[0], color[1], color[2], color[3]));
-			ypos += y_inc;
-		}
-		// only display these messages if we are actually rendering beacons at this moment
-		if (LLPipeline::getRenderBeacons(NULL) && LLFloaterReg::instanceVisible("beacons"))
-		{
-			if (LLPipeline::getRenderParticleBeacons(NULL))
-			{
-				addText(xpos, ypos, beacon_particle);
-				ypos += y_inc;
-			}
-			if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES))
-			{
-				addText(xpos, ypos, particle_hiding);
-				ypos += y_inc;
-			}
-			if (LLPipeline::getRenderPhysicalBeacons(NULL))
-			{
-				addText(xpos, ypos, beacon_physical);
-				ypos += y_inc;
-			}
-			if (LLPipeline::getRenderScriptedBeacons(NULL))
-			{
-				addText(xpos, ypos, beacon_scripted);
-				ypos += y_inc;
-			}
-			else
-				if (LLPipeline::getRenderScriptedTouchBeacons(NULL))
-				{
-					addText(xpos, ypos, beacon_scripted_touch);
-					ypos += y_inc;
-				}
-			if (LLPipeline::getRenderSoundBeacons(NULL))
-			{
-				addText(xpos, ypos, beacon_sound);
-				ypos += y_inc;
-			}
-		}
-		if(log_texture_traffic)
-		{	
-			U32 old_y = ypos ;
-			for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++)
-			{
-				if(gTotalTextureBytesPerBoostLevel[i] > 0)
-				{
-					addText(xpos, ypos, llformat("Boost_Level %d:  %.3f MB", i, (F32)gTotalTextureBytesPerBoostLevel[i] / (1024 * 1024)));
-					ypos += y_inc;
-				}
-			}
-			if(ypos != old_y)
-			{
-				addText(xpos, ypos, "Network traffic for textures:");
-				ypos += y_inc;
-			}
-		}
-		
-		if (gSavedSettings.getBOOL("DebugShowTextureInfo"))
-		{
-			LLViewerObject* objectp = NULL ;
-			//objectp = = gAgentCamera.getFocusObject();
-			
-			LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
-			if (nodep)
-			{
-				objectp = nodep->getObject();			
-			}
-			if (objectp && !objectp->isDead())
-			{
-				S32 num_faces = objectp->mDrawable->getNumFaces() ;
-				
-				for(S32 i = 0 ; i < num_faces; i++)
-				{
-					LLFace* facep = objectp->mDrawable->getFace(i) ;
-					if(facep)
-					{
-						//addText(xpos, ypos, llformat("ts_min: %.3f ts_max: %.3f tt_min: %.3f tt_max: %.3f", facep->mTexExtents[0].mV[0], facep->mTexExtents[1].mV[0],
-						//		facep->mTexExtents[0].mV[1], facep->mTexExtents[1].mV[1]));
-						//ypos += y_inc;
-						
-						addText(xpos, ypos, llformat("v_size: %.3f:  p_size: %.3f", facep->getVirtualSize(), facep->getPixelArea()));
-						ypos += y_inc;
-						
-						//const LLTextureEntry *tep = facep->getTextureEntry();
-						//if(tep)
-						//{
-						//	addText(xpos, ypos, llformat("scale_s: %.3f:  scale_t: %.3f", tep->mScaleS, tep->mScaleT)) ;
-						//	ypos += y_inc;
-						//}
-						
-						LLViewerTexture* tex = facep->getTexture() ;
-						if(tex)
-						{
-							addText(xpos, ypos, llformat("ID: %s v_size: %.3f", tex->getID().asString().c_str(), tex->getMaxVirtualSize()));
-							ypos += y_inc;
-						}
-					}
-				}
-			}
-		}
-	}
-
-	void draw()
-	{
-		for (line_list_t::iterator iter = mLineList.begin();
-			 iter != mLineList.end(); ++iter)
-		{
-			const Line& line = *iter;
-			LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
-											 LLFontGL::LEFT, LLFontGL::TOP,
-											 LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
-		}
-		mLineList.clear();
-	}
-
-};
-
-void LLViewerWindow::updateDebugText()
-{
-	mDebugText->update();
-}
-
-////////////////////////////////////////////////////////////////////////////
-//
-// LLViewerWindow
-//
-
-BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
-{
-	const char* buttonname = "";
-	const char* buttonstatestr = "";
-	S32 x = pos.mX;
-	S32 y = pos.mY;
-	x = llround((F32)x / mDisplayScale.mV[VX]);
-	y = llround((F32)y / mDisplayScale.mV[VY]);
-
-	// only send mouse clicks to UI if UI is visible
-	if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{	
-
-		if (down)
-		{
-			buttonstatestr = "down" ;
-		}
-		else
-		{
-			buttonstatestr = "up" ;
-		}
-		
-		switch (clicktype)
-		{
-		case LLMouseHandler::CLICK_LEFT:
-			mLeftMouseDown = down;
-			buttonname = "Left";
-			break;
-		case LLMouseHandler::CLICK_RIGHT:
-			mRightMouseDown = down;
-			buttonname = "Right";
-			break;
-		case LLMouseHandler::CLICK_MIDDLE:
-			mMiddleMouseDown = down;
-			buttonname = "Middle";
-			break;
-		case LLMouseHandler::CLICK_DOUBLELEFT:
-			mLeftMouseDown = down;
-			buttonname = "Left Double Click";
-			break;
-		}
-		
-		LLView::sMouseHandlerMessage.clear();
-
-		if (gMenuBarView)
-		{
-			// stop ALT-key access to menu
-			gMenuBarView->resetMenuTrigger();
-		}
-
-		if (gDebugClicks)
-		{	
-			llinfos << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << llendl;
-		}
-
-		// Make sure we get a corresponding mouseup event, even if the mouse leaves the window
-		if (down)
-			mWindow->captureMouse();
-		else
-			mWindow->releaseMouse();
-
-		// Indicate mouse was active
-		LLUI::resetMouseIdleTimer();
-
-		// Don't let the user move the mouse out of the window until mouse up.
-		if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
-		{
-			mWindow->setMouseClipping(down);
-		}
-
-		LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
-		if( mouse_captor )
-		{
-			S32 local_x;
-			S32 local_y;
-			mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
-			if (LLView::sDebugMouseHandling)
-			{
-				llinfos << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << llendl;
-			}
-			return mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down);
-		}
-
-		// Topmost view gets a chance before the hierarchy
-		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-		//if (top_ctrl)
-		//{
-		//	S32 local_x, local_y;
-		//	top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
-		//		if (top_ctrl->pointInView(local_x, local_y))
-		//		{
-		//			return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down)	;
-		//		}
-		//		else
-		//		{
-		//		if (down)
-		//		{
-		//			gFocusMgr.setTopCtrl(NULL);
-		//		}
-		//	}
-		//}
-
-		// Give the UI views a chance to process the click
-		if( mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) )
-		{
-			if (LLView::sDebugMouseHandling)
-			{
-				llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLView::sMouseHandlerMessage << llendl;
-			}
-			return TRUE;
-		}
-		else if (LLView::sDebugMouseHandling)
-		{
-			llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl;
-		}
-	}
-
-	// Do not allow tool manager to handle mouseclicks if we have disconnected	
-	if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )
-	{
-		return TRUE;
-	}
-	
-
-	// If we got this far on a down-click, it wasn't handled.
-	// Up-clicks, though, are always handled as far as the OS is concerned.
-	BOOL default_rtn = !down;
-	return default_rtn;
-}
-
-BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = TRUE;
-	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
-}
-
-BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	// try handling as a double-click first, then a single-click if that
-	// wasn't handled.
-	BOOL down = TRUE;
-	if (handleAnyMouseClick(window, pos, mask,
-				LLMouseHandler::CLICK_DOUBLELEFT, down))
-	{
-		return TRUE;
-	}
-	return handleMouseDown(window, pos, mask);
-}
-
-BOOL LLViewerWindow::handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = FALSE;
-	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
-}
-
-
-BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	S32 x = pos.mX;
-	S32 y = pos.mY;
-	x = llround((F32)x / mDisplayScale.mV[VX]);
-	y = llround((F32)y / mDisplayScale.mV[VY]);
-
-	BOOL down = TRUE;
-	BOOL handle = handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
-	if (handle)
-		return handle;
-
-	// *HACK: this should be rolled into the composite tool logic, not
-	// hardcoded at the top level.
-	if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance())
-	{
-		// If the current tool didn't process the click, we should show
-		// the pie menu.  This can be done by passing the event to the pie
-		// menu tool.
-		LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
-		// show_context_menu( x, y, mask );
-	}
-
-	return TRUE;
-}
-
-BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = FALSE;
- 	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
-}
-
-BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = TRUE;
-	LLVoiceClient::getInstance()->middleMouseState(true);
- 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
-  
-  	// Always handled as far as the OS is concerned.
-	return TRUE;
-}
-
-LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data)
-{
-	LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE;
-
-	const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop");
-	const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop");
-	
-	if ( prim_media_dnd_enabled || slurl_dnd_enabled )
-	{
-		switch(action)
-		{
-			// Much of the handling for these two cases is the same.
-			case LLWindowCallbacks::DNDA_TRACK:
-			case LLWindowCallbacks::DNDA_DROPPED:
-			case LLWindowCallbacks::DNDA_START_TRACKING:
-			{
-				bool drop = (LLWindowCallbacks::DNDA_DROPPED == action);
-					
-				if (slurl_dnd_enabled)
-				{
-					LLSLURL dropped_slurl(data);
-					if(dropped_slurl.isSpatial())
-					{
-						if (drop)
-						{
-							LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), NULL, true );
-							return LLWindowCallbacks::DND_MOVE;
-						}
-						return LLWindowCallbacks::DND_COPY;
-					}
-				}
-
-				if (prim_media_dnd_enabled)
-				{
-					LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY,  TRUE /*BOOL pick_transparent*/ );
-
-					LLUUID object_id = pick_info.getObjectID();
-					S32 object_face = pick_info.mObjectFace;
-					std::string url = data;
-
-					lldebugs << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl;
-
-					LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject()));
-				
-					if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty())
-					{
-						LLTextureEntry *te = obj->getTE(object_face);
-
-						// can modify URL if we can modify the object or we have navigate permissions
-						bool allow_modify_url = obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT );
-
-						if (te && allow_modify_url )
-						{
-							if (drop)
-							{
-								// object does NOT have media already
-								if ( ! te->hasMedia() )
-								{
-									// we are allowed to modify the object
-									if ( obj->permModify() )
-									{
-										// Create new media entry
-										LLSD media_data;
-										// XXX Should we really do Home URL too?
-										media_data[LLMediaEntry::HOME_URL_KEY] = url;
-										media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
-										media_data[LLMediaEntry::AUTO_PLAY_KEY] = true;
-										obj->syncMediaData(object_face, media_data, true, true);
-										// XXX This shouldn't be necessary, should it ?!?
-										if (obj->getMediaImpl(object_face))
-											obj->getMediaImpl(object_face)->navigateReload();
-										obj->sendMediaDataUpdate();
-
-										result = LLWindowCallbacks::DND_COPY;
-									}
-								}
-								else 
-								// object HAS media already
-								{
-									// URL passes the whitelist
-									if (te->getMediaData()->checkCandidateUrl( url ) )
-									{
-										// just navigate to the URL
-										if (obj->getMediaImpl(object_face))
-										{
-											obj->getMediaImpl(object_face)->navigateTo(url);
-										}
-										else 
-										{
-											// This is very strange.  Navigation should
-											// happen via the Impl, but we don't have one.
-											// This sends it to the server, which /should/
-											// trigger us getting it.  Hopefully.
-											LLSD media_data;
-											media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
-											obj->syncMediaData(object_face, media_data, true, true);
-											obj->sendMediaDataUpdate();
-										}
-										result = LLWindowCallbacks::DND_LINK;
-										
-									}
-								}
-								LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
-								mDragHoveredObject = NULL;
-							
-							}
-							else 
-							{
-								// Check the whitelist, if there's media (otherwise just show it)
-								if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
-								{
-									if ( obj != mDragHoveredObject)
-									{
-										// Highlight the dragged object
-										LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
-										mDragHoveredObject = obj;
-										LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject);
-									}
-									result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK;
-
-								}
-							}
-						}
-					}
-				}
-			}
-			break;
-			
-			case LLWindowCallbacks::DNDA_STOP_TRACKING:
-				// The cleanup case below will make sure things are unhilighted if necessary.
-			break;
-		}
-
-		if (prim_media_dnd_enabled &&
-			result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull())
-		{
-			LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
-			mDragHoveredObject = NULL;
-		}
-	}
-	
-	return result;
-}
-  
-BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	BOOL down = FALSE;
-	LLVoiceClient::getInstance()->middleMouseState(false);
- 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
-  
-  	// Always handled as far as the OS is concerned.
-	return TRUE;
-}
-
-// WARNING: this is potentially called multiple times per frame
-void LLViewerWindow::handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask)
-{
-	S32 x = pos.mX;
-	S32 y = pos.mY;
-
-	x = llround((F32)x / mDisplayScale.mV[VX]);
-	y = llround((F32)y / mDisplayScale.mV[VY]);
-
-	mMouseInWindow = TRUE;
-
-	// Save mouse point for access during idle() and display()
-
-	LLCoordGL mouse_point(x, y);
-
-	if (mouse_point != mCurrentMousePoint)
-	{
-		LLUI::resetMouseIdleTimer();
-	}
-
-	saveLastMouse(mouse_point);
-
-	mWindow->showCursorFromMouseMove();
-
-	if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
-	{
-		gAgent.clearAFK();
-	}
-}
-
-void LLViewerWindow::handleMouseLeave(LLWindow *window)
-{
-	// Note: we won't get this if we have captured the mouse.
-	llassert( gFocusMgr.getMouseCapture() == NULL );
-	mMouseInWindow = FALSE;
-	LLToolTipMgr::instance().blockToolTips();
-}
-
-BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
-{
-	// User has indicated they want to close, but we may need to ask
-	// about modified documents.
-	LLAppViewer::instance()->userQuit();
-	// Don't quit immediately
-	return FALSE;
-}
-
-void LLViewerWindow::handleQuit(LLWindow *window)
-{
-	LLAppViewer::instance()->forceQuit();
-}
-
-void LLViewerWindow::handleResize(LLWindow *window,  S32 width,  S32 height)
-{
-	reshape(width, height);
-	mResDirty = true;
-}
-
-// The top-level window has gained focus (e.g. via ALT-TAB)
-void LLViewerWindow::handleFocus(LLWindow *window)
-{
-	gFocusMgr.setAppHasFocus(TRUE);
-	LLModalDialog::onAppFocusGained();
-
-	gAgent.onAppFocusGained();
-	LLToolMgr::getInstance()->onAppFocusGained();
-
-	// See if we're coming in with modifier keys held down
-	if (gKeyboard)
-	{
-		gKeyboard->resetMaskKeys();
-	}
-
-	// resume foreground running timer
-	// since we artifically limit framerate when not frontmost
-	gForegroundTime.unpause();
-}
-
-// The top-level window has lost focus (e.g. via ALT-TAB)
-void LLViewerWindow::handleFocusLost(LLWindow *window)
-{
-	gFocusMgr.setAppHasFocus(FALSE);
-	//LLModalDialog::onAppFocusLost();
-	LLToolMgr::getInstance()->onAppFocusLost();
-	gFocusMgr.setMouseCapture( NULL );
-
-	if (gMenuBarView)
-	{
-		// stop ALT-key access to menu
-		gMenuBarView->resetMenuTrigger();
-	}
-
-	// restore mouse cursor
-	showCursor();
-	getWindow()->setMouseClipping(FALSE);
-
-	// If losing focus while keys are down, reset them.
-	if (gKeyboard)
-	{
-		gKeyboard->resetKeys();
-	}
-
-	// pause timer that tracks total foreground running time
-	gForegroundTime.pause();
-}
-
-
-BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
-{
-	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
-	LLVoiceClient::getInstance()->keyDown(key, mask);
-	
-	if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
-	{
-		gAgent.clearAFK();
-	}
-
-	// *NOTE: We want to interpret KEY_RETURN later when it arrives as
-	// a Unicode char, not as a keydown.  Otherwise when client frame
-	// rate is really low, hitting return sends your chat text before
-	// it's all entered/processed.
-	if (key == KEY_RETURN && mask == MASK_NONE)
-	{
-		return FALSE;
-	}
-
-	return gViewerKeyboard.handleKey(key, mask, repeated);
-}
-
-BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
-{
-	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
-	LLVoiceClient::getInstance()->keyUp(key, mask);
-
-	return FALSE;
-}
-
-
-void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
-{
-	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
-	return gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
-}
-
-
-
-
-BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated)
-{
-	if (activated)
-	{
-		mActive = TRUE;
-		send_agent_resume();
-		gAgent.clearAFK();
-		
-		// Unmute audio
-		audio_update_volume();
-	}
-	else
-	{
-		mActive = FALSE;
-				
-		if (gSavedSettings.getS32("AFKTimeout"))
-		{
-			gAgent.setAFK();
-		}
-		
-		// SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues
-		if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
-		{
-			gAgentCamera.changeCameraToDefault();
-		}
-		
-		send_agent_pause();
-	
-		// Mute audio
-		audio_update_volume();
-	}
-	return TRUE;
-}
-
-BOOL LLViewerWindow::handleActivateApp(LLWindow *window, BOOL activating)
-{
-	//if (!activating) gAgentCamera.changeCameraToDefault();
-
-	LLViewerJoystick::getInstance()->setNeedsReset(true);
-	return FALSE;
-}
-
-
-void LLViewerWindow::handleMenuSelect(LLWindow *window,  S32 menu_item)
-{
-}
-
-
-BOOL LLViewerWindow::handlePaint(LLWindow *window,  S32 x,  S32 y, S32 width,  S32 height)
-{
-#if LL_WINDOWS
-	if (gNoRender)
-	{
-		HWND window_handle = (HWND)window->getPlatformWindow();
-		PAINTSTRUCT ps; 
-		HDC hdc; 
- 
-		RECT wnd_rect;
-		wnd_rect.left = 0;
-		wnd_rect.top = 0;
-		wnd_rect.bottom = 200;
-		wnd_rect.right = 500;
-
-		hdc = BeginPaint(window_handle, &ps); 
-		//SetBKColor(hdc, RGB(255, 255, 255));
-		FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
-
-		std::string temp_str;
-		temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f",		/* Flawfinder: ignore */
-				LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(),
-				LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0),
-				LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0));
-		S32 len = temp_str.length();
-		TextOutA(hdc, 0, 0, temp_str.c_str(), len); 
-
-
-		LLVector3d pos_global = gAgent.getPositionGlobal();
-		temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]);
-		len = temp_str.length();
-		TextOutA(hdc, 0, 25, temp_str.c_str(), len); 
-
-		TextOutA(hdc, 0, 50, "Set \"DisableRendering FALSE\" in settings.ini file to reenable", 61);
-		EndPaint(window_handle, &ps); 
-		return TRUE;
-	}
-#endif
-	return FALSE;
-}
-
-
-void LLViewerWindow::handleScrollWheel(LLWindow *window,  S32 clicks)
-{
-	handleScrollWheel( clicks );
-}
-
-void LLViewerWindow::handleWindowBlock(LLWindow *window)
-{
-	send_agent_pause();
-}
-
-void LLViewerWindow::handleWindowUnblock(LLWindow *window)
-{
-	send_agent_resume();
-}
-
-void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
-{
-	const S32 SLURL_MESSAGE_TYPE = 0;
-	switch (data_type)
-	{
-	case SLURL_MESSAGE_TYPE:
-		// received URL
-		std::string url = (const char*)data;
-		LLMediaCtrl* web = NULL;
-		const bool trusted_browser = false;
-		if (LLURLDispatcher::dispatch(url, web, trusted_browser))
-		{
-			// bring window to foreground, as it has just been "launched" from a URL
-			mWindow->bringToFront();
-		}
-		break;
-	}
-}
-
-BOOL LLViewerWindow::handleTimerEvent(LLWindow *window)
-{
-	if (LLViewerJoystick::getInstance()->getOverrideCamera())
-	{
-		LLViewerJoystick::getInstance()->updateStatus();
-		return TRUE;
-	}
-	return FALSE;
-}
-
-BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
-{
-	// give a chance to use a joystick after startup (hot-plugging)
-	if (!LLViewerJoystick::getInstance()->isJoystickInitialized() )
-	{
-		LLViewerJoystick::getInstance()->init(true);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg)
-{
-	LLAppViewer::instance()->pingMainloopTimeout(msg);
-}
-
-
-void LLViewerWindow::handleResumeWatchdog(LLWindow *window)
-{
-	LLAppViewer::instance()->resumeMainloopTimeout();
-}
-
-void LLViewerWindow::handlePauseWatchdog(LLWindow *window)
-{
-	LLAppViewer::instance()->pauseMainloopTimeout();
-}
-
-//virtual
-std::string LLViewerWindow::translateString(const char* tag)
-{
-	return LLTrans::getString( std::string(tag) );
-}
-
-//virtual
-std::string LLViewerWindow::translateString(const char* tag,
-		const std::map<std::string, std::string>& args)
-{
-	// LLTrans uses a special subclass of std::string for format maps,
-	// but we must use std::map<> in these callbacks, otherwise we create
-	// a dependency between LLWindow and LLFormatMapString.  So copy the data.
-	LLStringUtil::format_map_t args_copy;
-	std::map<std::string,std::string>::const_iterator it = args.begin();
-	for ( ; it != args.end(); ++it)
-	{
-		args_copy[it->first] = it->second;
-	}
-	return LLTrans::getString( std::string(tag), args_copy);
-}
-
-//
-// Classes
-//
-LLViewerWindow::LLViewerWindow(
-	const std::string& title, const std::string& name,
-	S32 x, S32 y,
-	S32 width, S32 height,
-	BOOL fullscreen, BOOL ignore_pixel_depth) // fullscreen is no longer used
-	:
-	mWindow(NULL),
-	mActive(TRUE),
-	mWindowRectRaw(0, height, width, 0),
-	mWindowRectScaled(0, height, width, 0),
-	mWorldViewRectRaw(0, height, width, 0),
-	mLeftMouseDown(FALSE),
-	mMiddleMouseDown(FALSE),
-	mRightMouseDown(FALSE),
-	mMouseInWindow( FALSE ),
-	mLastMask( MASK_NONE ),
-	mToolStored( NULL ),
-	mHideCursorPermanent( FALSE ),
-	mCursorHidden(FALSE),
-	mIgnoreActivate( FALSE ),
-	mResDirty(false),
-	mStatesDirty(false),
-	mCurrResolutionIndex(0),
-    mViewerWindowListener(new LLViewerWindowListener(this)),
-	mProgressView(NULL)
-{
-	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
-	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
-
-	LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
-	LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
-	LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));
-	llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl;
-
-	// Default to application directory.
-	LLViewerWindow::sSnapshotBaseName = "Snapshot";
-	LLViewerWindow::sMovieBaseName = "SLmovie";
-	resetSnapshotLoc();
-
-	// create window
-	mWindow = LLWindowManager::createWindow(this,
-		title, name, x, y, width, height, 0,
-		fullscreen, 
-		gNoRender,
-		gSavedSettings.getBOOL("DisableVerticalSync"),
-		!gNoRender,
-		ignore_pixel_depth,
-		gSavedSettings.getBOOL("RenderUseFBO") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled
-
-	if (!LLAppViewer::instance()->restoreErrorTrap())
-	{
-		LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL;
-	}
-
-	LLCoordScreen scr;
-    mWindow->getSize(&scr);
-
-    if(fullscreen && ( scr.mX!=width || scr.mY!=height))
-    {
-		llwarns << "Fullscreen has forced us in to a different resolution now using "<<scr.mX<<" x "<<scr.mY<<llendl;
-		gSavedSettings.setS32("FullScreenWidth",scr.mX);
-		gSavedSettings.setS32("FullScreenHeight",scr.mY);
-    }
-
-	if (NULL == mWindow)
-	{
-		LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
-#if LL_LINUX || LL_SOLARIS
-		llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly.  See README-linux.txt or README-solaris.txt for further information."
-				<< llendl;
-#else
-		LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings"
-				<< LL_ENDL;
-#endif
-        LLAppViewer::instance()->fastQuit(1);
-	}
-	
-	// Get the real window rect the window was created with (since there are various OS-dependent reasons why
-	// the size of a window or fullscreen context may have been adjusted slightly...)
-	F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
-	
-	mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
-	mDisplayScale *= ui_scale_factor;
-	LLUI::setScaleFactor(mDisplayScale);
-
-	{
-		LLCoordWindow size;
-		mWindow->getSize(&size);
-		mWindowRectRaw.set(0, size.mY, size.mX, 0);
-		mWindowRectScaled.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0);
-	}
-	
-	LLFontManager::initClass();
-
-	//
-	// We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off
-	// stuff like AGP if we think that it'll crash the viewer.
-	//
-	LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
-
-	LLFeatureManager::getInstance()->init();
-
-	// Initialize OpenGL Renderer
-	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
-		!gGLManager.mHasVertexBufferObject)
-	{
-		gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
-	}
-	LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
-
-	if (LLFeatureManager::getInstance()->isSafe()
-		|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
-		|| (gSavedSettings.getS32("LastGPUClass") != LLFeatureManager::getInstance()->getGPUClass())
-		|| (gSavedSettings.getBOOL("ProbeHardwareOnStartup")))
-	{
-		LLFeatureManager::getInstance()->applyRecommendedSettings();
-		gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
-	}
-
-	if (!gGLManager.mHasDepthClamp)
-	{
-		LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL;
-	}
-	
-	// If we crashed while initializng GL stuff last time, disable certain features
-	if (gSavedSettings.getBOOL("RenderInitError"))
-	{
-		mInitAlert = "DisplaySettingsNoShaders";
-		LLFeatureManager::getInstance()->setGraphicsLevel(0, false);
-		gSavedSettings.setU32("RenderQualityPerformance", 0);		
-	}
-		
-	// Init the image list.  Must happen after GL is initialized and before the images that
-	// LLViewerWindow needs are requested.
-	LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ;
-	gTextureList.init();
-	LLViewerTextureManager::init() ;
-	gBumpImageList.init();
-	
-	// Init font system, but don't actually load the fonts yet
-	// because our window isn't onscreen and they take several
-	// seconds to parse.
-	LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
-								mDisplayScale.mV[VX],
-								mDisplayScale.mV[VY],
-								gDirUtilp->getAppRODataDir(),
-								LLUI::getXUIPaths());
-	
-	// Create container for all sub-views
-	LLView::Params rvp;
-	rvp.name("root");
-	rvp.rect(mWindowRectScaled);
-	rvp.mouse_opaque(false);
-	rvp.follows.flags(FOLLOWS_NONE);
-	mRootView = LLUICtrlFactory::create<LLRootView>(rvp);
-	LLUI::setRootView(mRootView);
-
-	// Make avatar head look forward at start
-	mCurrentMousePoint.mX = getWindowWidthScaled() / 2;
-	mCurrentMousePoint.mY = getWindowHeightScaled() / 2;
-
-	gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
-	mOverlayTitle = gSavedSettings.getString("OverlayTitle");
-	// Can't have spaces in settings.ini strings, so use underscores instead and convert them.
-	LLStringUtil::replaceChar(mOverlayTitle, '_', ' ');
-
-	// sync the keyboard's setting with the saved setting
-	gSavedSettings.getControl("NumpadControl")->firePropertyChanged();
-
-	mDebugText = new LLDebugText(this);
-
-	mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
-}
-
-void LLViewerWindow::initGLDefaults()
-{
-	gGL.setSceneBlendType(LLRender::BT_ALPHA);
-	glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
-
-	F32 ambient[4] = {0.f,0.f,0.f,0.f };
-	F32 diffuse[4] = {1.f,1.f,1.f,1.f };
-	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambient);
-	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuse);
-	
-	glPixelStorei(GL_PACK_ALIGNMENT,1);
-	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
-
-	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-
-	// lights for objects
-	glShadeModel( GL_SMOOTH );
-
-	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
-	
-	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
-	glCullFace(GL_BACK);
-
-	// RN: Need this for translation and stretch manip.
-	gCone.prerender();
-	gBox.prerender();
-	gSphere.prerender();
-	gCylinder.prerender();
-}
-
-struct MainPanel : public LLPanel
-{
-};
-
-void LLViewerWindow::initBase()
-{
-	S32 height = getWindowHeightScaled();
-	S32 width = getWindowWidthScaled();
-
-	LLRect full_window(0, height, width, 0);
-
-	////////////////////
-	//
-	// Set the gamma
-	//
-
-	F32 gamma = gSavedSettings.getF32("RenderGamma");
-	if (gamma != 0.0f)
-	{
-		getWindow()->setGamma(gamma);
-	}
-
-	// Create global views
-
-	// Create the floater view at the start so that other views can add children to it. 
-	// (But wait to add it as a child of the root view so that it will be in front of the 
-	// other views.)
-	MainPanel* main_view = new MainPanel();
-	main_view->buildFromFile("main_view.xml");
-	main_view->setShape(full_window);
-	getRootView()->addChild(main_view);
-
-	// placeholder widget that controls where "world" is rendered
-	mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle();
-	mNonSideTrayView = main_view->getChildView("non_side_tray_view")->getHandle();
-	mFloaterViewHolder = main_view->getChildView("floater_view_holder")->getHandle();
-	mPopupView = main_view->getChild<LLPopupView>("popup_holder");
-	mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle();
-	mLoginPanelHolder = main_view->getChild<LLView>("login_panel_holder")->getHandle();
-
-	// Constrain floaters to inside the menu and status bar regions.
-	gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
-	gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());
-	gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
-	
-
-	// Console
-	llassert( !gConsole );
-	LLConsole::Params cp;
-	cp.name("console");
-	cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize"));
-	cp.rect(getChatConsoleRect());
-	cp.persist_time(gSavedSettings.getF32("ChatPersistTime"));
-	cp.font_size_index(gSavedSettings.getS32("ChatFontSize"));
-	cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
-	gConsole = LLUICtrlFactory::create<LLConsole>(cp);
-	getRootView()->addChild(gConsole);
-
-	// optionally forward warnings to chat console/chat floater
-	// for qa runs and dev builds
-#if  !LL_RELEASE_FOR_DOWNLOAD
-	LLError::addRecorder(RecordToChatConsole::getInstance());
-#else
-	if(gSavedSettings.getBOOL("QAMode"))
-	{
-		LLError::addRecorder(RecordToChatConsole::getInstance());
-	}
-#endif
-
-	gDebugView = getRootView()->getChild<LLDebugView>("DebugView");
-	gDebugView->init();
-	gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view");
-
-	// Initialize busy response message when logged in
-	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initBusyResponse));
-
-	// Add the progress bar view (startup view), which overrides everything
-	mProgressView = getRootView()->findChild<LLProgressView>("progress_view");
-	setShowProgress(FALSE);
-	setProgressCancelButtonVisible(FALSE);
-
-	gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
-
-	LLMenuGL::sMenuContainer = gMenuHolder;
-
-}
-
-void LLViewerWindow::initWorldUI()
-{
-	S32 height = mRootView->getRect().getHeight();
-	S32 width = mRootView->getRect().getWidth();
-	LLRect full_window(0, height, width, 0);
-
-
-	gIMMgr = LLIMMgr::getInstance();
-
-	//getRootView()->sendChildToFront(gFloaterView);
-	//getRootView()->sendChildToFront(gSnapshotFloaterView);
-
-	// new bottom panel
-	LLPanel* bottom_tray_container = getRootView()->getChild<LLPanel>("bottom_tray_container");
-	LLBottomTray* bottom_tray = LLBottomTray::getInstance();
-	bottom_tray->setShape(bottom_tray_container->getLocalRect());
-	bottom_tray->setFollowsAll();
-	bottom_tray_container->addChild(bottom_tray);
-	bottom_tray_container->setVisible(TRUE);
-
-	LLRect morph_view_rect = full_window;
-	morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
-	morph_view_rect.mTop = full_window.mTop - 32;
-	LLMorphView::Params mvp;
-	mvp.name("MorphView");
-	mvp.rect(morph_view_rect);
-	mvp.visible(false);
-	gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp);
-	getRootView()->addChild(gMorphView);
-
-	LLWorldMapView::initClass();
-	
-	// Force gFloaterWorldMap to initialize
-	LLFloaterReg::getInstance("world_map");
-
-	// Force gFloaterTools to initialize
-	LLFloaterReg::getInstance("build");
-	LLFloaterReg::hideInstance("build");
-
-	// Status bar
-	LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container");
-	gStatusBar = new LLStatusBar(status_bar_container->getLocalRect());
-	gStatusBar->setFollowsAll();
-	gStatusBar->setShape(status_bar_container->getLocalRect());
-	// sync bg color with menu bar
-	gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
-	status_bar_container->addChild(gStatusBar);
-	status_bar_container->setVisible(TRUE);
-
-	// Navigation bar
-	LLPanel* nav_bar_container = getRootView()->getChild<LLPanel>("nav_bar_container");
-
-	LLNavigationBar* navbar = LLNavigationBar::getInstance();
-	navbar->setShape(nav_bar_container->getLocalRect());
-	navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
-	nav_bar_container->addChild(navbar);
-	nav_bar_container->setVisible(TRUE);
-	
-	if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
-	{
-		navbar->showNavigationPanel(FALSE);
-	}
-
-	if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"))
-	{
-		navbar->showFavoritesPanel(FALSE);
-	}
-
-	// Top Info bar
-	LLPanel* topinfo_bar_container = getRootView()->getChild<LLPanel>("topinfo_bar_container");
-	LLPanelTopInfoBar* topinfo_bar = LLPanelTopInfoBar::getInstance();
-
-	topinfo_bar->setShape(topinfo_bar_container->getLocalRect());
-
-	topinfo_bar_container->addChild(topinfo_bar);
-	topinfo_bar_container->setVisible(TRUE);
-
-	if (!gSavedSettings.getBOOL("ShowMiniLocationPanel"))
-	{
-		topinfo_bar->setVisible(FALSE);
-	}
-
-	if ( gHUDView == NULL )
-	{
-		LLRect hud_rect = full_window;
-		hud_rect.mBottom += 50;
-		if (gMenuBarView && gMenuBarView->isInVisibleChain())
-		{
-			hud_rect.mTop -= gMenuBarView->getRect().getHeight();
-		}
-		gHUDView = new LLHUDView(hud_rect);
-		// put behind everything else in the UI
-		getRootView()->addChildInBack(gHUDView);
-	}
-
-	LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("stand_stop_flying_container");
-	LLPanelStandStopFlying* panel_stand_stop_flying	= LLPanelStandStopFlying::getInstance();
-	panel_ssf_container->addChild(panel_stand_stop_flying);
-	panel_ssf_container->setVisible(TRUE);
-
-	// put sidetray in container
-	LLPanel* side_tray_container = getRootView()->getChild<LLPanel>("side_tray_container");
-	LLSideTray* sidetrayp = LLSideTray::getInstance();
-	sidetrayp->setShape(side_tray_container->getLocalRect());
-	// don't follow right edge to avoid spurious resizes, since we are using a fixed width layout
-	sidetrayp->setFollows(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_BOTTOM);
-	side_tray_container->addChild(sidetrayp);
-	side_tray_container->setVisible(FALSE);
-	
-	// put sidetray buttons in their own panel
-	LLPanel* buttons_panel = sidetrayp->getButtonsPanel();
-	LLPanel* buttons_panel_container = getRootView()->getChild<LLPanel>("side_bar_tabs");
-	buttons_panel->setShape(buttons_panel_container->getLocalRect());
-	buttons_panel->setFollowsAll();
-	buttons_panel_container->addChild(buttons_panel);
-
-	LLView* avatar_picker_destination_guide_container = gViewerWindow->getRootView()->getChild<LLView>("avatar_picker_and_destination_guide_container");
-	avatar_picker_destination_guide_container->getChild<LLButton>("close")->setCommitCallback(boost::bind(toggle_destination_and_avatar_picker, LLSD()));
-	LLMediaCtrl* destinations = avatar_picker_destination_guide_container->findChild<LLMediaCtrl>("destination_guide_contents");
-	LLMediaCtrl* avatar_picker = avatar_picker_destination_guide_container->findChild<LLMediaCtrl>("avatar_picker_contents");
-	if (destinations)
-	{
-		destinations->navigateTo(gSavedSettings.getString("DestinationGuideURL"), "text/html");
-	}
-
-	if (avatar_picker)
-	{
-		avatar_picker->navigateTo(gSavedSettings.getString("AvatarPickerURL"), "text/html");
-	}
-
-}
-
-// Destroy the UI
-void LLViewerWindow::shutdownViews()
-{
-	// clean up warning logger
-	LLError::removeRecorder(RecordToChatConsole::getInstance());
-
-	delete mDebugText;
-	mDebugText = NULL;
-	
-	// Cleanup global views
-	if (gMorphView)
-	{
-		gMorphView->setVisible(FALSE);
-	}
-
-	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
-	// will crump with LL_ERRS.
-	LLModalDialog::shutdownModals();
-	
-	// destroy the nav bar, not currently part of gViewerWindow
-	// *TODO: Make LLNavigationBar part of gViewerWindow
-	delete LLNavigationBar::getInstance();
-
-	// destroy menus after instantiating navbar above, as it needs
-	// access to gMenuHolder
-	cleanup_menus();
-
-	// Delete all child views.
-	delete mRootView;
-	mRootView = NULL;
-
-	// Automatically deleted as children of mRootView.  Fix the globals.
-	gStatusBar = NULL;
-	gIMMgr = NULL;
-	gToolTipView = NULL;
-
-	gFloaterView = NULL;
-	gMorphView = NULL;
-
-	gHUDView = NULL;
-}
-
-void LLViewerWindow::shutdownGL()
-{
-	//--------------------------------------------------------
-	// Shutdown GL cleanly.  Order is very important here.
-	//--------------------------------------------------------
-	LLFontGL::destroyDefaultFonts();
-	LLFontManager::cleanupClass();
-	stop_glerror();
-
-	gSky.cleanup();
-	stop_glerror();
-
-	LLWearableList::instance().cleanup() ;
-
-	gTextureList.shutdown();
-	stop_glerror();
-
-	gBumpImageList.shutdown();
-	stop_glerror();
-
-	LLWorldMapView::cleanupTextures();
-
-	llinfos << "Cleaning up pipeline" << llendl;
-	gPipeline.cleanup();
-	stop_glerror();
-
-	LLViewerTextureManager::cleanup() ;
-	LLImageGL::cleanupClass() ;
-
-	llinfos << "All textures and llimagegl images are destroyed!" << llendl ;
-
-	llinfos << "Cleaning up select manager" << llendl;
-	LLSelectMgr::getInstance()->cleanup();
-
-	LLVertexBuffer::cleanupClass();
-
-	llinfos << "Stopping GL during shutdown" << llendl;
-	if (!gNoRender)
-	{
-		stopGL(FALSE);
-		stop_glerror();
-	}
-
-	gGL.shutdown();
-}
-
-// shutdownViews() and shutdownGL() need to be called first
-LLViewerWindow::~LLViewerWindow()
-{
-	llinfos << "Destroying Window" << llendl;
-	destroyWindow();
-
-	delete mDebugText;
-	mDebugText = NULL;
-}
-
-
-void LLViewerWindow::setCursor( ECursorType c )
-{
-	mWindow->setCursor( c );
-}
-
-void LLViewerWindow::showCursor()
-{
-	mWindow->showCursor();
-	
-	mCursorHidden = FALSE;
-}
-
-void LLViewerWindow::hideCursor()
-{
-	// And hide the cursor
-	mWindow->hideCursor();
-
-	mCursorHidden = TRUE;
-}
-
-void LLViewerWindow::sendShapeToSim()
-{
-	LLMessageSystem* msg = gMessageSystem;
-	if(!msg) return;
-	msg->newMessageFast(_PREHASH_AgentHeightWidth);
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode);
-	msg->nextBlockFast(_PREHASH_HeightWidthBlock);
-	msg->addU32Fast(_PREHASH_GenCounter, 0);
-	U16 height16 = (U16) mWorldViewRectRaw.getHeight();
-	U16 width16 = (U16) mWorldViewRectRaw.getWidth();
-	msg->addU16Fast(_PREHASH_Height, height16);
-	msg->addU16Fast(_PREHASH_Width, width16);
-	gAgent.sendReliableMessage();
-}
-
-// Must be called after window is created to set up agent
-// camera variables and UI variables.
-void LLViewerWindow::reshape(S32 width, S32 height)
-{
-	// Destroying the window at quit time generates spurious
-	// reshape messages.  We don't care about these, and we
-	// don't want to send messages because the message system
-	// may have been destructed.
-	if (!LLApp::isExiting())
-	{
-		if (gNoRender)
-		{
-			return;
-		}
-
-		gWindowResized = TRUE;
-
-		// update our window rectangle
-		mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width;
-		mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height;
-
-		//glViewport(0, 0, width, height );
-
-		if (height > 0)
-		{ 
-			LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
-			LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
-		}
-
-		calcDisplayScale();
-	
-		BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
-		LLUI::setScaleFactor(mDisplayScale);
-
-		// update our window rectangle
-		mWindowRectScaled.mRight = mWindowRectScaled.mLeft + llround((F32)width / mDisplayScale.mV[VX]);
-		mWindowRectScaled.mTop = mWindowRectScaled.mBottom + llround((F32)height / mDisplayScale.mV[VY]);
-
-		setup2DViewport();
-
-		// Inform lower views of the change
-		// round up when converting coordinates to make sure there are no gaps at edge of window
-		LLView::sForceReshape = display_scale_changed;
-		mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY]));
-		LLView::sForceReshape = FALSE;
-
-		// clear font width caches
-		if (display_scale_changed)
-		{
-			LLHUDObject::reshapeAll();
-		}
-
-		sendShapeToSim();
-
-		// store new settings for the mode we are in, regardless
-		// Only save size if not maximized
-		BOOL maximized = mWindow->getMaximized();
-		gSavedSettings.setBOOL("WindowMaximized", maximized);
-
-		LLCoordScreen window_size;
-		if (!maximized
-			&& mWindow->getSize(&window_size))
-		{
-			gSavedSettings.setS32("WindowWidth", window_size.mX);
-			gSavedSettings.setS32("WindowHeight", window_size.mY);
-		}
-
-		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
-		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
-	}
-}
-
-
-// Hide normal UI when a logon fails
-void LLViewerWindow::setNormalControlsVisible( BOOL visible )
-{
-	if(LLBottomTray::instanceExists())
-	{
-		LLBottomTray::getInstance()->setVisible(visible);
-		LLBottomTray::getInstance()->setEnabled(visible);
-	}
-
-	if ( gMenuBarView )
-	{
-		gMenuBarView->setVisible( visible );
-		gMenuBarView->setEnabled( visible );
-
-		// ...and set the menu color appropriately.
-		setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, 
-			LLGridManager::getInstance()->isInProductionGrid());
-	}
-        
-	if ( gStatusBar )
-	{
-		gStatusBar->setVisible( visible );	
-		gStatusBar->setEnabled( visible );	
-	}
-	
-	LLNavigationBar* navbarp = LLUI::getRootView()->findChild<LLNavigationBar>("navigation_bar");
-	if (navbarp)
-	{
-		navbarp->setVisible( visible );
-	}
-}
-
-void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
-{
-    LLSD args;
-    LLColor4 new_bg_color;
-
-	// no l10n problem because channel is always an english string
-	std::string channel = LLVersionInfo::getChannel();
-	bool isProject = (channel.find("Project") != std::string::npos);
-	
-	// god more important than project, proj more important than grid
-    if(god_mode && LLGridManager::getInstance()->isInProductionGrid())
-    {
-        new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" );
-    }
-    else if(god_mode && !LLGridManager::getInstance()->isInProductionGrid())
-    {
-        new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" );
-    }
-	else if (!god_mode && isProject)
-	{
-		new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" );
-    }
-    else if(!god_mode && !LLGridManager::getInstance()->isInProductionGrid())
-    {
-        new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
-    }
-    else 
-    {
-        new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
-    }
-
-    if(gMenuBarView)
-    {
-        gMenuBarView->setBackgroundColor( new_bg_color );
-    }
-
-    if(gStatusBar)
-    {
-        gStatusBar->setBackgroundColor( new_bg_color );
-    }
-}
-
-void LLViewerWindow::drawDebugText()
-{
-	gGL.color4f(1,1,1,1);
-	gGL.pushMatrix();
-	gGL.pushUIMatrix();
-	{
-		// scale view by UI global scale factor and aspect ratio correction factor
-		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
-		mDebugText->draw();
-	}
-	gGL.popUIMatrix();
-	gGL.popMatrix();
-
-	gGL.flush();
-}
-
-void LLViewerWindow::draw()
-{
-	
-//#if LL_DEBUG
-	LLView::sIsDrawing = TRUE;
-//#endif
-	stop_glerror();
-	
-	LLUI::setLineWidth(1.f);
-
-	LLUI::setLineWidth(1.f);
-	// Reset any left-over transforms
-	glMatrixMode(GL_MODELVIEW);
-	
-	glLoadIdentity();
-
-	//S32 screen_x, screen_y;
-
-	if (!gSavedSettings.getBOOL("RenderUIBuffer"))
-	{
-		LLUI::sDirtyRect = getWindowRectScaled();
-	}
-
-	// HACK for timecode debugging
-	if (gSavedSettings.getBOOL("DisplayTimecode"))
-	{
-		// draw timecode block
-		std::string text;
-
-		glLoadIdentity();
-
-		microsecondsToTimecodeString(gFrameTime,text);
-		const LLFontGL* font = LLFontGL::getFontSansSerif();
-		font->renderUTF8(text, 0,
-						llround((getWindowWidthScaled()/2)-100.f),
-						llround((getWindowHeightScaled()-60.f)),
-			LLColor4( 1.f, 1.f, 1.f, 1.f ),
-			LLFontGL::LEFT, LLFontGL::TOP);
-	}
-
-	// Draw all nested UI views.
-	// No translation needed, this view is glued to 0,0
-
-	gGL.pushMatrix();
-	LLUI::pushMatrix();
-	{
-		
-		// scale view by UI global scale factor and aspect ratio correction factor
-		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
-
-		LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
-		// apply camera zoom transform (for high res screenshots)
-		F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
-		S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
-		if (zoom_factor > 1.f)
-		{
-			//decompose subregion number to x and y values
-			int pos_y = sub_region / llceil(zoom_factor);
-			int pos_x = sub_region - (pos_y*llceil(zoom_factor));
-			// offset for this tile
-			glTranslatef((F32)getWindowWidthScaled() * -(F32)pos_x, 
-						(F32)getWindowHeightScaled() * -(F32)pos_y, 
-						0.f);
-			glScalef(zoom_factor, zoom_factor, 1.f);
-			LLUI::sGLScaleFactor *= zoom_factor;
-		}
-
-		// Draw tool specific overlay on world
-		LLToolMgr::getInstance()->getCurrentTool()->draw();
-
-		if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() )
-		{
-			drawMouselookInstructions();
-			stop_glerror();
-		}
-
-		// Draw all nested UI views.
-		// No translation needed, this view is glued to 0,0
-		mRootView->draw();
-
-		if (LLView::sDebugRects)
-		{
-			gToolTipView->drawStickyRect();
-		}
-
-		// Draw optional on-top-of-everyone view
-		LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-		if (top_ctrl && top_ctrl->getVisible())
-		{
-			S32 screen_x, screen_y;
-			top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y);
-
-			glMatrixMode(GL_MODELVIEW);
-			LLUI::pushMatrix();
-			LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f);
-			top_ctrl->draw();	
-			LLUI::popMatrix();
-		}
-
-
-		if( gShowOverlayTitle && !mOverlayTitle.empty() )
-		{
-			// Used for special titles such as "Second Life - Special E3 2003 Beta"
-			const S32 DIST_FROM_TOP = 20;
-			LLFontGL::getFontSansSerifBig()->renderUTF8(
-				mOverlayTitle, 0,
-				llround( getWindowWidthScaled() * 0.5f),
-				getWindowHeightScaled() - DIST_FROM_TOP,
-				LLColor4(1, 1, 1, 0.4f),
-				LLFontGL::HCENTER, LLFontGL::TOP);
-		}
-
-		LLUI::sGLScaleFactor = old_scale_factor;
-	}
-	LLUI::popMatrix();
-	gGL.popMatrix();
-
-//#if LL_DEBUG
-	LLView::sIsDrawing = FALSE;
-//#endif
-}
-
-// Takes a single keydown event, usually when UI is visible
-BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
-{
-	// hide tooltips on keypress
-	LLToolTipMgr::instance().blockToolTips();
-
-	if (gFocusMgr.getKeyboardFocus() 
-		&& !(mask & (MASK_CONTROL | MASK_ALT))
-		&& !gFocusMgr.getKeystrokesOnly())
-	{
-		// We have keyboard focus, and it's not an accelerator
-		if (key < 0x80)
-		{
-			// Not a special key, so likely (we hope) to generate a character.  Let it fall through to character handler first.
-			return (gFocusMgr.getKeyboardFocus() != NULL);
-		}
-	}
-
-	// let menus handle navigation keys for navigation
-	if ((gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE))
-		||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE))
-		||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE)))
-	{
-		return TRUE;
-	}
-
-	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
-
-	// give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus 
-	// as long as focus isn't locked
-	if (mask & (MASK_CONTROL | MASK_ALT) && !gFocusMgr.focusLocked())
-	{
-		// Check the current floater's menu first, if it has one.
-		if (gFocusMgr.keyboardFocusHasAccelerators()
-			&& keyboard_focus 
-			&& keyboard_focus->handleKey(key,mask,FALSE))
-		{
-			return TRUE;
-		}
-
-		if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
-			||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))
-		{
-			return TRUE;
-		}
-	}
-
-	// give floaters first chance to handle TAB key
-	// so frontmost floater gets focus
-	// if nothing has focus, go to first or last UI element as appropriate
-	if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL))
-	{
-		if (gMenuHolder) gMenuHolder->hideMenus();
-
-		// if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode
-		gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0);
-
-		// do CTRL-TAB and CTRL-SHIFT-TAB logic
-		if (mask & MASK_SHIFT)
-		{
-			mRootView->focusPrevRoot();
-		}
-		else
-		{
-			mRootView->focusNextRoot();
-		}
-		return TRUE;
-	}
-	// hidden edit menu for cut/copy/paste
-	if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask))
-	{
-		return TRUE;
-	}
-
-	// Traverses up the hierarchy
-	if( keyboard_focus )
-	{
-		LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL;
-		// arrow keys move avatar while chatting hack
-		if (chat_editor && chat_editor->hasFocus())
-		{
-			// If text field is empty, there's no point in trying to move
-			// cursor with arrow keys, so allow movement
-			if (chat_editor->getText().empty() 
-				|| gSavedSettings.getBOOL("ArrowKeysAlwaysMove"))
-			{
-				// let Control-Up and Control-Down through for chat line history,
-				if (!(key == KEY_UP && mask == MASK_CONTROL)
-					&& !(key == KEY_DOWN && mask == MASK_CONTROL))
-				{
-					switch(key)
-					{
-					case KEY_LEFT:
-					case KEY_RIGHT:
-					case KEY_UP:
-					case KEY_DOWN:
-					case KEY_PAGE_UP:
-					case KEY_PAGE_DOWN:
-					case KEY_HOME:
-						// when chatbar is empty or ArrowKeysAlwaysMove set,
-						// pass arrow keys on to avatar...
-						return FALSE;
-					default:
-						break;
-					}
-				}
-			}
-		}
-
-		if (keyboard_focus->handleKey(key, mask, FALSE))
-		{
-			return TRUE;
-		}
-	}
-
-	if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) )
-	{
-		return TRUE;
-	}
-
-	// Try for a new-format gesture
-	if (LLGestureMgr::instance().triggerGesture(key, mask))
-	{
-		return TRUE;
-	}
-
-	// See if this is a gesture trigger.  If so, eat the key and
-	// don't pass it down to the menus.
-	if (gGestureList.trigger(key, mask))
-	{
-		return TRUE;
-	}
-
-	// If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, 
-	// no view has keyboard focus, this is a printable character key (and no modifier key is 
-	// pressed except shift), then give focus to nearby chat (STORM-560)
-	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && 
-		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
-	{
-		LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL;
-		if (chat_editor)
-		{
-			// passing NULL here, character will be added later when it is handled by character handler.
-			LLBottomTray::getInstance()->getNearbyChatBar()->startChat(NULL);
-			return TRUE;
-		}
-	}
-
-	// give menus a chance to handle unmodified accelerator keys
-	if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
-		||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))
-	{
-		return TRUE;
-	}
-
-	// don't pass keys on to world when something in ui has focus
-	return gFocusMgr.childHasKeyboardFocus(mRootView) 
-		|| LLMenuGL::getKeyboardMode() 
-		|| (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive());
-}
-
-
-BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
-{
-	// HACK:  We delay processing of return keys until they arrive as a Unicode char,
-	// so that if you're typing chat text at low frame rate, we don't send the chat
-	// until all keystrokes have been entered. JC
-	// HACK: Numeric keypad <enter> on Mac is Unicode 3
-	// HACK: Control-M on Windows is Unicode 13
-	if ((uni_char == 13 && mask != MASK_CONTROL)
-		|| (uni_char == 3 && mask == MASK_NONE))
-	{
-		return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
-	}
-
-	// let menus handle navigation (jump) keys
-	if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, TRUE))
-	{
-		return TRUE;
-	}
-
-	// Traverses up the hierarchy
-	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
-	if( keyboard_focus )
-	{
-		if (keyboard_focus->handleUnicodeChar(uni_char, FALSE))
-		{
-			return TRUE;
-		}
-
-		//// Topmost view gets a chance before the hierarchy
-		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-		//if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) )
-		//{
-		//	return TRUE;
-		//}
-
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-
-void LLViewerWindow::handleScrollWheel(S32 clicks)
-{
-	LLView::sMouseHandlerMessage.clear();
-
-	LLUI::resetMouseIdleTimer();
-	
-	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
-	if( mouse_captor )
-	{
-		S32 local_x;
-		S32 local_y;
-		mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
-		mouse_captor->handleScrollWheel(local_x, local_y, clicks);
-		if (LLView::sDebugMouseHandling)
-		{
-			llinfos << "Scroll Wheel handled by captor " << mouse_captor->getName() << llendl;
-		}
-		return;
-	}
-
-	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-	if (top_ctrl)
-	{
-		S32 local_x;
-		S32 local_y;
-		top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
-		if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return;
-	}
-
-	if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) )
-	{
-		if (LLView::sDebugMouseHandling)
-		{
-			llinfos << "Scroll Wheel" << LLView::sMouseHandlerMessage << llendl;
-		}
-		return;
-	}
-	else if (LLView::sDebugMouseHandling)
-	{
-		llinfos << "Scroll Wheel not handled by view" << llendl;
-	}
-
-	// Zoom the camera in and out behavior
-
-	if(top_ctrl == 0 
-		&& getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) 
-		&& gAgentCamera.isInitialized())
-		gAgentCamera.handleScrollWheel(clicks);
-
-	return;
-}
-
-void LLViewerWindow::addPopup(LLView* popup)
-{
-	if (mPopupView)
-	{
-		mPopupView->addPopup(popup);
-	}
-}
-
-void LLViewerWindow::removePopup(LLView* popup)
-{
-	if (mPopupView)
-	{
-		mPopupView->removePopup(popup);
-	}
-}
-
-void LLViewerWindow::clearPopups()
-{
-	if (mPopupView)
-	{
-		mPopupView->clearPopups();
-	}
-}
-
-void LLViewerWindow::moveCursorToCenter()
-{
-	if (! gSavedSettings.getBOOL("DisableMouseWarp"))
-	{
-		S32 x = getWorldViewWidthScaled() / 2;
-		S32 y = getWorldViewHeightScaled() / 2;
-	
-		//on a forced move, all deltas get zeroed out to prevent jumping
-		mCurrentMousePoint.set(x,y);
-		mLastMousePoint.set(x,y);
-		mCurrentMouseDelta.set(0,0);	
-
-		LLUI::setMousePositionScreen(x, y);	
-	}
-}
-
-
-//////////////////////////////////////////////////////////////////////
-//
-// Hover handlers
-//
-
-void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
-{
-	if (viewp) 
-	{
-		if (!params.styled_message.empty())
-		{
-			params.styled_message.add().text("\n---------\n"); 
-		}
-		LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView();
-		// NOTE: we skip "root" since it is assumed
-		for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView();
-			tooltip_it != end_tooltip_it;
-			++tooltip_it)
-		{
-			LLView* viewp = *tooltip_it;
-		
-			params.styled_message.add().text(viewp->getName());
-
-			LLPanel* panelp = dynamic_cast<LLPanel*>(viewp);
-			if (panelp && !panelp->getXMLFilename().empty())
-			{
-				params.styled_message.add()
-					.text("(" + panelp->getXMLFilename() + ")")
-					.style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f));
-			}
-			params.styled_message.add().text("/");
-		}
-	}
-}
-
-// Update UI based on stored mouse position from mouse-move
-// event processing.
-void LLViewerWindow::updateUI()
-{
-	static LLFastTimer::DeclareTimer ftm("Update UI");
-	LLFastTimer t(ftm);
-
-	static std::string last_handle_msg;
-
-	if (gLoggedInTime.getStarted())
-	{
-		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout"))
-		{
-			LLFirstUse::notUsingDestinationGuide();
-		}
-		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout"))
-		{
-			LLFirstUse::notUsingSidePanel();
-		}
-	}
-
-	LLConsole::updateClass();
-
-	// animate layout stacks so we have up to date rect for world view
-	LLLayoutStack::updateClass();
-
-	// use full window for world view when not rendering UI
-	bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
-	updateWorldViewRect(world_view_uses_full_window);
-
-	LLView::sMouseHandlerMessage.clear();
-
-	S32 x = mCurrentMousePoint.mX;
-	S32 y = mCurrentMousePoint.mY;
-	MASK mask = gKeyboard->currentMask(TRUE);
-
-	if (gNoRender)
-	{
-		return;
-	}
-
-	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
-	{
-		gDebugRaycastFaceHit = -1;
-		gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
-											  &gDebugRaycastFaceHit,
-											  &gDebugRaycastIntersection,
-											  &gDebugRaycastTexCoord,
-											  &gDebugRaycastNormal,
-											  &gDebugRaycastBinormal);
-	}
-
-	updateMouseDelta();
-	updateKeyboardFocus();
-
-	BOOL handled = FALSE;
-
-	BOOL handled_by_top_ctrl = FALSE;
-	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
-	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
-	LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
-
-	//FIXME: only include captor and captor's ancestors if mouse is truly over them --RN
-
-	//build set of views containing mouse cursor by traversing UI hierarchy and testing 
-	//screen rect against mouse cursor
-	view_handle_set_t mouse_hover_set;
-
-	// constraint mouse enter events to children of mouse captor
-	LLView* root_view = captor_view;
-
-	// if mouse captor doesn't exist or isn't a LLView
-	// then allow mouse enter events on entire UI hierarchy
-	if (!root_view)
-	{
-		root_view = mRootView;
-	}
-
-	// only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI
-	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{
-		// include all ancestors of captor_view as automatically having mouse
-		if (captor_view)
-		{
-			LLView* captor_parent_view = captor_view->getParent();
-			while(captor_parent_view)
-			{
-				mouse_hover_set.insert(captor_parent_view->getHandle());
-				captor_parent_view = captor_parent_view->getParent();
-			}
-		}
-
-		// aggregate visible views that contain mouse cursor in display order
-		LLPopupView::popup_list_t popups = mPopupView->getCurrentPopups();
-
-		for(LLPopupView::popup_list_t::iterator popup_it = popups.begin(); popup_it != popups.end(); ++popup_it)
-		{
-			LLView* popup = popup_it->get();
-			if (popup && popup->calcScreenBoundingRect().pointInRect(x, y))
-			{
-				// iterator over contents of top_ctrl, and throw into mouse_hover_set
-				for (LLView::tree_iterator_t it = popup->beginTreeDFS();
-					it != popup->endTreeDFS();
-					++it)
-				{
-					LLView* viewp = *it;
-					if (viewp->getVisible()
-						&& viewp->calcScreenBoundingRect().pointInRect(x, y))
-					{
-						// we have a view that contains the mouse, add it to the set
-						mouse_hover_set.insert(viewp->getHandle());
-					}
-					else
-					{
-						// skip this view and all of its children
-						it.skipDescendants();
-					}
-				}
-			}
-		}
-
-		// while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events
-		if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y))
-		{
-			// iterator over contents of top_ctrl, and throw into mouse_hover_set
-			for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS();
-				it != top_ctrl->endTreeDFS();
-				++it)
-			{
-				LLView* viewp = *it;
-				if (viewp->getVisible()
-					&& viewp->calcScreenBoundingRect().pointInRect(x, y))
-				{
-					// we have a view that contains the mouse, add it to the set
-					mouse_hover_set.insert(viewp->getHandle());
-				}
-				else
-				{
-					// skip this view and all of its children
-					it.skipDescendants();
-				}
-			}
-		}
-		else
-		{
-			// walk UI tree in depth-first order
-			for (LLView::tree_iterator_t it = root_view->beginTreeDFS();
-				it != root_view->endTreeDFS();
-				++it)
-			{
-				LLView* viewp = *it;
-				// calculating the screen rect involves traversing the parent, so this is less than optimal
-				if (viewp->getVisible()
-					&& viewp->calcScreenBoundingRect().pointInRect(x, y))
-				{
-
-					// if this view is mouse opaque, nothing behind it should be in mouse_hover_set
-					if (viewp->getMouseOpaque())
-					{
-						// constrain further iteration to children of this widget
-						it = viewp->beginTreeDFS();
-					}
-		
-					// we have a view that contains the mouse, add it to the set
-					mouse_hover_set.insert(viewp->getHandle());
-				}
-				else
-				{
-					// skip this view and all of its children
-					it.skipDescendants();
-				}
-			}
-		}
-	}
-
-	typedef std::vector<LLHandle<LLView> > view_handle_list_t;
-
-	// call onMouseEnter() on all views which contain the mouse cursor but did not before
-	view_handle_list_t mouse_enter_views;
-	std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(),
-						mMouseHoverViews.begin(), mMouseHoverViews.end(),
-						std::back_inserter(mouse_enter_views));
-	for (view_handle_list_t::iterator it = mouse_enter_views.begin();
-		it != mouse_enter_views.end();
-		++it)
-	{
-		LLView* viewp = it->get();
-		if (viewp)
-		{
-			LLRect view_screen_rect = viewp->calcScreenRect();
-			viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
-		}
-	}
-
-	// call onMouseLeave() on all views which no longer contain the mouse cursor
-	view_handle_list_t mouse_leave_views;
-	std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(),
-						mouse_hover_set.begin(), mouse_hover_set.end(),
-						std::back_inserter(mouse_leave_views));
-	for (view_handle_list_t::iterator it = mouse_leave_views.begin();
-		it != mouse_leave_views.end();
-		++it)
-	{
-		LLView* viewp = it->get();
-		if (viewp)
-		{
-			LLRect view_screen_rect = viewp->calcScreenRect();
-			viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
-		}
-	}
-
-	// store resulting hover set for next frame
-	swap(mMouseHoverViews, mouse_hover_set);
-
-	// only handle hover events when UI is enabled
-	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{	
-
-		if( mouse_captor )
-		{
-			// Pass hover events to object capturing mouse events.
-			S32 local_x;
-			S32 local_y; 
-			mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
-			handled = mouse_captor->handleHover(local_x, local_y, mask);
-			if (LLView::sDebugMouseHandling)
-			{
-				llinfos << "Hover handled by captor " << mouse_captor->getName() << llendl;
-			}
-
-			if( !handled )
-			{
-				lldebugst(LLERR_USER_INPUT) << "hover not handled by mouse captor" << llendl;
-			}
-		}
-		else
-		{
-			if (top_ctrl)
-			{
-				S32 local_x, local_y;
-				top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
-				handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
-				handled_by_top_ctrl = TRUE;
-			}
-
-			if ( !handled )
-			{
-				// x and y are from last time mouse was in window
-				// mMouseInWindow tracks *actual* mouse location
-				if (mMouseInWindow && mRootView->handleHover(x, y, mask) )
-				{
-					if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg)
-					{
-						last_handle_msg = LLView::sMouseHandlerMessage;
-						llinfos << "Hover" << LLView::sMouseHandlerMessage << llendl;
-					}
-					handled = TRUE;
-				}
-				else if (LLView::sDebugMouseHandling)
-				{
-					if (last_handle_msg != LLStringUtil::null)
-					{
-						last_handle_msg.clear();
-						llinfos << "Hover not handled by view" << llendl;
-					}
-				}
-			}
-		
-			if (!handled)
-			{
-				LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
-
-				if(mMouseInWindow && tool)
-				{
-					handled = tool->handleHover(x, y, mask);
-				}
-			}
-		}
-
-		// Show a new tool tip (or update one that is already shown)
-		BOOL tool_tip_handled = FALSE;
-		std::string tool_tip_msg;
-		if( handled 
-			&& !mWindow->isCursorHidden())
-		{
-			LLRect screen_sticky_rect = mRootView->getLocalRect();
-			S32 local_x, local_y;
-
-			if (gSavedSettings.getBOOL("DebugShowXUINames"))
-			{
-				LLToolTip::Params params;
-
-				LLView* tooltip_view = mRootView;
-				LLView::tree_iterator_t end_it = mRootView->endTreeDFS();
-				for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it)
-				{
-					LLView* viewp = *it;
-					LLRect screen_rect;
-					viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
-					if (!(viewp->getVisible()
-						 && screen_rect.pointInRect(x, y)))
-					{
-						it.skipDescendants();
-					}
-					// only report xui names for LLUICtrls, 
-					// and blacklist the various containers we don't care about
-					else if (dynamic_cast<LLUICtrl*>(viewp) 
-							&& viewp != gMenuHolder
-							&& viewp != gFloaterView
-							&& viewp != gConsole) 
-					{
-						if (dynamic_cast<LLFloater*>(viewp))
-						{
-							// constrain search to descendants of this (frontmost) floater
-							// by resetting iterator
-							it = viewp->beginTreeDFS();
-						}
-
-						// if we are in a new part of the tree (not a descendent of current tooltip_view)
-						// then push the results for tooltip_view and start with a new potential view
-						// NOTE: this emulates visiting only the leaf nodes that meet our criteria
-						if (!viewp->hasAncestor(tooltip_view))
-						{
-							append_xui_tooltip(tooltip_view, params);
-							screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
-						}
-						tooltip_view = viewp;
-					}
-				}
-
-				append_xui_tooltip(tooltip_view, params);
-				screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
-				
-				params.sticky_rect = screen_sticky_rect;
-				params.max_width = 400;
-
-				LLToolTipMgr::instance().show(params);
-			}
-			// if there is a mouse captor, nothing else gets a tooltip
-			else if (mouse_captor)
-			{
-				mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
-				tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask);
-			}
-			else 
-			{
-				// next is top_ctrl
-				if (!tool_tip_handled && top_ctrl)
-				{
-					top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
-					tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask );
-				}
-				
-				if (!tool_tip_handled)
-				{
-					local_x = x; local_y = y;
-					tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask );
-				}
-
-				LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
-				if (!tool_tip_handled && current_tool)
-				{
-					current_tool->screenPointToLocal(x, y, &local_x, &local_y);
-					tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask );
-				}
-			}
-		}		
-	}
-	else
-	{	// just have tools handle hover when UI is turned off
-		LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
-
-		if(mMouseInWindow && tool)
-		{
-			handled = tool->handleHover(x, y, mask);
-		}
-	}
-
-	updateLayout();
-
-	mLastMousePoint = mCurrentMousePoint;
-
-	// cleanup unused selections when no modal dialogs are open
-	if (LLModalDialog::activeCount() == 0)
-	{
-		LLViewerParcelMgr::getInstance()->deselectUnused();
-	}
-
-	if (LLModalDialog::activeCount() == 0)
-	{
-		LLSelectMgr::getInstance()->deselectUnused();
-	}
-}
-
-
-void LLViewerWindow::updateLayout()
-{
-	LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
-	if (gFloaterTools != NULL
-		&& tool != NULL
-		&& tool != gToolNull  
-		&& tool != LLToolCompInspect::getInstance() 
-		&& tool != LLToolDragAndDrop::getInstance() 
-		&& !gSavedSettings.getBOOL("FreezeTime"))
-	{ 
-		// Suppress the toolbox view if our source tool was the pie tool,
-		// and we've overridden to something else.
-		bool suppress_toolbox = 
-			(LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
-			(LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
-
-		LLMouseHandler *captor = gFocusMgr.getMouseCapture();
-		// With the null, inspect, or drag and drop tool, don't muck
-		// with visibility.
-
-		if (gFloaterTools->isMinimized()
-			||	(tool != LLToolPie::getInstance()						// not default tool
-				&& tool != LLToolCompGun::getInstance()					// not coming out of mouselook
-				&& !suppress_toolbox									// not override in third person
-				&& LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset	// not special mode
-				&& LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
-				&& (!captor || dynamic_cast<LLView*>(captor) != NULL)))						// not dragging
-		{
-			// Force floater tools to be visible (unless minimized)
-			if (!gFloaterTools->getVisible())
-			{
-				gFloaterTools->openFloater();
-			}
-			// Update the location of the blue box tool popup
-			LLCoordGL select_center_screen;
-			gFloaterTools->updatePopup( select_center_screen, gKeyboard->currentMask(TRUE) );
-		}
-		else
-		{
-			gFloaterTools->setVisible(FALSE);
-		}
-		//gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
-	}
-
-	// Always update console
-	if(gConsole)
-	{
-		LLRect console_rect = getChatConsoleRect();
-		gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
-		gConsole->setRect(console_rect);
-	}
-}
-
-void LLViewerWindow::updateMouseDelta()
-{
-	S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
-	S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
-
-	//RN: fix for asynchronous notification of mouse leaving window not working
-	LLCoordWindow mouse_pos;
-	mWindow->getCursorPosition(&mouse_pos);
-	if (mouse_pos.mX < 0 || 
-		mouse_pos.mY < 0 ||
-		mouse_pos.mX > mWindowRectRaw.getWidth() ||
-		mouse_pos.mY > mWindowRectRaw.getHeight())
-	{
-		mMouseInWindow = FALSE;
-	}
-	else
-	{
-		mMouseInWindow = TRUE;
-	}
-
-	LLVector2 mouse_vel; 
-
-	if (gSavedSettings.getBOOL("MouseSmooth"))
-	{
-		static F32 fdx = 0.f;
-		static F32 fdy = 0.f;
-
-		F32 amount = 16.f;
-		fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
-		fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
-
-		mCurrentMouseDelta.set(llround(fdx), llround(fdy));
-		mouse_vel.setVec(fdx,fdy);
-	}
-	else
-	{
-		mCurrentMouseDelta.set(dx, dy);
-		mouse_vel.setVec((F32) dx, (F32) dy);
-	}
-    
-	mMouseVelocityStat.addValue(mouse_vel.magVec());
-}
-
-void LLViewerWindow::updateKeyboardFocus()
-{
-	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{
-		gFocusMgr.setKeyboardFocus(NULL);
-	}
-
-	// clean up current focus
-	LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
-	if (cur_focus)
-	{
-		if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
-		{
-            // don't release focus, just reassign so that if being given
-            // to a sibling won't call onFocusLost on all the ancestors
-			// gFocusMgr.releaseFocusIfNeeded(cur_focus);
-
-			LLUICtrl* parent = cur_focus->getParentUICtrl();
-			const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
-			bool new_focus_found = false;
-			while(parent)
-			{
-				if (parent->isCtrl() 
-					&& (parent->hasTabStop() || parent == focus_root) 
-					&& !parent->getIsChrome() 
-					&& parent->isInVisibleChain() 
-					&& parent->isInEnabledChain())
-				{
-					if (!parent->focusFirstItem())
-					{
-						parent->setFocus(TRUE);
-					}
-					new_focus_found = true;
-					break;
-				}
-				parent = parent->getParentUICtrl();
-			}
-
-			// if we didn't find a better place to put focus, just release it
-			// hasFocus() will return true if and only if we didn't touch focus since we
-			// are only moving focus higher in the hierarchy
-			if (!new_focus_found)
-			{
-				cur_focus->setFocus(FALSE);
-			}
-		}
-		else if (cur_focus->isFocusRoot())
-		{
-			// focus roots keep trying to delegate focus to their first valid descendant
-			// this assumes that focus roots are not valid focus holders on their own
-			cur_focus->focusFirstItem();
-		}
-	}
-
-	// last ditch force of edit menu to selection manager
-	if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
-	{
-		LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance();
-	}
-
-	if (gFloaterView->getCycleMode())
-	{
-		// sync all floaters with their focus state
-		gFloaterView->highlightFocusedFloater();
-		gSnapshotFloaterView->highlightFocusedFloater();
-		if ((gKeyboard->currentMask(TRUE) & MASK_CONTROL) == 0)
-		{
-			// control key no longer held down, finish cycle mode
-			gFloaterView->setCycleMode(FALSE);
-
-			gFloaterView->syncFloaterTabOrder();
-		}
-		else
-		{
-			// user holding down CTRL, don't update tab order of floaters
-		}
-	}
-	else
-	{
-		// update focused floater
-		gFloaterView->highlightFocusedFloater();
-		gSnapshotFloaterView->highlightFocusedFloater();
-		// make sure floater visible order is in sync with tab order
-		gFloaterView->syncFloaterTabOrder();
-	}
-
-	if(LLSideTray::instanceCreated())//just getInstance will create sidetray. we don't want this
-		LLSideTray::getInstance()->highlightFocused();
-}
-
-static LLFastTimer::DeclareTimer FTM_UPDATE_WORLD_VIEW("Update World View");
-void LLViewerWindow::updateWorldViewRect(bool use_full_window)
-{
-	LLFastTimer ft(FTM_UPDATE_WORLD_VIEW);
-
-	// start off using whole window to render world
-	LLRect new_world_rect = mWindowRectRaw;
-
-	if (use_full_window == false && mWorldViewPlaceholder.get())
-	{
-		new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect();
-		// clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers
-		new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1);
-		new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1);
-
-		new_world_rect.mLeft = llround((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]);
-		new_world_rect.mRight = llround((F32)new_world_rect.mRight * mDisplayScale.mV[VX]);
-		new_world_rect.mBottom = llround((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]);
-		new_world_rect.mTop = llround((F32)new_world_rect.mTop * mDisplayScale.mV[VY]);
-	}
-
-	if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE)
-	{
-		// use right edge of window, ignoring sidebar
-		new_world_rect.mRight = mWindowRectRaw.mRight;
-	}
-
-	if (mWorldViewRectRaw != new_world_rect)
-	{
-		mWorldViewRectRaw = new_world_rect;
-		gResizeScreenTexture = TRUE;
-		LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
-		LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
-
-		LLRect old_world_rect_scaled = mWorldViewRectScaled;
-		mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
-
-		// sending a signal with a new WorldView rect
-		mOnWorldViewRectUpdated(old_world_rect_scaled, mWorldViewRectScaled);
-	}
-}
-
-void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
-{
-	// Store last mouse location.
-	// If mouse leaves window, pretend last point was on edge of window
-	if (point.mX < 0)
-	{
-		mCurrentMousePoint.mX = 0;
-	}
-	else if (point.mX > getWindowWidthScaled())
-	{
-		mCurrentMousePoint.mX = getWindowWidthScaled();
-	}
-	else
-	{
-		mCurrentMousePoint.mX = point.mX;
-	}
-
-	if (point.mY < 0)
-	{
-		mCurrentMousePoint.mY = 0;
-	}
-	else if (point.mY > getWindowHeightScaled() )
-	{
-		mCurrentMousePoint.mY = getWindowHeightScaled();
-	}
-	else
-	{
-		mCurrentMousePoint.mY = point.mY;
-	}
-}
-
-
-// Draws the selection outlines for the currently selected objects
-// Must be called after displayObjects is called, which sets the mGLName parameter
-// NOTE: This function gets called 3 times:
-//  render_ui_3d: 			FALSE, FALSE, TRUE
-//  render_hud_elements:	FALSE, FALSE, FALSE
-void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
-{
-	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
-
-	if (!for_hud && !for_gl_pick)
-	{
-		// Call this once and only once
-		LLSelectMgr::getInstance()->updateSilhouettes();
-	}
-	
-	// Draw fence around land selections
-	if (for_gl_pick)
-	{
-		if (pick_parcel_walls)
-		{
-			LLViewerParcelMgr::getInstance()->renderParcelCollision();
-		}
-	}
-	else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) ||
-			 (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD))
-	{		
-		LLSelectMgr::getInstance()->renderSilhouettes(for_hud);
-		
-		stop_glerror();
-
-		// setup HUD render
-		if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
-		{
-			LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
-
-			// set up transform to encompass bounding box of HUD
-			glMatrixMode(GL_PROJECTION);
-			glPushMatrix();
-			glLoadIdentity();
-			F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
-			glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
-			
-			glMatrixMode(GL_MODELVIEW);
-			glPushMatrix();
-			glLoadIdentity();
-			glLoadMatrixf(OGL_TO_CFR_ROTATION);		// Load Cory's favorite reference frame
-			glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
-		}
-
-		// Render light for editing
-		if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit())
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLGLEnable gls_blend(GL_BLEND);
-			LLGLEnable gls_cull(GL_CULL_FACE);
-			LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-			glMatrixMode(GL_MODELVIEW);
-			glPushMatrix();
-			if (selection->getSelectType() == SELECT_TYPE_HUD)
-			{
-				F32 zoom = gAgentCamera.mHUDCurZoom;
-				glScalef(zoom, zoom, zoom);
-			}
-
-			struct f : public LLSelectedObjectFunctor
-			{
-				virtual bool apply(LLViewerObject* object)
-				{
-					LLDrawable* drawable = object->mDrawable;
-					if (drawable && drawable->isLight())
-					{
-						LLVOVolume* vovolume = drawable->getVOVolume();
-						glPushMatrix();
-
-						LLVector3 center = drawable->getPositionAgent();
-						glTranslatef(center[0], center[1], center[2]);
-						F32 scale = vovolume->getLightRadius();
-						glScalef(scale, scale, scale);
-
-						LLColor4 color(vovolume->getLightColor(), .5f);
-						glColor4fv(color.mV);
-					
-						F32 pixel_area = 100000.f;
-						// Render Outside
-						gSphere.render(pixel_area);
-
-						// Render Inside
-						glCullFace(GL_FRONT);
-						gSphere.render(pixel_area);
-						glCullFace(GL_BACK);
-					
-						glPopMatrix();
-					}
-					return true;
-				}
-			} func;
-			LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
-			
-			glPopMatrix();
-		}				
-		
-		// NOTE: The average position for the axis arrows of the selected objects should
-		// 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 = LLToolMgr::getInstance()->getCurrentTool();
-		if (tool)
-		{
-			if(tool->isAlwaysRendered())
-			{
-				tool->render();
-			}
-			else
-			{
-				if( !LLSelectMgr::getInstance()->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("EditLinkedParts");
-
-					for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
-						 iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
-					{
-						LLSelectNode* nodep = *iter;
-						LLViewerObject* object = nodep->getObject();
-						BOOL this_object_movable = FALSE;
-						if (object->permMove() && (object->permModify() || selecting_linked_set))
-						{
-							moveable_object_selected = TRUE;
-							this_object_movable = TRUE;
-						}
-						all_selected_objects_move = all_selected_objects_move && this_object_movable;
-						all_selected_objects_modify = all_selected_objects_modify && object->permModify();
-					}
-
-					BOOL draw_handles = TRUE;
-
-					if (tool == LLToolCompTranslate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
-					{
-						draw_handles = FALSE;
-					}
-
-					if (tool == LLToolCompRotate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
-					{
-						draw_handles = FALSE;
-					}
-
-					if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() )
-					{
-						draw_handles = FALSE;
-					}
-				
-					if( draw_handles )
-					{
-						tool->render();
-					}
-				}
-			}
-			if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount())
-			{
-				glMatrixMode(GL_PROJECTION);
-				glPopMatrix();
-
-				glMatrixMode(GL_MODELVIEW);
-				glPopMatrix();
-				stop_glerror();
-			}
-		}
-	}
-}
-
-// Return a point near the clicked object representative of the place the object was clicked.
-LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot, LLViewerObject* clicked_object) const
-{
-	// create a normalized vector pointing from the camera center into the 
-	// world at the location of the mouse click
-	LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot );
-
-	LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgentCamera.getCameraPositionGlobal();
-
-	// make mouse vector as long as object vector, so it touchs a point near
-	// where the user clicked on the object
-	mouse_direction_global *= (F32) relative_object.magVec();
-
-	LLVector3d new_pos;
-	new_pos.setVec(mouse_direction_global);
-	// transform mouse vector back to world coords
-	new_pos += gAgentCamera.getCameraPositionGlobal();
-
-	return new_pos;
-}
-
-
-BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const
-{
-	BOOL intersect = FALSE;
-
-//	U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK;
-	if (!intersect)
-	{
-		point_global = clickPointInWorldGlobal(x, y, objectp);
-		llinfos << "approx intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
-	}
-	else
-	{
-		llinfos << "good intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
-	}
-
-	return intersect;
-}
-
-void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent)
-{
-	if (gNoRender)
-	{
-		return;
-	}
-	
-	BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
-	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
-	{
-		// build mode allows interaction with all transparent objects
-		// "Show Debug Alpha" means no object actually transparent
-		pick_transparent = TRUE;
-	}
-
-	LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback);
-	schedulePick(pick_info);
-}
-
-void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
-{
-	if (mPicks.size() >= 1024 || mWindow->getMinimized())
-	{ //something went wrong, picks are being scheduled but not processed
-		
-		if (pick_info.mPickCallback)
-		{
-			pick_info.mPickCallback(pick_info);
-		}
-	
-		return;
-	}
-	mPicks.push_back(pick_info);
-	
-	// delay further event processing until we receive results of pick
-	// only do this for async picks so that handleMouseUp won't be called
-	// until the pick triggered in handleMouseDown has been processed, for example
-	mWindow->delayInputProcessing();
-}
-
-
-void LLViewerWindow::performPick()
-{
-	if (gNoRender)
-	{
-		return;
-	}
-
-	if (!mPicks.empty())
-	{
-		std::vector<LLPickInfo>::iterator pick_it;
-		for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
-		{
-			pick_it->fetchResults();
-		}
-
-		mLastPick = mPicks.back();
-		mPicks.clear();
-	}
-}
-
-void LLViewerWindow::returnEmptyPicks()
-{
-	std::vector<LLPickInfo>::iterator pick_it;
-	for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
-	{
-		mLastPick = *pick_it;
-		// just trigger callback with empty results
-		if (pick_it->mPickCallback)
-		{
-			pick_it->mPickCallback(*pick_it);
-		}
-	}
-	mPicks.clear();
-}
-
-// Performs the GL object/land pick.
-LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot,  BOOL pick_transparent)
-{
-	if (gNoRender)
-	{
-		return LLPickInfo();
-	}
-
-	BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
-	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
-	{
-		// build mode allows interaction with all transparent objects
-		// "Show Debug Alpha" means no object actually transparent
-		pick_transparent = TRUE;
-	}
-
-	// shortcut queueing in mPicks and just update mLastPick in place
-	mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), gKeyboard->currentMask(TRUE), pick_transparent, TRUE, NULL);
-	mLastPick.fetchResults();
-
-	return mLastPick;
-}
-
-LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
-										   LLVector3* intersection)
-{
-	S32 x = mouse_x;
-	S32 y = mouse_y;
-
-	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
-	{
-		x = getCurrentMouseX();
-		y = getCurrentMouseY();
-	}
-
-	// world coordinates of mouse
-	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
-	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
-	LLVector3 mouse_world_start = mouse_point_global;
-	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
-
-	return LLHUDIcon::lineSegmentIntersectAll(mouse_world_start, mouse_world_end, intersection);
-
-	
-}
-
-LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
-												LLViewerObject *this_object,
-												S32 this_face,
-												BOOL pick_transparent,
-												S32* face_hit,
-												LLVector3 *intersection,
-												LLVector2 *uv,
-												LLVector3 *normal,
-												LLVector3 *binormal)
-{
-	S32 x = mouse_x;
-	S32 y = mouse_y;
-
-	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
-	{
-		x = getCurrentMouseX();
-		y = getCurrentMouseY();
-	}
-
-	// HUD coordinates of mouse
-	LLVector3 mouse_point_hud = mousePointHUD(x, y);
-	LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
-	LLVector3 mouse_hud_end   = mouse_point_hud + LLVector3(depth, 0, 0);
-	
-	// world coordinates of mouse
-	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
-	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
-	
-	//get near clip plane
-	LLVector3 n = LLViewerCamera::getInstance()->getAtAxis();
-	LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear();
-
-	//project mouse point onto plane
-	LLVector3 pos;
-	line_plane(mouse_point_global, mouse_direction_global, p, n, pos);
-	mouse_point_global = pos;
-
-	LLVector3 mouse_world_start = mouse_point_global;
-	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
-
-	
-	LLViewerObject* found = NULL;
-
-	if (this_object)  // check only this object
-	{
-		if (this_object->isHUDAttachment()) // is a HUD object?
-		{
-			if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face, pick_transparent,
-												  face_hit, intersection, uv, normal, binormal))
-			{
-				found = this_object;
-			}
-			}
-		
-		else // is a world object
-		{
-			if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, pick_transparent,
-												  face_hit, intersection, uv, normal, binormal))
-			{
-				found = this_object;
-			}
-			}
-			}
-
-	else // check ALL objects
-			{
-		found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, pick_transparent,
-													face_hit, intersection, uv, normal, binormal);
-
-		if (!found) // if not found in HUD, look in world:
-
-			{
-			found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, pick_transparent,
-														  face_hit, intersection, uv, normal, binormal);
-			}
-
-	}
-
-	return found;
-}
-
-// Returns unit vector relative to camera
-// indicating direction of point on screen x,y
-LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
-{
-	// find vertical field of view
-	F32			fov = LLViewerCamera::getInstance()->getView();
-
-	// find world view center in scaled ui coordinates
-	F32			center_x = getWorldViewRectScaled().getCenterX();
-	F32			center_y = getWorldViewRectScaled().getCenterY();
-
-	// calculate pixel distance to screen
-	F32			distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f));
-
-	// calculate click point relative to middle of screen
-	F32			click_x = x - center_x;
-	F32			click_y = y - center_y;
-
-	// compute mouse vector
-	LLVector3	mouse_vector =	distance * LLViewerCamera::getInstance()->getAtAxis()
-								- click_x * LLViewerCamera::getInstance()->getLeftAxis()
-								+ click_y * LLViewerCamera::getInstance()->getUpAxis();
-
-	mouse_vector.normVec();
-
-	return mouse_vector;
-}
-
-LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
-{
-	// find screen resolution
-	S32			height = getWorldViewHeightScaled();
-
-	// find world view center
-	F32			center_x = getWorldViewRectScaled().getCenterX();
-	F32			center_y = getWorldViewRectScaled().getCenterY();
-
-	// remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
-	F32 hud_x = -((F32)x - center_x)  / height;
-	F32 hud_y = ((F32)y - center_y) / height;
-
-	return LLVector3(0.f, hud_x/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.mHUDCurZoom);
-}
-
-// Returns unit vector relative to camera in camera space
-// indicating direction of point on screen x,y
-LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
-{
-	// find vertical field of view
-	F32			fov_height = LLViewerCamera::getInstance()->getView();
-	F32			fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
-
-	// find screen resolution
-	S32			height = getWorldViewHeightScaled();
-	S32			width = getWorldViewWidthScaled();
-
-	// find world view center
-	F32			center_x = getWorldViewRectScaled().getCenterX();
-	F32			center_y = getWorldViewRectScaled().getCenterY();
-
-	// calculate click point relative to middle of screen
-	F32			click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f;
-	F32			click_y = (((F32)y - center_y) / (F32)height) * fov_height;
-
-	// compute mouse vector
-	LLVector3	mouse_vector =	LLVector3(0.f, 0.f, -1.f);
-	LLQuaternion mouse_rotate;
-	mouse_rotate.setQuat(click_y, click_x, 0.f);
-
-	mouse_vector = mouse_vector * mouse_rotate;
-	// project to z = -1 plane;
-	mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]);
-
-	return mouse_vector;
-}
-
-
-
-BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, 
-										const LLVector3d &plane_point_global, 
-										const LLVector3 &plane_normal_global)
-{
-	LLVector3d	mouse_direction_global_d;
-
-	mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y));
-	LLVector3d	plane_normal_global_d;
-	plane_normal_global_d.setVec(plane_normal_global);
-	F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d);
-	LLVector3d plane_origin_camera_rel = plane_point_global - gAgentCamera.getCameraPositionGlobal();
-	F64	mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel)
-								/ plane_mouse_dot;
-	if (llabs(plane_mouse_dot) < 0.00001)
-	{
-		// if mouse is parallel to plane, return closest point on line through plane origin
-		// that is parallel to camera plane by scaling mouse direction vector
-		// by distance to plane origin, modulated by deviation of mouse direction from plane origin
-		LLVector3d plane_origin_dir = plane_origin_camera_rel;
-		plane_origin_dir.normVec();
-		
-		mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d);
-	}
-
-	point = gAgentCamera.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d;
-
-	return mouse_look_at_scale > 0.0;
-}
-
-
-// Returns global position
-BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global)
-{
-	LLVector3		mouse_direction_global = mouseDirectionGlobal(x,y);
-	F32				mouse_dir_scale;
-	BOOL			hit_land = FALSE;
-	LLViewerRegion	*regionp;
-	F32			land_z;
-	const F32	FIRST_PASS_STEP = 1.0f;		// meters
-	const F32	SECOND_PASS_STEP = 0.1f;	// meters
-	LLVector3d	camera_pos_global;
-
-	camera_pos_global = gAgentCamera.getCameraPositionGlobal();
-	LLVector3d		probe_point_global;
-	LLVector3		probe_point_region;
-
-	// walk forwards to find the point
-	for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < gAgentCamera.mDrawDistance; mouse_dir_scale += FIRST_PASS_STEP)
-	{
-		LLVector3d mouse_direction_global_d;
-		mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
-		probe_point_global = camera_pos_global + mouse_direction_global_d;
-
-		regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
-
-		if (!regionp)
-		{
-			// ...we're outside the world somehow
-			continue;
-		}
-
-		S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid());
-		S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid());
-		S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge;
-		if ((i >= grids_per_edge) || (j >= grids_per_edge))
-		{
-			//llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
-			continue;
-		}
-
-		land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
-
-		//llinfos << "mousePointOnLand initial z " << land_z << llendl;
-
-		if (probe_point_region.mV[VZ] < land_z)
-		{
-			// ...just went under land
-
-			// cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl;
-
-			hit_land = TRUE;
-			break;
-		}
-	}
-
-
-	if (hit_land)
-	{
-		// Don't go more than one step beyond where we stopped above.
-		// This can't just be "mouse_vec_scale" because floating point error
-		// will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X
-		F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP;
-
-		// take a step backwards, then walk forwards again to refine position
-		for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP)
-		{
-			LLVector3d mouse_direction_global_d;
-			mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
-			probe_point_global = camera_pos_global + mouse_direction_global_d;
-
-			regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
-
-			if (!regionp)
-			{
-				// ...we're outside the world somehow
-				continue;
-			}
-
-			/*
-			i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid());
-			j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid());
-			if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge))
-			{
-				// llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
-				continue;
-			}
-			land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ];
-			*/
-
-			land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
-
-			//llinfos << "mousePointOnLand refine z " << land_z << llendl;
-
-			if (probe_point_region.mV[VZ] < land_z)
-			{
-				// ...just went under land again
-
-				*land_position_global = probe_point_global;
-				return TRUE;
-			}
-		}
-	}
-
-	return FALSE;
-}
-
-// Saves an image to the harddrive as "SnapshotX" where X >= 1.
-BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image)
-{
-	if (!image)
-	{
-		return FALSE;
-	}
-
-	LLFilePicker::ESaveFilter pick_type;
-	std::string extension("." + image->getExtension());
-	if (extension == ".j2c")
-		pick_type = LLFilePicker::FFSAVE_J2C;
-	else if (extension == ".bmp")
-		pick_type = LLFilePicker::FFSAVE_BMP;
-	else if (extension == ".jpg")
-		pick_type = LLFilePicker::FFSAVE_JPEG;
-	else if (extension == ".png")
-		pick_type = LLFilePicker::FFSAVE_PNG;
-	else if (extension == ".tga")
-		pick_type = LLFilePicker::FFSAVE_TGA;
-	else
-		pick_type = LLFilePicker::FFSAVE_ALL; // ???
-	
-	// Get a base file location if needed.
-	if ( ! isSnapshotLocSet())		
-	{
-		std::string proposed_name( sSnapshotBaseName );
-
-		// getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in.
-
-		// pick a directory in which to save
-		LLFilePicker& picker = LLFilePicker::instance();
-		if (!picker.getSaveFile(pick_type, proposed_name))
-		{
-			// Clicked cancel
-			return FALSE;
-		}
-
-		// Copy the directory + file name
-		std::string filepath = picker.getFirstFile();
-
-		LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true);
-		LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath);
-	}
-
-	// Look for an unused file name
-	std::string filepath;
-	S32 i = 1;
-	S32 err = 0;
-
-	do
-	{
-		filepath = sSnapshotDir;
-		filepath += gDirUtilp->getDirDelimiter();
-		filepath += sSnapshotBaseName;
-		filepath += llformat("_%.3d",i);
-		filepath += extension;
-
-		llstat stat_info;
-		err = LLFile::stat( filepath, &stat_info );
-		i++;
-	}
-	while( -1 != err );  // search until the file is not found (i.e., stat() gives an error).
-
-	return image->save(filepath);
-}
-
-void LLViewerWindow::resetSnapshotLoc()
-{
-	sSnapshotDir.clear();
-}
-
-static S32 BORDERHEIGHT = 0;
-static S32 BORDERWIDTH = 0;
-
-// static
-void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
-{
-	LLCoordScreen size;
-	gViewerWindow->mWindow->getSize(&size);
-	if (  (size.mX != new_width + BORDERWIDTH)
-		||(size.mY != new_height + BORDERHEIGHT))
-	{
-		// use actual display dimensions, not virtual UI dimensions
-		S32 x = gViewerWindow->getWindowWidthRaw();
-		S32 y = gViewerWindow->getWindowHeightRaw();
-		BORDERWIDTH = size.mX - x;
-		BORDERHEIGHT = size.mY- y;
-		LLCoordScreen new_size(new_width + BORDERWIDTH, 
-							   new_height + BORDERHEIGHT);
-		gViewerWindow->mWindow->setSize(new_size);
-	}
-}
-
-BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
-{
-	llinfos << "Saving snapshot to: " << filepath << llendl;
-
-	LLPointer<LLImageRaw> raw = new LLImageRaw;
-	BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
-
-	if (success)
-	{
-		LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
-		success = bmp_image->encode(raw, 0.0f);
-		if( success )
-		{
-			success = bmp_image->save(filepath);
-		}
-		else
-		{
-			llwarns << "Unable to encode bmp snapshot" << llendl;
-		}
-	}
-	else
-	{
-		llwarns << "Unable to capture raw snapshot" << llendl;
-	}
-
-	return success;
-}
-
-
-void LLViewerWindow::playSnapshotAnimAndSound()
-{
-	if (gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
-	{
-		return;
-	}
-	gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START);
-	send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
-}
-
-BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
-{
-	return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
-}
-
-// Saves the image from the screen to the specified filename and path.
-BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, 
-								 BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
-{
-	if (!raw)
-	{
-		return FALSE;
-	}
-
-	// PRE SNAPSHOT
-	gDisplaySwapBuffers = FALSE;
-	
-	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-	setCursor(UI_CURSOR_WAIT);
-
-	// Hide all the UI widgets first and draw a frame
-	BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
-
-	show_ui = show_ui ? TRUE : FALSE;
-
-	if ( prev_draw_ui != show_ui)
-	{
-		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
-	}
-
-	BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
-	if (hide_hud)
-	{
-		LLPipeline::sShowHUDAttachments = FALSE;
-	}
-
-	// if not showing ui, use full window to render world view
-	updateWorldViewRect(!show_ui);
-
-	// Copy screen to a buffer
-	// crop sides or top and bottom, if taking a snapshot of different aspect ratio
-	// from window
-	LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); 
-
-	S32 snapshot_width = window_rect.getWidth();
-	S32 snapshot_height = window_rect.getHeight();
-	// SNAPSHOT
-	S32 window_width = snapshot_width;
-	S32 window_height = snapshot_height;
-	
-	if (show_ui)
-	{
-		image_width = llmin(image_width, window_width);
-		image_height = llmin(image_height, window_height);
-	}
-
-	F32 scale_factor = 1.0f ;
-	if(!keep_window_aspect) //image cropping
-	{		
-		F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
-		snapshot_width = (S32)(ratio * image_width) ;
-		snapshot_height = (S32)(ratio * image_height) ;
-		scale_factor = llmax(1.0f, 1.0f / ratio) ;
-	}
-	else //the scene(window) proportion needs to be maintained.
-	{
-		if(image_width > window_width || image_height > window_height) //need to enlarge the scene
-		{
-			F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
-			snapshot_width = (S32)(ratio * image_width) ;
-			snapshot_height = (S32)(ratio * image_height) ;
-			scale_factor = llmax(1.0f, 1.0f / ratio) ;	
-		}
-	}
-	
-	if (show_ui && scale_factor > 1.f)
-	{
-		llwarns << "over scaling UI not supported." << llendl;
-	}
-
-	S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f);
-	S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
-
-	S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ;
-	S32 image_buffer_y = llfloor(snapshot_height *scale_factor) ;
-
-	if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow
-	{
-		scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
-		image_buffer_x = llfloor(snapshot_width*scale_factor) ;
-		image_buffer_y = llfloor(snapshot_height *scale_factor) ;
-	}
-	if(image_buffer_x > 0 && image_buffer_y > 0)
-	{
-		raw->resize(image_buffer_x, image_buffer_y, 3);
-	}
-	else
-	{
-		return FALSE ;
-	}
-	if(raw->isBufferInvalid())
-	{
-		return FALSE ;
-	}
-
-	BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher
-	if (high_res && show_ui)
-	{
-		llwarns << "High res UI snapshot not supported. " << llendl;
-		/*send_agent_pause();
-		//rescale fonts
-		initFonts(scale_factor);
-		LLHUDObject::reshapeAll();*/
-	}
-
-	S32 output_buffer_offset_y = 0;
-
-	F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
-	F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
-
-	gObjectList.generatePickList(*LLViewerCamera::getInstance());
-
-	for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
-	{
-		S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
-		// handle fractional columns
-		U32 read_height = llmax(0, (window_height - subimage_y_offset) -
-			llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight())));
-
-		S32 output_buffer_offset_x = 0;
-		for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x)
-		{
-			gDisplaySwapBuffers = FALSE;
-			gDepthDirty = TRUE;
-
-			const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
-
-			if (LLPipeline::sRenderDeferred)
-			{
-					display(do_rebuild, scale_factor, subfield, TRUE);
-			}
-			else
-			{
-				display(do_rebuild, scale_factor, subfield, TRUE);
-					// Required for showing the GUI in snapshots and performing bloom composite overlay
-					// Call even if show_ui is FALSE
-				render_ui(scale_factor, subfield);
-			}
-
-			S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
-			// handle fractional rows
-			U32 read_width = llmax(0, (window_width - subimage_x_offset) -
-									llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth())));
-			for(U32 out_y = 0; out_y < read_height ; out_y++)
-			{
-				S32 output_buffer_offset = ( 
-							(out_y * (raw->getWidth())) // ...plus iterated y...
-							+ (window_width * subimage_x) // ...plus subimage start in x...
-							+ (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y...
-							- output_buffer_offset_x // ...minus buffer padding x...
-							- (output_buffer_offset_y * (raw->getWidth()))  // ...minus buffer padding y...
-						) * raw->getComponents();
-				
-				// Ping the wathdog thread every 100 lines to keep us alive (arbitrary number, feel free to change)
-				if (out_y % 100 == 0)
-				{
-					LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
-				}
-				
-				if (type == SNAPSHOT_TYPE_COLOR)
-				{
-					glReadPixels(
-						subimage_x_offset, out_y + subimage_y_offset,
-						read_width, 1,
-						GL_RGB, GL_UNSIGNED_BYTE,
-						raw->getData() + output_buffer_offset
-					);
-				}
-				else // SNAPSHOT_TYPE_DEPTH
-				{
-					LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values
-					glReadPixels(
-						subimage_x_offset, out_y + subimage_y_offset,
-						read_width, 1,
-						GL_DEPTH_COMPONENT, GL_FLOAT,
-						depth_line_buffer->getData()// current output pixel is beginning of buffer...
-					);
-
-					for (S32 i = 0; i < (S32)read_width; i++)
-					{
-						F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32)));
-					
-						F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2));
-						U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar());
-						//write converted scanline out to result image
-						for(S32 j = 0; j < raw->getComponents(); j++)
-						{
-							*(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte;
-						}
-					}
-				}
-			}
-			output_buffer_offset_x += subimage_x_offset;
-			stop_glerror();
-		}
-		output_buffer_offset_y += subimage_y_offset;
-	}
-
-	gDisplaySwapBuffers = FALSE;
-	gDepthDirty = TRUE;
-
-	// POST SNAPSHOT
-	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{
-		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
-	}
-
-	if (hide_hud)
-	{
-		LLPipeline::sShowHUDAttachments = TRUE;
-	}
-
-	/*if (high_res)
-	{
-		initFonts(1.f);
-		LLHUDObject::reshapeAll();
-	}*/
-
-	// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
-	// Note: this formula depends on the number of components being 3.  Not obvious, but it's correct.	
-	image_width += (image_width * 3) % 4;
-
-	BOOL ret = TRUE ;
-	// Resize image
-	if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
-	{
-		ret = raw->scale( image_width, image_height );  
-	}
-	else if(image_width != image_buffer_x || image_height != image_buffer_y)
-	{
-		ret = raw->scale( image_width, image_height, FALSE );  
-	}
-	
-
-	setCursor(UI_CURSOR_ARROW);
-
-	if (do_rebuild)
-	{
-		// If we had to do a rebuild, that means that the lists of drawables to be rendered
-		// was empty before we started.
-		// Need to reset these, otherwise we call state sort on it again when render gets called the next time
-		// and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
-		// objects on them.
-		gPipeline.resetDrawOrders();
-	}
-
-	if (high_res)
-	{
-		send_agent_resume();
-	}
-
-	return ret;
-}
-
-void LLViewerWindow::destroyWindow()
-{
-	if (mWindow)
-	{
-		LLWindowManager::destroyWindow(mWindow);
-	}
-	mWindow = NULL;
-}
-
-
-void LLViewerWindow::drawMouselookInstructions()
-{
-	// Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.)
-	const std::string instructions = LLTrans::getString("LeaveMouselook");
-	const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD));
-	
-	//to be on top of Bottom bar when it is opened
-	const S32 INSTRUCTIONS_PAD = 50;
-
-	font->renderUTF8( 
-		instructions, 0,
-		getWorldViewRectScaled().getCenterX(),
-		getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD,
-		LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
-		LLFontGL::HCENTER, LLFontGL::TOP,
-		LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
-}
-
-void* LLViewerWindow::getPlatformWindow() const
-{
-	return mWindow->getPlatformWindow();
-}
-
-void* LLViewerWindow::getMediaWindow() 	const
-{
-	return mWindow->getMediaWindow();
-}
-
-void LLViewerWindow::focusClient()		const
-{
-	return mWindow->focusClient();
-}
-
-LLRootView*	LLViewerWindow::getRootView() const
-{
-	return mRootView;
-}
-
-LLRect LLViewerWindow::getWorldViewRectScaled() const
-{
-	return mWorldViewRectScaled;
-}
-
-S32 LLViewerWindow::getWorldViewHeightScaled() const
-{
-	return mWorldViewRectScaled.getHeight();
-}
-
-S32 LLViewerWindow::getWorldViewWidthScaled() const
-{
-	return mWorldViewRectScaled.getWidth();
-}
-
-
-S32 LLViewerWindow::getWorldViewHeightRaw() const
-{
-	return mWorldViewRectRaw.getHeight(); 
-}
-
-S32 LLViewerWindow::getWorldViewWidthRaw() const
-{
-	return mWorldViewRectRaw.getWidth(); 
-}
-
-S32	LLViewerWindow::getWindowHeightScaled()	const 	
-{ 
-	return mWindowRectScaled.getHeight(); 
-}
-
-S32	LLViewerWindow::getWindowWidthScaled() const 	
-{ 
-	return mWindowRectScaled.getWidth(); 
-}
-
-S32	LLViewerWindow::getWindowHeightRaw()	const 	
-{ 
-	return mWindowRectRaw.getHeight(); 
-}
-
-S32	LLViewerWindow::getWindowWidthRaw() const 	
-{ 
-	return mWindowRectRaw.getWidth(); 
-}
-
-void LLViewerWindow::setup2DRender()
-{
-	// setup ortho camera
-	gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight());
-	setup2DViewport();
-}
-
-void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset)
-{
-	gGLViewport[0] = mWindowRectRaw.mLeft + x_offset;
-	gGLViewport[1] = mWindowRectRaw.mBottom + y_offset;
-	gGLViewport[2] = mWindowRectRaw.getWidth();
-	gGLViewport[3] = mWindowRectRaw.getHeight();
-	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-}
-
-
-void LLViewerWindow::setup3DRender()
-{
-	// setup perspective camera
-	LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom,  mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
-	setup3DViewport();
-}
-
-void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
-{
-	gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
-	gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
-	gGLViewport[2] = mWorldViewRectRaw.getWidth();
-	gGLViewport[3] = mWorldViewRectRaw.getHeight();
-	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-}
-
-void LLViewerWindow::setShowProgress(const BOOL show)
-{
-	if (mProgressView)
-	{
-		mProgressView->setVisible(show);
-	}
-}
-
-BOOL LLViewerWindow::getShowProgress() const
-{
-	return (mProgressView && mProgressView->getVisible());
-}
-
-void LLViewerWindow::setProgressString(const std::string& string)
-{
-	if (mProgressView)
-	{
-		mProgressView->setText(string);
-	}
-}
-
-void LLViewerWindow::setProgressMessage(const std::string& msg)
-{
-	if(mProgressView)
-	{
-		mProgressView->setMessage(msg);
-	}
-}
-
-void LLViewerWindow::setProgressPercent(const F32 percent)
-{
-	if (mProgressView)
-	{
-		mProgressView->setPercent(percent);
-	}
-}
-
-void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& label )
-{
-	if (mProgressView)
-	{
-		mProgressView->setCancelButtonVisible( b, label );
-	}
-}
-
-
-LLProgressView *LLViewerWindow::getProgressView() const
-{
-	return mProgressView;
-}
-
-void LLViewerWindow::dumpState()
-{
-	llinfos << "LLViewerWindow Active " << S32(mActive) << llendl;
-	llinfos << "mWindow visible " << S32(mWindow->getVisible())
-		<< " minimized " << S32(mWindow->getMinimized())
-		<< llendl;
-}
-
-void LLViewerWindow::stopGL(BOOL save_state)
-{
-	//Note: --bao
-	//if not necessary, do not change the order of the function calls in this function.
-	//if change something, make sure it will not break anything.
-	//especially be careful to put anything behind gTextureList.destroyGL(save_state);
-	if (!gGLManager.mIsDisabled)
-	{
-		llinfos << "Shutting down GL..." << llendl;
-
-		// Pause texture decode threads (will get unpaused during main loop)
-		LLAppViewer::getTextureCache()->pause();
-		LLAppViewer::getImageDecodeThread()->pause();
-		LLAppViewer::getTextureFetch()->pause();
-				
-		gSky.destroyGL();
-		stop_glerror();		
-
-		LLManipTranslate::destroyGL() ;
-		stop_glerror();		
-
-		gBumpImageList.destroyGL();
-		stop_glerror();
-
-		LLFontGL::destroyAllGL();
-		stop_glerror();
-
-		LLVOAvatar::destroyGL();
-		stop_glerror();
-
-		LLViewerDynamicTexture::destroyGL();
-		stop_glerror();
-
-		if (gPipeline.isInit())
-		{
-			gPipeline.destroyGL();
-		}
-		
-		gCone.cleanupGL();
-		gBox.cleanupGL();
-		gSphere.cleanupGL();
-		gCylinder.cleanupGL();
-		
-		if(gPostProcess)
-		{
-			gPostProcess->invalidate();
-		}
-
-		gTextureList.destroyGL(save_state);
-		stop_glerror();
-		
-		gGLManager.mIsDisabled = TRUE;
-		stop_glerror();
-		
-		llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << llendl;
-	}
-}
-
-void LLViewerWindow::restoreGL(const std::string& progress_message)
-{
-	//Note: --bao
-	//if not necessary, do not change the order of the function calls in this function.
-	//if change something, make sure it will not break anything. 
-	//especially, be careful to put something before gTextureList.restoreGL();
-	if (gGLManager.mIsDisabled)
-	{
-		llinfos << "Restoring GL..." << llendl;
-		gGLManager.mIsDisabled = FALSE;
-		
-		initGLDefaults();
-		LLGLState::restoreGL();
-		
-		gTextureList.restoreGL();
-		
-		// for future support of non-square pixels, and fonts that are properly stretched
-		//LLFontGL::destroyDefaultFonts();
-		initFonts();
-				
-		gSky.restoreGL();
-		gPipeline.restoreGL();
-		LLDrawPoolWater::restoreGL();
-		LLManipTranslate::restoreGL();
-		
-		gBumpImageList.restoreGL();
-		LLViewerDynamicTexture::restoreGL();
-		LLVOAvatar::restoreGL();
-		
-		gResizeScreenTexture = TRUE;
-		gWindowResized = TRUE;
-
-		if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
-		{
-			LLVisualParamHint::requestHintUpdates();
-		}
-
-		if (!progress_message.empty())
-		{
-			gRestoreGLTimer.reset();
-			gRestoreGL = TRUE;
-			setShowProgress(TRUE);
-			setProgressString(progress_message);
-		}
-		llinfos << "...Restoring GL done" << llendl;
-		if(!LLAppViewer::instance()->restoreErrorTrap())
-		{
-			llwarns << " Someone took over my signal/exception handler (post restoreGL)!" << llendl;
-		}
-
-	}
-}
-
-void LLViewerWindow::initFonts(F32 zoom_factor)
-{
-	LLFontGL::destroyAllGL();
-	// Initialize with possibly different zoom factor
-	LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
-								mDisplayScale.mV[VX] * zoom_factor,
-								mDisplayScale.mV[VY] * zoom_factor,
-								gDirUtilp->getAppRODataDir(),
-								LLUI::getXUIPaths());
-	// Force font reloads, which can be very slow
-	LLFontGL::loadDefaultFonts();
-}
-
-void LLViewerWindow::requestResolutionUpdate()
-{
-	mResDirty = true;
-}
-
-void LLViewerWindow::checkSettings()
-{
-	if (mStatesDirty)
-	{
-		gGL.refreshState();
-		LLViewerShaderMgr::instance()->setShaders();
-		mStatesDirty = false;
-	}
-	
-	// We want to update the resolution AFTER the states getting refreshed not before.
-	if (mResDirty)
-	{
-		reshape(getWindowWidthRaw(), getWindowHeightRaw());
-		mResDirty = false;
-	}	
-}
-
-void LLViewerWindow::restartDisplay(BOOL show_progress_bar)
-{
-	llinfos << "Restaring GL" << llendl;
-	stopGL();
-	if (show_progress_bar)
-	{
-		restoreGL(LLTrans::getString("ProgressChangingResolution"));
-	}
-	else
-	{
-		restoreGL();
-	}
-}
-
-BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar)
-{
-	//BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
-
-	//gResizeScreenTexture = TRUE;
-
-	//U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
-	//U32 old_fsaa = mWindow->getFSAASamples();
-
-	// if not maximized, use the request size
-	if (!mWindow->getMaximized())
-	{
-		mWindow->setSize(size);
-	}
-
-	//if (fsaa == old_fsaa)
-	{
-		return TRUE;
-	}
-
-/*
-
-	// Close floaters that don't handle settings change
-	LLFloaterReg::hideInstance("snapshot");
-	
-	BOOL result_first_try = FALSE;
-	BOOL result_second_try = FALSE;
-
-	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
-	send_agent_pause();
-	llinfos << "Stopping GL during changeDisplaySettings" << llendl;
-	stopGL();
-	mIgnoreActivate = TRUE;
-	LLCoordScreen old_size;
-	LLCoordScreen old_pos;
-	mWindow->getSize(&old_size);
-
-	//mWindow->setFSAASamples(fsaa);
-
-	result_first_try = mWindow->switchContext(false, size, disable_vsync);
-	if (!result_first_try)
-	{
-		// try to switch back
-		//mWindow->setFSAASamples(old_fsaa);
-		result_second_try = mWindow->switchContext(false, old_size, disable_vsync);
-
-		if (!result_second_try)
-		{
-			// we are stuck...try once again with a minimal resolution?
-			send_agent_resume();
-			mIgnoreActivate = FALSE;
-			return FALSE;
-		}
-	}
-	send_agent_resume();
-
-	llinfos << "Restoring GL during resolution change" << llendl;
-	if (show_progress_bar)
-	{
-		restoreGL(LLTrans::getString("ProgressChangingResolution"));
-	}
-	else
-	{
-		restoreGL();
-	}
-
-	if (!result_first_try)
-	{
-		LLSD args;
-		args["RESX"] = llformat("%d",size.mX);
-		args["RESY"] = llformat("%d",size.mY);
-		LLNotificationsUtil::add("ResolutionSwitchFail", args);
-		size = old_size; // for reshape below
-	}
-
-	BOOL success = result_first_try || result_second_try;
-
-	if (success)
-	{
-		// maximize window if was maximized, else reposition
-		if (was_maximized)
-		{
-			mWindow->maximize();
-		}
-		else
-		{
-			S32 windowX = gSavedSettings.getS32("WindowX");
-			S32 windowY = gSavedSettings.getS32("WindowY");
-
-			mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
-		}
-	}
-
-	mIgnoreActivate = FALSE;
-	gFocusMgr.setKeyboardFocus(keyboard_focus);
-	
-	return success;
-
-	*/
-}
-
-F32	LLViewerWindow::getWorldViewAspectRatio() const
-{
-	F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();
-	return world_aspect;
-}
-
-void LLViewerWindow::calcDisplayScale()
-{
-	F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
-	LLVector2 display_scale;
-	display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
-	display_scale *= ui_scale_factor;
-
-	// limit minimum display scale
-	if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE)
-	{
-		display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]);
-	}
-	
-	if (display_scale != mDisplayScale)
-	{
-		llinfos << "Setting display scale to " << display_scale << llendl;
-
-		mDisplayScale = display_scale;
-		// Init default fonts
-		initFonts();
-	}
-}
-
-//static
-LLRect 	LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale)
-{
-	LLRect res = rect;
-	res.mLeft = llround((F32)res.mLeft / display_scale.mV[VX]);
-	res.mRight = llround((F32)res.mRight / display_scale.mV[VX]);
-	res.mBottom = llround((F32)res.mBottom / display_scale.mV[VY]);
-	res.mTop = llround((F32)res.mTop / display_scale.mV[VY]);
-
-	return res;
-}
-
-S32 LLViewerWindow::getChatConsoleBottomPad()
-{
-	S32 offset = 0;
-
-	if(LLBottomTray::instanceExists())
-		offset += LLBottomTray::getInstance()->getRect().getHeight();
-
-	return offset;
-}
-
-LLRect LLViewerWindow::getChatConsoleRect()
-{
-	LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0);
-	LLRect console_rect = full_window;
-
-	const S32 CONSOLE_PADDING_TOP = 24;
-	const S32 CONSOLE_PADDING_LEFT = 24;
-	const S32 CONSOLE_PADDING_RIGHT = 10;
-
-	console_rect.mTop    -= CONSOLE_PADDING_TOP;
-	console_rect.mBottom += getChatConsoleBottomPad();
-
-	console_rect.mLeft   += CONSOLE_PADDING_LEFT; 
-
-	static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth");
-
-	if (CHAT_FULL_WIDTH)
-	{
-		console_rect.mRight -= CONSOLE_PADDING_RIGHT;
-	}
-	else
-	{
-		// Make console rect somewhat narrow so having inventory open is
-		// less of a problem.
-		console_rect.mRight  = console_rect.mLeft + 2 * getWindowWidthScaled() / 3;
-	}
-
-	return console_rect;
-}
-//----------------------------------------------------------------------------
-
-
-//static 
-bool LLViewerWindow::onAlert(const LLSD& notify)
-{
-	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
-
-	if (gNoRender)
-	{
-		llinfos << "Alert: " << notification->getName() << llendl;
-		notification->respond(LLSD::emptyMap());
-		LLNotifications::instance().cancel(notification);
-		return false;
-	}
-
-	// If we're in mouselook, the mouse is hidden and so the user can't click 
-	// the dialog buttons.  In that case, change to First Person instead.
-	if( gAgentCamera.cameraMouselook() )
-	{
-		gAgentCamera.changeCameraToDefault();
-	}
-	return false;
-}
-
-////////////////////////////////////////////////////////////////////////////
-//
-// LLPickInfo
-//
-LLPickInfo::LLPickInfo()
-	: mKeyMask(MASK_NONE),
-	  mPickCallback(NULL),
-	  mPickType(PICK_INVALID),
-	  mWantSurfaceInfo(FALSE),
-	  mObjectFace(-1),
-	  mUVCoords(-1.f, -1.f),
-	  mSTCoords(-1.f, -1.f),
-	  mXYCoords(-1, -1),
-	  mIntersection(),
-	  mNormal(),
-	  mBinormal(),
-	  mHUDIcon(NULL),
-	  mPickTransparent(FALSE)
-{
-}
-
-LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, 
-		       MASK keyboard_mask, 
-		       BOOL pick_transparent,
-		       BOOL pick_uv_coords,
-		       void (*pick_callback)(const LLPickInfo& pick_info))
-	: mMousePt(mouse_pos),
-	  mKeyMask(keyboard_mask),
-	  mPickCallback(pick_callback),
-	  mPickType(PICK_INVALID),
-	  mWantSurfaceInfo(pick_uv_coords),
-	  mObjectFace(-1),
-	  mUVCoords(-1.f, -1.f),
-	  mSTCoords(-1.f, -1.f),
-	  mXYCoords(-1, -1),
-	  mNormal(),
-	  mBinormal(),
-	  mHUDIcon(NULL),
-	  mPickTransparent(pick_transparent)
-{
-}
-
-void LLPickInfo::fetchResults()
-{
-
-	S32 face_hit = -1;
-	LLVector3 intersection, normal, binormal;
-	LLVector2 uv;
-
-	LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection);
-	
-	F32 icon_dist = 0.f;
-	if (hit_icon)
-	{
-		icon_dist = (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec();
-	}
-	LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
-									NULL, -1, mPickTransparent, &face_hit,
-									&intersection, &uv, &normal, &binormal);
-	
-	mPickPt = mMousePt;
-
-	U32 te_offset = face_hit > -1 ? face_hit : 0;
-
-	//unproject relative clicked coordinate from window coordinate using GL
-	
-	LLViewerObject* objectp = hit_object;
-
-	if (hit_icon && 
-		(!objectp || 
-		icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
-	{
-		// was this name referring to a hud icon?
-		mHUDIcon = hit_icon;
-		mPickType = PICK_ICON;
-		mPosGlobal = mHUDIcon->getPositionGlobal();
-	}
-	else if (objectp)
-	{
-		if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
-		{
-			// Hit land
-			mPickType = PICK_LAND;
-			mObjectID.setNull(); // land has no id
-
-			// put global position into land_pos
-			LLVector3d land_pos;
-			if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos))
-			{
-				// The selected point is beyond the draw distance or is otherwise 
-				// not selectable. Return before calling mPickCallback().
-				return;
-			}
-
-			// Fudge the land focus a little bit above ground.
-			mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
-		}
-		else
-		{
-			if(isFlora(objectp))
-			{
-				mPickType = PICK_FLORA;
-			}
-			else
-			{
-				mPickType = PICK_OBJECT;
-			}
-			mObjectOffset = gAgentCamera.calcFocusOffset(objectp, intersection, mPickPt.mX, mPickPt.mY);
-			mObjectID = objectp->mID;
-			mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
-
-			mPosGlobal = gAgent.getPosGlobalFromAgent(intersection);
-			
-			if (mWantSurfaceInfo)
-			{
-				getSurfaceInfo();
-			}
-		}
-	}
-	
-	if (mPickCallback)
-	{
-		mPickCallback(*this);
-	}
-}
-
-LLPointer<LLViewerObject> LLPickInfo::getObject() const
-{
-	return gObjectList.findObject( mObjectID );
-}
-
-void LLPickInfo::updateXYCoords()
-{
-	if (mObjectFace > -1)
-	{
-		const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
-		LLPointer<LLViewerTexture> imagep = LLViewerTextureManager::getFetchedTexture(tep->getID());
-		if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
-		{
-			mXYCoords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
-			mXYCoords.mY = llround((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight());
-		}
-	}
-}
-
-void LLPickInfo::getSurfaceInfo()
-{
-	// set values to uninitialized - this is what we return if no intersection is found
-	mObjectFace   = -1;
-	mUVCoords     = LLVector2(-1, -1);
-	mSTCoords     = LLVector2(-1, -1);
-	mXYCoords	  = LLCoordScreen(-1, -1);
-	mIntersection = LLVector3(0,0,0);
-	mNormal       = LLVector3(0,0,0);
-	mBinormal     = LLVector3(0,0,0);
-	
-	LLViewerObject* objectp = getObject();
-
-	if (objectp)
-	{
-		if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f,
-										   objectp, -1, mPickTransparent,
-										   &mObjectFace,
-										   &mIntersection,
-										   &mSTCoords,
-										   &mNormal,
-										   &mBinormal))
-		{
-			// if we succeeded with the intersect above, compute the texture coordinates:
-
-			if (objectp->mDrawable.notNull() && mObjectFace > -1)
-			{
-				LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
-
-				mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal);
-			}
-
-			// and XY coords:
-			updateXYCoords();
-			
-		}
-	}
-}
-
-
-/* code to get UV via a special UV render - removed in lieu of raycast method
-LLVector2 LLPickInfo::pickUV()
-{
-	LLVector2 result(-1.f, -1.f);
-
-	LLViewerObject* objectp = getObject();
-	if (!objectp)
-	{
-		return result;
-	}
-
-	if (mObjectFace > -1 &&
-		objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
-		mObjectFace < objectp->mDrawable->getNumFaces())
-	{
-		S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]);
-		S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]);
-		const S32 UV_PICK_WIDTH = 5;
-		const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
-		U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
-		LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
-		if (facep)
-		{
-			LLGLState scissor_state(GL_SCISSOR_TEST);
-			scissor_state.enable();
-			LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
-			//glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
-			glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
-
-			glClear(GL_DEPTH_BUFFER_BIT);
-
-			facep->renderSelectedUV();
-
-			glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
-			U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
-
-			result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
-			result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
-		}
-	}
-
-	return result;
-} */
-
-
-//static 
-bool LLPickInfo::isFlora(LLViewerObject* object)
-{
-	if (!object) return false;
-
-	LLPCode pcode = object->getPCode();
-
-	if( (LL_PCODE_LEGACY_GRASS == pcode) 
-		|| (LL_PCODE_LEGACY_TREE == pcode) 
-		|| (LL_PCODE_TREE_NEW == pcode))
-	{
-		return true;
-	}
-	return false;
-}
+/** 
+ * @file llviewerwindow.cpp
+ * @brief Implementation of the LLViewerWindow class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerwindow.h"
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+// system library includes
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llfloaterreg.h"
+#include "llpanellogin.h"
+#include "llviewerkeyboard.h"
+#include "llviewermenu.h"
+
+#include "llviewquery.h"
+#include "llxmltree.h"
+#include "llslurl.h"
+//#include "llviewercamera.h"
+#include "llrender.h"
+
+#include "llvoiceclient.h"	// for push-to-talk button handling
+
+//
+// TODO: Many of these includes are unnecessary.  Remove them.
+//
+
+// linden library includes
+#include "llaudioengine.h"		// mute on minimize
+#include "indra_constants.h"
+#include "llassetstorage.h"
+#include "llerrorcontrol.h"
+#include "llfontgl.h"
+#include "llmousehandler.h"
+#include "llrect.h"
+#include "llsky.h"
+#include "llstring.h"
+#include "llui.h"
+#include "lluuid.h"
+#include "llview.h"
+#include "llxfermanager.h"
+#include "message.h"
+#include "object_flags.h"
+#include "lltimer.h"
+#include "timing.h"
+#include "llviewermenu.h"
+#include "lltooltip.h"
+#include "llmediaentry.h"
+#include "llurldispatcher.h"
+
+// newview includes
+#include "llagent.h"
+#include "llbox.h"
+#include "llconsole.h"
+#include "llviewercontrol.h"
+#include "llcylinder.h"
+#include "lldebugview.h"
+#include "lldir.h"
+#include "lldrawable.h"
+#include "lldrawpoolalpha.h"
+#include "lldrawpoolbump.h"
+#include "lldrawpoolwater.h"
+#include "llmaniptranslate.h"
+#include "llface.h"
+#include "llfeaturemanager.h"
+#include "llfilepicker.h"
+#include "llfirstuse.h"
+#include "llfloater.h"
+#include "llfloaterbuildoptions.h"
+#include "llfloaterbuyland.h"
+#include "llfloatercamera.h"
+#include "llfloaterland.h"
+#include "llfloaterinspect.h"
+#include "llfloatermap.h"
+#include "llfloaternamedesc.h"
+#include "llfloaterpreference.h"
+#include "llfloatersnapshot.h"
+#include "llfloatertools.h"
+#include "llfloaterworldmap.h"
+#include "llfocusmgr.h"
+#include "llfontfreetype.h"
+#include "llgesturemgr.h"
+#include "llglheaders.h"
+#include "lltooltip.h"
+#include "llhudmanager.h"
+#include "llhudobject.h"
+#include "llhudview.h"
+#include "llimagebmp.h"
+#include "llimagej2c.h"
+#include "llimageworker.h"
+#include "llkeyboard.h"
+#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llmodaldialog.h"
+#include "llmorphview.h"
+#include "llmoveview.h"
+#include "llnavigationbar.h"
+#include "llpopupview.h"
+#include "llpreviewtexture.h"
+#include "llprogressview.h"
+#include "llresmgr.h"
+#include "llsidetray.h"
+#include "llselectmgr.h"
+#include "llrootview.h"
+#include "llrendersphere.h"
+#include "llstartup.h"
+#include "llstatusbar.h"
+#include "llstatview.h"
+#include "llsurface.h"
+#include "llsurfacepatch.h"
+#include "lltexlayer.h"
+#include "lltextbox.h"
+#include "lltexturecache.h"
+#include "lltexturefetch.h"
+#include "lltextureview.h"
+#include "lltool.h"
+#include "lltoolcomp.h"
+#include "lltooldraganddrop.h"
+#include "lltoolface.h"
+#include "lltoolfocus.h"
+#include "lltoolgrab.h"
+#include "lltoolmgr.h"
+#include "lltoolmorph.h"
+#include "lltoolpie.h"
+#include "lltoolselectland.h"
+#include "lltrans.h"
+#include "lluictrlfactory.h"
+#include "llurldispatcher.h"		// SLURL from other app instance
+#include "llversioninfo.h"
+#include "llvieweraudio.h"
+#include "llviewercamera.h"
+#include "llviewergesture.h"
+#include "llviewertexturelist.h"
+#include "llviewerinventory.h"
+#include "llviewerkeyboard.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llviewermenu.h"
+#include "llviewermessage.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewershadermgr.h"
+#include "llviewerstats.h"
+#include "llvoavatarself.h"
+#include "llvovolume.h"
+#include "llworld.h"
+#include "llworldmapview.h"
+#include "pipeline.h"
+#include "llappviewer.h"
+#include "llviewerdisplay.h"
+#include "llspatialpartition.h"
+#include "llviewerjoystick.h"
+#include "llviewernetwork.h"
+#include "llpostprocess.h"
+#include "llbottomtray.h"
+#include "llnearbychatbar.h"
+#include "llagentui.h"
+#include "llwearablelist.h"
+
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llnotificationmanager.h"
+
+#include "llfloaternotificationsconsole.h"
+
+#include "llnearbychat.h"
+#include "llviewerwindowlistener.h"
+#include "llpaneltopinfobar.h"
+
+#if LL_WINDOWS
+#include <tchar.h> // For Unicode conversion methods
+#endif
+
+//
+// Globals
+//
+void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
+
+extern BOOL gDebugClicks;
+extern BOOL gDisplaySwapBuffers;
+extern BOOL gDepthDirty;
+extern BOOL gResizeScreenTexture;
+
+LLViewerWindow	*gViewerWindow = NULL;
+
+LLFrameTimer	gAwayTimer;
+LLFrameTimer	gAwayTriggerTimer;
+
+BOOL			gShowOverlayTitle = FALSE;
+
+LLViewerObject*  gDebugRaycastObject = NULL;
+LLVector3       gDebugRaycastIntersection;
+LLVector2       gDebugRaycastTexCoord;
+LLVector3       gDebugRaycastNormal;
+LLVector3       gDebugRaycastBinormal;
+S32				gDebugRaycastFaceHit;
+
+// HUD display lines in lower right
+BOOL				gDisplayWindInfo = FALSE;
+BOOL				gDisplayCameraPos = FALSE;
+BOOL				gDisplayFOV = FALSE;
+BOOL				gDisplayBadge = FALSE;
+
+S32 CHAT_BAR_HEIGHT = 28; 
+S32 OVERLAY_BAR_HEIGHT = 20;
+
+const U8 NO_FACE = 255;
+BOOL gQuietSnapshot = FALSE;
+
+const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before coming back
+const F32 MAX_FAST_FRAME_TIME = 0.5f;
+const F32 FAST_FRAME_INCREMENT = 0.1f;
+
+const F32 MIN_DISPLAY_SCALE = 0.75f;
+
+std::string	LLViewerWindow::sSnapshotBaseName;
+std::string	LLViewerWindow::sSnapshotDir;
+
+std::string	LLViewerWindow::sMovieBaseName;
+
+class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole>
+{
+public:
+	virtual void recordMessage(LLError::ELevel level,
+								const std::string& message)
+	{
+		//FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread
+
+		// only log warnings to chat console
+		//if (level == LLError::LEVEL_WARN)
+		//{
+			//LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat");
+			//if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat"))
+			//{
+			//	LLChat chat;
+			//	chat.mText = message;
+			//	chat.mSourceType = CHAT_SOURCE_SYSTEM;
+
+			//	chat_floater->addChat(chat, FALSE, FALSE);
+			//}
+		//}
+	}
+};
+
+////////////////////////////////////////////////////////////////////////////
+//
+// LLDebugText
+//
+
+class LLDebugText
+{
+private:
+	struct Line
+	{
+		Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {}
+		std::string text;
+		S32 x,y;
+	};
+
+	LLViewerWindow *mWindow;
+	
+	typedef std::vector<Line> line_list_t;
+	line_list_t mLineList;
+	LLColor4 mTextColor;
+	
+	void addText(S32 x, S32 y, const std::string &text) 
+	{
+		mLineList.push_back(Line(text, x, y));
+	}
+	
+	void clearText() { mLineList.clear(); }
+	
+public:
+	LLDebugText(LLViewerWindow* window) : mWindow(window) {}
+
+	void update()
+	{
+		static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ;
+
+		std::string wind_vel_text;
+		std::string wind_vector_text;
+		std::string rwind_vel_text;
+		std::string rwind_vector_text;
+		std::string audio_text;
+
+		static const std::string beacon_particle = LLTrans::getString("BeaconParticle");
+		static const std::string beacon_physical = LLTrans::getString("BeaconPhysical");
+		static const std::string beacon_scripted = LLTrans::getString("BeaconScripted");
+		static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch");
+		static const std::string beacon_sound = LLTrans::getString("BeaconSound");
+		static const std::string beacon_media = LLTrans::getString("BeaconMedia");
+		static const std::string particle_hiding = LLTrans::getString("ParticleHiding");
+
+		// Draw the statistics in a light gray
+		// and in a thin font
+		mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
+
+		// Draw stuff growing up from right lower corner of screen
+		U32 xpos = mWindow->getWindowWidthScaled() - 350;
+		U32 ypos = 64;
+		const U32 y_inc = 20;
+
+		clearText();
+		
+		if (gSavedSettings.getBOOL("DebugShowTime"))
+		{
+			const U32 y_inc2 = 15;
+			for (std::map<S32,LLFrameTimer>::reverse_iterator iter = gDebugTimers.rbegin();
+				 iter != gDebugTimers.rend(); ++iter)
+			{
+				S32 idx = iter->first;
+				LLFrameTimer& timer = iter->second;
+				F32 time = timer.getElapsedTimeF32();
+				S32 hours = (S32)(time / (60*60));
+				S32 mins = (S32)((time - hours*(60*60)) / 60);
+				S32 secs = (S32)((time - hours*(60*60) - mins*60));
+				std::string label = gDebugTimerLabel[idx];
+				if (label.empty()) label = llformat("Debug: %d", idx);
+				addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2;
+			}
+			
+			F32 time = gFrameTimeSeconds;
+			S32 hours = (S32)(time / (60*60));
+			S32 mins = (S32)((time - hours*(60*60)) / 60);
+			S32 secs = (S32)((time - hours*(60*60) - mins*60));
+			addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
+		}
+		
+#if LL_WINDOWS
+		if (gSavedSettings.getBOOL("DebugShowMemory"))
+		{
+			addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getWorkingSetSize() / 1024)); 
+			ypos += y_inc;
+		}
+#endif
+
+		if (gDisplayCameraPos)
+		{
+			std::string camera_view_text;
+			std::string camera_center_text;
+			std::string agent_view_text;
+			std::string agent_left_text;
+			std::string agent_center_text;
+			std::string agent_root_center_text;
+
+			LLVector3d tvector; // Temporary vector to hold data for printing.
+
+			// Update camera center, camera view, wind info every other frame
+			tvector = gAgent.getPositionGlobal();
+			agent_center_text = llformat("AgentCenter  %f %f %f",
+										 (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+
+			if (isAgentAvatarValid())
+			{
+				tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot.getWorldPosition());
+				agent_root_center_text = llformat("AgentRootCenter %f %f %f",
+												  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+			}
+			else
+			{
+				agent_root_center_text = "---";
+			}
+
+
+			tvector = LLVector4(gAgent.getFrameAgent().getAtAxis());
+			agent_view_text = llformat("AgentAtAxis  %f %f %f",
+									   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+
+			tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis());
+			agent_left_text = llformat("AgentLeftAxis  %f %f %f",
+									   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+
+			tvector = gAgentCamera.getCameraPositionGlobal();
+			camera_center_text = llformat("CameraCenter %f %f %f",
+										  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+
+			tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis());
+			camera_view_text = llformat("CameraAtAxis    %f %f %f",
+										(F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
+		
+			addText(xpos, ypos, agent_center_text);  ypos += y_inc;
+			addText(xpos, ypos, agent_root_center_text);  ypos += y_inc;
+			addText(xpos, ypos, agent_view_text);  ypos += y_inc;
+			addText(xpos, ypos, agent_left_text);  ypos += y_inc;
+			addText(xpos, ypos, camera_center_text);  ypos += y_inc;
+			addText(xpos, ypos, camera_view_text);  ypos += y_inc;
+		}
+
+		if (gDisplayWindInfo)
+		{
+			wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec());
+			wind_vector_text = llformat("Wind vector   %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]);
+			rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec());
+			rwind_vector_text = llformat("RWind vec   %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]);
+
+			addText(xpos, ypos, wind_vel_text);  ypos += y_inc;
+			addText(xpos, ypos, wind_vector_text);  ypos += y_inc;
+			addText(xpos, ypos, rwind_vel_text);  ypos += y_inc;
+			addText(xpos, ypos, rwind_vector_text);  ypos += y_inc;
+		}
+		if (gDisplayWindInfo)
+		{
+			if (gAudiop)
+			{
+				audio_text= llformat("Audio for wind: %d", gAudiop->isWindEnabled());
+			}
+			addText(xpos, ypos, audio_text);  ypos += y_inc;
+		}
+		if (gDisplayFOV)
+		{
+			addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
+			ypos += y_inc;
+		}
+		if (gDisplayBadge)
+		{
+			addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
+			ypos += y_inc * 2;
+		}
+		
+		/*if (LLViewerJoystick::getInstance()->getOverrideCamera())
+		{
+			addText(xpos + 200, ypos, llformat("Flycam"));
+			ypos += y_inc;
+		}*/
+		
+		if (gSavedSettings.getBOOL("DebugShowRenderInfo"))
+		{
+			if (gPipeline.getUseVertexShaders() == 0)
+			{
+				addText(xpos, ypos, "Shaders Disabled");
+				ypos += y_inc;
+			}
+			addText(xpos, ypos, llformat("%d MB Vertex Data", LLVertexBuffer::sAllocatedBytes/(1024*1024)));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Mapped Buffers", LLVertexBuffer::sMappedCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Vertex Buffer Binds", LLVertexBuffer::sBindCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Vertex Buffer Sets", LLVertexBuffer::sSetCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount));
+            ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps));
+			ypos += y_inc;
+
+			gPipeline.mTextureMatrixOps = 0;
+			gPipeline.mMatrixOpCount = 0;
+
+			if (gPipeline.mBatchCount > 0)
+			{
+				addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, 
+					gPipeline.mTrianglesDrawn/gPipeline.mBatchCount));
+
+				gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize;
+				gPipeline.mMaxBatchSize = 0;
+				gPipeline.mBatchCount = 0;
+			}
+            ypos += y_inc;
+
+			addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls));
+			LLRender::sUICalls = LLRender::sUIVerts = 0;
+			ypos += y_inc;
+
+			addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount));
+			
+			ypos += y_inc;
+
+
+			addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars));
+			
+			ypos += y_inc;
+
+			addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount));
+			
+			ypos += y_inc;
+
+			LLVertexBuffer::sBindCount = LLImageGL::sBindCount = 
+				LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = 
+				gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0;
+		}
+		if (gSavedSettings.getBOOL("DebugShowRenderMatrices"))
+		{
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[8], gGLProjection[9], gGLProjection[10], gGLProjection[11]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[4], gGLProjection[5], gGLProjection[6], gGLProjection[7]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[0], gGLProjection[1], gGLProjection[2], gGLProjection[3]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, "Projection Matrix");
+			ypos += y_inc;
+
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[12], gGLModelView[13], gGLModelView[14], gGLModelView[15]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[8], gGLModelView[9], gGLModelView[10], gGLModelView[11]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[4], gGLModelView[5], gGLModelView[6], gGLModelView[7]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[0], gGLModelView[1], gGLModelView[2], gGLModelView[3]));
+			ypos += y_inc;
+
+			addText(xpos, ypos, "View Matrix");
+			ypos += y_inc;
+		}
+		if (gSavedSettings.getBOOL("DebugShowColor"))
+		{
+			U8 color[4];
+			LLCoordGL coord = gViewerWindow->getCurrentMouse();
+			glReadPixels(coord.mX, coord.mY, 1,1,GL_RGBA, GL_UNSIGNED_BYTE, color);
+			addText(xpos, ypos, llformat("%d %d %d %d", color[0], color[1], color[2], color[3]));
+			ypos += y_inc;
+		}
+		// only display these messages if we are actually rendering beacons at this moment
+		if (LLPipeline::getRenderBeacons(NULL) && LLFloaterReg::instanceVisible("beacons"))
+		{
+			if (LLPipeline::getRenderParticleBeacons(NULL))
+			{
+				addText(xpos, ypos, beacon_particle);
+				ypos += y_inc;
+			}
+			if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES))
+			{
+				addText(xpos, ypos, particle_hiding);
+				ypos += y_inc;
+			}
+			if (LLPipeline::getRenderPhysicalBeacons(NULL))
+			{
+				addText(xpos, ypos, beacon_physical);
+				ypos += y_inc;
+			}
+			if (LLPipeline::getRenderScriptedBeacons(NULL))
+			{
+				addText(xpos, ypos, beacon_scripted);
+				ypos += y_inc;
+			}
+			else
+				if (LLPipeline::getRenderScriptedTouchBeacons(NULL))
+				{
+					addText(xpos, ypos, beacon_scripted_touch);
+					ypos += y_inc;
+				}
+			if (LLPipeline::getRenderSoundBeacons(NULL))
+			{
+				addText(xpos, ypos, beacon_sound);
+				ypos += y_inc;
+			}
+		}
+		if(log_texture_traffic)
+		{	
+			U32 old_y = ypos ;
+			for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++)
+			{
+				if(gTotalTextureBytesPerBoostLevel[i] > 0)
+				{
+					addText(xpos, ypos, llformat("Boost_Level %d:  %.3f MB", i, (F32)gTotalTextureBytesPerBoostLevel[i] / (1024 * 1024)));
+					ypos += y_inc;
+				}
+			}
+			if(ypos != old_y)
+			{
+				addText(xpos, ypos, "Network traffic for textures:");
+				ypos += y_inc;
+			}
+		}
+		
+		if (gSavedSettings.getBOOL("DebugShowTextureInfo"))
+		{
+			LLViewerObject* objectp = NULL ;
+			//objectp = = gAgentCamera.getFocusObject();
+			
+			LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode();
+			if (nodep)
+			{
+				objectp = nodep->getObject();			
+			}
+			if (objectp && !objectp->isDead())
+			{
+				S32 num_faces = objectp->mDrawable->getNumFaces() ;
+				
+				for(S32 i = 0 ; i < num_faces; i++)
+				{
+					LLFace* facep = objectp->mDrawable->getFace(i) ;
+					if(facep)
+					{
+						//addText(xpos, ypos, llformat("ts_min: %.3f ts_max: %.3f tt_min: %.3f tt_max: %.3f", facep->mTexExtents[0].mV[0], facep->mTexExtents[1].mV[0],
+						//		facep->mTexExtents[0].mV[1], facep->mTexExtents[1].mV[1]));
+						//ypos += y_inc;
+						
+						addText(xpos, ypos, llformat("v_size: %.3f:  p_size: %.3f", facep->getVirtualSize(), facep->getPixelArea()));
+						ypos += y_inc;
+						
+						//const LLTextureEntry *tep = facep->getTextureEntry();
+						//if(tep)
+						//{
+						//	addText(xpos, ypos, llformat("scale_s: %.3f:  scale_t: %.3f", tep->mScaleS, tep->mScaleT)) ;
+						//	ypos += y_inc;
+						//}
+						
+						LLViewerTexture* tex = facep->getTexture() ;
+						if(tex)
+						{
+							addText(xpos, ypos, llformat("ID: %s v_size: %.3f", tex->getID().asString().c_str(), tex->getMaxVirtualSize()));
+							ypos += y_inc;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	void draw()
+	{
+		for (line_list_t::iterator iter = mLineList.begin();
+			 iter != mLineList.end(); ++iter)
+		{
+			const Line& line = *iter;
+			LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
+											 LLFontGL::LEFT, LLFontGL::TOP,
+											 LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
+		}
+		mLineList.clear();
+	}
+
+};
+
+void LLViewerWindow::updateDebugText()
+{
+	mDebugText->update();
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// LLViewerWindow
+//
+
+BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
+{
+	const char* buttonname = "";
+	const char* buttonstatestr = "";
+	S32 x = pos.mX;
+	S32 y = pos.mY;
+	x = llround((F32)x / mDisplayScale.mV[VX]);
+	y = llround((F32)y / mDisplayScale.mV[VY]);
+
+	// only send mouse clicks to UI if UI is visible
+	if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{	
+
+		if (down)
+		{
+			buttonstatestr = "down" ;
+		}
+		else
+		{
+			buttonstatestr = "up" ;
+		}
+		
+		switch (clicktype)
+		{
+		case LLMouseHandler::CLICK_LEFT:
+			mLeftMouseDown = down;
+			buttonname = "Left";
+			break;
+		case LLMouseHandler::CLICK_RIGHT:
+			mRightMouseDown = down;
+			buttonname = "Right";
+			break;
+		case LLMouseHandler::CLICK_MIDDLE:
+			mMiddleMouseDown = down;
+			buttonname = "Middle";
+			break;
+		case LLMouseHandler::CLICK_DOUBLELEFT:
+			mLeftMouseDown = down;
+			buttonname = "Left Double Click";
+			break;
+		}
+		
+		LLView::sMouseHandlerMessage.clear();
+
+		if (gMenuBarView)
+		{
+			// stop ALT-key access to menu
+			gMenuBarView->resetMenuTrigger();
+		}
+
+		if (gDebugClicks)
+		{	
+			llinfos << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << llendl;
+		}
+
+		// Make sure we get a corresponding mouseup event, even if the mouse leaves the window
+		if (down)
+			mWindow->captureMouse();
+		else
+			mWindow->releaseMouse();
+
+		// Indicate mouse was active
+		LLUI::resetMouseIdleTimer();
+
+		// Don't let the user move the mouse out of the window until mouse up.
+		if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
+		{
+			mWindow->setMouseClipping(down);
+		}
+
+		LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+		if( mouse_captor )
+		{
+			S32 local_x;
+			S32 local_y;
+			mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
+			if (LLView::sDebugMouseHandling)
+			{
+				llinfos << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << llendl;
+			}
+			return mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down);
+		}
+
+		// Topmost view gets a chance before the hierarchy
+		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+		//if (top_ctrl)
+		//{
+		//	S32 local_x, local_y;
+		//	top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
+		//		if (top_ctrl->pointInView(local_x, local_y))
+		//		{
+		//			return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down)	;
+		//		}
+		//		else
+		//		{
+		//		if (down)
+		//		{
+		//			gFocusMgr.setTopCtrl(NULL);
+		//		}
+		//	}
+		//}
+
+		// Give the UI views a chance to process the click
+		if( mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) )
+		{
+			if (LLView::sDebugMouseHandling)
+			{
+				llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLView::sMouseHandlerMessage << llendl;
+			}
+			return TRUE;
+		}
+		else if (LLView::sDebugMouseHandling)
+		{
+			llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl;
+		}
+	}
+
+	// Do not allow tool manager to handle mouseclicks if we have disconnected	
+	if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )
+	{
+		return TRUE;
+	}
+	
+
+	// If we got this far on a down-click, it wasn't handled.
+	// Up-clicks, though, are always handled as far as the OS is concerned.
+	BOOL default_rtn = !down;
+	return default_rtn;
+}
+
+BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = TRUE;
+	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
+}
+
+BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	// try handling as a double-click first, then a single-click if that
+	// wasn't handled.
+	BOOL down = TRUE;
+	if (handleAnyMouseClick(window, pos, mask,
+				LLMouseHandler::CLICK_DOUBLELEFT, down))
+	{
+		return TRUE;
+	}
+	return handleMouseDown(window, pos, mask);
+}
+
+BOOL LLViewerWindow::handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = FALSE;
+	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
+}
+
+
+BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	S32 x = pos.mX;
+	S32 y = pos.mY;
+	x = llround((F32)x / mDisplayScale.mV[VX]);
+	y = llround((F32)y / mDisplayScale.mV[VY]);
+
+	BOOL down = TRUE;
+	BOOL handle = handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
+	if (handle)
+		return handle;
+
+	// *HACK: this should be rolled into the composite tool logic, not
+	// hardcoded at the top level.
+	if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance())
+	{
+		// If the current tool didn't process the click, we should show
+		// the pie menu.  This can be done by passing the event to the pie
+		// menu tool.
+		LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
+		// show_context_menu( x, y, mask );
+	}
+
+	return TRUE;
+}
+
+BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = FALSE;
+ 	return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
+}
+
+BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = TRUE;
+	LLVoiceClient::getInstance()->middleMouseState(true);
+ 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
+  
+  	// Always handled as far as the OS is concerned.
+	return TRUE;
+}
+
+LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data)
+{
+	LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE;
+
+	const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop");
+	const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop");
+	
+	if ( prim_media_dnd_enabled || slurl_dnd_enabled )
+	{
+		switch(action)
+		{
+			// Much of the handling for these two cases is the same.
+			case LLWindowCallbacks::DNDA_TRACK:
+			case LLWindowCallbacks::DNDA_DROPPED:
+			case LLWindowCallbacks::DNDA_START_TRACKING:
+			{
+				bool drop = (LLWindowCallbacks::DNDA_DROPPED == action);
+					
+				if (slurl_dnd_enabled)
+				{
+					LLSLURL dropped_slurl(data);
+					if(dropped_slurl.isSpatial())
+					{
+						if (drop)
+						{
+							LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), NULL, true );
+							return LLWindowCallbacks::DND_MOVE;
+						}
+						return LLWindowCallbacks::DND_COPY;
+					}
+				}
+
+				if (prim_media_dnd_enabled)
+				{
+					LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY,  TRUE /*BOOL pick_transparent*/ );
+
+					LLUUID object_id = pick_info.getObjectID();
+					S32 object_face = pick_info.mObjectFace;
+					std::string url = data;
+
+					lldebugs << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl;
+
+					LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject()));
+				
+					if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty())
+					{
+						LLTextureEntry *te = obj->getTE(object_face);
+
+						// can modify URL if we can modify the object or we have navigate permissions
+						bool allow_modify_url = obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT );
+
+						if (te && allow_modify_url )
+						{
+							if (drop)
+							{
+								// object does NOT have media already
+								if ( ! te->hasMedia() )
+								{
+									// we are allowed to modify the object
+									if ( obj->permModify() )
+									{
+										// Create new media entry
+										LLSD media_data;
+										// XXX Should we really do Home URL too?
+										media_data[LLMediaEntry::HOME_URL_KEY] = url;
+										media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
+										media_data[LLMediaEntry::AUTO_PLAY_KEY] = true;
+										obj->syncMediaData(object_face, media_data, true, true);
+										// XXX This shouldn't be necessary, should it ?!?
+										if (obj->getMediaImpl(object_face))
+											obj->getMediaImpl(object_face)->navigateReload();
+										obj->sendMediaDataUpdate();
+
+										result = LLWindowCallbacks::DND_COPY;
+									}
+								}
+								else 
+								// object HAS media already
+								{
+									// URL passes the whitelist
+									if (te->getMediaData()->checkCandidateUrl( url ) )
+									{
+										// just navigate to the URL
+										if (obj->getMediaImpl(object_face))
+										{
+											obj->getMediaImpl(object_face)->navigateTo(url);
+										}
+										else 
+										{
+											// This is very strange.  Navigation should
+											// happen via the Impl, but we don't have one.
+											// This sends it to the server, which /should/
+											// trigger us getting it.  Hopefully.
+											LLSD media_data;
+											media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
+											obj->syncMediaData(object_face, media_data, true, true);
+											obj->sendMediaDataUpdate();
+										}
+										result = LLWindowCallbacks::DND_LINK;
+										
+									}
+								}
+								LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+								mDragHoveredObject = NULL;
+							
+							}
+							else 
+							{
+								// Check the whitelist, if there's media (otherwise just show it)
+								if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
+								{
+									if ( obj != mDragHoveredObject)
+									{
+										// Highlight the dragged object
+										LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+										mDragHoveredObject = obj;
+										LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject);
+									}
+									result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK;
+
+								}
+							}
+						}
+					}
+				}
+			}
+			break;
+			
+			case LLWindowCallbacks::DNDA_STOP_TRACKING:
+				// The cleanup case below will make sure things are unhilighted if necessary.
+			break;
+		}
+
+		if (prim_media_dnd_enabled &&
+			result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull())
+		{
+			LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+			mDragHoveredObject = NULL;
+		}
+	}
+	
+	return result;
+}
+  
+BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	BOOL down = FALSE;
+	LLVoiceClient::getInstance()->middleMouseState(false);
+ 	handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
+  
+  	// Always handled as far as the OS is concerned.
+	return TRUE;
+}
+
+// WARNING: this is potentially called multiple times per frame
+void LLViewerWindow::handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask)
+{
+	S32 x = pos.mX;
+	S32 y = pos.mY;
+
+	x = llround((F32)x / mDisplayScale.mV[VX]);
+	y = llround((F32)y / mDisplayScale.mV[VY]);
+
+	mMouseInWindow = TRUE;
+
+	// Save mouse point for access during idle() and display()
+
+	LLCoordGL mouse_point(x, y);
+
+	if (mouse_point != mCurrentMousePoint)
+	{
+		LLUI::resetMouseIdleTimer();
+	}
+
+	saveLastMouse(mouse_point);
+
+	mWindow->showCursorFromMouseMove();
+
+	if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
+	{
+		gAgent.clearAFK();
+	}
+}
+
+void LLViewerWindow::handleMouseLeave(LLWindow *window)
+{
+	// Note: we won't get this if we have captured the mouse.
+	llassert( gFocusMgr.getMouseCapture() == NULL );
+	mMouseInWindow = FALSE;
+	LLToolTipMgr::instance().blockToolTips();
+}
+
+BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
+{
+	// User has indicated they want to close, but we may need to ask
+	// about modified documents.
+	LLAppViewer::instance()->userQuit();
+	// Don't quit immediately
+	return FALSE;
+}
+
+void LLViewerWindow::handleQuit(LLWindow *window)
+{
+	LLAppViewer::instance()->forceQuit();
+}
+
+void LLViewerWindow::handleResize(LLWindow *window,  S32 width,  S32 height)
+{
+	reshape(width, height);
+	mResDirty = true;
+}
+
+// The top-level window has gained focus (e.g. via ALT-TAB)
+void LLViewerWindow::handleFocus(LLWindow *window)
+{
+	gFocusMgr.setAppHasFocus(TRUE);
+	LLModalDialog::onAppFocusGained();
+
+	gAgent.onAppFocusGained();
+	LLToolMgr::getInstance()->onAppFocusGained();
+
+	// See if we're coming in with modifier keys held down
+	if (gKeyboard)
+	{
+		gKeyboard->resetMaskKeys();
+	}
+
+	// resume foreground running timer
+	// since we artifically limit framerate when not frontmost
+	gForegroundTime.unpause();
+}
+
+// The top-level window has lost focus (e.g. via ALT-TAB)
+void LLViewerWindow::handleFocusLost(LLWindow *window)
+{
+	gFocusMgr.setAppHasFocus(FALSE);
+	//LLModalDialog::onAppFocusLost();
+	LLToolMgr::getInstance()->onAppFocusLost();
+	gFocusMgr.setMouseCapture( NULL );
+
+	if (gMenuBarView)
+	{
+		// stop ALT-key access to menu
+		gMenuBarView->resetMenuTrigger();
+	}
+
+	// restore mouse cursor
+	showCursor();
+	getWindow()->setMouseClipping(FALSE);
+
+	// If losing focus while keys are down, reset them.
+	if (gKeyboard)
+	{
+		gKeyboard->resetKeys();
+	}
+
+	// pause timer that tracks total foreground running time
+	gForegroundTime.pause();
+}
+
+
+BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
+{
+	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
+	LLVoiceClient::getInstance()->keyDown(key, mask);
+	
+	if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
+	{
+		gAgent.clearAFK();
+	}
+
+	// *NOTE: We want to interpret KEY_RETURN later when it arrives as
+	// a Unicode char, not as a keydown.  Otherwise when client frame
+	// rate is really low, hitting return sends your chat text before
+	// it's all entered/processed.
+	if (key == KEY_RETURN && mask == MASK_NONE)
+	{
+		return FALSE;
+	}
+
+	return gViewerKeyboard.handleKey(key, mask, repeated);
+}
+
+BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
+{
+	// Let the voice chat code check for its PTT key.  Note that this never affects event processing.
+	LLVoiceClient::getInstance()->keyUp(key, mask);
+
+	return FALSE;
+}
+
+
+void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
+{
+	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
+	return gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
+}
+
+
+
+
+BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated)
+{
+	if (activated)
+	{
+		mActive = TRUE;
+		send_agent_resume();
+		gAgent.clearAFK();
+		
+		// Unmute audio
+		audio_update_volume();
+	}
+	else
+	{
+		mActive = FALSE;
+				
+		if (gSavedSettings.getS32("AFKTimeout"))
+		{
+			gAgent.setAFK();
+		}
+		
+		// SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues
+		if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
+		{
+			gAgentCamera.changeCameraToDefault();
+		}
+		
+		send_agent_pause();
+	
+		// Mute audio
+		audio_update_volume();
+	}
+	return TRUE;
+}
+
+BOOL LLViewerWindow::handleActivateApp(LLWindow *window, BOOL activating)
+{
+	//if (!activating) gAgentCamera.changeCameraToDefault();
+
+	LLViewerJoystick::getInstance()->setNeedsReset(true);
+	return FALSE;
+}
+
+
+void LLViewerWindow::handleMenuSelect(LLWindow *window,  S32 menu_item)
+{
+}
+
+
+BOOL LLViewerWindow::handlePaint(LLWindow *window,  S32 x,  S32 y, S32 width,  S32 height)
+{
+#if LL_WINDOWS
+	if (gNoRender)
+	{
+		HWND window_handle = (HWND)window->getPlatformWindow();
+		PAINTSTRUCT ps; 
+		HDC hdc; 
+ 
+		RECT wnd_rect;
+		wnd_rect.left = 0;
+		wnd_rect.top = 0;
+		wnd_rect.bottom = 200;
+		wnd_rect.right = 500;
+
+		hdc = BeginPaint(window_handle, &ps); 
+		//SetBKColor(hdc, RGB(255, 255, 255));
+		FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
+
+		std::string temp_str;
+		temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f",		/* Flawfinder: ignore */
+				LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(),
+				LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0),
+				LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0));
+		S32 len = temp_str.length();
+		TextOutA(hdc, 0, 0, temp_str.c_str(), len); 
+
+
+		LLVector3d pos_global = gAgent.getPositionGlobal();
+		temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]);
+		len = temp_str.length();
+		TextOutA(hdc, 0, 25, temp_str.c_str(), len); 
+
+		TextOutA(hdc, 0, 50, "Set \"DisableRendering FALSE\" in settings.ini file to reenable", 61);
+		EndPaint(window_handle, &ps); 
+		return TRUE;
+	}
+#endif
+	return FALSE;
+}
+
+
+void LLViewerWindow::handleScrollWheel(LLWindow *window,  S32 clicks)
+{
+	handleScrollWheel( clicks );
+}
+
+void LLViewerWindow::handleWindowBlock(LLWindow *window)
+{
+	send_agent_pause();
+}
+
+void LLViewerWindow::handleWindowUnblock(LLWindow *window)
+{
+	send_agent_resume();
+}
+
+void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
+{
+	const S32 SLURL_MESSAGE_TYPE = 0;
+	switch (data_type)
+	{
+	case SLURL_MESSAGE_TYPE:
+		// received URL
+		std::string url = (const char*)data;
+		LLMediaCtrl* web = NULL;
+		const bool trusted_browser = false;
+		if (LLURLDispatcher::dispatch(url, web, trusted_browser))
+		{
+			// bring window to foreground, as it has just been "launched" from a URL
+			mWindow->bringToFront();
+		}
+		break;
+	}
+}
+
+BOOL LLViewerWindow::handleTimerEvent(LLWindow *window)
+{
+	if (LLViewerJoystick::getInstance()->getOverrideCamera())
+	{
+		LLViewerJoystick::getInstance()->updateStatus();
+		return TRUE;
+	}
+	return FALSE;
+}
+
+BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
+{
+	// give a chance to use a joystick after startup (hot-plugging)
+	if (!LLViewerJoystick::getInstance()->isJoystickInitialized() )
+	{
+		LLViewerJoystick::getInstance()->init(true);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg)
+{
+	LLAppViewer::instance()->pingMainloopTimeout(msg);
+}
+
+
+void LLViewerWindow::handleResumeWatchdog(LLWindow *window)
+{
+	LLAppViewer::instance()->resumeMainloopTimeout();
+}
+
+void LLViewerWindow::handlePauseWatchdog(LLWindow *window)
+{
+	LLAppViewer::instance()->pauseMainloopTimeout();
+}
+
+//virtual
+std::string LLViewerWindow::translateString(const char* tag)
+{
+	return LLTrans::getString( std::string(tag) );
+}
+
+//virtual
+std::string LLViewerWindow::translateString(const char* tag,
+		const std::map<std::string, std::string>& args)
+{
+	// LLTrans uses a special subclass of std::string for format maps,
+	// but we must use std::map<> in these callbacks, otherwise we create
+	// a dependency between LLWindow and LLFormatMapString.  So copy the data.
+	LLStringUtil::format_map_t args_copy;
+	std::map<std::string,std::string>::const_iterator it = args.begin();
+	for ( ; it != args.end(); ++it)
+	{
+		args_copy[it->first] = it->second;
+	}
+	return LLTrans::getString( std::string(tag), args_copy);
+}
+
+//
+// Classes
+//
+LLViewerWindow::LLViewerWindow(
+	const std::string& title, const std::string& name,
+	S32 x, S32 y,
+	S32 width, S32 height,
+	BOOL fullscreen, BOOL ignore_pixel_depth) // fullscreen is no longer used
+	:
+	mWindow(NULL),
+	mActive(TRUE),
+	mWindowRectRaw(0, height, width, 0),
+	mWindowRectScaled(0, height, width, 0),
+	mWorldViewRectRaw(0, height, width, 0),
+	mLeftMouseDown(FALSE),
+	mMiddleMouseDown(FALSE),
+	mRightMouseDown(FALSE),
+	mMouseInWindow( FALSE ),
+	mLastMask( MASK_NONE ),
+	mToolStored( NULL ),
+	mHideCursorPermanent( FALSE ),
+	mCursorHidden(FALSE),
+	mIgnoreActivate( FALSE ),
+	mResDirty(false),
+	mStatesDirty(false),
+	mCurrResolutionIndex(0),
+    mViewerWindowListener(new LLViewerWindowListener(this)),
+	mProgressView(NULL)
+{
+	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
+	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
+
+	LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
+	LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
+	LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));
+	llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl;
+
+	// Default to application directory.
+	LLViewerWindow::sSnapshotBaseName = "Snapshot";
+	LLViewerWindow::sMovieBaseName = "SLmovie";
+	resetSnapshotLoc();
+
+	// create window
+	mWindow = LLWindowManager::createWindow(this,
+		title, name, x, y, width, height, 0,
+		fullscreen, 
+		gNoRender,
+		gSavedSettings.getBOOL("DisableVerticalSync"),
+		!gNoRender,
+		ignore_pixel_depth,
+		gSavedSettings.getBOOL("RenderUseFBO") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled
+
+	if (!LLAppViewer::instance()->restoreErrorTrap())
+	{
+		LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL;
+	}
+
+	LLCoordScreen scr;
+    mWindow->getSize(&scr);
+
+    if(fullscreen && ( scr.mX!=width || scr.mY!=height))
+    {
+		llwarns << "Fullscreen has forced us in to a different resolution now using "<<scr.mX<<" x "<<scr.mY<<llendl;
+		gSavedSettings.setS32("FullScreenWidth",scr.mX);
+		gSavedSettings.setS32("FullScreenHeight",scr.mY);
+    }
+
+	if (NULL == mWindow)
+	{
+		LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
+#if LL_LINUX || LL_SOLARIS
+		llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly.  See README-linux.txt or README-solaris.txt for further information."
+				<< llendl;
+#else
+		LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings"
+				<< LL_ENDL;
+#endif
+        LLAppViewer::instance()->fastQuit(1);
+	}
+	
+	// Get the real window rect the window was created with (since there are various OS-dependent reasons why
+	// the size of a window or fullscreen context may have been adjusted slightly...)
+	F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
+	
+	mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
+	mDisplayScale *= ui_scale_factor;
+	LLUI::setScaleFactor(mDisplayScale);
+
+	{
+		LLCoordWindow size;
+		mWindow->getSize(&size);
+		mWindowRectRaw.set(0, size.mY, size.mX, 0);
+		mWindowRectScaled.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0);
+	}
+	
+	LLFontManager::initClass();
+
+	//
+	// We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off
+	// stuff like AGP if we think that it'll crash the viewer.
+	//
+	LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
+
+	LLFeatureManager::getInstance()->init();
+
+	// Initialize OpenGL Renderer
+	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
+		!gGLManager.mHasVertexBufferObject)
+	{
+		gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
+	}
+	LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
+
+	if (LLFeatureManager::getInstance()->isSafe()
+		|| (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
+		|| (gSavedSettings.getS32("LastGPUClass") != LLFeatureManager::getInstance()->getGPUClass())
+		|| (gSavedSettings.getBOOL("ProbeHardwareOnStartup")))
+	{
+		LLFeatureManager::getInstance()->applyRecommendedSettings();
+		gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
+	}
+
+	if (!gGLManager.mHasDepthClamp)
+	{
+		LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL;
+	}
+	
+	// If we crashed while initializng GL stuff last time, disable certain features
+	if (gSavedSettings.getBOOL("RenderInitError"))
+	{
+		mInitAlert = "DisplaySettingsNoShaders";
+		LLFeatureManager::getInstance()->setGraphicsLevel(0, false);
+		gSavedSettings.setU32("RenderQualityPerformance", 0);		
+	}
+		
+	// Init the image list.  Must happen after GL is initialized and before the images that
+	// LLViewerWindow needs are requested.
+	LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ;
+	gTextureList.init();
+	LLViewerTextureManager::init() ;
+	gBumpImageList.init();
+	
+	// Init font system, but don't actually load the fonts yet
+	// because our window isn't onscreen and they take several
+	// seconds to parse.
+	LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
+								mDisplayScale.mV[VX],
+								mDisplayScale.mV[VY],
+								gDirUtilp->getAppRODataDir(),
+								LLUI::getXUIPaths());
+	
+	// Create container for all sub-views
+	LLView::Params rvp;
+	rvp.name("root");
+	rvp.rect(mWindowRectScaled);
+	rvp.mouse_opaque(false);
+	rvp.follows.flags(FOLLOWS_NONE);
+	mRootView = LLUICtrlFactory::create<LLRootView>(rvp);
+	LLUI::setRootView(mRootView);
+
+	// Make avatar head look forward at start
+	mCurrentMousePoint.mX = getWindowWidthScaled() / 2;
+	mCurrentMousePoint.mY = getWindowHeightScaled() / 2;
+
+	gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
+	mOverlayTitle = gSavedSettings.getString("OverlayTitle");
+	// Can't have spaces in settings.ini strings, so use underscores instead and convert them.
+	LLStringUtil::replaceChar(mOverlayTitle, '_', ' ');
+
+	// sync the keyboard's setting with the saved setting
+	gSavedSettings.getControl("NumpadControl")->firePropertyChanged();
+
+	mDebugText = new LLDebugText(this);
+
+	mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
+}
+
+void LLViewerWindow::initGLDefaults()
+{
+	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+	glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
+
+	F32 ambient[4] = {0.f,0.f,0.f,0.f };
+	F32 diffuse[4] = {1.f,1.f,1.f,1.f };
+	glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambient);
+	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuse);
+	
+	glPixelStorei(GL_PACK_ALIGNMENT,1);
+	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+
+	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+
+	// lights for objects
+	glShadeModel( GL_SMOOTH );
+
+	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
+	
+	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+	glCullFace(GL_BACK);
+
+	// RN: Need this for translation and stretch manip.
+	gCone.prerender();
+	gBox.prerender();
+	gSphere.prerender();
+	gCylinder.prerender();
+}
+
+struct MainPanel : public LLPanel
+{
+};
+
+void LLViewerWindow::initBase()
+{
+	S32 height = getWindowHeightScaled();
+	S32 width = getWindowWidthScaled();
+
+	LLRect full_window(0, height, width, 0);
+
+	////////////////////
+	//
+	// Set the gamma
+	//
+
+	F32 gamma = gSavedSettings.getF32("RenderGamma");
+	if (gamma != 0.0f)
+	{
+		getWindow()->setGamma(gamma);
+	}
+
+	// Create global views
+
+	// Create the floater view at the start so that other views can add children to it. 
+	// (But wait to add it as a child of the root view so that it will be in front of the 
+	// other views.)
+	MainPanel* main_view = new MainPanel();
+	main_view->buildFromFile("main_view.xml");
+	main_view->setShape(full_window);
+	getRootView()->addChild(main_view);
+
+	// placeholder widget that controls where "world" is rendered
+	mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle();
+	mNonSideTrayView = main_view->getChildView("non_side_tray_view")->getHandle();
+	mFloaterViewHolder = main_view->getChildView("floater_view_holder")->getHandle();
+	mPopupView = main_view->getChild<LLPopupView>("popup_holder");
+	mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle();
+	mLoginPanelHolder = main_view->getChild<LLView>("login_panel_holder")->getHandle();
+
+	// Constrain floaters to inside the menu and status bar regions.
+	gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
+	gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());
+	gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
+	
+
+	// Console
+	llassert( !gConsole );
+	LLConsole::Params cp;
+	cp.name("console");
+	cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize"));
+	cp.rect(getChatConsoleRect());
+	cp.persist_time(gSavedSettings.getF32("ChatPersistTime"));
+	cp.font_size_index(gSavedSettings.getS32("ChatFontSize"));
+	cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
+	gConsole = LLUICtrlFactory::create<LLConsole>(cp);
+	getRootView()->addChild(gConsole);
+
+	// optionally forward warnings to chat console/chat floater
+	// for qa runs and dev builds
+#if  !LL_RELEASE_FOR_DOWNLOAD
+	LLError::addRecorder(RecordToChatConsole::getInstance());
+#else
+	if(gSavedSettings.getBOOL("QAMode"))
+	{
+		LLError::addRecorder(RecordToChatConsole::getInstance());
+	}
+#endif
+
+	gDebugView = getRootView()->getChild<LLDebugView>("DebugView");
+	gDebugView->init();
+	gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view");
+
+	// Initialize busy response message when logged in
+	LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initBusyResponse));
+
+	// Add the progress bar view (startup view), which overrides everything
+	mProgressView = getRootView()->findChild<LLProgressView>("progress_view");
+	setShowProgress(FALSE);
+	setProgressCancelButtonVisible(FALSE);
+
+	gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
+
+	LLMenuGL::sMenuContainer = gMenuHolder;
+
+}
+
+void LLViewerWindow::initWorldUI()
+{
+	S32 height = mRootView->getRect().getHeight();
+	S32 width = mRootView->getRect().getWidth();
+	LLRect full_window(0, height, width, 0);
+
+
+	gIMMgr = LLIMMgr::getInstance();
+
+	//getRootView()->sendChildToFront(gFloaterView);
+	//getRootView()->sendChildToFront(gSnapshotFloaterView);
+
+	// new bottom panel
+	LLPanel* bottom_tray_container = getRootView()->getChild<LLPanel>("bottom_tray_container");
+	LLBottomTray* bottom_tray = LLBottomTray::getInstance();
+	bottom_tray->setShape(bottom_tray_container->getLocalRect());
+	bottom_tray->setFollowsAll();
+	bottom_tray_container->addChild(bottom_tray);
+	bottom_tray_container->setVisible(TRUE);
+
+	LLRect morph_view_rect = full_window;
+	morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
+	morph_view_rect.mTop = full_window.mTop - 32;
+	LLMorphView::Params mvp;
+	mvp.name("MorphView");
+	mvp.rect(morph_view_rect);
+	mvp.visible(false);
+	gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp);
+	getRootView()->addChild(gMorphView);
+
+	LLWorldMapView::initClass();
+	
+	// Force gFloaterWorldMap to initialize
+	LLFloaterReg::getInstance("world_map");
+
+	// Force gFloaterTools to initialize
+	LLFloaterReg::getInstance("build");
+	LLFloaterReg::hideInstance("build");
+
+	// Status bar
+	LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container");
+	gStatusBar = new LLStatusBar(status_bar_container->getLocalRect());
+	gStatusBar->setFollowsAll();
+	gStatusBar->setShape(status_bar_container->getLocalRect());
+	// sync bg color with menu bar
+	gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
+	status_bar_container->addChild(gStatusBar);
+	status_bar_container->setVisible(TRUE);
+
+	// Navigation bar
+	LLPanel* nav_bar_container = getRootView()->getChild<LLPanel>("nav_bar_container");
+
+	LLNavigationBar* navbar = LLNavigationBar::getInstance();
+	navbar->setShape(nav_bar_container->getLocalRect());
+	navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
+	nav_bar_container->addChild(navbar);
+	nav_bar_container->setVisible(TRUE);
+	
+	if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
+	{
+		navbar->showNavigationPanel(FALSE);
+	}
+
+	if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"))
+	{
+		navbar->showFavoritesPanel(FALSE);
+	}
+
+	// Top Info bar
+	LLPanel* topinfo_bar_container = getRootView()->getChild<LLPanel>("topinfo_bar_container");
+	LLPanelTopInfoBar* topinfo_bar = LLPanelTopInfoBar::getInstance();
+
+	topinfo_bar->setShape(topinfo_bar_container->getLocalRect());
+
+	topinfo_bar_container->addChild(topinfo_bar);
+	topinfo_bar_container->setVisible(TRUE);
+
+	if (!gSavedSettings.getBOOL("ShowMiniLocationPanel"))
+	{
+		topinfo_bar->setVisible(FALSE);
+	}
+
+	if ( gHUDView == NULL )
+	{
+		LLRect hud_rect = full_window;
+		hud_rect.mBottom += 50;
+		if (gMenuBarView && gMenuBarView->isInVisibleChain())
+		{
+			hud_rect.mTop -= gMenuBarView->getRect().getHeight();
+		}
+		gHUDView = new LLHUDView(hud_rect);
+		// put behind everything else in the UI
+		getRootView()->addChildInBack(gHUDView);
+	}
+
+	LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("stand_stop_flying_container");
+	LLPanelStandStopFlying* panel_stand_stop_flying	= LLPanelStandStopFlying::getInstance();
+	panel_ssf_container->addChild(panel_stand_stop_flying);
+	panel_ssf_container->setVisible(TRUE);
+
+	// put sidetray in container
+	LLPanel* side_tray_container = getRootView()->getChild<LLPanel>("side_tray_container");
+	LLSideTray* sidetrayp = LLSideTray::getInstance();
+	sidetrayp->setShape(side_tray_container->getLocalRect());
+	// don't follow right edge to avoid spurious resizes, since we are using a fixed width layout
+	sidetrayp->setFollows(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_BOTTOM);
+	side_tray_container->addChild(sidetrayp);
+	side_tray_container->setVisible(FALSE);
+	
+	// put sidetray buttons in their own panel
+	LLPanel* buttons_panel = sidetrayp->getButtonsPanel();
+	LLPanel* buttons_panel_container = getRootView()->getChild<LLPanel>("side_bar_tabs");
+	buttons_panel->setShape(buttons_panel_container->getLocalRect());
+	buttons_panel->setFollowsAll();
+	buttons_panel_container->addChild(buttons_panel);
+
+	LLView* avatar_picker_destination_guide_container = gViewerWindow->getRootView()->getChild<LLView>("avatar_picker_and_destination_guide_container");
+	avatar_picker_destination_guide_container->getChild<LLButton>("close")->setCommitCallback(boost::bind(toggle_destination_and_avatar_picker, LLSD()));
+	LLMediaCtrl* destinations = avatar_picker_destination_guide_container->findChild<LLMediaCtrl>("destination_guide_contents");
+	LLMediaCtrl* avatar_picker = avatar_picker_destination_guide_container->findChild<LLMediaCtrl>("avatar_picker_contents");
+	if (destinations)
+	{
+		destinations->navigateTo(gSavedSettings.getString("DestinationGuideURL"), "text/html");
+	}
+
+	if (avatar_picker)
+	{
+		avatar_picker->navigateTo(gSavedSettings.getString("AvatarPickerURL"), "text/html");
+	}
+
+}
+
+// Destroy the UI
+void LLViewerWindow::shutdownViews()
+{
+	// clean up warning logger
+	LLError::removeRecorder(RecordToChatConsole::getInstance());
+
+	delete mDebugText;
+	mDebugText = NULL;
+	
+	// Cleanup global views
+	if (gMorphView)
+	{
+		gMorphView->setVisible(FALSE);
+	}
+
+	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
+	// will crump with LL_ERRS.
+	LLModalDialog::shutdownModals();
+	
+	// destroy the nav bar, not currently part of gViewerWindow
+	// *TODO: Make LLNavigationBar part of gViewerWindow
+	delete LLNavigationBar::getInstance();
+
+	// destroy menus after instantiating navbar above, as it needs
+	// access to gMenuHolder
+	cleanup_menus();
+
+	// Delete all child views.
+	delete mRootView;
+	mRootView = NULL;
+
+	// Automatically deleted as children of mRootView.  Fix the globals.
+	gStatusBar = NULL;
+	gIMMgr = NULL;
+	gToolTipView = NULL;
+
+	gFloaterView = NULL;
+	gMorphView = NULL;
+
+	gHUDView = NULL;
+}
+
+void LLViewerWindow::shutdownGL()
+{
+	//--------------------------------------------------------
+	// Shutdown GL cleanly.  Order is very important here.
+	//--------------------------------------------------------
+	LLFontGL::destroyDefaultFonts();
+	LLFontManager::cleanupClass();
+	stop_glerror();
+
+	gSky.cleanup();
+	stop_glerror();
+
+	LLWearableList::instance().cleanup() ;
+
+	gTextureList.shutdown();
+	stop_glerror();
+
+	gBumpImageList.shutdown();
+	stop_glerror();
+
+	LLWorldMapView::cleanupTextures();
+
+	llinfos << "Cleaning up pipeline" << llendl;
+	gPipeline.cleanup();
+	stop_glerror();
+
+	LLViewerTextureManager::cleanup() ;
+	LLImageGL::cleanupClass() ;
+
+	llinfos << "All textures and llimagegl images are destroyed!" << llendl ;
+
+	llinfos << "Cleaning up select manager" << llendl;
+	LLSelectMgr::getInstance()->cleanup();
+
+	LLVertexBuffer::cleanupClass();
+
+	llinfos << "Stopping GL during shutdown" << llendl;
+	if (!gNoRender)
+	{
+		stopGL(FALSE);
+		stop_glerror();
+	}
+
+	gGL.shutdown();
+}
+
+// shutdownViews() and shutdownGL() need to be called first
+LLViewerWindow::~LLViewerWindow()
+{
+	llinfos << "Destroying Window" << llendl;
+	destroyWindow();
+
+	delete mDebugText;
+	mDebugText = NULL;
+}
+
+
+void LLViewerWindow::setCursor( ECursorType c )
+{
+	mWindow->setCursor( c );
+}
+
+void LLViewerWindow::showCursor()
+{
+	mWindow->showCursor();
+	
+	mCursorHidden = FALSE;
+}
+
+void LLViewerWindow::hideCursor()
+{
+	// And hide the cursor
+	mWindow->hideCursor();
+
+	mCursorHidden = TRUE;
+}
+
+void LLViewerWindow::sendShapeToSim()
+{
+	LLMessageSystem* msg = gMessageSystem;
+	if(!msg) return;
+	msg->newMessageFast(_PREHASH_AgentHeightWidth);
+	msg->nextBlockFast(_PREHASH_AgentData);
+	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+	msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode);
+	msg->nextBlockFast(_PREHASH_HeightWidthBlock);
+	msg->addU32Fast(_PREHASH_GenCounter, 0);
+	U16 height16 = (U16) mWorldViewRectRaw.getHeight();
+	U16 width16 = (U16) mWorldViewRectRaw.getWidth();
+	msg->addU16Fast(_PREHASH_Height, height16);
+	msg->addU16Fast(_PREHASH_Width, width16);
+	gAgent.sendReliableMessage();
+}
+
+// Must be called after window is created to set up agent
+// camera variables and UI variables.
+void LLViewerWindow::reshape(S32 width, S32 height)
+{
+	// Destroying the window at quit time generates spurious
+	// reshape messages.  We don't care about these, and we
+	// don't want to send messages because the message system
+	// may have been destructed.
+	if (!LLApp::isExiting())
+	{
+		if (gNoRender)
+		{
+			return;
+		}
+
+		gWindowResized = TRUE;
+
+		// update our window rectangle
+		mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width;
+		mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height;
+
+		//glViewport(0, 0, width, height );
+
+		if (height > 0)
+		{ 
+			LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
+			LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
+		}
+
+		calcDisplayScale();
+	
+		BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
+		LLUI::setScaleFactor(mDisplayScale);
+
+		// update our window rectangle
+		mWindowRectScaled.mRight = mWindowRectScaled.mLeft + llround((F32)width / mDisplayScale.mV[VX]);
+		mWindowRectScaled.mTop = mWindowRectScaled.mBottom + llround((F32)height / mDisplayScale.mV[VY]);
+
+		setup2DViewport();
+
+		// Inform lower views of the change
+		// round up when converting coordinates to make sure there are no gaps at edge of window
+		LLView::sForceReshape = display_scale_changed;
+		mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY]));
+		LLView::sForceReshape = FALSE;
+
+		// clear font width caches
+		if (display_scale_changed)
+		{
+			LLHUDObject::reshapeAll();
+		}
+
+		sendShapeToSim();
+
+		// store new settings for the mode we are in, regardless
+		// Only save size if not maximized
+		BOOL maximized = mWindow->getMaximized();
+		gSavedSettings.setBOOL("WindowMaximized", maximized);
+
+		LLCoordScreen window_size;
+		if (!maximized
+			&& mWindow->getSize(&window_size))
+		{
+			gSavedSettings.setS32("WindowWidth", window_size.mX);
+			gSavedSettings.setS32("WindowHeight", window_size.mY);
+		}
+
+		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
+		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
+	}
+}
+
+
+// Hide normal UI when a logon fails
+void LLViewerWindow::setNormalControlsVisible( BOOL visible )
+{
+	if(LLBottomTray::instanceExists())
+	{
+		LLBottomTray::getInstance()->setVisible(visible);
+		LLBottomTray::getInstance()->setEnabled(visible);
+	}
+
+	if ( gMenuBarView )
+	{
+		gMenuBarView->setVisible( visible );
+		gMenuBarView->setEnabled( visible );
+
+		// ...and set the menu color appropriately.
+		setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, 
+			LLGridManager::getInstance()->isInProductionGrid());
+	}
+        
+	if ( gStatusBar )
+	{
+		gStatusBar->setVisible( visible );	
+		gStatusBar->setEnabled( visible );	
+	}
+	
+	LLNavigationBar* navbarp = LLUI::getRootView()->findChild<LLNavigationBar>("navigation_bar");
+	if (navbarp)
+	{
+		navbarp->setVisible( visible );
+	}
+}
+
+void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
+{
+    LLSD args;
+    LLColor4 new_bg_color;
+
+	// no l10n problem because channel is always an english string
+	std::string channel = LLVersionInfo::getChannel();
+	bool isProject = (channel.find("Project") != std::string::npos);
+	
+	// god more important than project, proj more important than grid
+    if(god_mode && LLGridManager::getInstance()->isInProductionGrid())
+    {
+        new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" );
+    }
+    else if(god_mode && !LLGridManager::getInstance()->isInProductionGrid())
+    {
+        new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" );
+    }
+	else if (!god_mode && isProject)
+	{
+		new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" );
+    }
+    else if(!god_mode && !LLGridManager::getInstance()->isInProductionGrid())
+    {
+        new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
+    }
+    else 
+    {
+        new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
+    }
+
+    if(gMenuBarView)
+    {
+        gMenuBarView->setBackgroundColor( new_bg_color );
+    }
+
+    if(gStatusBar)
+    {
+        gStatusBar->setBackgroundColor( new_bg_color );
+    }
+}
+
+void LLViewerWindow::drawDebugText()
+{
+	gGL.color4f(1,1,1,1);
+	gGL.pushMatrix();
+	gGL.pushUIMatrix();
+	{
+		// scale view by UI global scale factor and aspect ratio correction factor
+		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
+		mDebugText->draw();
+	}
+	gGL.popUIMatrix();
+	gGL.popMatrix();
+
+	gGL.flush();
+}
+
+void LLViewerWindow::draw()
+{
+	
+//#if LL_DEBUG
+	LLView::sIsDrawing = TRUE;
+//#endif
+	stop_glerror();
+	
+	LLUI::setLineWidth(1.f);
+
+	LLUI::setLineWidth(1.f);
+	// Reset any left-over transforms
+	glMatrixMode(GL_MODELVIEW);
+	
+	glLoadIdentity();
+
+	//S32 screen_x, screen_y;
+
+	if (!gSavedSettings.getBOOL("RenderUIBuffer"))
+	{
+		LLUI::sDirtyRect = getWindowRectScaled();
+	}
+
+	// HACK for timecode debugging
+	if (gSavedSettings.getBOOL("DisplayTimecode"))
+	{
+		// draw timecode block
+		std::string text;
+
+		glLoadIdentity();
+
+		microsecondsToTimecodeString(gFrameTime,text);
+		const LLFontGL* font = LLFontGL::getFontSansSerif();
+		font->renderUTF8(text, 0,
+						llround((getWindowWidthScaled()/2)-100.f),
+						llround((getWindowHeightScaled()-60.f)),
+			LLColor4( 1.f, 1.f, 1.f, 1.f ),
+			LLFontGL::LEFT, LLFontGL::TOP);
+	}
+
+	// Draw all nested UI views.
+	// No translation needed, this view is glued to 0,0
+
+	gGL.pushMatrix();
+	LLUI::pushMatrix();
+	{
+		
+		// scale view by UI global scale factor and aspect ratio correction factor
+		gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
+
+		LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
+		// apply camera zoom transform (for high res screenshots)
+		F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
+		S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
+		if (zoom_factor > 1.f)
+		{
+			//decompose subregion number to x and y values
+			int pos_y = sub_region / llceil(zoom_factor);
+			int pos_x = sub_region - (pos_y*llceil(zoom_factor));
+			// offset for this tile
+			glTranslatef((F32)getWindowWidthScaled() * -(F32)pos_x, 
+						(F32)getWindowHeightScaled() * -(F32)pos_y, 
+						0.f);
+			glScalef(zoom_factor, zoom_factor, 1.f);
+			LLUI::sGLScaleFactor *= zoom_factor;
+		}
+
+		// Draw tool specific overlay on world
+		LLToolMgr::getInstance()->getCurrentTool()->draw();
+
+		if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() )
+		{
+			drawMouselookInstructions();
+			stop_glerror();
+		}
+
+		// Draw all nested UI views.
+		// No translation needed, this view is glued to 0,0
+		mRootView->draw();
+
+		if (LLView::sDebugRects)
+		{
+			gToolTipView->drawStickyRect();
+		}
+
+		// Draw optional on-top-of-everyone view
+		LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+		if (top_ctrl && top_ctrl->getVisible())
+		{
+			S32 screen_x, screen_y;
+			top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y);
+
+			glMatrixMode(GL_MODELVIEW);
+			LLUI::pushMatrix();
+			LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f);
+			top_ctrl->draw();	
+			LLUI::popMatrix();
+		}
+
+
+		if( gShowOverlayTitle && !mOverlayTitle.empty() )
+		{
+			// Used for special titles such as "Second Life - Special E3 2003 Beta"
+			const S32 DIST_FROM_TOP = 20;
+			LLFontGL::getFontSansSerifBig()->renderUTF8(
+				mOverlayTitle, 0,
+				llround( getWindowWidthScaled() * 0.5f),
+				getWindowHeightScaled() - DIST_FROM_TOP,
+				LLColor4(1, 1, 1, 0.4f),
+				LLFontGL::HCENTER, LLFontGL::TOP);
+		}
+
+		LLUI::sGLScaleFactor = old_scale_factor;
+	}
+	LLUI::popMatrix();
+	gGL.popMatrix();
+
+//#if LL_DEBUG
+	LLView::sIsDrawing = FALSE;
+//#endif
+}
+
+// Takes a single keydown event, usually when UI is visible
+BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
+{
+	// hide tooltips on keypress
+	LLToolTipMgr::instance().blockToolTips();
+
+	if (gFocusMgr.getKeyboardFocus() 
+		&& !(mask & (MASK_CONTROL | MASK_ALT))
+		&& !gFocusMgr.getKeystrokesOnly())
+	{
+		// We have keyboard focus, and it's not an accelerator
+		if (key < 0x80)
+		{
+			// Not a special key, so likely (we hope) to generate a character.  Let it fall through to character handler first.
+			return (gFocusMgr.getKeyboardFocus() != NULL);
+		}
+	}
+
+	// let menus handle navigation keys for navigation
+	if ((gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE))
+		||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE))
+		||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE)))
+	{
+		return TRUE;
+	}
+
+	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+
+	// give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus 
+	// as long as focus isn't locked
+	if (mask & (MASK_CONTROL | MASK_ALT) && !gFocusMgr.focusLocked())
+	{
+		// Check the current floater's menu first, if it has one.
+		if (gFocusMgr.keyboardFocusHasAccelerators()
+			&& keyboard_focus 
+			&& keyboard_focus->handleKey(key,mask,FALSE))
+		{
+			return TRUE;
+		}
+
+		if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
+			||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))
+		{
+			return TRUE;
+		}
+	}
+
+	// give floaters first chance to handle TAB key
+	// so frontmost floater gets focus
+	// if nothing has focus, go to first or last UI element as appropriate
+	if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL))
+	{
+		if (gMenuHolder) gMenuHolder->hideMenus();
+
+		// if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode
+		gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0);
+
+		// do CTRL-TAB and CTRL-SHIFT-TAB logic
+		if (mask & MASK_SHIFT)
+		{
+			mRootView->focusPrevRoot();
+		}
+		else
+		{
+			mRootView->focusNextRoot();
+		}
+		return TRUE;
+	}
+	// hidden edit menu for cut/copy/paste
+	if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask))
+	{
+		return TRUE;
+	}
+
+	// Traverses up the hierarchy
+	if( keyboard_focus )
+	{
+		LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL;
+		// arrow keys move avatar while chatting hack
+		if (chat_editor && chat_editor->hasFocus())
+		{
+			// If text field is empty, there's no point in trying to move
+			// cursor with arrow keys, so allow movement
+			if (chat_editor->getText().empty() 
+				|| gSavedSettings.getBOOL("ArrowKeysAlwaysMove"))
+			{
+				// let Control-Up and Control-Down through for chat line history,
+				if (!(key == KEY_UP && mask == MASK_CONTROL)
+					&& !(key == KEY_DOWN && mask == MASK_CONTROL))
+				{
+					switch(key)
+					{
+					case KEY_LEFT:
+					case KEY_RIGHT:
+					case KEY_UP:
+					case KEY_DOWN:
+					case KEY_PAGE_UP:
+					case KEY_PAGE_DOWN:
+					case KEY_HOME:
+						// when chatbar is empty or ArrowKeysAlwaysMove set,
+						// pass arrow keys on to avatar...
+						return FALSE;
+					default:
+						break;
+					}
+				}
+			}
+		}
+
+		if (keyboard_focus->handleKey(key, mask, FALSE))
+		{
+			return TRUE;
+		}
+	}
+
+	if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) )
+	{
+		return TRUE;
+	}
+
+	// Try for a new-format gesture
+	if (LLGestureMgr::instance().triggerGesture(key, mask))
+	{
+		return TRUE;
+	}
+
+	// See if this is a gesture trigger.  If so, eat the key and
+	// don't pass it down to the menus.
+	if (gGestureList.trigger(key, mask))
+	{
+		return TRUE;
+	}
+
+	// If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, 
+	// no view has keyboard focus, this is a printable character key (and no modifier key is 
+	// pressed except shift), then give focus to nearby chat (STORM-560)
+	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && 
+		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
+	{
+		LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL;
+		if (chat_editor)
+		{
+			// passing NULL here, character will be added later when it is handled by character handler.
+			LLBottomTray::getInstance()->getNearbyChatBar()->startChat(NULL);
+			return TRUE;
+		}
+	}
+
+	// give menus a chance to handle unmodified accelerator keys
+	if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
+		||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)))
+	{
+		return TRUE;
+	}
+
+	// don't pass keys on to world when something in ui has focus
+	return gFocusMgr.childHasKeyboardFocus(mRootView) 
+		|| LLMenuGL::getKeyboardMode() 
+		|| (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive());
+}
+
+
+BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
+{
+	// HACK:  We delay processing of return keys until they arrive as a Unicode char,
+	// so that if you're typing chat text at low frame rate, we don't send the chat
+	// until all keystrokes have been entered. JC
+	// HACK: Numeric keypad <enter> on Mac is Unicode 3
+	// HACK: Control-M on Windows is Unicode 13
+	if ((uni_char == 13 && mask != MASK_CONTROL)
+		|| (uni_char == 3 && mask == MASK_NONE))
+	{
+		return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
+	}
+
+	// let menus handle navigation (jump) keys
+	if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, TRUE))
+	{
+		return TRUE;
+	}
+
+	// Traverses up the hierarchy
+	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+	if( keyboard_focus )
+	{
+		if (keyboard_focus->handleUnicodeChar(uni_char, FALSE))
+		{
+			return TRUE;
+		}
+
+		//// Topmost view gets a chance before the hierarchy
+		//LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+		//if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) )
+		//{
+		//	return TRUE;
+		//}
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+void LLViewerWindow::handleScrollWheel(S32 clicks)
+{
+	LLView::sMouseHandlerMessage.clear();
+
+	LLUI::resetMouseIdleTimer();
+	
+	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+	if( mouse_captor )
+	{
+		S32 local_x;
+		S32 local_y;
+		mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
+		mouse_captor->handleScrollWheel(local_x, local_y, clicks);
+		if (LLView::sDebugMouseHandling)
+		{
+			llinfos << "Scroll Wheel handled by captor " << mouse_captor->getName() << llendl;
+		}
+		return;
+	}
+
+	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+	if (top_ctrl)
+	{
+		S32 local_x;
+		S32 local_y;
+		top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
+		if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return;
+	}
+
+	if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) )
+	{
+		if (LLView::sDebugMouseHandling)
+		{
+			llinfos << "Scroll Wheel" << LLView::sMouseHandlerMessage << llendl;
+		}
+		return;
+	}
+	else if (LLView::sDebugMouseHandling)
+	{
+		llinfos << "Scroll Wheel not handled by view" << llendl;
+	}
+
+	// Zoom the camera in and out behavior
+
+	if(top_ctrl == 0 
+		&& getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) 
+		&& gAgentCamera.isInitialized())
+		gAgentCamera.handleScrollWheel(clicks);
+
+	return;
+}
+
+void LLViewerWindow::addPopup(LLView* popup)
+{
+	if (mPopupView)
+	{
+		mPopupView->addPopup(popup);
+	}
+}
+
+void LLViewerWindow::removePopup(LLView* popup)
+{
+	if (mPopupView)
+	{
+		mPopupView->removePopup(popup);
+	}
+}
+
+void LLViewerWindow::clearPopups()
+{
+	if (mPopupView)
+	{
+		mPopupView->clearPopups();
+	}
+}
+
+void LLViewerWindow::moveCursorToCenter()
+{
+	if (! gSavedSettings.getBOOL("DisableMouseWarp"))
+	{
+		S32 x = getWorldViewWidthScaled() / 2;
+		S32 y = getWorldViewHeightScaled() / 2;
+	
+		//on a forced move, all deltas get zeroed out to prevent jumping
+		mCurrentMousePoint.set(x,y);
+		mLastMousePoint.set(x,y);
+		mCurrentMouseDelta.set(0,0);	
+
+		LLUI::setMousePositionScreen(x, y);	
+	}
+}
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// Hover handlers
+//
+
+void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
+{
+	if (viewp) 
+	{
+		if (!params.styled_message.empty())
+		{
+			params.styled_message.add().text("\n---------\n"); 
+		}
+		LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView();
+		// NOTE: we skip "root" since it is assumed
+		for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView();
+			tooltip_it != end_tooltip_it;
+			++tooltip_it)
+		{
+			LLView* viewp = *tooltip_it;
+		
+			params.styled_message.add().text(viewp->getName());
+
+			LLPanel* panelp = dynamic_cast<LLPanel*>(viewp);
+			if (panelp && !panelp->getXMLFilename().empty())
+			{
+				params.styled_message.add()
+					.text("(" + panelp->getXMLFilename() + ")")
+					.style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f));
+			}
+			params.styled_message.add().text("/");
+		}
+	}
+}
+
+// Update UI based on stored mouse position from mouse-move
+// event processing.
+void LLViewerWindow::updateUI()
+{
+	static LLFastTimer::DeclareTimer ftm("Update UI");
+	LLFastTimer t(ftm);
+
+	static std::string last_handle_msg;
+
+	if (gLoggedInTime.getStarted())
+	{
+		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout"))
+		{
+			LLFirstUse::notUsingDestinationGuide();
+		}
+		if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout"))
+		{
+			LLFirstUse::notUsingSidePanel();
+		}
+	}
+
+	LLConsole::updateClass();
+
+	// animate layout stacks so we have up to date rect for world view
+	LLLayoutStack::updateClass();
+
+	// use full window for world view when not rendering UI
+	bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+	updateWorldViewRect(world_view_uses_full_window);
+
+	LLView::sMouseHandlerMessage.clear();
+
+	S32 x = mCurrentMousePoint.mX;
+	S32 y = mCurrentMousePoint.mY;
+	MASK mask = gKeyboard->currentMask(TRUE);
+
+	if (gNoRender)
+	{
+		return;
+	}
+
+	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
+	{
+		gDebugRaycastFaceHit = -1;
+		gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
+											  &gDebugRaycastFaceHit,
+											  &gDebugRaycastIntersection,
+											  &gDebugRaycastTexCoord,
+											  &gDebugRaycastNormal,
+											  &gDebugRaycastBinormal);
+	}
+
+	updateMouseDelta();
+	updateKeyboardFocus();
+
+	BOOL handled = FALSE;
+
+	BOOL handled_by_top_ctrl = FALSE;
+	LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
+	LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+	LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
+
+	//FIXME: only include captor and captor's ancestors if mouse is truly over them --RN
+
+	//build set of views containing mouse cursor by traversing UI hierarchy and testing 
+	//screen rect against mouse cursor
+	view_handle_set_t mouse_hover_set;
+
+	// constraint mouse enter events to children of mouse captor
+	LLView* root_view = captor_view;
+
+	// if mouse captor doesn't exist or isn't a LLView
+	// then allow mouse enter events on entire UI hierarchy
+	if (!root_view)
+	{
+		root_view = mRootView;
+	}
+
+	// only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI
+	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		// include all ancestors of captor_view as automatically having mouse
+		if (captor_view)
+		{
+			LLView* captor_parent_view = captor_view->getParent();
+			while(captor_parent_view)
+			{
+				mouse_hover_set.insert(captor_parent_view->getHandle());
+				captor_parent_view = captor_parent_view->getParent();
+			}
+		}
+
+		// aggregate visible views that contain mouse cursor in display order
+		LLPopupView::popup_list_t popups = mPopupView->getCurrentPopups();
+
+		for(LLPopupView::popup_list_t::iterator popup_it = popups.begin(); popup_it != popups.end(); ++popup_it)
+		{
+			LLView* popup = popup_it->get();
+			if (popup && popup->calcScreenBoundingRect().pointInRect(x, y))
+			{
+				// iterator over contents of top_ctrl, and throw into mouse_hover_set
+				for (LLView::tree_iterator_t it = popup->beginTreeDFS();
+					it != popup->endTreeDFS();
+					++it)
+				{
+					LLView* viewp = *it;
+					if (viewp->getVisible()
+						&& viewp->calcScreenBoundingRect().pointInRect(x, y))
+					{
+						// we have a view that contains the mouse, add it to the set
+						mouse_hover_set.insert(viewp->getHandle());
+					}
+					else
+					{
+						// skip this view and all of its children
+						it.skipDescendants();
+					}
+				}
+			}
+		}
+
+		// while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events
+		if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y))
+		{
+			// iterator over contents of top_ctrl, and throw into mouse_hover_set
+			for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS();
+				it != top_ctrl->endTreeDFS();
+				++it)
+			{
+				LLView* viewp = *it;
+				if (viewp->getVisible()
+					&& viewp->calcScreenBoundingRect().pointInRect(x, y))
+				{
+					// we have a view that contains the mouse, add it to the set
+					mouse_hover_set.insert(viewp->getHandle());
+				}
+				else
+				{
+					// skip this view and all of its children
+					it.skipDescendants();
+				}
+			}
+		}
+		else
+		{
+			// walk UI tree in depth-first order
+			for (LLView::tree_iterator_t it = root_view->beginTreeDFS();
+				it != root_view->endTreeDFS();
+				++it)
+			{
+				LLView* viewp = *it;
+				// calculating the screen rect involves traversing the parent, so this is less than optimal
+				if (viewp->getVisible()
+					&& viewp->calcScreenBoundingRect().pointInRect(x, y))
+				{
+
+					// if this view is mouse opaque, nothing behind it should be in mouse_hover_set
+					if (viewp->getMouseOpaque())
+					{
+						// constrain further iteration to children of this widget
+						it = viewp->beginTreeDFS();
+					}
+		
+					// we have a view that contains the mouse, add it to the set
+					mouse_hover_set.insert(viewp->getHandle());
+				}
+				else
+				{
+					// skip this view and all of its children
+					it.skipDescendants();
+				}
+			}
+		}
+	}
+
+	typedef std::vector<LLHandle<LLView> > view_handle_list_t;
+
+	// call onMouseEnter() on all views which contain the mouse cursor but did not before
+	view_handle_list_t mouse_enter_views;
+	std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(),
+						mMouseHoverViews.begin(), mMouseHoverViews.end(),
+						std::back_inserter(mouse_enter_views));
+	for (view_handle_list_t::iterator it = mouse_enter_views.begin();
+		it != mouse_enter_views.end();
+		++it)
+	{
+		LLView* viewp = it->get();
+		if (viewp)
+		{
+			LLRect view_screen_rect = viewp->calcScreenRect();
+			viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
+		}
+	}
+
+	// call onMouseLeave() on all views which no longer contain the mouse cursor
+	view_handle_list_t mouse_leave_views;
+	std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(),
+						mouse_hover_set.begin(), mouse_hover_set.end(),
+						std::back_inserter(mouse_leave_views));
+	for (view_handle_list_t::iterator it = mouse_leave_views.begin();
+		it != mouse_leave_views.end();
+		++it)
+	{
+		LLView* viewp = it->get();
+		if (viewp)
+		{
+			LLRect view_screen_rect = viewp->calcScreenRect();
+			viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
+		}
+	}
+
+	// store resulting hover set for next frame
+	swap(mMouseHoverViews, mouse_hover_set);
+
+	// only handle hover events when UI is enabled
+	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{	
+
+		if( mouse_captor )
+		{
+			// Pass hover events to object capturing mouse events.
+			S32 local_x;
+			S32 local_y; 
+			mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
+			handled = mouse_captor->handleHover(local_x, local_y, mask);
+			if (LLView::sDebugMouseHandling)
+			{
+				llinfos << "Hover handled by captor " << mouse_captor->getName() << llendl;
+			}
+
+			if( !handled )
+			{
+				lldebugst(LLERR_USER_INPUT) << "hover not handled by mouse captor" << llendl;
+			}
+		}
+		else
+		{
+			if (top_ctrl)
+			{
+				S32 local_x, local_y;
+				top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
+				handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
+				handled_by_top_ctrl = TRUE;
+			}
+
+			if ( !handled )
+			{
+				// x and y are from last time mouse was in window
+				// mMouseInWindow tracks *actual* mouse location
+				if (mMouseInWindow && mRootView->handleHover(x, y, mask) )
+				{
+					if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg)
+					{
+						last_handle_msg = LLView::sMouseHandlerMessage;
+						llinfos << "Hover" << LLView::sMouseHandlerMessage << llendl;
+					}
+					handled = TRUE;
+				}
+				else if (LLView::sDebugMouseHandling)
+				{
+					if (last_handle_msg != LLStringUtil::null)
+					{
+						last_handle_msg.clear();
+						llinfos << "Hover not handled by view" << llendl;
+					}
+				}
+			}
+		
+			if (!handled)
+			{
+				LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
+
+				if(mMouseInWindow && tool)
+				{
+					handled = tool->handleHover(x, y, mask);
+				}
+			}
+		}
+
+		// Show a new tool tip (or update one that is already shown)
+		BOOL tool_tip_handled = FALSE;
+		std::string tool_tip_msg;
+		if( handled 
+			&& !mWindow->isCursorHidden())
+		{
+			LLRect screen_sticky_rect = mRootView->getLocalRect();
+			S32 local_x, local_y;
+
+			if (gSavedSettings.getBOOL("DebugShowXUINames"))
+			{
+				LLToolTip::Params params;
+
+				LLView* tooltip_view = mRootView;
+				LLView::tree_iterator_t end_it = mRootView->endTreeDFS();
+				for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it)
+				{
+					LLView* viewp = *it;
+					LLRect screen_rect;
+					viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
+					if (!(viewp->getVisible()
+						 && screen_rect.pointInRect(x, y)))
+					{
+						it.skipDescendants();
+					}
+					// only report xui names for LLUICtrls, 
+					// and blacklist the various containers we don't care about
+					else if (dynamic_cast<LLUICtrl*>(viewp) 
+							&& viewp != gMenuHolder
+							&& viewp != gFloaterView
+							&& viewp != gConsole) 
+					{
+						if (dynamic_cast<LLFloater*>(viewp))
+						{
+							// constrain search to descendants of this (frontmost) floater
+							// by resetting iterator
+							it = viewp->beginTreeDFS();
+						}
+
+						// if we are in a new part of the tree (not a descendent of current tooltip_view)
+						// then push the results for tooltip_view and start with a new potential view
+						// NOTE: this emulates visiting only the leaf nodes that meet our criteria
+						if (!viewp->hasAncestor(tooltip_view))
+						{
+							append_xui_tooltip(tooltip_view, params);
+							screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
+						}
+						tooltip_view = viewp;
+					}
+				}
+
+				append_xui_tooltip(tooltip_view, params);
+				screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
+				
+				params.sticky_rect = screen_sticky_rect;
+				params.max_width = 400;
+
+				LLToolTipMgr::instance().show(params);
+			}
+			// if there is a mouse captor, nothing else gets a tooltip
+			else if (mouse_captor)
+			{
+				mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
+				tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask);
+			}
+			else 
+			{
+				// next is top_ctrl
+				if (!tool_tip_handled && top_ctrl)
+				{
+					top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
+					tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask );
+				}
+				
+				if (!tool_tip_handled)
+				{
+					local_x = x; local_y = y;
+					tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask );
+				}
+
+				LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
+				if (!tool_tip_handled && current_tool)
+				{
+					current_tool->screenPointToLocal(x, y, &local_x, &local_y);
+					tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask );
+				}
+			}
+		}		
+	}
+	else
+	{	// just have tools handle hover when UI is turned off
+		LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
+
+		if(mMouseInWindow && tool)
+		{
+			handled = tool->handleHover(x, y, mask);
+		}
+	}
+
+	updateLayout();
+
+	mLastMousePoint = mCurrentMousePoint;
+
+	// cleanup unused selections when no modal dialogs are open
+	if (LLModalDialog::activeCount() == 0)
+	{
+		LLViewerParcelMgr::getInstance()->deselectUnused();
+	}
+
+	if (LLModalDialog::activeCount() == 0)
+	{
+		LLSelectMgr::getInstance()->deselectUnused();
+	}
+}
+
+
+void LLViewerWindow::updateLayout()
+{
+	LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
+	if (gFloaterTools != NULL
+		&& tool != NULL
+		&& tool != gToolNull  
+		&& tool != LLToolCompInspect::getInstance() 
+		&& tool != LLToolDragAndDrop::getInstance() 
+		&& !gSavedSettings.getBOOL("FreezeTime"))
+	{ 
+		// Suppress the toolbox view if our source tool was the pie tool,
+		// and we've overridden to something else.
+		bool suppress_toolbox = 
+			(LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
+			(LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
+
+		LLMouseHandler *captor = gFocusMgr.getMouseCapture();
+		// With the null, inspect, or drag and drop tool, don't muck
+		// with visibility.
+
+		if (gFloaterTools->isMinimized()
+			||	(tool != LLToolPie::getInstance()						// not default tool
+				&& tool != LLToolCompGun::getInstance()					// not coming out of mouselook
+				&& !suppress_toolbox									// not override in third person
+				&& LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset	// not special mode
+				&& LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
+				&& (!captor || dynamic_cast<LLView*>(captor) != NULL)))						// not dragging
+		{
+			// Force floater tools to be visible (unless minimized)
+			if (!gFloaterTools->getVisible())
+			{
+				gFloaterTools->openFloater();
+			}
+			// Update the location of the blue box tool popup
+			LLCoordGL select_center_screen;
+			gFloaterTools->updatePopup( select_center_screen, gKeyboard->currentMask(TRUE) );
+		}
+		else
+		{
+			gFloaterTools->setVisible(FALSE);
+		}
+		//gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
+	}
+
+	// Always update console
+	if(gConsole)
+	{
+		LLRect console_rect = getChatConsoleRect();
+		gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
+		gConsole->setRect(console_rect);
+	}
+}
+
+void LLViewerWindow::updateMouseDelta()
+{
+	S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
+	S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
+
+	//RN: fix for asynchronous notification of mouse leaving window not working
+	LLCoordWindow mouse_pos;
+	mWindow->getCursorPosition(&mouse_pos);
+	if (mouse_pos.mX < 0 || 
+		mouse_pos.mY < 0 ||
+		mouse_pos.mX > mWindowRectRaw.getWidth() ||
+		mouse_pos.mY > mWindowRectRaw.getHeight())
+	{
+		mMouseInWindow = FALSE;
+	}
+	else
+	{
+		mMouseInWindow = TRUE;
+	}
+
+	LLVector2 mouse_vel; 
+
+	if (gSavedSettings.getBOOL("MouseSmooth"))
+	{
+		static F32 fdx = 0.f;
+		static F32 fdy = 0.f;
+
+		F32 amount = 16.f;
+		fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
+		fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
+
+		mCurrentMouseDelta.set(llround(fdx), llround(fdy));
+		mouse_vel.setVec(fdx,fdy);
+	}
+	else
+	{
+		mCurrentMouseDelta.set(dx, dy);
+		mouse_vel.setVec((F32) dx, (F32) dy);
+	}
+    
+	mMouseVelocityStat.addValue(mouse_vel.magVec());
+}
+
+void LLViewerWindow::updateKeyboardFocus()
+{
+	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		gFocusMgr.setKeyboardFocus(NULL);
+	}
+
+	// clean up current focus
+	LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
+	if (cur_focus)
+	{
+		if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
+		{
+            // don't release focus, just reassign so that if being given
+            // to a sibling won't call onFocusLost on all the ancestors
+			// gFocusMgr.releaseFocusIfNeeded(cur_focus);
+
+			LLUICtrl* parent = cur_focus->getParentUICtrl();
+			const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
+			bool new_focus_found = false;
+			while(parent)
+			{
+				if (parent->isCtrl() 
+					&& (parent->hasTabStop() || parent == focus_root) 
+					&& !parent->getIsChrome() 
+					&& parent->isInVisibleChain() 
+					&& parent->isInEnabledChain())
+				{
+					if (!parent->focusFirstItem())
+					{
+						parent->setFocus(TRUE);
+					}
+					new_focus_found = true;
+					break;
+				}
+				parent = parent->getParentUICtrl();
+			}
+
+			// if we didn't find a better place to put focus, just release it
+			// hasFocus() will return true if and only if we didn't touch focus since we
+			// are only moving focus higher in the hierarchy
+			if (!new_focus_found)
+			{
+				cur_focus->setFocus(FALSE);
+			}
+		}
+		else if (cur_focus->isFocusRoot())
+		{
+			// focus roots keep trying to delegate focus to their first valid descendant
+			// this assumes that focus roots are not valid focus holders on their own
+			cur_focus->focusFirstItem();
+		}
+	}
+
+	// last ditch force of edit menu to selection manager
+	if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
+	{
+		LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance();
+	}
+
+	if (gFloaterView->getCycleMode())
+	{
+		// sync all floaters with their focus state
+		gFloaterView->highlightFocusedFloater();
+		gSnapshotFloaterView->highlightFocusedFloater();
+		if ((gKeyboard->currentMask(TRUE) & MASK_CONTROL) == 0)
+		{
+			// control key no longer held down, finish cycle mode
+			gFloaterView->setCycleMode(FALSE);
+
+			gFloaterView->syncFloaterTabOrder();
+		}
+		else
+		{
+			// user holding down CTRL, don't update tab order of floaters
+		}
+	}
+	else
+	{
+		// update focused floater
+		gFloaterView->highlightFocusedFloater();
+		gSnapshotFloaterView->highlightFocusedFloater();
+		// make sure floater visible order is in sync with tab order
+		gFloaterView->syncFloaterTabOrder();
+	}
+
+	if(LLSideTray::instanceCreated())//just getInstance will create sidetray. we don't want this
+		LLSideTray::getInstance()->highlightFocused();
+}
+
+static LLFastTimer::DeclareTimer FTM_UPDATE_WORLD_VIEW("Update World View");
+void LLViewerWindow::updateWorldViewRect(bool use_full_window)
+{
+	LLFastTimer ft(FTM_UPDATE_WORLD_VIEW);
+
+	// start off using whole window to render world
+	LLRect new_world_rect = mWindowRectRaw;
+
+	if (use_full_window == false && mWorldViewPlaceholder.get())
+	{
+		new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect();
+		// clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers
+		new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1);
+		new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1);
+
+		new_world_rect.mLeft = llround((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]);
+		new_world_rect.mRight = llround((F32)new_world_rect.mRight * mDisplayScale.mV[VX]);
+		new_world_rect.mBottom = llround((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]);
+		new_world_rect.mTop = llround((F32)new_world_rect.mTop * mDisplayScale.mV[VY]);
+	}
+
+	if (gSavedSettings.getBOOL("SidebarCameraMovement") == FALSE)
+	{
+		// use right edge of window, ignoring sidebar
+		new_world_rect.mRight = mWindowRectRaw.mRight;
+	}
+
+	if (mWorldViewRectRaw != new_world_rect)
+	{
+		mWorldViewRectRaw = new_world_rect;
+		gResizeScreenTexture = TRUE;
+		LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
+		LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
+
+		LLRect old_world_rect_scaled = mWorldViewRectScaled;
+		mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
+
+		// sending a signal with a new WorldView rect
+		mOnWorldViewRectUpdated(old_world_rect_scaled, mWorldViewRectScaled);
+	}
+}
+
+void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
+{
+	// Store last mouse location.
+	// If mouse leaves window, pretend last point was on edge of window
+	if (point.mX < 0)
+	{
+		mCurrentMousePoint.mX = 0;
+	}
+	else if (point.mX > getWindowWidthScaled())
+	{
+		mCurrentMousePoint.mX = getWindowWidthScaled();
+	}
+	else
+	{
+		mCurrentMousePoint.mX = point.mX;
+	}
+
+	if (point.mY < 0)
+	{
+		mCurrentMousePoint.mY = 0;
+	}
+	else if (point.mY > getWindowHeightScaled() )
+	{
+		mCurrentMousePoint.mY = getWindowHeightScaled();
+	}
+	else
+	{
+		mCurrentMousePoint.mY = point.mY;
+	}
+}
+
+
+// Draws the selection outlines for the currently selected objects
+// Must be called after displayObjects is called, which sets the mGLName parameter
+// NOTE: This function gets called 3 times:
+//  render_ui_3d: 			FALSE, FALSE, TRUE
+//  render_hud_elements:	FALSE, FALSE, FALSE
+void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
+{
+	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+
+	if (!for_hud && !for_gl_pick)
+	{
+		// Call this once and only once
+		LLSelectMgr::getInstance()->updateSilhouettes();
+	}
+	
+	// Draw fence around land selections
+	if (for_gl_pick)
+	{
+		if (pick_parcel_walls)
+		{
+			LLViewerParcelMgr::getInstance()->renderParcelCollision();
+		}
+	}
+	else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) ||
+			 (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD))
+	{		
+		LLSelectMgr::getInstance()->renderSilhouettes(for_hud);
+		
+		stop_glerror();
+
+		// setup HUD render
+		if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
+		{
+			LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
+
+			// set up transform to encompass bounding box of HUD
+			glMatrixMode(GL_PROJECTION);
+			glPushMatrix();
+			glLoadIdentity();
+			F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
+			glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
+			
+			glMatrixMode(GL_MODELVIEW);
+			glPushMatrix();
+			glLoadIdentity();
+			glLoadMatrixf(OGL_TO_CFR_ROTATION);		// Load Cory's favorite reference frame
+			glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
+		}
+
+		// Render light for editing
+		if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit())
+		{
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			LLGLEnable gls_blend(GL_BLEND);
+			LLGLEnable gls_cull(GL_CULL_FACE);
+			LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+			glMatrixMode(GL_MODELVIEW);
+			glPushMatrix();
+			if (selection->getSelectType() == SELECT_TYPE_HUD)
+			{
+				F32 zoom = gAgentCamera.mHUDCurZoom;
+				glScalef(zoom, zoom, zoom);
+			}
+
+			struct f : public LLSelectedObjectFunctor
+			{
+				virtual bool apply(LLViewerObject* object)
+				{
+					LLDrawable* drawable = object->mDrawable;
+					if (drawable && drawable->isLight())
+					{
+						LLVOVolume* vovolume = drawable->getVOVolume();
+						glPushMatrix();
+
+						LLVector3 center = drawable->getPositionAgent();
+						glTranslatef(center[0], center[1], center[2]);
+						F32 scale = vovolume->getLightRadius();
+						glScalef(scale, scale, scale);
+
+						LLColor4 color(vovolume->getLightColor(), .5f);
+						glColor4fv(color.mV);
+					
+						F32 pixel_area = 100000.f;
+						// Render Outside
+						gSphere.render(pixel_area);
+
+						// Render Inside
+						glCullFace(GL_FRONT);
+						gSphere.render(pixel_area);
+						glCullFace(GL_BACK);
+					
+						glPopMatrix();
+					}
+					return true;
+				}
+			} func;
+			LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
+			
+			glPopMatrix();
+		}				
+		
+		// NOTE: The average position for the axis arrows of the selected objects should
+		// 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 = LLToolMgr::getInstance()->getCurrentTool();
+		if (tool)
+		{
+			if(tool->isAlwaysRendered())
+			{
+				tool->render();
+			}
+			else
+			{
+				if( !LLSelectMgr::getInstance()->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("EditLinkedParts");
+
+					for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
+						 iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
+					{
+						LLSelectNode* nodep = *iter;
+						LLViewerObject* object = nodep->getObject();
+						BOOL this_object_movable = FALSE;
+						if (object->permMove() && (object->permModify() || selecting_linked_set))
+						{
+							moveable_object_selected = TRUE;
+							this_object_movable = TRUE;
+						}
+						all_selected_objects_move = all_selected_objects_move && this_object_movable;
+						all_selected_objects_modify = all_selected_objects_modify && object->permModify();
+					}
+
+					BOOL draw_handles = TRUE;
+
+					if (tool == LLToolCompTranslate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
+					{
+						draw_handles = FALSE;
+					}
+
+					if (tool == LLToolCompRotate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
+					{
+						draw_handles = FALSE;
+					}
+
+					if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() )
+					{
+						draw_handles = FALSE;
+					}
+				
+					if( draw_handles )
+					{
+						tool->render();
+					}
+				}
+			}
+			if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount())
+			{
+				glMatrixMode(GL_PROJECTION);
+				glPopMatrix();
+
+				glMatrixMode(GL_MODELVIEW);
+				glPopMatrix();
+				stop_glerror();
+			}
+		}
+	}
+}
+
+// Return a point near the clicked object representative of the place the object was clicked.
+LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot, LLViewerObject* clicked_object) const
+{
+	// create a normalized vector pointing from the camera center into the 
+	// world at the location of the mouse click
+	LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot );
+
+	LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgentCamera.getCameraPositionGlobal();
+
+	// make mouse vector as long as object vector, so it touchs a point near
+	// where the user clicked on the object
+	mouse_direction_global *= (F32) relative_object.magVec();
+
+	LLVector3d new_pos;
+	new_pos.setVec(mouse_direction_global);
+	// transform mouse vector back to world coords
+	new_pos += gAgentCamera.getCameraPositionGlobal();
+
+	return new_pos;
+}
+
+
+BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const
+{
+	BOOL intersect = FALSE;
+
+//	U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK;
+	if (!intersect)
+	{
+		point_global = clickPointInWorldGlobal(x, y, objectp);
+		llinfos << "approx intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
+	}
+	else
+	{
+		llinfos << "good intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
+	}
+
+	return intersect;
+}
+
+void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent)
+{
+	if (gNoRender)
+	{
+		return;
+	}
+	
+	BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
+	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
+	{
+		// build mode allows interaction with all transparent objects
+		// "Show Debug Alpha" means no object actually transparent
+		pick_transparent = TRUE;
+	}
+
+	LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback);
+	schedulePick(pick_info);
+}
+
+void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
+{
+	if (mPicks.size() >= 1024 || mWindow->getMinimized())
+	{ //something went wrong, picks are being scheduled but not processed
+		
+		if (pick_info.mPickCallback)
+		{
+			pick_info.mPickCallback(pick_info);
+		}
+	
+		return;
+	}
+	mPicks.push_back(pick_info);
+	
+	// delay further event processing until we receive results of pick
+	// only do this for async picks so that handleMouseUp won't be called
+	// until the pick triggered in handleMouseDown has been processed, for example
+	mWindow->delayInputProcessing();
+}
+
+
+void LLViewerWindow::performPick()
+{
+	if (gNoRender)
+	{
+		return;
+	}
+
+	if (!mPicks.empty())
+	{
+		std::vector<LLPickInfo>::iterator pick_it;
+		for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
+		{
+			pick_it->fetchResults();
+		}
+
+		mLastPick = mPicks.back();
+		mPicks.clear();
+	}
+}
+
+void LLViewerWindow::returnEmptyPicks()
+{
+	std::vector<LLPickInfo>::iterator pick_it;
+	for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
+	{
+		mLastPick = *pick_it;
+		// just trigger callback with empty results
+		if (pick_it->mPickCallback)
+		{
+			pick_it->mPickCallback(*pick_it);
+		}
+	}
+	mPicks.clear();
+}
+
+// Performs the GL object/land pick.
+LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot,  BOOL pick_transparent)
+{
+	if (gNoRender)
+	{
+		return LLPickInfo();
+	}
+
+	BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
+	if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
+	{
+		// build mode allows interaction with all transparent objects
+		// "Show Debug Alpha" means no object actually transparent
+		pick_transparent = TRUE;
+	}
+
+	// shortcut queueing in mPicks and just update mLastPick in place
+	mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), gKeyboard->currentMask(TRUE), pick_transparent, TRUE, NULL);
+	mLastPick.fetchResults();
+
+	return mLastPick;
+}
+
+LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
+										   LLVector3* intersection)
+{
+	S32 x = mouse_x;
+	S32 y = mouse_y;
+
+	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
+	{
+		x = getCurrentMouseX();
+		y = getCurrentMouseY();
+	}
+
+	// world coordinates of mouse
+	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
+	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
+	LLVector3 mouse_world_start = mouse_point_global;
+	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
+
+	return LLHUDIcon::lineSegmentIntersectAll(mouse_world_start, mouse_world_end, intersection);
+
+	
+}
+
+LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
+												LLViewerObject *this_object,
+												S32 this_face,
+												BOOL pick_transparent,
+												S32* face_hit,
+												LLVector3 *intersection,
+												LLVector2 *uv,
+												LLVector3 *normal,
+												LLVector3 *binormal)
+{
+	S32 x = mouse_x;
+	S32 y = mouse_y;
+
+	if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
+	{
+		x = getCurrentMouseX();
+		y = getCurrentMouseY();
+	}
+
+	// HUD coordinates of mouse
+	LLVector3 mouse_point_hud = mousePointHUD(x, y);
+	LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
+	LLVector3 mouse_hud_end   = mouse_point_hud + LLVector3(depth, 0, 0);
+	
+	// world coordinates of mouse
+	LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
+	LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
+	
+	//get near clip plane
+	LLVector3 n = LLViewerCamera::getInstance()->getAtAxis();
+	LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear();
+
+	//project mouse point onto plane
+	LLVector3 pos;
+	line_plane(mouse_point_global, mouse_direction_global, p, n, pos);
+	mouse_point_global = pos;
+
+	LLVector3 mouse_world_start = mouse_point_global;
+	LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
+
+	
+	LLViewerObject* found = NULL;
+
+	if (this_object)  // check only this object
+	{
+		if (this_object->isHUDAttachment()) // is a HUD object?
+		{
+			if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face, pick_transparent,
+												  face_hit, intersection, uv, normal, binormal))
+			{
+				found = this_object;
+			}
+			}
+		
+		else // is a world object
+		{
+			if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, pick_transparent,
+												  face_hit, intersection, uv, normal, binormal))
+			{
+				found = this_object;
+			}
+			}
+			}
+
+	else // check ALL objects
+			{
+		found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, pick_transparent,
+													face_hit, intersection, uv, normal, binormal);
+
+		if (!found) // if not found in HUD, look in world:
+
+			{
+			found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, pick_transparent,
+														  face_hit, intersection, uv, normal, binormal);
+			}
+
+	}
+
+	return found;
+}
+
+// Returns unit vector relative to camera
+// indicating direction of point on screen x,y
+LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
+{
+	// find vertical field of view
+	F32			fov = LLViewerCamera::getInstance()->getView();
+
+	// find world view center in scaled ui coordinates
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
+
+	// calculate pixel distance to screen
+	F32			distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f));
+
+	// calculate click point relative to middle of screen
+	F32			click_x = x - center_x;
+	F32			click_y = y - center_y;
+
+	// compute mouse vector
+	LLVector3	mouse_vector =	distance * LLViewerCamera::getInstance()->getAtAxis()
+								- click_x * LLViewerCamera::getInstance()->getLeftAxis()
+								+ click_y * LLViewerCamera::getInstance()->getUpAxis();
+
+	mouse_vector.normVec();
+
+	return mouse_vector;
+}
+
+LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
+{
+	// find screen resolution
+	S32			height = getWorldViewHeightScaled();
+
+	// find world view center
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
+
+	// remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
+	F32 hud_x = -((F32)x - center_x)  / height;
+	F32 hud_y = ((F32)y - center_y) / height;
+
+	return LLVector3(0.f, hud_x/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.mHUDCurZoom);
+}
+
+// Returns unit vector relative to camera in camera space
+// indicating direction of point on screen x,y
+LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
+{
+	// find vertical field of view
+	F32			fov_height = LLViewerCamera::getInstance()->getView();
+	F32			fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
+
+	// find screen resolution
+	S32			height = getWorldViewHeightScaled();
+	S32			width = getWorldViewWidthScaled();
+
+	// find world view center
+	F32			center_x = getWorldViewRectScaled().getCenterX();
+	F32			center_y = getWorldViewRectScaled().getCenterY();
+
+	// calculate click point relative to middle of screen
+	F32			click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f;
+	F32			click_y = (((F32)y - center_y) / (F32)height) * fov_height;
+
+	// compute mouse vector
+	LLVector3	mouse_vector =	LLVector3(0.f, 0.f, -1.f);
+	LLQuaternion mouse_rotate;
+	mouse_rotate.setQuat(click_y, click_x, 0.f);
+
+	mouse_vector = mouse_vector * mouse_rotate;
+	// project to z = -1 plane;
+	mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]);
+
+	return mouse_vector;
+}
+
+
+
+BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, 
+										const LLVector3d &plane_point_global, 
+										const LLVector3 &plane_normal_global)
+{
+	LLVector3d	mouse_direction_global_d;
+
+	mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y));
+	LLVector3d	plane_normal_global_d;
+	plane_normal_global_d.setVec(plane_normal_global);
+	F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d);
+	LLVector3d plane_origin_camera_rel = plane_point_global - gAgentCamera.getCameraPositionGlobal();
+	F64	mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel)
+								/ plane_mouse_dot;
+	if (llabs(plane_mouse_dot) < 0.00001)
+	{
+		// if mouse is parallel to plane, return closest point on line through plane origin
+		// that is parallel to camera plane by scaling mouse direction vector
+		// by distance to plane origin, modulated by deviation of mouse direction from plane origin
+		LLVector3d plane_origin_dir = plane_origin_camera_rel;
+		plane_origin_dir.normVec();
+		
+		mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d);
+	}
+
+	point = gAgentCamera.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d;
+
+	return mouse_look_at_scale > 0.0;
+}
+
+
+// Returns global position
+BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global)
+{
+	LLVector3		mouse_direction_global = mouseDirectionGlobal(x,y);
+	F32				mouse_dir_scale;
+	BOOL			hit_land = FALSE;
+	LLViewerRegion	*regionp;
+	F32			land_z;
+	const F32	FIRST_PASS_STEP = 1.0f;		// meters
+	const F32	SECOND_PASS_STEP = 0.1f;	// meters
+	LLVector3d	camera_pos_global;
+
+	camera_pos_global = gAgentCamera.getCameraPositionGlobal();
+	LLVector3d		probe_point_global;
+	LLVector3		probe_point_region;
+
+	// walk forwards to find the point
+	for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < gAgentCamera.mDrawDistance; mouse_dir_scale += FIRST_PASS_STEP)
+	{
+		LLVector3d mouse_direction_global_d;
+		mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
+		probe_point_global = camera_pos_global + mouse_direction_global_d;
+
+		regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
+
+		if (!regionp)
+		{
+			// ...we're outside the world somehow
+			continue;
+		}
+
+		S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid());
+		S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid());
+		S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge;
+		if ((i >= grids_per_edge) || (j >= grids_per_edge))
+		{
+			//llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
+			continue;
+		}
+
+		land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
+
+		//llinfos << "mousePointOnLand initial z " << land_z << llendl;
+
+		if (probe_point_region.mV[VZ] < land_z)
+		{
+			// ...just went under land
+
+			// cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl;
+
+			hit_land = TRUE;
+			break;
+		}
+	}
+
+
+	if (hit_land)
+	{
+		// Don't go more than one step beyond where we stopped above.
+		// This can't just be "mouse_vec_scale" because floating point error
+		// will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X
+		F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP;
+
+		// take a step backwards, then walk forwards again to refine position
+		for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP)
+		{
+			LLVector3d mouse_direction_global_d;
+			mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
+			probe_point_global = camera_pos_global + mouse_direction_global_d;
+
+			regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
+
+			if (!regionp)
+			{
+				// ...we're outside the world somehow
+				continue;
+			}
+
+			/*
+			i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid());
+			j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid());
+			if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge))
+			{
+				// llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
+				continue;
+			}
+			land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ];
+			*/
+
+			land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
+
+			//llinfos << "mousePointOnLand refine z " << land_z << llendl;
+
+			if (probe_point_region.mV[VZ] < land_z)
+			{
+				// ...just went under land again
+
+				*land_position_global = probe_point_global;
+				return TRUE;
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+// Saves an image to the harddrive as "SnapshotX" where X >= 1.
+BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image)
+{
+	if (!image)
+	{
+		return FALSE;
+	}
+
+	LLFilePicker::ESaveFilter pick_type;
+	std::string extension("." + image->getExtension());
+	if (extension == ".j2c")
+		pick_type = LLFilePicker::FFSAVE_J2C;
+	else if (extension == ".bmp")
+		pick_type = LLFilePicker::FFSAVE_BMP;
+	else if (extension == ".jpg")
+		pick_type = LLFilePicker::FFSAVE_JPEG;
+	else if (extension == ".png")
+		pick_type = LLFilePicker::FFSAVE_PNG;
+	else if (extension == ".tga")
+		pick_type = LLFilePicker::FFSAVE_TGA;
+	else
+		pick_type = LLFilePicker::FFSAVE_ALL; // ???
+	
+	// Get a base file location if needed.
+	if ( ! isSnapshotLocSet())		
+	{
+		std::string proposed_name( sSnapshotBaseName );
+
+		// getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in.
+
+		// pick a directory in which to save
+		LLFilePicker& picker = LLFilePicker::instance();
+		if (!picker.getSaveFile(pick_type, proposed_name))
+		{
+			// Clicked cancel
+			return FALSE;
+		}
+
+		// Copy the directory + file name
+		std::string filepath = picker.getFirstFile();
+
+		LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true);
+		LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath);
+	}
+
+	// Look for an unused file name
+	std::string filepath;
+	S32 i = 1;
+	S32 err = 0;
+
+	do
+	{
+		filepath = sSnapshotDir;
+		filepath += gDirUtilp->getDirDelimiter();
+		filepath += sSnapshotBaseName;
+		filepath += llformat("_%.3d",i);
+		filepath += extension;
+
+		llstat stat_info;
+		err = LLFile::stat( filepath, &stat_info );
+		i++;
+	}
+	while( -1 != err );  // search until the file is not found (i.e., stat() gives an error).
+
+	return image->save(filepath);
+}
+
+void LLViewerWindow::resetSnapshotLoc()
+{
+	sSnapshotDir.clear();
+}
+
+static S32 BORDERHEIGHT = 0;
+static S32 BORDERWIDTH = 0;
+
+// static
+void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
+{
+	LLCoordScreen size;
+	gViewerWindow->mWindow->getSize(&size);
+	if (  (size.mX != new_width + BORDERWIDTH)
+		||(size.mY != new_height + BORDERHEIGHT))
+	{
+		// use actual display dimensions, not virtual UI dimensions
+		S32 x = gViewerWindow->getWindowWidthRaw();
+		S32 y = gViewerWindow->getWindowHeightRaw();
+		BORDERWIDTH = size.mX - x;
+		BORDERHEIGHT = size.mY- y;
+		LLCoordScreen new_size(new_width + BORDERWIDTH, 
+							   new_height + BORDERHEIGHT);
+		gViewerWindow->mWindow->setSize(new_size);
+	}
+}
+
+BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+{
+	llinfos << "Saving snapshot to: " << filepath << llendl;
+
+	LLPointer<LLImageRaw> raw = new LLImageRaw;
+	BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
+
+	if (success)
+	{
+		LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
+		success = bmp_image->encode(raw, 0.0f);
+		if( success )
+		{
+			success = bmp_image->save(filepath);
+		}
+		else
+		{
+			llwarns << "Unable to encode bmp snapshot" << llendl;
+		}
+	}
+	else
+	{
+		llwarns << "Unable to capture raw snapshot" << llendl;
+	}
+
+	return success;
+}
+
+
+void LLViewerWindow::playSnapshotAnimAndSound()
+{
+	if (gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
+	{
+		return;
+	}
+	gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START);
+	send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
+}
+
+BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
+{
+	return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
+}
+
+// Saves the image from the screen to the specified filename and path.
+BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, 
+								 BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
+{
+	if (!raw)
+	{
+		return FALSE;
+	}
+
+	// PRE SNAPSHOT
+	gDisplaySwapBuffers = FALSE;
+	
+	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+	setCursor(UI_CURSOR_WAIT);
+
+	// Hide all the UI widgets first and draw a frame
+	BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
+
+	show_ui = show_ui ? TRUE : FALSE;
+
+	if ( prev_draw_ui != show_ui)
+	{
+		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
+	}
+
+	BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
+	if (hide_hud)
+	{
+		LLPipeline::sShowHUDAttachments = FALSE;
+	}
+
+	// if not showing ui, use full window to render world view
+	updateWorldViewRect(!show_ui);
+
+	// Copy screen to a buffer
+	// crop sides or top and bottom, if taking a snapshot of different aspect ratio
+	// from window
+	LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); 
+
+	S32 snapshot_width = window_rect.getWidth();
+	S32 snapshot_height = window_rect.getHeight();
+	// SNAPSHOT
+	S32 window_width = snapshot_width;
+	S32 window_height = snapshot_height;
+	
+	if (show_ui)
+	{
+		image_width = llmin(image_width, window_width);
+		image_height = llmin(image_height, window_height);
+	}
+
+	F32 scale_factor = 1.0f ;
+	if(!keep_window_aspect) //image cropping
+	{		
+		F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
+		snapshot_width = (S32)(ratio * image_width) ;
+		snapshot_height = (S32)(ratio * image_height) ;
+		scale_factor = llmax(1.0f, 1.0f / ratio) ;
+	}
+	else //the scene(window) proportion needs to be maintained.
+	{
+		if(image_width > window_width || image_height > window_height) //need to enlarge the scene
+		{
+			F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
+			snapshot_width = (S32)(ratio * image_width) ;
+			snapshot_height = (S32)(ratio * image_height) ;
+			scale_factor = llmax(1.0f, 1.0f / ratio) ;	
+		}
+	}
+	
+	if (show_ui && scale_factor > 1.f)
+	{
+		llwarns << "over scaling UI not supported." << llendl;
+	}
+
+	S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f);
+	S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
+
+	S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ;
+	S32 image_buffer_y = llfloor(snapshot_height *scale_factor) ;
+
+	if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow
+	{
+		scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
+		image_buffer_x = llfloor(snapshot_width*scale_factor) ;
+		image_buffer_y = llfloor(snapshot_height *scale_factor) ;
+	}
+	if(image_buffer_x > 0 && image_buffer_y > 0)
+	{
+		raw->resize(image_buffer_x, image_buffer_y, 3);
+	}
+	else
+	{
+		return FALSE ;
+	}
+	if(raw->isBufferInvalid())
+	{
+		return FALSE ;
+	}
+
+	BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher
+	if (high_res && show_ui)
+	{
+		llwarns << "High res UI snapshot not supported. " << llendl;
+		/*send_agent_pause();
+		//rescale fonts
+		initFonts(scale_factor);
+		LLHUDObject::reshapeAll();*/
+	}
+
+	S32 output_buffer_offset_y = 0;
+
+	F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
+	F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
+
+	gObjectList.generatePickList(*LLViewerCamera::getInstance());
+
+	for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
+	{
+		S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
+		// handle fractional columns
+		U32 read_height = llmax(0, (window_height - subimage_y_offset) -
+			llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight())));
+
+		S32 output_buffer_offset_x = 0;
+		for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x)
+		{
+			gDisplaySwapBuffers = FALSE;
+			gDepthDirty = TRUE;
+
+			const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
+
+			if (LLPipeline::sRenderDeferred)
+			{
+					display(do_rebuild, scale_factor, subfield, TRUE);
+			}
+			else
+			{
+				display(do_rebuild, scale_factor, subfield, TRUE);
+					// Required for showing the GUI in snapshots and performing bloom composite overlay
+					// Call even if show_ui is FALSE
+				render_ui(scale_factor, subfield);
+			}
+
+			S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
+			// handle fractional rows
+			U32 read_width = llmax(0, (window_width - subimage_x_offset) -
+									llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth())));
+			for(U32 out_y = 0; out_y < read_height ; out_y++)
+			{
+				S32 output_buffer_offset = ( 
+							(out_y * (raw->getWidth())) // ...plus iterated y...
+							+ (window_width * subimage_x) // ...plus subimage start in x...
+							+ (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y...
+							- output_buffer_offset_x // ...minus buffer padding x...
+							- (output_buffer_offset_y * (raw->getWidth()))  // ...minus buffer padding y...
+						) * raw->getComponents();
+				
+				// Ping the wathdog thread every 100 lines to keep us alive (arbitrary number, feel free to change)
+				if (out_y % 100 == 0)
+				{
+					LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
+				}
+				
+				if (type == SNAPSHOT_TYPE_COLOR)
+				{
+					glReadPixels(
+						subimage_x_offset, out_y + subimage_y_offset,
+						read_width, 1,
+						GL_RGB, GL_UNSIGNED_BYTE,
+						raw->getData() + output_buffer_offset
+					);
+				}
+				else // SNAPSHOT_TYPE_DEPTH
+				{
+					LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values
+					glReadPixels(
+						subimage_x_offset, out_y + subimage_y_offset,
+						read_width, 1,
+						GL_DEPTH_COMPONENT, GL_FLOAT,
+						depth_line_buffer->getData()// current output pixel is beginning of buffer...
+					);
+
+					for (S32 i = 0; i < (S32)read_width; i++)
+					{
+						F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32)));
+					
+						F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2));
+						U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar());
+						//write converted scanline out to result image
+						for(S32 j = 0; j < raw->getComponents(); j++)
+						{
+							*(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte;
+						}
+					}
+				}
+			}
+			output_buffer_offset_x += subimage_x_offset;
+			stop_glerror();
+		}
+		output_buffer_offset_y += subimage_y_offset;
+	}
+
+	gDisplaySwapBuffers = FALSE;
+	gDepthDirty = TRUE;
+
+	// POST SNAPSHOT
+	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
+	}
+
+	if (hide_hud)
+	{
+		LLPipeline::sShowHUDAttachments = TRUE;
+	}
+
+	/*if (high_res)
+	{
+		initFonts(1.f);
+		LLHUDObject::reshapeAll();
+	}*/
+
+	// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
+	// Note: this formula depends on the number of components being 3.  Not obvious, but it's correct.	
+	image_width += (image_width * 3) % 4;
+
+	BOOL ret = TRUE ;
+	// Resize image
+	if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
+	{
+		ret = raw->scale( image_width, image_height );  
+	}
+	else if(image_width != image_buffer_x || image_height != image_buffer_y)
+	{
+		ret = raw->scale( image_width, image_height, FALSE );  
+	}
+	
+
+	setCursor(UI_CURSOR_ARROW);
+
+	if (do_rebuild)
+	{
+		// If we had to do a rebuild, that means that the lists of drawables to be rendered
+		// was empty before we started.
+		// Need to reset these, otherwise we call state sort on it again when render gets called the next time
+		// and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
+		// objects on them.
+		gPipeline.resetDrawOrders();
+	}
+
+	if (high_res)
+	{
+		send_agent_resume();
+	}
+
+	return ret;
+}
+
+void LLViewerWindow::destroyWindow()
+{
+	if (mWindow)
+	{
+		LLWindowManager::destroyWindow(mWindow);
+	}
+	mWindow = NULL;
+}
+
+
+void LLViewerWindow::drawMouselookInstructions()
+{
+	// Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.)
+	const std::string instructions = LLTrans::getString("LeaveMouselook");
+	const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD));
+	
+	//to be on top of Bottom bar when it is opened
+	const S32 INSTRUCTIONS_PAD = 50;
+
+	font->renderUTF8( 
+		instructions, 0,
+		getWorldViewRectScaled().getCenterX(),
+		getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD,
+		LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
+		LLFontGL::HCENTER, LLFontGL::TOP,
+		LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
+}
+
+void* LLViewerWindow::getPlatformWindow() const
+{
+	return mWindow->getPlatformWindow();
+}
+
+void* LLViewerWindow::getMediaWindow() 	const
+{
+	return mWindow->getMediaWindow();
+}
+
+void LLViewerWindow::focusClient()		const
+{
+	return mWindow->focusClient();
+}
+
+LLRootView*	LLViewerWindow::getRootView() const
+{
+	return mRootView;
+}
+
+LLRect LLViewerWindow::getWorldViewRectScaled() const
+{
+	return mWorldViewRectScaled;
+}
+
+S32 LLViewerWindow::getWorldViewHeightScaled() const
+{
+	return mWorldViewRectScaled.getHeight();
+}
+
+S32 LLViewerWindow::getWorldViewWidthScaled() const
+{
+	return mWorldViewRectScaled.getWidth();
+}
+
+
+S32 LLViewerWindow::getWorldViewHeightRaw() const
+{
+	return mWorldViewRectRaw.getHeight(); 
+}
+
+S32 LLViewerWindow::getWorldViewWidthRaw() const
+{
+	return mWorldViewRectRaw.getWidth(); 
+}
+
+S32	LLViewerWindow::getWindowHeightScaled()	const 	
+{ 
+	return mWindowRectScaled.getHeight(); 
+}
+
+S32	LLViewerWindow::getWindowWidthScaled() const 	
+{ 
+	return mWindowRectScaled.getWidth(); 
+}
+
+S32	LLViewerWindow::getWindowHeightRaw()	const 	
+{ 
+	return mWindowRectRaw.getHeight(); 
+}
+
+S32	LLViewerWindow::getWindowWidthRaw() const 	
+{ 
+	return mWindowRectRaw.getWidth(); 
+}
+
+void LLViewerWindow::setup2DRender()
+{
+	// setup ortho camera
+	gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight());
+	setup2DViewport();
+}
+
+void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset)
+{
+	gGLViewport[0] = mWindowRectRaw.mLeft + x_offset;
+	gGLViewport[1] = mWindowRectRaw.mBottom + y_offset;
+	gGLViewport[2] = mWindowRectRaw.getWidth();
+	gGLViewport[3] = mWindowRectRaw.getHeight();
+	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+}
+
+
+void LLViewerWindow::setup3DRender()
+{
+	// setup perspective camera
+	LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom,  mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
+	setup3DViewport();
+}
+
+void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
+{
+	gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
+	gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
+	gGLViewport[2] = mWorldViewRectRaw.getWidth();
+	gGLViewport[3] = mWorldViewRectRaw.getHeight();
+	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+}
+
+void LLViewerWindow::setShowProgress(const BOOL show)
+{
+	if (mProgressView)
+	{
+		mProgressView->setVisible(show);
+	}
+}
+
+BOOL LLViewerWindow::getShowProgress() const
+{
+	return (mProgressView && mProgressView->getVisible());
+}
+
+void LLViewerWindow::setProgressString(const std::string& string)
+{
+	if (mProgressView)
+	{
+		mProgressView->setText(string);
+	}
+}
+
+void LLViewerWindow::setProgressMessage(const std::string& msg)
+{
+	if(mProgressView)
+	{
+		mProgressView->setMessage(msg);
+	}
+}
+
+void LLViewerWindow::setProgressPercent(const F32 percent)
+{
+	if (mProgressView)
+	{
+		mProgressView->setPercent(percent);
+	}
+}
+
+void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& label )
+{
+	if (mProgressView)
+	{
+		mProgressView->setCancelButtonVisible( b, label );
+	}
+}
+
+
+LLProgressView *LLViewerWindow::getProgressView() const
+{
+	return mProgressView;
+}
+
+void LLViewerWindow::dumpState()
+{
+	llinfos << "LLViewerWindow Active " << S32(mActive) << llendl;
+	llinfos << "mWindow visible " << S32(mWindow->getVisible())
+		<< " minimized " << S32(mWindow->getMinimized())
+		<< llendl;
+}
+
+void LLViewerWindow::stopGL(BOOL save_state)
+{
+	//Note: --bao
+	//if not necessary, do not change the order of the function calls in this function.
+	//if change something, make sure it will not break anything.
+	//especially be careful to put anything behind gTextureList.destroyGL(save_state);
+	if (!gGLManager.mIsDisabled)
+	{
+		llinfos << "Shutting down GL..." << llendl;
+
+		// Pause texture decode threads (will get unpaused during main loop)
+		LLAppViewer::getTextureCache()->pause();
+		LLAppViewer::getImageDecodeThread()->pause();
+		LLAppViewer::getTextureFetch()->pause();
+				
+		gSky.destroyGL();
+		stop_glerror();		
+
+		LLManipTranslate::destroyGL() ;
+		stop_glerror();		
+
+		gBumpImageList.destroyGL();
+		stop_glerror();
+
+		LLFontGL::destroyAllGL();
+		stop_glerror();
+
+		LLVOAvatar::destroyGL();
+		stop_glerror();
+
+		LLViewerDynamicTexture::destroyGL();
+		stop_glerror();
+
+		if (gPipeline.isInit())
+		{
+			gPipeline.destroyGL();
+		}
+		
+		gCone.cleanupGL();
+		gBox.cleanupGL();
+		gSphere.cleanupGL();
+		gCylinder.cleanupGL();
+		
+		if(gPostProcess)
+		{
+			gPostProcess->invalidate();
+		}
+
+		gTextureList.destroyGL(save_state);
+		stop_glerror();
+		
+		gGLManager.mIsDisabled = TRUE;
+		stop_glerror();
+		
+		llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << llendl;
+	}
+}
+
+void LLViewerWindow::restoreGL(const std::string& progress_message)
+{
+	//Note: --bao
+	//if not necessary, do not change the order of the function calls in this function.
+	//if change something, make sure it will not break anything. 
+	//especially, be careful to put something before gTextureList.restoreGL();
+	if (gGLManager.mIsDisabled)
+	{
+		llinfos << "Restoring GL..." << llendl;
+		gGLManager.mIsDisabled = FALSE;
+		
+		initGLDefaults();
+		LLGLState::restoreGL();
+		
+		gTextureList.restoreGL();
+		
+		// for future support of non-square pixels, and fonts that are properly stretched
+		//LLFontGL::destroyDefaultFonts();
+		initFonts();
+				
+		gSky.restoreGL();
+		gPipeline.restoreGL();
+		LLDrawPoolWater::restoreGL();
+		LLManipTranslate::restoreGL();
+		
+		gBumpImageList.restoreGL();
+		LLViewerDynamicTexture::restoreGL();
+		LLVOAvatar::restoreGL();
+		
+		gResizeScreenTexture = TRUE;
+		gWindowResized = TRUE;
+
+		if (isAgentAvatarValid() && !gAgentAvatarp->isUsingBakedTextures())
+		{
+			LLVisualParamHint::requestHintUpdates();
+		}
+
+		if (!progress_message.empty())
+		{
+			gRestoreGLTimer.reset();
+			gRestoreGL = TRUE;
+			setShowProgress(TRUE);
+			setProgressString(progress_message);
+		}
+		llinfos << "...Restoring GL done" << llendl;
+		if(!LLAppViewer::instance()->restoreErrorTrap())
+		{
+			llwarns << " Someone took over my signal/exception handler (post restoreGL)!" << llendl;
+		}
+
+	}
+}
+
+void LLViewerWindow::initFonts(F32 zoom_factor)
+{
+	LLFontGL::destroyAllGL();
+	// Initialize with possibly different zoom factor
+	LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
+								mDisplayScale.mV[VX] * zoom_factor,
+								mDisplayScale.mV[VY] * zoom_factor,
+								gDirUtilp->getAppRODataDir(),
+								LLUI::getXUIPaths());
+	// Force font reloads, which can be very slow
+	LLFontGL::loadDefaultFonts();
+}
+
+void LLViewerWindow::requestResolutionUpdate()
+{
+	mResDirty = true;
+}
+
+void LLViewerWindow::checkSettings()
+{
+	if (mStatesDirty)
+	{
+		gGL.refreshState();
+		LLViewerShaderMgr::instance()->setShaders();
+		mStatesDirty = false;
+	}
+	
+	// We want to update the resolution AFTER the states getting refreshed not before.
+	if (mResDirty)
+	{
+		reshape(getWindowWidthRaw(), getWindowHeightRaw());
+		mResDirty = false;
+	}	
+}
+
+void LLViewerWindow::restartDisplay(BOOL show_progress_bar)
+{
+	llinfos << "Restaring GL" << llendl;
+	stopGL();
+	if (show_progress_bar)
+	{
+		restoreGL(LLTrans::getString("ProgressChangingResolution"));
+	}
+	else
+	{
+		restoreGL();
+	}
+}
+
+BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar)
+{
+	//BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
+
+	//gResizeScreenTexture = TRUE;
+
+	//U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
+	//U32 old_fsaa = mWindow->getFSAASamples();
+
+	// if not maximized, use the request size
+	if (!mWindow->getMaximized())
+	{
+		mWindow->setSize(size);
+	}
+
+	//if (fsaa == old_fsaa)
+	{
+		return TRUE;
+	}
+
+/*
+
+	// Close floaters that don't handle settings change
+	LLFloaterReg::hideInstance("snapshot");
+	
+	BOOL result_first_try = FALSE;
+	BOOL result_second_try = FALSE;
+
+	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
+	send_agent_pause();
+	llinfos << "Stopping GL during changeDisplaySettings" << llendl;
+	stopGL();
+	mIgnoreActivate = TRUE;
+	LLCoordScreen old_size;
+	LLCoordScreen old_pos;
+	mWindow->getSize(&old_size);
+
+	//mWindow->setFSAASamples(fsaa);
+
+	result_first_try = mWindow->switchContext(false, size, disable_vsync);
+	if (!result_first_try)
+	{
+		// try to switch back
+		//mWindow->setFSAASamples(old_fsaa);
+		result_second_try = mWindow->switchContext(false, old_size, disable_vsync);
+
+		if (!result_second_try)
+		{
+			// we are stuck...try once again with a minimal resolution?
+			send_agent_resume();
+			mIgnoreActivate = FALSE;
+			return FALSE;
+		}
+	}
+	send_agent_resume();
+
+	llinfos << "Restoring GL during resolution change" << llendl;
+	if (show_progress_bar)
+	{
+		restoreGL(LLTrans::getString("ProgressChangingResolution"));
+	}
+	else
+	{
+		restoreGL();
+	}
+
+	if (!result_first_try)
+	{
+		LLSD args;
+		args["RESX"] = llformat("%d",size.mX);
+		args["RESY"] = llformat("%d",size.mY);
+		LLNotificationsUtil::add("ResolutionSwitchFail", args);
+		size = old_size; // for reshape below
+	}
+
+	BOOL success = result_first_try || result_second_try;
+
+	if (success)
+	{
+		// maximize window if was maximized, else reposition
+		if (was_maximized)
+		{
+			mWindow->maximize();
+		}
+		else
+		{
+			S32 windowX = gSavedSettings.getS32("WindowX");
+			S32 windowY = gSavedSettings.getS32("WindowY");
+
+			mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
+		}
+	}
+
+	mIgnoreActivate = FALSE;
+	gFocusMgr.setKeyboardFocus(keyboard_focus);
+	
+	return success;
+
+	*/
+}
+
+F32	LLViewerWindow::getWorldViewAspectRatio() const
+{
+	F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();
+	return world_aspect;
+}
+
+void LLViewerWindow::calcDisplayScale()
+{
+	F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
+	LLVector2 display_scale;
+	display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
+	display_scale *= ui_scale_factor;
+
+	// limit minimum display scale
+	if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE)
+	{
+		display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]);
+	}
+	
+	if (display_scale != mDisplayScale)
+	{
+		llinfos << "Setting display scale to " << display_scale << llendl;
+
+		mDisplayScale = display_scale;
+		// Init default fonts
+		initFonts();
+	}
+}
+
+//static
+LLRect 	LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale)
+{
+	LLRect res = rect;
+	res.mLeft = llround((F32)res.mLeft / display_scale.mV[VX]);
+	res.mRight = llround((F32)res.mRight / display_scale.mV[VX]);
+	res.mBottom = llround((F32)res.mBottom / display_scale.mV[VY]);
+	res.mTop = llround((F32)res.mTop / display_scale.mV[VY]);
+
+	return res;
+}
+
+S32 LLViewerWindow::getChatConsoleBottomPad()
+{
+	S32 offset = 0;
+
+	if(LLBottomTray::instanceExists())
+		offset += LLBottomTray::getInstance()->getRect().getHeight();
+
+	return offset;
+}
+
+LLRect LLViewerWindow::getChatConsoleRect()
+{
+	LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0);
+	LLRect console_rect = full_window;
+
+	const S32 CONSOLE_PADDING_TOP = 24;
+	const S32 CONSOLE_PADDING_LEFT = 24;
+	const S32 CONSOLE_PADDING_RIGHT = 10;
+
+	console_rect.mTop    -= CONSOLE_PADDING_TOP;
+	console_rect.mBottom += getChatConsoleBottomPad();
+
+	console_rect.mLeft   += CONSOLE_PADDING_LEFT; 
+
+	static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth");
+
+	if (CHAT_FULL_WIDTH)
+	{
+		console_rect.mRight -= CONSOLE_PADDING_RIGHT;
+	}
+	else
+	{
+		// Make console rect somewhat narrow so having inventory open is
+		// less of a problem.
+		console_rect.mRight  = console_rect.mLeft + 2 * getWindowWidthScaled() / 3;
+	}
+
+	return console_rect;
+}
+//----------------------------------------------------------------------------
+
+
+//static 
+bool LLViewerWindow::onAlert(const LLSD& notify)
+{
+	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
+
+	if (gNoRender)
+	{
+		llinfos << "Alert: " << notification->getName() << llendl;
+		notification->respond(LLSD::emptyMap());
+		LLNotifications::instance().cancel(notification);
+		return false;
+	}
+
+	// If we're in mouselook, the mouse is hidden and so the user can't click 
+	// the dialog buttons.  In that case, change to First Person instead.
+	if( gAgentCamera.cameraMouselook() )
+	{
+		gAgentCamera.changeCameraToDefault();
+	}
+	return false;
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// LLPickInfo
+//
+LLPickInfo::LLPickInfo()
+	: mKeyMask(MASK_NONE),
+	  mPickCallback(NULL),
+	  mPickType(PICK_INVALID),
+	  mWantSurfaceInfo(FALSE),
+	  mObjectFace(-1),
+	  mUVCoords(-1.f, -1.f),
+	  mSTCoords(-1.f, -1.f),
+	  mXYCoords(-1, -1),
+	  mIntersection(),
+	  mNormal(),
+	  mBinormal(),
+	  mHUDIcon(NULL),
+	  mPickTransparent(FALSE)
+{
+}
+
+LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, 
+		       MASK keyboard_mask, 
+		       BOOL pick_transparent,
+		       BOOL pick_uv_coords,
+		       void (*pick_callback)(const LLPickInfo& pick_info))
+	: mMousePt(mouse_pos),
+	  mKeyMask(keyboard_mask),
+	  mPickCallback(pick_callback),
+	  mPickType(PICK_INVALID),
+	  mWantSurfaceInfo(pick_uv_coords),
+	  mObjectFace(-1),
+	  mUVCoords(-1.f, -1.f),
+	  mSTCoords(-1.f, -1.f),
+	  mXYCoords(-1, -1),
+	  mNormal(),
+	  mBinormal(),
+	  mHUDIcon(NULL),
+	  mPickTransparent(pick_transparent)
+{
+}
+
+void LLPickInfo::fetchResults()
+{
+
+	S32 face_hit = -1;
+	LLVector3 intersection, normal, binormal;
+	LLVector2 uv;
+
+	LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection);
+	
+	F32 icon_dist = 0.f;
+	if (hit_icon)
+	{
+		icon_dist = (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec();
+	}
+	LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
+									NULL, -1, mPickTransparent, &face_hit,
+									&intersection, &uv, &normal, &binormal);
+	
+	mPickPt = mMousePt;
+
+	U32 te_offset = face_hit > -1 ? face_hit : 0;
+
+	//unproject relative clicked coordinate from window coordinate using GL
+	
+	LLViewerObject* objectp = hit_object;
+
+	if (hit_icon && 
+		(!objectp || 
+		icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
+	{
+		// was this name referring to a hud icon?
+		mHUDIcon = hit_icon;
+		mPickType = PICK_ICON;
+		mPosGlobal = mHUDIcon->getPositionGlobal();
+	}
+	else if (objectp)
+	{
+		if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
+		{
+			// Hit land
+			mPickType = PICK_LAND;
+			mObjectID.setNull(); // land has no id
+
+			// put global position into land_pos
+			LLVector3d land_pos;
+			if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos))
+			{
+				// The selected point is beyond the draw distance or is otherwise 
+				// not selectable. Return before calling mPickCallback().
+				return;
+			}
+
+			// Fudge the land focus a little bit above ground.
+			mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
+		}
+		else
+		{
+			if(isFlora(objectp))
+			{
+				mPickType = PICK_FLORA;
+			}
+			else
+			{
+				mPickType = PICK_OBJECT;
+			}
+			mObjectOffset = gAgentCamera.calcFocusOffset(objectp, intersection, mPickPt.mX, mPickPt.mY);
+			mObjectID = objectp->mID;
+			mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
+
+			mPosGlobal = gAgent.getPosGlobalFromAgent(intersection);
+			
+			if (mWantSurfaceInfo)
+			{
+				getSurfaceInfo();
+			}
+		}
+	}
+	
+	if (mPickCallback)
+	{
+		mPickCallback(*this);
+	}
+}
+
+LLPointer<LLViewerObject> LLPickInfo::getObject() const
+{
+	return gObjectList.findObject( mObjectID );
+}
+
+void LLPickInfo::updateXYCoords()
+{
+	if (mObjectFace > -1)
+	{
+		const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
+		LLPointer<LLViewerTexture> imagep = LLViewerTextureManager::getFetchedTexture(tep->getID());
+		if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
+		{
+			mXYCoords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
+			mXYCoords.mY = llround((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight());
+		}
+	}
+}
+
+void LLPickInfo::getSurfaceInfo()
+{
+	// set values to uninitialized - this is what we return if no intersection is found
+	mObjectFace   = -1;
+	mUVCoords     = LLVector2(-1, -1);
+	mSTCoords     = LLVector2(-1, -1);
+	mXYCoords	  = LLCoordScreen(-1, -1);
+	mIntersection = LLVector3(0,0,0);
+	mNormal       = LLVector3(0,0,0);
+	mBinormal     = LLVector3(0,0,0);
+	
+	LLViewerObject* objectp = getObject();
+
+	if (objectp)
+	{
+		if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f,
+										   objectp, -1, mPickTransparent,
+										   &mObjectFace,
+										   &mIntersection,
+										   &mSTCoords,
+										   &mNormal,
+										   &mBinormal))
+		{
+			// if we succeeded with the intersect above, compute the texture coordinates:
+
+			if (objectp->mDrawable.notNull() && mObjectFace > -1)
+			{
+				LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
+
+				mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal);
+			}
+
+			// and XY coords:
+			updateXYCoords();
+			
+		}
+	}
+}
+
+
+/* code to get UV via a special UV render - removed in lieu of raycast method
+LLVector2 LLPickInfo::pickUV()
+{
+	LLVector2 result(-1.f, -1.f);
+
+	LLViewerObject* objectp = getObject();
+	if (!objectp)
+	{
+		return result;
+	}
+
+	if (mObjectFace > -1 &&
+		objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
+		mObjectFace < objectp->mDrawable->getNumFaces())
+	{
+		S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]);
+		S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]);
+		const S32 UV_PICK_WIDTH = 5;
+		const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
+		U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
+		LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
+		if (facep)
+		{
+			LLGLState scissor_state(GL_SCISSOR_TEST);
+			scissor_state.enable();
+			LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
+			//glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
+			glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
+
+			glClear(GL_DEPTH_BUFFER_BIT);
+
+			facep->renderSelectedUV();
+
+			glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
+			U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
+
+			result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
+			result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
+		}
+	}
+
+	return result;
+} */
+
+
+//static 
+bool LLPickInfo::isFlora(LLViewerObject* object)
+{
+	if (!object) return false;
+
+	LLPCode pcode = object->getPCode();
+
+	if( (LL_PCODE_LEGACY_GRASS == pcode) 
+		|| (LL_PCODE_LEGACY_TREE == pcode) 
+		|| (LL_PCODE_TREE_NEW == pcode))
+	{
+		return true;
+	}
+	return false;
+}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 99feb9a0616be33ab7c28eb871ddb0fd4bb98fac..65fdc12f0a755670e7b1bad940a42e64012ff137 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1,9024 +1,9024 @@
-/** 
- * @file pipeline.cpp
- * @brief Rendering pipeline.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "pipeline.h"
-
-// library includes
-#include "llaudioengine.h" // For debugging.
-#include "imageids.h"
-#include "llerror.h"
-#include "llviewercontrol.h"
-#include "llfasttimer.h"
-#include "llfontgl.h"
-#include "llmemtype.h"
-#include "llnamevalue.h"
-#include "llpointer.h"
-#include "llprimitive.h"
-#include "llvolume.h"
-#include "material_codes.h"
-#include "timing.h"
-#include "v3color.h"
-#include "llui.h" 
-#include "llglheaders.h"
-#include "llrender.h"
-#include "llwindow.h"	// swapBuffers()
-
-// newview includes
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "lldrawable.h"
-#include "lldrawpoolalpha.h"
-#include "lldrawpoolavatar.h"
-#include "lldrawpoolground.h"
-#include "lldrawpoolbump.h"
-#include "lldrawpooltree.h"
-#include "lldrawpoolwater.h"
-#include "llface.h"
-#include "llfeaturemanager.h"
-#include "llfloatertelehub.h"
-#include "llfloaterreg.h"
-#include "llgldbg.h"
-#include "llhudmanager.h"
-#include "llhudnametag.h"
-#include "llhudtext.h"
-#include "lllightconstants.h"
-#include "llresmgr.h"
-#include "llselectmgr.h"
-#include "llsky.h"
-#include "lltracker.h"
-#include "lltool.h"
-#include "lltoolmgr.h"
-#include "llviewercamera.h"
-#include "llviewertexturelist.h"
-#include "llviewerobject.h"
-#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
-#include "llviewerregion.h" // for audio debugging.
-#include "llviewerwindow.h" // For getSpinAxis
-#include "llvoavatarself.h"
-#include "llvoground.h"
-#include "llvosky.h"
-#include "llvotree.h"
-#include "llvovolume.h"
-#include "llvosurfacepatch.h"
-#include "llvowater.h"
-#include "llvotree.h"
-#include "llvopartgroup.h"
-#include "llworld.h"
-#include "llcubemap.h"
-#include "llviewershadermgr.h"
-#include "llviewerstats.h"
-#include "llviewerjoystick.h"
-#include "llviewerdisplay.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-#include "llspatialpartition.h"
-#include "llmutelist.h"
-#include "lltoolpie.h"
-
-
-#ifdef _DEBUG
-// Debug indices is disabled for now for debug performance - djs 4/24/02
-//#define DEBUG_INDICES
-#else
-//#define DEBUG_INDICES
-#endif
-
-const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
-const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
-const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
-const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
-const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
-const U32 REFLECTION_MAP_RES = 128;
-
-// Max number of occluders to search for. JC
-const S32 MAX_OCCLUDER_COUNT = 2;
-
-extern S32 gBoxFrame;
-//extern BOOL gHideSelectedObjects;
-extern BOOL gDisplaySwapBuffers;
-extern BOOL gDebugGL;
-
-// hack counter for rendering a fixed number of frames after toggling
-// fullscreen to work around DEV-5361
-static S32 sDelayedVBOEnable = 0;
-
-BOOL	gAvatarBacklight = FALSE;
-
-BOOL	gDebugPipeline = FALSE;
-LLPipeline gPipeline;
-const LLMatrix4* gGLLastMatrix = NULL;
-
-LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry");
-LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass");
-LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible");
-LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion");
-LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny");
-LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple");
-LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain");
-LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees");
-LLFastTimer::DeclareTimer FTM_RENDER_UI("UI");
-LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water");
-LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky");
-LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects");
-LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars");
-LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump");
-LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright");
-LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow");
-LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update");
-LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool");
-LLFastTimer::DeclareTimer FTM_POOLS("Pools");
-LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO");
-LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State");
-LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline");
-LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy");
-LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
-
-
-static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
-static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
-
-//----------------------------------------
-std::string gPoolNames[] = 
-{
-	// Correspond to LLDrawpool enum render type
-	"NONE",
-	"POOL_SIMPLE",
-	"POOL_TERRAIN",
-	"POOL_BUMP",
-	"POOL_TREE",
-	"POOL_SKY",
-	"POOL_WL_SKY",
-	"POOL_GROUND",
-	"POOL_INVISIBLE",
-	"POOL_AVATAR",
-	"POOL_WATER",
-	"POOL_GRASS",
-	"POOL_FULLBRIGHT",
-	"POOL_GLOW",
-	"POOL_ALPHA",
-};
-
-void drawBox(const LLVector3& c, const LLVector3& r);
-void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
-
-U32 nhpo2(U32 v) 
-{
-	U32 r = 1;
-	while (r < v) {
-		r *= 2;
-	}
-	return r;
-}
-
-glh::matrix4f glh_copy_matrix(GLdouble* src)
-{
-	glh::matrix4f ret;
-	for (U32 i = 0; i < 16; i++)
-	{
-		ret.m[i] = (F32) src[i];
-	}
-	return ret;
-}
-
-glh::matrix4f glh_get_current_modelview()
-{
-	return glh_copy_matrix(gGLModelView);
-}
-
-glh::matrix4f glh_get_current_projection()
-{
-	return glh_copy_matrix(gGLProjection);
-}
-
-void glh_copy_matrix(const glh::matrix4f& src, GLdouble* dst)
-{
-	for (U32 i = 0; i < 16; i++)
-	{
-		dst[i] = src.m[i];
-	}
-}
-
-void glh_set_current_modelview(const glh::matrix4f& mat)
-{
-	glh_copy_matrix(mat, gGLModelView);
-}
-
-void glh_set_current_projection(glh::matrix4f& mat)
-{
-	glh_copy_matrix(mat, gGLProjection);
-}
-
-glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
-{
-	glh::matrix4f ret(
-		2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
-		0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
-		0.f, 0.f, -2.f/(zfar-znear),  -(zfar+znear)/(zfar-znear),
-		0.f, 0.f, 0.f, 1.f);
-
-	return ret;
-}
-
-void display_update_camera();
-//----------------------------------------
-
-S32		LLPipeline::sCompiles = 0;
-
-BOOL	LLPipeline::sPickAvatar = TRUE;
-BOOL	LLPipeline::sDynamicLOD = TRUE;
-BOOL	LLPipeline::sShowHUDAttachments = TRUE;
-BOOL	LLPipeline::sRenderPhysicalBeacons = TRUE;
-BOOL	LLPipeline::sRenderScriptedBeacons = FALSE;
-BOOL	LLPipeline::sRenderScriptedTouchBeacons = TRUE;
-BOOL	LLPipeline::sRenderParticleBeacons = FALSE;
-BOOL	LLPipeline::sRenderSoundBeacons = FALSE;
-BOOL	LLPipeline::sRenderBeacons = FALSE;
-BOOL	LLPipeline::sRenderHighlight = TRUE;
-BOOL	LLPipeline::sForceOldBakedUpload = FALSE;
-S32		LLPipeline::sUseOcclusion = 0;
-BOOL	LLPipeline::sDelayVBUpdate = TRUE;
-BOOL	LLPipeline::sAutoMaskAlphaDeferred = TRUE;
-BOOL	LLPipeline::sAutoMaskAlphaNonDeferred = FALSE;
-BOOL	LLPipeline::sDisableShaders = FALSE;
-BOOL	LLPipeline::sRenderBump = TRUE;
-BOOL	LLPipeline::sUseTriStrips = TRUE;
-BOOL	LLPipeline::sUseFarClip = TRUE;
-BOOL	LLPipeline::sShadowRender = FALSE;
-BOOL	LLPipeline::sWaterReflections = FALSE;
-BOOL	LLPipeline::sRenderGlow = FALSE;
-BOOL	LLPipeline::sReflectionRender = FALSE;
-BOOL	LLPipeline::sImpostorRender = FALSE;
-BOOL	LLPipeline::sUnderWaterRender = FALSE;
-BOOL	LLPipeline::sTextureBindTest = FALSE;
-BOOL	LLPipeline::sRenderFrameTest = FALSE;
-BOOL	LLPipeline::sRenderAttachedLights = TRUE;
-BOOL	LLPipeline::sRenderAttachedParticles = TRUE;
-BOOL	LLPipeline::sRenderDeferred = FALSE;
-BOOL    LLPipeline::sAllowRebuildPriorityGroup = FALSE ;
-S32		LLPipeline::sVisibleLightCount = 0;
-F32		LLPipeline::sMinRenderSize = 0.f;
-
-
-static LLCullResult* sCull = NULL;
-
-static const U32 gl_cube_face[] = 
-{
-	GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
-	GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
-	GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
-	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
-	GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
-	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
-};
-
-void validate_framebuffer_object();
-
-
-void addDeferredAttachments(LLRenderTarget& target)
-{
-	target.addColorAttachment(GL_RGBA); //specular
-	target.addColorAttachment(GL_RGBA); //normal+z	
-}
-
-LLPipeline::LLPipeline() :
-	mBackfaceCull(FALSE),
-	mBatchCount(0),
-	mMatrixOpCount(0),
-	mTextureMatrixOps(0),
-	mMaxBatchSize(0),
-	mMinBatchSize(0),
-	mMeanBatchSize(0),
-	mTrianglesDrawn(0),
-	mNumVisibleNodes(0),
-	mVerticesRelit(0),
-	mLightingChanges(0),
-	mGeometryChanges(0),
-	mNumVisibleFaces(0),
-
-	mInitialized(FALSE),
-	mVertexShadersEnabled(FALSE),
-	mVertexShadersLoaded(0),
-	mRenderDebugFeatureMask(0),
-	mRenderDebugMask(0),
-	mOldRenderDebugMask(0),
-	mLastRebuildPool(NULL),
-	mAlphaPool(NULL),
-	mSkyPool(NULL),
-	mTerrainPool(NULL),
-	mWaterPool(NULL),
-	mGroundPool(NULL),
-	mSimplePool(NULL),
-	mFullbrightPool(NULL),
-	mInvisiblePool(NULL),
-	mGlowPool(NULL),
-	mBumpPool(NULL),
-	mWLSkyPool(NULL),
-	mLightMask(0),
-	mLightMovingMask(0),
-	mLightingDetail(0),
-	mScreenWidth(0),
-	mScreenHeight(0)
-{
-	mNoiseMap = 0;
-	mTrueNoiseMap = 0;
-	mLightFunc = 0;
-}
-
-void LLPipeline::init()
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
-
-	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
-	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
-	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
-	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
-	sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
-	sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
-
-	mInitialized = TRUE;
-	
-	stop_glerror();
-
-	//create render pass pools
-	getPool(LLDrawPool::POOL_ALPHA);
-	getPool(LLDrawPool::POOL_SIMPLE);
-	getPool(LLDrawPool::POOL_GRASS);
-	getPool(LLDrawPool::POOL_FULLBRIGHT);
-	getPool(LLDrawPool::POOL_INVISIBLE);
-	getPool(LLDrawPool::POOL_BUMP);
-	getPool(LLDrawPool::POOL_GLOW);
-
-	LLViewerStats::getInstance()->mTrianglesDrawnStat.reset();
-	resetFrameStats();
-
-	for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
-	{
-		mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled
-	}
-
-	mRenderDebugFeatureMask = 0xffffffff; // All debugging features on
-	mRenderDebugMask = 0;	// All debug starts off
-
-	// Don't turn on ground when this is set
-	// Mac Books with intel 950s need this
-	if(!gSavedSettings.getBOOL("RenderGround"))
-	{
-		toggleRenderType(RENDER_TYPE_GROUND);
-	}
-
-	mOldRenderDebugMask = mRenderDebugMask;
-
-	mBackfaceCull = TRUE;
-
-	stop_glerror();
-	
-	// Enable features
-		
-	LLViewerShaderMgr::instance()->setShaders();
-
-	stop_glerror();
-
-	for (U32 i = 0; i < 2; ++i)
-	{
-		mSpotLightFade[i] = 1.f;
-	}
-
-	setLightingDetail(-1);
-}
-
-LLPipeline::~LLPipeline()
-{
-
-}
-
-void LLPipeline::cleanup()
-{
-	assertInitialized();
-
-	mGroupQ1.clear() ;
-	mGroupQ2.clear() ;
-
-	for(pool_set_t::iterator iter = mPools.begin();
-		iter != mPools.end(); )
-	{
-		pool_set_t::iterator curiter = iter++;
-		LLDrawPool* poolp = *curiter;
-		if (poolp->isFacePool())
-		{
-			LLFacePool* face_pool = (LLFacePool*) poolp;
-			if (face_pool->mReferences.empty())
-			{
-				mPools.erase(curiter);
-				removeFromQuickLookup( poolp );
-				delete poolp;
-			}
-		}
-		else
-		{
-			mPools.erase(curiter);
-			removeFromQuickLookup( poolp );
-			delete poolp;
-		}
-	}
-	
-	if (!mTerrainPools.empty())
-	{
-		llwarns << "Terrain Pools not cleaned up" << llendl;
-	}
-	if (!mTreePools.empty())
-	{
-		llwarns << "Tree Pools not cleaned up" << llendl;
-	}
-		
-	delete mAlphaPool;
-	mAlphaPool = NULL;
-	delete mSkyPool;
-	mSkyPool = NULL;
-	delete mTerrainPool;
-	mTerrainPool = NULL;
-	delete mWaterPool;
-	mWaterPool = NULL;
-	delete mGroundPool;
-	mGroundPool = NULL;
-	delete mSimplePool;
-	mSimplePool = NULL;
-	delete mFullbrightPool;
-	mFullbrightPool = NULL;
-	delete mInvisiblePool;
-	mInvisiblePool = NULL;
-	delete mGlowPool;
-	mGlowPool = NULL;
-	delete mBumpPool;
-	mBumpPool = NULL;
-	// don't delete wl sky pool it was handled above in the for loop
-	//delete mWLSkyPool;
-	mWLSkyPool = NULL;
-
-	releaseGLBuffers();
-
-	mFaceSelectImagep = NULL;
-
-	mMovedBridge.clear();
-
-	mInitialized = FALSE;
-}
-
-//============================================================================
-
-void LLPipeline::destroyGL() 
-{
-	stop_glerror();
-	unloadShaders();
-	mHighlightFaces.clear();
-	
-	resetDrawOrders();
-
-	resetVertexBuffers();
-
-	releaseGLBuffers();
-
-	if (LLVertexBuffer::sEnableVBOs)
-	{
-		// render 30 frames after switching to work around DEV-5361
-		sDelayedVBOEnable = 30;
-		LLVertexBuffer::sEnableVBOs = FALSE;
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
-
-void LLPipeline::resizeScreenTexture()
-{
-	LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE);
-	if (gPipeline.canUseVertexShaders() && assertInitialized())
-	{
-		GLuint resX = gViewerWindow->getWorldViewWidthRaw();
-		GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-	
-		allocateScreenBuffer(resX,resY);
-	}
-}
-
-void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
-{
-	// remember these dimensions
-	mScreenWidth = resX;
-	mScreenHeight = resY;
-	
-	//never use more than 4 samples for render targets
-	U32 samples = llmin(gSavedSettings.getU32("RenderFSAASamples"), (U32) 4);
-	U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
-
-	if (res_mod > 1 && res_mod < resX && res_mod < resY)
-	{
-		resX /= res_mod;
-		resY /= res_mod;
-	}
-
-	if (gSavedSettings.getBOOL("RenderUIBuffer"))
-	{
-		mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
-	}	
-
-	if (LLPipeline::sRenderDeferred)
-	{
-		//allocate deferred rendering color buffers
-		mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
-		mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
-		addDeferredAttachments(mDeferredScreen);
-	
-		mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);		
-		mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
-
-		for (U32 i = 0; i < 3; i++)
-		{
-			mDeferredLight[i].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
-		}
-
-		for (U32 i = 0; i < 2; i++)
-		{
-			mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
-		}
-
-		F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale");
-
-		//HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug)
-		U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0;
-
-		for (U32 i = 0; i < 4; i++)
-		{
-			mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
-		}
-
-
-		U32 width = nhpo2(U32(resX*scale))/2;
-		U32 height = width;
-
-		for (U32 i = 4; i < 6; i++)
-		{
-			mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE);
-		}
-
-		width = nhpo2(resX)/2;
-		height = nhpo2(resY)/2;
-		mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE);
-	}
-	else
-	{
-		mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);		
-	}
-	
-
-	if (LLRenderTarget::sUseFBO && gGLManager.mHasFramebufferMultisample && samples > 1)
-	{
-		mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
-		if (LLPipeline::sRenderDeferred)
-		{
-			addDeferredAttachments(mSampleBuffer);
-			mDeferredScreen.setSampleBuffer(&mSampleBuffer);
-		}
-
-		mScreen.setSampleBuffer(&mSampleBuffer);
-
-		stop_glerror();
-	}
-	
-	if (LLPipeline::sRenderDeferred)
-	{ //share depth buffer between deferred targets
-		mDeferredScreen.shareDepthBuffer(mScreen);
-		for (U32 i = 0; i < 3; i++)
-		{ //share stencil buffer with screen space lightmap to stencil out sky
-			mDeferredScreen.shareDepthBuffer(mDeferredLight[i]);
-		}
-	}
-
-	gGL.getTexUnit(0)->disable();
-
-	stop_glerror();
-
-}
-
-//static
-void LLPipeline::updateRenderDeferred()
-{
-	BOOL deferred = ((gSavedSettings.getBOOL("RenderDeferred") && 
-					 LLRenderTarget::sUseFBO &&
-					 LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
-					 gSavedSettings.getBOOL("VertexShaderEnable") && 
-					 gSavedSettings.getBOOL("RenderAvatarVP") &&
-					 gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) &&
-					!gUseWireframe;
-
-	sRenderDeferred = deferred;			
-}
-
-void LLPipeline::releaseGLBuffers()
-{
-	assertInitialized();
-	
-	if (mNoiseMap)
-	{
-		LLImageGL::deleteTextures(1, &mNoiseMap);
-		mNoiseMap = 0;
-	}
-
-	if (mTrueNoiseMap)
-	{
-		LLImageGL::deleteTextures(1, &mTrueNoiseMap);
-		mTrueNoiseMap = 0;
-	}
-
-	if (mLightFunc)
-	{
-		LLImageGL::deleteTextures(1, &mLightFunc);
-		mLightFunc = 0;
-	}
-
-	mWaterRef.release();
-	mWaterDis.release();
-	mScreen.release();
-	mUIScreen.release();
-	mSampleBuffer.releaseSampleBuffer();
-	mDeferredScreen.release();
-	mDeferredDepth.release();
-	for (U32 i = 0; i < 3; i++)
-	{
-		mDeferredLight[i].release();
-	}
-
-	mEdgeMap.release();
-	mGIMap.release();
-	mGIMapPost[0].release();
-	mGIMapPost[1].release();
-	mHighlight.release();
-	mLuminanceMap.release();
-	
-	for (U32 i = 0; i < 6; i++)
-	{
-		mShadow[i].release();
-	}
-
-	for (U32 i = 0; i < 3; i++)
-	{
-		mGlow[i].release();
-	}
-
-	LLVOAvatar::resetImpostors();
-}
-
-void LLPipeline::createGLBuffers()
-{
-	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS);
-	assertInitialized();
-
-	updateRenderDeferred();
-
-	if (LLPipeline::sWaterReflections)
-	{ //water reflection texture
-		U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
-			
-		mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
-		mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
-	}
-
-	mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
-
-	stop_glerror();
-
-	GLuint resX = gViewerWindow->getWorldViewWidthRaw();
-	GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-	
-	if (LLPipeline::sRenderGlow)
-	{ //screen space glow buffers
-		const U32 glow_res = llmax(1, 
-			llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
-
-		for (U32 i = 0; i < 3; i++)
-		{
-			mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
-		}
-
-		allocateScreenBuffer(resX,resY);
-		mScreenWidth = 0;
-		mScreenHeight = 0;
-
-	}
-	
-	if (sRenderDeferred)
-	{
-		if (!mNoiseMap)
-		{
-			const U32 noiseRes = 128;
-			LLVector3 noise[noiseRes*noiseRes];
-
-			F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f;
-			for (U32 i = 0; i < noiseRes*noiseRes; ++i)
-			{
-				noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f);
-				noise[i].normVec();
-				noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;
-			}
-
-			LLImageGL::generateTextures(1, &mNoiseMap);
-			
-			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
-			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
-			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		}
-
-		if (!mTrueNoiseMap)
-		{
-			const U32 noiseRes = 128;
-			F32 noise[noiseRes*noiseRes*3];
-			for (U32 i = 0; i < noiseRes*noiseRes*3; i++)
-			{
-				noise[i] = ll_frand()*2.0-1.0;
-			}
-
-			LLImageGL::generateTextures(1, &mTrueNoiseMap);
-			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
-			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
-			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		}
-
-		if (!mLightFunc)
-		{
-			U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
-			U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
-			U8* lg = new U8[lightResX*lightResY];
-
-			for (U32 y = 0; y < lightResY; ++y)
-			{
-				for (U32 x = 0; x < lightResX; ++x)
-				{
-					//spec func
-					F32 sa = (F32) x/(lightResX-1);
-					F32 spec = (F32) y/(lightResY-1);
-					//lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
-
-					//F32 sp = acosf(sa)/(1.f-spec);
-
-					sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
-					F32 a = acosf(sa*0.25f+0.75f);
-					F32 m = llmax(0.5f-spec*0.5f, 0.001f);
-					F32 t2 = tanf(a)/m;
-					t2 *= t2;
-
-					F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
-					F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
-
-					lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
-				}
-			}
-
-			LLImageGL::generateTextures(1, &mLightFunc);
-			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
-			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_ALPHA, lightResX, lightResY, GL_ALPHA, GL_UNSIGNED_BYTE, lg);
-			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
-
-			delete [] lg;
-		}
-
-		if (gSavedSettings.getBOOL("RenderDeferredGI"))
-		{
-			mGIMap.allocate(512,512,GL_RGBA, TRUE, FALSE);
-			addDeferredAttachments(mGIMap);
-		}
-	}
-}
-
-void LLPipeline::restoreGL() 
-{
-	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
-	assertInitialized();
-
-	if (mVertexShadersEnabled)
-	{
-		LLViewerShaderMgr::instance()->setShaders();
-	}
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				part->restoreGL();
-			}
-		}
-	}
-}
-
-
-BOOL LLPipeline::canUseVertexShaders()
-{
-	if (sDisableShaders ||
-		!gGLManager.mHasVertexShader ||
-		!gGLManager.mHasFragmentShader ||
-		!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") ||
-		(assertInitialized() && mVertexShadersLoaded != 1) )
-	{
-		return FALSE;
-	}
-	else
-	{
-		return TRUE;
-	}
-}
-
-BOOL LLPipeline::canUseWindLightShaders() const
-{
-	return (!LLPipeline::sDisableShaders &&
-			gWLSkyProgram.mProgramObject != 0 &&
-			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
-}
-
-BOOL LLPipeline::canUseWindLightShadersOnObjects() const
-{
-	return (canUseWindLightShaders() 
-		&& LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
-}
-
-BOOL LLPipeline::canUseAntiAliasing() const
-{
-	return TRUE; //(gSavedSettings.getBOOL("RenderUseFBO"));
-}
-
-void LLPipeline::unloadShaders()
-{
-	LLMemType mt_us(LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS);
-	LLViewerShaderMgr::instance()->unloadShaders();
-
-	mVertexShadersLoaded = 0;
-}
-
-void LLPipeline::assertInitializedDoError()
-{
-	llerrs << "LLPipeline used when uninitialized." << llendl;
-}
-
-//============================================================================
-
-void LLPipeline::enableShadows(const BOOL enable_shadows)
-{
-	//should probably do something here to wrangle shadows....	
-}
-
-S32 LLPipeline::getMaxLightingDetail() const
-{
-	/*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
-	{
-		return 3;
-	}
-	else*/
-	{
-		return 1;
-	}
-}
-
-S32 LLPipeline::setLightingDetail(S32 level)
-{
-	LLMemType mt_ld(LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL);
-	assertInitialized();
-
-	if (level < 0)
-	{
-		if (gSavedSettings.getBOOL("VertexShaderEnable"))
-		{
-			level = 1;
-		}
-		else
-		{
-			level = 0;
-		}
-	}
-	level = llclamp(level, 0, getMaxLightingDetail());
-	if (level != mLightingDetail)
-	{
-		mLightingDetail = level;
-
-		if (mVertexShadersLoaded == 1)
-		{
-			LLViewerShaderMgr::instance()->setShaders();
-		}
-	}
-	return mLightingDetail;
-}
-
-class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
-{
-public:
-	const std::set<LLViewerFetchedTexture*>& mTextures;
-
-	LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { }
-
-	virtual void visit(const LLOctreeNode<LLDrawable>* node)
-	{
-		LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
-
-		if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
-		{
-			for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
-			{
-				for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) 
-				{
-					LLDrawInfo* params = *j;
-					LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture);
-					if (tex && mTextures.find(tex) != mTextures.end())
-					{ 
-						group->setState(LLSpatialGroup::GEOM_DIRTY);
-					}
-				}
-			}
-		}
-
-		for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
-		{
-			LLSpatialBridge* bridge = *i;
-			traverse(bridge->mOctree);
-		}
-	}
-};
-
-// Called when a texture changes # of channels (causes faces to move to alpha pool)
-void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures)
-{
-	assertInitialized();
-
-	// *TODO: This is inefficient and causes frame spikes; need a better way to do this
-	//        Most of the time is spent in dirty.traverse.
-
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		if (poolp->isFacePool())
-		{
-			((LLFacePool*) poolp)->dirtyTextures(textures);
-		}
-	}
-	
-	LLOctreeDirtyTexture dirty(textures);
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				dirty.traverse(part->mOctree);
-			}
-		}
-	}
-}
-
-LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
-{
-	assertInitialized();
-
-	LLDrawPool *poolp = NULL;
-	switch( type )
-	{
-	case LLDrawPool::POOL_SIMPLE:
-		poolp = mSimplePool;
-		break;
-
-	case LLDrawPool::POOL_GRASS:
-		poolp = mGrassPool;
-		break;
-
-	case LLDrawPool::POOL_FULLBRIGHT:
-		poolp = mFullbrightPool;
-		break;
-
-	case LLDrawPool::POOL_INVISIBLE:
-		poolp = mInvisiblePool;
-		break;
-
-	case LLDrawPool::POOL_GLOW:
-		poolp = mGlowPool;
-		break;
-
-	case LLDrawPool::POOL_TREE:
-		poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
-		break;
-
-	case LLDrawPool::POOL_TERRAIN:
-		poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
-		break;
-
-	case LLDrawPool::POOL_BUMP:
-		poolp = mBumpPool;
-		break;
-
-	case LLDrawPool::POOL_ALPHA:
-		poolp = mAlphaPool;
-		break;
-
-	case LLDrawPool::POOL_AVATAR:
-		break; // Do nothing
-
-	case LLDrawPool::POOL_SKY:
-		poolp = mSkyPool;
-		break;
-
-	case LLDrawPool::POOL_WATER:
-		poolp = mWaterPool;
-		break;
-
-	case LLDrawPool::POOL_GROUND:
-		poolp = mGroundPool;
-		break;
-
-	case LLDrawPool::POOL_WL_SKY:
-		poolp = mWLSkyPool;
-		break;
-
-	default:
-		llassert(0);
-		llerrs << "Invalid Pool Type in  LLPipeline::findPool() type=" << type << llendl;
-		break;
-	}
-
-	return poolp;
-}
-
-
-LLDrawPool *LLPipeline::getPool(const U32 type,	LLViewerTexture *tex0)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	LLDrawPool *poolp = findPool(type, tex0);
-	if (poolp)
-	{
-		return poolp;
-	}
-
-	LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
-	addPool( new_poolp );
-
-	return new_poolp;
-}
-
-
-// static
-LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	U32 type = getPoolTypeFromTE(te, imagep);
-	return gPipeline.getPool(type, imagep);
-}
-
-//static 
-U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
-{
-	LLMemType mt_gpt(LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE);
-	
-	if (!te || !imagep)
-	{
-		return 0;
-	}
-		
-	bool alpha = te->getColor().mV[3] < 0.999f;
-	if (imagep)
-	{
-		alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2);
-	}
-
-	if (alpha)
-	{
-		return LLDrawPool::POOL_ALPHA;
-	}
-	else if ((te->getBumpmap() || te->getShiny()))
-	{
-		return LLDrawPool::POOL_BUMP;
-	}
-	else
-	{
-		return LLDrawPool::POOL_SIMPLE;
-	}
-}
-
-
-void LLPipeline::addPool(LLDrawPool *new_poolp)
-{
-	LLMemType mt_a(LLMemType::MTYPE_PIPELINE_ADD_POOL);
-	assertInitialized();
-	mPools.insert(new_poolp);
-	addToQuickLookup( new_poolp );
-}
-
-void LLPipeline::allocDrawable(LLViewerObject *vobj)
-{
-	LLMemType mt_ad(LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE);
-	LLDrawable *drawable = new LLDrawable();
-	vobj->mDrawable = drawable;
-	
-	drawable->mVObjp     = vobj;
-	
-	//encompass completely sheared objects by taking 
-	//the most extreme point possible (<1,1,0.5>)
-	drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length());
-	if (vobj->isOrphaned())
-	{
-		drawable->setState(LLDrawable::FORCE_INVISIBLE);
-	}
-	drawable->updateXform(TRUE);
-}
-
-
-void LLPipeline::unlinkDrawable(LLDrawable *drawable)
-{
-	LLFastTimer t(FTM_PIPELINE);
-
-	assertInitialized();
-
-	LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
-	
-	// Based on flags, remove the drawable from the queues that it's on.
-	if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
-	{
-		LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
-		if (iter != mMovedList.end())
-		{
-			mMovedList.erase(iter);
-		}
-	}
-
-	if (drawablep->getSpatialGroup())
-	{
-		if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
-		{
-#ifdef LL_RELEASE_FOR_DOWNLOAD
-			llwarns << "Couldn't remove object from spatial group!" << llendl;
-#else
-			llerrs << "Couldn't remove object from spatial group!" << llendl;
-#endif
-		}
-	}
-
-	mLights.erase(drawablep);
-	for (light_set_t::iterator iter = mNearbyLights.begin();
-				iter != mNearbyLights.end(); iter++)
-	{
-		if (iter->drawable == drawablep)
-		{
-			mNearbyLights.erase(iter);
-			break;
-		}
-	}
-
-	{
-		HighlightItem item(drawablep);
-		mHighlightSet.erase(item);
-
-		if (mHighlightObject == drawablep)
-		{
-			mHighlightObject = NULL;
-		}
-	}
-
-	for (U32 i = 0; i < 2; ++i)
-	{
-		if (mShadowSpotLight[i] == drawablep)
-		{
-			mShadowSpotLight[i] = NULL;
-		}
-
-		if (mTargetShadowSpotLight[i] == drawablep)
-		{
-			mTargetShadowSpotLight[i] = NULL;
-		}
-	}
-
-
-}
-
-U32 LLPipeline::addObject(LLViewerObject *vobj)
-{
-	LLMemType mt_ao(LLMemType::MTYPE_PIPELINE_ADD_OBJECT);
-	if (gNoRender)
-	{
-		return 0;
-	}
-
-	if (gSavedSettings.getBOOL("RenderDelayCreation"))
-	{
-		mCreateQ.push_back(vobj);
-	}
-	else
-	{
-		createObject(vobj);
-	}
-
-	return 1;
-}
-
-void LLPipeline::createObjects(F32 max_dtime)
-{
-	LLFastTimer ftm(FTM_GEO_UPDATE);
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS);
-
-	LLTimer update_timer;
-
-	while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime)
-	{
-		LLViewerObject* vobj = mCreateQ.front();
-		if (!vobj->isDead())
-		{
-			createObject(vobj);
-		}
-		mCreateQ.pop_front();
-	}
-	
-	//for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter)
-	//{
-	//	createObject(*iter);
-	//}
-
-	//mCreateQ.clear();
-}
-
-void LLPipeline::createObject(LLViewerObject* vobj)
-{
-	LLDrawable* drawablep = vobj->mDrawable;
-
-	if (!drawablep)
-	{
-		drawablep = vobj->createDrawable(this);
-	}
-	else
-	{
-		llerrs << "Redundant drawable creation!" << llendl;
-	}
-		
-	llassert(drawablep);
-
-	if (vobj->getParent())
-	{
-		vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
-	}
-	else
-	{
-		vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
-	}
-
-	markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
-
-	if (drawablep->getVOVolume() && gSavedSettings.getBOOL("RenderAnimateRes"))
-	{
-		// fun animated res
-		drawablep->updateXform(TRUE);
-		drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
-		drawablep->setScale(LLVector3(0,0,0));
-		drawablep->makeActive();
-	}
-}
-
-
-void LLPipeline::resetFrameStats()
-{
-	assertInitialized();
-
-	LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
-
-	if (mBatchCount > 0)
-	{
-		mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount;
-	}
-	mTrianglesDrawn = 0;
-	sCompiles        = 0;
-	mVerticesRelit   = 0;
-	mLightingChanges = 0;
-	mGeometryChanges = 0;
-	mNumVisibleFaces = 0;
-
-	if (mOldRenderDebugMask != mRenderDebugMask)
-	{
-		gObjectList.clearDebugText();
-		mOldRenderDebugMask = mRenderDebugMask;
-	}
-		
-}
-
-//external functions for asynchronous updating
-void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
-{
-	if (gSavedSettings.getBOOL("FreezeTime"))
-	{
-		return;
-	}
-	if (!drawablep)
-	{
-		llerrs << "updateMove called with NULL drawablep" << llendl;
-		return;
-	}
-	if (drawablep->isState(LLDrawable::EARLY_MOVE))
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	// update drawable now
-	drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED
-	drawablep->updateMove(); // returns done
-	drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
-	// Put on move list so that EARLY_MOVE gets cleared
-	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
-	{
-		mMovedList.push_back(drawablep);
-		drawablep->setState(LLDrawable::ON_MOVE_LIST);
-	}
-}
-
-void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
-{
-	if (gSavedSettings.getBOOL("FreezeTime"))
-	{
-		return;
-	}
-	if (!drawablep)
-	{
-		llerrs << "updateMove called with NULL drawablep" << llendl;
-		return;
-	}
-	if (drawablep->isState(LLDrawable::EARLY_MOVE))
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	// update drawable now
-	drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
-	drawablep->updateMove();
-	drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
-	// Put on move list so that EARLY_MOVE gets cleared
-	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
-	{
-		mMovedList.push_back(drawablep);
-		drawablep->setState(LLDrawable::ON_MOVE_LIST);
-	}
-}
-
-void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
-{
-	for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
-		 iter != moved_list.end(); )
-	{
-		LLDrawable::drawable_vector_t::iterator curiter = iter++;
-		LLDrawable *drawablep = *curiter;
-		BOOL done = TRUE;
-		if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
-		{
-			done = drawablep->updateMove();
-		}
-		drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
-		if (done)
-		{
-			drawablep->clearState(LLDrawable::ON_MOVE_LIST);
-			iter = moved_list.erase(curiter);
-		}
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree");
-static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move");
-
-void LLPipeline::updateMove()
-{
-	LLFastTimer t(FTM_UPDATE_MOVE);
-	LLMemType mt_um(LLMemType::MTYPE_PIPELINE_UPDATE_MOVE);
-
-	if (gSavedSettings.getBOOL("FreezeTime"))
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	{
-		static LLFastTimer::DeclareTimer ftm("Retexture");
-		LLFastTimer t(ftm);
-
-		for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
-			 iter != mRetexturedList.end(); ++iter)
-		{
-			LLDrawable* drawablep = *iter;
-			if (drawablep && !drawablep->isDead())
-			{
-				drawablep->updateTexture();
-			}
-		}
-		mRetexturedList.clear();
-	}
-
-	{
-		static LLFastTimer::DeclareTimer ftm("Moved List");
-		LLFastTimer t(ftm);
-		updateMovedList(mMovedList);
-	}
-
-	//balance octrees
-	{
- 		LLFastTimer ot(FTM_OCTREE_BALANCE);
-
-		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-		{
-			LLViewerRegion* region = *iter;
-			for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-			{
-				LLSpatialPartition* part = region->getSpatialPartition(i);
-				if (part)
-				{
-					part->mOctree->balance();
-				}
-			}
-		}
-	}
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Culling and occlusion testing
-/////////////////////////////////////////////////////////////////////////////
-
-//static
-F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
-{
-	LLVector3 lookAt = center - camera.getOrigin();
-	F32 dist = lookAt.length();
-
-	//ramp down distance for nearby objects
-	//shrink dist by dist/16.
-	if (dist < 16.f)
-	{
-		dist /= 16.f;
-		dist *= dist;
-		dist *= 16.f;
-	}
-
-	//get area of circle around node
-	F32 app_angle = atanf(size.length()/dist);
-	F32 radius = app_angle*LLDrawable::sCurPixelAngle;
-	return radius*radius * F_PI;
-}
-
-void LLPipeline::grabReferences(LLCullResult& result)
-{
-	sCull = &result;
-}
-
-BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera)
-{
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if (hasRenderType(part->mDrawableType))
-				{
-					if (part->visibleObjectsInFrustum(camera))
-					{
-						return TRUE;
-					}
-				}
-			}
-		}
-	}
-
-	return FALSE;
-}
-
-BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max)
-{
-	const F32 X = 65536.f;
-
-	min = LLVector3(X,X,X);
-	max = LLVector3(-X,-X,-X);
-
-	U32 saved_camera_id = LLViewerCamera::sCurCameraID;
-	LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-
-	BOOL res = TRUE;
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if (hasRenderType(part->mDrawableType))
-				{
-					if (!part->getVisibleExtents(camera, min, max))
-					{
-						res = FALSE;
-					}
-				}
-			}
-		}
-	}
-
-	LLViewerCamera::sCurCameraID = saved_camera_id;
-
-	return res;
-}
-
-static LLFastTimer::DeclareTimer FTM_CULL("Object Culling");
-
-void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip)
-{
-	LLFastTimer t(FTM_CULL);
-	LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL);
-
-	grabReferences(result);
-
-	sCull->clear();
-
-	BOOL to_texture =	LLPipeline::sUseOcclusion > 1 &&
-						!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && 
-						LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
-						gPipeline.canUseVertexShaders() &&
-						sRenderGlow;
-
-	if (to_texture)
-	{
-		mScreen.bindTarget();
-	}
-
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	glLoadMatrixd(gGLLastProjection);
-	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
-	gGLLastMatrix = NULL;
-	glLoadMatrixd(gGLLastModelView);
-
-
-	LLVertexBuffer::unbind();
-	LLGLDisable blend(GL_BLEND);
-	LLGLDisable test(GL_ALPHA_TEST);
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-	if (sUseOcclusion > 1)
-	{
-		gGL.setColorMask(false, false);
-	}
-
-	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		if (water_clip != 0)
-		{
-			LLPlane plane(LLVector3(0,0, (F32) -water_clip), (F32) water_clip*region->getWaterHeight());
-			camera.setUserClipPlane(plane);
-		}
-		else
-		{
-			camera.disableUserClipPlane();
-		}
-
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if (hasRenderType(part->mDrawableType))
-				{
-					part->cull(camera);
-				}
-			}
-		}
-	}
-
-	camera.disableUserClipPlane();
-
-	if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && 
-		gSky.mVOSkyp.notNull() && 
-		gSky.mVOSkyp->mDrawable.notNull())
-	{
-		gSky.mVOSkyp->mDrawable->setVisible(camera);
-		sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
-		gSky.updateCull();
-		stop_glerror();
-	}
-
-	if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && 
-		!gPipeline.canUseWindLightShaders() &&
-		gSky.mVOGroundp.notNull() && 
-		gSky.mVOGroundp->mDrawable.notNull() &&
-		!LLPipeline::sWaterReflections)
-	{
-		gSky.mVOGroundp->mDrawable->setVisible(camera);
-		sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
-	}
-	
-	
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-
-	if (sUseOcclusion > 1)
-	{
-		gGL.setColorMask(true, false);
-	}
-
-	if (to_texture)
-	{
-		mScreen.flush();
-	}
-}
-
-void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
-{
-	if (group->getData().empty())
-	{ 
-		return;
-	}
-	
-	group->setVisible();
-
-	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-	{
-		group->updateDistance(camera);
-	}
-	
-	const F32 MINIMUM_PIXEL_AREA = 16.f;
-
-	if (group->mPixelArea < MINIMUM_PIXEL_AREA)
-	{
-		return;
-	}
-
-	if (sMinRenderSize > 0.f && 
-			llmax(llmax(group->mBounds[1].mV[0], group->mBounds[1].mV[1]), group->mBounds[1].mV[2]) < sMinRenderSize)
-	{
-		return;
-	}
-
-	assertInitialized();
-	
-	if (!group->mSpatialPartition->mRenderByGroup)
-	{ //render by drawable
-		sCull->pushDrawableGroup(group);
-	}
-	else
-	{   //render by group
-		sCull->pushVisibleGroup(group);
-	}
-
-	mNumVisibleNodes++;
-}
-
-void LLPipeline::markOccluder(LLSpatialGroup* group)
-{
-	if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION))
-	{
-		LLSpatialGroup* parent = group->getParent();
-
-		if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{ //only mark top most occluders as active occlusion
-			sCull->pushOcclusionGroup(group);
-			group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
-				
-			if (parent && 
-				!parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
-				parent->getElementCount() == 0 &&
-				parent->needsUpdate())
-			{
-				sCull->pushOcclusionGroup(group);
-				parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
-			}
-		}
-	}
-}
-
-void LLPipeline::doOcclusion(LLCamera& camera)
-{
-	LLVertexBuffer::unbind();
-
-	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
-	{
-		gGL.setColorMask(true, false, false, false);
-	}
-	else
-	{
-		gGL.setColorMask(false, false);
-	}
-	LLGLDisable blend(GL_BLEND);
-	LLGLDisable test(GL_ALPHA_TEST);
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-
-	LLGLDisable cull(GL_CULL_FACE);
-	if (LLPipeline::sUseOcclusion > 1)
-	{
-		for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			group->doOcclusion(&camera);
-			group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
-		}
-	}
-
-	gGL.setColorMask(true, false);
-}
-	
-BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
-{
-	BOOL update_complete = drawablep->updateGeometry(priority);
-	if (update_complete && assertInitialized())
-	{
-		drawablep->setState(LLDrawable::BUILT);
-		mGeometryChanges++;
-	}
-	return update_complete;
-}
-
-void LLPipeline::updateGL()
-{
-	while (!LLGLUpdate::sGLQ.empty())
-	{
-		LLGLUpdate* glu = LLGLUpdate::sGLQ.front();
-		glu->updateGL();
-		glu->mInQ = FALSE;
-		LLGLUpdate::sGLQ.pop_front();
-	}
-}
-
-void LLPipeline::rebuildPriorityGroups()
-{
-	if(!sAllowRebuildPriorityGroup)
-	{
-		return ;
-	}
-	sAllowRebuildPriorityGroup = FALSE ;
-
-	LLTimer update_timer;
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	
-	assertInitialized();
-
-	// Iterate through all drawables on the priority build queue,
-	for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin();
-		 iter != mGroupQ1.end(); ++iter)
-	{
-		LLSpatialGroup* group = *iter;
-		group->rebuildGeom();
-		group->clearState(LLSpatialGroup::IN_BUILD_Q1);
-	}
-
-	mGroupQ1.clear();
-}
-		
-void LLPipeline::rebuildGroups()
-{
-	// Iterate through some drawables on the non-priority build queue
-	S32 size = (S32) mGroupQ2.size();
-	S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
-			
-	S32 count = 0;
-	
-	std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency());
-
-	LLSpatialGroup::sg_vector_t::iterator iter;
-	for (iter = mGroupQ2.begin();
-		 iter != mGroupQ2.end(); ++iter)
-	{
-		LLSpatialGroup* group = *iter;
-
-		if (group->isDead())
-		{
-			continue;
-		}
-
-		group->rebuildGeom();
-		
-		if (group->mSpatialPartition->mRenderByGroup)
-		{
-			count++;
-		}
-			
-		group->clearState(LLSpatialGroup::IN_BUILD_Q2);
-
-		if (count > min_count)
-		{
-			++iter;
-			break;
-		}
-	}	
-
-	mGroupQ2.erase(mGroupQ2.begin(), iter);
-
-	updateMovedList(mMovedBridge);
-}
-
-void LLPipeline::updateGeom(F32 max_dtime)
-{
-	LLTimer update_timer;
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_UPDATE_GEOM);
-	LLPointer<LLDrawable> drawablep;
-
-	LLFastTimer t(FTM_GEO_UPDATE);
-
-	assertInitialized();
-
-	if (sDelayedVBOEnable > 0)
-	{
-		if (--sDelayedVBOEnable <= 0)
-		{
-			resetVertexBuffers();
-			LLVertexBuffer::sEnableVBOs = TRUE;
-		}
-	}
-
-	// notify various object types to reset internal cost metrics, etc.
-	// for now, only LLVOVolume does this to throttle LOD changes
-	LLVOVolume::preUpdateGeom();
-
-	// Iterate through all drawables on the priority build queue,
-	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
-		 iter != mBuildQ1.end();)
-	{
-		LLDrawable::drawable_list_t::iterator curiter = iter++;
-		LLDrawable* drawablep = *curiter;
-		if (drawablep && !drawablep->isDead())
-		{
-			if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
-			{
-				drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
-				LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
-				if (find != mBuildQ2.end())
-				{
-					mBuildQ2.erase(find);
-				}
-			}
-
-			if (updateDrawableGeom(drawablep, TRUE))
-			{
-				drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
-				mBuildQ1.erase(curiter);
-			}
-		}
-		else
-		{
-			mBuildQ1.erase(curiter);
-		}
-	}
-		
-	// Iterate through some drawables on the non-priority build queue
-	S32 min_count = 16;
-	S32 size = (S32) mBuildQ2.size();
-	if (size > 1024)
-	{
-		min_count = llclamp((S32) (size * (F32) size/4096), 16, size);
-	}
-		
-	S32 count = 0;
-	
-	max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
-	LLSpatialGroup* last_group = NULL;
-	LLSpatialBridge* last_bridge = NULL;
-
-	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
-		 iter != mBuildQ2.end(); )
-	{
-		LLDrawable::drawable_list_t::iterator curiter = iter++;
-		LLDrawable* drawablep = *curiter;
-
-		LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
-									drawablep->getParent()->getSpatialBridge();
-
-		if (drawablep->getSpatialGroup() != last_group && 
-			(!last_bridge || bridge != last_bridge) &&
-			(update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
-		{
-			break;
-		}
-
-		//make sure updates don't stop in the middle of a spatial group
-		//to avoid thrashing (objects are enqueued by group)
-		last_group = drawablep->getSpatialGroup();
-		last_bridge = bridge;
-
-		BOOL update_complete = TRUE;
-		if (!drawablep->isDead())
-		{
-			update_complete = updateDrawableGeom(drawablep, FALSE);
-			count++;
-		}
-		if (update_complete)
-		{
-			drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
-			mBuildQ2.erase(curiter);
-		}
-	}	
-
-	updateMovedList(mMovedBridge);
-}
-
-void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_VISIBLE);
-
-	if(drawablep && !drawablep->isDead())
-	{
-		if (drawablep->isSpatialBridge())
-		{
-			const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
-			llassert(root); // trying to catch a bad assumption
-			if (root && //  // this test may not be needed, see above
-					root->getVObj()->isAttachment())
-			{
-				LLDrawable* rootparent = root->getParent();
-				if (rootparent) // this IS sometimes NULL
-				{
-					LLViewerObject *vobj = rootparent->getVObj();
-					llassert(vobj); // trying to catch a bad assumption
-					if (vobj) // this test may not be needed, see above
-					{
-						const LLVOAvatar* av = vobj->asAvatar();
-						if (av && av->isImpostor())
-						{
-							return;
-						}
-					}
-				}
-			}
-			sCull->pushBridge((LLSpatialBridge*) drawablep);
-		}
-		else
-		{
-			sCull->pushDrawable(drawablep);
-		}
-
-		drawablep->setVisible(camera);
-	}
-}
-
-void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
-{
-	LLMemType mt_mm(LLMemType::MTYPE_PIPELINE_MARK_MOVED);
-
-	if (!drawablep)
-	{
-		//llerrs << "Sending null drawable to moved list!" << llendl;
-		return;
-	}
-	
-	if (drawablep->isDead())
-	{
-		llwarns << "Marking NULL or dead drawable moved!" << llendl;
-		return;
-	}
-	
-	if (drawablep->getParent()) 
-	{
-		//ensure that parent drawables are moved first
-		markMoved(drawablep->getParent(), damped_motion);
-	}
-
-	assertInitialized();
-
-	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
-	{
-		if (drawablep->isSpatialBridge())
-		{
-			mMovedBridge.push_back(drawablep);
-		}
-		else
-		{
-			mMovedList.push_back(drawablep);
-		}
-		drawablep->setState(LLDrawable::ON_MOVE_LIST);
-	}
-	if (damped_motion == FALSE)
-	{
-		drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED
-	}
-	else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
-	{
-		drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
-	}
-}
-
-void LLPipeline::markShift(LLDrawable *drawablep)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_SHIFT);
-
-	if (!drawablep || drawablep->isDead())
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
-	{
-		drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
-		if (drawablep->getParent()) 
-		{
-			markShift(drawablep->getParent());
-		}
-		mShiftList.push_back(drawablep);
-		drawablep->setState(LLDrawable::ON_SHIFT_LIST);
-	}
-}
-
-void LLPipeline::shiftObjects(const LLVector3 &offset)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS);
-
-	assertInitialized();
-
-	glClear(GL_DEPTH_BUFFER_BIT);
-	gDepthDirty = TRUE;
-		
-	for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
-		 iter != mShiftList.end(); iter++)
-	{
-		LLDrawable *drawablep = *iter;
-		if (drawablep->isDead())
-		{
-			continue;
-		}	
-		drawablep->shiftPos(offset);	
-		drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
-	}
-	mShiftList.resize(0);
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				part->shift(offset);
-			}
-		}
-	}
-
-	LLHUDText::shiftAll(offset);
-	LLHUDNameTag::shiftAll(offset);
-	display_update_camera();
-}
-
-void LLPipeline::markTextured(LLDrawable *drawablep)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_TEXTURED);
-
-	if (drawablep && !drawablep->isDead() && assertInitialized())
-	{
-		mRetexturedList.insert(drawablep);
-	}
-}
-
-void LLPipeline::markGLRebuild(LLGLUpdate* glu)
-{
-	if (glu && !glu->mInQ)
-	{
-		LLGLUpdate::sGLQ.push_back(glu);
-		glu->mInQ = TRUE;
-	}
-}
-
-void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	//assert_main_thread();
-
-	if (group && !group->isDead() && group->mSpatialPartition)
-	{
-		if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
-		{
-			priority = TRUE;
-		}
-
-		if (priority)
-		{
-			if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
-			{
-				mGroupQ1.push_back(group);
-				group->setState(LLSpatialGroup::IN_BUILD_Q1);
-
-				if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
-				{
-					LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
-					if (iter != mGroupQ2.end())
-					{
-						mGroupQ2.erase(iter);
-					}
-					group->clearState(LLSpatialGroup::IN_BUILD_Q2);
-				}
-			}
-		}
-		else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
-		{
-			//llerrs << "Non-priority updates not yet supported!" << llendl;
-			if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end())
-			{
-				llerrs << "WTF?" << llendl;
-			}
-			mGroupQ2.push_back(group);
-			group->setState(LLSpatialGroup::IN_BUILD_Q2);
-
-		}
-	}
-}
-
-void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_REBUILD);
-
-	if (drawablep && !drawablep->isDead() && assertInitialized())
-	{
-		if (!drawablep->isState(LLDrawable::BUILT))
-		{
-			priority = TRUE;
-		}
-		if (priority)
-		{
-			if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
-			{
-				mBuildQ1.push_back(drawablep);
-				drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
-			}
-		}
-		else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
-		{
-			mBuildQ2.push_back(drawablep);
-			drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
-		}
-		if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
-		{
-			drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
-		}
-		drawablep->setState(flag);
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order");
-
-void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
-{
-	if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
-					  LLPipeline::RENDER_TYPE_GROUND,
-					  LLPipeline::RENDER_TYPE_TERRAIN,
-					  LLPipeline::RENDER_TYPE_TREE,
-					  LLPipeline::RENDER_TYPE_SKY,
-					  LLPipeline::RENDER_TYPE_VOIDWATER,
-					  LLPipeline::RENDER_TYPE_WATER,
-					  LLPipeline::END_RENDER_TYPES))
-	{
-		//clear faces from face pools
-		LLFastTimer t(FTM_RESET_DRAWORDER);
-		gPipeline.resetDrawOrders();
-	}
-
-	LLFastTimer ftm(FTM_STATESORT);
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-
-	//LLVertexBuffer::unbind();
-
-	grabReferences(result);
-	for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
-	{
-		LLSpatialGroup* group = *iter;
-		group->checkOcclusion();
-		if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{
-			markOccluder(group);
-		}
-		else
-		{
-			group->setVisible();
-			for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
-			{
-				markVisible(*i, camera);
-			}
-		}
-	}
-	for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
-	{
-		LLSpatialGroup* group = *iter;
-		group->checkOcclusion();
-		if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{
-			markOccluder(group);
-		}
-		else
-		{
-			group->setVisible();
-			stateSort(group, camera);
-		}
-	}
-	
-	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-	{
-		for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
-		{
-			LLCullResult::bridge_list_t::iterator cur_iter = i;
-			LLSpatialBridge* bridge = *cur_iter;
-			LLSpatialGroup* group = bridge->getSpatialGroup();
-			if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-			{
-				stateSort(bridge, camera);
-			}
-		}
-	}
-	{
-		LLFastTimer ftm(FTM_STATESORT_DRAWABLE);
-		for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
-			 iter != sCull->endVisibleList(); ++iter)
-		{
-			LLDrawable *drawablep = *iter;
-			if (!drawablep->isDead())
-			{
-				stateSort(drawablep, camera);
-			}
-		}
-	}
-	{
-		LLFastTimer ftm(FTM_CLIENT_COPY);
-		LLVertexBuffer::clientCopy();
-	}
-	
-	postSort(camera);	
-}
-
-void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-	if (group->changeLOD())
-	{
-		for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
-		{
-			LLDrawable* drawablep = *i;
-			stateSort(drawablep, camera);
-		}
-	}
-
-}
-
-void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-	if (!sShadowRender && bridge->getSpatialGroup()->changeLOD())
-	{
-		bool force_update = false;
-		bridge->updateDistance(camera, force_update);
-	}
-}
-
-void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
-		
-	if (!drawablep
-		|| drawablep->isDead() 
-		|| !hasRenderType(drawablep->getRenderType()))
-	{
-		return;
-	}
-	
-	if (LLSelectMgr::getInstance()->mHideSelectedObjects)
-	{
-		if (drawablep->getVObj().notNull() &&
-			drawablep->getVObj()->isSelected())
-		{
-			return;
-		}
-	}
-
-	if (drawablep->isAvatar())
-	{ //don't draw avatars beyond render distance or if we don't have a spatial group.
-		if ((drawablep->getSpatialGroup() == NULL) || 
-			(drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance))
-		{
-			return;
-		}
-
-		LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get();
-		if (!avatarp->isVisible())
-		{
-			return;
-		}
-	}
-
-	assertInitialized();
-
-	if (hasRenderType(drawablep->mRenderType))
-	{
-		if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
-		{
-			drawablep->setVisible(camera, NULL, FALSE);
-		}
-		else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
-		{
-			// clear invisible flag here to avoid single frame glitch
-			drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
-		}
-	}
-
-	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-	{
-		LLSpatialGroup* group = drawablep->getSpatialGroup();
-		if (!group || group->changeLOD())
-		{
-			if (drawablep->isVisible())
-			{
-				if (!drawablep->isActive())
-				{
-					bool force_update = false;
-					drawablep->updateDistance(camera, force_update);
-				}
-				else if (drawablep->isAvatar())
-				{
-					bool force_update = false;
-					drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
-				}
-			}
-		}
-	}
-
-	if (!drawablep->getVOVolume())
-	{
-		for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
-				iter != drawablep->mFaces.end(); iter++)
-		{
-			LLFace* facep = *iter;
-
-			if (facep->hasGeometry())
-			{
-				if (facep->getPool())
-				{
-					facep->getPool()->enqueue(facep);
-				}
-				else
-				{
-					break;
-				}
-			}
-		}
-	}
-	
-
-	mNumVisibleFaces += drawablep->getNumFaces();
-}
-
-
-void forAllDrawables(LLCullResult::sg_list_t::iterator begin, 
-					 LLCullResult::sg_list_t::iterator end,
-					 void (*func)(LLDrawable*))
-{
-	for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i)
-	{
-		for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
-		{
-			func(*j);	
-		}
-	}
-}
-
-void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
-{
-	forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func);
-	forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func);
-}
-
-//function for creating scripted beacons
-void renderScriptedBeacons(LLDrawable* drawablep)
-{
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj 
-		&& !vobj->isAvatar() 
-		&& !vobj->getParent()
-		&& vobj->flagScripted())
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderScriptedTouchBeacons(LLDrawable* drawablep)
-{
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj 
-		&& !vobj->isAvatar() 
-		&& !vobj->getParent()
-		&& vobj->flagScripted()
-		&& vobj->flagHandleTouch())
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderPhysicalBeacons(LLDrawable* drawablep)
-{
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj 
-		&& !vobj->isAvatar() 
-		//&& !vobj->getParent()
-		&& vobj->usePhysics())
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderParticleBeacons(LLDrawable* drawablep)
-{
-	// Look for attachments, objects, etc.
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj 
-		&& vobj->isParticleSource())
-	{
-		if (gPipeline.sRenderBeacons)
-		{
-			LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
-			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
-		}
-
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void renderSoundHighlights(LLDrawable* drawablep)
-{
-	// Look for attachments, objects, etc.
-	LLViewerObject *vobj = drawablep->getVObj();
-	if (vobj && vobj->isAudioSource())
-	{
-		if (gPipeline.sRenderHighlight)
-		{
-			S32 face_id;
-			S32 count = drawablep->getNumFaces();
-			for (face_id = 0; face_id < count; face_id++)
-			{
-				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
-			}
-		}
-	}
-}
-
-void LLPipeline::postSort(LLCamera& camera)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_POST_SORT);
-	LLFastTimer ftm(FTM_STATESORT_POSTSORT);
-
-	assertInitialized();
-
-	llpushcallstacks ;
-	//rebuild drawable geometry
-	for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
-	{
-		LLSpatialGroup* group = *i;
-		if (!sUseOcclusion || 
-			!group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{
-			group->rebuildGeom();
-		}
-	}
-	llpushcallstacks ;
-	//rebuild groups
-	sCull->assertDrawMapsEmpty();
-
-	/*LLSpatialGroup::sNoDelete = FALSE;
-	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
-	{
-		LLSpatialGroup* group = *i;
-		if (sUseOcclusion && 
-			group->isState(LLSpatialGroup::OCCLUDED))
-		{
-			continue;
-		}
-		
-		group->rebuildGeom();
-	}
-	LLSpatialGroup::sNoDelete = TRUE;*/
-
-
-	rebuildPriorityGroups();
-	llpushcallstacks ;
-
-	const S32 bin_count = 1024*8;
-		
-	static LLCullResult::drawinfo_list_t alpha_bins[bin_count];
-	static U32 bin_size[bin_count];
-
-	//clear one bin per frame to avoid memory bloat
-	static S32 clear_idx = 0;
-	clear_idx = (1+clear_idx)%bin_count;
-	alpha_bins[clear_idx].clear();
-
-	for (U32 j = 0; j < bin_count; j++)
-	{
-		bin_size[j] = 0;
-	}
-
-	//build render map
-	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
-	{
-		LLSpatialGroup* group = *i;
-		if (sUseOcclusion && 
-			group->isOcclusionState(LLSpatialGroup::OCCLUDED))
-		{
-			continue;
-		}
-
-		if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
-		{ //no way this group is going to be drawable without a rebuild
-			group->rebuildGeom();
-		}
-
-		for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
-		{
-			LLSpatialGroup::drawmap_elem_t& src_vec = j->second;	
-			if (!hasRenderType(j->first))
-			{
-				continue;
-			}
-			
-			for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
-			{
-				if (sMinRenderSize > 0.f)
-				{
-					LLVector3 bounds = (*k)->mExtents[1]-(*k)->mExtents[0];
-					if (llmax(llmax(bounds.mV[0], bounds.mV[1]), bounds.mV[2]) > sMinRenderSize)
-					{
-						sCull->pushDrawInfo(j->first, *k);
-					}
-				}
-				else
-				{
-					sCull->pushDrawInfo(j->first, *k);
-				}
-			}
-		}
-
-		if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
-		{
-			LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
-			
-			if (alpha != group->mDrawMap.end())
-			{ //store alpha groups for sorting
-				LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
-				if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
-				{
-					if (bridge)
-					{
-						LLCamera trans_camera = bridge->transformCamera(camera);
-						group->updateDistance(trans_camera);
-					}
-					else
-					{
-						group->updateDistance(camera);
-					}
-				}
-							
-				if (hasRenderType(LLDrawPool::POOL_ALPHA))
-				{
-					sCull->pushAlphaGroup(group);
-				}
-			}
-		}
-	}
-		
-	if (!sShadowRender)
-	{
-		//sort by texture or bump map
-		for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i)
-		{
-			if (i == LLRenderPass::PASS_BUMP)
-			{
-				std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump());
-			}
-			else 
-			{
-				std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix());
-			}	
-		}
-
-		std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
-	}
-	llpushcallstacks ;
-	// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
-	if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender)
-	{
-		if (sRenderScriptedTouchBeacons)
-		{
-			// Only show the beacon on the root object.
-			forAllVisibleDrawables(renderScriptedTouchBeacons);
-		}
-		else
-		if (sRenderScriptedBeacons)
-		{
-			// Only show the beacon on the root object.
-			forAllVisibleDrawables(renderScriptedBeacons);
-		}
-
-		if (sRenderPhysicalBeacons)
-		{
-			// Only show the beacon on the root object.
-			forAllVisibleDrawables(renderPhysicalBeacons);
-		}
-
-		if (sRenderParticleBeacons)
-		{
-			forAllVisibleDrawables(renderParticleBeacons);
-		}
-
-		// If god mode, also show audio cues
-		if (sRenderSoundBeacons && gAudiop)
-		{
-			// Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible.
-			LLAudioEngine::source_map::iterator iter;
-			for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
-			{
-				LLAudioSource *sourcep = iter->second;
-
-				LLVector3d pos_global = sourcep->getPositionGlobal();
-				LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
-				if (gPipeline.sRenderBeacons)
-				{
-					//pos += LLVector3(0.f, 0.f, 0.2f);
-					gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
-				}
-			}
-			// now deal with highlights for all those seeable sound sources
-			forAllVisibleDrawables(renderSoundHighlights);
-		}
-	}
-	llpushcallstacks ;
-	// If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
-	if (LLFloaterTelehub::renderBeacons())
-	{
-		LLFloaterTelehub::addBeacons();
-	}
-
-	if (!sShadowRender)
-	{
-		mSelectedFaces.clear();
-		
-		// Draw face highlights for selected faces.
-		if (LLSelectMgr::getInstance()->getTEMode())
-		{
-			struct f : public LLSelectedTEFunctor
-			{
-				virtual bool apply(LLViewerObject* object, S32 te)
-				{
-					if (object->mDrawable)
-					{
-						gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
-					}
-					return true;
-				}
-			} func;
-			LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
-		}
-	}
-
-	//LLSpatialGroup::sNoDelete = FALSE;
-	llpushcallstacks ;
-}
-
-
-void render_hud_elements()
-{
-	LLMemType mt_rhe(LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS);
-	LLFastTimer t(FTM_RENDER_UI);
-	gPipeline.disableLights();		
-	
-	LLGLDisable fog(GL_FOG);
-	LLGLSUIDefault gls_ui;
-
-	LLGLEnable stencil(GL_STENCIL_TEST);
-	glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
-	glStencilMask(0xFFFFFFFF);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-	
-	gGL.color4f(1,1,1,1);
-	if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-	{
-		LLGLEnable multisample(GL_MULTISAMPLE_ARB);
-		gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
-	
-		// Draw the tracking overlays
-		LLTracker::render3D();
-		
-		// Show the property lines
-		LLWorld::getInstance()->renderPropertyLines();
-		LLViewerParcelMgr::getInstance()->render();
-		LLViewerParcelMgr::getInstance()->renderParcelCollision();
-	
-		// Render name tags.
-		LLHUDObject::renderAll();
-	}
-	else if (gForceRenderLandFence)
-	{
-		// This is only set when not rendering the UI, for parcel snapshots
-		LLViewerParcelMgr::getInstance()->render();
-	}
-	else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-	{
-		LLHUDText::renderAllHUD();
-	}
-	gGL.flush();
-}
-
-void LLPipeline::renderHighlights()
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_HL);
-
-	assertInitialized();
-
-	// Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
-	// Render highlighted faces.
-	LLGLSPipelineAlpha gls_pipeline_alpha;
-	LLColor4 color(1.f, 1.f, 1.f, 0.5f);
-	LLGLEnable color_mat(GL_COLOR_MATERIAL);
-	disableLights();
-
-	if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
-	{ //draw blurry highlight image over screen
-		LLGLEnable blend(GL_BLEND);
-		LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-		LLGLDisable test(GL_ALPHA_TEST);
-
-		LLGLEnable stencil(GL_STENCIL_TEST);
-		gGL.flush();
-		glStencilMask(0xFFFFFFFF);
-		glClearStencil(1);
-		glClear(GL_STENCIL_BUFFER_BIT);
-
-		glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
-		glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
-				
-		gGL.setColorMask(false, false);
-		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
-		{
-			renderHighlight(iter->mItem->getVObj(), 1.f);
-		}
-		gGL.setColorMask(true, false);
-
-		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-		glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
-		
-		//gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-
-		gGL.pushMatrix();
-		glLoadIdentity();
-		glMatrixMode(GL_PROJECTION);
-		gGL.pushMatrix();
-		glLoadIdentity();
-
-		gGL.getTexUnit(0)->bind(&mHighlight);
-
-		LLVector2 tc1;
-		LLVector2 tc2;
-
-		tc1.setVec(0,0);
-		tc2.setVec(2,2);
-
-		gGL.begin(LLRender::TRIANGLES);
-				
-		F32 scale = gSavedSettings.getF32("RenderHighlightBrightness");
-		LLColor4 color = gSavedSettings.getColor4("RenderHighlightColor");
-		F32 thickness = gSavedSettings.getF32("RenderHighlightThickness");
-
-		for (S32 pass = 0; pass < 2; ++pass)
-		{
-			if (pass == 0)
-			{
-				gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-			}
-			else
-			{
-				gGL.setSceneBlendType(LLRender::BT_ALPHA);
-			}
-
-			for (S32 i = 0; i < 8; ++i)
-			{
-				for (S32 j = 0; j < 8; ++j)
-				{
-					LLVector2 tc(i-4+0.5f, j-4+0.5f);
-
-					F32 dist = 1.f-(tc.length()/sqrtf(32.f));
-					dist *= scale/64.f;
-
-					tc *= thickness;
-					tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
-					tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
-
-					gGL.color4f(color.mV[0],
-								color.mV[1],
-								color.mV[2],
-								color.mV[3]*dist);
-					
-					gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
-					gGL.vertex2f(-1,3);
-					
-					gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
-					gGL.vertex2f(-1,-1);
-					
-					gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
-					gGL.vertex2f(3,-1);
-				}
-			}
-		}
-
-		gGL.end();
-
-		gGL.popMatrix();
-		glMatrixMode(GL_MODELVIEW);
-		gGL.popMatrix();
-		
-		//gGL.setSceneBlendType(LLRender::BT_ALPHA);
-	}
-
-	if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
-	{
-		gHighlightProgram.bind();
-		gHighlightProgram.vertexAttrib4f(LLViewerShaderMgr::MATERIAL_COLOR,1,1,1,0.5f);
-	}
-	
-	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
-	{
-		// Make sure the selection image gets downloaded and decoded
-		if (!mFaceSelectImagep)
-		{
-			mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
-		}
-		mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
-
-		U32 count = mSelectedFaces.size();
-		for (U32 i = 0; i < count; i++)
-		{
-			LLFace *facep = mSelectedFaces[i];
-			if (!facep || facep->getDrawable()->isDead())
-			{
-				llerrs << "Bad face on selection" << llendl;
-				return;
-			}
-			
-			facep->renderSelected(mFaceSelectImagep, color);
-		}
-	}
-
-	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
-	{
-		// Paint 'em red!
-		color.setVec(1.f, 0.f, 0.f, 0.5f);
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
-		{
-			gHighlightProgram.vertexAttrib4f(LLViewerShaderMgr::MATERIAL_COLOR,1,0,0,0.5f);
-		}
-		int count = mHighlightFaces.size();
-		for (S32 i = 0; i < count; i++)
-		{
-			LLFace* facep = mHighlightFaces[i];
-			facep->renderSelected(LLViewerTexture::sNullImagep, color);
-		}
-	}
-
-	// Contains a list of the faces of objects that are physical or
-	// have touch-handlers.
-	mHighlightFaces.clear();
-
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
-	{
-		gHighlightProgram.unbind();
-	}
-}
-
-//debug use
-U32 LLPipeline::sCurRenderPoolType = 0 ;
-
-void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_GEOM);
-	LLFastTimer t(FTM_RENDER_GEOMETRY);
-
-	assertInitialized();
-
-	F64 saved_modelview[16];
-	F64 saved_projection[16];
-
-	//HACK: preserve/restore matrices around HUD render
-	if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-	{
-		for (U32 i = 0; i < 16; i++)
-		{
-			saved_modelview[i] = gGLModelView[i];
-			saved_projection[i] = gGLProjection[i];
-		}
-	}
-
-	///////////////////////////////////////////
-	//
-	// Sync and verify GL state
-	//
-	//
-
-	stop_glerror();
-
-	LLVertexBuffer::unbind();
-
-	// Do verification of GL state
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-	if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
-	{
-		if (!verify())
-		{
-			llerrs << "Pipeline verification failed!" << llendl;
-		}
-	}
-
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
-	
-	// Initialize lots of GL state to "safe" values
-	glMatrixMode(GL_TEXTURE);
-	glLoadIdentity();
-	glMatrixMode(GL_MODELVIEW);
-
-	LLGLSPipeline gls_pipeline;
-	LLGLEnable multisample(GL_MULTISAMPLE_ARB);
-
-	LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
-				
-	// Toggle backface culling for debugging
-	LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
-	// Set fog
-	BOOL use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG);
-	LLGLEnable fog_enable(use_fog &&
-						  !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0);
-	gSky.updateFog(camera.getFar());
-	if (!use_fog)
-	{
-		sUnderWaterRender = FALSE;
-	}
-
-	gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep);
-	LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
-	
-	//////////////////////////////////////////////
-	//
-	// Actually render all of the geometry
-	//
-	//	
-	stop_glerror();
-	
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
-
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		if (hasRenderType(poolp->getType()))
-		{
-			poolp->prerender();
-		}
-	}
-
-	{
-		LLFastTimer t(FTM_POOLS);
-		
-		// HACK: don't calculate local lights if we're rendering the HUD!
-		//    Removing this check will cause bad flickering when there are 
-		//    HUD elements being rendered AND the user is in flycam mode  -nyx
-		if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{
-			calcNearbyLights(camera);
-			setupHWLights(NULL);
-		}
-
-		BOOL occlude = sUseOcclusion > 1;
-		U32 cur_type = 0;
-
-		pool_set_t::iterator iter1 = mPools.begin();
-		while ( iter1 != mPools.end() )
-		{
-			LLDrawPool *poolp = *iter1;
-			
-			cur_type = poolp->getType();
-
-			//debug use
-			sCurRenderPoolType = cur_type ;
-
-			if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
-			{
-				occlude = FALSE;
-				gGLLastMatrix = NULL;
-				glLoadMatrixd(gGLModelView);
-				doOcclusion(camera);
-			}
-
-			pool_set_t::iterator iter2 = iter1;
-			if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
-			{
-				LLFastTimer t(FTM_POOLRENDER);
-
-				gGLLastMatrix = NULL;
-				glLoadMatrixd(gGLModelView);
-			
-				for( S32 i = 0; i < poolp->getNumPasses(); i++ )
-				{
-					LLVertexBuffer::unbind();
-					poolp->beginRenderPass(i);
-					for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-					{
-						LLDrawPool *p = *iter2;
-						if (p->getType() != cur_type)
-						{
-							break;
-						}
-						
-						p->render(i);
-					}
-					poolp->endRenderPass(i);
-					LLVertexBuffer::unbind();
-					if (gDebugGL || gDebugPipeline)
-					{
-						GLint depth;
-						glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
-						if (depth > 3)
-						{
-							if (gDebugSession)
-							{
-								ll_fail("GL matrix stack corrupted.");
-							}
-							llerrs << "GL matrix stack corrupted!" << llendl;
-						}
-						std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i);
-						LLGLState::checkStates(msg);
-						LLGLState::checkTextureChannels(msg);
-						LLGLState::checkClientArrays(msg);
-					}
-				}
-			}
-			else
-			{
-				// Skip all pools of this type
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
-					{
-						break;
-					}
-				}
-			}
-			iter1 = iter2;
-			stop_glerror();
-		}
-	
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd");
-
-	LLVertexBuffer::unbind();
-		
-		gGLLastMatrix = NULL;
-		glLoadMatrixd(gGLModelView);
-
-		if (occlude)
-		{
-			occlude = FALSE;
-			gGLLastMatrix = NULL;
-			glLoadMatrixd(gGLModelView);
-			doOcclusion(camera);
-		}
-	}
-
-	LLVertexBuffer::unbind();
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-
-	
-
-	stop_glerror();
-		
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
-
-	if (!sReflectionRender)
-	{
-		renderHighlights();
-	}
-
-	// Contains a list of the faces of objects that are physical or
-	// have touch-handlers.
-	mHighlightFaces.clear();
-
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
-	
-	renderDebug();
-
-	LLVertexBuffer::unbind();
-	
-	if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
-	{
-		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-		{
-		      // Render debugging beacons.
-		      gObjectList.renderObjectBeacons();
-		      gObjectList.resetObjectBeacons();
-		}
-		else
-		{
-			// Make sure particle effects disappear
-			LLHUDObject::renderAllForTimer();
-		}
-	}
-	else
-	{
-		// Make sure particle effects disappear
-		LLHUDObject::renderAllForTimer();
-	}
-
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
-
-	//HACK: preserve/restore matrices around HUD render
-	if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-	{
-		for (U32 i = 0; i < 16; i++)
-		{
-			gGLModelView[i] = saved_modelview[i];
-			gGLProjection[i] = saved_projection[i];
-		}
-	}
-
-	LLVertexBuffer::unbind();
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-}
-
-void LLPipeline::renderGeomDeferred(LLCamera& camera)
-{
-	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
-
-	LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED);
-	LLFastTimer t(FTM_RENDER_GEOMETRY);
-
-	LLFastTimer t2(FTM_POOLS);
-
-	LLGLEnable cull(GL_CULL_FACE);
-
-	LLGLEnable stencil(GL_STENCIL_TEST);
-	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
-	stop_glerror();
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-	stop_glerror();
-
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		if (hasRenderType(poolp->getType()))
-		{
-			poolp->prerender();
-		}
-	}
-
-	LLGLEnable multisample(GL_MULTISAMPLE_ARB);
-
-	LLVertexBuffer::unbind();
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-
-	U32 cur_type = 0;
-
-	gGL.setColorMask(true, true);
-	
-	pool_set_t::iterator iter1 = mPools.begin();
-
-	while ( iter1 != mPools.end() )
-	{
-		LLDrawPool *poolp = *iter1;
-		
-		cur_type = poolp->getType();
-
-		pool_set_t::iterator iter2 = iter1;
-		if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
-		{
-			LLFastTimer t(FTM_POOLRENDER);
-
-			gGLLastMatrix = NULL;
-			glLoadMatrixd(gGLModelView);
-		
-			for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
-			{
-				LLVertexBuffer::unbind();
-				poolp->beginDeferredPass(i);
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
-					{
-						break;
-					}
-										
-					p->renderDeferred(i);
-				}
-				poolp->endDeferredPass(i);
-				LLVertexBuffer::unbind();
-
-				if (gDebugGL || gDebugPipeline)
-				{
-					GLint depth;
-					glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
-					if (depth > 3)
-					{
-						llerrs << "GL matrix stack corrupted!" << llendl;
-					}
-					LLGLState::checkStates();
-					LLGLState::checkTextureChannels();
-					LLGLState::checkClientArrays();
-				}
-			}
-		}
-		else
-		{
-			// Skip all pools of this type
-			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-			{
-				LLDrawPool *p = *iter2;
-				if (p->getType() != cur_type)
-				{
-					break;
-				}
-			}
-		}
-		iter1 = iter2;
-		stop_glerror();
-	}
-
-	gGLLastMatrix = NULL;
-	glLoadMatrixd(gGLModelView);
-
-	gGL.setColorMask(true, false);
-}
-
-void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
-{
-	LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF);
-	LLFastTimer t(FTM_POOLS);
-	U32 cur_type = 0;
-
-	LLGLEnable cull(GL_CULL_FACE);
-
-	LLGLEnable multisample(GL_MULTISAMPLE_ARB);
-
-	calcNearbyLights(camera);
-	setupHWLights(NULL);
-
-	gGL.setColorMask(true, false);
-
-	pool_set_t::iterator iter1 = mPools.begin();
-	BOOL occlude = LLPipeline::sUseOcclusion > 1;
-
-	while ( iter1 != mPools.end() )
-	{
-		LLDrawPool *poolp = *iter1;
-		
-		cur_type = poolp->getType();
-
-		if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
-		{
-			occlude = FALSE;
-			gGLLastMatrix = NULL;
-			glLoadMatrixd(gGLModelView);
-			doOcclusion(camera);
-			gGL.setColorMask(true, false);
-		}
-
-		pool_set_t::iterator iter2 = iter1;
-		if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
-		{
-			LLFastTimer t(FTM_POOLRENDER);
-
-			gGLLastMatrix = NULL;
-			glLoadMatrixd(gGLModelView);
-		
-			for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ )
-			{
-				LLVertexBuffer::unbind();
-				poolp->beginPostDeferredPass(i);
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
-					{
-						break;
-					}
-										
-					p->renderPostDeferred(i);
-				}
-				poolp->endPostDeferredPass(i);
-				LLVertexBuffer::unbind();
-
-				if (gDebugGL || gDebugPipeline)
-				{
-					GLint depth;
-					glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
-					if (depth > 3)
-					{
-						llerrs << "GL matrix stack corrupted!" << llendl;
-					}
-					LLGLState::checkStates();
-					LLGLState::checkTextureChannels();
-					LLGLState::checkClientArrays();
-				}
-			}
-		}
-		else
-		{
-			// Skip all pools of this type
-			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-			{
-				LLDrawPool *p = *iter2;
-				if (p->getType() != cur_type)
-				{
-					break;
-				}
-			}
-		}
-		iter1 = iter2;
-		stop_glerror();
-	}
-
-	gGLLastMatrix = NULL;
-	glLoadMatrixd(gGLModelView);
-
-	if (occlude)
-	{
-		occlude = FALSE;
-		gGLLastMatrix = NULL;
-		glLoadMatrixd(gGLModelView);
-		doOcclusion(camera);
-		gGLLastMatrix = NULL;
-		glLoadMatrixd(gGLModelView);
-	}
-}
-
-void LLPipeline::renderGeomShadow(LLCamera& camera)
-{
-	LLMemType mt_rgs(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW);
-	U32 cur_type = 0;
-	
-	LLGLEnable cull(GL_CULL_FACE);
-
-	LLVertexBuffer::unbind();
-
-	pool_set_t::iterator iter1 = mPools.begin();
-	
-	while ( iter1 != mPools.end() )
-	{
-		LLDrawPool *poolp = *iter1;
-		
-		cur_type = poolp->getType();
-
-		pool_set_t::iterator iter2 = iter1;
-		if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0)
-		{
-			gGLLastMatrix = NULL;
-			glLoadMatrixd(gGLModelView);
-		
-			for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ )
-			{
-				LLVertexBuffer::unbind();
-				poolp->beginShadowPass(i);
-				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-				{
-					LLDrawPool *p = *iter2;
-					if (p->getType() != cur_type)
-					{
-						break;
-					}
-										
-					p->renderShadow(i);
-				}
-				poolp->endShadowPass(i);
-				LLVertexBuffer::unbind();
-
-				LLGLState::checkStates();
-				LLGLState::checkTextureChannels();
-				LLGLState::checkClientArrays();
-			}
-		}
-		else
-		{
-			// Skip all pools of this type
-			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
-			{
-				LLDrawPool *p = *iter2;
-				if (p->getType() != cur_type)
-				{
-					break;
-				}
-			}
-		}
-		iter1 = iter2;
-		stop_glerror();
-	}
-
-	gGLLastMatrix = NULL;
-	glLoadMatrixd(gGLModelView);
-}
-
-
-void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
-{
-	assertInitialized();
-	S32 count = 0;
-	if (render_type == LLRender::TRIANGLE_STRIP)
-	{
-		count = index_count-2;
-	}
-	else
-	{
-		count = index_count/3;
-	}
-
-	mTrianglesDrawn += count;
-	mBatchCount++;
-	mMaxBatchSize = llmax(mMaxBatchSize, count);
-	mMinBatchSize = llmin(mMinBatchSize, count);
-
-	if (LLPipeline::sRenderFrameTest)
-	{
-		gViewerWindow->getWindow()->swapBuffers();
-		ms_sleep(16);
-	}
-}
-
-void LLPipeline::renderDebug()
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-
-	assertInitialized();
-
-	gGL.color4f(1,1,1,1);
-
-	gGLLastMatrix = NULL;
-	glLoadMatrixd(gGLModelView);
-	gGL.setColorMask(true, false);
-
-	// Debug stuff.
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				if (hasRenderType(part->mDrawableType))
-				{
-					part->renderDebug();
-				}
-			}
-		}
-	}
-
-	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
-	{
-		LLSpatialBridge* bridge = *i;
-		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
-		{
-			glPushMatrix();
-			glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
-			bridge->renderDebug();
-			glPopMatrix();
-		}
-	}
-
-	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-	{
-		LLGLEnable blend(GL_BLEND);
-		LLGLDepthTest depth(TRUE, FALSE);
-		LLGLDisable cull(GL_CULL_FACE);
-
-		gGL.color4f(1,1,1,1);
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-				
-		F32 a = 0.1f;
-
-		F32 col[] =
-		{
-			1,0,0,a,
-			0,1,0,a,
-			0,0,1,a,
-			1,0,1,a,
-			
-			1,1,0,a,
-			0,1,1,a,
-			1,1,1,a,
-			1,0,1,a,
-		};
-
-		for (U32 i = 0; i < 8; i++)
-		{
-			LLVector3* frust = mShadowCamera[i].mAgentFrustum;
-
-			if (i > 3)
-			{ //render shadow frusta as volumes
-				if (mShadowFrustPoints[i-4].empty())
-			{
-					continue;
-				}
-
-				gGL.color4fv(col+(i-4)*4);	
-			
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
-				gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
-				gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
-				gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
-				gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
-				gGL.end();
-				
-				
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.vertex3fv(frust[0].mV);
-				gGL.vertex3fv(frust[1].mV);
-				gGL.vertex3fv(frust[3].mV);
-				gGL.vertex3fv(frust[2].mV);
-				gGL.end();
-				
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.vertex3fv(frust[4].mV);
-				gGL.vertex3fv(frust[5].mV);
-				gGL.vertex3fv(frust[7].mV);
-				gGL.vertex3fv(frust[6].mV);
-				gGL.end();		
-			}
-
-	
-			if (i < 4)
-			{
-				
-				if (i == 0 || !mShadowFrustPoints[i].empty())
-				{
-					//render visible point cloud
-					gGL.flush();
-					glPointSize(8.f);
-					gGL.begin(LLRender::POINTS);
-					
-					F32* c = col+i*4;
-					gGL.color3fv(c);
-
-					for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j)
-						{
-							gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
-						
-						}
-					gGL.end();
-
-					gGL.flush();
-					glPointSize(1.f);
-
-					LLVector3* ext = mShadowExtents[i]; 
-					LLVector3 pos = (ext[0]+ext[1])*0.5f;
-					LLVector3 size = (ext[1]-ext[0])*0.5f;
-					drawBoxOutline(pos, size);
-
-					//render camera frustum splits as outlines
-					gGL.begin(LLRender::LINES);
-					gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
-					gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
-					gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
-					gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
-					gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
-					gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
-					gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
-					gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
-					gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
-					gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
-					gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
-					gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
-					gGL.end();
-					}
-
-			}
-
-			/*for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-					iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-			{
-				LLViewerRegion* region = *iter;
-				for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
-				{
-					LLSpatialPartition* part = region->getSpatialPartition(j);
-					if (part)
-					{
-						if (hasRenderType(part->mDrawableType))
-						{
-							part->renderIntersectingBBoxes(&mShadowCamera[i]);
-						}
-					}
-				}
-			}*/
-		}
-	}
-
-	if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
-	{
-		// Debug composition layers
-		F32 x, y;
-
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-		if (gAgent.getRegion())
-		{
-			gGL.begin(LLRender::POINTS);
-			// Draw the composition layer for the region that I'm in.
-			for (x = 0; x <= 260; x++)
-			{
-				for (y = 0; y <= 260; y++)
-				{
-					if ((x > 255) || (y > 255))
-					{
-						gGL.color4f(1.f, 0.f, 0.f, 1.f);
-					}
-					else
-					{
-						gGL.color4f(0.f, 0.f, 1.f, 1.f);
-					}
-					F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
-					z *= 5.f;
-					z += 50.f;
-					gGL.vertex3f(x, y, z);
-				}
-			}
-			gGL.end();
-		}
-	}
-
-	if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE)
-	{
-		U32 count = 0;
-		U32 size = mBuildQ2.size();
-		LLColor4 col;
-
-		LLGLEnable blend(GL_BLEND);
-		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
-		
-		for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter)
-		{
-			LLSpatialGroup* group = *iter;
-			if (group->isDead())
-			{
-				continue;
-			}
-
-			LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
-
-			if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
-			{
-				continue;
-			}
-
-			if (bridge)
-			{
-				gGL.pushMatrix();
-				glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
-			}
-
-			F32 alpha = (F32) (size-count)/size;
-
-			
-			LLVector2 c(1.f-alpha, alpha);
-			c.normVec();
-
-			
-			++count;
-			col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.1f);
-			group->drawObjectBox(col);
-
-			if (bridge)
-			{
-				gGL.popMatrix();
-			}
-		}
-	}
-
-	gGL.flush();
-}
-
-void LLPipeline::rebuildPools()
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS);
-
-	assertInitialized();
-
-	S32 max_count = mPools.size();
-	pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
-	while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
-	{
-		if (iter1 == mPools.end())
-		{
-			iter1 = mPools.begin();
-		}
-		LLDrawPool* poolp = *iter1;
-
-		if (poolp->isDead())
-		{
-			mPools.erase(iter1++);
-			removeFromQuickLookup( poolp );
-			if (poolp == mLastRebuildPool)
-			{
-				mLastRebuildPool = NULL;
-			}
-			delete poolp;
-		}
-		else
-		{
-			mLastRebuildPool = poolp;
-			iter1++;
-		}
-		max_count--;
-	}
-
-	if (isAgentAvatarValid())
-	{
-		gAgentAvatarp->rebuildHUD();
-	}
-}
-
-void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
-{
-	LLMemType mt(LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP);
-
-	assertInitialized();
-
-	switch( new_poolp->getType() )
-	{
-	case LLDrawPool::POOL_SIMPLE:
-		if (mSimplePool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate simple pool." << llendl;
-		}
-		else
-		{
-			mSimplePool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_GRASS:
-		if (mGrassPool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate grass pool." << llendl;
-		}
-		else
-		{
-			mGrassPool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_FULLBRIGHT:
-		if (mFullbrightPool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate simple pool." << llendl;
-		}
-		else
-		{
-			mFullbrightPool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_INVISIBLE:
-		if (mInvisiblePool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate simple pool." << llendl;
-		}
-		else
-		{
-			mInvisiblePool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_GLOW:
-		if (mGlowPool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate glow pool." << llendl;
-		}
-		else
-		{
-			mGlowPool = (LLRenderPass*) new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_TREE:
-		mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
-		break;
- 
-	case LLDrawPool::POOL_TERRAIN:
-		mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
-		break;
-
-	case LLDrawPool::POOL_BUMP:
-		if (mBumpPool)
-		{
-			llassert(0);
-			llwarns << "Ignoring duplicate bump pool." << llendl;
-		}
-		else
-		{
-			mBumpPool = new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_ALPHA:
-		if( mAlphaPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
-		}
-		else
-		{
-			mAlphaPool = new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_AVATAR:
-		break; // Do nothing
-
-	case LLDrawPool::POOL_SKY:
-		if( mSkyPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
-		}
-		else
-		{
-			mSkyPool = new_poolp;
-		}
-		break;
-	
-	case LLDrawPool::POOL_WATER:
-		if( mWaterPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
-		}
-		else
-		{
-			mWaterPool = new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_GROUND:
-		if( mGroundPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
-		}
-		else
-		{ 
-			mGroundPool = new_poolp;
-		}
-		break;
-
-	case LLDrawPool::POOL_WL_SKY:
-		if( mWLSkyPool )
-		{
-			llassert(0);
-			llwarns << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << llendl;
-		}
-		else
-		{ 
-			mWLSkyPool = new_poolp;
-		}
-		break;
-
-	default:
-		llassert(0);
-		llwarns << "Invalid Pool Type in  LLPipeline::addPool()" << llendl;
-		break;
-	}
-}
-
-void LLPipeline::removePool( LLDrawPool* poolp )
-{
-	assertInitialized();
-	removeFromQuickLookup(poolp);
-	mPools.erase(poolp);
-	delete poolp;
-}
-
-void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
-{
-	assertInitialized();
-	LLMemType mt(LLMemType::MTYPE_PIPELINE);
-	switch( poolp->getType() )
-	{
-	case LLDrawPool::POOL_SIMPLE:
-		llassert(mSimplePool == poolp);
-		mSimplePool = NULL;
-		break;
-
-	case LLDrawPool::POOL_GRASS:
-		llassert(mGrassPool == poolp);
-		mGrassPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_FULLBRIGHT:
-		llassert(mFullbrightPool == poolp);
-		mFullbrightPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_INVISIBLE:
-		llassert(mInvisiblePool == poolp);
-		mInvisiblePool = NULL;
-		break;
-
-	case LLDrawPool::POOL_WL_SKY:
-		llassert(mWLSkyPool == poolp);
-		mWLSkyPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_GLOW:
-		llassert(mGlowPool == poolp);
-		mGlowPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_TREE:
-		#ifdef _DEBUG
-			{
-				BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
-				llassert( found );
-			}
-		#else
-			mTreePools.erase( (uintptr_t)poolp->getTexture() );
-		#endif
-		break;
-
-	case LLDrawPool::POOL_TERRAIN:
-		#ifdef _DEBUG
-			{
-				BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
-				llassert( found );
-			}
-		#else
-			mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
-		#endif
-		break;
-
-	case LLDrawPool::POOL_BUMP:
-		llassert( poolp == mBumpPool );
-		mBumpPool = NULL;
-		break;
-	
-	case LLDrawPool::POOL_ALPHA:
-		llassert( poolp == mAlphaPool );
-		mAlphaPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_AVATAR:
-		break; // Do nothing
-
-	case LLDrawPool::POOL_SKY:
-		llassert( poolp == mSkyPool );
-		mSkyPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_WATER:
-		llassert( poolp == mWaterPool );
-		mWaterPool = NULL;
-		break;
-
-	case LLDrawPool::POOL_GROUND:
-		llassert( poolp == mGroundPool );
-		mGroundPool = NULL;
-		break;
-
-	default:
-		llassert(0);
-		llwarns << "Invalid Pool Type in  LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
-		break;
-	}
-}
-
-void LLPipeline::resetDrawOrders()
-{
-	assertInitialized();
-	// Iterate through all of the draw pools and rebuild them.
-	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-	{
-		LLDrawPool *poolp = *iter;
-		poolp->resetDrawOrders();
-	}
-}
-
-//============================================================================
-// Once-per-frame setup of hardware lights,
-// including sun/moon, avatar backlight, and up to 6 local lights
-
-void LLPipeline::setupAvatarLights(BOOL for_edit)
-{
-	assertInitialized();
-
-	if (for_edit)
-	{
-		LLColor4 diffuse(1.f, 1.f, 1.f, 0.f);
-		LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f);  // w==0 => directional light
-		LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
-		LLMatrix4 camera_rot(camera_mat.getMat3());
-		camera_rot.invert();
-		LLVector4 light_pos = light_pos_cam * camera_rot;
-		
-		light_pos.normalize();
-
-		mHWLightColors[1] = diffuse;
-		glLightfv(GL_LIGHT1, GL_DIFFUSE,  diffuse.mV);
-		glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
-		glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
-		glLightfv(GL_LIGHT1, GL_POSITION, light_pos.mV); 
-		glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION,  1.0f);
-		glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 	 0.0f);
-		glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
-		glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 		 0.0f);
-		glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 			 180.0f);
-	}
-	else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
-	{
-		LLVector3 opposite_pos = -1.f * mSunDir;
-		LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
-		LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
-		backlight_pos.normalize();
-			
-		LLColor4 light_diffuse = mSunDiffuse;
-		LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
-		F32 max_component = 0.001f;
-		for (S32 i = 0; i < 3; i++)
-		{
-			if (backlight_diffuse.mV[i] > max_component)
-			{
-				max_component = backlight_diffuse.mV[i];
-			}
-		}
-		F32 backlight_mag;
-		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
-		{
-			backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
-		}
-		else
-		{
-			backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
-		}
-		backlight_diffuse *= backlight_mag / max_component;
-
-		mHWLightColors[1] = backlight_diffuse;
-		glLightfv(GL_LIGHT1, GL_POSITION, backlight_pos.mV); // this is just sun/moon direction
-		glLightfv(GL_LIGHT1, GL_DIFFUSE,  backlight_diffuse.mV);
-		glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
-		glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
-		glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION,  1.0f);
-		glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION,    0.0f);
-		glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
-		glLightf (GL_LIGHT1, GL_SPOT_EXPONENT,         0.0f);
-		glLightf (GL_LIGHT1, GL_SPOT_CUTOFF,           180.0f);
-	}
-	else
-	{
-		mHWLightColors[1] = LLColor4::black;
-		glLightfv(GL_LIGHT1, GL_DIFFUSE,  LLColor4::black.mV);
-		glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
-		glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
-	}
-}
-
-static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
-{
-	F32 inten = light->getLightIntensity();
-	if (inten < .001f)
-	{
-		return max_dist;
-	}
-	F32 radius = light->getLightRadius();
-	BOOL selected = light->isSelected();
-	LLVector3 dpos = light->getRenderPosition() - cam_pos;
-	F32 dist2 = dpos.lengthSquared();
-	if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
-	{
-		return max_dist;
-	}
-	F32 dist = fsqrtf(dist2);
-	dist *= 1.f / inten;
-	dist -= radius;
-	if (selected)
-	{
-		dist -= 10000.f; // selected lights get highest priority
-	}
-	if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
-	{
-		// moving lights get a little higher priority (too much causes artifacts)
-		dist -= light->getLightRadius()*0.25f;
-	}
-	return dist;
-}
-
-void LLPipeline::calcNearbyLights(LLCamera& camera)
-{
-	assertInitialized();
-
-	if (LLPipeline::sReflectionRender)
-	{
-		return;
-	}
-
-	if (mLightingDetail >= 1)
-	{
-		// mNearbyLight (and all light_set_t's) are sorted such that
-		// begin() == the closest light and rbegin() == the farthest light
-		const S32 MAX_LOCAL_LIGHTS = 6;
-// 		LLVector3 cam_pos = gAgentCamera.getCameraPositionAgent();
-		LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ?
-						camera.getOrigin() : 
-						gAgent.getPositionAgent();
-
-		F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
-		
-		// UPDATE THE EXISTING NEARBY LIGHTS
-		light_set_t cur_nearby_lights;
-		for (light_set_t::iterator iter = mNearbyLights.begin();
-			iter != mNearbyLights.end(); iter++)
-		{
-			const Light* light = &(*iter);
-			LLDrawable* drawable = light->drawable;
-			LLVOVolume* volight = drawable->getVOVolume();
-			if (!volight || !drawable->isState(LLDrawable::LIGHT))
-			{
-				drawable->clearState(LLDrawable::NEARBY_LIGHT);
-				continue;
-			}
-			if (light->fade <= -LIGHT_FADE_TIME)
-			{
-				drawable->clearState(LLDrawable::NEARBY_LIGHT);
-				continue;
-			}
-			if (!sRenderAttachedLights && volight && volight->isAttachment())
-			{
-				drawable->clearState(LLDrawable::NEARBY_LIGHT);
-				continue;
-			}
-
-			F32 dist = calc_light_dist(volight, cam_pos, max_dist);
-			cur_nearby_lights.insert(Light(drawable, dist, light->fade));
-		}
-		mNearbyLights = cur_nearby_lights;
-				
-		// FIND NEW LIGHTS THAT ARE IN RANGE
-		light_set_t new_nearby_lights;
-		for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
-			 iter != mLights.end(); ++iter)
-		{
-			LLDrawable* drawable = *iter;
-			LLVOVolume* light = drawable->getVOVolume();
-			if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
-			{
-				continue;
-			}
-			if (light->isHUDAttachment())
-			{
-				continue; // no lighting from HUD objects
-			}
-			F32 dist = calc_light_dist(light, cam_pos, max_dist);
-			if (dist >= max_dist)
-			{
-				continue;
-			}
-			if (!sRenderAttachedLights && light && light->isAttachment())
-			{
-				continue;
-			}
-			new_nearby_lights.insert(Light(drawable, dist, 0.f));
-			if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
-			{
-				new_nearby_lights.erase(--new_nearby_lights.end());
-				const Light& last = *new_nearby_lights.rbegin();
-				max_dist = last.dist;
-			}
-		}
-
-		// INSERT ANY NEW LIGHTS
-		for (light_set_t::iterator iter = new_nearby_lights.begin();
-			 iter != new_nearby_lights.end(); iter++)
-		{
-			const Light* light = &(*iter);
-			if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
-			{
-				mNearbyLights.insert(*light);
-				((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
-			}
-			else
-			{
-				// crazy cast so that we can overwrite the fade value
-				// even though gcc enforces sets as const
-				// (fade value doesn't affect sort so this is safe)
-				Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
-				if (light->dist < farthest_light->dist)
-				{
-					if (farthest_light->fade >= 0.f)
-					{
-						farthest_light->fade = -gFrameIntervalSeconds;
-					}
-				}
-				else
-				{
-					break; // none of the other lights are closer
-				}
-			}
-		}
-		
-	}
-}
-
-void LLPipeline::setupHWLights(LLDrawPool* pool)
-{
-	assertInitialized();
-
-	// Ambient
-	LLColor4 ambient = gSky.getTotalAmbientColor();
-	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
-
-	// Light 0 = Sun or Moon (All objects)
-	{
-		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
-		{
-			mSunDir.setVec(gSky.getSunDirection());
-			mSunDiffuse.setVec(gSky.getSunDiffuseColor());
-		}
-		else
-		{
-			mSunDir.setVec(gSky.getMoonDirection());
-			mSunDiffuse.setVec(gSky.getMoonDiffuseColor());
-		}
-
-		F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
-		if (max_color > 1.f)
-		{
-			mSunDiffuse *= 1.f/max_color;
-		}
-		mSunDiffuse.clamp();
-
-		LLVector4 light_pos(mSunDir, 0.0f);
-		LLColor4 light_diffuse = mSunDiffuse;
-		mHWLightColors[0] = light_diffuse;
-		glLightfv(GL_LIGHT0, GL_POSITION, light_pos.mV); // this is just sun/moon direction
-		glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse.mV);
-		glLightfv(GL_LIGHT0, GL_AMBIENT,  LLColor4::black.mV);
-		glLightfv(GL_LIGHT0, GL_SPECULAR, LLColor4::black.mV);
-		glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION,  1.0f);
-		glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION,    0.0f);
-		glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f);
-		glLightf (GL_LIGHT0, GL_SPOT_EXPONENT,         0.0f);
-		glLightf (GL_LIGHT0, GL_SPOT_CUTOFF,           180.0f);
-	}
-	
-	// Light 1 = Backlight (for avatars)
-	// (set by enableLightsAvatar)
-	
-	S32 cur_light = 2;
-	
-	// Nearby lights = LIGHT 2-7
-
-	mLightMovingMask = 0;
-	
-	if (mLightingDetail >= 1)
-	{
-		for (light_set_t::iterator iter = mNearbyLights.begin();
-			 iter != mNearbyLights.end(); ++iter)
-		{
-			LLDrawable* drawable = iter->drawable;
-			LLVOVolume* light = drawable->getVOVolume();
-			if (!light)
-			{
-				continue;
-			}
-			if (drawable->isState(LLDrawable::ACTIVE))
-			{
-				mLightMovingMask |= (1<<cur_light);
-			}
-			
-			LLColor4  light_color = light->getLightColor();
-			light_color.mV[3] = 0.0f;
-
-			F32 fade = iter->fade;
-			if (fade < LIGHT_FADE_TIME)
-			{
-				// fade in/out light
-				if (fade >= 0.f)
-				{
-					fade = fade / LIGHT_FADE_TIME;
-					((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
-				}
-				else
-				{
-					fade = 1.f + fade / LIGHT_FADE_TIME;
-					((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
-				}
-				fade = llclamp(fade,0.f,1.f);
-				light_color *= fade;
-			}
-
-			LLVector3 light_pos(light->getRenderPosition());
-			LLVector4 light_pos_gl(light_pos, 1.0f);
-	
-			F32 light_radius = llmax(light->getLightRadius(), 0.001f);
-
-			F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic?  probably trying to match a historic behavior.
-			float linatten = x / (light_radius); // % of brightness at radius
-
-			mHWLightColors[cur_light] = light_color;
-			S32 gllight = GL_LIGHT0+cur_light;
-			glLightfv(gllight, GL_POSITION, light_pos_gl.mV);
-			glLightfv(gllight, GL_DIFFUSE,  light_color.mV);
-			glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
-			glLightf (gllight, GL_CONSTANT_ATTENUATION,   0.0f);
-			glLightf (gllight, GL_LINEAR_ATTENUATION,     linatten);
-			glLightf (gllight, GL_QUADRATIC_ATTENUATION,  0.0f);
-			if (light->isLightSpotlight() // directional (spot-)light
-			    && (LLPipeline::sRenderDeferred || gSavedSettings.getBOOL("RenderSpotLightsInNondeferred"))) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on
-			{
-				LLVector3 spotparams = light->getSpotLightParams();
-				LLQuaternion quat = light->getRenderRotation();
-				LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction
-				at_axis *= quat;
-				//llinfos << "SPOT!!!!!!! fov: " << spotparams.mV[0] << " focus: " << spotparams.mV[1] << " dir: " << at_axis << llendl;
-				glLightfv(gllight, GL_SPOT_DIRECTION, at_axis.mV);
-				glLightf (gllight, GL_SPOT_EXPONENT,  2.0f); // 2.0 = good old dot product ^ 2
-				glLightf (gllight, GL_SPOT_CUTOFF,    90.0f); // hemisphere
-				const float specular[] = {0.f, 0.f, 0.f, 0.f};
-				glLightfv(gllight, GL_SPECULAR, specular);
-			}
-			else // omnidirectional (point) light
-			{
-			glLightf (gllight, GL_SPOT_EXPONENT,          0.0f);
-			glLightf (gllight, GL_SPOT_CUTOFF,            180.0f);
-
-				// we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight
-				const float specular[] = {0.f, 0.f, 0.f, 1.f};
-				glLightfv(gllight, GL_SPECULAR, specular);
-				//llinfos << "boring light" << llendl;
-			}
-			cur_light++;
-			if (cur_light >= 8)
-			{
-				break; // safety
-			}
-		}
-	}
-	for ( ; cur_light < 8 ; cur_light++)
-	{
-		mHWLightColors[cur_light] = LLColor4::black;
-		S32 gllight = GL_LIGHT0+cur_light;
-		glLightfv(gllight, GL_DIFFUSE,  LLColor4::black.mV);
-		glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
-		glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV);
-	}
-
-	if (isAgentAvatarValid() &&
-		gAgentAvatarp->mSpecialRenderMode == 3)
-	{
-		LLColor4  light_color = LLColor4::white;
-		light_color.mV[3] = 0.0f;
-
-		LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
-		LLVector4 light_pos_gl(light_pos, 1.0f);
-
-		F32 light_radius = 16.f;
-
-			F32 x = 3.f;
-		float linatten = x / (light_radius); // % of brightness at radius
-
-		mHWLightColors[2] = light_color;
-		S32 gllight = GL_LIGHT2;
-		glLightfv(gllight, GL_POSITION, light_pos_gl.mV);
-		glLightfv(gllight, GL_DIFFUSE,  light_color.mV);
-		glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
-		glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV);
-		glLightf (gllight, GL_CONSTANT_ATTENUATION,   0.0f);
-		glLightf (gllight, GL_LINEAR_ATTENUATION,     linatten);
-		glLightf (gllight, GL_QUADRATIC_ATTENUATION,  0.0f);
-		glLightf (gllight, GL_SPOT_EXPONENT,          0.0f);
-		glLightf (gllight, GL_SPOT_CUTOFF,            180.0f);
-	}
-
-	// Init GL state
-	glDisable(GL_LIGHTING);
-	for (S32 gllight=GL_LIGHT0; gllight<=GL_LIGHT7; gllight++)
-	{
-		glDisable(gllight);
-	}
-	mLightMask = 0;
-}
-
-void LLPipeline::enableLights(U32 mask)
-{
-	assertInitialized();
-
-	if (mLightingDetail == 0)
-	{
-		mask &= 0xf003; // sun and backlight only (and fullbright bit)
-	}
-	if (mLightMask != mask)
-	{
-		stop_glerror();
-		if (!mLightMask)
-		{
-			glEnable(GL_LIGHTING);
-		}
-		if (mask)
-		{
-			stop_glerror();
-			for (S32 i=0; i<8; i++)
-			{
-				if (mask & (1<<i))
-				{
-					glEnable(GL_LIGHT0 + i);
-					glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  mHWLightColors[i].mV);
-				}
-				else
-				{
-					glDisable(GL_LIGHT0 + i);
-					glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  LLColor4::black.mV);
-				}
-			}
-			stop_glerror();
-		}
-		else
-		{
-			glDisable(GL_LIGHTING);
-		}
-		stop_glerror();
-		mLightMask = mask;
-		LLColor4 ambient = gSky.getTotalAmbientColor();
-		glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
-		stop_glerror();
-	}
-}
-
-void LLPipeline::enableLightsStatic()
-{
-	assertInitialized();
-	U32 mask = 0x01; // Sun
-	if (mLightingDetail >= 2)
-	{
-		mask |= mLightMovingMask; // Hardware moving lights
-		glColor4f(0.f, 0.f, 0.f, 1.0f); // no local lighting by default
-	}
-	else
-	{
-		mask |= 0xff & (~2); // Hardware local lights
-	}
-	enableLights(mask);
-}
-
-void LLPipeline::enableLightsDynamic()
-{
-	assertInitialized();
-	U32 mask = 0xff & (~2); // Local lights
-	enableLights(mask);
-	if (mLightingDetail >= 2)
-	{
-		glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default
-	}
-
-	if (isAgentAvatarValid() && getLightingDetail() <= 0)
-	{
-		if (gAgentAvatarp->mSpecialRenderMode == 0) // normal
-		{
-			gPipeline.enableLightsAvatar();
-		}
-		else if (gAgentAvatarp->mSpecialRenderMode >= 1)  // anim preview
-		{
-			gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
-		}
-	}
-}
-
-void LLPipeline::enableLightsAvatar()
-{
-	U32 mask = 0xff; // All lights
-	setupAvatarLights(FALSE);
-	enableLights(mask);
-}
-
-void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
-{
-	U32 mask = 0x2002; // Avatar backlight only, set ambient
-	setupAvatarLights(TRUE);
-	enableLights(mask);
-
-	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
-}
-
-void LLPipeline::enableLightsFullbright(const LLColor4& color)
-{
-	assertInitialized();
-	U32 mask = 0x1000; // Non-0 mask, set ambient
-	enableLights(mask);
-
-	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
-	/*if (mLightingDetail >= 2)
-	{
-		glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default
-	}*/
-}
-
-void LLPipeline::disableLights()
-{
-	enableLights(0); // no lighting (full bright)
-	glColor4f(1.f, 1.f, 1.f, 1.f); // lighting color = white by default
-}
-
-//============================================================================
-
-class LLMenuItemGL;
-class LLInvFVBridge;
-struct cat_folder_pair;
-class LLVOBranch;
-class LLVOLeaf;
-
-void LLPipeline::findReferences(LLDrawable *drawablep)
-{
-	assertInitialized();
-	if (mLights.find(drawablep) != mLights.end())
-	{
-		llinfos << "In mLights" << llendl;
-	}
-	if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
-	{
-		llinfos << "In mMovedList" << llendl;
-	}
-	if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
-	{
-		llinfos << "In mShiftList" << llendl;
-	}
-	if (mRetexturedList.find(drawablep) != mRetexturedList.end())
-	{
-		llinfos << "In mRetexturedList" << llendl;
-	}
-	
-	if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
-	{
-		llinfos << "In mBuildQ1" << llendl;
-	}
-	if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
-	{
-		llinfos << "In mBuildQ2" << llendl;
-	}
-
-	S32 count;
-	
-	count = gObjectList.findReferences(drawablep);
-	if (count)
-	{
-		llinfos << "In other drawables: " << count << " references" << llendl;
-	}
-}
-
-BOOL LLPipeline::verify()
-{
-	BOOL ok = assertInitialized();
-	if (ok) 
-	{
-		for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
-		{
-			LLDrawPool *poolp = *iter;
-			if (!poolp->verify())
-			{
-				ok = FALSE;
-			}
-		}
-	}
-
-	if (!ok)
-	{
-		llwarns << "Pipeline verify failed!" << llendl;
-	}
-	return ok;
-}
-
-//////////////////////////////
-//
-// Collision detection
-//
-//
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-/**
- *	A method to compute a ray-AABB intersection.
- *	Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
- *	Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
- *	Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
- *
- *	Hence this version is faster as well as more robust than the original one.
- *
- *	Should work provided:
- *	1) the integer representation of 0.0f is 0x00000000
- *	2) the sign bit of the float is the most significant one
- *
- *	Report bugs: p.terdiman@codercorner.com
- *
- *	\param		aabb		[in] the axis-aligned bounding box
- *	\param		origin		[in] ray origin
- *	\param		dir			[in] ray direction
- *	\param		coord		[out] impact coordinates
- *	\return		true if ray intersects AABB
- */
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//#define RAYAABB_EPSILON 0.00001f
-#define IR(x)	((U32&)x)
-
-bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
-{
-	BOOL Inside = TRUE;
-	LLVector3 MinB = center - size;
-	LLVector3 MaxB = center + size;
-	LLVector3 MaxT;
-	MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
-
-	// Find candidate planes.
-	for(U32 i=0;i<3;i++)
-	{
-		if(origin.mV[i] < MinB.mV[i])
-		{
-			coord.mV[i]	= MinB.mV[i];
-			Inside		= FALSE;
-
-			// Calculate T distances to candidate planes
-			if(IR(dir.mV[i]))	MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
-		}
-		else if(origin.mV[i] > MaxB.mV[i])
-		{
-			coord.mV[i]	= MaxB.mV[i];
-			Inside		= FALSE;
-
-			// Calculate T distances to candidate planes
-			if(IR(dir.mV[i]))	MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
-		}
-	}
-
-	// Ray origin inside bounding box
-	if(Inside)
-	{
-		coord = origin;
-		return true;
-	}
-
-	// Get largest of the maxT's for final choice of intersection
-	U32 WhichPlane = 0;
-	if(MaxT.mV[1] > MaxT.mV[WhichPlane])	WhichPlane = 1;
-	if(MaxT.mV[2] > MaxT.mV[WhichPlane])	WhichPlane = 2;
-
-	// Check final candidate actually inside box
-	if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
-
-	for(U32 i=0;i<3;i++)
-	{
-		if(i!=WhichPlane)
-		{
-			coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
-			if (epsilon > 0)
-			{
-				if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon)	return false;
-			}
-			else
-			{
-				if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i])	return false;
-			}
-		}
-	}
-	return true;	// ray hits box
-}
-
-//////////////////////////////
-//
-// Macros, functions, and inline methods from other classes
-//
-//
-
-void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
-{
-	if (drawablep && assertInitialized())
-	{
-		if (is_light)
-		{
-			mLights.insert(drawablep);
-			drawablep->setState(LLDrawable::LIGHT);
-		}
-		else
-		{
-			drawablep->clearState(LLDrawable::LIGHT);
-			mLights.erase(drawablep);
-		}
-	}
-}
-
-//static
-void LLPipeline::toggleRenderType(U32 type)
-{
-	gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type];
-	if (type == LLPipeline::RENDER_TYPE_WATER)
-	{
-		gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER];
-	}
-}
-
-//static
-void LLPipeline::toggleRenderTypeControl(void* data)
-{
-	U32 type = (U32)(intptr_t)data;
-	U32 bit = (1<<type);
-	if (gPipeline.hasRenderType(type))
-	{
-		llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
-	}
-	else
-	{
-		llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
-	}
-	gPipeline.toggleRenderType(type);
-}
-
-//static
-BOOL LLPipeline::hasRenderTypeControl(void* data)
-{
-	U32 type = (U32)(intptr_t)data;
-	return gPipeline.hasRenderType(type);
-}
-
-// Allows UI items labeled "Hide foo" instead of "Show foo"
-//static
-BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
-{
-	S32 type = (S32)(intptr_t)data;
-	return !gPipeline.hasRenderType(type);
-}
-
-//static
-void LLPipeline::toggleRenderDebug(void* data)
-{
-	U32 bit = (U32)(intptr_t)data;
-	if (gPipeline.hasRenderDebugMask(bit))
-	{
-		llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
-	}
-	else
-	{
-		llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
-	}
-	gPipeline.mRenderDebugMask ^= bit;
-}
-
-
-//static
-BOOL LLPipeline::toggleRenderDebugControl(void* data)
-{
-	U32 bit = (U32)(intptr_t)data;
-	return gPipeline.hasRenderDebugMask(bit);
-}
-
-//static
-void LLPipeline::toggleRenderDebugFeature(void* data)
-{
-	U32 bit = (U32)(intptr_t)data;
-	gPipeline.mRenderDebugFeatureMask ^= bit;
-}
-
-
-//static
-BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
-{
-	U32 bit = (U32)(intptr_t)data;
-	return gPipeline.hasRenderDebugFeatureMask(bit);
-}
-
-// static
-void LLPipeline::setRenderScriptedBeacons(BOOL val)
-{
-	sRenderScriptedBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderScriptedBeacons(void*)
-{
-	sRenderScriptedBeacons = !sRenderScriptedBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderScriptedBeacons(void*)
-{
-	return sRenderScriptedBeacons;
-}
-
-// static
-void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
-{
-	sRenderScriptedTouchBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
-{
-	sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
-{
-	return sRenderScriptedTouchBeacons;
-}
-
-// static
-void LLPipeline::setRenderPhysicalBeacons(BOOL val)
-{
-	sRenderPhysicalBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderPhysicalBeacons(void*)
-{
-	sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderPhysicalBeacons(void*)
-{
-	return sRenderPhysicalBeacons;
-}
-
-// static
-void LLPipeline::setRenderParticleBeacons(BOOL val)
-{
-	sRenderParticleBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderParticleBeacons(void*)
-{
-	sRenderParticleBeacons = !sRenderParticleBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderParticleBeacons(void*)
-{
-	return sRenderParticleBeacons;
-}
-
-// static
-void LLPipeline::setRenderSoundBeacons(BOOL val)
-{
-	sRenderSoundBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderSoundBeacons(void*)
-{
-	sRenderSoundBeacons = !sRenderSoundBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderSoundBeacons(void*)
-{
-	return sRenderSoundBeacons;
-}
-
-// static
-void LLPipeline::setRenderBeacons(BOOL val)
-{
-	sRenderBeacons = val;
-}
-
-// static
-void LLPipeline::toggleRenderBeacons(void*)
-{
-	sRenderBeacons = !sRenderBeacons;
-}
-
-// static
-BOOL LLPipeline::getRenderBeacons(void*)
-{
-	return sRenderBeacons;
-}
-
-// static
-void LLPipeline::setRenderHighlights(BOOL val)
-{
-	sRenderHighlight = val;
-}
-
-// static
-void LLPipeline::toggleRenderHighlights(void*)
-{
-	sRenderHighlight = !sRenderHighlight;
-}
-
-// static
-BOOL LLPipeline::getRenderHighlights(void*)
-{
-	return sRenderHighlight;
-}
-
-LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
-														BOOL pick_transparent,												
-														S32* face_hit,
-														LLVector3* intersection,         // return the intersection point
-														LLVector2* tex_coord,            // return the texture coordinates of the intersection point
-														LLVector3* normal,               // return the surface normal at the intersection point
-														LLVector3* bi_normal             // return the surface bi-normal at the intersection point
-	)
-{
-	LLDrawable* drawable = NULL;
-
-	LLVector3 local_end = end;
-
-	LLVector3 position;
-
-	sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE;
-	
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
-		{
-			if ((j == LLViewerRegion::PARTITION_VOLUME) || 
-				(j == LLViewerRegion::PARTITION_BRIDGE) || 
-				(j == LLViewerRegion::PARTITION_TERRAIN) ||
-				(j == LLViewerRegion::PARTITION_TREE) ||
-				(j == LLViewerRegion::PARTITION_GRASS))  // only check these partitions for now
-			{
-				LLSpatialPartition* part = region->getSpatialPartition(j);
-				if (part && hasRenderType(part->mDrawableType))
-				{
-					LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
-					if (hit)
-					{
-						drawable = hit;
-						local_end = position;						
-					}
-				}
-			}
-		}
-	}
-	
-	if (!sPickAvatar)
-	{
-		//save hit info in case we need to restore
-		//due to attachment override
-		LLVector3 local_normal;
-		LLVector3 local_binormal;
-		LLVector2 local_texcoord;
-		S32 local_face_hit = -1;
-
-		if (face_hit)
-		{ 
-			local_face_hit = *face_hit;
-		}
-		if (tex_coord)
-		{
-			local_texcoord = *tex_coord;
-		}
-		if (bi_normal)
-		{
-			local_binormal = *bi_normal;
-		}
-		if (normal)
-		{
-			local_normal = *normal;
-		}
-				
-		const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f;
-
-		//check against avatars
-		sPickAvatar = TRUE;
-		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-				iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-		{
-			LLViewerRegion* region = *iter;
-
-			LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
-			if (part && hasRenderType(part->mDrawableType))
-			{
-				LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
-				if (hit)
-				{
-					if (!drawable || 
-						!drawable->getVObj()->isAttachment() ||
-						(position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST)
-					{ //avatar overrides if previously hit drawable is not an attachment or 
-					  //attachment is far enough away from detected intersection
-						drawable = hit;
-						local_end = position;						
-					}
-					else
-					{ //prioritize attachments over avatars
-						position = local_end;
-
-						if (face_hit)
-						{
-							*face_hit = local_face_hit;
-						}
-						if (tex_coord)
-						{
-							*tex_coord = local_texcoord;
-						}
-						if (bi_normal)
-						{
-							*bi_normal = local_binormal;
-						}
-						if (normal)
-						{
-							*normal = local_normal;
-						}
-					}
-				}
-			}
-		}
-	}
-
-	//check all avatar nametags (silly, isn't it?)
-	for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin();
-		iter != LLCharacter::sInstances.end();
-		++iter)
-	{
-		LLVOAvatar* av = (LLVOAvatar*) *iter;
-		if (av->mNameText.notNull()
-			&& av->mNameText->lineSegmentIntersect(start, local_end, position))
-		{
-			drawable = av->mDrawable;
-			local_end = position;
-		}
-	}
-
-	if (intersection)
-	{
-		*intersection = position;
-	}
-
-	return drawable ? drawable->getVObj().get() : NULL;
-}
-
-LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end,
-													  BOOL pick_transparent,													
-													  S32* face_hit,
-													  LLVector3* intersection,         // return the intersection point
-													  LLVector2* tex_coord,            // return the texture coordinates of the intersection point
-													  LLVector3* normal,               // return the surface normal at the intersection point
-													  LLVector3* bi_normal             // return the surface bi-normal at the intersection point
-	)
-{
-	LLDrawable* drawable = NULL;
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-
-		BOOL toggle = FALSE;
-		if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{
-			toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-			toggle = TRUE;
-		}
-
-		LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
-		if (part)
-		{
-			LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal);
-			if (hit)
-			{
-				drawable = hit;
-			}
-		}
-
-		if (toggle)
-		{
-			toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-		}
-	}
-	return drawable ? drawable->getVObj().get() : NULL;
-}
-
-LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
-{
-	if (vobj)
-	{
-		LLViewerRegion* region = vobj->getRegion();
-		if (region)
-		{
-			return region->getSpatialPartition(vobj->getPartitionType());
-		}
-	}
-	return NULL;
-}
-
-
-void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
-{
-	if (!drawable || drawable->isDead())
-	{
-		return;
-	}
-
-	for (S32 i = 0; i < drawable->getNumFaces(); i++)
-	{
-		LLFace* facep = drawable->getFace(i);
-		facep->mVertexBuffer = NULL;
-		facep->mLastVertexBuffer = NULL;
-	}
-}
-
-void LLPipeline::resetVertexBuffers()
-{
-	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
-	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
-	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
-
-	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
-			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
-	{
-		LLViewerRegion* region = *iter;
-		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
-		{
-			LLSpatialPartition* part = region->getSpatialPartition(i);
-			if (part)
-			{
-				part->resetVertexBuffers();
-			}
-		}
-	}
-
-	resetDrawOrders();
-
-	gSky.resetVertexBuffers();
-
-	if (LLVertexBuffer::sGLCount > 0)
-	{
-		LLVertexBuffer::cleanupClass();
-	}
-
-	//delete all name pool caches
-	LLGLNamePool::cleanupPools();
-
-	if (LLVertexBuffer::sGLCount > 0)
-	{
-		llwarns << "VBO wipe failed." << llendl;
-	}
-
-	if (!LLVertexBuffer::sStreamIBOPool.mNameList.empty() ||
-		!LLVertexBuffer::sStreamVBOPool.mNameList.empty() ||
-		!LLVertexBuffer::sDynamicIBOPool.mNameList.empty() ||
-		!LLVertexBuffer::sDynamicVBOPool.mNameList.empty())
-	{
-		llwarns << "VBO name pool cleanup failed." << llendl;
-	}
-
-	LLVertexBuffer::unbind();
-
-	LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
-}
-
-void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)
-{
-	LLMemType mt_ro(LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS);
-	assertInitialized();
-	glLoadMatrixd(gGLModelView);
-	gGLLastMatrix = NULL;
-	mSimplePool->pushBatches(type, mask);
-	glLoadMatrixd(gGLModelView);
-	gGLLastMatrix = NULL;		
-}
-
-void LLPipeline::setUseVBO(BOOL use_vbo)
-{
-	if (use_vbo != LLVertexBuffer::sEnableVBOs)
-	{
-		if (use_vbo)
-		{
-			llinfos << "Enabling VBO." << llendl;
-		}
-		else
-		{ 
-			llinfos << "Disabling VBO." << llendl;
-		}
-		
-		resetVertexBuffers();
-		LLVertexBuffer::initClass(use_vbo, gSavedSettings.getBOOL("RenderVBOMappingDisable"));
-	}
-}
-
-void LLPipeline::setDisableVBOMapping(BOOL no_vbo_mapping)
-{
-	if (LLVertexBuffer::sEnableVBOs && no_vbo_mapping != LLVertexBuffer::sDisableVBOMapping)
-	{
-		if (no_vbo_mapping)
-		{
-			llinfos << "Disabling VBO glMapBufferARB." << llendl;
-		}
-		else
-		{ 
-			llinfos << "Enabling VBO glMapBufferARB." << llendl;
-		}
-		
-		resetVertexBuffers();
-		LLVertexBuffer::initClass(true, no_vbo_mapping);
-	}
-}
-
-void apply_cube_face_rotation(U32 face)
-{
-	switch (face)
-	{
-		case 0: 
-			glRotatef(90.f, 0, 1, 0);
-			glRotatef(180.f, 1, 0, 0);
-		break;
-		case 2: 
-			glRotatef(-90.f, 1, 0, 0);
-		break;
-		case 4:
-			glRotatef(180.f, 0, 1, 0);
-			glRotatef(180.f, 0, 0, 1);
-		break;
-		case 1: 
-			glRotatef(-90.f, 0, 1, 0);
-			glRotatef(180.f, 1, 0, 0);
-		break;
-		case 3:
-			glRotatef(90, 1, 0, 0);
-		break;
-		case 5: 
-			glRotatef(180, 0, 0, 1);
-		break;
-	}
-}
-
-void validate_framebuffer_object()
-{                                                           
-	GLenum status;                                            
-	status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 
-	switch(status) 
-	{                                          
-		case GL_FRAMEBUFFER_COMPLETE_EXT:                       
-			//framebuffer OK, no error.
-			break;
-		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
-			// frame buffer not OK: probably means unsupported depth buffer format
-			llerrs << "Framebuffer Incomplete Dimensions." << llendl;
-			break;
-		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
-			// frame buffer not OK: probably means unsupported depth buffer format
-			llerrs << "Framebuffer Incomplete Attachment." << llendl;
-			break; 
-		case GL_FRAMEBUFFER_UNSUPPORTED_EXT:                    
-			/* choose different formats */                        
-			llerrs << "Framebuffer unsupported." << llendl;
-			break;                                                
-		default:                                                
-			llerrs << "Unknown framebuffer status." << llendl;
-			break;
-	}
-}
-
-void LLPipeline::bindScreenToTexture() 
-{
-	
-}
-
-static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom");
-
-void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
-{
-	LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
-	if (!(gPipeline.canUseVertexShaders() &&
-		sRenderGlow))
-	{
-		return;
-	}
-
-	LLVertexBuffer::unbind();
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	assertInitialized();
-
-	if (gUseWireframe)
-	{
-		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-	}
-
-	U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
-
-	LLVector2 tc1(0,0);
-	LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
-				  (F32) gViewerWindow->getWorldViewHeightRaw()*2);
-
-	if (res_mod > 1)
-	{
-		tc2 /= (F32) res_mod;
-	}
-
-	gGL.setColorMask(true, true);
-		
-	LLFastTimer ftm(FTM_RENDER_BLOOM);
-	gGL.color4f(1,1,1,1);
-	LLGLDepthTest depth(GL_FALSE);
-	LLGLDisable blend(GL_BLEND);
-	LLGLDisable cull(GL_CULL_FACE);
-	
-	enableLightsFullbright(LLColor4(1,1,1,1));
-
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	glLoadIdentity();
-	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
-	glLoadIdentity();
-
-	LLGLDisable test(GL_ALPHA_TEST);
-
-	gGL.setColorMask(true, true);
-	glClearColor(0,0,0,0);
-
-	/*if (for_snapshot)
-	{
-		gGL.getTexUnit(0)->bind(&mGlow[1]);
-		{
-			//LLGLEnable stencil(GL_STENCIL_TEST);
-			//glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF);
-			//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-			//LLGLDisable blend(GL_BLEND);
-
-			// If the snapshot is constructed from tiles, calculate which
-			// tile we're in.
-
-			//from LLViewerCamera::setPerpsective
-			if (zoom_factor > 1.f)
-			{
-				int pos_y = subfield / llceil(zoom_factor);
-				int pos_x = subfield - (pos_y*llceil(zoom_factor));
-				F32 size = 1.f/zoom_factor;
-
-				tc1.set(pos_x*size, pos_y*size);
-				tc2 = tc1 + LLVector2(size,size);
-			}
-			else
-			{
-				tc2.set(1,1);
-			}
-			
-			LLGLEnable blend(GL_BLEND);
-			gGL.setSceneBlendType(LLRender::BT_ADD);
-			
-				
-			gGL.begin(LLRender::TRIANGLE_STRIP);
-			gGL.color4f(1,1,1,1);
-			gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-			gGL.vertex2f(-1,-1);
-			
-			gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-			gGL.vertex2f(-1,1);
-			
-			gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-			gGL.vertex2f(1,-1);
-			
-			gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
-			gGL.vertex2f(1,1);
-
-			gGL.end();
-
-			gGL.flush();
-			gGL.setSceneBlendType(LLRender::BT_ALPHA);
-		}
-
-		gGL.flush();
-		glMatrixMode(GL_PROJECTION);
-		glPopMatrix();
-		glMatrixMode(GL_MODELVIEW);
-		glPopMatrix();
-
-		return;
-	}*/
-	
-	{
-		{
-			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
-			mGlow[2].bindTarget();
-			mGlow[2].clear();
-		}
-		
-		gGlowExtractProgram.bind();
-		F32 minLum = llmax(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f);
-		F32 maxAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha");		
-		F32 warmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount");	
-		LLVector3 lumWeights = gSavedSettings.getVector3("RenderGlowLumWeights");
-		LLVector3 warmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights");
-		gGlowExtractProgram.uniform1f("minLuminance", minLum);
-		gGlowExtractProgram.uniform1f("maxExtractAlpha", maxAlpha);
-		gGlowExtractProgram.uniform3f("lumWeights", lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
-		gGlowExtractProgram.uniform3f("warmthWeights", warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
-		gGlowExtractProgram.uniform1f("warmthAmount", warmthAmount);
-		LLGLEnable blend_on(GL_BLEND);
-		LLGLEnable test(GL_ALPHA_TEST);
-		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
-		gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-		
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);		
-		gGL.getTexUnit(0)->disable();
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
-		gGL.getTexUnit(0)->bind(&mScreen);
-
-		gGL.color4f(1,1,1,1);
-		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-
-		mGlow[2].flush();
-	}
-
-	tc1.setVec(0,0);
-	tc2.setVec(2,2);
-
-	// power of two between 1 and 1024
-	U32 glowResPow = gSavedSettings.getS32("RenderGlowResolutionPow");
-	const U32 glow_res = llmax(1, 
-		llmin(1024, 1 << glowResPow));
-
-	S32 kernel = gSavedSettings.getS32("RenderGlowIterations")*2;
-	F32 delta = gSavedSettings.getF32("RenderGlowWidth") / glow_res;
-	// Use half the glow width if we have the res set to less than 9 so that it looks
-	// almost the same in either case.
-	if (glowResPow < 9)
-	{
-		delta *= 0.5f;
-	}
-	F32 strength = gSavedSettings.getF32("RenderGlowStrength");
-
-	gGlowProgram.bind();
-	gGlowProgram.uniform1f("glowStrength", strength);
-
-	for (S32 i = 0; i < kernel; i++)
-	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		{
-			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
-			mGlow[i%2].bindTarget();
-			mGlow[i%2].clear();
-		}
-			
-		if (i == 0)
-		{
-			gGL.getTexUnit(0)->bind(&mGlow[2]);
-		}
-		else
-		{
-			gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]);
-		}
-
-		if (i%2 == 0)
-		{
-			gGlowProgram.uniform2f("glowDelta", delta, 0);
-		}
-		else
-		{
-			gGlowProgram.uniform2f("glowDelta", 0, delta);
-		}
-
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		
-		mGlow[i%2].flush();
-	}
-
-	gGlowProgram.unbind();
-
-	if (LLRenderTarget::sUseFBO)
-	{
-		LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
-		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-	}
-
-	gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
-	gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
-	gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
-	gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
-	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-
-	tc2.setVec((F32) gViewerWindow->getWorldViewWidthRaw(),
-			(F32) gViewerWindow->getWorldViewHeightRaw());
-
-	gGL.flush();
-	
-	LLVertexBuffer::unbind();
-
-	if (LLPipeline::sRenderDeferred && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
-	{
-		LLGLDisable blend(GL_BLEND);
-		bindDeferredShader(gDeferredGIFinalProgram);
-
-		S32 channel = gDeferredGIFinalProgram.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
-		if (channel > -1)
-		{
-			mScreen.bindTexture(0, channel);
-		}
-
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-
-		unbindDeferredShader(gDeferredGIFinalProgram);
-	}
-	else
-	{
-
-		if (res_mod > 1)
-		{
-			tc2 /= (F32) res_mod;
-		}
-
-		U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
-		LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
-		buff->allocateBuffer(3,0,TRUE);
-
-		LLStrider<LLVector3> v;
-		LLStrider<LLVector2> uv1;
-		LLStrider<LLVector2> uv2;
-
-		buff->getVertexStrider(v);
-		buff->getTexCoord0Strider(uv1);
-		buff->getTexCoord1Strider(uv2);
-		
-		uv1[0] = LLVector2(0, 0);
-		uv1[1] = LLVector2(0, 2);
-		uv1[2] = LLVector2(2, 0);
-		
-		uv2[0] = LLVector2(0, 0);
-		uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
-		uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
-		
-		v[0] = LLVector3(-1,-1,0);
-		v[1] = LLVector3(-1,3,0);
-		v[2] = LLVector3(3,-1,0);
-				
-		buff->setBuffer(0);
-
-		LLGLDisable blend(GL_BLEND);
-
-		//tex unit 0
-		gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
-	
-		gGL.getTexUnit(0)->bind(&mGlow[1]);
-		gGL.getTexUnit(1)->activate();
-		gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE);
-
-
-		//tex unit 1
-		gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
-		
-		gGL.getTexUnit(1)->bind(&mScreen);
-		gGL.getTexUnit(1)->activate();
-		
-		LLGLEnable multisample(GL_MULTISAMPLE_ARB);
-		
-		buff->setBuffer(mask);
-		buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
-		
-		gGL.getTexUnit(1)->disable();
-		gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
-
-		gGL.getTexUnit(0)->activate();
-		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-
-		if (LLRenderTarget::sUseFBO)
-		{ //copy depth buffer from mScreen to framebuffer
-			LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 
-				0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-		}
-	}
-	
-
-	gGL.setSceneBlendType(LLRender::BT_ALPHA);
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-
-	LLVertexBuffer::unbind();
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-}
-
-static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred");
-
-void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post, U32 noise_map)
-{
-	LLFastTimer t(FTM_BIND_DEFERRED);
-
-	if (noise_map == 0xFFFFFFFF)
-	{
-		noise_map = mNoiseMap;
-	}
-
-	LLGLState::checkTextureChannels();
-
-	shader.bind();
-	S32 channel = 0;
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mDeferredScreen.bindTexture(0,channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mDeferredScreen.bindTexture(1, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mDeferredScreen.bindTexture(2, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	if (gi_source)
-	{
-		BOOL has_gi = FALSE;
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			gi_source->bindTexture(0, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			gi_source->bindTexture(1, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			gi_source->bindTexture(2, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			gi_source->bindTexture(1, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			gi_source->bindTexture(3, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			last_gi_post->bindTexture(0, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			last_gi_post->bindTexture(2, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			last_gi_post->bindTexture(1, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			last_gi_post->bindTexture(3, channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-		}
-		
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
-		if (channel > -1)
-		{
-			has_gi = TRUE;
-			gGL.getTexUnit(channel)->bind(gi_source, TRUE);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-			stop_glerror();
-			
-			glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
-			glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
-
-			stop_glerror();
-		}
-
-		if (has_gi)
-		{
-			F32 range_x = llmin(mGIRange.mV[0], 1.f);
-			F32 range_y = llmin(mGIRange.mV[1], 1.f);
-
-			LLVector2 scale(range_x,range_y);
-
-			LLVector2 kern[25];
-
-			for (S32 i = 0; i < 5; ++i)
-			{
-				for (S32 j = 0; j < 5; ++j)
-				{
-					S32 idx = i*5+j;
-					kern[idx].mV[0] = (i-2)*0.5f;
-					kern[idx].mV[1] = (j-2)*0.5f;
-					kern[idx].scaleVec(scale);
-				}
-			}
-
-			shader.uniform2fv("gi_kern", 25, (F32*) kern);
-			shader.uniformMatrix4fv("gi_mat", 1, FALSE, mGIMatrix.m);
-			shader.uniformMatrix4fv("gi_mat_proj", 1, FALSE, mGIMatrixProj.m);
-			shader.uniformMatrix4fv("gi_inv_proj", 1, FALSE, mGIInvProj.m);
-			shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m);
-		}
-	}
-	
-	/*channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mDeferredScreen.bindTexture(3, channel);
-	}*/
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		stop_glerror();
-		
-		glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
-		glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
-
-		stop_glerror();
-
-		glh::matrix4f projection = glh_get_current_projection();
-		glh::matrix4f inv_proj = projection.inverse();
-		
-		shader.uniformMatrix4fv("inv_proj", 1, FALSE, inv_proj.m);
-		shader.uniform4f("viewport", (F32) gGLViewport[0],
-									(F32) gGLViewport[1],
-									(F32) gGLViewport[2],
-									(F32) gGLViewport[3]);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
-	if (channel > -1)
-	{
-		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC);
-	if (channel > -1)
-	{
-		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
-	}
-
-	stop_glerror();
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mDeferredLight[light_index].bindTexture(0, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
-	if (channel > -1)
-	{
-		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_BLOOM);
-	if (channel > -1)
-	{
-		mGlow[1].bindTexture(0, channel);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		gi_source->bindTexture(0, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mEdgeMap.bindTexture(0, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mDeferredLight[1].bindTexture(0, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	if (channel > -1)
-	{
-		mDeferredLight[2].bindTexture(0, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-	}
-
-
-	stop_glerror();
-
-	for (U32 i = 0; i < 4; i++)
-	{
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE);
-		stop_glerror();
-		if (channel > -1)
-		{
-			stop_glerror();
-			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-			stop_glerror();
-			
-			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
-			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
-			stop_glerror();
-		}
-	}
-
-	for (U32 i = 4; i < 6; i++)
-	{
-		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i);
-		stop_glerror();
-		if (channel > -1)
-		{
-			stop_glerror();
-			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-			stop_glerror();
-			
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
-			stop_glerror();
-		}
-	}
-
-	stop_glerror();
-
-	F32 mat[16*6];
-	for (U32 i = 0; i < 16; i++)
-	{
-		mat[i] = mSunShadowMatrix[0].m[i];
-		mat[i+16] = mSunShadowMatrix[1].m[i];
-		mat[i+32] = mSunShadowMatrix[2].m[i];
-		mat[i+48] = mSunShadowMatrix[3].m[i];
-		mat[i+64] = mSunShadowMatrix[4].m[i];
-		mat[i+80] = mSunShadowMatrix[5].m[i];
-	}
-
-	shader.uniformMatrix4fv("shadow_matrix[0]", 6, FALSE, mat);
-	shader.uniformMatrix4fv("shadow_matrix", 6, FALSE, mat);
-
-	stop_glerror();
-
-	channel = shader.enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
-	if (channel > -1)
-	{
-		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
-		if (cube_map)
-		{
-			cube_map->enable(channel);
-			cube_map->bind();
-			F64* m = gGLModelView;
-
-			
-			F32 mat[] = { m[0], m[1], m[2],
-						  m[4], m[5], m[6],
-						  m[8], m[9], m[10] };
-		
-			shader.uniform3fv("env_mat[0]", 3, mat);
-			shader.uniform3fv("env_mat", 3, mat);
-		}
-	}
-
-	shader.uniform4fv("shadow_clip", 1, mSunClipPlanes.mV);
-	shader.uniform1f("sun_wash", gSavedSettings.getF32("RenderDeferredSunWash"));
-	shader.uniform1f("shadow_noise", gSavedSettings.getF32("RenderShadowNoise"));
-	shader.uniform1f("blur_size", gSavedSettings.getF32("RenderShadowBlurSize"));
-
-	shader.uniform1f("ssao_radius", gSavedSettings.getF32("RenderSSAOScale"));
-	shader.uniform1f("ssao_max_radius", gSavedSettings.getU32("RenderSSAOMaxScale"));
-
-	F32 ssao_factor = gSavedSettings.getF32("RenderSSAOFactor");
-	shader.uniform1f("ssao_factor", ssao_factor);
-	shader.uniform1f("ssao_factor_inv", 1.0/ssao_factor);
-
-	LLVector3 ssao_effect = gSavedSettings.getVector3("RenderSSAOEffect");
-	F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0;
-	F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0;
-	// This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by
-	// value factor, and scales remainder by saturation factor
-	F32 ssao_effect_mat[] = {	matrix_diag, matrix_nondiag, matrix_nondiag,
-								matrix_nondiag, matrix_diag, matrix_nondiag,
-								matrix_nondiag, matrix_nondiag, matrix_diag};
-	shader.uniformMatrix3fv("ssao_effect_mat", 1, GL_FALSE, ssao_effect_mat);
-
-	F32 shadow_offset_error = 1.f + gSavedSettings.getF32("RenderShadowOffsetError") * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
-	F32 shadow_bias_error = 1.f + gSavedSettings.getF32("RenderShadowBiasError") * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
-
-	shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
-	shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f);
-	shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")*shadow_offset_error);
-	shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")*shadow_bias_error);
-	shader.uniform1f ("spot_shadow_offset", gSavedSettings.getF32("RenderSpotShadowOffset"));
-	shader.uniform1f("spot_shadow_bias", gSavedSettings.getF32("RenderSpotShadowBias"));	
-
-	shader.uniform1f("lum_scale", gSavedSettings.getF32("RenderLuminanceScale"));
-	shader.uniform1f("sun_lum_scale", gSavedSettings.getF32("RenderSunLuminanceScale"));
-	shader.uniform1f("sun_lum_offset", gSavedSettings.getF32("RenderSunLuminanceOffset"));
-	shader.uniform1f("lum_lod", gSavedSettings.getF32("RenderLuminanceDetail"));
-	shader.uniform1f("gi_range", gSavedSettings.getF32("RenderGIRange"));
-	shader.uniform1f("gi_brightness", gSavedSettings.getF32("RenderGIBrightness"));
-	shader.uniform1f("gi_luminance", gSavedSettings.getF32("RenderGILuminance"));
-	shader.uniform1f("gi_edge_weight", gSavedSettings.getF32("RenderGIBlurEdgeWeight"));
-	shader.uniform1f("gi_blur_brightness", gSavedSettings.getF32("RenderGIBlurBrightness"));
-	shader.uniform1f("gi_sample_width", mGILightRadius);
-	shader.uniform1f("gi_noise", gSavedSettings.getF32("RenderGINoise"));
-	shader.uniform1f("gi_attenuation", gSavedSettings.getF32("RenderGIAttenuation"));
-	shader.uniform1f("gi_ambiance", gSavedSettings.getF32("RenderGIAmbiance"));
-	shader.uniform2f("shadow_res", mShadow[0].getWidth(), mShadow[0].getHeight());
-	shader.uniform2f("proj_shadow_res", mShadow[4].getWidth(), mShadow[4].getHeight());
-	shader.uniform1f("depth_cutoff", gSavedSettings.getF32("RenderEdgeDepthCutoff"));
-	shader.uniform1f("norm_cutoff", gSavedSettings.getF32("RenderEdgeNormCutoff"));
-
-	if (shader.getUniformLocation("norm_mat") >= 0)
-	{
-		glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
-		shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m);
-	}
-}
-
-static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
-static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather");
-static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map");
-static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften");
-static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges");
-static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights");
-static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics");
-static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
-static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors");
-static LLFastTimer::DeclareTimer FTM_POST("Post");
-
-
-void LLPipeline::renderDeferredLighting()
-{
-	if (!sCull)
-	{
-		return;
-	}
-
-	{
-		LLFastTimer ftm(FTM_RENDER_DEFERRED);
-
-		LLViewerCamera* camera = LLViewerCamera::getInstance();
-		{
-			LLGLDepthTest depth(GL_TRUE);
-			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
-							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	
-		}
-
-		LLGLEnable multisample(GL_MULTISAMPLE_ARB);
-
-		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{
-			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-		}
-
-		//ati doesn't seem to love actually using the stencil buffer on FBO's
-		LLGLEnable stencil(GL_STENCIL_TEST);
-		glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
-		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
-		gGL.setColorMask(true, true);
-		
-		//draw a cube around every light
-		LLVertexBuffer::unbind();
-
-		LLGLEnable cull(GL_CULL_FACE);
-		LLGLEnable blend(GL_BLEND);
-
-		glh::matrix4f mat = glh_copy_matrix(gGLModelView);
-
-		F32 vert[] = 
-		{
-			-1,1,
-			-1,-3,
-			3,1,
-		};
-		glVertexPointer(2, GL_FLOAT, 0, vert);
-		glColor3f(1,1,1);
-
-		{
-			setupHWLights(NULL); //to set mSunDir;
-			LLVector4 dir(mSunDir, 0.f);
-			glh::vec4f tc(dir.mV);
-			mat.mult_matrix_vec(tc);
-			glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0);
-		}
-
-			glPushMatrix();
-			glLoadIdentity();
-			glMatrixMode(GL_PROJECTION);
-			glPushMatrix();
-			glLoadIdentity();
-
-			mDeferredLight[0].bindTarget();
-
-		if (gSavedSettings.getBOOL("RenderDeferredSSAO") || gSavedSettings.getS32("RenderShadowDetail") > 0)
-		{
-			{ //paint shadow/SSAO light map (direct lighting lightmap)
-				LLFastTimer ftm(FTM_SUN_SHADOW);
-				bindDeferredShader(gDeferredSunProgram, 0);
-
-				glClearColor(1,1,1,1);
-				mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT);
-				glClearColor(0,0,0,0);
-
-				glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
-
-				const U32 slice = 32;
-				F32 offset[slice*3];
-				for (U32 i = 0; i < 4; i++)
-				{
-					for (U32 j = 0; j < 8; j++)
-					{
-						glh::vec3f v;
-						v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
-						v.normalize();
-						inv_trans.mult_matrix_vec(v);
-						v.normalize();
-						offset[(i*8+j)*3+0] = v.v[0];
-						offset[(i*8+j)*3+1] = v.v[2];
-						offset[(i*8+j)*3+2] = v.v[1];
-					}
-				}
-
-				gDeferredSunProgram.uniform3fv("offset", slice, offset);
-				gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
-				
-				{
-					LLGLDisable blend(GL_BLEND);
-					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-					stop_glerror();
-					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-					stop_glerror();
-				}
-				
-				unbindDeferredShader(gDeferredSunProgram);
-			}
-		}
-			else
-			{
-			glClearColor(1,1,1,1);
-				mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT);
-			glClearColor(0,0,0,0);
-			}
-
-			mDeferredLight[0].flush();
-
-		{ //global illumination specific block (still experimental)
-			if (gSavedSettings.getBOOL("RenderDeferredBlurLight") &&
-			    gSavedSettings.getBOOL("RenderDeferredGI"))
-			{
-				LLFastTimer ftm(FTM_EDGE_DETECTION);
-				//generate edge map
-				LLGLDisable blend(GL_BLEND);
-				LLGLDisable test(GL_ALPHA_TEST);
-				LLGLDepthTest depth(GL_FALSE);
-				LLGLDisable stencil(GL_STENCIL_TEST);
-
-				{
-					gDeferredEdgeProgram.bind();
-					mEdgeMap.bindTarget();
-					bindDeferredShader(gDeferredEdgeProgram);
-					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-					unbindDeferredShader(gDeferredEdgeProgram);
-					mEdgeMap.flush();
-				}
-			}
-
-			if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
-			{
-				{ //get luminance map from previous frame's light map
-					LLGLEnable blend(GL_BLEND);
-					LLGLDisable test(GL_ALPHA_TEST);
-					LLGLDepthTest depth(GL_FALSE);
-					LLGLDisable stencil(GL_STENCIL_TEST);
-
-					//static F32 fade = 1.f;
-
-					{
-						gGL.setSceneBlendType(LLRender::BT_ALPHA);
-						gLuminanceGatherProgram.bind();
-						gLuminanceGatherProgram.uniform2f("screen_res", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
-						mLuminanceMap.bindTarget();
-						bindDeferredShader(gLuminanceGatherProgram);
-						glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-						unbindDeferredShader(gLuminanceGatherProgram);
-						mLuminanceMap.flush();
-						gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true);
-						gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
-						glGenerateMipmapEXT(GL_TEXTURE_2D);
-					}
-				}
-
-				{ //paint noisy GI map (bounce lighting lightmap)
-					LLFastTimer ftm(FTM_GI_TRACE);
-					LLGLDisable blend(GL_BLEND);
-					LLGLDepthTest depth(GL_FALSE);
-					LLGLDisable test(GL_ALPHA_TEST);
-
-					mGIMapPost[0].bindTarget();
-
-					bindDeferredShader(gDeferredGIProgram, 0, &mGIMap, 0, mTrueNoiseMap);
-					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-					unbindDeferredShader(gDeferredGIProgram);
-					mGIMapPost[0].flush();
-				}
-
-				U32 pass_count = 0;
-				if (gSavedSettings.getBOOL("RenderDeferredBlurLight"))
-				{
-					pass_count = llclamp(gSavedSettings.getU32("RenderGIBlurPasses"), (U32) 1, (U32) 128);
-				}
-
-				for (U32 i = 0; i < pass_count; ++i)
-				{ //gather/soften indirect lighting map
-					LLFastTimer ftm(FTM_GI_GATHER);
-					bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[0], NULL, mTrueNoiseMap);
-					F32 blur_size = gSavedSettings.getF32("RenderGIBlurSize")/((F32) i * gSavedSettings.getF32("RenderGIBlurIncrement")+1.f);
-					gDeferredPostGIProgram.uniform2f("delta", 1.f, 0.f);
-					gDeferredPostGIProgram.uniform1f("kern_scale", blur_size);
-					gDeferredPostGIProgram.uniform1f("gi_blur_brightness", gSavedSettings.getF32("RenderGIBlurBrightness"));
-				
-					mGIMapPost[1].bindTarget();
-					{
-						LLGLDisable blend(GL_BLEND);
-						LLGLDepthTest depth(GL_FALSE);
-						stop_glerror();
-						glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-						stop_glerror();
-					}
-					
-					mGIMapPost[1].flush();
-					unbindDeferredShader(gDeferredPostGIProgram);
-					bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[1], NULL, mTrueNoiseMap);
-					mGIMapPost[0].bindTarget();
-
-					gDeferredPostGIProgram.uniform2f("delta", 0.f, 1.f);
-
-					{
-						LLGLDisable blend(GL_BLEND);
-						LLGLDepthTest depth(GL_FALSE);
-						stop_glerror();
-						glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-						stop_glerror();
-					}
-					mGIMapPost[0].flush();
-					unbindDeferredShader(gDeferredPostGIProgram);
-				}
-			}
-		}
-
-		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
-			{ //soften direct lighting lightmap
-				LLFastTimer ftm(FTM_SOFTEN_SHADOW);
-				//blur lightmap
-				mDeferredLight[1].bindTarget();
-
-				glClearColor(1,1,1,1);
-				mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT);
-				glClearColor(0,0,0,0);
-				
-				bindDeferredShader(gDeferredBlurLightProgram);
-
-				LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian");
-				const U32 kern_length = 4;
-				F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize");
-				F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
-
-				// sample symmetrically with the middle sample falling exactly on 0.0
-				F32 x = 0.f;
-
-				LLVector3 gauss[32]; // xweight, yweight, offset
-
-				for (U32 i = 0; i < kern_length; i++)
-				{
-					gauss[i].mV[0] = llgaussian(x, go.mV[0]);
-					gauss[i].mV[1] = llgaussian(x, go.mV[1]);
-					gauss[i].mV[2] = x;
-					x += 1.f;
-				}
-
-				gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
-				gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor);
-				gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
-				gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
-				gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
-			
-				{
-					LLGLDisable blend(GL_BLEND);
-					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-					stop_glerror();
-					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-					stop_glerror();
-				}
-				
-				mDeferredLight[1].flush();
-				unbindDeferredShader(gDeferredBlurLightProgram);
-
-				bindDeferredShader(gDeferredBlurLightProgram, 1);
-				mDeferredLight[0].bindTarget();
-
-				gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
-
-				{
-					LLGLDisable blend(GL_BLEND);
-					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-					stop_glerror();
-					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-					stop_glerror();
-				}
-				mDeferredLight[0].flush();
-				unbindDeferredShader(gDeferredBlurLightProgram);
-			}
-
-			stop_glerror();
-			glPopMatrix();
-			stop_glerror();
-			glMatrixMode(GL_MODELVIEW);
-			stop_glerror();
-			glPopMatrix();
-			stop_glerror();
-
-		//copy depth and stencil from deferred screen
-		//mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
-		//					0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-
-		if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
-		{
-			mDeferredLight[1].bindTarget();
-			// clear color buffer here (GI) - zeroing alpha (glow) is important or it will accumulate against sky
-			glClearColor(0,0,0,0);
-			mScreen.clear(GL_COLOR_BUFFER_BIT);
-		}
-		else
-		{
-			mScreen.bindTarget();
-			// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
-			glClearColor(0,0,0,0);
-			mScreen.clear(GL_COLOR_BUFFER_BIT);
-		}
-
-		if (gSavedSettings.getBOOL("RenderDeferredAtmospheric"))
-		{ //apply sunlight contribution 
-			LLFastTimer ftm(FTM_ATMOSPHERICS);
-			bindDeferredShader(gDeferredSoftenProgram, 0, &mGIMapPost[0]);	
-			{
-				LLGLDepthTest depth(GL_FALSE);
-				LLGLDisable blend(GL_BLEND);
-				LLGLDisable test(GL_ALPHA_TEST);
-
-				//full screen blit
-				glPushMatrix();
-				glLoadIdentity();
-				glMatrixMode(GL_PROJECTION);
-				glPushMatrix();
-				glLoadIdentity();
-
-				glVertexPointer(2, GL_FLOAT, 0, vert);
-				
-				glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-				
-				glPopMatrix();
-				glMatrixMode(GL_MODELVIEW);
-				glPopMatrix();
-			}
-
-			unbindDeferredShader(gDeferredSoftenProgram);
-		}
-
-		{ //render sky
-			LLGLDisable blend(GL_BLEND);
-			LLGLDisable stencil(GL_STENCIL_TEST);
-			gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
-			gPipeline.pushRenderTypeMask();
-			
-			gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
-										LLPipeline::RENDER_TYPE_CLOUDS,
-										LLPipeline::RENDER_TYPE_WL_SKY,
-										LLPipeline::END_RENDER_TYPES);
-								
-			
-			renderGeomPostDeferred(*LLViewerCamera::getInstance());
-			gPipeline.popRenderTypeMask();
-		}
-
-		BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights");
-		BOOL render_fullscreen = gSavedSettings.getBOOL("RenderDeferredFullscreenLights");
-		
-
-		if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
-		{
-			mDeferredLight[1].flush();
-			mDeferredLight[2].bindTarget();
-			mDeferredLight[2].clear(GL_COLOR_BUFFER_BIT);
-		}
-
-		if (render_local || render_fullscreen)
-		{
-			gGL.setSceneBlendType(LLRender::BT_ADD);
-			std::list<LLVector4> fullscreen_lights;
-			LLDrawable::drawable_list_t spot_lights;
-			LLDrawable::drawable_list_t fullscreen_spot_lights;
-
-			for (U32 i = 0; i < 2; i++)
-			{
-				mTargetShadowSpotLight[i] = NULL;
-			}
-
-			std::list<LLVector4> light_colors;
-
-			F32 v[24];
-			glVertexPointer(3, GL_FLOAT, 0, v);
-			BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights");
-
-			{
-				bindDeferredShader(gDeferredLightProgram);
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-				for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
-				{
-					LLDrawable* drawablep = *iter;
-					
-					LLVOVolume* volume = drawablep->getVOVolume();
-					if (!volume)
-					{
-						continue;
-					}
-
-					if (volume->isAttachment())
-					{
-						if (!sRenderAttachedLights)
-						{
-							continue;
-						}
-					}
-
-
-					LLVector3 center = drawablep->getPositionAgent();
-					F32* c = center.mV;
-					F32 s = volume->getLightRadius()*1.5f;
-
-					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
-					if (col.magVecSquared() < 0.001f)
-					{
-						continue;
-					}
-
-					if (s <= 0.001f)
-					{
-						continue;
-					}
-
-					if (camera->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0)
-					{
-						continue;
-					}
-
-					sVisibleLightCount++;
-
-					glh::vec3f tc(c);
-					mat.mult_matrix_vec(tc);
-					
-					//vertex positions are encoded so the 3 bits of their vertex index 
-					//correspond to their axis facing, with bit position 3,2,1 matching
-					//axis facing x,y,z, bit set meaning positive facing, bit clear 
-					//meaning negative facing
-					v[0] = c[0]-s; v[1]  = c[1]-s; v[2]  = c[2]-s;  // 0 - 0000 
-					v[3] = c[0]-s; v[4]  = c[1]-s; v[5]  = c[2]+s;  // 1 - 0001
-					v[6] = c[0]-s; v[7]  = c[1]+s; v[8]  = c[2]-s;  // 2 - 0010
-					v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s;  // 3 - 0011
-																									   
-					v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
-					v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
-					v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
-					v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
-
-					if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
-						camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
-						camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
-						camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
-						camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
-						camera->getOrigin().mV[2] < c[2] - s - 0.2f)
-					{ //draw box if camera is outside box
-						if (render_local)
-						{
-							if (volume->isLightSpotlight())
-							{
-								drawablep->getVOVolume()->updateSpotLightPriority();
-								spot_lights.push_back(drawablep);
-								continue;
-							}
-							
-							LLFastTimer ftm(FTM_LOCAL_LIGHTS);
-							glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
-							glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
-							glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
-								GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center));
-							stop_glerror();
-						}
-					}
-					else if (render_fullscreen)
-					{	
-						if (volume->isLightSpotlight())
-						{
-							drawablep->getVOVolume()->updateSpotLightPriority();
-							fullscreen_spot_lights.push_back(drawablep);
-							continue;
-						}
-
-						fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
-						light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
-					}
-				}
-				unbindDeferredShader(gDeferredLightProgram);
-			}
-
-			if (!spot_lights.empty())
-			{
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-				bindDeferredShader(gDeferredSpotLightProgram);
-
-				gDeferredSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
-
-				for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
-				{
-					LLFastTimer ftm(FTM_PROJECTORS);
-					LLDrawable* drawablep = *iter;
-
-					LLVOVolume* volume = drawablep->getVOVolume();
-
-					LLVector3 center = drawablep->getPositionAgent();
-					F32* c = center.mV;
-					F32 s = volume->getLightRadius()*1.5f;
-
-					sVisibleLightCount++;
-
-					glh::vec3f tc(c);
-					mat.mult_matrix_vec(tc);
-					
-					setupSpotLight(gDeferredSpotLightProgram, drawablep);
-					
-					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
-					//vertex positions are encoded so the 3 bits of their vertex index 
-					//correspond to their axis facing, with bit position 3,2,1 matching
-					//axis facing x,y,z, bit set meaning positive facing, bit clear 
-					//meaning negative facing
-					v[0] = c[0]-s; v[1]  = c[1]-s; v[2]  = c[2]-s;  // 0 - 0000 
-					v[3] = c[0]-s; v[4]  = c[1]-s; v[5]  = c[2]+s;  // 1 - 0001
-					v[6] = c[0]-s; v[7]  = c[1]+s; v[8]  = c[2]-s;  // 2 - 0010
-					v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s;  // 3 - 0011
-																									   
-					v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
-					v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
-					v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
-					v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
-
-					glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
-					glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
-					glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
-							GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center));
-				}
-				gDeferredSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
-				unbindDeferredShader(gDeferredSpotLightProgram);
-			}
-
-			{
-				bindDeferredShader(gDeferredMultiLightProgram);
-			
-				LLGLDepthTest depth(GL_FALSE);
-
-				//full screen blit
-				glPushMatrix();
-				glLoadIdentity();
-				glMatrixMode(GL_PROJECTION);
-				glPushMatrix();
-				glLoadIdentity();
-
-				U32 count = 0;
-
-				const U32 max_count = 8;
-				LLVector4 light[max_count];
-				LLVector4 col[max_count];
-
-				glVertexPointer(2, GL_FLOAT, 0, vert);
-
-				F32 far_z = 0.f;
-
-				while (!fullscreen_lights.empty())
-				{
-					LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS);
-					light[count] = fullscreen_lights.front();
-					fullscreen_lights.pop_front();
-					col[count] = light_colors.front();
-					light_colors.pop_front();
-
-					far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
-
-					count++;
-					if (count == max_count || fullscreen_lights.empty())
-					{
-						gDeferredMultiLightProgram.uniform1i("light_count", count);
-						gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light);
-						gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light);
-						gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col);
-						gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col);
-						gDeferredMultiLightProgram.uniform1f("far_z", far_z);
-						far_z = 0.f;
-						count = 0;
-						glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-					}
-				}
-				
-				unbindDeferredShader(gDeferredMultiLightProgram);
-
-				bindDeferredShader(gDeferredMultiSpotLightProgram);
-
-				gDeferredMultiSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
-
-				for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
-				{
-					LLFastTimer ftm(FTM_PROJECTORS);
-					LLDrawable* drawablep = *iter;
-					
-					LLVOVolume* volume = drawablep->getVOVolume();
-
-					LLVector3 center = drawablep->getPositionAgent();
-					F32* c = center.mV;
-					F32 s = volume->getLightRadius()*1.5f;
-
-					sVisibleLightCount++;
-
-					glh::vec3f tc(c);
-					mat.mult_matrix_vec(tc);
-					
-					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
-
-					LLColor3 col = volume->getLightColor();
-					col *= volume->getLightIntensity();
-
-					glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
-					glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
-					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
-				}
-
-				gDeferredMultiSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
-				unbindDeferredShader(gDeferredMultiSpotLightProgram);
-
-				glPopMatrix();
-				glMatrixMode(GL_MODELVIEW);
-				glPopMatrix();
-			}
-		}
-
-		gGL.setColorMask(true, true);
-
-		if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
-		{
-			mDeferredLight[2].flush();
-
-			mScreen.bindTarget();
-			mScreen.clear(GL_COLOR_BUFFER_BIT);
-		
-			gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
-			{ //mix various light maps (local, sun, gi)
-				LLFastTimer ftm(FTM_POST);
-				LLGLDisable blend(GL_BLEND);
-				LLGLDisable test(GL_ALPHA_TEST);
-				LLGLDepthTest depth(GL_FALSE);
-				LLGLDisable stencil(GL_STENCIL_TEST);
-			
-				bindDeferredShader(gDeferredPostProgram, 0, &mGIMapPost[0]);
-
-				gDeferredPostProgram.bind();
-
-				LLVertexBuffer::unbind();
-
-				glVertexPointer(2, GL_FLOAT, 0, vert);
-				glColor3f(1,1,1);
-
-				glPushMatrix();
-				glLoadIdentity();
-				glMatrixMode(GL_PROJECTION);
-				glPushMatrix();
-				glLoadIdentity();
-
-				glDrawArrays(GL_TRIANGLES, 0, 3);
-
-				glPopMatrix();
-				glMatrixMode(GL_MODELVIEW);
-				glPopMatrix();
-
-				unbindDeferredShader(gDeferredPostProgram);
-			}
-		}
-	}
-
-	{ //render non-deferred geometry (alpha, fullbright, glow)
-		LLGLDisable blend(GL_BLEND);
-		LLGLDisable stencil(GL_STENCIL_TEST);
-
-		pushRenderTypeMask();
-		andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
-						 LLPipeline::RENDER_TYPE_FULLBRIGHT,
-						 LLPipeline::RENDER_TYPE_VOLUME,
-						 LLPipeline::RENDER_TYPE_GLOW,
-						 LLPipeline::RENDER_TYPE_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_SIMPLE,
-						 LLPipeline::RENDER_TYPE_PASS_ALPHA,
-						 LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
-						 LLPipeline::RENDER_TYPE_PASS_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
-						 LLPipeline::RENDER_TYPE_PASS_GLOW,
-						 LLPipeline::RENDER_TYPE_PASS_GRASS,
-						 LLPipeline::RENDER_TYPE_PASS_SHINY,
-						 LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
-						 LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
-						 LLPipeline::RENDER_TYPE_AVATAR,
-						 END_RENDER_TYPES);
-		
-		renderGeomPostDeferred(*LLViewerCamera::getInstance());
-		popRenderTypeMask();
-	}
-
-	{
-		//render highlights, etc.
-		renderHighlights();
-		mHighlightFaces.clear();
-
-		renderDebug();
-
-		LLVertexBuffer::unbind();
-
-		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-		{
-			// Render debugging beacons.
-			gObjectList.renderObjectBeacons();
-			gObjectList.resetObjectBeacons();
-		}
-	}
-
-	mScreen.flush();
-						
-}
-
-void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
-{
-	//construct frustum
-	LLVOVolume* volume = drawablep->getVOVolume();
-	LLVector3 params = volume->getSpotLightParams();
-
-	F32 fov = params.mV[0];
-	F32 focus = params.mV[1];
-
-	LLVector3 pos = drawablep->getPositionAgent();
-	LLQuaternion quat = volume->getRenderRotation();
-	LLVector3 scale = volume->getScale();
-	
-	//get near clip plane
-	LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
-	at_axis *= quat;
-
-	LLVector3 np = pos+at_axis;
-	at_axis.normVec();
-
-	//get origin that has given fov for plane np, at_axis, and given scale
-	F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
-
-	LLVector3 origin = np - at_axis*dist;
-
-	//matrix from volume space to agent space
-	LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
-
-	glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
-	glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
-
-	glh::matrix4f screen_to_light = light_to_screen.inverse();
-
-	F32 s = volume->getLightRadius()*1.5f;
-	F32 near_clip = dist;
-	F32 width = scale.mV[VX];
-	F32 height = scale.mV[VY];
-	F32 far_clip = s+dist-scale.mV[VZ];
-
-	F32 fovy = fov * RAD_TO_DEG;
-	F32 aspect = width/height;
-
-	glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
-				0.f, 0.5f, 0.f, 0.5f,
-				0.f, 0.f, 0.5f, 0.5f,
-				0.f, 0.f, 0.f, 1.f);
-
-	glh::vec3f p1(0, 0, -(near_clip+0.01f));
-	glh::vec3f p2(0, 0, -(near_clip+1.f));
-
-	glh::vec3f screen_origin(0, 0, 0);
-
-	light_to_screen.mult_matrix_vec(p1);
-	light_to_screen.mult_matrix_vec(p2);
-	light_to_screen.mult_matrix_vec(screen_origin);
-
-	glh::vec3f n = p2-p1;
-	n.normalize();
-	
-	F32 proj_range = far_clip - near_clip;
-	glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip);
-	screen_to_light = trans * light_proj * screen_to_light;
-	shader.uniformMatrix4fv("proj_mat", 1, FALSE, screen_to_light.m);
-	shader.uniform1f("proj_near", near_clip);
-	shader.uniform3fv("proj_p", 1, p1.v);
-	shader.uniform3fv("proj_n", 1, n.v);
-	shader.uniform3fv("proj_origin", 1, screen_origin.v);
-	shader.uniform1f("proj_range", proj_range);
-	shader.uniform1f("proj_ambiance", params.mV[2]);
-	S32 s_idx = -1;
-
-	for (U32 i = 0; i < 2; i++)
-	{
-		if (mShadowSpotLight[i] == drawablep)
-		{
-			s_idx = i;
-		}
-	}
-
-	shader.uniform1i("proj_shadow_idx", s_idx);
-
-	if (s_idx >= 0)
-	{
-		shader.uniform1f("shadow_fade", 1.f-mSpotLightFade[s_idx]);
-	}
-	else
-	{
-		shader.uniform1f("shadow_fade", 1.f);
-	}
-
-	{
-		LLDrawable* potential = drawablep;
-		//determine if this is a good light for casting shadows
-		F32 m_pri = volume->getSpotLightPriority();
-
-		for (U32 i = 0; i < 2; i++)
-		{
-			F32 pri = 0.f;
-
-			if (mTargetShadowSpotLight[i].notNull())
-			{
-				pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();			
-			}
-
-			if (m_pri > pri)
-			{
-				LLDrawable* temp = mTargetShadowSpotLight[i];
-				mTargetShadowSpotLight[i] = potential;
-				potential = temp;
-				m_pri = pri;
-			}
-		}
-	}
-
-	LLViewerTexture* img = volume->getLightTexture();
-
-	S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
-
-	if (channel > -1 && img)
-	{
-		gGL.getTexUnit(channel)->bind(img);
-
-		F32 lod_range = logf(img->getWidth())/logf(2.f);
-
-		shader.uniform1f("proj_focus", focus);
-		shader.uniform1f("proj_lod", lod_range);
-		shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
-	}
-}
-
-void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
-{
-	stop_glerror();
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
-	shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIP);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_BLOOM);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS);
-
-	for (U32 i = 0; i < 4; i++)
-	{
-		if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1)
-		{
-			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
-		}
-	}
-
-	for (U32 i = 4; i < 6; i++)
-	{
-		if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1)
-		{
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
-		}
-	}
-
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
-	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC);
-
-	S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
-	if (channel > -1)
-	{
-		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
-		if (cube_map)
-		{
-			cube_map->disable();
-		}
-	}
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(0)->activate();
-	shader.unbind();
-
-	LLGLState::checkTextureChannels();
-}
-
-inline float sgn(float a)
-{
-    if (a > 0.0F) return (1.0F);
-    if (a < 0.0F) return (-1.0F);
-    return (0.0F);
-}
-
-void LLPipeline::generateWaterReflection(LLCamera& camera_in)
-{	
-	if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
-	{
-		BOOL skip_avatar_update = FALSE;
-		if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK)
-		{
-			skip_avatar_update = TRUE;
-		}
-
-		if (!skip_avatar_update)
-		{
-			gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
-		}
-		LLVertexBuffer::unbind();
-
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
-
-		LLCamera camera = camera_in;
-		camera.setFar(camera.getFar()*0.87654321f);
-		LLPipeline::sReflectionRender = TRUE;
-		S32 occlusion = LLPipeline::sUseOcclusion;
-
-		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-
-		LLPipeline::sUseOcclusion = llmin(occlusion, 1);
-		
-		gPipeline.pushRenderTypeMask();
-
-		glh::matrix4f projection = glh_get_current_projection();
-		glh::matrix4f mat;
-
-		stop_glerror();
-		LLPlane plane;
-
-		F32 height = gAgent.getRegion()->getWaterHeight(); 
-		F32 to_clip = fabsf(camera.getOrigin().mV[2]-height);
-		F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by
-
-		//plane params
-		LLVector3 pnorm;
-		F32 pd;
-
-		S32 water_clip = 0;
-		if (!LLViewerCamera::getInstance()->cameraUnderWater())
-		{ //camera is above water, clip plane points up
-			pnorm.setVec(0,0,1);
-			pd = -height;
-			plane.setVec(pnorm, pd);
-			water_clip = -1;
-		}
-		else
-		{	//camera is below water, clip plane points down
-			pnorm = LLVector3(0,0,-1);
-			pd = height;
-			plane.setVec(pnorm, pd);
-			water_clip = 1;
-		}
-
-		if (!LLViewerCamera::getInstance()->cameraUnderWater())
-		{	//generate planar reflection map
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			glClearColor(0,0,0,0);
-			mWaterRef.bindTarget();
-			gGL.setColorMask(true, true);
-			mWaterRef.clear();
-			gGL.setColorMask(true, false);
-
-			mWaterRef.getViewport(gGLViewport);
-			
-			stop_glerror();
-
-			glPushMatrix();
-
-			mat.set_scale(glh::vec3f(1,1,-1));
-			mat.set_translate(glh::vec3f(0,0,height*2.f));
-			
-			glh::matrix4f current = glh_get_current_modelview();
-
-			mat = current * mat;
-
-			glh_set_current_modelview(mat);
-			glLoadMatrixf(mat.m);
-
-			LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
-
-			glh::matrix4f inv_mat = mat.inverse();
-
-			glh::vec3f origin(0,0,0);
-			inv_mat.mult_matrix_vec(origin);
-
-			camera.setOrigin(origin.v);
-
-			glCullFace(GL_FRONT);
-
-			static LLCullResult ref_result;
-		
-			if (LLDrawPoolWater::sNeedsDistortionUpdate)
-			{
-				//initial sky pass (no user clip plane)
-				{ //mask out everything but the sky
-					gPipeline.pushRenderTypeMask();
-					gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
-												LLPipeline::RENDER_TYPE_WL_SKY,
-												LLPipeline::END_RENDER_TYPES);
-					static LLCullResult result;
-					updateCull(camera, result);
-					stateSort(camera, result);
-					andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
-										LLPipeline::RENDER_TYPE_CLOUDS,
-										LLPipeline::RENDER_TYPE_WL_SKY,
-										LLPipeline::END_RENDER_TYPES);
-
-					renderGeom(camera, TRUE);
-					gPipeline.popRenderTypeMask();
-				}
-
-				gPipeline.pushRenderTypeMask();
-
-				clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
-									LLPipeline::RENDER_TYPE_VOIDWATER,
-									LLPipeline::RENDER_TYPE_GROUND,
-									LLPipeline::RENDER_TYPE_SKY,
-									LLPipeline::RENDER_TYPE_CLOUDS,
-									LLPipeline::END_RENDER_TYPES);	
-
-					S32 detail = gSavedSettings.getS32("RenderReflectionDetail");
-				if (detail > 0)
-				{ //mask out selected geometry based on reflection detail
-					if (detail < 4)
-					{
-						clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
-					if (detail < 3)
-					{
-							clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
-						if (detail < 2)
-						{
-								clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
-							}
-						}
-					}
-
-					LLGLUserClipPlane clip_plane(plane, mat, projection);
-					LLGLDisable cull(GL_CULL_FACE);
-					updateCull(camera, ref_result, 1);
-					stateSort(camera, ref_result);
-				}
-				
-			if (LLDrawPoolWater::sNeedsDistortionUpdate)
-			{
-					if (gSavedSettings.getS32("RenderReflectionDetail") > 0)
-				{
-					gPipeline.grabReferences(ref_result);
-					LLGLUserClipPlane clip_plane(plane, mat, projection);
-					renderGeom(camera);
-				}
-			}	
-
-				gPipeline.popRenderTypeMask();
-			}	
-			glCullFace(GL_BACK);
-			glPopMatrix();
-			mWaterRef.flush();
-			glh_set_current_modelview(current);
-		}
-
-		camera.setOrigin(camera_in.getOrigin());
-		//render distortion map
-		static BOOL last_update = TRUE;
-		if (last_update)
-		{
-			camera.setFar(camera_in.getFar());
-			clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
-								LLPipeline::RENDER_TYPE_VOIDWATER,
-								LLPipeline::RENDER_TYPE_GROUND,
-								END_RENDER_TYPES);	
-			stop_glerror();
-
-			LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? FALSE : TRUE;
-
-			if (LLPipeline::sUnderWaterRender)
-			{
-				clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND,
-									LLPipeline::RENDER_TYPE_SKY,
-									LLPipeline::RENDER_TYPE_CLOUDS,
-									LLPipeline::RENDER_TYPE_WL_SKY,
-									END_RENDER_TYPES);		
-			}
-			LLViewerCamera::updateFrustumPlanes(camera);
-
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLColor4& col = LLDrawPoolWater::sWaterFogColor;
-			glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
-			mWaterDis.bindTarget();
-			mWaterDis.getViewport(gGLViewport);
-			
-			if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
-			{
-				//clip out geometry on the same side of water as the camera
-				mat = glh_get_current_modelview();
-				LLGLUserClipPlane clip_plane(LLPlane(-pnorm, -(pd+pad)), mat, projection);
-				static LLCullResult result;
-				updateCull(camera, result, water_clip);
-				stateSort(camera, result);
-
-				gGL.setColorMask(true, true);
-				mWaterDis.clear();
-				gGL.setColorMask(true, false);
-
-				renderGeom(camera);
-			}
-
-			LLPipeline::sUnderWaterRender = FALSE;
-			mWaterDis.flush();
-		}
-		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
-
-		LLRenderTarget::unbindTarget();
-
-		LLPipeline::sReflectionRender = FALSE;
-
-		if (!LLRenderTarget::sUseFBO)
-		{
-			glClear(GL_DEPTH_BUFFER_BIT);
-		}
-		glClearColor(0.f, 0.f, 0.f, 0.f);
-		gViewerWindow->setup3DViewport();
-		gPipeline.popRenderTypeMask();
-		LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
-		LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
-		LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd));
-		LLPipeline::sUseOcclusion = occlusion;
-		
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
-
-		if (!skip_avatar_update)
-		{
-			gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
-		}
-	}
-}
-
-glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
-{
-	glh::matrix4f ret;
-
-	LLVector3 dirN;
-	LLVector3 upN;
-	LLVector3 lftN;
-
-	lftN = dir % up;
-	lftN.normVec();
-	
-	upN = lftN % dir;
-	upN.normVec();
-	
-	dirN = dir;
-	dirN.normVec();
-
-	ret.m[ 0] = lftN[0];
-	ret.m[ 1] = upN[0];
-	ret.m[ 2] = -dirN[0];
-	ret.m[ 3] = 0.f;
-
-	ret.m[ 4] = lftN[1];
-	ret.m[ 5] = upN[1];
-	ret.m[ 6] = -dirN[1];
-	ret.m[ 7] = 0.f;
-
-	ret.m[ 8] = lftN[2];
-	ret.m[ 9] = upN[2];
-	ret.m[10] = -dirN[2];
-	ret.m[11] = 0.f;
-
-	ret.m[12] = -(lftN*pos);
-	ret.m[13] = -(upN*pos);
-	ret.m[14] = dirN*pos;
-	ret.m[15] = 1.f;
-
-	return ret;
-}
-
-glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
-{
-	glh::matrix4f ret;
-	ret.m[ 0] = 2/(max[0]-min[0]);
-	ret.m[ 4] = 0;
-	ret.m[ 8] = 0;
-	ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]);
-
-	ret.m[ 1] = 0;
-	ret.m[ 5] = 2/(max[1]-min[1]);
-	ret.m[ 9] = 0;
-	ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]);
-
-	ret.m[ 2] = 0;
-	ret.m[ 6] = 0;
-	ret.m[10] = 2/(max[2]-min[2]);
-	ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]);
-
-	ret.m[ 3] = 0;
-	ret.m[ 7] = 0;
-	ret.m[11] = 0;
-	ret.m[15] = 1;
-
-	return ret;
-}
-
-static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
-static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
-static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
-
-void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
-{
-	LLFastTimer t(FTM_SHADOW_RENDER);
-
-	//clip out geometry on the same side of water as the camera
-	S32 occlude = LLPipeline::sUseOcclusion;
-	if (!use_occlusion)
-	{
-		LLPipeline::sUseOcclusion = 0;
-	}
-	LLPipeline::sShadowRender = TRUE;
-	
-	U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP, LLRenderPass::PASS_FULLBRIGHT_SHINY };
-	LLGLEnable cull(GL_CULL_FACE);
-
-	if (use_shader)
-	{
-		gDeferredShadowProgram.bind();
-	}
-
-	updateCull(shadow_cam, result);
-	stateSort(shadow_cam, result);
-	
-	//generate shadow map
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	glLoadMatrixf(proj.m);
-	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
-	glLoadMatrixf(view.m);
-
-	stop_glerror();
-	gGLLastMatrix = NULL;
-
-	{
-		LLGLDepthTest depth(GL_TRUE);
-		glClear(GL_DEPTH_BUFFER_BIT);
-	}
-
-	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			
-	glColor4f(1,1,1,1);
-	
-	stop_glerror();
-
-	gGL.setColorMask(false, false);
-	
-	//glCullFace(GL_FRONT);
-
-	{
-		LLFastTimer ftm(FTM_SHADOW_SIMPLE);
-		LLGLDisable test(GL_ALPHA_TEST);
-		gGL.getTexUnit(0)->disable();
-		for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
-		{
-			renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
-		}
-		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-	}
-	
-	if (use_shader)
-	{
-		gDeferredShadowProgram.unbind();
-		renderGeomShadow(shadow_cam);
-		gDeferredShadowProgram.bind();
-	}
-	else
-	{
-		renderGeomShadow(shadow_cam);
-	}
-
-	{
-		LLFastTimer ftm(FTM_SHADOW_ALPHA);
-		LLGLEnable test(GL_ALPHA_TEST);
-		gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f);
-		renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE);
-		glColor4f(1,1,1,1);
-		renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
-		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
-	}
-
-	//glCullFace(GL_BACK);
-
-	gGLLastMatrix = NULL;
-	glLoadMatrixd(gGLModelView);
-	doOcclusion(shadow_cam);
-
-	if (use_shader)
-	{
-		gDeferredShadowProgram.unbind();
-	}
-	
-	gGL.setColorMask(true, true);
-			
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-	gGLLastMatrix = NULL;
-
-	LLPipeline::sUseOcclusion = occlude;
-	LLPipeline::sShadowRender = FALSE;
-}
-
-static LLFastTimer::DeclareTimer FTM_VISIBLE_CLOUD("Visible Cloud");
-BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
-{
-	LLFastTimer t(FTM_VISIBLE_CLOUD);
-	//get point cloud of intersection of frust and min, max
-
-	if (getVisibleExtents(camera, min, max))
-	{
-		return FALSE;
-	}
-
-	//get set of planes on bounding box
-	std::vector<LLPlane> bp;
-		
-	bp.push_back(LLPlane(min, LLVector3(-1,0,0)));
-	bp.push_back(LLPlane(min, LLVector3(0,-1,0)));
-	bp.push_back(LLPlane(min, LLVector3(0,0,-1)));
-	bp.push_back(LLPlane(max, LLVector3(1,0,0)));
-	bp.push_back(LLPlane(max, LLVector3(0,1,0)));
-	bp.push_back(LLPlane(max, LLVector3(0,0,1)));
-	
-	//potential points
-	std::vector<LLVector3> pp;
-
-	//add corners of AABB
-	pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2]));
-	pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2]));
-	pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2]));
-	pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2]));
-	pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2]));
-	pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2]));
-	pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2]));
-	pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2]));
-
-	//add corners of camera frustum
-	for (U32 i = 0; i < 8; i++)
-	{
-		pp.push_back(camera.mAgentFrustum[i]);
-	}
-
-
-	//bounding box line segments
-	U32 bs[] = 
-			{
-		0,1,
-		1,3,
-		3,2,
-		2,0,
-
-		4,5,
-		5,7,
-		7,6,
-		6,4,
-
-		0,4,
-		1,5,
-		3,7,
-		2,6
-	};
-
-	for (U32 i = 0; i < 12; i++)
-	{ //for each line segment in bounding box
-		for (U32 j = 0; j < 6; j++) 
-		{ //for each plane in camera frustum
-			const LLPlane& cp = camera.getAgentPlane(j);
-			const LLVector3& v1 = pp[bs[i*2+0]];
-			const LLVector3& v2 = pp[bs[i*2+1]];
-			const LLVector3 n(cp.mV);
-
-			LLVector3 line = v1-v2;
-
-			F32 d1 = line*n;
-			F32 d2 = -cp.dist(v2);
-
-			F32 t = d2/d1;
-
-			if (t > 0.f && t < 1.f)
-			{
-				LLVector3 intersect = v2+line*t;
-				pp.push_back(intersect);
-			}
-			}
-		}
-			
-	//camera frustum line segments
-	const U32 fs[] =
-	{
-		0,1,
-		1,2,
-		2,3,
-		3,1,
-
-		4,5,
-		5,6,
-		6,7,
-		7,4,
-	
-		0,4,
-		1,5,
-		2,6,
-		3,7	
-	};
-
-	LLVector3 center = (max+min)*0.5f;
-	LLVector3 size = (max-min)*0.5f;
-	
-	for (U32 i = 0; i < 12; i++)
-	{
-		for (U32 j = 0; j < 6; ++j)
-		{
-			const LLVector3& v1 = pp[fs[i*2+0]+8];
-			const LLVector3& v2 = pp[fs[i*2+1]+8];
-			const LLPlane& cp = bp[j];
-			const LLVector3 n(cp.mV);
-
-			LLVector3 line = v1-v2;
-
-			F32 d1 = line*n;
-			F32 d2 = -cp.dist(v2);
-
-			F32 t = d2/d1;
-
-			if (t > 0.f && t < 1.f)
-			{
-				LLVector3 intersect = v2+line*t;
-				pp.push_back(intersect);
-			}	
-		}
-				}
-
-	LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f),
-		max+LLVector3(0.05f,0.05f,0.05f) };
-
-	for (U32 i = 0; i < pp.size(); ++i)
-	{
-		bool found = true;
-
-		const F32* p = pp[i].mV;
-			
-		for (U32 j = 0; j < 3; ++j)
-		{
-			if (p[j] < ext[0].mV[j] ||
-				p[j] > ext[1].mV[j])
-			{
-				found = false;
-				break;
-			}
-		}
-				
-		for (U32 j = 0; j < 6; ++j)
-		{
-			const LLPlane& cp = camera.getAgentPlane(j);
-			F32 dist = cp.dist(pp[i]);
-			if (dist > 0.05f) //point is above some plane, not contained
-					{
-				found = false;
-				break;
-						}
-					}
-
-					if (found)
-					{
-			fp.push_back(pp[i]);
-		}
-	}
-	
-	if (fp.empty())
-	{
-		return FALSE;
-	}
-	
-	return TRUE;
-}
-
-void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc)
-{
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) < 3)
-	{
-		return;
-	}
-
-	LLVector3 up;
-
-	//LLGLEnable depth_clamp(GL_DEPTH_CLAMP_NV);
-
-	if (lightDir.mV[2] > 0.5f)
-	{
-		up = LLVector3(1,0,0);
-	}
-	else
-	{
-		up = LLVector3(0, 0, 1);
-	}
-
-	
-	F32 gi_range = gSavedSettings.getF32("RenderGIRange");
-
-	U32 res = mGIMap.getWidth();
-
-	F32 atten = llmax(gSavedSettings.getF32("RenderGIAttenuation"), 0.001f);
-
-	//set radius to range at which distance attenuation of incoming photons is near 0
-
-	F32 lrad = sqrtf(1.f/(atten*0.01f));
-
-	F32 lrange = lrad+gi_range*0.5f;
-
-	LLVector3 pad(lrange,lrange,lrange);
-
-	glh::matrix4f view = look(LLVector3(128.f,128.f,128.f), lightDir, up);
-
-	LLVector3 cp = camera.getOrigin()+camera.getAtAxis()*(gi_range*0.5f);
-
-	glh::vec3f scp(cp.mV);
-	view.mult_matrix_vec(scp);
-	cp.setVec(scp.v);
-
-	F32 pix_width = lrange/(res*0.5f);
-
-	//move cp to the nearest pix_width
-	for (U32 i = 0; i < 3; i++)
-	{
-		cp.mV[i] = llround(cp.mV[i], pix_width);
-	}
-	
-	LLVector3 min = cp-pad;
-	LLVector3 max = cp+pad;
-	
-	//set mGIRange to range in tc space[0,1] that covers texture block of intersecting lights around a point
-	mGIRange.mV[0] = (max.mV[0]-min.mV[0])/res;
-	mGIRange.mV[1] = (max.mV[1]-min.mV[1])/res;
-	mGILightRadius = lrad/lrange*0.5f;
-
-	glh::matrix4f proj = gl_ortho(min.mV[0], max.mV[0],
-								min.mV[1], max.mV[1],
-								-max.mV[2], -min.mV[2]);
-
-	LLCamera sun_cam = camera;
-
-	glh::matrix4f eye_view = glh_get_current_modelview();
-	
-	//get eye space to camera space matrix
-	mGIMatrix = view*eye_view.inverse();
-	mGINormalMatrix = mGIMatrix.inverse().transpose();
-	mGIInvProj = proj.inverse();
-	mGIMatrixProj = proj*mGIMatrix;
-
-	//translate and scale to [0,1]
-	glh::matrix4f trans(.5f, 0.f, 0.f, .5f,
-						0.f, 0.5f, 0.f, 0.5f,
-						0.f, 0.f, 0.5f, 0.5f,
-						0.f, 0.f, 0.f, 1.f);
-
-	mGIMatrixProj = trans*mGIMatrixProj;
-
-	glh_set_current_modelview(view);
-	glh_set_current_projection(proj);
-
-	LLViewerCamera::updateFrustumPlanes(sun_cam, TRUE, FALSE, TRUE);
-
-	sun_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
-	static LLCullResult result;
-
-	pushRenderTypeMask();
-
-	andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
-								 LLPipeline::RENDER_TYPE_FULLBRIGHT,
-								 LLPipeline::RENDER_TYPE_BUMP,
-								 LLPipeline::RENDER_TYPE_VOLUME,
-								 LLPipeline::RENDER_TYPE_TREE, 
-								 LLPipeline::RENDER_TYPE_TERRAIN,
-								 LLPipeline::RENDER_TYPE_WATER,
-								 LLPipeline::RENDER_TYPE_VOIDWATER,
-								 LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,
-								 LLPipeline::RENDER_TYPE_AVATAR,
-								 LLPipeline::RENDER_TYPE_PASS_SIMPLE,
-								 LLPipeline::RENDER_TYPE_PASS_BUMP,
-								 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
-								 LLPipeline::RENDER_TYPE_PASS_SHINY,
-								 END_RENDER_TYPES);
-
-
-	
-	S32 occlude = LLPipeline::sUseOcclusion;
-	//LLPipeline::sUseOcclusion = 0;
-	LLPipeline::sShadowRender = TRUE;
-	
-	//only render large objects into GI map
-	sMinRenderSize = gSavedSettings.getF32("RenderGIMinRenderSize");
-	
-	LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_GI_SOURCE;
-	mGIMap.bindTarget();
-	
-	F64 last_modelview[16];
-	F64 last_projection[16];
-	for (U32 i = 0; i < 16; i++)
-	{
-		last_modelview[i] = gGLLastModelView[i];
-		last_projection[i] = gGLLastProjection[i];
-		gGLLastModelView[i] = mGIModelview.m[i];
-		gGLLastProjection[i] = mGIProjection.m[i];
-	}
-
-	sun_cam.setOrigin(0.f, 0.f, 0.f);
-	updateCull(sun_cam, result);
-	stateSort(sun_cam, result);
-	
-	for (U32 i = 0; i < 16; i++)
-	{
-		gGLLastModelView[i] = last_modelview[i];
-		gGLLastProjection[i] = last_projection[i];
-	}
-
-	mGIProjection = proj;
-	mGIModelview = view;
-
-	LLGLEnable cull(GL_CULL_FACE);
-
-	//generate GI map
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	glLoadMatrixf(proj.m);
-	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
-	glLoadMatrixf(view.m);
-
-	stop_glerror();
-	gGLLastMatrix = NULL;
-
-	mGIMap.clear();
-
-	{
-		//LLGLEnable enable(GL_DEPTH_CLAMP_NV);
-		renderGeomDeferred(camera);
-	}
-
-	mGIMap.flush();
-	
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-	gGLLastMatrix = NULL;
-
-	LLPipeline::sUseOcclusion = occlude;
-	LLPipeline::sShadowRender = FALSE;
-	sMinRenderSize = 0.f;
-
-	popRenderTypeMask();
-
-}
-
-void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
-{
-	if (obj && obj->getVolume())
-	{
-		for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter)
-		{
-			renderHighlight(*iter, fade);
-		}
-
-		LLDrawable* drawable = obj->mDrawable;
-		if (drawable)
-		{
-			for (S32 i = 0; i < drawable->getNumFaces(); ++i)
-			{
-				LLFace* face = drawable->getFace(i);
-				if (face)
-				{
-					face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade));
-				}
-			}
-		}
-	}
-}
-
-void LLPipeline::generateHighlight(LLCamera& camera)
-{
-	//render highlighted object as white into offscreen render target
-	if (mHighlightObject.notNull())
-	{
-		mHighlightSet.insert(HighlightItem(mHighlightObject));
-	}
-	
-	if (!mHighlightSet.empty())
-	{
-		F32 transition = gFrameIntervalSeconds/gSavedSettings.getF32("RenderHighlightFadeTime");
-
-		LLGLDisable test(GL_ALPHA_TEST);
-		LLGLDepthTest depth(GL_FALSE);
-		mHighlight.bindTarget();
-		disableLights();
-		gGL.setColorMask(true, true);
-		mHighlight.clear();
-
-		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
-		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
-		{
-			std::set<HighlightItem>::iterator cur_iter = iter++;
-
-			if (cur_iter->mItem.isNull())
-			{
-				mHighlightSet.erase(cur_iter);
-				continue;
-			}
-
-			if (cur_iter->mItem == mHighlightObject)
-			{
-				cur_iter->incrFade(transition); 
-			}
-			else
-			{
-				cur_iter->incrFade(-transition);
-				if (cur_iter->mFade <= 0.f)
-				{
-					mHighlightSet.erase(cur_iter);
-					continue;
-				}
-			}
-
-			renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
-		}
-
-		mHighlight.flush();
-		gGL.setColorMask(true, false);
-		gViewerWindow->setup3DViewport();
-	}
-}
-
-
-void LLPipeline::generateSunShadow(LLCamera& camera)
-{
-	if (!sRenderDeferred || gSavedSettings.getS32("RenderShadowDetail") <= 0)
-	{
-		return;
-	}
-
-	F64 last_modelview[16];
-	F64 last_projection[16];
-	for (U32 i = 0; i < 16; i++)
-	{ //store last_modelview of world camera
-		last_modelview[i] = gGLLastModelView[i];
-		last_projection[i] = gGLLastProjection[i];
-	}
-
-	pushRenderTypeMask();
-	andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
-					LLPipeline::RENDER_TYPE_ALPHA,
-					LLPipeline::RENDER_TYPE_GRASS,
-					LLPipeline::RENDER_TYPE_FULLBRIGHT,
-					LLPipeline::RENDER_TYPE_BUMP,
-					LLPipeline::RENDER_TYPE_VOLUME,
-					LLPipeline::RENDER_TYPE_AVATAR,
-					LLPipeline::RENDER_TYPE_TREE, 
-					LLPipeline::RENDER_TYPE_TERRAIN,
-					LLPipeline::RENDER_TYPE_WATER,
-					LLPipeline::RENDER_TYPE_VOIDWATER,
-					LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,
-					LLPipeline::RENDER_TYPE_PASS_SIMPLE,
-					LLPipeline::RENDER_TYPE_PASS_BUMP,
-					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
-					LLPipeline::RENDER_TYPE_PASS_SHINY,
-					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
-					END_RENDER_TYPES);
-
-	gGL.setColorMask(false, false);
-
-	//get sun view matrix
-	
-	//store current projection/modelview matrix
-	glh::matrix4f saved_proj = glh_get_current_projection();
-	glh::matrix4f saved_view = glh_get_current_modelview();
-	glh::matrix4f inv_view = saved_view.inverse();
-
-	glh::matrix4f view[6];
-	glh::matrix4f proj[6];
-	
-	//clip contains parallel split distances for 3 splits
-	LLVector3 clip = gSavedSettings.getVector3("RenderShadowClipPlanes");
-
-	//F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
-
-	//far clip on last split is minimum of camera view distance and 128
-	mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
-
-	clip = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
-	mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
-
-	//currently used for amount to extrude frusta corners for constructing shadow frusta
-	LLVector3 n = gSavedSettings.getVector3("RenderShadowNearDist");
-	//F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
-
-	LLVector3 lightDir = -mSunDir;
-	lightDir.normVec();
-
-	glh::vec3f light_dir(lightDir.mV);
-
-	//create light space camera matrix
-	
-	LLVector3 at = lightDir;
-
-	LLVector3 up = camera.getAtAxis();
-
-	if (fabsf(up*lightDir) > 0.75f)
-	{
-		up = camera.getUpAxis();
-	}
-
-	/*LLVector3 left = up%at;
-	up = at%left;*/
-
-	up.normVec();
-	at.normVec();
-	
-	
-	LLCamera main_camera = camera;
-	
-	F32 near_clip = 0.f;
-	{
-		//get visible point cloud
-		std::vector<LLVector3> fp;
-
-		main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum);
-		
-		LLVector3 min,max;
-		getVisiblePointCloud(main_camera,min,max,fp);
-
-		if (fp.empty())
-		{
-			if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
-			{
-				mShadowCamera[0] = main_camera;
-				mShadowExtents[0][0] = min;
-				mShadowExtents[0][1] = max;
-
-				mShadowFrustPoints[0].clear();
-				mShadowFrustPoints[1].clear();
-				mShadowFrustPoints[2].clear();
-				mShadowFrustPoints[3].clear();
-			}
-			popRenderTypeMask();
-			return;
-		}
-
-		generateGI(camera, lightDir, fp);
-
-		//get good split distances for frustum
-		for (U32 i = 0; i < fp.size(); ++i)
-		{
-			glh::vec3f v(fp[i].mV);
-			saved_view.mult_matrix_vec(v);
-			fp[i].setVec(v.v);
-		}
-
-		min = fp[0];
-		max = fp[0];
-
-		//get camera space bounding box
-		for (U32 i = 1; i < fp.size(); ++i)
-		{
-			update_min_max(min, max, fp[i]);
-		}
-
-		near_clip = -max.mV[2];
-		F32 far_clip = -min.mV[2]*2.f;
-
-		far_clip = llmin(far_clip, 128.f);
-		far_clip = llmin(far_clip, camera.getFar());
-
-		F32 range = far_clip-near_clip;
-
-		LLVector3 split_exp = gSavedSettings.getVector3("RenderShadowSplitExponent");
-
-		F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) );
-		
-		da = powf(da, split_exp.mV[2]);
-
-
-		F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
-
-
-		for (U32 i = 0; i < 4; ++i)
-		{
-			F32 x = (F32)(i+1)/4.f;
-			x = powf(x, sxp);
-			mSunClipPlanes.mV[i] = near_clip+range*x;
-		}
-	}
-
-	// convenience array of 4 near clip plane distances
-	F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
-	
-	for (S32 j = 0; j < 4; j++)
-	{
-		if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
-		{
-			mShadowFrustPoints[j].clear();
-		}
-
-		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j;
-
-		//restore render matrices
-		glh_set_current_modelview(saved_view);
-		glh_set_current_projection(saved_proj);
-
-		LLVector3 eye = camera.getOrigin();
-
-		//camera used for shadow cull/render
-		LLCamera shadow_cam;
-		
-		//create world space camera frustum for this split
-		shadow_cam = camera;
-		shadow_cam.setFar(16.f);
-	
-		LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
-		LLVector3* frust = shadow_cam.mAgentFrustum;
-
-		LLVector3 pn = shadow_cam.getAtAxis();
-		
-		LLVector3 min, max;
-
-		//construct 8 corners of split frustum section
-		for (U32 i = 0; i < 4; i++)
-		{
-			LLVector3 delta = frust[i+4]-eye;
-			delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f;
-			delta.normVec();
-			F32 dp = delta*pn;
-			frust[i] = eye + (delta*dist[j]*0.95f)/dp;
-			frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp;
-		}
-						
-		shadow_cam.calcAgentFrustumPlanes(frust);
-		shadow_cam.mFrustumCornerDist = 0.f;
-		
-		if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-		{
-			mShadowCamera[j] = shadow_cam;
-		}
-
-		std::vector<LLVector3> fp;
-
-		if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
-		{
-			//no possible shadow receivers
-			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-			{
-				mShadowExtents[j][0] = LLVector3();
-				mShadowExtents[j][1] = LLVector3();
-				mShadowCamera[j+4] = shadow_cam;
-			}
-
-			mShadow[j].bindTarget();
-			{
-				LLGLDepthTest depth(GL_TRUE);
-				mShadow[j].clear();
-			}
-			mShadow[j].flush();
-
-			mShadowError.mV[j] = 0.f;
-			mShadowFOV.mV[j] = 0.f;
-
-			continue;
-		}
-
-		if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-		{
-			mShadowExtents[j][0] = min;
-			mShadowExtents[j][1] = max;
-			mShadowFrustPoints[j] = fp;
-		}
-				
-
-		//find a good origin for shadow projection
-		LLVector3 origin;
-
-		//get a temporary view projection
-		view[j] = look(camera.getOrigin(), lightDir, -up);
-
-		std::vector<LLVector3> wpf;
-
-		for (U32 i = 0; i < fp.size(); i++)
-		{
-			glh::vec3f p = glh::vec3f(fp[i].mV);
-			view[j].mult_matrix_vec(p);
-			wpf.push_back(LLVector3(p.v));
-		}
-
-		min = wpf[0];
-		max = wpf[0];
-
-		for (U32 i = 0; i < fp.size(); ++i)
-		{ //get AABB in camera space
-			update_min_max(min, max, wpf[i]);
-		}
-
-		// Construct a perspective transform with perspective along y-axis that contains
-		// points in wpf
-		//Known:
-		// - far clip plane
-		// - near clip plane
-		// - points in frustum
-		//Find:
-		// - origin
-
-		//get some "interesting" points of reference
-		LLVector3 center = (min+max)*0.5f;
-		LLVector3 size = (max-min)*0.5f;
-		LLVector3 near_center = center;
-		near_center.mV[1] += size.mV[1]*2.f;
-		
-		
-		//put all points in wpf in quadrant 0, reletive to center of min/max
-		//get the best fit line using least squares
-		F32 bfm = 0.f;
-		F32 bfb = 0.f;
-
-		for (U32 i = 0; i < wpf.size(); ++i)
-		{
-			wpf[i] -= center;
-			wpf[i].mV[0] = fabsf(wpf[i].mV[0]);
-			wpf[i].mV[2] = fabsf(wpf[i].mV[2]);
-		}
-
-		if (!wpf.empty())
-		{ 
-			F32 sx = 0.f;
-			F32 sx2 = 0.f;
-			F32 sy = 0.f;
-			F32 sxy = 0.f;
-			
-			for (U32 i = 0; i < wpf.size(); ++i)
-			{		
-				sx += wpf[i].mV[0];
-				sx2 += wpf[i].mV[0]*wpf[i].mV[0];
-				sy += wpf[i].mV[1];
-				sxy += wpf[i].mV[0]*wpf[i].mV[1]; 
-			}
-
-			bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2);
-			bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2);
-		}
-		
-		{
-			// best fit line is y=bfm*x+bfb
-		
-			//find point that is furthest to the right of line
-			F32 off_x = -1.f;
-			LLVector3 lp;
-
-			for (U32 i = 0; i < wpf.size(); ++i)
-			{
-				//y = bfm*x+bfb
-				//x = (y-bfb)/bfm
-				F32 lx = (wpf[i].mV[1]-bfb)/bfm;
-
-				lx = wpf[i].mV[0]-lx;
-				
-				if (off_x < lx)
-				{
-					off_x = lx;
-					lp = wpf[i];
-				}
-			}
-
-			//get line with slope bfm through lp
-			// bfb = y-bfm*x
-			bfb = lp.mV[1]-bfm*lp.mV[0];
-
-			//calculate error
-			mShadowError.mV[j] = 0.f;
-
-			for (U32 i = 0; i < wpf.size(); ++i)
-			{
-				F32 lx = (wpf[i].mV[1]-bfb)/bfm;
-				mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx);
-			}
-
-			mShadowError.mV[j] /= wpf.size();
-			mShadowError.mV[j] /= size.mV[0];
-
-			if (mShadowError.mV[j] > gSavedSettings.getF32("RenderShadowErrorCutoff"))
-			{ //just use ortho projection
-				mShadowFOV.mV[j] = -1.f;
-				origin.clearVec();
-				proj[j] = gl_ortho(min.mV[0], max.mV[0],
-									min.mV[1], max.mV[1],
-									-max.mV[2], -min.mV[2]);
-			}
-			else
-			{
-				//origin is where line x = 0;
-				origin.setVec(0,bfb,0);
-
-				F32 fovz = 1.f;
-				F32 fovx = 1.f;
-				
-				LLVector3 zp;
-				LLVector3 xp;
-
-				for (U32 i = 0; i < wpf.size(); ++i)
-				{
-					LLVector3 atz = wpf[i]-origin;
-					atz.mV[0] = 0.f;
-					atz.normVec();
-					if (fovz > -atz.mV[1])
-					{
-						zp = wpf[i];
-						fovz = -atz.mV[1];
-					}
-					
-					LLVector3 atx = wpf[i]-origin;
-					atx.mV[2] = 0.f;
-					atx.normVec();
-					if (fovx > -atx.mV[1])
-					{
-						fovx = -atx.mV[1];
-						xp = wpf[i];
-					}
-				}
-
-				fovx = acos(fovx);
-				fovz = acos(fovz);
-
-				F32 cutoff = llmin(gSavedSettings.getF32("RenderShadowFOVCutoff"), 1.4f);
-				
-				mShadowFOV.mV[j] = fovx;
-				
-				if (fovx < cutoff && fovz > cutoff)
-				{
-					//x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff
-					F32 d = zp.mV[2]/tan(cutoff);
-					F32 ny = zp.mV[1] + fabsf(d);
-
-					origin.mV[1] = ny;
-
-					fovz = 1.f;
-					fovx = 1.f;
-
-					for (U32 i = 0; i < wpf.size(); ++i)
-					{
-						LLVector3 atz = wpf[i]-origin;
-						atz.mV[0] = 0.f;
-						atz.normVec();
-						fovz = llmin(fovz, -atz.mV[1]);
-
-						LLVector3 atx = wpf[i]-origin;
-						atx.mV[2] = 0.f;
-						atx.normVec();
-						fovx = llmin(fovx, -atx.mV[1]);
-					}
-
-					fovx = acos(fovx);
-					fovz = acos(fovz);
-
-					if (fovx > cutoff || llround(fovz, 0.01f) > cutoff)
-					{
-					//	llerrs << "WTF?" << llendl;
-					}
-
-					mShadowFOV.mV[j] = cutoff;
-				}
-
-				
-				origin += center;
-			
-				F32 ynear = -(max.mV[1]-origin.mV[1]);
-				F32 yfar = -(min.mV[1]-origin.mV[1]);
-				
-				if (ynear < 0.1f) //keep a sensible near clip plane
-				{
-					F32 diff = 0.1f-ynear;
-					origin.mV[1] += diff;
-					ynear += diff;
-					yfar += diff;
-				}
-								
-				if (fovx > cutoff)
-				{ //just use ortho projection
-					origin.clearVec();
-					mShadowError.mV[j] = -1.f;
-					proj[j] = gl_ortho(min.mV[0], max.mV[0],
-							min.mV[1], max.mV[1],
-							-max.mV[2], -min.mV[2]);
-				}
-				else
-				{
-					//get perspective projection
-					view[j] = view[j].inverse();
-
-					glh::vec3f origin_agent(origin.mV);
-					
-					//translate view to origin
-					view[j].mult_matrix_vec(origin_agent);
-
-					eye = LLVector3(origin_agent.v);
-
-					if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-					{
-						mShadowFrustOrigin[j] = eye;
-					}
-				
-					view[j] = look(LLVector3(origin_agent.v), lightDir, -up);
-
-					F32 fx = 1.f/tanf(fovx);
-					F32 fz = 1.f/tanf(fovz);
-
-					proj[j] = glh::matrix4f(-fx, 0, 0, 0,
-											0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar),
-											0, 0, -fz, 0,
-											0, -1.f, 0, 0);
-				}
-			}
-		}
-
-		shadow_cam.setFar(128.f);
-		shadow_cam.setOriginAndLookAt(eye, up, center);
-
-		shadow_cam.setOrigin(0,0,0);
-
-		glh_set_current_modelview(view[j]);
-		glh_set_current_projection(proj[j]);
-
-		LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
-		shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
-
-		//translate and scale to from [-1, 1] to [0, 1]
-		glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
-						0.f, 0.5f, 0.f, 0.5f,
-						0.f, 0.f, 0.5f, 0.5f,
-						0.f, 0.f, 0.f, 1.f);
-
-		glh_set_current_modelview(view[j]);
-		glh_set_current_projection(proj[j]);
-
-		for (U32 i = 0; i < 16; i++)
-		{
-			gGLLastModelView[i] = mShadowModelview[j].m[i];
-			gGLLastProjection[i] = mShadowProjection[j].m[i];
-		}
-
-		mShadowModelview[j] = view[j];
-		mShadowProjection[j] = proj[j];
-
-	
-		mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
-		
-		stop_glerror();
-
-		mShadow[j].bindTarget();
-		mShadow[j].getViewport(gGLViewport);
-
-		{
-			static LLCullResult result[4];
-
-			//LLGLEnable enable(GL_DEPTH_CLAMP_NV);
-			renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
-		}
-
-		mShadow[j].flush();
- 
-		if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
-		{
-			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-			mShadowCamera[j+4] = shadow_cam;
-		}
-	}
-
-	
-	//hack to disable projector shadows 
-	static bool clear = true;
-	bool gen_shadow = gSavedSettings.getS32("RenderShadowDetail") > 1;
-
-	if (gen_shadow)
-	{
-		clear = true;
-	F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f);
-
-	//update shadow targets
-	for (U32 i = 0; i < 2; i++)
-	{ //for each current shadow
-		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i;
-
-		if (mShadowSpotLight[i].notNull() && 
-			(mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
-			mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
-		{ //keep this spotlight
-			mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
-		}
-		else
-		{ //fade out this light
-			mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
-			
-			if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
-			{ //faded out, grab one of the pending spots (whichever one isn't already taken)
-				if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
-				{
-					mShadowSpotLight[i] = mTargetShadowSpotLight[0];
-				}
-				else
-				{
-					mShadowSpotLight[i] = mTargetShadowSpotLight[1];
-				}
-			}
-		}
-	}
-
-	for (S32 i = 0; i < 2; i++)
-	{
-		glh_set_current_modelview(saved_view);
-		glh_set_current_projection(saved_proj);
-
-		if (mShadowSpotLight[i].isNull())
-		{
-			continue;
-		}
-
-		LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
-
-		if (!volume)
-		{
-			mShadowSpotLight[i] = NULL;
-			continue;
-		}
-
-		LLDrawable* drawable = mShadowSpotLight[i];
-
-		LLVector3 params = volume->getSpotLightParams();
-		F32 fov = params.mV[0];
-
-		//get agent->light space matrix (modelview)
-		LLVector3 center = drawable->getPositionAgent();
-		LLQuaternion quat = volume->getRenderRotation();
-
-		//get near clip plane
-		LLVector3 scale = volume->getScale();
-		LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
-		at_axis *= quat;
-
-		LLVector3 np = center+at_axis;
-		at_axis.normVec();
-
-		//get origin that has given fov for plane np, at_axis, and given scale
-		F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
-
-		LLVector3 origin = np - at_axis*dist;
-
-		LLMatrix4 mat(quat, LLVector4(origin, 1.f));
-
-		view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
-
-		view[i+4] = view[i+4].inverse();
-
-		//get perspective matrix
-		F32 near_clip = dist+0.01f;
-		F32 width = scale.mV[VX];
-		F32 height = scale.mV[VY];
-		F32 far_clip = dist+volume->getLightRadius()*1.5f;
-
-		F32 fovy = fov * RAD_TO_DEG;
-		F32 aspect = width/height;
-		
-		proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
-
-		//translate and scale to from [-1, 1] to [0, 1]
-		glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
-						0.f, 0.5f, 0.f, 0.5f,
-						0.f, 0.f, 0.5f, 0.5f,
-						0.f, 0.f, 0.f, 1.f);
-
-		glh_set_current_modelview(view[i+4]);
-		glh_set_current_projection(proj[i+4]);
-
-		mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
-		
-		for (U32 j = 0; j < 16; j++)
-		{
-			gGLLastModelView[j] = mShadowModelview[i+4].m[j];
-			gGLLastProjection[j] = mShadowProjection[i+4].m[j];
-		}
-
-		mShadowModelview[i+4] = view[i+4];
-		mShadowProjection[i+4] = proj[i+4];
-
-		LLCamera shadow_cam = camera;
-		shadow_cam.setFar(far_clip);
-		shadow_cam.setOrigin(origin);
-
-		LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
-
-		stop_glerror();
-
-		mShadow[i+4].bindTarget();
-		mShadow[i+4].getViewport(gGLViewport);
-
-		static LLCullResult result[2];
-
-		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
-
-		renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
-
-		mShadow[i+4].flush();
- 	}
-	}
-	else
-	{
-		if (clear)
-		{
-			clear = false;
-			for (U32 i = 4; i < 6; i++)
-			{
-				mShadow[i].bindTarget();
-				mShadow[i].clear();
-				mShadow[i].flush();
-			}
-		}
-	}
-
-	if (!gSavedSettings.getBOOL("CameraOffset"))
-	{
-		glh_set_current_modelview(saved_view);
-		glh_set_current_projection(saved_proj);
-	}
-	else
-	{
-		glh_set_current_modelview(view[1]);
-		glh_set_current_projection(proj[1]);
-		glLoadMatrixf(view[1].m);
-		glMatrixMode(GL_PROJECTION);
-		glLoadMatrixf(proj[1].m);
-		glMatrixMode(GL_MODELVIEW);
-	}
-	gGL.setColorMask(true, false);
-
-	for (U32 i = 0; i < 16; i++)
-	{
-		gGLLastModelView[i] = last_modelview[i];
-		gGLLastProjection[i] = last_projection[i];
-	}
-
-	popRenderTypeMask();
-}
-
-void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
-{
-	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
-	{
-		LLSpatialGroup* group = *i;
-		if (!group->isDead() &&
-			(!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
-			gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
-			group->mDrawMap.find(type) != group->mDrawMap.end())
-		{
-			pass->renderGroup(group,type,mask,texture);
-		}
-	}
-}
-
-void LLPipeline::generateImpostor(LLVOAvatar* avatar)
-{
-	LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR);
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-
-	static LLCullResult result;
-	result.clear();
-	grabReferences(result);
-	
-	if (!avatar || !avatar->mDrawable)
-	{
-		return;
-	}
-
-	assertInitialized();
-
-	BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID());
-
-	pushRenderTypeMask();
-	
-	if (muted)
-	{
-		andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
-	}
-	else
-	{
-		andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME,
-						LLPipeline::RENDER_TYPE_AVATAR,
-						LLPipeline::RENDER_TYPE_BUMP,
-						LLPipeline::RENDER_TYPE_GRASS,
-						LLPipeline::RENDER_TYPE_SIMPLE,
-						LLPipeline::RENDER_TYPE_FULLBRIGHT,
-						LLPipeline::RENDER_TYPE_ALPHA, 
-						LLPipeline::RENDER_TYPE_INVISIBLE,
-						LLPipeline::RENDER_TYPE_PASS_SIMPLE,
-						LLPipeline::RENDER_TYPE_PASS_ALPHA,
-						LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
-						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
-						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
-						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
-						LLPipeline::RENDER_TYPE_PASS_SHINY,
-						LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
-						LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
-						END_RENDER_TYPES);
-	}
-	
-	S32 occlusion = sUseOcclusion;
-	sUseOcclusion = 0;
-	sReflectionRender = sRenderDeferred ? FALSE : TRUE;
-	sShadowRender = TRUE;
-	sImpostorRender = TRUE;
-
-	LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
-	markVisible(avatar->mDrawable, *viewer_camera);
-	LLVOAvatar::sUseImpostors = FALSE;
-
-	LLVOAvatar::attachment_map_t::iterator iter;
-	for (iter = avatar->mAttachmentPoints.begin();
-		iter != avatar->mAttachmentPoints.end();
-		++iter)
-	{
-		LLViewerJointAttachment *attachment = iter->second;
-		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
-			 attachment_iter != attachment->mAttachedObjects.end();
-			 ++attachment_iter)
-		{
-			if (LLViewerObject* attached_object = (*attachment_iter))
-			{
-				markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
-			}
-		}
-	}
-
-	stateSort(*LLViewerCamera::getInstance(), result);
-	
-	const LLVector3* ext = avatar->mDrawable->getSpatialExtents();
-	LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
-
-	LLCamera camera = *viewer_camera;
-
-	camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
-	
-	LLVector2 tdim;
-
-	LLVector3 half_height = (ext[1]-ext[0])*0.5f;
-
-	LLVector3 left = camera.getLeftAxis();
-	left *= left;
-	left.normalize();
-
-	LLVector3 up = camera.getUpAxis();
-	up *= up;
-	up.normalize();
-
-	tdim.mV[0] = fabsf(half_height * left);
-	tdim.mV[1] = fabsf(half_height * up);
-
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	//glh::matrix4f ortho = gl_ortho(-tdim.mV[0], tdim.mV[0], -tdim.mV[1], tdim.mV[1], 1.0, 256.0);
-	F32 distance = (pos-camera.getOrigin()).length();
-	F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
-	F32 aspect = tdim.mV[0]/tdim.mV[1]; //128.f/256.f;
-	glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
-	glh_set_current_projection(persp);
-	glLoadMatrixf(persp.m);
-
-	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
-	glh::matrix4f mat;
-	camera.getOpenGLTransform(mat.m);
-
-	mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
-
-	glLoadMatrixf(mat.m);
-	glh_set_current_modelview(mat);
-
-	glClearColor(0.0f,0.0f,0.0f,0.0f);
-	gGL.setColorMask(true, true);
-	glStencilMask(0xFFFFFFFF);
-	glClearStencil(0);
-
-	// get the number of pixels per angle
-	F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
-
-	//get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
-	U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
-	U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
-
-	if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
-		resY != avatar->mImpostor.getHeight())
-	{
-		avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE);
-		
-		if (LLPipeline::sRenderDeferred)
-		{
-			addDeferredAttachments(avatar->mImpostor);
-		}
-		
-		gGL.getTexUnit(0)->bind(&avatar->mImpostor);
-		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-	}
-
-	LLGLEnable stencil(GL_STENCIL_TEST);
-	glStencilMask(0xFFFFFFFF);
-	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
-	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
-	{
-		LLGLEnable scissor(GL_SCISSOR_TEST);
-		glScissor(0, 0, resX, resY);
-		avatar->mImpostor.bindTarget();
-		avatar->mImpostor.clear();
-	}
-	
-	if (LLPipeline::sRenderDeferred)
-	{
-		stop_glerror();
-		renderGeomDeferred(camera);
-		renderGeomPostDeferred(camera);
-	}
-	else
-	{
-		renderGeom(camera);
-	}
-	
-	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-	glStencilFunc(GL_EQUAL, 1, 0xFFFFFF);
-
-	{ //create alpha mask based on stencil buffer (grey out if muted)
-		LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f;
-		LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f;
-
-		if (LLPipeline::sRenderDeferred)
-		{
-			GLuint buff = GL_COLOR_ATTACHMENT0_EXT;
-			glDrawBuffersARB(1, &buff);
-		}
-
-		LLGLEnable blend(muted ? 0 : GL_BLEND);
-
-		if (muted)
-		{
-			gGL.setColorMask(true, true);
-		}
-		else
-		{
-			gGL.setColorMask(false, true);
-		}
-		
-		gGL.setSceneBlendType(LLRender::BT_ADD);
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-		LLGLDepthTest depth(GL_FALSE, GL_FALSE);
-
-		gGL.color4f(1,1,1,1);
-		gGL.color4ub(64,64,64,255);
-		gGL.begin(LLRender::QUADS);
-		gGL.vertex3fv((pos+left-up).mV);
-		gGL.vertex3fv((pos-left-up).mV);
-		gGL.vertex3fv((pos-left+up).mV);
-		gGL.vertex3fv((pos+left+up).mV);
-		gGL.end();
-		gGL.flush();
-
-		gGL.setSceneBlendType(LLRender::BT_ALPHA);
-	}
-
-
-	avatar->mImpostor.flush();
-
-	avatar->setImpostorDim(tdim);
-
-	LLVOAvatar::sUseImpostors = TRUE;
-	sUseOcclusion = occlusion;
-	sReflectionRender = FALSE;
-	sImpostorRender = FALSE;
-	sShadowRender = FALSE;
-	popRenderTypeMask();
-
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-	glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-
-	avatar->mNeedsImpostorUpdate = FALSE;
-	avatar->cacheImpostorValues();
-
-	LLVertexBuffer::unbind();
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-	LLGLState::checkClientArrays();
-}
-
-BOOL LLPipeline::hasRenderBatches(const U32 type) const
-{
-	return sCull->getRenderMapSize(type) > 0;
-}
-
-LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type)
-{
-	return sCull->beginRenderMap(type);
-}
-
-LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type)
-{
-	return sCull->endRenderMap(type);
-}
-
-LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups()
-{
-	return sCull->beginAlphaGroups();
-}
-
-LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
-{
-	return sCull->endAlphaGroups();
-}
-
-BOOL LLPipeline::hasRenderType(const U32 type) const
-{
-    // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render"
-    // We then need to test that value here and return FALSE to prevent attachment to render (in mouselook for instance)
-    // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to FALSE explicitely
-	return (type == 0 ? FALSE : mRenderTypeEnabled[type]);
-}
-
-void LLPipeline::setRenderTypeMask(U32 type, ...)
-{
-	va_list args;
-
-	va_start(args, type);
-	while (type < END_RENDER_TYPES)
-	{
-		mRenderTypeEnabled[type] = TRUE;
-		type = va_arg(args, U32);
-	}
-	va_end(args);
-
-	if (type > END_RENDER_TYPES)
-	{
-		llerrs << "Invalid render type." << llendl;
-	}
-}
-
-BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const
-{
-	va_list args;
-
-	va_start(args, type);
-	while (type < END_RENDER_TYPES)
-	{
-		if (mRenderTypeEnabled[type])
-		{
-			return TRUE;
-		}
-		type = va_arg(args, U32);
-	}
-	va_end(args);
-
-	if (type > END_RENDER_TYPES)
-	{
-		llerrs << "Invalid render type." << llendl;
-	}
-
-	return FALSE;
-}
-
-void LLPipeline::pushRenderTypeMask()
-{
-	std::string cur_mask;
-	cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled));
-	mRenderTypeEnableStack.push(cur_mask);
-}
-
-void LLPipeline::popRenderTypeMask()
-{
-	if (mRenderTypeEnableStack.empty())
-	{
-		llerrs << "Depleted render type stack." << llendl;
-	}
-
-	memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled));
-	mRenderTypeEnableStack.pop();
-}
-
-void LLPipeline::andRenderTypeMask(U32 type, ...)
-{
-	va_list args;
-
-	BOOL tmp[NUM_RENDER_TYPES];
-	for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
-	{
-		tmp[i] = FALSE;
-	}
-
-	va_start(args, type);
-	while (type < END_RENDER_TYPES)
-	{
-		if (mRenderTypeEnabled[type]) 
-		{
-			tmp[type] = TRUE;
-		}
-
-		type = va_arg(args, U32);
-	}
-	va_end(args);
-
-	if (type > END_RENDER_TYPES)
-	{
-		llerrs << "Invalid render type." << llendl;
-	}
-
-	for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i)
-	{
-		mRenderTypeEnabled[i] = tmp[i];
-	}
-
-}
-
-void LLPipeline::clearRenderTypeMask(U32 type, ...)
-{
-	va_list args;
-
-	va_start(args, type);
-	while (type < END_RENDER_TYPES)
-	{
-		mRenderTypeEnabled[type] = FALSE;
-		
-		type = va_arg(args, U32);
-	}
-	va_end(args);
-
-	if (type > END_RENDER_TYPES)
-	{
-		llerrs << "Invalid render type." << llendl;
-	}
-}
-
-
+/** 
+ * @file pipeline.cpp
+ * @brief Rendering pipeline.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "pipeline.h"
+
+// library includes
+#include "llaudioengine.h" // For debugging.
+#include "imageids.h"
+#include "llerror.h"
+#include "llviewercontrol.h"
+#include "llfasttimer.h"
+#include "llfontgl.h"
+#include "llmemtype.h"
+#include "llnamevalue.h"
+#include "llpointer.h"
+#include "llprimitive.h"
+#include "llvolume.h"
+#include "material_codes.h"
+#include "timing.h"
+#include "v3color.h"
+#include "llui.h" 
+#include "llglheaders.h"
+#include "llrender.h"
+#include "llwindow.h"	// swapBuffers()
+
+// newview includes
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "lldrawable.h"
+#include "lldrawpoolalpha.h"
+#include "lldrawpoolavatar.h"
+#include "lldrawpoolground.h"
+#include "lldrawpoolbump.h"
+#include "lldrawpooltree.h"
+#include "lldrawpoolwater.h"
+#include "llface.h"
+#include "llfeaturemanager.h"
+#include "llfloatertelehub.h"
+#include "llfloaterreg.h"
+#include "llgldbg.h"
+#include "llhudmanager.h"
+#include "llhudnametag.h"
+#include "llhudtext.h"
+#include "lllightconstants.h"
+#include "llresmgr.h"
+#include "llselectmgr.h"
+#include "llsky.h"
+#include "lltracker.h"
+#include "lltool.h"
+#include "lltoolmgr.h"
+#include "llviewercamera.h"
+#include "llviewertexturelist.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h" // for audio debugging.
+#include "llviewerwindow.h" // For getSpinAxis
+#include "llvoavatarself.h"
+#include "llvoground.h"
+#include "llvosky.h"
+#include "llvotree.h"
+#include "llvovolume.h"
+#include "llvosurfacepatch.h"
+#include "llvowater.h"
+#include "llvotree.h"
+#include "llvopartgroup.h"
+#include "llworld.h"
+#include "llcubemap.h"
+#include "llviewershadermgr.h"
+#include "llviewerstats.h"
+#include "llviewerjoystick.h"
+#include "llviewerdisplay.h"
+#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
+#include "llspatialpartition.h"
+#include "llmutelist.h"
+#include "lltoolpie.h"
+
+
+#ifdef _DEBUG
+// Debug indices is disabled for now for debug performance - djs 4/24/02
+//#define DEBUG_INDICES
+#else
+//#define DEBUG_INDICES
+#endif
+
+const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f;
+const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f;
+const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
+const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
+const S32 MAX_OFFSCREEN_GEOMETRY_CHANGES_PER_FRAME = 10;
+const U32 REFLECTION_MAP_RES = 128;
+
+// Max number of occluders to search for. JC
+const S32 MAX_OCCLUDER_COUNT = 2;
+
+extern S32 gBoxFrame;
+//extern BOOL gHideSelectedObjects;
+extern BOOL gDisplaySwapBuffers;
+extern BOOL gDebugGL;
+
+// hack counter for rendering a fixed number of frames after toggling
+// fullscreen to work around DEV-5361
+static S32 sDelayedVBOEnable = 0;
+
+BOOL	gAvatarBacklight = FALSE;
+
+BOOL	gDebugPipeline = FALSE;
+LLPipeline gPipeline;
+const LLMatrix4* gGLLastMatrix = NULL;
+
+LLFastTimer::DeclareTimer FTM_RENDER_GEOMETRY("Geometry");
+LLFastTimer::DeclareTimer FTM_RENDER_GRASS("Grass");
+LLFastTimer::DeclareTimer FTM_RENDER_INVISIBLE("Invisible");
+LLFastTimer::DeclareTimer FTM_RENDER_OCCLUSION("Occlusion");
+LLFastTimer::DeclareTimer FTM_RENDER_SHINY("Shiny");
+LLFastTimer::DeclareTimer FTM_RENDER_SIMPLE("Simple");
+LLFastTimer::DeclareTimer FTM_RENDER_TERRAIN("Terrain");
+LLFastTimer::DeclareTimer FTM_RENDER_TREES("Trees");
+LLFastTimer::DeclareTimer FTM_RENDER_UI("UI");
+LLFastTimer::DeclareTimer FTM_RENDER_WATER("Water");
+LLFastTimer::DeclareTimer FTM_RENDER_WL_SKY("Windlight Sky");
+LLFastTimer::DeclareTimer FTM_RENDER_ALPHA("Alpha Objects");
+LLFastTimer::DeclareTimer FTM_RENDER_CHARACTERS("Avatars");
+LLFastTimer::DeclareTimer FTM_RENDER_BUMP("Bump");
+LLFastTimer::DeclareTimer FTM_RENDER_FULLBRIGHT("Fullbright");
+LLFastTimer::DeclareTimer FTM_RENDER_GLOW("Glow");
+LLFastTimer::DeclareTimer FTM_GEO_UPDATE("Geo Update");
+LLFastTimer::DeclareTimer FTM_POOLRENDER("RenderPool");
+LLFastTimer::DeclareTimer FTM_POOLS("Pools");
+LLFastTimer::DeclareTimer FTM_RENDER_BLOOM_FBO("First FBO");
+LLFastTimer::DeclareTimer FTM_STATESORT("Sort Draw State");
+LLFastTimer::DeclareTimer FTM_PIPELINE("Pipeline");
+LLFastTimer::DeclareTimer FTM_CLIENT_COPY("Client Copy");
+LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
+
+
+static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
+static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
+
+//----------------------------------------
+std::string gPoolNames[] = 
+{
+	// Correspond to LLDrawpool enum render type
+	"NONE",
+	"POOL_SIMPLE",
+	"POOL_TERRAIN",
+	"POOL_BUMP",
+	"POOL_TREE",
+	"POOL_SKY",
+	"POOL_WL_SKY",
+	"POOL_GROUND",
+	"POOL_INVISIBLE",
+	"POOL_AVATAR",
+	"POOL_WATER",
+	"POOL_GRASS",
+	"POOL_FULLBRIGHT",
+	"POOL_GLOW",
+	"POOL_ALPHA",
+};
+
+void drawBox(const LLVector3& c, const LLVector3& r);
+void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
+
+U32 nhpo2(U32 v) 
+{
+	U32 r = 1;
+	while (r < v) {
+		r *= 2;
+	}
+	return r;
+}
+
+glh::matrix4f glh_copy_matrix(GLdouble* src)
+{
+	glh::matrix4f ret;
+	for (U32 i = 0; i < 16; i++)
+	{
+		ret.m[i] = (F32) src[i];
+	}
+	return ret;
+}
+
+glh::matrix4f glh_get_current_modelview()
+{
+	return glh_copy_matrix(gGLModelView);
+}
+
+glh::matrix4f glh_get_current_projection()
+{
+	return glh_copy_matrix(gGLProjection);
+}
+
+void glh_copy_matrix(const glh::matrix4f& src, GLdouble* dst)
+{
+	for (U32 i = 0; i < 16; i++)
+	{
+		dst[i] = src.m[i];
+	}
+}
+
+void glh_set_current_modelview(const glh::matrix4f& mat)
+{
+	glh_copy_matrix(mat, gGLModelView);
+}
+
+void glh_set_current_projection(glh::matrix4f& mat)
+{
+	glh_copy_matrix(mat, gGLProjection);
+}
+
+glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
+{
+	glh::matrix4f ret(
+		2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
+		0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
+		0.f, 0.f, -2.f/(zfar-znear),  -(zfar+znear)/(zfar-znear),
+		0.f, 0.f, 0.f, 1.f);
+
+	return ret;
+}
+
+void display_update_camera();
+//----------------------------------------
+
+S32		LLPipeline::sCompiles = 0;
+
+BOOL	LLPipeline::sPickAvatar = TRUE;
+BOOL	LLPipeline::sDynamicLOD = TRUE;
+BOOL	LLPipeline::sShowHUDAttachments = TRUE;
+BOOL	LLPipeline::sRenderPhysicalBeacons = TRUE;
+BOOL	LLPipeline::sRenderScriptedBeacons = FALSE;
+BOOL	LLPipeline::sRenderScriptedTouchBeacons = TRUE;
+BOOL	LLPipeline::sRenderParticleBeacons = FALSE;
+BOOL	LLPipeline::sRenderSoundBeacons = FALSE;
+BOOL	LLPipeline::sRenderBeacons = FALSE;
+BOOL	LLPipeline::sRenderHighlight = TRUE;
+BOOL	LLPipeline::sForceOldBakedUpload = FALSE;
+S32		LLPipeline::sUseOcclusion = 0;
+BOOL	LLPipeline::sDelayVBUpdate = TRUE;
+BOOL	LLPipeline::sAutoMaskAlphaDeferred = TRUE;
+BOOL	LLPipeline::sAutoMaskAlphaNonDeferred = FALSE;
+BOOL	LLPipeline::sDisableShaders = FALSE;
+BOOL	LLPipeline::sRenderBump = TRUE;
+BOOL	LLPipeline::sUseTriStrips = TRUE;
+BOOL	LLPipeline::sUseFarClip = TRUE;
+BOOL	LLPipeline::sShadowRender = FALSE;
+BOOL	LLPipeline::sWaterReflections = FALSE;
+BOOL	LLPipeline::sRenderGlow = FALSE;
+BOOL	LLPipeline::sReflectionRender = FALSE;
+BOOL	LLPipeline::sImpostorRender = FALSE;
+BOOL	LLPipeline::sUnderWaterRender = FALSE;
+BOOL	LLPipeline::sTextureBindTest = FALSE;
+BOOL	LLPipeline::sRenderFrameTest = FALSE;
+BOOL	LLPipeline::sRenderAttachedLights = TRUE;
+BOOL	LLPipeline::sRenderAttachedParticles = TRUE;
+BOOL	LLPipeline::sRenderDeferred = FALSE;
+BOOL    LLPipeline::sAllowRebuildPriorityGroup = FALSE ;
+S32		LLPipeline::sVisibleLightCount = 0;
+F32		LLPipeline::sMinRenderSize = 0.f;
+
+
+static LLCullResult* sCull = NULL;
+
+static const U32 gl_cube_face[] = 
+{
+	GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+	GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
+};
+
+void validate_framebuffer_object();
+
+
+void addDeferredAttachments(LLRenderTarget& target)
+{
+	target.addColorAttachment(GL_RGBA); //specular
+	target.addColorAttachment(GL_RGBA); //normal+z	
+}
+
+LLPipeline::LLPipeline() :
+	mBackfaceCull(FALSE),
+	mBatchCount(0),
+	mMatrixOpCount(0),
+	mTextureMatrixOps(0),
+	mMaxBatchSize(0),
+	mMinBatchSize(0),
+	mMeanBatchSize(0),
+	mTrianglesDrawn(0),
+	mNumVisibleNodes(0),
+	mVerticesRelit(0),
+	mLightingChanges(0),
+	mGeometryChanges(0),
+	mNumVisibleFaces(0),
+
+	mInitialized(FALSE),
+	mVertexShadersEnabled(FALSE),
+	mVertexShadersLoaded(0),
+	mRenderDebugFeatureMask(0),
+	mRenderDebugMask(0),
+	mOldRenderDebugMask(0),
+	mLastRebuildPool(NULL),
+	mAlphaPool(NULL),
+	mSkyPool(NULL),
+	mTerrainPool(NULL),
+	mWaterPool(NULL),
+	mGroundPool(NULL),
+	mSimplePool(NULL),
+	mFullbrightPool(NULL),
+	mInvisiblePool(NULL),
+	mGlowPool(NULL),
+	mBumpPool(NULL),
+	mWLSkyPool(NULL),
+	mLightMask(0),
+	mLightMovingMask(0),
+	mLightingDetail(0),
+	mScreenWidth(0),
+	mScreenHeight(0)
+{
+	mNoiseMap = 0;
+	mTrueNoiseMap = 0;
+	mLightFunc = 0;
+}
+
+void LLPipeline::init()
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_INIT);
+
+	sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
+	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
+	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
+	sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
+	sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles");
+
+	mInitialized = TRUE;
+	
+	stop_glerror();
+
+	//create render pass pools
+	getPool(LLDrawPool::POOL_ALPHA);
+	getPool(LLDrawPool::POOL_SIMPLE);
+	getPool(LLDrawPool::POOL_GRASS);
+	getPool(LLDrawPool::POOL_FULLBRIGHT);
+	getPool(LLDrawPool::POOL_INVISIBLE);
+	getPool(LLDrawPool::POOL_BUMP);
+	getPool(LLDrawPool::POOL_GLOW);
+
+	LLViewerStats::getInstance()->mTrianglesDrawnStat.reset();
+	resetFrameStats();
+
+	for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
+	{
+		mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled
+	}
+
+	mRenderDebugFeatureMask = 0xffffffff; // All debugging features on
+	mRenderDebugMask = 0;	// All debug starts off
+
+	// Don't turn on ground when this is set
+	// Mac Books with intel 950s need this
+	if(!gSavedSettings.getBOOL("RenderGround"))
+	{
+		toggleRenderType(RENDER_TYPE_GROUND);
+	}
+
+	mOldRenderDebugMask = mRenderDebugMask;
+
+	mBackfaceCull = TRUE;
+
+	stop_glerror();
+	
+	// Enable features
+		
+	LLViewerShaderMgr::instance()->setShaders();
+
+	stop_glerror();
+
+	for (U32 i = 0; i < 2; ++i)
+	{
+		mSpotLightFade[i] = 1.f;
+	}
+
+	setLightingDetail(-1);
+}
+
+LLPipeline::~LLPipeline()
+{
+
+}
+
+void LLPipeline::cleanup()
+{
+	assertInitialized();
+
+	mGroupQ1.clear() ;
+	mGroupQ2.clear() ;
+
+	for(pool_set_t::iterator iter = mPools.begin();
+		iter != mPools.end(); )
+	{
+		pool_set_t::iterator curiter = iter++;
+		LLDrawPool* poolp = *curiter;
+		if (poolp->isFacePool())
+		{
+			LLFacePool* face_pool = (LLFacePool*) poolp;
+			if (face_pool->mReferences.empty())
+			{
+				mPools.erase(curiter);
+				removeFromQuickLookup( poolp );
+				delete poolp;
+			}
+		}
+		else
+		{
+			mPools.erase(curiter);
+			removeFromQuickLookup( poolp );
+			delete poolp;
+		}
+	}
+	
+	if (!mTerrainPools.empty())
+	{
+		llwarns << "Terrain Pools not cleaned up" << llendl;
+	}
+	if (!mTreePools.empty())
+	{
+		llwarns << "Tree Pools not cleaned up" << llendl;
+	}
+		
+	delete mAlphaPool;
+	mAlphaPool = NULL;
+	delete mSkyPool;
+	mSkyPool = NULL;
+	delete mTerrainPool;
+	mTerrainPool = NULL;
+	delete mWaterPool;
+	mWaterPool = NULL;
+	delete mGroundPool;
+	mGroundPool = NULL;
+	delete mSimplePool;
+	mSimplePool = NULL;
+	delete mFullbrightPool;
+	mFullbrightPool = NULL;
+	delete mInvisiblePool;
+	mInvisiblePool = NULL;
+	delete mGlowPool;
+	mGlowPool = NULL;
+	delete mBumpPool;
+	mBumpPool = NULL;
+	// don't delete wl sky pool it was handled above in the for loop
+	//delete mWLSkyPool;
+	mWLSkyPool = NULL;
+
+	releaseGLBuffers();
+
+	mFaceSelectImagep = NULL;
+
+	mMovedBridge.clear();
+
+	mInitialized = FALSE;
+}
+
+//============================================================================
+
+void LLPipeline::destroyGL() 
+{
+	stop_glerror();
+	unloadShaders();
+	mHighlightFaces.clear();
+	
+	resetDrawOrders();
+
+	resetVertexBuffers();
+
+	releaseGLBuffers();
+
+	if (LLVertexBuffer::sEnableVBOs)
+	{
+		// render 30 frames after switching to work around DEV-5361
+		sDelayedVBOEnable = 30;
+		LLVertexBuffer::sEnableVBOs = FALSE;
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
+
+void LLPipeline::resizeScreenTexture()
+{
+	LLFastTimer ft(FTM_RESIZE_SCREEN_TEXTURE);
+	if (gPipeline.canUseVertexShaders() && assertInitialized())
+	{
+		GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+		GLuint resY = gViewerWindow->getWorldViewHeightRaw();
+	
+		allocateScreenBuffer(resX,resY);
+	}
+}
+
+void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
+{
+	// remember these dimensions
+	mScreenWidth = resX;
+	mScreenHeight = resY;
+	
+	//never use more than 4 samples for render targets
+	U32 samples = llmin(gSavedSettings.getU32("RenderFSAASamples"), (U32) 4);
+	U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
+
+	if (res_mod > 1 && res_mod < resX && res_mod < resY)
+	{
+		resX /= res_mod;
+		resY /= res_mod;
+	}
+
+	if (gSavedSettings.getBOOL("RenderUIBuffer"))
+	{
+		mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+	}	
+
+	if (LLPipeline::sRenderDeferred)
+	{
+		//allocate deferred rendering color buffers
+		mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+		mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+		addDeferredAttachments(mDeferredScreen);
+	
+		mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);		
+		mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+
+		for (U32 i = 0; i < 3; i++)
+		{
+			mDeferredLight[i].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+		}
+
+		for (U32 i = 0; i < 2; i++)
+		{
+			mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+		}
+
+		F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale");
+
+		//HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug)
+		U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0;
+
+		for (U32 i = 0; i < 4; i++)
+		{
+			mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+		}
+
+
+		U32 width = nhpo2(U32(resX*scale))/2;
+		U32 height = width;
+
+		for (U32 i = 4; i < 6; i++)
+		{
+			mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE);
+		}
+
+		width = nhpo2(resX)/2;
+		height = nhpo2(resY)/2;
+		mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE);
+	}
+	else
+	{
+		mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);		
+	}
+	
+
+	if (LLRenderTarget::sUseFBO && gGLManager.mHasFramebufferMultisample && samples > 1)
+	{
+		mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
+		if (LLPipeline::sRenderDeferred)
+		{
+			addDeferredAttachments(mSampleBuffer);
+			mDeferredScreen.setSampleBuffer(&mSampleBuffer);
+		}
+
+		mScreen.setSampleBuffer(&mSampleBuffer);
+
+		stop_glerror();
+	}
+	
+	if (LLPipeline::sRenderDeferred)
+	{ //share depth buffer between deferred targets
+		mDeferredScreen.shareDepthBuffer(mScreen);
+		for (U32 i = 0; i < 3; i++)
+		{ //share stencil buffer with screen space lightmap to stencil out sky
+			mDeferredScreen.shareDepthBuffer(mDeferredLight[i]);
+		}
+	}
+
+	gGL.getTexUnit(0)->disable();
+
+	stop_glerror();
+
+}
+
+//static
+void LLPipeline::updateRenderDeferred()
+{
+	BOOL deferred = ((gSavedSettings.getBOOL("RenderDeferred") && 
+					 LLRenderTarget::sUseFBO &&
+					 LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
+					 gSavedSettings.getBOOL("VertexShaderEnable") && 
+					 gSavedSettings.getBOOL("RenderAvatarVP") &&
+					 gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) &&
+					!gUseWireframe;
+
+	sRenderDeferred = deferred;			
+}
+
+void LLPipeline::releaseGLBuffers()
+{
+	assertInitialized();
+	
+	if (mNoiseMap)
+	{
+		LLImageGL::deleteTextures(1, &mNoiseMap);
+		mNoiseMap = 0;
+	}
+
+	if (mTrueNoiseMap)
+	{
+		LLImageGL::deleteTextures(1, &mTrueNoiseMap);
+		mTrueNoiseMap = 0;
+	}
+
+	if (mLightFunc)
+	{
+		LLImageGL::deleteTextures(1, &mLightFunc);
+		mLightFunc = 0;
+	}
+
+	mWaterRef.release();
+	mWaterDis.release();
+	mScreen.release();
+	mUIScreen.release();
+	mSampleBuffer.releaseSampleBuffer();
+	mDeferredScreen.release();
+	mDeferredDepth.release();
+	for (U32 i = 0; i < 3; i++)
+	{
+		mDeferredLight[i].release();
+	}
+
+	mEdgeMap.release();
+	mGIMap.release();
+	mGIMapPost[0].release();
+	mGIMapPost[1].release();
+	mHighlight.release();
+	mLuminanceMap.release();
+	
+	for (U32 i = 0; i < 6; i++)
+	{
+		mShadow[i].release();
+	}
+
+	for (U32 i = 0; i < 3; i++)
+	{
+		mGlow[i].release();
+	}
+
+	LLVOAvatar::resetImpostors();
+}
+
+void LLPipeline::createGLBuffers()
+{
+	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS);
+	assertInitialized();
+
+	updateRenderDeferred();
+
+	if (LLPipeline::sWaterReflections)
+	{ //water reflection texture
+		U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
+			
+		mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
+		mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
+	}
+
+	mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
+
+	stop_glerror();
+
+	GLuint resX = gViewerWindow->getWorldViewWidthRaw();
+	GLuint resY = gViewerWindow->getWorldViewHeightRaw();
+	
+	if (LLPipeline::sRenderGlow)
+	{ //screen space glow buffers
+		const U32 glow_res = llmax(1, 
+			llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
+
+		for (U32 i = 0; i < 3; i++)
+		{
+			mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
+		}
+
+		allocateScreenBuffer(resX,resY);
+		mScreenWidth = 0;
+		mScreenHeight = 0;
+
+	}
+	
+	if (sRenderDeferred)
+	{
+		if (!mNoiseMap)
+		{
+			const U32 noiseRes = 128;
+			LLVector3 noise[noiseRes*noiseRes];
+
+			F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f;
+			for (U32 i = 0; i < noiseRes*noiseRes; ++i)
+			{
+				noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f);
+				noise[i].normVec();
+				noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;
+			}
+
+			LLImageGL::generateTextures(1, &mNoiseMap);
+			
+			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
+			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+		}
+
+		if (!mTrueNoiseMap)
+		{
+			const U32 noiseRes = 128;
+			F32 noise[noiseRes*noiseRes*3];
+			for (U32 i = 0; i < noiseRes*noiseRes*3; i++)
+			{
+				noise[i] = ll_frand()*2.0-1.0;
+			}
+
+			LLImageGL::generateTextures(1, &mTrueNoiseMap);
+			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap);
+			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise);
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+		}
+
+		if (!mLightFunc)
+		{
+			U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
+			U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
+			U8* lg = new U8[lightResX*lightResY];
+
+			for (U32 y = 0; y < lightResY; ++y)
+			{
+				for (U32 x = 0; x < lightResX; ++x)
+				{
+					//spec func
+					F32 sa = (F32) x/(lightResX-1);
+					F32 spec = (F32) y/(lightResY-1);
+					//lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255);
+
+					//F32 sp = acosf(sa)/(1.f-spec);
+
+					sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent"));
+					F32 a = acosf(sa*0.25f+0.75f);
+					F32 m = llmax(0.5f-spec*0.5f, 0.001f);
+					F32 t2 = tanf(a)/m;
+					t2 *= t2;
+
+					F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f;
+					F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2);
+
+					lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255);
+				}
+			}
+
+			LLImageGL::generateTextures(1, &mLightFunc);
+			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_ALPHA, lightResX, lightResY, GL_ALPHA, GL_UNSIGNED_BYTE, lg);
+			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+
+			delete [] lg;
+		}
+
+		if (gSavedSettings.getBOOL("RenderDeferredGI"))
+		{
+			mGIMap.allocate(512,512,GL_RGBA, TRUE, FALSE);
+			addDeferredAttachments(mGIMap);
+		}
+	}
+}
+
+void LLPipeline::restoreGL() 
+{
+	LLMemType mt_cb(LLMemType::MTYPE_PIPELINE_RESTORE_GL);
+	assertInitialized();
+
+	if (mVertexShadersEnabled)
+	{
+		LLViewerShaderMgr::instance()->setShaders();
+	}
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				part->restoreGL();
+			}
+		}
+	}
+}
+
+
+BOOL LLPipeline::canUseVertexShaders()
+{
+	if (sDisableShaders ||
+		!gGLManager.mHasVertexShader ||
+		!gGLManager.mHasFragmentShader ||
+		!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") ||
+		(assertInitialized() && mVertexShadersLoaded != 1) )
+	{
+		return FALSE;
+	}
+	else
+	{
+		return TRUE;
+	}
+}
+
+BOOL LLPipeline::canUseWindLightShaders() const
+{
+	return (!LLPipeline::sDisableShaders &&
+			gWLSkyProgram.mProgramObject != 0 &&
+			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
+}
+
+BOOL LLPipeline::canUseWindLightShadersOnObjects() const
+{
+	return (canUseWindLightShaders() 
+		&& LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
+}
+
+BOOL LLPipeline::canUseAntiAliasing() const
+{
+	return TRUE; //(gSavedSettings.getBOOL("RenderUseFBO"));
+}
+
+void LLPipeline::unloadShaders()
+{
+	LLMemType mt_us(LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS);
+	LLViewerShaderMgr::instance()->unloadShaders();
+
+	mVertexShadersLoaded = 0;
+}
+
+void LLPipeline::assertInitializedDoError()
+{
+	llerrs << "LLPipeline used when uninitialized." << llendl;
+}
+
+//============================================================================
+
+void LLPipeline::enableShadows(const BOOL enable_shadows)
+{
+	//should probably do something here to wrangle shadows....	
+}
+
+S32 LLPipeline::getMaxLightingDetail() const
+{
+	/*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
+	{
+		return 3;
+	}
+	else*/
+	{
+		return 1;
+	}
+}
+
+S32 LLPipeline::setLightingDetail(S32 level)
+{
+	LLMemType mt_ld(LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL);
+	assertInitialized();
+
+	if (level < 0)
+	{
+		if (gSavedSettings.getBOOL("VertexShaderEnable"))
+		{
+			level = 1;
+		}
+		else
+		{
+			level = 0;
+		}
+	}
+	level = llclamp(level, 0, getMaxLightingDetail());
+	if (level != mLightingDetail)
+	{
+		mLightingDetail = level;
+
+		if (mVertexShadersLoaded == 1)
+		{
+			LLViewerShaderMgr::instance()->setShaders();
+		}
+	}
+	return mLightingDetail;
+}
+
+class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
+{
+public:
+	const std::set<LLViewerFetchedTexture*>& mTextures;
+
+	LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { }
+
+	virtual void visit(const LLOctreeNode<LLDrawable>* node)
+	{
+		LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+
+		if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty())
+		{
+			for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
+			{
+				for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) 
+				{
+					LLDrawInfo* params = *j;
+					LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture);
+					if (tex && mTextures.find(tex) != mTextures.end())
+					{ 
+						group->setState(LLSpatialGroup::GEOM_DIRTY);
+					}
+				}
+			}
+		}
+
+		for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
+		{
+			LLSpatialBridge* bridge = *i;
+			traverse(bridge->mOctree);
+		}
+	}
+};
+
+// Called when a texture changes # of channels (causes faces to move to alpha pool)
+void LLPipeline::dirtyPoolObjectTextures(const std::set<LLViewerFetchedTexture*>& textures)
+{
+	assertInitialized();
+
+	// *TODO: This is inefficient and causes frame spikes; need a better way to do this
+	//        Most of the time is spent in dirty.traverse.
+
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		if (poolp->isFacePool())
+		{
+			((LLFacePool*) poolp)->dirtyTextures(textures);
+		}
+	}
+	
+	LLOctreeDirtyTexture dirty(textures);
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				dirty.traverse(part->mOctree);
+			}
+		}
+	}
+}
+
+LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
+{
+	assertInitialized();
+
+	LLDrawPool *poolp = NULL;
+	switch( type )
+	{
+	case LLDrawPool::POOL_SIMPLE:
+		poolp = mSimplePool;
+		break;
+
+	case LLDrawPool::POOL_GRASS:
+		poolp = mGrassPool;
+		break;
+
+	case LLDrawPool::POOL_FULLBRIGHT:
+		poolp = mFullbrightPool;
+		break;
+
+	case LLDrawPool::POOL_INVISIBLE:
+		poolp = mInvisiblePool;
+		break;
+
+	case LLDrawPool::POOL_GLOW:
+		poolp = mGlowPool;
+		break;
+
+	case LLDrawPool::POOL_TREE:
+		poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 );
+		break;
+
+	case LLDrawPool::POOL_TERRAIN:
+		poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 );
+		break;
+
+	case LLDrawPool::POOL_BUMP:
+		poolp = mBumpPool;
+		break;
+
+	case LLDrawPool::POOL_ALPHA:
+		poolp = mAlphaPool;
+		break;
+
+	case LLDrawPool::POOL_AVATAR:
+		break; // Do nothing
+
+	case LLDrawPool::POOL_SKY:
+		poolp = mSkyPool;
+		break;
+
+	case LLDrawPool::POOL_WATER:
+		poolp = mWaterPool;
+		break;
+
+	case LLDrawPool::POOL_GROUND:
+		poolp = mGroundPool;
+		break;
+
+	case LLDrawPool::POOL_WL_SKY:
+		poolp = mWLSkyPool;
+		break;
+
+	default:
+		llassert(0);
+		llerrs << "Invalid Pool Type in  LLPipeline::findPool() type=" << type << llendl;
+		break;
+	}
+
+	return poolp;
+}
+
+
+LLDrawPool *LLPipeline::getPool(const U32 type,	LLViewerTexture *tex0)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	LLDrawPool *poolp = findPool(type, tex0);
+	if (poolp)
+	{
+		return poolp;
+	}
+
+	LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0);
+	addPool( new_poolp );
+
+	return new_poolp;
+}
+
+
+// static
+LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	U32 type = getPoolTypeFromTE(te, imagep);
+	return gPipeline.getPool(type, imagep);
+}
+
+//static 
+U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep)
+{
+	LLMemType mt_gpt(LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE);
+	
+	if (!te || !imagep)
+	{
+		return 0;
+	}
+		
+	bool alpha = te->getColor().mV[3] < 0.999f;
+	if (imagep)
+	{
+		alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2);
+	}
+
+	if (alpha)
+	{
+		return LLDrawPool::POOL_ALPHA;
+	}
+	else if ((te->getBumpmap() || te->getShiny()))
+	{
+		return LLDrawPool::POOL_BUMP;
+	}
+	else
+	{
+		return LLDrawPool::POOL_SIMPLE;
+	}
+}
+
+
+void LLPipeline::addPool(LLDrawPool *new_poolp)
+{
+	LLMemType mt_a(LLMemType::MTYPE_PIPELINE_ADD_POOL);
+	assertInitialized();
+	mPools.insert(new_poolp);
+	addToQuickLookup( new_poolp );
+}
+
+void LLPipeline::allocDrawable(LLViewerObject *vobj)
+{
+	LLMemType mt_ad(LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE);
+	LLDrawable *drawable = new LLDrawable();
+	vobj->mDrawable = drawable;
+	
+	drawable->mVObjp     = vobj;
+	
+	//encompass completely sheared objects by taking 
+	//the most extreme point possible (<1,1,0.5>)
+	drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length());
+	if (vobj->isOrphaned())
+	{
+		drawable->setState(LLDrawable::FORCE_INVISIBLE);
+	}
+	drawable->updateXform(TRUE);
+}
+
+
+void LLPipeline::unlinkDrawable(LLDrawable *drawable)
+{
+	LLFastTimer t(FTM_PIPELINE);
+
+	assertInitialized();
+
+	LLPointer<LLDrawable> drawablep = drawable; // make sure this doesn't get deleted before we are done
+	
+	// Based on flags, remove the drawable from the queues that it's on.
+	if (drawablep->isState(LLDrawable::ON_MOVE_LIST))
+	{
+		LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep);
+		if (iter != mMovedList.end())
+		{
+			mMovedList.erase(iter);
+		}
+	}
+
+	if (drawablep->getSpatialGroup())
+	{
+		if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup()))
+		{
+#ifdef LL_RELEASE_FOR_DOWNLOAD
+			llwarns << "Couldn't remove object from spatial group!" << llendl;
+#else
+			llerrs << "Couldn't remove object from spatial group!" << llendl;
+#endif
+		}
+	}
+
+	mLights.erase(drawablep);
+	for (light_set_t::iterator iter = mNearbyLights.begin();
+				iter != mNearbyLights.end(); iter++)
+	{
+		if (iter->drawable == drawablep)
+		{
+			mNearbyLights.erase(iter);
+			break;
+		}
+	}
+
+	{
+		HighlightItem item(drawablep);
+		mHighlightSet.erase(item);
+
+		if (mHighlightObject == drawablep)
+		{
+			mHighlightObject = NULL;
+		}
+	}
+
+	for (U32 i = 0; i < 2; ++i)
+	{
+		if (mShadowSpotLight[i] == drawablep)
+		{
+			mShadowSpotLight[i] = NULL;
+		}
+
+		if (mTargetShadowSpotLight[i] == drawablep)
+		{
+			mTargetShadowSpotLight[i] = NULL;
+		}
+	}
+
+
+}
+
+U32 LLPipeline::addObject(LLViewerObject *vobj)
+{
+	LLMemType mt_ao(LLMemType::MTYPE_PIPELINE_ADD_OBJECT);
+	if (gNoRender)
+	{
+		return 0;
+	}
+
+	if (gSavedSettings.getBOOL("RenderDelayCreation"))
+	{
+		mCreateQ.push_back(vobj);
+	}
+	else
+	{
+		createObject(vobj);
+	}
+
+	return 1;
+}
+
+void LLPipeline::createObjects(F32 max_dtime)
+{
+	LLFastTimer ftm(FTM_GEO_UPDATE);
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS);
+
+	LLTimer update_timer;
+
+	while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime)
+	{
+		LLViewerObject* vobj = mCreateQ.front();
+		if (!vobj->isDead())
+		{
+			createObject(vobj);
+		}
+		mCreateQ.pop_front();
+	}
+	
+	//for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter)
+	//{
+	//	createObject(*iter);
+	//}
+
+	//mCreateQ.clear();
+}
+
+void LLPipeline::createObject(LLViewerObject* vobj)
+{
+	LLDrawable* drawablep = vobj->mDrawable;
+
+	if (!drawablep)
+	{
+		drawablep = vobj->createDrawable(this);
+	}
+	else
+	{
+		llerrs << "Redundant drawable creation!" << llendl;
+	}
+		
+	llassert(drawablep);
+
+	if (vobj->getParent())
+	{
+		vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1
+	}
+	else
+	{
+		vobj->setDrawableParent(NULL); // LLPipeline::addObject 2
+	}
+
+	markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
+
+	if (drawablep->getVOVolume() && gSavedSettings.getBOOL("RenderAnimateRes"))
+	{
+		// fun animated res
+		drawablep->updateXform(TRUE);
+		drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
+		drawablep->setScale(LLVector3(0,0,0));
+		drawablep->makeActive();
+	}
+}
+
+
+void LLPipeline::resetFrameStats()
+{
+	assertInitialized();
+
+	LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f);
+
+	if (mBatchCount > 0)
+	{
+		mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount;
+	}
+	mTrianglesDrawn = 0;
+	sCompiles        = 0;
+	mVerticesRelit   = 0;
+	mLightingChanges = 0;
+	mGeometryChanges = 0;
+	mNumVisibleFaces = 0;
+
+	if (mOldRenderDebugMask != mRenderDebugMask)
+	{
+		gObjectList.clearDebugText();
+		mOldRenderDebugMask = mRenderDebugMask;
+	}
+		
+}
+
+//external functions for asynchronous updating
+void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep)
+{
+	if (gSavedSettings.getBOOL("FreezeTime"))
+	{
+		return;
+	}
+	if (!drawablep)
+	{
+		llerrs << "updateMove called with NULL drawablep" << llendl;
+		return;
+	}
+	if (drawablep->isState(LLDrawable::EARLY_MOVE))
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	// update drawable now
+	drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED
+	drawablep->updateMove(); // returns done
+	drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
+	// Put on move list so that EARLY_MOVE gets cleared
+	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+	{
+		mMovedList.push_back(drawablep);
+		drawablep->setState(LLDrawable::ON_MOVE_LIST);
+	}
+}
+
+void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep)
+{
+	if (gSavedSettings.getBOOL("FreezeTime"))
+	{
+		return;
+	}
+	if (!drawablep)
+	{
+		llerrs << "updateMove called with NULL drawablep" << llendl;
+		return;
+	}
+	if (drawablep->isState(LLDrawable::EARLY_MOVE))
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	// update drawable now
+	drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED
+	drawablep->updateMove();
+	drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame
+	// Put on move list so that EARLY_MOVE gets cleared
+	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+	{
+		mMovedList.push_back(drawablep);
+		drawablep->setState(LLDrawable::ON_MOVE_LIST);
+	}
+}
+
+void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
+{
+	for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin();
+		 iter != moved_list.end(); )
+	{
+		LLDrawable::drawable_vector_t::iterator curiter = iter++;
+		LLDrawable *drawablep = *curiter;
+		BOOL done = TRUE;
+		if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE)))
+		{
+			done = drawablep->updateMove();
+		}
+		drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
+		if (done)
+		{
+			drawablep->clearState(LLDrawable::ON_MOVE_LIST);
+			iter = moved_list.erase(curiter);
+		}
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree");
+static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move");
+
+void LLPipeline::updateMove()
+{
+	LLFastTimer t(FTM_UPDATE_MOVE);
+	LLMemType mt_um(LLMemType::MTYPE_PIPELINE_UPDATE_MOVE);
+
+	if (gSavedSettings.getBOOL("FreezeTime"))
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	{
+		static LLFastTimer::DeclareTimer ftm("Retexture");
+		LLFastTimer t(ftm);
+
+		for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin();
+			 iter != mRetexturedList.end(); ++iter)
+		{
+			LLDrawable* drawablep = *iter;
+			if (drawablep && !drawablep->isDead())
+			{
+				drawablep->updateTexture();
+			}
+		}
+		mRetexturedList.clear();
+	}
+
+	{
+		static LLFastTimer::DeclareTimer ftm("Moved List");
+		LLFastTimer t(ftm);
+		updateMovedList(mMovedList);
+	}
+
+	//balance octrees
+	{
+ 		LLFastTimer ot(FTM_OCTREE_BALANCE);
+
+		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+		{
+			LLViewerRegion* region = *iter;
+			for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+			{
+				LLSpatialPartition* part = region->getSpatialPartition(i);
+				if (part)
+				{
+					part->mOctree->balance();
+				}
+			}
+		}
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Culling and occlusion testing
+/////////////////////////////////////////////////////////////////////////////
+
+//static
+F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
+{
+	LLVector3 lookAt = center - camera.getOrigin();
+	F32 dist = lookAt.length();
+
+	//ramp down distance for nearby objects
+	//shrink dist by dist/16.
+	if (dist < 16.f)
+	{
+		dist /= 16.f;
+		dist *= dist;
+		dist *= 16.f;
+	}
+
+	//get area of circle around node
+	F32 app_angle = atanf(size.length()/dist);
+	F32 radius = app_angle*LLDrawable::sCurPixelAngle;
+	return radius*radius * F_PI;
+}
+
+void LLPipeline::grabReferences(LLCullResult& result)
+{
+	sCull = &result;
+}
+
+BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera)
+{
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if (hasRenderType(part->mDrawableType))
+				{
+					if (part->visibleObjectsInFrustum(camera))
+					{
+						return TRUE;
+					}
+				}
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max)
+{
+	const F32 X = 65536.f;
+
+	min = LLVector3(X,X,X);
+	max = LLVector3(-X,-X,-X);
+
+	U32 saved_camera_id = LLViewerCamera::sCurCameraID;
+	LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
+	BOOL res = TRUE;
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if (hasRenderType(part->mDrawableType))
+				{
+					if (!part->getVisibleExtents(camera, min, max))
+					{
+						res = FALSE;
+					}
+				}
+			}
+		}
+	}
+
+	LLViewerCamera::sCurCameraID = saved_camera_id;
+
+	return res;
+}
+
+static LLFastTimer::DeclareTimer FTM_CULL("Object Culling");
+
+void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip)
+{
+	LLFastTimer t(FTM_CULL);
+	LLMemType mt_uc(LLMemType::MTYPE_PIPELINE_UPDATE_CULL);
+
+	grabReferences(result);
+
+	sCull->clear();
+
+	BOOL to_texture =	LLPipeline::sUseOcclusion > 1 &&
+						!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && 
+						LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+						gPipeline.canUseVertexShaders() &&
+						sRenderGlow;
+
+	if (to_texture)
+	{
+		mScreen.bindTarget();
+	}
+
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadMatrixd(gGLLastProjection);
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	gGLLastMatrix = NULL;
+	glLoadMatrixd(gGLLastModelView);
+
+
+	LLVertexBuffer::unbind();
+	LLGLDisable blend(GL_BLEND);
+	LLGLDisable test(GL_ALPHA_TEST);
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	if (sUseOcclusion > 1)
+	{
+		gGL.setColorMask(false, false);
+	}
+
+	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		if (water_clip != 0)
+		{
+			LLPlane plane(LLVector3(0,0, (F32) -water_clip), (F32) water_clip*region->getWaterHeight());
+			camera.setUserClipPlane(plane);
+		}
+		else
+		{
+			camera.disableUserClipPlane();
+		}
+
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if (hasRenderType(part->mDrawableType))
+				{
+					part->cull(camera);
+				}
+			}
+		}
+	}
+
+	camera.disableUserClipPlane();
+
+	if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && 
+		gSky.mVOSkyp.notNull() && 
+		gSky.mVOSkyp->mDrawable.notNull())
+	{
+		gSky.mVOSkyp->mDrawable->setVisible(camera);
+		sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
+		gSky.updateCull();
+		stop_glerror();
+	}
+
+	if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && 
+		!gPipeline.canUseWindLightShaders() &&
+		gSky.mVOGroundp.notNull() && 
+		gSky.mVOGroundp->mDrawable.notNull() &&
+		!LLPipeline::sWaterReflections)
+	{
+		gSky.mVOGroundp->mDrawable->setVisible(camera);
+		sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
+	}
+	
+	
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	if (sUseOcclusion > 1)
+	{
+		gGL.setColorMask(true, false);
+	}
+
+	if (to_texture)
+	{
+		mScreen.flush();
+	}
+}
+
+void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
+{
+	if (group->getData().empty())
+	{ 
+		return;
+	}
+	
+	group->setVisible();
+
+	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+	{
+		group->updateDistance(camera);
+	}
+	
+	const F32 MINIMUM_PIXEL_AREA = 16.f;
+
+	if (group->mPixelArea < MINIMUM_PIXEL_AREA)
+	{
+		return;
+	}
+
+	if (sMinRenderSize > 0.f && 
+			llmax(llmax(group->mBounds[1].mV[0], group->mBounds[1].mV[1]), group->mBounds[1].mV[2]) < sMinRenderSize)
+	{
+		return;
+	}
+
+	assertInitialized();
+	
+	if (!group->mSpatialPartition->mRenderByGroup)
+	{ //render by drawable
+		sCull->pushDrawableGroup(group);
+	}
+	else
+	{   //render by group
+		sCull->pushVisibleGroup(group);
+	}
+
+	mNumVisibleNodes++;
+}
+
+void LLPipeline::markOccluder(LLSpatialGroup* group)
+{
+	if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION))
+	{
+		LLSpatialGroup* parent = group->getParent();
+
+		if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{ //only mark top most occluders as active occlusion
+			sCull->pushOcclusionGroup(group);
+			group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+				
+			if (parent && 
+				!parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) &&
+				parent->getElementCount() == 0 &&
+				parent->needsUpdate())
+			{
+				sCull->pushOcclusionGroup(group);
+				parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+			}
+		}
+	}
+}
+
+void LLPipeline::doOcclusion(LLCamera& camera)
+{
+	LLVertexBuffer::unbind();
+
+	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
+	{
+		gGL.setColorMask(true, false, false, false);
+	}
+	else
+	{
+		gGL.setColorMask(false, false);
+	}
+	LLGLDisable blend(GL_BLEND);
+	LLGLDisable test(GL_ALPHA_TEST);
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+
+	LLGLDisable cull(GL_CULL_FACE);
+	if (LLPipeline::sUseOcclusion > 1)
+	{
+		for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			group->doOcclusion(&camera);
+			group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION);
+		}
+	}
+
+	gGL.setColorMask(true, false);
+}
+	
+BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority)
+{
+	BOOL update_complete = drawablep->updateGeometry(priority);
+	if (update_complete && assertInitialized())
+	{
+		drawablep->setState(LLDrawable::BUILT);
+		mGeometryChanges++;
+	}
+	return update_complete;
+}
+
+void LLPipeline::updateGL()
+{
+	while (!LLGLUpdate::sGLQ.empty())
+	{
+		LLGLUpdate* glu = LLGLUpdate::sGLQ.front();
+		glu->updateGL();
+		glu->mInQ = FALSE;
+		LLGLUpdate::sGLQ.pop_front();
+	}
+}
+
+void LLPipeline::rebuildPriorityGroups()
+{
+	if(!sAllowRebuildPriorityGroup)
+	{
+		return ;
+	}
+	sAllowRebuildPriorityGroup = FALSE ;
+
+	LLTimer update_timer;
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	
+	assertInitialized();
+
+	// Iterate through all drawables on the priority build queue,
+	for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin();
+		 iter != mGroupQ1.end(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		group->rebuildGeom();
+		group->clearState(LLSpatialGroup::IN_BUILD_Q1);
+	}
+
+	mGroupQ1.clear();
+}
+		
+void LLPipeline::rebuildGroups()
+{
+	// Iterate through some drawables on the non-priority build queue
+	S32 size = (S32) mGroupQ2.size();
+	S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size);
+			
+	S32 count = 0;
+	
+	std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency());
+
+	LLSpatialGroup::sg_vector_t::iterator iter;
+	for (iter = mGroupQ2.begin();
+		 iter != mGroupQ2.end(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+
+		if (group->isDead())
+		{
+			continue;
+		}
+
+		group->rebuildGeom();
+		
+		if (group->mSpatialPartition->mRenderByGroup)
+		{
+			count++;
+		}
+			
+		group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+
+		if (count > min_count)
+		{
+			++iter;
+			break;
+		}
+	}	
+
+	mGroupQ2.erase(mGroupQ2.begin(), iter);
+
+	updateMovedList(mMovedBridge);
+}
+
+void LLPipeline::updateGeom(F32 max_dtime)
+{
+	LLTimer update_timer;
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_UPDATE_GEOM);
+	LLPointer<LLDrawable> drawablep;
+
+	LLFastTimer t(FTM_GEO_UPDATE);
+
+	assertInitialized();
+
+	if (sDelayedVBOEnable > 0)
+	{
+		if (--sDelayedVBOEnable <= 0)
+		{
+			resetVertexBuffers();
+			LLVertexBuffer::sEnableVBOs = TRUE;
+		}
+	}
+
+	// notify various object types to reset internal cost metrics, etc.
+	// for now, only LLVOVolume does this to throttle LOD changes
+	LLVOVolume::preUpdateGeom();
+
+	// Iterate through all drawables on the priority build queue,
+	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();
+		 iter != mBuildQ1.end();)
+	{
+		LLDrawable::drawable_list_t::iterator curiter = iter++;
+		LLDrawable* drawablep = *curiter;
+		if (drawablep && !drawablep->isDead())
+		{
+			if (drawablep->isState(LLDrawable::IN_REBUILD_Q2))
+			{
+				drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
+				LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep);
+				if (find != mBuildQ2.end())
+				{
+					mBuildQ2.erase(find);
+				}
+			}
+
+			if (updateDrawableGeom(drawablep, TRUE))
+			{
+				drawablep->clearState(LLDrawable::IN_REBUILD_Q1);
+				mBuildQ1.erase(curiter);
+			}
+		}
+		else
+		{
+			mBuildQ1.erase(curiter);
+		}
+	}
+		
+	// Iterate through some drawables on the non-priority build queue
+	S32 min_count = 16;
+	S32 size = (S32) mBuildQ2.size();
+	if (size > 1024)
+	{
+		min_count = llclamp((S32) (size * (F32) size/4096), 16, size);
+	}
+		
+	S32 count = 0;
+	
+	max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
+	LLSpatialGroup* last_group = NULL;
+	LLSpatialBridge* last_bridge = NULL;
+
+	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin();
+		 iter != mBuildQ2.end(); )
+	{
+		LLDrawable::drawable_list_t::iterator curiter = iter++;
+		LLDrawable* drawablep = *curiter;
+
+		LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() :
+									drawablep->getParent()->getSpatialBridge();
+
+		if (drawablep->getSpatialGroup() != last_group && 
+			(!last_bridge || bridge != last_bridge) &&
+			(update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count)
+		{
+			break;
+		}
+
+		//make sure updates don't stop in the middle of a spatial group
+		//to avoid thrashing (objects are enqueued by group)
+		last_group = drawablep->getSpatialGroup();
+		last_bridge = bridge;
+
+		BOOL update_complete = TRUE;
+		if (!drawablep->isDead())
+		{
+			update_complete = updateDrawableGeom(drawablep, FALSE);
+			count++;
+		}
+		if (update_complete)
+		{
+			drawablep->clearState(LLDrawable::IN_REBUILD_Q2);
+			mBuildQ2.erase(curiter);
+		}
+	}	
+
+	updateMovedList(mMovedBridge);
+}
+
+void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_VISIBLE);
+
+	if(drawablep && !drawablep->isDead())
+	{
+		if (drawablep->isSpatialBridge())
+		{
+			const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable;
+			llassert(root); // trying to catch a bad assumption
+			if (root && //  // this test may not be needed, see above
+					root->getVObj()->isAttachment())
+			{
+				LLDrawable* rootparent = root->getParent();
+				if (rootparent) // this IS sometimes NULL
+				{
+					LLViewerObject *vobj = rootparent->getVObj();
+					llassert(vobj); // trying to catch a bad assumption
+					if (vobj) // this test may not be needed, see above
+					{
+						const LLVOAvatar* av = vobj->asAvatar();
+						if (av && av->isImpostor())
+						{
+							return;
+						}
+					}
+				}
+			}
+			sCull->pushBridge((LLSpatialBridge*) drawablep);
+		}
+		else
+		{
+			sCull->pushDrawable(drawablep);
+		}
+
+		drawablep->setVisible(camera);
+	}
+}
+
+void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
+{
+	LLMemType mt_mm(LLMemType::MTYPE_PIPELINE_MARK_MOVED);
+
+	if (!drawablep)
+	{
+		//llerrs << "Sending null drawable to moved list!" << llendl;
+		return;
+	}
+	
+	if (drawablep->isDead())
+	{
+		llwarns << "Marking NULL or dead drawable moved!" << llendl;
+		return;
+	}
+	
+	if (drawablep->getParent()) 
+	{
+		//ensure that parent drawables are moved first
+		markMoved(drawablep->getParent(), damped_motion);
+	}
+
+	assertInitialized();
+
+	if (!drawablep->isState(LLDrawable::ON_MOVE_LIST))
+	{
+		if (drawablep->isSpatialBridge())
+		{
+			mMovedBridge.push_back(drawablep);
+		}
+		else
+		{
+			mMovedList.push_back(drawablep);
+		}
+		drawablep->setState(LLDrawable::ON_MOVE_LIST);
+	}
+	if (damped_motion == FALSE)
+	{
+		drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED
+	}
+	else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
+	{
+		drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
+	}
+}
+
+void LLPipeline::markShift(LLDrawable *drawablep)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_SHIFT);
+
+	if (!drawablep || drawablep->isDead())
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST))
+	{
+		drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE);
+		if (drawablep->getParent()) 
+		{
+			markShift(drawablep->getParent());
+		}
+		mShiftList.push_back(drawablep);
+		drawablep->setState(LLDrawable::ON_SHIFT_LIST);
+	}
+}
+
+void LLPipeline::shiftObjects(const LLVector3 &offset)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS);
+
+	assertInitialized();
+
+	glClear(GL_DEPTH_BUFFER_BIT);
+	gDepthDirty = TRUE;
+		
+	for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
+		 iter != mShiftList.end(); iter++)
+	{
+		LLDrawable *drawablep = *iter;
+		if (drawablep->isDead())
+		{
+			continue;
+		}	
+		drawablep->shiftPos(offset);	
+		drawablep->clearState(LLDrawable::ON_SHIFT_LIST);
+	}
+	mShiftList.resize(0);
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				part->shift(offset);
+			}
+		}
+	}
+
+	LLHUDText::shiftAll(offset);
+	LLHUDNameTag::shiftAll(offset);
+	display_update_camera();
+}
+
+void LLPipeline::markTextured(LLDrawable *drawablep)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_TEXTURED);
+
+	if (drawablep && !drawablep->isDead() && assertInitialized())
+	{
+		mRetexturedList.insert(drawablep);
+	}
+}
+
+void LLPipeline::markGLRebuild(LLGLUpdate* glu)
+{
+	if (glu && !glu->mInQ)
+	{
+		LLGLUpdate::sGLQ.push_back(glu);
+		glu->mInQ = TRUE;
+	}
+}
+
+void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	//assert_main_thread();
+
+	if (group && !group->isDead() && group->mSpatialPartition)
+	{
+		if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD)
+		{
+			priority = TRUE;
+		}
+
+		if (priority)
+		{
+			if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
+			{
+				mGroupQ1.push_back(group);
+				group->setState(LLSpatialGroup::IN_BUILD_Q1);
+
+				if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
+				{
+					LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
+					if (iter != mGroupQ2.end())
+					{
+						mGroupQ2.erase(iter);
+					}
+					group->clearState(LLSpatialGroup::IN_BUILD_Q2);
+				}
+			}
+		}
+		else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
+		{
+			//llerrs << "Non-priority updates not yet supported!" << llendl;
+			if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end())
+			{
+				llerrs << "WTF?" << llendl;
+			}
+			mGroupQ2.push_back(group);
+			group->setState(LLSpatialGroup::IN_BUILD_Q2);
+
+		}
+	}
+}
+
+void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_MARK_REBUILD);
+
+	if (drawablep && !drawablep->isDead() && assertInitialized())
+	{
+		if (!drawablep->isState(LLDrawable::BUILT))
+		{
+			priority = TRUE;
+		}
+		if (priority)
+		{
+			if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1))
+			{
+				mBuildQ1.push_back(drawablep);
+				drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue
+			}
+		}
+		else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2))
+		{
+			mBuildQ2.push_back(drawablep);
+			drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list
+		}
+		if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
+		{
+			drawablep->getVObj()->setChanged(LLXform::SILHOUETTE);
+		}
+		drawablep->setState(flag);
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order");
+
+void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
+{
+	if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
+					  LLPipeline::RENDER_TYPE_GROUND,
+					  LLPipeline::RENDER_TYPE_TERRAIN,
+					  LLPipeline::RENDER_TYPE_TREE,
+					  LLPipeline::RENDER_TYPE_SKY,
+					  LLPipeline::RENDER_TYPE_VOIDWATER,
+					  LLPipeline::RENDER_TYPE_WATER,
+					  LLPipeline::END_RENDER_TYPES))
+	{
+		//clear faces from face pools
+		LLFastTimer t(FTM_RESET_DRAWORDER);
+		gPipeline.resetDrawOrders();
+	}
+
+	LLFastTimer ftm(FTM_STATESORT);
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+
+	//LLVertexBuffer::unbind();
+
+	grabReferences(result);
+	for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		group->checkOcclusion();
+		if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{
+			markOccluder(group);
+		}
+		else
+		{
+			group->setVisible();
+			for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+			{
+				markVisible(*i, camera);
+			}
+		}
+	}
+	for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+	{
+		LLSpatialGroup* group = *iter;
+		group->checkOcclusion();
+		if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{
+			markOccluder(group);
+		}
+		else
+		{
+			group->setVisible();
+			stateSort(group, camera);
+		}
+	}
+	
+	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+	{
+		for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+		{
+			LLCullResult::bridge_list_t::iterator cur_iter = i;
+			LLSpatialBridge* bridge = *cur_iter;
+			LLSpatialGroup* group = bridge->getSpatialGroup();
+			if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+			{
+				stateSort(bridge, camera);
+			}
+		}
+	}
+	{
+		LLFastTimer ftm(FTM_STATESORT_DRAWABLE);
+		for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
+			 iter != sCull->endVisibleList(); ++iter)
+		{
+			LLDrawable *drawablep = *iter;
+			if (!drawablep->isDead())
+			{
+				stateSort(drawablep, camera);
+			}
+		}
+	}
+	{
+		LLFastTimer ftm(FTM_CLIENT_COPY);
+		LLVertexBuffer::clientCopy();
+	}
+	
+	postSort(camera);	
+}
+
+void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+	if (group->changeLOD())
+	{
+		for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+		{
+			LLDrawable* drawablep = *i;
+			stateSort(drawablep, camera);
+		}
+	}
+
+}
+
+void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+	if (!sShadowRender && bridge->getSpatialGroup()->changeLOD())
+	{
+		bool force_update = false;
+		bridge->updateDistance(camera, force_update);
+	}
+}
+
+void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT);
+		
+	if (!drawablep
+		|| drawablep->isDead() 
+		|| !hasRenderType(drawablep->getRenderType()))
+	{
+		return;
+	}
+	
+	if (LLSelectMgr::getInstance()->mHideSelectedObjects)
+	{
+		if (drawablep->getVObj().notNull() &&
+			drawablep->getVObj()->isSelected())
+		{
+			return;
+		}
+	}
+
+	if (drawablep->isAvatar())
+	{ //don't draw avatars beyond render distance or if we don't have a spatial group.
+		if ((drawablep->getSpatialGroup() == NULL) || 
+			(drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance))
+		{
+			return;
+		}
+
+		LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get();
+		if (!avatarp->isVisible())
+		{
+			return;
+		}
+	}
+
+	assertInitialized();
+
+	if (hasRenderType(drawablep->mRenderType))
+	{
+		if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE))
+		{
+			drawablep->setVisible(camera, NULL, FALSE);
+		}
+		else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE))
+		{
+			// clear invisible flag here to avoid single frame glitch
+			drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE);
+		}
+	}
+
+	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+	{
+		LLSpatialGroup* group = drawablep->getSpatialGroup();
+		if (!group || group->changeLOD())
+		{
+			if (drawablep->isVisible())
+			{
+				if (!drawablep->isActive())
+				{
+					bool force_update = false;
+					drawablep->updateDistance(camera, force_update);
+				}
+				else if (drawablep->isAvatar())
+				{
+					bool force_update = false;
+					drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
+				}
+			}
+		}
+	}
+
+	if (!drawablep->getVOVolume())
+	{
+		for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin();
+				iter != drawablep->mFaces.end(); iter++)
+		{
+			LLFace* facep = *iter;
+
+			if (facep->hasGeometry())
+			{
+				if (facep->getPool())
+				{
+					facep->getPool()->enqueue(facep);
+				}
+				else
+				{
+					break;
+				}
+			}
+		}
+	}
+	
+
+	mNumVisibleFaces += drawablep->getNumFaces();
+}
+
+
+void forAllDrawables(LLCullResult::sg_list_t::iterator begin, 
+					 LLCullResult::sg_list_t::iterator end,
+					 void (*func)(LLDrawable*))
+{
+	for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i)
+	{
+		for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j)
+		{
+			func(*j);	
+		}
+	}
+}
+
+void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*))
+{
+	forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func);
+	forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func);
+}
+
+//function for creating scripted beacons
+void renderScriptedBeacons(LLDrawable* drawablep)
+{
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj 
+		&& !vobj->isAvatar() 
+		&& !vobj->getParent()
+		&& vobj->flagScripted())
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderScriptedTouchBeacons(LLDrawable* drawablep)
+{
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj 
+		&& !vobj->isAvatar() 
+		&& !vobj->getParent()
+		&& vobj->flagScripted()
+		&& vobj->flagHandleTouch())
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderPhysicalBeacons(LLDrawable* drawablep)
+{
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj 
+		&& !vobj->isAvatar() 
+		//&& !vobj->getParent()
+		&& vobj->usePhysics())
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderParticleBeacons(LLDrawable* drawablep)
+{
+	// Look for attachments, objects, etc.
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj 
+		&& vobj->isParticleSource())
+	{
+		if (gPipeline.sRenderBeacons)
+		{
+			LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f);
+			gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
+		}
+
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void renderSoundHighlights(LLDrawable* drawablep)
+{
+	// Look for attachments, objects, etc.
+	LLViewerObject *vobj = drawablep->getVObj();
+	if (vobj && vobj->isAudioSource())
+	{
+		if (gPipeline.sRenderHighlight)
+		{
+			S32 face_id;
+			S32 count = drawablep->getNumFaces();
+			for (face_id = 0; face_id < count; face_id++)
+			{
+				gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) );
+			}
+		}
+	}
+}
+
+void LLPipeline::postSort(LLCamera& camera)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_POST_SORT);
+	LLFastTimer ftm(FTM_STATESORT_POSTSORT);
+
+	assertInitialized();
+
+	llpushcallstacks ;
+	//rebuild drawable geometry
+	for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
+	{
+		LLSpatialGroup* group = *i;
+		if (!sUseOcclusion || 
+			!group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{
+			group->rebuildGeom();
+		}
+	}
+	llpushcallstacks ;
+	//rebuild groups
+	sCull->assertDrawMapsEmpty();
+
+	/*LLSpatialGroup::sNoDelete = FALSE;
+	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+	{
+		LLSpatialGroup* group = *i;
+		if (sUseOcclusion && 
+			group->isState(LLSpatialGroup::OCCLUDED))
+		{
+			continue;
+		}
+		
+		group->rebuildGeom();
+	}
+	LLSpatialGroup::sNoDelete = TRUE;*/
+
+
+	rebuildPriorityGroups();
+	llpushcallstacks ;
+
+	const S32 bin_count = 1024*8;
+		
+	static LLCullResult::drawinfo_list_t alpha_bins[bin_count];
+	static U32 bin_size[bin_count];
+
+	//clear one bin per frame to avoid memory bloat
+	static S32 clear_idx = 0;
+	clear_idx = (1+clear_idx)%bin_count;
+	alpha_bins[clear_idx].clear();
+
+	for (U32 j = 0; j < bin_count; j++)
+	{
+		bin_size[j] = 0;
+	}
+
+	//build render map
+	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+	{
+		LLSpatialGroup* group = *i;
+		if (sUseOcclusion && 
+			group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+		{
+			continue;
+		}
+
+		if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
+		{ //no way this group is going to be drawable without a rebuild
+			group->rebuildGeom();
+		}
+
+		for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j)
+		{
+			LLSpatialGroup::drawmap_elem_t& src_vec = j->second;	
+			if (!hasRenderType(j->first))
+			{
+				continue;
+			}
+			
+			for (LLSpatialGroup::drawmap_elem_t::iterator k = src_vec.begin(); k != src_vec.end(); ++k)
+			{
+				if (sMinRenderSize > 0.f)
+				{
+					LLVector3 bounds = (*k)->mExtents[1]-(*k)->mExtents[0];
+					if (llmax(llmax(bounds.mV[0], bounds.mV[1]), bounds.mV[2]) > sMinRenderSize)
+					{
+						sCull->pushDrawInfo(j->first, *k);
+					}
+				}
+				else
+				{
+					sCull->pushDrawInfo(j->first, *k);
+				}
+			}
+		}
+
+		if (hasRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA))
+		{
+			LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
+			
+			if (alpha != group->mDrawMap.end())
+			{ //store alpha groups for sorting
+				LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+				if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+				{
+					if (bridge)
+					{
+						LLCamera trans_camera = bridge->transformCamera(camera);
+						group->updateDistance(trans_camera);
+					}
+					else
+					{
+						group->updateDistance(camera);
+					}
+				}
+							
+				if (hasRenderType(LLDrawPool::POOL_ALPHA))
+				{
+					sCull->pushAlphaGroup(group);
+				}
+			}
+		}
+	}
+		
+	if (!sShadowRender)
+	{
+		//sort by texture or bump map
+		for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i)
+		{
+			if (i == LLRenderPass::PASS_BUMP)
+			{
+				std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump());
+			}
+			else 
+			{
+				std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix());
+			}	
+		}
+
+		std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
+	}
+	llpushcallstacks ;
+	// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
+	if (LLFloaterReg::instanceVisible("beacons") && !sShadowRender)
+	{
+		if (sRenderScriptedTouchBeacons)
+		{
+			// Only show the beacon on the root object.
+			forAllVisibleDrawables(renderScriptedTouchBeacons);
+		}
+		else
+		if (sRenderScriptedBeacons)
+		{
+			// Only show the beacon on the root object.
+			forAllVisibleDrawables(renderScriptedBeacons);
+		}
+
+		if (sRenderPhysicalBeacons)
+		{
+			// Only show the beacon on the root object.
+			forAllVisibleDrawables(renderPhysicalBeacons);
+		}
+
+		if (sRenderParticleBeacons)
+		{
+			forAllVisibleDrawables(renderParticleBeacons);
+		}
+
+		// If god mode, also show audio cues
+		if (sRenderSoundBeacons && gAudiop)
+		{
+			// Walk all sound sources and render out beacons for them. Note, this isn't done in the ForAllVisibleDrawables function, because some are not visible.
+			LLAudioEngine::source_map::iterator iter;
+			for (iter = gAudiop->mAllSources.begin(); iter != gAudiop->mAllSources.end(); ++iter)
+			{
+				LLAudioSource *sourcep = iter->second;
+
+				LLVector3d pos_global = sourcep->getPositionGlobal();
+				LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global);
+				if (gPipeline.sRenderBeacons)
+				{
+					//pos += LLVector3(0.f, 0.f, 0.2f);
+					gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth"));
+				}
+			}
+			// now deal with highlights for all those seeable sound sources
+			forAllVisibleDrawables(renderSoundHighlights);
+		}
+	}
+	llpushcallstacks ;
+	// If managing your telehub, draw beacons at telehub and currently selected spawnpoint.
+	if (LLFloaterTelehub::renderBeacons())
+	{
+		LLFloaterTelehub::addBeacons();
+	}
+
+	if (!sShadowRender)
+	{
+		mSelectedFaces.clear();
+		
+		// Draw face highlights for selected faces.
+		if (LLSelectMgr::getInstance()->getTEMode())
+		{
+			struct f : public LLSelectedTEFunctor
+			{
+				virtual bool apply(LLViewerObject* object, S32 te)
+				{
+					if (object->mDrawable)
+					{
+						gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
+					}
+					return true;
+				}
+			} func;
+			LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+		}
+	}
+
+	//LLSpatialGroup::sNoDelete = FALSE;
+	llpushcallstacks ;
+}
+
+
+void render_hud_elements()
+{
+	LLMemType mt_rhe(LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS);
+	LLFastTimer t(FTM_RENDER_UI);
+	gPipeline.disableLights();		
+	
+	LLGLDisable fog(GL_FOG);
+	LLGLSUIDefault gls_ui;
+
+	LLGLEnable stencil(GL_STENCIL_TEST);
+	glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF);
+	glStencilMask(0xFFFFFFFF);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+	
+	gGL.color4f(1,1,1,1);
+	if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+	{
+		LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+		gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d()
+	
+		// Draw the tracking overlays
+		LLTracker::render3D();
+		
+		// Show the property lines
+		LLWorld::getInstance()->renderPropertyLines();
+		LLViewerParcelMgr::getInstance()->render();
+		LLViewerParcelMgr::getInstance()->renderParcelCollision();
+	
+		// Render name tags.
+		LLHUDObject::renderAll();
+	}
+	else if (gForceRenderLandFence)
+	{
+		// This is only set when not rendering the UI, for parcel snapshots
+		LLViewerParcelMgr::getInstance()->render();
+	}
+	else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+	{
+		LLHUDText::renderAllHUD();
+	}
+	gGL.flush();
+}
+
+void LLPipeline::renderHighlights()
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_HL);
+
+	assertInitialized();
+
+	// Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD)
+	// Render highlighted faces.
+	LLGLSPipelineAlpha gls_pipeline_alpha;
+	LLColor4 color(1.f, 1.f, 1.f, 0.5f);
+	LLGLEnable color_mat(GL_COLOR_MATERIAL);
+	disableLights();
+
+	if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !mHighlightSet.empty())
+	{ //draw blurry highlight image over screen
+		LLGLEnable blend(GL_BLEND);
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+		LLGLDisable test(GL_ALPHA_TEST);
+
+		LLGLEnable stencil(GL_STENCIL_TEST);
+		gGL.flush();
+		glStencilMask(0xFFFFFFFF);
+		glClearStencil(1);
+		glClear(GL_STENCIL_BUFFER_BIT);
+
+		glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
+		glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+				
+		gGL.setColorMask(false, false);
+		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
+		{
+			renderHighlight(iter->mItem->getVObj(), 1.f);
+		}
+		gGL.setColorMask(true, false);
+
+		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+		glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
+		
+		//gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+
+		gGL.pushMatrix();
+		glLoadIdentity();
+		glMatrixMode(GL_PROJECTION);
+		gGL.pushMatrix();
+		glLoadIdentity();
+
+		gGL.getTexUnit(0)->bind(&mHighlight);
+
+		LLVector2 tc1;
+		LLVector2 tc2;
+
+		tc1.setVec(0,0);
+		tc2.setVec(2,2);
+
+		gGL.begin(LLRender::TRIANGLES);
+				
+		F32 scale = gSavedSettings.getF32("RenderHighlightBrightness");
+		LLColor4 color = gSavedSettings.getColor4("RenderHighlightColor");
+		F32 thickness = gSavedSettings.getF32("RenderHighlightThickness");
+
+		for (S32 pass = 0; pass < 2; ++pass)
+		{
+			if (pass == 0)
+			{
+				gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+			}
+			else
+			{
+				gGL.setSceneBlendType(LLRender::BT_ALPHA);
+			}
+
+			for (S32 i = 0; i < 8; ++i)
+			{
+				for (S32 j = 0; j < 8; ++j)
+				{
+					LLVector2 tc(i-4+0.5f, j-4+0.5f);
+
+					F32 dist = 1.f-(tc.length()/sqrtf(32.f));
+					dist *= scale/64.f;
+
+					tc *= thickness;
+					tc.mV[0] = (tc.mV[0])/mHighlight.getWidth();
+					tc.mV[1] = (tc.mV[1])/mHighlight.getHeight();
+
+					gGL.color4f(color.mV[0],
+								color.mV[1],
+								color.mV[2],
+								color.mV[3]*dist);
+					
+					gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc2.mV[1]);
+					gGL.vertex2f(-1,3);
+					
+					gGL.texCoord2f(tc.mV[0]+tc1.mV[0], tc.mV[1]+tc1.mV[1]);
+					gGL.vertex2f(-1,-1);
+					
+					gGL.texCoord2f(tc.mV[0]+tc2.mV[0], tc.mV[1]+tc1.mV[1]);
+					gGL.vertex2f(3,-1);
+				}
+			}
+		}
+
+		gGL.end();
+
+		gGL.popMatrix();
+		glMatrixMode(GL_MODELVIEW);
+		gGL.popMatrix();
+		
+		//gGL.setSceneBlendType(LLRender::BT_ALPHA);
+	}
+
+	if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+	{
+		gHighlightProgram.bind();
+		gHighlightProgram.vertexAttrib4f(LLViewerShaderMgr::MATERIAL_COLOR,1,1,1,0.5f);
+	}
+	
+	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
+	{
+		// Make sure the selection image gets downloaded and decoded
+		if (!mFaceSelectImagep)
+		{
+			mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT);
+		}
+		mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA);
+
+		U32 count = mSelectedFaces.size();
+		for (U32 i = 0; i < count; i++)
+		{
+			LLFace *facep = mSelectedFaces[i];
+			if (!facep || facep->getDrawable()->isDead())
+			{
+				llerrs << "Bad face on selection" << llendl;
+				return;
+			}
+			
+			facep->renderSelected(mFaceSelectImagep, color);
+		}
+	}
+
+	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
+	{
+		// Paint 'em red!
+		color.setVec(1.f, 0.f, 0.f, 0.5f);
+		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		{
+			gHighlightProgram.vertexAttrib4f(LLViewerShaderMgr::MATERIAL_COLOR,1,0,0,0.5f);
+		}
+		int count = mHighlightFaces.size();
+		for (S32 i = 0; i < count; i++)
+		{
+			LLFace* facep = mHighlightFaces[i];
+			facep->renderSelected(LLViewerTexture::sNullImagep, color);
+		}
+	}
+
+	// Contains a list of the faces of objects that are physical or
+	// have touch-handlers.
+	mHighlightFaces.clear();
+
+	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
+	{
+		gHighlightProgram.unbind();
+	}
+}
+
+//debug use
+U32 LLPipeline::sCurRenderPoolType = 0 ;
+
+void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_RENDER_GEOM);
+	LLFastTimer t(FTM_RENDER_GEOMETRY);
+
+	assertInitialized();
+
+	F64 saved_modelview[16];
+	F64 saved_projection[16];
+
+	//HACK: preserve/restore matrices around HUD render
+	if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+	{
+		for (U32 i = 0; i < 16; i++)
+		{
+			saved_modelview[i] = gGLModelView[i];
+			saved_projection[i] = gGLProjection[i];
+		}
+	}
+
+	///////////////////////////////////////////
+	//
+	// Sync and verify GL state
+	//
+	//
+
+	stop_glerror();
+
+	LLVertexBuffer::unbind();
+
+	// Do verification of GL state
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+	if (mRenderDebugMask & RENDER_DEBUG_VERIFY)
+	{
+		if (!verify())
+		{
+			llerrs << "Pipeline verification failed!" << llendl;
+		}
+	}
+
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO");
+	
+	// Initialize lots of GL state to "safe" values
+	glMatrixMode(GL_TEXTURE);
+	glLoadIdentity();
+	glMatrixMode(GL_MODELVIEW);
+
+	LLGLSPipeline gls_pipeline;
+	LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+
+	LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2);
+				
+	// Toggle backface culling for debugging
+	LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0);
+	// Set fog
+	BOOL use_fog = hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG);
+	LLGLEnable fog_enable(use_fog &&
+						  !gPipeline.canUseWindLightShadersOnObjects() ? GL_FOG : 0);
+	gSky.updateFog(camera.getFar());
+	if (!use_fog)
+	{
+		sUnderWaterRender = FALSE;
+	}
+
+	gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sDefaultImagep);
+	LLViewerFetchedTexture::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
+	
+	//////////////////////////////////////////////
+	//
+	// Actually render all of the geometry
+	//
+	//	
+	stop_glerror();
+	
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
+
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		if (hasRenderType(poolp->getType()))
+		{
+			poolp->prerender();
+		}
+	}
+
+	{
+		LLFastTimer t(FTM_POOLS);
+		
+		// HACK: don't calculate local lights if we're rendering the HUD!
+		//    Removing this check will cause bad flickering when there are 
+		//    HUD elements being rendered AND the user is in flycam mode  -nyx
+		if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+		{
+			calcNearbyLights(camera);
+			setupHWLights(NULL);
+		}
+
+		BOOL occlude = sUseOcclusion > 1;
+		U32 cur_type = 0;
+
+		pool_set_t::iterator iter1 = mPools.begin();
+		while ( iter1 != mPools.end() )
+		{
+			LLDrawPool *poolp = *iter1;
+			
+			cur_type = poolp->getType();
+
+			//debug use
+			sCurRenderPoolType = cur_type ;
+
+			if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
+			{
+				occlude = FALSE;
+				gGLLastMatrix = NULL;
+				glLoadMatrixd(gGLModelView);
+				doOcclusion(camera);
+			}
+
+			pool_set_t::iterator iter2 = iter1;
+			if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0)
+			{
+				LLFastTimer t(FTM_POOLRENDER);
+
+				gGLLastMatrix = NULL;
+				glLoadMatrixd(gGLModelView);
+			
+				for( S32 i = 0; i < poolp->getNumPasses(); i++ )
+				{
+					LLVertexBuffer::unbind();
+					poolp->beginRenderPass(i);
+					for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+					{
+						LLDrawPool *p = *iter2;
+						if (p->getType() != cur_type)
+						{
+							break;
+						}
+						
+						p->render(i);
+					}
+					poolp->endRenderPass(i);
+					LLVertexBuffer::unbind();
+					if (gDebugGL || gDebugPipeline)
+					{
+						GLint depth;
+						glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+						if (depth > 3)
+						{
+							if (gDebugSession)
+							{
+								ll_fail("GL matrix stack corrupted.");
+							}
+							llerrs << "GL matrix stack corrupted!" << llendl;
+						}
+						std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i);
+						LLGLState::checkStates(msg);
+						LLGLState::checkTextureChannels(msg);
+						LLGLState::checkClientArrays(msg);
+					}
+				}
+			}
+			else
+			{
+				// Skip all pools of this type
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+				}
+			}
+			iter1 = iter2;
+			stop_glerror();
+		}
+	
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd");
+
+	LLVertexBuffer::unbind();
+		
+		gGLLastMatrix = NULL;
+		glLoadMatrixd(gGLModelView);
+
+		if (occlude)
+		{
+			occlude = FALSE;
+			gGLLastMatrix = NULL;
+			glLoadMatrixd(gGLModelView);
+			doOcclusion(camera);
+		}
+	}
+
+	LLVertexBuffer::unbind();
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+
+	
+
+	stop_glerror();
+		
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights");
+
+	if (!sReflectionRender)
+	{
+		renderHighlights();
+	}
+
+	// Contains a list of the faces of objects that are physical or
+	// have touch-handlers.
+	mHighlightFaces.clear();
+
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug");
+	
+	renderDebug();
+
+	LLVertexBuffer::unbind();
+	
+	if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred)
+	{
+		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+		{
+		      // Render debugging beacons.
+		      gObjectList.renderObjectBeacons();
+		      gObjectList.resetObjectBeacons();
+		}
+		else
+		{
+			// Make sure particle effects disappear
+			LLHUDObject::renderAllForTimer();
+		}
+	}
+	else
+	{
+		// Make sure particle effects disappear
+		LLHUDObject::renderAllForTimer();
+	}
+
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd");
+
+	//HACK: preserve/restore matrices around HUD render
+	if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+	{
+		for (U32 i = 0; i < 16; i++)
+		{
+			gGLModelView[i] = saved_modelview[i];
+			gGLProjection[i] = saved_projection[i];
+		}
+	}
+
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+}
+
+void LLPipeline::renderGeomDeferred(LLCamera& camera)
+{
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
+
+	LLMemType mt_rgd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED);
+	LLFastTimer t(FTM_RENDER_GEOMETRY);
+
+	LLFastTimer t2(FTM_POOLS);
+
+	LLGLEnable cull(GL_CULL_FACE);
+
+	LLGLEnable stencil(GL_STENCIL_TEST);
+	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+	stop_glerror();
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+	stop_glerror();
+
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		if (hasRenderType(poolp->getType()))
+		{
+			poolp->prerender();
+		}
+	}
+
+	LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+
+	U32 cur_type = 0;
+
+	gGL.setColorMask(true, true);
+	
+	pool_set_t::iterator iter1 = mPools.begin();
+
+	while ( iter1 != mPools.end() )
+	{
+		LLDrawPool *poolp = *iter1;
+		
+		cur_type = poolp->getType();
+
+		pool_set_t::iterator iter2 = iter1;
+		if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
+		{
+			LLFastTimer t(FTM_POOLRENDER);
+
+			gGLLastMatrix = NULL;
+			glLoadMatrixd(gGLModelView);
+		
+			for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
+			{
+				LLVertexBuffer::unbind();
+				poolp->beginDeferredPass(i);
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+										
+					p->renderDeferred(i);
+				}
+				poolp->endDeferredPass(i);
+				LLVertexBuffer::unbind();
+
+				if (gDebugGL || gDebugPipeline)
+				{
+					GLint depth;
+					glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+					if (depth > 3)
+					{
+						llerrs << "GL matrix stack corrupted!" << llendl;
+					}
+					LLGLState::checkStates();
+					LLGLState::checkTextureChannels();
+					LLGLState::checkClientArrays();
+				}
+			}
+		}
+		else
+		{
+			// Skip all pools of this type
+			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+			{
+				LLDrawPool *p = *iter2;
+				if (p->getType() != cur_type)
+				{
+					break;
+				}
+			}
+		}
+		iter1 = iter2;
+		stop_glerror();
+	}
+
+	gGLLastMatrix = NULL;
+	glLoadMatrixd(gGLModelView);
+
+	gGL.setColorMask(true, false);
+}
+
+void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
+{
+	LLMemType mt_rgpd(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF);
+	LLFastTimer t(FTM_POOLS);
+	U32 cur_type = 0;
+
+	LLGLEnable cull(GL_CULL_FACE);
+
+	LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+
+	calcNearbyLights(camera);
+	setupHWLights(NULL);
+
+	gGL.setColorMask(true, false);
+
+	pool_set_t::iterator iter1 = mPools.begin();
+	BOOL occlude = LLPipeline::sUseOcclusion > 1;
+
+	while ( iter1 != mPools.end() )
+	{
+		LLDrawPool *poolp = *iter1;
+		
+		cur_type = poolp->getType();
+
+		if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
+		{
+			occlude = FALSE;
+			gGLLastMatrix = NULL;
+			glLoadMatrixd(gGLModelView);
+			doOcclusion(camera);
+			gGL.setColorMask(true, false);
+		}
+
+		pool_set_t::iterator iter2 = iter1;
+		if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
+		{
+			LLFastTimer t(FTM_POOLRENDER);
+
+			gGLLastMatrix = NULL;
+			glLoadMatrixd(gGLModelView);
+		
+			for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ )
+			{
+				LLVertexBuffer::unbind();
+				poolp->beginPostDeferredPass(i);
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+										
+					p->renderPostDeferred(i);
+				}
+				poolp->endPostDeferredPass(i);
+				LLVertexBuffer::unbind();
+
+				if (gDebugGL || gDebugPipeline)
+				{
+					GLint depth;
+					glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+					if (depth > 3)
+					{
+						llerrs << "GL matrix stack corrupted!" << llendl;
+					}
+					LLGLState::checkStates();
+					LLGLState::checkTextureChannels();
+					LLGLState::checkClientArrays();
+				}
+			}
+		}
+		else
+		{
+			// Skip all pools of this type
+			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+			{
+				LLDrawPool *p = *iter2;
+				if (p->getType() != cur_type)
+				{
+					break;
+				}
+			}
+		}
+		iter1 = iter2;
+		stop_glerror();
+	}
+
+	gGLLastMatrix = NULL;
+	glLoadMatrixd(gGLModelView);
+
+	if (occlude)
+	{
+		occlude = FALSE;
+		gGLLastMatrix = NULL;
+		glLoadMatrixd(gGLModelView);
+		doOcclusion(camera);
+		gGLLastMatrix = NULL;
+		glLoadMatrixd(gGLModelView);
+	}
+}
+
+void LLPipeline::renderGeomShadow(LLCamera& camera)
+{
+	LLMemType mt_rgs(LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW);
+	U32 cur_type = 0;
+	
+	LLGLEnable cull(GL_CULL_FACE);
+
+	LLVertexBuffer::unbind();
+
+	pool_set_t::iterator iter1 = mPools.begin();
+	
+	while ( iter1 != mPools.end() )
+	{
+		LLDrawPool *poolp = *iter1;
+		
+		cur_type = poolp->getType();
+
+		pool_set_t::iterator iter2 = iter1;
+		if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0)
+		{
+			gGLLastMatrix = NULL;
+			glLoadMatrixd(gGLModelView);
+		
+			for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ )
+			{
+				LLVertexBuffer::unbind();
+				poolp->beginShadowPass(i);
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+										
+					p->renderShadow(i);
+				}
+				poolp->endShadowPass(i);
+				LLVertexBuffer::unbind();
+
+				LLGLState::checkStates();
+				LLGLState::checkTextureChannels();
+				LLGLState::checkClientArrays();
+			}
+		}
+		else
+		{
+			// Skip all pools of this type
+			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+			{
+				LLDrawPool *p = *iter2;
+				if (p->getType() != cur_type)
+				{
+					break;
+				}
+			}
+		}
+		iter1 = iter2;
+		stop_glerror();
+	}
+
+	gGLLastMatrix = NULL;
+	glLoadMatrixd(gGLModelView);
+}
+
+
+void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type)
+{
+	assertInitialized();
+	S32 count = 0;
+	if (render_type == LLRender::TRIANGLE_STRIP)
+	{
+		count = index_count-2;
+	}
+	else
+	{
+		count = index_count/3;
+	}
+
+	mTrianglesDrawn += count;
+	mBatchCount++;
+	mMaxBatchSize = llmax(mMaxBatchSize, count);
+	mMinBatchSize = llmin(mMinBatchSize, count);
+
+	if (LLPipeline::sRenderFrameTest)
+	{
+		gViewerWindow->getWindow()->swapBuffers();
+		ms_sleep(16);
+	}
+}
+
+void LLPipeline::renderDebug()
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+
+	assertInitialized();
+
+	gGL.color4f(1,1,1,1);
+
+	gGLLastMatrix = NULL;
+	glLoadMatrixd(gGLModelView);
+	gGL.setColorMask(true, false);
+
+	// Debug stuff.
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				if (hasRenderType(part->mDrawableType))
+				{
+					part->renderDebug();
+				}
+			}
+		}
+	}
+
+	for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+	{
+		LLSpatialBridge* bridge = *i;
+		if (!bridge->isDead() && hasRenderType(bridge->mDrawableType))
+		{
+			glPushMatrix();
+			glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+			bridge->renderDebug();
+			glPopMatrix();
+		}
+	}
+
+	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+	{
+		LLGLEnable blend(GL_BLEND);
+		LLGLDepthTest depth(TRUE, FALSE);
+		LLGLDisable cull(GL_CULL_FACE);
+
+		gGL.color4f(1,1,1,1);
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+				
+		F32 a = 0.1f;
+
+		F32 col[] =
+		{
+			1,0,0,a,
+			0,1,0,a,
+			0,0,1,a,
+			1,0,1,a,
+			
+			1,1,0,a,
+			0,1,1,a,
+			1,1,1,a,
+			1,0,1,a,
+		};
+
+		for (U32 i = 0; i < 8; i++)
+		{
+			LLVector3* frust = mShadowCamera[i].mAgentFrustum;
+
+			if (i > 3)
+			{ //render shadow frusta as volumes
+				if (mShadowFrustPoints[i-4].empty())
+			{
+					continue;
+				}
+
+				gGL.color4fv(col+(i-4)*4);	
+			
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+				gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+				gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+				gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+				gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+				gGL.end();
+				
+				
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.vertex3fv(frust[0].mV);
+				gGL.vertex3fv(frust[1].mV);
+				gGL.vertex3fv(frust[3].mV);
+				gGL.vertex3fv(frust[2].mV);
+				gGL.end();
+				
+				gGL.begin(LLRender::TRIANGLE_STRIP);
+				gGL.vertex3fv(frust[4].mV);
+				gGL.vertex3fv(frust[5].mV);
+				gGL.vertex3fv(frust[7].mV);
+				gGL.vertex3fv(frust[6].mV);
+				gGL.end();		
+			}
+
+	
+			if (i < 4)
+			{
+				
+				if (i == 0 || !mShadowFrustPoints[i].empty())
+				{
+					//render visible point cloud
+					gGL.flush();
+					glPointSize(8.f);
+					gGL.begin(LLRender::POINTS);
+					
+					F32* c = col+i*4;
+					gGL.color3fv(c);
+
+					for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j)
+						{
+							gGL.vertex3fv(mShadowFrustPoints[i][j].mV);
+						
+						}
+					gGL.end();
+
+					gGL.flush();
+					glPointSize(1.f);
+
+					LLVector3* ext = mShadowExtents[i]; 
+					LLVector3 pos = (ext[0]+ext[1])*0.5f;
+					LLVector3 size = (ext[1]-ext[0])*0.5f;
+					drawBoxOutline(pos, size);
+
+					//render camera frustum splits as outlines
+					gGL.begin(LLRender::LINES);
+					gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
+					gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
+					gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
+					gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
+					gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
+					gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
+					gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
+					gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
+					gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+					gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+					gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+					gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+					gGL.end();
+					}
+
+			}
+
+			/*for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+					iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+			{
+				LLViewerRegion* region = *iter;
+				for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
+				{
+					LLSpatialPartition* part = region->getSpatialPartition(j);
+					if (part)
+					{
+						if (hasRenderType(part->mDrawableType))
+						{
+							part->renderIntersectingBBoxes(&mShadowCamera[i]);
+						}
+					}
+				}
+			}*/
+		}
+	}
+
+	if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
+	{
+		// Debug composition layers
+		F32 x, y;
+
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+		if (gAgent.getRegion())
+		{
+			gGL.begin(LLRender::POINTS);
+			// Draw the composition layer for the region that I'm in.
+			for (x = 0; x <= 260; x++)
+			{
+				for (y = 0; y <= 260; y++)
+				{
+					if ((x > 255) || (y > 255))
+					{
+						gGL.color4f(1.f, 0.f, 0.f, 1.f);
+					}
+					else
+					{
+						gGL.color4f(0.f, 0.f, 1.f, 1.f);
+					}
+					F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y);
+					z *= 5.f;
+					z += 50.f;
+					gGL.vertex3f(x, y, z);
+				}
+			}
+			gGL.end();
+		}
+	}
+
+	if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE)
+	{
+		U32 count = 0;
+		U32 size = mBuildQ2.size();
+		LLColor4 col;
+
+		LLGLEnable blend(GL_BLEND);
+		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+		
+		for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter)
+		{
+			LLSpatialGroup* group = *iter;
+			if (group->isDead())
+			{
+				continue;
+			}
+
+			LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
+
+			if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead()))
+			{
+				continue;
+			}
+
+			if (bridge)
+			{
+				gGL.pushMatrix();
+				glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
+			}
+
+			F32 alpha = (F32) (size-count)/size;
+
+			
+			LLVector2 c(1.f-alpha, alpha);
+			c.normVec();
+
+			
+			++count;
+			col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.1f);
+			group->drawObjectBox(col);
+
+			if (bridge)
+			{
+				gGL.popMatrix();
+			}
+		}
+	}
+
+	gGL.flush();
+}
+
+void LLPipeline::rebuildPools()
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_REBUILD_POOLS);
+
+	assertInitialized();
+
+	S32 max_count = mPools.size();
+	pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool);
+	while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS)
+	{
+		if (iter1 == mPools.end())
+		{
+			iter1 = mPools.begin();
+		}
+		LLDrawPool* poolp = *iter1;
+
+		if (poolp->isDead())
+		{
+			mPools.erase(iter1++);
+			removeFromQuickLookup( poolp );
+			if (poolp == mLastRebuildPool)
+			{
+				mLastRebuildPool = NULL;
+			}
+			delete poolp;
+		}
+		else
+		{
+			mLastRebuildPool = poolp;
+			iter1++;
+		}
+		max_count--;
+	}
+
+	if (isAgentAvatarValid())
+	{
+		gAgentAvatarp->rebuildHUD();
+	}
+}
+
+void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
+{
+	LLMemType mt(LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP);
+
+	assertInitialized();
+
+	switch( new_poolp->getType() )
+	{
+	case LLDrawPool::POOL_SIMPLE:
+		if (mSimplePool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate simple pool." << llendl;
+		}
+		else
+		{
+			mSimplePool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_GRASS:
+		if (mGrassPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate grass pool." << llendl;
+		}
+		else
+		{
+			mGrassPool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_FULLBRIGHT:
+		if (mFullbrightPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate simple pool." << llendl;
+		}
+		else
+		{
+			mFullbrightPool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_INVISIBLE:
+		if (mInvisiblePool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate simple pool." << llendl;
+		}
+		else
+		{
+			mInvisiblePool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_GLOW:
+		if (mGlowPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate glow pool." << llendl;
+		}
+		else
+		{
+			mGlowPool = (LLRenderPass*) new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_TREE:
+		mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
+		break;
+ 
+	case LLDrawPool::POOL_TERRAIN:
+		mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ;
+		break;
+
+	case LLDrawPool::POOL_BUMP:
+		if (mBumpPool)
+		{
+			llassert(0);
+			llwarns << "Ignoring duplicate bump pool." << llendl;
+		}
+		else
+		{
+			mBumpPool = new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_ALPHA:
+		if( mAlphaPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl;
+		}
+		else
+		{
+			mAlphaPool = new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_AVATAR:
+		break; // Do nothing
+
+	case LLDrawPool::POOL_SKY:
+		if( mSkyPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl;
+		}
+		else
+		{
+			mSkyPool = new_poolp;
+		}
+		break;
+	
+	case LLDrawPool::POOL_WATER:
+		if( mWaterPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl;
+		}
+		else
+		{
+			mWaterPool = new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_GROUND:
+		if( mGroundPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl;
+		}
+		else
+		{ 
+			mGroundPool = new_poolp;
+		}
+		break;
+
+	case LLDrawPool::POOL_WL_SKY:
+		if( mWLSkyPool )
+		{
+			llassert(0);
+			llwarns << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << llendl;
+		}
+		else
+		{ 
+			mWLSkyPool = new_poolp;
+		}
+		break;
+
+	default:
+		llassert(0);
+		llwarns << "Invalid Pool Type in  LLPipeline::addPool()" << llendl;
+		break;
+	}
+}
+
+void LLPipeline::removePool( LLDrawPool* poolp )
+{
+	assertInitialized();
+	removeFromQuickLookup(poolp);
+	mPools.erase(poolp);
+	delete poolp;
+}
+
+void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
+{
+	assertInitialized();
+	LLMemType mt(LLMemType::MTYPE_PIPELINE);
+	switch( poolp->getType() )
+	{
+	case LLDrawPool::POOL_SIMPLE:
+		llassert(mSimplePool == poolp);
+		mSimplePool = NULL;
+		break;
+
+	case LLDrawPool::POOL_GRASS:
+		llassert(mGrassPool == poolp);
+		mGrassPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_FULLBRIGHT:
+		llassert(mFullbrightPool == poolp);
+		mFullbrightPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_INVISIBLE:
+		llassert(mInvisiblePool == poolp);
+		mInvisiblePool = NULL;
+		break;
+
+	case LLDrawPool::POOL_WL_SKY:
+		llassert(mWLSkyPool == poolp);
+		mWLSkyPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_GLOW:
+		llassert(mGlowPool == poolp);
+		mGlowPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_TREE:
+		#ifdef _DEBUG
+			{
+				BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() );
+				llassert( found );
+			}
+		#else
+			mTreePools.erase( (uintptr_t)poolp->getTexture() );
+		#endif
+		break;
+
+	case LLDrawPool::POOL_TERRAIN:
+		#ifdef _DEBUG
+			{
+				BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
+				llassert( found );
+			}
+		#else
+			mTerrainPools.erase( (uintptr_t)poolp->getTexture() );
+		#endif
+		break;
+
+	case LLDrawPool::POOL_BUMP:
+		llassert( poolp == mBumpPool );
+		mBumpPool = NULL;
+		break;
+	
+	case LLDrawPool::POOL_ALPHA:
+		llassert( poolp == mAlphaPool );
+		mAlphaPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_AVATAR:
+		break; // Do nothing
+
+	case LLDrawPool::POOL_SKY:
+		llassert( poolp == mSkyPool );
+		mSkyPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_WATER:
+		llassert( poolp == mWaterPool );
+		mWaterPool = NULL;
+		break;
+
+	case LLDrawPool::POOL_GROUND:
+		llassert( poolp == mGroundPool );
+		mGroundPool = NULL;
+		break;
+
+	default:
+		llassert(0);
+		llwarns << "Invalid Pool Type in  LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl;
+		break;
+	}
+}
+
+void LLPipeline::resetDrawOrders()
+{
+	assertInitialized();
+	// Iterate through all of the draw pools and rebuild them.
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		poolp->resetDrawOrders();
+	}
+}
+
+//============================================================================
+// Once-per-frame setup of hardware lights,
+// including sun/moon, avatar backlight, and up to 6 local lights
+
+void LLPipeline::setupAvatarLights(BOOL for_edit)
+{
+	assertInitialized();
+
+	if (for_edit)
+	{
+		LLColor4 diffuse(1.f, 1.f, 1.f, 0.f);
+		LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f);  // w==0 => directional light
+		LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
+		LLMatrix4 camera_rot(camera_mat.getMat3());
+		camera_rot.invert();
+		LLVector4 light_pos = light_pos_cam * camera_rot;
+		
+		light_pos.normalize();
+
+		mHWLightColors[1] = diffuse;
+		glLightfv(GL_LIGHT1, GL_DIFFUSE,  diffuse.mV);
+		glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
+		glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
+		glLightfv(GL_LIGHT1, GL_POSITION, light_pos.mV); 
+		glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION,  1.0f);
+		glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 	 0.0f);
+		glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
+		glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 		 0.0f);
+		glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 			 180.0f);
+	}
+	else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
+	{
+		LLVector3 opposite_pos = -1.f * mSunDir;
+		LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
+		LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
+		backlight_pos.normalize();
+			
+		LLColor4 light_diffuse = mSunDiffuse;
+		LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
+		F32 max_component = 0.001f;
+		for (S32 i = 0; i < 3; i++)
+		{
+			if (backlight_diffuse.mV[i] > max_component)
+			{
+				max_component = backlight_diffuse.mV[i];
+			}
+		}
+		F32 backlight_mag;
+		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
+		{
+			backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
+		}
+		else
+		{
+			backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT;
+		}
+		backlight_diffuse *= backlight_mag / max_component;
+
+		mHWLightColors[1] = backlight_diffuse;
+		glLightfv(GL_LIGHT1, GL_POSITION, backlight_pos.mV); // this is just sun/moon direction
+		glLightfv(GL_LIGHT1, GL_DIFFUSE,  backlight_diffuse.mV);
+		glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
+		glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
+		glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION,  1.0f);
+		glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION,    0.0f);
+		glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f);
+		glLightf (GL_LIGHT1, GL_SPOT_EXPONENT,         0.0f);
+		glLightf (GL_LIGHT1, GL_SPOT_CUTOFF,           180.0f);
+	}
+	else
+	{
+		mHWLightColors[1] = LLColor4::black;
+		glLightfv(GL_LIGHT1, GL_DIFFUSE,  LLColor4::black.mV);
+		glLightfv(GL_LIGHT1, GL_AMBIENT,  LLColor4::black.mV);
+		glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV);
+	}
+}
+
+static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
+{
+	F32 inten = light->getLightIntensity();
+	if (inten < .001f)
+	{
+		return max_dist;
+	}
+	F32 radius = light->getLightRadius();
+	BOOL selected = light->isSelected();
+	LLVector3 dpos = light->getRenderPosition() - cam_pos;
+	F32 dist2 = dpos.lengthSquared();
+	if (!selected && dist2 > (max_dist + radius)*(max_dist + radius))
+	{
+		return max_dist;
+	}
+	F32 dist = fsqrtf(dist2);
+	dist *= 1.f / inten;
+	dist -= radius;
+	if (selected)
+	{
+		dist -= 10000.f; // selected lights get highest priority
+	}
+	if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE))
+	{
+		// moving lights get a little higher priority (too much causes artifacts)
+		dist -= light->getLightRadius()*0.25f;
+	}
+	return dist;
+}
+
+void LLPipeline::calcNearbyLights(LLCamera& camera)
+{
+	assertInitialized();
+
+	if (LLPipeline::sReflectionRender)
+	{
+		return;
+	}
+
+	if (mLightingDetail >= 1)
+	{
+		// mNearbyLight (and all light_set_t's) are sorted such that
+		// begin() == the closest light and rbegin() == the farthest light
+		const S32 MAX_LOCAL_LIGHTS = 6;
+// 		LLVector3 cam_pos = gAgentCamera.getCameraPositionAgent();
+		LLVector3 cam_pos = LLViewerJoystick::getInstance()->getOverrideCamera() ?
+						camera.getOrigin() : 
+						gAgent.getPositionAgent();
+
+		F32 max_dist = LIGHT_MAX_RADIUS * 4.f; // ignore enitrely lights > 4 * max light rad
+		
+		// UPDATE THE EXISTING NEARBY LIGHTS
+		light_set_t cur_nearby_lights;
+		for (light_set_t::iterator iter = mNearbyLights.begin();
+			iter != mNearbyLights.end(); iter++)
+		{
+			const Light* light = &(*iter);
+			LLDrawable* drawable = light->drawable;
+			LLVOVolume* volight = drawable->getVOVolume();
+			if (!volight || !drawable->isState(LLDrawable::LIGHT))
+			{
+				drawable->clearState(LLDrawable::NEARBY_LIGHT);
+				continue;
+			}
+			if (light->fade <= -LIGHT_FADE_TIME)
+			{
+				drawable->clearState(LLDrawable::NEARBY_LIGHT);
+				continue;
+			}
+			if (!sRenderAttachedLights && volight && volight->isAttachment())
+			{
+				drawable->clearState(LLDrawable::NEARBY_LIGHT);
+				continue;
+			}
+
+			F32 dist = calc_light_dist(volight, cam_pos, max_dist);
+			cur_nearby_lights.insert(Light(drawable, dist, light->fade));
+		}
+		mNearbyLights = cur_nearby_lights;
+				
+		// FIND NEW LIGHTS THAT ARE IN RANGE
+		light_set_t new_nearby_lights;
+		for (LLDrawable::drawable_set_t::iterator iter = mLights.begin();
+			 iter != mLights.end(); ++iter)
+		{
+			LLDrawable* drawable = *iter;
+			LLVOVolume* light = drawable->getVOVolume();
+			if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT))
+			{
+				continue;
+			}
+			if (light->isHUDAttachment())
+			{
+				continue; // no lighting from HUD objects
+			}
+			F32 dist = calc_light_dist(light, cam_pos, max_dist);
+			if (dist >= max_dist)
+			{
+				continue;
+			}
+			if (!sRenderAttachedLights && light && light->isAttachment())
+			{
+				continue;
+			}
+			new_nearby_lights.insert(Light(drawable, dist, 0.f));
+			if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
+			{
+				new_nearby_lights.erase(--new_nearby_lights.end());
+				const Light& last = *new_nearby_lights.rbegin();
+				max_dist = last.dist;
+			}
+		}
+
+		// INSERT ANY NEW LIGHTS
+		for (light_set_t::iterator iter = new_nearby_lights.begin();
+			 iter != new_nearby_lights.end(); iter++)
+		{
+			const Light* light = &(*iter);
+			if (mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS)
+			{
+				mNearbyLights.insert(*light);
+				((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT);
+			}
+			else
+			{
+				// crazy cast so that we can overwrite the fade value
+				// even though gcc enforces sets as const
+				// (fade value doesn't affect sort so this is safe)
+				Light* farthest_light = ((Light*) (&(*(mNearbyLights.rbegin()))));
+				if (light->dist < farthest_light->dist)
+				{
+					if (farthest_light->fade >= 0.f)
+					{
+						farthest_light->fade = -gFrameIntervalSeconds;
+					}
+				}
+				else
+				{
+					break; // none of the other lights are closer
+				}
+			}
+		}
+		
+	}
+}
+
+void LLPipeline::setupHWLights(LLDrawPool* pool)
+{
+	assertInitialized();
+
+	// Ambient
+	LLColor4 ambient = gSky.getTotalAmbientColor();
+	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
+
+	// Light 0 = Sun or Moon (All objects)
+	{
+		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
+		{
+			mSunDir.setVec(gSky.getSunDirection());
+			mSunDiffuse.setVec(gSky.getSunDiffuseColor());
+		}
+		else
+		{
+			mSunDir.setVec(gSky.getMoonDirection());
+			mSunDiffuse.setVec(gSky.getMoonDiffuseColor());
+		}
+
+		F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
+		if (max_color > 1.f)
+		{
+			mSunDiffuse *= 1.f/max_color;
+		}
+		mSunDiffuse.clamp();
+
+		LLVector4 light_pos(mSunDir, 0.0f);
+		LLColor4 light_diffuse = mSunDiffuse;
+		mHWLightColors[0] = light_diffuse;
+		glLightfv(GL_LIGHT0, GL_POSITION, light_pos.mV); // this is just sun/moon direction
+		glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse.mV);
+		glLightfv(GL_LIGHT0, GL_AMBIENT,  LLColor4::black.mV);
+		glLightfv(GL_LIGHT0, GL_SPECULAR, LLColor4::black.mV);
+		glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION,  1.0f);
+		glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION,    0.0f);
+		glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f);
+		glLightf (GL_LIGHT0, GL_SPOT_EXPONENT,         0.0f);
+		glLightf (GL_LIGHT0, GL_SPOT_CUTOFF,           180.0f);
+	}
+	
+	// Light 1 = Backlight (for avatars)
+	// (set by enableLightsAvatar)
+	
+	S32 cur_light = 2;
+	
+	// Nearby lights = LIGHT 2-7
+
+	mLightMovingMask = 0;
+	
+	if (mLightingDetail >= 1)
+	{
+		for (light_set_t::iterator iter = mNearbyLights.begin();
+			 iter != mNearbyLights.end(); ++iter)
+		{
+			LLDrawable* drawable = iter->drawable;
+			LLVOVolume* light = drawable->getVOVolume();
+			if (!light)
+			{
+				continue;
+			}
+			if (drawable->isState(LLDrawable::ACTIVE))
+			{
+				mLightMovingMask |= (1<<cur_light);
+			}
+			
+			LLColor4  light_color = light->getLightColor();
+			light_color.mV[3] = 0.0f;
+
+			F32 fade = iter->fade;
+			if (fade < LIGHT_FADE_TIME)
+			{
+				// fade in/out light
+				if (fade >= 0.f)
+				{
+					fade = fade / LIGHT_FADE_TIME;
+					((Light*) (&(*iter)))->fade += gFrameIntervalSeconds;
+				}
+				else
+				{
+					fade = 1.f + fade / LIGHT_FADE_TIME;
+					((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds;
+				}
+				fade = llclamp(fade,0.f,1.f);
+				light_color *= fade;
+			}
+
+			LLVector3 light_pos(light->getRenderPosition());
+			LLVector4 light_pos_gl(light_pos, 1.0f);
+	
+			F32 light_radius = llmax(light->getLightRadius(), 0.001f);
+
+			F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic?  probably trying to match a historic behavior.
+			float linatten = x / (light_radius); // % of brightness at radius
+
+			mHWLightColors[cur_light] = light_color;
+			S32 gllight = GL_LIGHT0+cur_light;
+			glLightfv(gllight, GL_POSITION, light_pos_gl.mV);
+			glLightfv(gllight, GL_DIFFUSE,  light_color.mV);
+			glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
+			glLightf (gllight, GL_CONSTANT_ATTENUATION,   0.0f);
+			glLightf (gllight, GL_LINEAR_ATTENUATION,     linatten);
+			glLightf (gllight, GL_QUADRATIC_ATTENUATION,  0.0f);
+			if (light->isLightSpotlight() // directional (spot-)light
+			    && (LLPipeline::sRenderDeferred || gSavedSettings.getBOOL("RenderSpotLightsInNondeferred"))) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on
+			{
+				LLVector3 spotparams = light->getSpotLightParams();
+				LLQuaternion quat = light->getRenderRotation();
+				LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction
+				at_axis *= quat;
+				//llinfos << "SPOT!!!!!!! fov: " << spotparams.mV[0] << " focus: " << spotparams.mV[1] << " dir: " << at_axis << llendl;
+				glLightfv(gllight, GL_SPOT_DIRECTION, at_axis.mV);
+				glLightf (gllight, GL_SPOT_EXPONENT,  2.0f); // 2.0 = good old dot product ^ 2
+				glLightf (gllight, GL_SPOT_CUTOFF,    90.0f); // hemisphere
+				const float specular[] = {0.f, 0.f, 0.f, 0.f};
+				glLightfv(gllight, GL_SPECULAR, specular);
+			}
+			else // omnidirectional (point) light
+			{
+			glLightf (gllight, GL_SPOT_EXPONENT,          0.0f);
+			glLightf (gllight, GL_SPOT_CUTOFF,            180.0f);
+
+				// we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight
+				const float specular[] = {0.f, 0.f, 0.f, 1.f};
+				glLightfv(gllight, GL_SPECULAR, specular);
+				//llinfos << "boring light" << llendl;
+			}
+			cur_light++;
+			if (cur_light >= 8)
+			{
+				break; // safety
+			}
+		}
+	}
+	for ( ; cur_light < 8 ; cur_light++)
+	{
+		mHWLightColors[cur_light] = LLColor4::black;
+		S32 gllight = GL_LIGHT0+cur_light;
+		glLightfv(gllight, GL_DIFFUSE,  LLColor4::black.mV);
+		glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
+		glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV);
+	}
+
+	if (isAgentAvatarValid() &&
+		gAgentAvatarp->mSpecialRenderMode == 3)
+	{
+		LLColor4  light_color = LLColor4::white;
+		light_color.mV[3] = 0.0f;
+
+		LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
+		LLVector4 light_pos_gl(light_pos, 1.0f);
+
+		F32 light_radius = 16.f;
+
+			F32 x = 3.f;
+		float linatten = x / (light_radius); // % of brightness at radius
+
+		mHWLightColors[2] = light_color;
+		S32 gllight = GL_LIGHT2;
+		glLightfv(gllight, GL_POSITION, light_pos_gl.mV);
+		glLightfv(gllight, GL_DIFFUSE,  light_color.mV);
+		glLightfv(gllight, GL_AMBIENT,  LLColor4::black.mV);
+		glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV);
+		glLightf (gllight, GL_CONSTANT_ATTENUATION,   0.0f);
+		glLightf (gllight, GL_LINEAR_ATTENUATION,     linatten);
+		glLightf (gllight, GL_QUADRATIC_ATTENUATION,  0.0f);
+		glLightf (gllight, GL_SPOT_EXPONENT,          0.0f);
+		glLightf (gllight, GL_SPOT_CUTOFF,            180.0f);
+	}
+
+	// Init GL state
+	glDisable(GL_LIGHTING);
+	for (S32 gllight=GL_LIGHT0; gllight<=GL_LIGHT7; gllight++)
+	{
+		glDisable(gllight);
+	}
+	mLightMask = 0;
+}
+
+void LLPipeline::enableLights(U32 mask)
+{
+	assertInitialized();
+
+	if (mLightingDetail == 0)
+	{
+		mask &= 0xf003; // sun and backlight only (and fullbright bit)
+	}
+	if (mLightMask != mask)
+	{
+		stop_glerror();
+		if (!mLightMask)
+		{
+			glEnable(GL_LIGHTING);
+		}
+		if (mask)
+		{
+			stop_glerror();
+			for (S32 i=0; i<8; i++)
+			{
+				if (mask & (1<<i))
+				{
+					glEnable(GL_LIGHT0 + i);
+					glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  mHWLightColors[i].mV);
+				}
+				else
+				{
+					glDisable(GL_LIGHT0 + i);
+					glLightfv(GL_LIGHT0 + i, GL_DIFFUSE,  LLColor4::black.mV);
+				}
+			}
+			stop_glerror();
+		}
+		else
+		{
+			glDisable(GL_LIGHTING);
+		}
+		stop_glerror();
+		mLightMask = mask;
+		LLColor4 ambient = gSky.getTotalAmbientColor();
+		glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV);
+		stop_glerror();
+	}
+}
+
+void LLPipeline::enableLightsStatic()
+{
+	assertInitialized();
+	U32 mask = 0x01; // Sun
+	if (mLightingDetail >= 2)
+	{
+		mask |= mLightMovingMask; // Hardware moving lights
+		glColor4f(0.f, 0.f, 0.f, 1.0f); // no local lighting by default
+	}
+	else
+	{
+		mask |= 0xff & (~2); // Hardware local lights
+	}
+	enableLights(mask);
+}
+
+void LLPipeline::enableLightsDynamic()
+{
+	assertInitialized();
+	U32 mask = 0xff & (~2); // Local lights
+	enableLights(mask);
+	if (mLightingDetail >= 2)
+	{
+		glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default
+	}
+
+	if (isAgentAvatarValid() && getLightingDetail() <= 0)
+	{
+		if (gAgentAvatarp->mSpecialRenderMode == 0) // normal
+		{
+			gPipeline.enableLightsAvatar();
+		}
+		else if (gAgentAvatarp->mSpecialRenderMode >= 1)  // anim preview
+		{
+			gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f));
+		}
+	}
+}
+
+void LLPipeline::enableLightsAvatar()
+{
+	U32 mask = 0xff; // All lights
+	setupAvatarLights(FALSE);
+	enableLights(mask);
+}
+
+void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
+{
+	U32 mask = 0x2002; // Avatar backlight only, set ambient
+	setupAvatarLights(TRUE);
+	enableLights(mask);
+
+	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
+}
+
+void LLPipeline::enableLightsFullbright(const LLColor4& color)
+{
+	assertInitialized();
+	U32 mask = 0x1000; // Non-0 mask, set ambient
+	enableLights(mask);
+
+	glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV);
+	/*if (mLightingDetail >= 2)
+	{
+		glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default
+	}*/
+}
+
+void LLPipeline::disableLights()
+{
+	enableLights(0); // no lighting (full bright)
+	glColor4f(1.f, 1.f, 1.f, 1.f); // lighting color = white by default
+}
+
+//============================================================================
+
+class LLMenuItemGL;
+class LLInvFVBridge;
+struct cat_folder_pair;
+class LLVOBranch;
+class LLVOLeaf;
+
+void LLPipeline::findReferences(LLDrawable *drawablep)
+{
+	assertInitialized();
+	if (mLights.find(drawablep) != mLights.end())
+	{
+		llinfos << "In mLights" << llendl;
+	}
+	if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end())
+	{
+		llinfos << "In mMovedList" << llendl;
+	}
+	if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end())
+	{
+		llinfos << "In mShiftList" << llendl;
+	}
+	if (mRetexturedList.find(drawablep) != mRetexturedList.end())
+	{
+		llinfos << "In mRetexturedList" << llendl;
+	}
+	
+	if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end())
+	{
+		llinfos << "In mBuildQ1" << llendl;
+	}
+	if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end())
+	{
+		llinfos << "In mBuildQ2" << llendl;
+	}
+
+	S32 count;
+	
+	count = gObjectList.findReferences(drawablep);
+	if (count)
+	{
+		llinfos << "In other drawables: " << count << " references" << llendl;
+	}
+}
+
+BOOL LLPipeline::verify()
+{
+	BOOL ok = assertInitialized();
+	if (ok) 
+	{
+		for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+		{
+			LLDrawPool *poolp = *iter;
+			if (!poolp->verify())
+			{
+				ok = FALSE;
+			}
+		}
+	}
+
+	if (!ok)
+	{
+		llwarns << "Pipeline verify failed!" << llendl;
+	}
+	return ok;
+}
+
+//////////////////////////////
+//
+// Collision detection
+//
+//
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ *	A method to compute a ray-AABB intersection.
+ *	Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
+ *	Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
+ *	Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
+ *
+ *	Hence this version is faster as well as more robust than the original one.
+ *
+ *	Should work provided:
+ *	1) the integer representation of 0.0f is 0x00000000
+ *	2) the sign bit of the float is the most significant one
+ *
+ *	Report bugs: p.terdiman@codercorner.com
+ *
+ *	\param		aabb		[in] the axis-aligned bounding box
+ *	\param		origin		[in] ray origin
+ *	\param		dir			[in] ray direction
+ *	\param		coord		[out] impact coordinates
+ *	\return		true if ray intersects AABB
+ */
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//#define RAYAABB_EPSILON 0.00001f
+#define IR(x)	((U32&)x)
+
+bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon)
+{
+	BOOL Inside = TRUE;
+	LLVector3 MinB = center - size;
+	LLVector3 MaxB = center + size;
+	LLVector3 MaxT;
+	MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f;
+
+	// Find candidate planes.
+	for(U32 i=0;i<3;i++)
+	{
+		if(origin.mV[i] < MinB.mV[i])
+		{
+			coord.mV[i]	= MinB.mV[i];
+			Inside		= FALSE;
+
+			// Calculate T distances to candidate planes
+			if(IR(dir.mV[i]))	MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i];
+		}
+		else if(origin.mV[i] > MaxB.mV[i])
+		{
+			coord.mV[i]	= MaxB.mV[i];
+			Inside		= FALSE;
+
+			// Calculate T distances to candidate planes
+			if(IR(dir.mV[i]))	MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i];
+		}
+	}
+
+	// Ray origin inside bounding box
+	if(Inside)
+	{
+		coord = origin;
+		return true;
+	}
+
+	// Get largest of the maxT's for final choice of intersection
+	U32 WhichPlane = 0;
+	if(MaxT.mV[1] > MaxT.mV[WhichPlane])	WhichPlane = 1;
+	if(MaxT.mV[2] > MaxT.mV[WhichPlane])	WhichPlane = 2;
+
+	// Check final candidate actually inside box
+	if(IR(MaxT.mV[WhichPlane])&0x80000000) return false;
+
+	for(U32 i=0;i<3;i++)
+	{
+		if(i!=WhichPlane)
+		{
+			coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i];
+			if (epsilon > 0)
+			{
+				if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon)	return false;
+			}
+			else
+			{
+				if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i])	return false;
+			}
+		}
+	}
+	return true;	// ray hits box
+}
+
+//////////////////////////////
+//
+// Macros, functions, and inline methods from other classes
+//
+//
+
+void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
+{
+	if (drawablep && assertInitialized())
+	{
+		if (is_light)
+		{
+			mLights.insert(drawablep);
+			drawablep->setState(LLDrawable::LIGHT);
+		}
+		else
+		{
+			drawablep->clearState(LLDrawable::LIGHT);
+			mLights.erase(drawablep);
+		}
+	}
+}
+
+//static
+void LLPipeline::toggleRenderType(U32 type)
+{
+	gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type];
+	if (type == LLPipeline::RENDER_TYPE_WATER)
+	{
+		gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER];
+	}
+}
+
+//static
+void LLPipeline::toggleRenderTypeControl(void* data)
+{
+	U32 type = (U32)(intptr_t)data;
+	U32 bit = (1<<type);
+	if (gPipeline.hasRenderType(type))
+	{
+		llinfos << "Toggling render type mask " << std::hex << bit << " off" << std::dec << llendl;
+	}
+	else
+	{
+		llinfos << "Toggling render type mask " << std::hex << bit << " on" << std::dec << llendl;
+	}
+	gPipeline.toggleRenderType(type);
+}
+
+//static
+BOOL LLPipeline::hasRenderTypeControl(void* data)
+{
+	U32 type = (U32)(intptr_t)data;
+	return gPipeline.hasRenderType(type);
+}
+
+// Allows UI items labeled "Hide foo" instead of "Show foo"
+//static
+BOOL LLPipeline::toggleRenderTypeControlNegated(void* data)
+{
+	S32 type = (S32)(intptr_t)data;
+	return !gPipeline.hasRenderType(type);
+}
+
+//static
+void LLPipeline::toggleRenderDebug(void* data)
+{
+	U32 bit = (U32)(intptr_t)data;
+	if (gPipeline.hasRenderDebugMask(bit))
+	{
+		llinfos << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << llendl;
+	}
+	else
+	{
+		llinfos << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << llendl;
+	}
+	gPipeline.mRenderDebugMask ^= bit;
+}
+
+
+//static
+BOOL LLPipeline::toggleRenderDebugControl(void* data)
+{
+	U32 bit = (U32)(intptr_t)data;
+	return gPipeline.hasRenderDebugMask(bit);
+}
+
+//static
+void LLPipeline::toggleRenderDebugFeature(void* data)
+{
+	U32 bit = (U32)(intptr_t)data;
+	gPipeline.mRenderDebugFeatureMask ^= bit;
+}
+
+
+//static
+BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
+{
+	U32 bit = (U32)(intptr_t)data;
+	return gPipeline.hasRenderDebugFeatureMask(bit);
+}
+
+// static
+void LLPipeline::setRenderScriptedBeacons(BOOL val)
+{
+	sRenderScriptedBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderScriptedBeacons(void*)
+{
+	sRenderScriptedBeacons = !sRenderScriptedBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderScriptedBeacons(void*)
+{
+	return sRenderScriptedBeacons;
+}
+
+// static
+void LLPipeline::setRenderScriptedTouchBeacons(BOOL val)
+{
+	sRenderScriptedTouchBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderScriptedTouchBeacons(void*)
+{
+	sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderScriptedTouchBeacons(void*)
+{
+	return sRenderScriptedTouchBeacons;
+}
+
+// static
+void LLPipeline::setRenderPhysicalBeacons(BOOL val)
+{
+	sRenderPhysicalBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderPhysicalBeacons(void*)
+{
+	sRenderPhysicalBeacons = !sRenderPhysicalBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderPhysicalBeacons(void*)
+{
+	return sRenderPhysicalBeacons;
+}
+
+// static
+void LLPipeline::setRenderParticleBeacons(BOOL val)
+{
+	sRenderParticleBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderParticleBeacons(void*)
+{
+	sRenderParticleBeacons = !sRenderParticleBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderParticleBeacons(void*)
+{
+	return sRenderParticleBeacons;
+}
+
+// static
+void LLPipeline::setRenderSoundBeacons(BOOL val)
+{
+	sRenderSoundBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderSoundBeacons(void*)
+{
+	sRenderSoundBeacons = !sRenderSoundBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderSoundBeacons(void*)
+{
+	return sRenderSoundBeacons;
+}
+
+// static
+void LLPipeline::setRenderBeacons(BOOL val)
+{
+	sRenderBeacons = val;
+}
+
+// static
+void LLPipeline::toggleRenderBeacons(void*)
+{
+	sRenderBeacons = !sRenderBeacons;
+}
+
+// static
+BOOL LLPipeline::getRenderBeacons(void*)
+{
+	return sRenderBeacons;
+}
+
+// static
+void LLPipeline::setRenderHighlights(BOOL val)
+{
+	sRenderHighlight = val;
+}
+
+// static
+void LLPipeline::toggleRenderHighlights(void*)
+{
+	sRenderHighlight = !sRenderHighlight;
+}
+
+// static
+BOOL LLPipeline::getRenderHighlights(void*)
+{
+	return sRenderHighlight;
+}
+
+LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, const LLVector3& end,
+														BOOL pick_transparent,												
+														S32* face_hit,
+														LLVector3* intersection,         // return the intersection point
+														LLVector2* tex_coord,            // return the texture coordinates of the intersection point
+														LLVector3* normal,               // return the surface normal at the intersection point
+														LLVector3* bi_normal             // return the surface bi-normal at the intersection point
+	)
+{
+	LLDrawable* drawable = NULL;
+
+	LLVector3 local_end = end;
+
+	LLVector3 position;
+
+	sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE;
+	
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+
+		for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
+		{
+			if ((j == LLViewerRegion::PARTITION_VOLUME) || 
+				(j == LLViewerRegion::PARTITION_BRIDGE) || 
+				(j == LLViewerRegion::PARTITION_TERRAIN) ||
+				(j == LLViewerRegion::PARTITION_TREE) ||
+				(j == LLViewerRegion::PARTITION_GRASS))  // only check these partitions for now
+			{
+				LLSpatialPartition* part = region->getSpatialPartition(j);
+				if (part && hasRenderType(part->mDrawableType))
+				{
+					LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
+					if (hit)
+					{
+						drawable = hit;
+						local_end = position;						
+					}
+				}
+			}
+		}
+	}
+	
+	if (!sPickAvatar)
+	{
+		//save hit info in case we need to restore
+		//due to attachment override
+		LLVector3 local_normal;
+		LLVector3 local_binormal;
+		LLVector2 local_texcoord;
+		S32 local_face_hit = -1;
+
+		if (face_hit)
+		{ 
+			local_face_hit = *face_hit;
+		}
+		if (tex_coord)
+		{
+			local_texcoord = *tex_coord;
+		}
+		if (bi_normal)
+		{
+			local_binormal = *bi_normal;
+		}
+		if (normal)
+		{
+			local_normal = *normal;
+		}
+				
+		const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f;
+
+		//check against avatars
+		sPickAvatar = TRUE;
+		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+				iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+		{
+			LLViewerRegion* region = *iter;
+
+			LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
+			if (part && hasRenderType(part->mDrawableType))
+			{
+				LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal);
+				if (hit)
+				{
+					if (!drawable || 
+						!drawable->getVObj()->isAttachment() ||
+						(position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST)
+					{ //avatar overrides if previously hit drawable is not an attachment or 
+					  //attachment is far enough away from detected intersection
+						drawable = hit;
+						local_end = position;						
+					}
+					else
+					{ //prioritize attachments over avatars
+						position = local_end;
+
+						if (face_hit)
+						{
+							*face_hit = local_face_hit;
+						}
+						if (tex_coord)
+						{
+							*tex_coord = local_texcoord;
+						}
+						if (bi_normal)
+						{
+							*bi_normal = local_binormal;
+						}
+						if (normal)
+						{
+							*normal = local_normal;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	//check all avatar nametags (silly, isn't it?)
+	for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin();
+		iter != LLCharacter::sInstances.end();
+		++iter)
+	{
+		LLVOAvatar* av = (LLVOAvatar*) *iter;
+		if (av->mNameText.notNull()
+			&& av->mNameText->lineSegmentIntersect(start, local_end, position))
+		{
+			drawable = av->mDrawable;
+			local_end = position;
+		}
+	}
+
+	if (intersection)
+	{
+		*intersection = position;
+	}
+
+	return drawable ? drawable->getVObj().get() : NULL;
+}
+
+LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector3& start, const LLVector3& end,
+													  BOOL pick_transparent,													
+													  S32* face_hit,
+													  LLVector3* intersection,         // return the intersection point
+													  LLVector2* tex_coord,            // return the texture coordinates of the intersection point
+													  LLVector3* normal,               // return the surface normal at the intersection point
+													  LLVector3* bi_normal             // return the surface bi-normal at the intersection point
+	)
+{
+	LLDrawable* drawable = NULL;
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+
+		BOOL toggle = FALSE;
+		if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+		{
+			toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+			toggle = TRUE;
+		}
+
+		LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
+		if (part)
+		{
+			LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal);
+			if (hit)
+			{
+				drawable = hit;
+			}
+		}
+
+		if (toggle)
+		{
+			toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+		}
+	}
+	return drawable ? drawable->getVObj().get() : NULL;
+}
+
+LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj)
+{
+	if (vobj)
+	{
+		LLViewerRegion* region = vobj->getRegion();
+		if (region)
+		{
+			return region->getSpatialPartition(vobj->getPartitionType());
+		}
+	}
+	return NULL;
+}
+
+
+void LLPipeline::resetVertexBuffers(LLDrawable* drawable)
+{
+	if (!drawable || drawable->isDead())
+	{
+		return;
+	}
+
+	for (S32 i = 0; i < drawable->getNumFaces(); i++)
+	{
+		LLFace* facep = drawable->getFace(i);
+		facep->mVertexBuffer = NULL;
+		facep->mLastVertexBuffer = NULL;
+	}
+}
+
+void LLPipeline::resetVertexBuffers()
+{
+	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
+	sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
+	LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("RenderUseStreamVBO");
+
+	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
+			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+	{
+		LLViewerRegion* region = *iter;
+		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+		{
+			LLSpatialPartition* part = region->getSpatialPartition(i);
+			if (part)
+			{
+				part->resetVertexBuffers();
+			}
+		}
+	}
+
+	resetDrawOrders();
+
+	gSky.resetVertexBuffers();
+
+	if (LLVertexBuffer::sGLCount > 0)
+	{
+		LLVertexBuffer::cleanupClass();
+	}
+
+	//delete all name pool caches
+	LLGLNamePool::cleanupPools();
+
+	if (LLVertexBuffer::sGLCount > 0)
+	{
+		llwarns << "VBO wipe failed." << llendl;
+	}
+
+	if (!LLVertexBuffer::sStreamIBOPool.mNameList.empty() ||
+		!LLVertexBuffer::sStreamVBOPool.mNameList.empty() ||
+		!LLVertexBuffer::sDynamicIBOPool.mNameList.empty() ||
+		!LLVertexBuffer::sDynamicVBOPool.mNameList.empty())
+	{
+		llwarns << "VBO name pool cleanup failed." << llendl;
+	}
+
+	LLVertexBuffer::unbind();
+
+	LLPipeline::sTextureBindTest = gSavedSettings.getBOOL("RenderDebugTextureBind");
+}
+
+void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)
+{
+	LLMemType mt_ro(LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS);
+	assertInitialized();
+	glLoadMatrixd(gGLModelView);
+	gGLLastMatrix = NULL;
+	mSimplePool->pushBatches(type, mask);
+	glLoadMatrixd(gGLModelView);
+	gGLLastMatrix = NULL;		
+}
+
+void LLPipeline::setUseVBO(BOOL use_vbo)
+{
+	if (use_vbo != LLVertexBuffer::sEnableVBOs)
+	{
+		if (use_vbo)
+		{
+			llinfos << "Enabling VBO." << llendl;
+		}
+		else
+		{ 
+			llinfos << "Disabling VBO." << llendl;
+		}
+		
+		resetVertexBuffers();
+		LLVertexBuffer::initClass(use_vbo, gSavedSettings.getBOOL("RenderVBOMappingDisable"));
+	}
+}
+
+void LLPipeline::setDisableVBOMapping(BOOL no_vbo_mapping)
+{
+	if (LLVertexBuffer::sEnableVBOs && no_vbo_mapping != LLVertexBuffer::sDisableVBOMapping)
+	{
+		if (no_vbo_mapping)
+		{
+			llinfos << "Disabling VBO glMapBufferARB." << llendl;
+		}
+		else
+		{ 
+			llinfos << "Enabling VBO glMapBufferARB." << llendl;
+		}
+		
+		resetVertexBuffers();
+		LLVertexBuffer::initClass(true, no_vbo_mapping);
+	}
+}
+
+void apply_cube_face_rotation(U32 face)
+{
+	switch (face)
+	{
+		case 0: 
+			glRotatef(90.f, 0, 1, 0);
+			glRotatef(180.f, 1, 0, 0);
+		break;
+		case 2: 
+			glRotatef(-90.f, 1, 0, 0);
+		break;
+		case 4:
+			glRotatef(180.f, 0, 1, 0);
+			glRotatef(180.f, 0, 0, 1);
+		break;
+		case 1: 
+			glRotatef(-90.f, 0, 1, 0);
+			glRotatef(180.f, 1, 0, 0);
+		break;
+		case 3:
+			glRotatef(90, 1, 0, 0);
+		break;
+		case 5: 
+			glRotatef(180, 0, 0, 1);
+		break;
+	}
+}
+
+void validate_framebuffer_object()
+{                                                           
+	GLenum status;                                            
+	status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 
+	switch(status) 
+	{                                          
+		case GL_FRAMEBUFFER_COMPLETE_EXT:                       
+			//framebuffer OK, no error.
+			break;
+		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+			// frame buffer not OK: probably means unsupported depth buffer format
+			llerrs << "Framebuffer Incomplete Dimensions." << llendl;
+			break;
+		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
+			// frame buffer not OK: probably means unsupported depth buffer format
+			llerrs << "Framebuffer Incomplete Attachment." << llendl;
+			break; 
+		case GL_FRAMEBUFFER_UNSUPPORTED_EXT:                    
+			/* choose different formats */                        
+			llerrs << "Framebuffer unsupported." << llendl;
+			break;                                                
+		default:                                                
+			llerrs << "Unknown framebuffer status." << llendl;
+			break;
+	}
+}
+
+void LLPipeline::bindScreenToTexture() 
+{
+	
+}
+
+static LLFastTimer::DeclareTimer FTM_RENDER_BLOOM("Bloom");
+
+void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
+{
+	LLMemType mt_ru(LLMemType::MTYPE_PIPELINE_RENDER_BLOOM);
+	if (!(gPipeline.canUseVertexShaders() &&
+		sRenderGlow))
+	{
+		return;
+	}
+
+	LLVertexBuffer::unbind();
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+
+	assertInitialized();
+
+	if (gUseWireframe)
+	{
+		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+	}
+
+	U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
+
+	LLVector2 tc1(0,0);
+	LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
+				  (F32) gViewerWindow->getWorldViewHeightRaw()*2);
+
+	if (res_mod > 1)
+	{
+		tc2 /= (F32) res_mod;
+	}
+
+	gGL.setColorMask(true, true);
+		
+	LLFastTimer ftm(FTM_RENDER_BLOOM);
+	gGL.color4f(1,1,1,1);
+	LLGLDepthTest depth(GL_FALSE);
+	LLGLDisable blend(GL_BLEND);
+	LLGLDisable cull(GL_CULL_FACE);
+	
+	enableLightsFullbright(LLColor4(1,1,1,1));
+
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadIdentity();
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadIdentity();
+
+	LLGLDisable test(GL_ALPHA_TEST);
+
+	gGL.setColorMask(true, true);
+	glClearColor(0,0,0,0);
+
+	/*if (for_snapshot)
+	{
+		gGL.getTexUnit(0)->bind(&mGlow[1]);
+		{
+			//LLGLEnable stencil(GL_STENCIL_TEST);
+			//glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF);
+			//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+			//LLGLDisable blend(GL_BLEND);
+
+			// If the snapshot is constructed from tiles, calculate which
+			// tile we're in.
+
+			//from LLViewerCamera::setPerpsective
+			if (zoom_factor > 1.f)
+			{
+				int pos_y = subfield / llceil(zoom_factor);
+				int pos_x = subfield - (pos_y*llceil(zoom_factor));
+				F32 size = 1.f/zoom_factor;
+
+				tc1.set(pos_x*size, pos_y*size);
+				tc2 = tc1 + LLVector2(size,size);
+			}
+			else
+			{
+				tc2.set(1,1);
+			}
+			
+			LLGLEnable blend(GL_BLEND);
+			gGL.setSceneBlendType(LLRender::BT_ADD);
+			
+				
+			gGL.begin(LLRender::TRIANGLE_STRIP);
+			gGL.color4f(1,1,1,1);
+			gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+			gGL.vertex2f(-1,-1);
+			
+			gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+			gGL.vertex2f(-1,1);
+			
+			gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+			gGL.vertex2f(1,-1);
+			
+			gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
+			gGL.vertex2f(1,1);
+
+			gGL.end();
+
+			gGL.flush();
+			gGL.setSceneBlendType(LLRender::BT_ALPHA);
+		}
+
+		gGL.flush();
+		glMatrixMode(GL_PROJECTION);
+		glPopMatrix();
+		glMatrixMode(GL_MODELVIEW);
+		glPopMatrix();
+
+		return;
+	}*/
+	
+	{
+		{
+			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+			mGlow[2].bindTarget();
+			mGlow[2].clear();
+		}
+		
+		gGlowExtractProgram.bind();
+		F32 minLum = llmax(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f);
+		F32 maxAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha");		
+		F32 warmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount");	
+		LLVector3 lumWeights = gSavedSettings.getVector3("RenderGlowLumWeights");
+		LLVector3 warmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights");
+		gGlowExtractProgram.uniform1f("minLuminance", minLum);
+		gGlowExtractProgram.uniform1f("maxExtractAlpha", maxAlpha);
+		gGlowExtractProgram.uniform3f("lumWeights", lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
+		gGlowExtractProgram.uniform3f("warmthWeights", warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
+		gGlowExtractProgram.uniform1f("warmthAmount", warmthAmount);
+		LLGLEnable blend_on(GL_BLEND);
+		LLGLEnable test(GL_ALPHA_TEST);
+		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+		gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
+		
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);		
+		gGL.getTexUnit(0)->disable();
+		gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
+		gGL.getTexUnit(0)->bind(&mScreen);
+
+		gGL.color4f(1,1,1,1);
+		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+		gGL.begin(LLRender::TRIANGLE_STRIP);
+		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+		gGL.vertex2f(-1,-1);
+		
+		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+		gGL.vertex2f(-1,3);
+		
+		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+		gGL.vertex2f(3,-1);
+		
+		gGL.end();
+		
+		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+
+		mGlow[2].flush();
+	}
+
+	tc1.setVec(0,0);
+	tc2.setVec(2,2);
+
+	// power of two between 1 and 1024
+	U32 glowResPow = gSavedSettings.getS32("RenderGlowResolutionPow");
+	const U32 glow_res = llmax(1, 
+		llmin(1024, 1 << glowResPow));
+
+	S32 kernel = gSavedSettings.getS32("RenderGlowIterations")*2;
+	F32 delta = gSavedSettings.getF32("RenderGlowWidth") / glow_res;
+	// Use half the glow width if we have the res set to less than 9 so that it looks
+	// almost the same in either case.
+	if (glowResPow < 9)
+	{
+		delta *= 0.5f;
+	}
+	F32 strength = gSavedSettings.getF32("RenderGlowStrength");
+
+	gGlowProgram.bind();
+	gGlowProgram.uniform1f("glowStrength", strength);
+
+	for (S32 i = 0; i < kernel; i++)
+	{
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		{
+			LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+			mGlow[i%2].bindTarget();
+			mGlow[i%2].clear();
+		}
+			
+		if (i == 0)
+		{
+			gGL.getTexUnit(0)->bind(&mGlow[2]);
+		}
+		else
+		{
+			gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]);
+		}
+
+		if (i%2 == 0)
+		{
+			gGlowProgram.uniform2f("glowDelta", delta, 0);
+		}
+		else
+		{
+			gGlowProgram.uniform2f("glowDelta", 0, delta);
+		}
+
+		gGL.begin(LLRender::TRIANGLE_STRIP);
+		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+		gGL.vertex2f(-1,-1);
+		
+		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+		gGL.vertex2f(-1,3);
+		
+		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+		gGL.vertex2f(3,-1);
+		
+		gGL.end();
+		
+		mGlow[i%2].flush();
+	}
+
+	gGlowProgram.unbind();
+
+	if (LLRenderTarget::sUseFBO)
+	{
+		LLFastTimer ftm(FTM_RENDER_BLOOM_FBO);
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+	}
+
+	gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+	gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+	gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+	gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+	tc2.setVec((F32) gViewerWindow->getWorldViewWidthRaw(),
+			(F32) gViewerWindow->getWorldViewHeightRaw());
+
+	gGL.flush();
+	
+	LLVertexBuffer::unbind();
+
+	if (LLPipeline::sRenderDeferred && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+	{
+		LLGLDisable blend(GL_BLEND);
+		bindDeferredShader(gDeferredGIFinalProgram);
+
+		S32 channel = gDeferredGIFinalProgram.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+		if (channel > -1)
+		{
+			mScreen.bindTexture(0, channel);
+		}
+
+		gGL.begin(LLRender::TRIANGLE_STRIP);
+		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+		gGL.vertex2f(-1,-1);
+		
+		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+		gGL.vertex2f(-1,3);
+		
+		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+		gGL.vertex2f(3,-1);
+		
+		gGL.end();
+
+		unbindDeferredShader(gDeferredGIFinalProgram);
+	}
+	else
+	{
+
+		if (res_mod > 1)
+		{
+			tc2 /= (F32) res_mod;
+		}
+
+		U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
+		LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
+		buff->allocateBuffer(3,0,TRUE);
+
+		LLStrider<LLVector3> v;
+		LLStrider<LLVector2> uv1;
+		LLStrider<LLVector2> uv2;
+
+		buff->getVertexStrider(v);
+		buff->getTexCoord0Strider(uv1);
+		buff->getTexCoord1Strider(uv2);
+		
+		uv1[0] = LLVector2(0, 0);
+		uv1[1] = LLVector2(0, 2);
+		uv1[2] = LLVector2(2, 0);
+		
+		uv2[0] = LLVector2(0, 0);
+		uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
+		uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
+		
+		v[0] = LLVector3(-1,-1,0);
+		v[1] = LLVector3(-1,3,0);
+		v[2] = LLVector3(3,-1,0);
+				
+		buff->setBuffer(0);
+
+		LLGLDisable blend(GL_BLEND);
+
+		//tex unit 0
+		gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
+	
+		gGL.getTexUnit(0)->bind(&mGlow[1]);
+		gGL.getTexUnit(1)->activate();
+		gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE);
+
+
+		//tex unit 1
+		gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
+		
+		gGL.getTexUnit(1)->bind(&mScreen);
+		gGL.getTexUnit(1)->activate();
+		
+		LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+		
+		buff->setBuffer(mask);
+		buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
+		
+		gGL.getTexUnit(1)->disable();
+		gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+		gGL.getTexUnit(0)->activate();
+		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+		if (LLRenderTarget::sUseFBO)
+		{ //copy depth buffer from mScreen to framebuffer
+			LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 
+				0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+		}
+	}
+	
+
+	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+
+}
+
+static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred");
+
+void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post, U32 noise_map)
+{
+	LLFastTimer t(FTM_BIND_DEFERRED);
+
+	if (noise_map == 0xFFFFFFFF)
+	{
+		noise_map = mNoiseMap;
+	}
+
+	LLGLState::checkTextureChannels();
+
+	shader.bind();
+	S32 channel = 0;
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		mDeferredScreen.bindTexture(0,channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		mDeferredScreen.bindTexture(1, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		mDeferredScreen.bindTexture(2, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	if (gi_source)
+	{
+		BOOL has_gi = FALSE;
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			gi_source->bindTexture(0, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			gi_source->bindTexture(1, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			gi_source->bindTexture(2, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			gi_source->bindTexture(1, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			gi_source->bindTexture(3, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			last_gi_post->bindTexture(0, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			last_gi_post->bindTexture(2, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			last_gi_post->bindTexture(1, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			last_gi_post->bindTexture(3, channel);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+		}
+		
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
+		if (channel > -1)
+		{
+			has_gi = TRUE;
+			gGL.getTexUnit(channel)->bind(gi_source, TRUE);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+			stop_glerror();
+			
+			glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
+			glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
+
+			stop_glerror();
+		}
+
+		if (has_gi)
+		{
+			F32 range_x = llmin(mGIRange.mV[0], 1.f);
+			F32 range_y = llmin(mGIRange.mV[1], 1.f);
+
+			LLVector2 scale(range_x,range_y);
+
+			LLVector2 kern[25];
+
+			for (S32 i = 0; i < 5; ++i)
+			{
+				for (S32 j = 0; j < 5; ++j)
+				{
+					S32 idx = i*5+j;
+					kern[idx].mV[0] = (i-2)*0.5f;
+					kern[idx].mV[1] = (j-2)*0.5f;
+					kern[idx].scaleVec(scale);
+				}
+			}
+
+			shader.uniform2fv("gi_kern", 25, (F32*) kern);
+			shader.uniformMatrix4fv("gi_mat", 1, FALSE, mGIMatrix.m);
+			shader.uniformMatrix4fv("gi_mat_proj", 1, FALSE, mGIMatrixProj.m);
+			shader.uniformMatrix4fv("gi_inv_proj", 1, FALSE, mGIInvProj.m);
+			shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m);
+		}
+	}
+	
+	/*channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		mDeferredScreen.bindTexture(3, channel);
+	}*/
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+		stop_glerror();
+		
+		glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
+		glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
+
+		stop_glerror();
+
+		glh::matrix4f projection = glh_get_current_projection();
+		glh::matrix4f inv_proj = projection.inverse();
+		
+		shader.uniformMatrix4fv("inv_proj", 1, FALSE, inv_proj.m);
+		shader.uniform4f("viewport", (F32) gGLViewport[0],
+									(F32) gGLViewport[1],
+									(F32) gGLViewport[2],
+									(F32) gGLViewport[3]);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
+	if (channel > -1)
+	{
+		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC);
+	if (channel > -1)
+	{
+		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
+	}
+
+	stop_glerror();
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		mDeferredLight[light_index].bindTexture(0, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
+	if (channel > -1)
+	{
+		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_BLOOM);
+	if (channel > -1)
+	{
+		mGlow[1].bindTexture(0, channel);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		gi_source->bindTexture(0, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		mEdgeMap.bindTexture(0, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		mDeferredLight[1].bindTexture(0, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+	channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	if (channel > -1)
+	{
+		mDeferredLight[2].bindTexture(0, channel);
+		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+	}
+
+
+	stop_glerror();
+
+	for (U32 i = 0; i < 4; i++)
+	{
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE);
+		stop_glerror();
+		if (channel > -1)
+		{
+			stop_glerror();
+			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			stop_glerror();
+			
+			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+			stop_glerror();
+		}
+	}
+
+	for (U32 i = 4; i < 6; i++)
+	{
+		channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i);
+		stop_glerror();
+		if (channel > -1)
+		{
+			stop_glerror();
+			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			stop_glerror();
+			
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+			stop_glerror();
+		}
+	}
+
+	stop_glerror();
+
+	F32 mat[16*6];
+	for (U32 i = 0; i < 16; i++)
+	{
+		mat[i] = mSunShadowMatrix[0].m[i];
+		mat[i+16] = mSunShadowMatrix[1].m[i];
+		mat[i+32] = mSunShadowMatrix[2].m[i];
+		mat[i+48] = mSunShadowMatrix[3].m[i];
+		mat[i+64] = mSunShadowMatrix[4].m[i];
+		mat[i+80] = mSunShadowMatrix[5].m[i];
+	}
+
+	shader.uniformMatrix4fv("shadow_matrix[0]", 6, FALSE, mat);
+	shader.uniformMatrix4fv("shadow_matrix", 6, FALSE, mat);
+
+	stop_glerror();
+
+	channel = shader.enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+	if (channel > -1)
+	{
+		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+		if (cube_map)
+		{
+			cube_map->enable(channel);
+			cube_map->bind();
+			F64* m = gGLModelView;
+
+			
+			F32 mat[] = { m[0], m[1], m[2],
+						  m[4], m[5], m[6],
+						  m[8], m[9], m[10] };
+		
+			shader.uniform3fv("env_mat[0]", 3, mat);
+			shader.uniform3fv("env_mat", 3, mat);
+		}
+	}
+
+	shader.uniform4fv("shadow_clip", 1, mSunClipPlanes.mV);
+	shader.uniform1f("sun_wash", gSavedSettings.getF32("RenderDeferredSunWash"));
+	shader.uniform1f("shadow_noise", gSavedSettings.getF32("RenderShadowNoise"));
+	shader.uniform1f("blur_size", gSavedSettings.getF32("RenderShadowBlurSize"));
+
+	shader.uniform1f("ssao_radius", gSavedSettings.getF32("RenderSSAOScale"));
+	shader.uniform1f("ssao_max_radius", gSavedSettings.getU32("RenderSSAOMaxScale"));
+
+	F32 ssao_factor = gSavedSettings.getF32("RenderSSAOFactor");
+	shader.uniform1f("ssao_factor", ssao_factor);
+	shader.uniform1f("ssao_factor_inv", 1.0/ssao_factor);
+
+	LLVector3 ssao_effect = gSavedSettings.getVector3("RenderSSAOEffect");
+	F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0;
+	F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0;
+	// This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by
+	// value factor, and scales remainder by saturation factor
+	F32 ssao_effect_mat[] = {	matrix_diag, matrix_nondiag, matrix_nondiag,
+								matrix_nondiag, matrix_diag, matrix_nondiag,
+								matrix_nondiag, matrix_nondiag, matrix_diag};
+	shader.uniformMatrix3fv("ssao_effect_mat", 1, GL_FALSE, ssao_effect_mat);
+
+	F32 shadow_offset_error = 1.f + gSavedSettings.getF32("RenderShadowOffsetError") * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
+	F32 shadow_bias_error = 1.f + gSavedSettings.getF32("RenderShadowBiasError") * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
+
+	shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+	shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f);
+	shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")*shadow_offset_error);
+	shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")*shadow_bias_error);
+	shader.uniform1f ("spot_shadow_offset", gSavedSettings.getF32("RenderSpotShadowOffset"));
+	shader.uniform1f("spot_shadow_bias", gSavedSettings.getF32("RenderSpotShadowBias"));	
+
+	shader.uniform1f("lum_scale", gSavedSettings.getF32("RenderLuminanceScale"));
+	shader.uniform1f("sun_lum_scale", gSavedSettings.getF32("RenderSunLuminanceScale"));
+	shader.uniform1f("sun_lum_offset", gSavedSettings.getF32("RenderSunLuminanceOffset"));
+	shader.uniform1f("lum_lod", gSavedSettings.getF32("RenderLuminanceDetail"));
+	shader.uniform1f("gi_range", gSavedSettings.getF32("RenderGIRange"));
+	shader.uniform1f("gi_brightness", gSavedSettings.getF32("RenderGIBrightness"));
+	shader.uniform1f("gi_luminance", gSavedSettings.getF32("RenderGILuminance"));
+	shader.uniform1f("gi_edge_weight", gSavedSettings.getF32("RenderGIBlurEdgeWeight"));
+	shader.uniform1f("gi_blur_brightness", gSavedSettings.getF32("RenderGIBlurBrightness"));
+	shader.uniform1f("gi_sample_width", mGILightRadius);
+	shader.uniform1f("gi_noise", gSavedSettings.getF32("RenderGINoise"));
+	shader.uniform1f("gi_attenuation", gSavedSettings.getF32("RenderGIAttenuation"));
+	shader.uniform1f("gi_ambiance", gSavedSettings.getF32("RenderGIAmbiance"));
+	shader.uniform2f("shadow_res", mShadow[0].getWidth(), mShadow[0].getHeight());
+	shader.uniform2f("proj_shadow_res", mShadow[4].getWidth(), mShadow[4].getHeight());
+	shader.uniform1f("depth_cutoff", gSavedSettings.getF32("RenderEdgeDepthCutoff"));
+	shader.uniform1f("norm_cutoff", gSavedSettings.getF32("RenderEdgeNormCutoff"));
+
+	if (shader.getUniformLocation("norm_mat") >= 0)
+	{
+		glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
+		shader.uniformMatrix4fv("norm_mat", 1, FALSE, norm_mat.m);
+	}
+}
+
+static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
+static LLFastTimer::DeclareTimer FTM_GI_GATHER("Gather");
+static LLFastTimer::DeclareTimer FTM_SUN_SHADOW("Shadow Map");
+static LLFastTimer::DeclareTimer FTM_SOFTEN_SHADOW("Shadow Soften");
+static LLFastTimer::DeclareTimer FTM_EDGE_DETECTION("Find Edges");
+static LLFastTimer::DeclareTimer FTM_LOCAL_LIGHTS("Local Lights");
+static LLFastTimer::DeclareTimer FTM_ATMOSPHERICS("Atmospherics");
+static LLFastTimer::DeclareTimer FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
+static LLFastTimer::DeclareTimer FTM_PROJECTORS("Projectors");
+static LLFastTimer::DeclareTimer FTM_POST("Post");
+
+
+void LLPipeline::renderDeferredLighting()
+{
+	if (!sCull)
+	{
+		return;
+	}
+
+	{
+		LLFastTimer ftm(FTM_RENDER_DEFERRED);
+
+		LLViewerCamera* camera = LLViewerCamera::getInstance();
+		{
+			LLGLDepthTest depth(GL_TRUE);
+			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	
+		}
+
+		LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+
+		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+		{
+			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+		}
+
+		//ati doesn't seem to love actually using the stencil buffer on FBO's
+		LLGLEnable stencil(GL_STENCIL_TEST);
+		glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+		gGL.setColorMask(true, true);
+		
+		//draw a cube around every light
+		LLVertexBuffer::unbind();
+
+		LLGLEnable cull(GL_CULL_FACE);
+		LLGLEnable blend(GL_BLEND);
+
+		glh::matrix4f mat = glh_copy_matrix(gGLModelView);
+
+		F32 vert[] = 
+		{
+			-1,1,
+			-1,-3,
+			3,1,
+		};
+		glVertexPointer(2, GL_FLOAT, 0, vert);
+		glColor3f(1,1,1);
+
+		{
+			setupHWLights(NULL); //to set mSunDir;
+			LLVector4 dir(mSunDir, 0.f);
+			glh::vec4f tc(dir.mV);
+			mat.mult_matrix_vec(tc);
+			glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0);
+		}
+
+			glPushMatrix();
+			glLoadIdentity();
+			glMatrixMode(GL_PROJECTION);
+			glPushMatrix();
+			glLoadIdentity();
+
+			mDeferredLight[0].bindTarget();
+
+		if (gSavedSettings.getBOOL("RenderDeferredSSAO") || gSavedSettings.getS32("RenderShadowDetail") > 0)
+		{
+			{ //paint shadow/SSAO light map (direct lighting lightmap)
+				LLFastTimer ftm(FTM_SUN_SHADOW);
+				bindDeferredShader(gDeferredSunProgram, 0);
+
+				glClearColor(1,1,1,1);
+				mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT);
+				glClearColor(0,0,0,0);
+
+				glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+
+				const U32 slice = 32;
+				F32 offset[slice*3];
+				for (U32 i = 0; i < 4; i++)
+				{
+					for (U32 j = 0; j < 8; j++)
+					{
+						glh::vec3f v;
+						v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
+						v.normalize();
+						inv_trans.mult_matrix_vec(v);
+						v.normalize();
+						offset[(i*8+j)*3+0] = v.v[0];
+						offset[(i*8+j)*3+1] = v.v[2];
+						offset[(i*8+j)*3+2] = v.v[1];
+					}
+				}
+
+				gDeferredSunProgram.uniform3fv("offset", slice, offset);
+				gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
+				
+				{
+					LLGLDisable blend(GL_BLEND);
+					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+					stop_glerror();
+					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+					stop_glerror();
+				}
+				
+				unbindDeferredShader(gDeferredSunProgram);
+			}
+		}
+			else
+			{
+			glClearColor(1,1,1,1);
+				mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT);
+			glClearColor(0,0,0,0);
+			}
+
+			mDeferredLight[0].flush();
+
+		{ //global illumination specific block (still experimental)
+			if (gSavedSettings.getBOOL("RenderDeferredBlurLight") &&
+			    gSavedSettings.getBOOL("RenderDeferredGI"))
+			{
+				LLFastTimer ftm(FTM_EDGE_DETECTION);
+				//generate edge map
+				LLGLDisable blend(GL_BLEND);
+				LLGLDisable test(GL_ALPHA_TEST);
+				LLGLDepthTest depth(GL_FALSE);
+				LLGLDisable stencil(GL_STENCIL_TEST);
+
+				{
+					gDeferredEdgeProgram.bind();
+					mEdgeMap.bindTarget();
+					bindDeferredShader(gDeferredEdgeProgram);
+					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+					unbindDeferredShader(gDeferredEdgeProgram);
+					mEdgeMap.flush();
+				}
+			}
+
+			if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+			{
+				{ //get luminance map from previous frame's light map
+					LLGLEnable blend(GL_BLEND);
+					LLGLDisable test(GL_ALPHA_TEST);
+					LLGLDepthTest depth(GL_FALSE);
+					LLGLDisable stencil(GL_STENCIL_TEST);
+
+					//static F32 fade = 1.f;
+
+					{
+						gGL.setSceneBlendType(LLRender::BT_ALPHA);
+						gLuminanceGatherProgram.bind();
+						gLuminanceGatherProgram.uniform2f("screen_res", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
+						mLuminanceMap.bindTarget();
+						bindDeferredShader(gLuminanceGatherProgram);
+						glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+						unbindDeferredShader(gLuminanceGatherProgram);
+						mLuminanceMap.flush();
+						gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true);
+						gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
+						glGenerateMipmapEXT(GL_TEXTURE_2D);
+					}
+				}
+
+				{ //paint noisy GI map (bounce lighting lightmap)
+					LLFastTimer ftm(FTM_GI_TRACE);
+					LLGLDisable blend(GL_BLEND);
+					LLGLDepthTest depth(GL_FALSE);
+					LLGLDisable test(GL_ALPHA_TEST);
+
+					mGIMapPost[0].bindTarget();
+
+					bindDeferredShader(gDeferredGIProgram, 0, &mGIMap, 0, mTrueNoiseMap);
+					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+					unbindDeferredShader(gDeferredGIProgram);
+					mGIMapPost[0].flush();
+				}
+
+				U32 pass_count = 0;
+				if (gSavedSettings.getBOOL("RenderDeferredBlurLight"))
+				{
+					pass_count = llclamp(gSavedSettings.getU32("RenderGIBlurPasses"), (U32) 1, (U32) 128);
+				}
+
+				for (U32 i = 0; i < pass_count; ++i)
+				{ //gather/soften indirect lighting map
+					LLFastTimer ftm(FTM_GI_GATHER);
+					bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[0], NULL, mTrueNoiseMap);
+					F32 blur_size = gSavedSettings.getF32("RenderGIBlurSize")/((F32) i * gSavedSettings.getF32("RenderGIBlurIncrement")+1.f);
+					gDeferredPostGIProgram.uniform2f("delta", 1.f, 0.f);
+					gDeferredPostGIProgram.uniform1f("kern_scale", blur_size);
+					gDeferredPostGIProgram.uniform1f("gi_blur_brightness", gSavedSettings.getF32("RenderGIBlurBrightness"));
+				
+					mGIMapPost[1].bindTarget();
+					{
+						LLGLDisable blend(GL_BLEND);
+						LLGLDepthTest depth(GL_FALSE);
+						stop_glerror();
+						glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+						stop_glerror();
+					}
+					
+					mGIMapPost[1].flush();
+					unbindDeferredShader(gDeferredPostGIProgram);
+					bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[1], NULL, mTrueNoiseMap);
+					mGIMapPost[0].bindTarget();
+
+					gDeferredPostGIProgram.uniform2f("delta", 0.f, 1.f);
+
+					{
+						LLGLDisable blend(GL_BLEND);
+						LLGLDepthTest depth(GL_FALSE);
+						stop_glerror();
+						glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+						stop_glerror();
+					}
+					mGIMapPost[0].flush();
+					unbindDeferredShader(gDeferredPostGIProgram);
+				}
+			}
+		}
+
+		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
+			{ //soften direct lighting lightmap
+				LLFastTimer ftm(FTM_SOFTEN_SHADOW);
+				//blur lightmap
+				mDeferredLight[1].bindTarget();
+
+				glClearColor(1,1,1,1);
+				mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT);
+				glClearColor(0,0,0,0);
+				
+				bindDeferredShader(gDeferredBlurLightProgram);
+
+				LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian");
+				const U32 kern_length = 4;
+				F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize");
+				F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor");
+
+				// sample symmetrically with the middle sample falling exactly on 0.0
+				F32 x = 0.f;
+
+				LLVector3 gauss[32]; // xweight, yweight, offset
+
+				for (U32 i = 0; i < kern_length; i++)
+				{
+					gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+					gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+					gauss[i].mV[2] = x;
+					x += 1.f;
+				}
+
+				gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
+				gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor);
+				gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
+				gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
+				gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+			
+				{
+					LLGLDisable blend(GL_BLEND);
+					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+					stop_glerror();
+					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+					stop_glerror();
+				}
+				
+				mDeferredLight[1].flush();
+				unbindDeferredShader(gDeferredBlurLightProgram);
+
+				bindDeferredShader(gDeferredBlurLightProgram, 1);
+				mDeferredLight[0].bindTarget();
+
+				gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
+
+				{
+					LLGLDisable blend(GL_BLEND);
+					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+					stop_glerror();
+					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+					stop_glerror();
+				}
+				mDeferredLight[0].flush();
+				unbindDeferredShader(gDeferredBlurLightProgram);
+			}
+
+			stop_glerror();
+			glPopMatrix();
+			stop_glerror();
+			glMatrixMode(GL_MODELVIEW);
+			stop_glerror();
+			glPopMatrix();
+			stop_glerror();
+
+		//copy depth and stencil from deferred screen
+		//mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+		//					0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+		if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+		{
+			mDeferredLight[1].bindTarget();
+			// clear color buffer here (GI) - zeroing alpha (glow) is important or it will accumulate against sky
+			glClearColor(0,0,0,0);
+			mScreen.clear(GL_COLOR_BUFFER_BIT);
+		}
+		else
+		{
+			mScreen.bindTarget();
+			// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
+			glClearColor(0,0,0,0);
+			mScreen.clear(GL_COLOR_BUFFER_BIT);
+		}
+
+		if (gSavedSettings.getBOOL("RenderDeferredAtmospheric"))
+		{ //apply sunlight contribution 
+			LLFastTimer ftm(FTM_ATMOSPHERICS);
+			bindDeferredShader(gDeferredSoftenProgram, 0, &mGIMapPost[0]);	
+			{
+				LLGLDepthTest depth(GL_FALSE);
+				LLGLDisable blend(GL_BLEND);
+				LLGLDisable test(GL_ALPHA_TEST);
+
+				//full screen blit
+				glPushMatrix();
+				glLoadIdentity();
+				glMatrixMode(GL_PROJECTION);
+				glPushMatrix();
+				glLoadIdentity();
+
+				glVertexPointer(2, GL_FLOAT, 0, vert);
+				
+				glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+				
+				glPopMatrix();
+				glMatrixMode(GL_MODELVIEW);
+				glPopMatrix();
+			}
+
+			unbindDeferredShader(gDeferredSoftenProgram);
+		}
+
+		{ //render sky
+			LLGLDisable blend(GL_BLEND);
+			LLGLDisable stencil(GL_STENCIL_TEST);
+			gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+			gPipeline.pushRenderTypeMask();
+			
+			gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+										LLPipeline::RENDER_TYPE_CLOUDS,
+										LLPipeline::RENDER_TYPE_WL_SKY,
+										LLPipeline::END_RENDER_TYPES);
+								
+			
+			renderGeomPostDeferred(*LLViewerCamera::getInstance());
+			gPipeline.popRenderTypeMask();
+		}
+
+		BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights");
+		BOOL render_fullscreen = gSavedSettings.getBOOL("RenderDeferredFullscreenLights");
+		
+
+		if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+		{
+			mDeferredLight[1].flush();
+			mDeferredLight[2].bindTarget();
+			mDeferredLight[2].clear(GL_COLOR_BUFFER_BIT);
+		}
+
+		if (render_local || render_fullscreen)
+		{
+			gGL.setSceneBlendType(LLRender::BT_ADD);
+			std::list<LLVector4> fullscreen_lights;
+			LLDrawable::drawable_list_t spot_lights;
+			LLDrawable::drawable_list_t fullscreen_spot_lights;
+
+			for (U32 i = 0; i < 2; i++)
+			{
+				mTargetShadowSpotLight[i] = NULL;
+			}
+
+			std::list<LLVector4> light_colors;
+
+			F32 v[24];
+			glVertexPointer(3, GL_FLOAT, 0, v);
+			BOOL render_local = gSavedSettings.getBOOL("RenderDeferredLocalLights");
+
+			{
+				bindDeferredShader(gDeferredLightProgram);
+				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+				for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
+				{
+					LLDrawable* drawablep = *iter;
+					
+					LLVOVolume* volume = drawablep->getVOVolume();
+					if (!volume)
+					{
+						continue;
+					}
+
+					if (volume->isAttachment())
+					{
+						if (!sRenderAttachedLights)
+						{
+							continue;
+						}
+					}
+
+
+					LLVector3 center = drawablep->getPositionAgent();
+					F32* c = center.mV;
+					F32 s = volume->getLightRadius()*1.5f;
+
+					LLColor3 col = volume->getLightColor();
+					col *= volume->getLightIntensity();
+
+					if (col.magVecSquared() < 0.001f)
+					{
+						continue;
+					}
+
+					if (s <= 0.001f)
+					{
+						continue;
+					}
+
+					if (camera->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0)
+					{
+						continue;
+					}
+
+					sVisibleLightCount++;
+
+					glh::vec3f tc(c);
+					mat.mult_matrix_vec(tc);
+					
+					//vertex positions are encoded so the 3 bits of their vertex index 
+					//correspond to their axis facing, with bit position 3,2,1 matching
+					//axis facing x,y,z, bit set meaning positive facing, bit clear 
+					//meaning negative facing
+					v[0] = c[0]-s; v[1]  = c[1]-s; v[2]  = c[2]-s;  // 0 - 0000 
+					v[3] = c[0]-s; v[4]  = c[1]-s; v[5]  = c[2]+s;  // 1 - 0001
+					v[6] = c[0]-s; v[7]  = c[1]+s; v[8]  = c[2]-s;  // 2 - 0010
+					v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s;  // 3 - 0011
+																									   
+					v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
+					v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
+					v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
+					v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
+
+					if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
+						camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
+						camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
+						camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
+						camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
+						camera->getOrigin().mV[2] < c[2] - s - 0.2f)
+					{ //draw box if camera is outside box
+						if (render_local)
+						{
+							if (volume->isLightSpotlight())
+							{
+								drawablep->getVOVolume()->updateSpotLightPriority();
+								spot_lights.push_back(drawablep);
+								continue;
+							}
+							
+							LLFastTimer ftm(FTM_LOCAL_LIGHTS);
+							glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+							glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+							glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+								GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center));
+							stop_glerror();
+						}
+					}
+					else if (render_fullscreen)
+					{	
+						if (volume->isLightSpotlight())
+						{
+							drawablep->getVOVolume()->updateSpotLightPriority();
+							fullscreen_spot_lights.push_back(drawablep);
+							continue;
+						}
+
+						fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
+						light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
+					}
+				}
+				unbindDeferredShader(gDeferredLightProgram);
+			}
+
+			if (!spot_lights.empty())
+			{
+				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+				bindDeferredShader(gDeferredSpotLightProgram);
+
+				gDeferredSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+
+				for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
+				{
+					LLFastTimer ftm(FTM_PROJECTORS);
+					LLDrawable* drawablep = *iter;
+
+					LLVOVolume* volume = drawablep->getVOVolume();
+
+					LLVector3 center = drawablep->getPositionAgent();
+					F32* c = center.mV;
+					F32 s = volume->getLightRadius()*1.5f;
+
+					sVisibleLightCount++;
+
+					glh::vec3f tc(c);
+					mat.mult_matrix_vec(tc);
+					
+					setupSpotLight(gDeferredSpotLightProgram, drawablep);
+					
+					LLColor3 col = volume->getLightColor();
+					col *= volume->getLightIntensity();
+
+					//vertex positions are encoded so the 3 bits of their vertex index 
+					//correspond to their axis facing, with bit position 3,2,1 matching
+					//axis facing x,y,z, bit set meaning positive facing, bit clear 
+					//meaning negative facing
+					v[0] = c[0]-s; v[1]  = c[1]-s; v[2]  = c[2]-s;  // 0 - 0000 
+					v[3] = c[0]-s; v[4]  = c[1]-s; v[5]  = c[2]+s;  // 1 - 0001
+					v[6] = c[0]-s; v[7]  = c[1]+s; v[8]  = c[2]-s;  // 2 - 0010
+					v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s;  // 3 - 0011
+																									   
+					v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
+					v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
+					v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
+					v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
+
+					glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+					glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+					glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+							GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center));
+				}
+				gDeferredSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+				unbindDeferredShader(gDeferredSpotLightProgram);
+			}
+
+			{
+				bindDeferredShader(gDeferredMultiLightProgram);
+			
+				LLGLDepthTest depth(GL_FALSE);
+
+				//full screen blit
+				glPushMatrix();
+				glLoadIdentity();
+				glMatrixMode(GL_PROJECTION);
+				glPushMatrix();
+				glLoadIdentity();
+
+				U32 count = 0;
+
+				const U32 max_count = 8;
+				LLVector4 light[max_count];
+				LLVector4 col[max_count];
+
+				glVertexPointer(2, GL_FLOAT, 0, vert);
+
+				F32 far_z = 0.f;
+
+				while (!fullscreen_lights.empty())
+				{
+					LLFastTimer ftm(FTM_FULLSCREEN_LIGHTS);
+					light[count] = fullscreen_lights.front();
+					fullscreen_lights.pop_front();
+					col[count] = light_colors.front();
+					light_colors.pop_front();
+
+					far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
+
+					count++;
+					if (count == max_count || fullscreen_lights.empty())
+					{
+						gDeferredMultiLightProgram.uniform1i("light_count", count);
+						gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light);
+						gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light);
+						gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col);
+						gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col);
+						gDeferredMultiLightProgram.uniform1f("far_z", far_z);
+						far_z = 0.f;
+						count = 0;
+						glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+					}
+				}
+				
+				unbindDeferredShader(gDeferredMultiLightProgram);
+
+				bindDeferredShader(gDeferredMultiSpotLightProgram);
+
+				gDeferredMultiSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+
+				for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
+				{
+					LLFastTimer ftm(FTM_PROJECTORS);
+					LLDrawable* drawablep = *iter;
+					
+					LLVOVolume* volume = drawablep->getVOVolume();
+
+					LLVector3 center = drawablep->getPositionAgent();
+					F32* c = center.mV;
+					F32 s = volume->getLightRadius()*1.5f;
+
+					sVisibleLightCount++;
+
+					glh::vec3f tc(c);
+					mat.mult_matrix_vec(tc);
+					
+					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+
+					LLColor3 col = volume->getLightColor();
+					col *= volume->getLightIntensity();
+
+					glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+					glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+					glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+				}
+
+				gDeferredMultiSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+				unbindDeferredShader(gDeferredMultiSpotLightProgram);
+
+				glPopMatrix();
+				glMatrixMode(GL_MODELVIEW);
+				glPopMatrix();
+			}
+		}
+
+		gGL.setColorMask(true, true);
+
+		if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+		{
+			mDeferredLight[2].flush();
+
+			mScreen.bindTarget();
+			mScreen.clear(GL_COLOR_BUFFER_BIT);
+		
+			gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+			{ //mix various light maps (local, sun, gi)
+				LLFastTimer ftm(FTM_POST);
+				LLGLDisable blend(GL_BLEND);
+				LLGLDisable test(GL_ALPHA_TEST);
+				LLGLDepthTest depth(GL_FALSE);
+				LLGLDisable stencil(GL_STENCIL_TEST);
+			
+				bindDeferredShader(gDeferredPostProgram, 0, &mGIMapPost[0]);
+
+				gDeferredPostProgram.bind();
+
+				LLVertexBuffer::unbind();
+
+				glVertexPointer(2, GL_FLOAT, 0, vert);
+				glColor3f(1,1,1);
+
+				glPushMatrix();
+				glLoadIdentity();
+				glMatrixMode(GL_PROJECTION);
+				glPushMatrix();
+				glLoadIdentity();
+
+				glDrawArrays(GL_TRIANGLES, 0, 3);
+
+				glPopMatrix();
+				glMatrixMode(GL_MODELVIEW);
+				glPopMatrix();
+
+				unbindDeferredShader(gDeferredPostProgram);
+			}
+		}
+	}
+
+	{ //render non-deferred geometry (alpha, fullbright, glow)
+		LLGLDisable blend(GL_BLEND);
+		LLGLDisable stencil(GL_STENCIL_TEST);
+
+		pushRenderTypeMask();
+		andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
+						 LLPipeline::RENDER_TYPE_FULLBRIGHT,
+						 LLPipeline::RENDER_TYPE_VOLUME,
+						 LLPipeline::RENDER_TYPE_GLOW,
+						 LLPipeline::RENDER_TYPE_BUMP,
+						 LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+						 LLPipeline::RENDER_TYPE_PASS_ALPHA,
+						 LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+						 LLPipeline::RENDER_TYPE_PASS_BUMP,
+						 LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
+						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+						 LLPipeline::RENDER_TYPE_PASS_GLOW,
+						 LLPipeline::RENDER_TYPE_PASS_GRASS,
+						 LLPipeline::RENDER_TYPE_PASS_SHINY,
+						 LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
+						 LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
+						 LLPipeline::RENDER_TYPE_AVATAR,
+						 END_RENDER_TYPES);
+		
+		renderGeomPostDeferred(*LLViewerCamera::getInstance());
+		popRenderTypeMask();
+	}
+
+	{
+		//render highlights, etc.
+		renderHighlights();
+		mHighlightFaces.clear();
+
+		renderDebug();
+
+		LLVertexBuffer::unbind();
+
+		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+		{
+			// Render debugging beacons.
+			gObjectList.renderObjectBeacons();
+			gObjectList.resetObjectBeacons();
+		}
+	}
+
+	mScreen.flush();
+						
+}
+
+void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
+{
+	//construct frustum
+	LLVOVolume* volume = drawablep->getVOVolume();
+	LLVector3 params = volume->getSpotLightParams();
+
+	F32 fov = params.mV[0];
+	F32 focus = params.mV[1];
+
+	LLVector3 pos = drawablep->getPositionAgent();
+	LLQuaternion quat = volume->getRenderRotation();
+	LLVector3 scale = volume->getScale();
+	
+	//get near clip plane
+	LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+	at_axis *= quat;
+
+	LLVector3 np = pos+at_axis;
+	at_axis.normVec();
+
+	//get origin that has given fov for plane np, at_axis, and given scale
+	F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+	LLVector3 origin = np - at_axis*dist;
+
+	//matrix from volume space to agent space
+	LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
+
+	glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
+	glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
+
+	glh::matrix4f screen_to_light = light_to_screen.inverse();
+
+	F32 s = volume->getLightRadius()*1.5f;
+	F32 near_clip = dist;
+	F32 width = scale.mV[VX];
+	F32 height = scale.mV[VY];
+	F32 far_clip = s+dist-scale.mV[VZ];
+
+	F32 fovy = fov * RAD_TO_DEG;
+	F32 aspect = width/height;
+
+	glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+				0.f, 0.5f, 0.f, 0.5f,
+				0.f, 0.f, 0.5f, 0.5f,
+				0.f, 0.f, 0.f, 1.f);
+
+	glh::vec3f p1(0, 0, -(near_clip+0.01f));
+	glh::vec3f p2(0, 0, -(near_clip+1.f));
+
+	glh::vec3f screen_origin(0, 0, 0);
+
+	light_to_screen.mult_matrix_vec(p1);
+	light_to_screen.mult_matrix_vec(p2);
+	light_to_screen.mult_matrix_vec(screen_origin);
+
+	glh::vec3f n = p2-p1;
+	n.normalize();
+	
+	F32 proj_range = far_clip - near_clip;
+	glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip);
+	screen_to_light = trans * light_proj * screen_to_light;
+	shader.uniformMatrix4fv("proj_mat", 1, FALSE, screen_to_light.m);
+	shader.uniform1f("proj_near", near_clip);
+	shader.uniform3fv("proj_p", 1, p1.v);
+	shader.uniform3fv("proj_n", 1, n.v);
+	shader.uniform3fv("proj_origin", 1, screen_origin.v);
+	shader.uniform1f("proj_range", proj_range);
+	shader.uniform1f("proj_ambiance", params.mV[2]);
+	S32 s_idx = -1;
+
+	for (U32 i = 0; i < 2; i++)
+	{
+		if (mShadowSpotLight[i] == drawablep)
+		{
+			s_idx = i;
+		}
+	}
+
+	shader.uniform1i("proj_shadow_idx", s_idx);
+
+	if (s_idx >= 0)
+	{
+		shader.uniform1f("shadow_fade", 1.f-mSpotLightFade[s_idx]);
+	}
+	else
+	{
+		shader.uniform1f("shadow_fade", 1.f);
+	}
+
+	{
+		LLDrawable* potential = drawablep;
+		//determine if this is a good light for casting shadows
+		F32 m_pri = volume->getSpotLightPriority();
+
+		for (U32 i = 0; i < 2; i++)
+		{
+			F32 pri = 0.f;
+
+			if (mTargetShadowSpotLight[i].notNull())
+			{
+				pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();			
+			}
+
+			if (m_pri > pri)
+			{
+				LLDrawable* temp = mTargetShadowSpotLight[i];
+				mTargetShadowSpotLight[i] = potential;
+				potential = temp;
+				m_pri = pri;
+			}
+		}
+	}
+
+	LLViewerTexture* img = volume->getLightTexture();
+
+	S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION);
+
+	if (channel > -1 && img)
+	{
+		gGL.getTexUnit(channel)->bind(img);
+
+		F32 lod_range = logf(img->getWidth())/logf(2.f);
+
+		shader.uniform1f("proj_focus", focus);
+		shader.uniform1f("proj_lod", lod_range);
+		shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f));
+	}
+}
+
+void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
+{
+	stop_glerror();
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE);
+	shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIP);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_BLOOM);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS);
+
+	for (U32 i = 0; i < 4; i++)
+	{
+		if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1)
+		{
+			glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+		}
+	}
+
+	for (U32 i = 4; i < 6; i++)
+	{
+		if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1)
+		{
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+		}
+	}
+
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
+	shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC);
+
+	S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+	if (channel > -1)
+	{
+		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+		if (cube_map)
+		{
+			cube_map->disable();
+		}
+	}
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	gGL.getTexUnit(0)->activate();
+	shader.unbind();
+
+	LLGLState::checkTextureChannels();
+}
+
+inline float sgn(float a)
+{
+    if (a > 0.0F) return (1.0F);
+    if (a < 0.0F) return (-1.0F);
+    return (0.0F);
+}
+
+void LLPipeline::generateWaterReflection(LLCamera& camera_in)
+{	
+	if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
+	{
+		BOOL skip_avatar_update = FALSE;
+		if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK)
+		{
+			skip_avatar_update = TRUE;
+		}
+
+		if (!skip_avatar_update)
+		{
+			gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
+		}
+		LLVertexBuffer::unbind();
+
+		LLGLState::checkStates();
+		LLGLState::checkTextureChannels();
+		LLGLState::checkClientArrays();
+
+		LLCamera camera = camera_in;
+		camera.setFar(camera.getFar()*0.87654321f);
+		LLPipeline::sReflectionRender = TRUE;
+		S32 occlusion = LLPipeline::sUseOcclusion;
+
+		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
+		LLPipeline::sUseOcclusion = llmin(occlusion, 1);
+		
+		gPipeline.pushRenderTypeMask();
+
+		glh::matrix4f projection = glh_get_current_projection();
+		glh::matrix4f mat;
+
+		stop_glerror();
+		LLPlane plane;
+
+		F32 height = gAgent.getRegion()->getWaterHeight(); 
+		F32 to_clip = fabsf(camera.getOrigin().mV[2]-height);
+		F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by
+
+		//plane params
+		LLVector3 pnorm;
+		F32 pd;
+
+		S32 water_clip = 0;
+		if (!LLViewerCamera::getInstance()->cameraUnderWater())
+		{ //camera is above water, clip plane points up
+			pnorm.setVec(0,0,1);
+			pd = -height;
+			plane.setVec(pnorm, pd);
+			water_clip = -1;
+		}
+		else
+		{	//camera is below water, clip plane points down
+			pnorm = LLVector3(0,0,-1);
+			pd = height;
+			plane.setVec(pnorm, pd);
+			water_clip = 1;
+		}
+
+		if (!LLViewerCamera::getInstance()->cameraUnderWater())
+		{	//generate planar reflection map
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			glClearColor(0,0,0,0);
+			mWaterRef.bindTarget();
+			gGL.setColorMask(true, true);
+			mWaterRef.clear();
+			gGL.setColorMask(true, false);
+
+			mWaterRef.getViewport(gGLViewport);
+			
+			stop_glerror();
+
+			glPushMatrix();
+
+			mat.set_scale(glh::vec3f(1,1,-1));
+			mat.set_translate(glh::vec3f(0,0,height*2.f));
+			
+			glh::matrix4f current = glh_get_current_modelview();
+
+			mat = current * mat;
+
+			glh_set_current_modelview(mat);
+			glLoadMatrixf(mat.m);
+
+			LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
+
+			glh::matrix4f inv_mat = mat.inverse();
+
+			glh::vec3f origin(0,0,0);
+			inv_mat.mult_matrix_vec(origin);
+
+			camera.setOrigin(origin.v);
+
+			glCullFace(GL_FRONT);
+
+			static LLCullResult ref_result;
+		
+			if (LLDrawPoolWater::sNeedsDistortionUpdate)
+			{
+				//initial sky pass (no user clip plane)
+				{ //mask out everything but the sky
+					gPipeline.pushRenderTypeMask();
+					gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+												LLPipeline::RENDER_TYPE_WL_SKY,
+												LLPipeline::END_RENDER_TYPES);
+					static LLCullResult result;
+					updateCull(camera, result);
+					stateSort(camera, result);
+					andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+										LLPipeline::RENDER_TYPE_CLOUDS,
+										LLPipeline::RENDER_TYPE_WL_SKY,
+										LLPipeline::END_RENDER_TYPES);
+
+					renderGeom(camera, TRUE);
+					gPipeline.popRenderTypeMask();
+				}
+
+				gPipeline.pushRenderTypeMask();
+
+				clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
+									LLPipeline::RENDER_TYPE_VOIDWATER,
+									LLPipeline::RENDER_TYPE_GROUND,
+									LLPipeline::RENDER_TYPE_SKY,
+									LLPipeline::RENDER_TYPE_CLOUDS,
+									LLPipeline::END_RENDER_TYPES);	
+
+					S32 detail = gSavedSettings.getS32("RenderReflectionDetail");
+				if (detail > 0)
+				{ //mask out selected geometry based on reflection detail
+					if (detail < 4)
+					{
+						clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
+					if (detail < 3)
+					{
+							clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+						if (detail < 2)
+						{
+								clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
+							}
+						}
+					}
+
+					LLGLUserClipPlane clip_plane(plane, mat, projection);
+					LLGLDisable cull(GL_CULL_FACE);
+					updateCull(camera, ref_result, 1);
+					stateSort(camera, ref_result);
+				}
+				
+			if (LLDrawPoolWater::sNeedsDistortionUpdate)
+			{
+					if (gSavedSettings.getS32("RenderReflectionDetail") > 0)
+				{
+					gPipeline.grabReferences(ref_result);
+					LLGLUserClipPlane clip_plane(plane, mat, projection);
+					renderGeom(camera);
+				}
+			}	
+
+				gPipeline.popRenderTypeMask();
+			}	
+			glCullFace(GL_BACK);
+			glPopMatrix();
+			mWaterRef.flush();
+			glh_set_current_modelview(current);
+		}
+
+		camera.setOrigin(camera_in.getOrigin());
+		//render distortion map
+		static BOOL last_update = TRUE;
+		if (last_update)
+		{
+			camera.setFar(camera_in.getFar());
+			clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
+								LLPipeline::RENDER_TYPE_VOIDWATER,
+								LLPipeline::RENDER_TYPE_GROUND,
+								END_RENDER_TYPES);	
+			stop_glerror();
+
+			LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? FALSE : TRUE;
+
+			if (LLPipeline::sUnderWaterRender)
+			{
+				clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND,
+									LLPipeline::RENDER_TYPE_SKY,
+									LLPipeline::RENDER_TYPE_CLOUDS,
+									LLPipeline::RENDER_TYPE_WL_SKY,
+									END_RENDER_TYPES);		
+			}
+			LLViewerCamera::updateFrustumPlanes(camera);
+
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			LLColor4& col = LLDrawPoolWater::sWaterFogColor;
+			glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+			mWaterDis.bindTarget();
+			mWaterDis.getViewport(gGLViewport);
+			
+			if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
+			{
+				//clip out geometry on the same side of water as the camera
+				mat = glh_get_current_modelview();
+				LLGLUserClipPlane clip_plane(LLPlane(-pnorm, -(pd+pad)), mat, projection);
+				static LLCullResult result;
+				updateCull(camera, result, water_clip);
+				stateSort(camera, result);
+
+				gGL.setColorMask(true, true);
+				mWaterDis.clear();
+				gGL.setColorMask(true, false);
+
+				renderGeom(camera);
+			}
+
+			LLPipeline::sUnderWaterRender = FALSE;
+			mWaterDis.flush();
+		}
+		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
+
+		LLRenderTarget::unbindTarget();
+
+		LLPipeline::sReflectionRender = FALSE;
+
+		if (!LLRenderTarget::sUseFBO)
+		{
+			glClear(GL_DEPTH_BUFFER_BIT);
+		}
+		glClearColor(0.f, 0.f, 0.f, 0.f);
+		gViewerWindow->setup3DViewport();
+		gPipeline.popRenderTypeMask();
+		LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
+		LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
+		LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd));
+		LLPipeline::sUseOcclusion = occlusion;
+		
+		LLGLState::checkStates();
+		LLGLState::checkTextureChannels();
+		LLGLState::checkClientArrays();
+
+		if (!skip_avatar_update)
+		{
+			gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+		}
+	}
+}
+
+glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
+{
+	glh::matrix4f ret;
+
+	LLVector3 dirN;
+	LLVector3 upN;
+	LLVector3 lftN;
+
+	lftN = dir % up;
+	lftN.normVec();
+	
+	upN = lftN % dir;
+	upN.normVec();
+	
+	dirN = dir;
+	dirN.normVec();
+
+	ret.m[ 0] = lftN[0];
+	ret.m[ 1] = upN[0];
+	ret.m[ 2] = -dirN[0];
+	ret.m[ 3] = 0.f;
+
+	ret.m[ 4] = lftN[1];
+	ret.m[ 5] = upN[1];
+	ret.m[ 6] = -dirN[1];
+	ret.m[ 7] = 0.f;
+
+	ret.m[ 8] = lftN[2];
+	ret.m[ 9] = upN[2];
+	ret.m[10] = -dirN[2];
+	ret.m[11] = 0.f;
+
+	ret.m[12] = -(lftN*pos);
+	ret.m[13] = -(upN*pos);
+	ret.m[14] = dirN*pos;
+	ret.m[15] = 1.f;
+
+	return ret;
+}
+
+glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
+{
+	glh::matrix4f ret;
+	ret.m[ 0] = 2/(max[0]-min[0]);
+	ret.m[ 4] = 0;
+	ret.m[ 8] = 0;
+	ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]);
+
+	ret.m[ 1] = 0;
+	ret.m[ 5] = 2/(max[1]-min[1]);
+	ret.m[ 9] = 0;
+	ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]);
+
+	ret.m[ 2] = 0;
+	ret.m[ 6] = 0;
+	ret.m[10] = 2/(max[2]-min[2]);
+	ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]);
+
+	ret.m[ 3] = 0;
+	ret.m[ 7] = 0;
+	ret.m[11] = 0;
+	ret.m[15] = 1;
+
+	return ret;
+}
+
+static LLFastTimer::DeclareTimer FTM_SHADOW_RENDER("Render Shadows");
+static LLFastTimer::DeclareTimer FTM_SHADOW_ALPHA("Alpha Shadow");
+static LLFastTimer::DeclareTimer FTM_SHADOW_SIMPLE("Simple Shadow");
+
+void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion)
+{
+	LLFastTimer t(FTM_SHADOW_RENDER);
+
+	//clip out geometry on the same side of water as the camera
+	S32 occlude = LLPipeline::sUseOcclusion;
+	if (!use_occlusion)
+	{
+		LLPipeline::sUseOcclusion = 0;
+	}
+	LLPipeline::sShadowRender = TRUE;
+	
+	U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP, LLRenderPass::PASS_FULLBRIGHT_SHINY };
+	LLGLEnable cull(GL_CULL_FACE);
+
+	if (use_shader)
+	{
+		gDeferredShadowProgram.bind();
+	}
+
+	updateCull(shadow_cam, result);
+	stateSort(shadow_cam, result);
+	
+	//generate shadow map
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadMatrixf(proj.m);
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadMatrixf(view.m);
+
+	stop_glerror();
+	gGLLastMatrix = NULL;
+
+	{
+		LLGLDepthTest depth(GL_TRUE);
+		glClear(GL_DEPTH_BUFFER_BIT);
+	}
+
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			
+	glColor4f(1,1,1,1);
+	
+	stop_glerror();
+
+	gGL.setColorMask(false, false);
+	
+	//glCullFace(GL_FRONT);
+
+	{
+		LLFastTimer ftm(FTM_SHADOW_SIMPLE);
+		LLGLDisable test(GL_ALPHA_TEST);
+		gGL.getTexUnit(0)->disable();
+		for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
+		{
+			renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
+		}
+		gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+	}
+	
+	if (use_shader)
+	{
+		gDeferredShadowProgram.unbind();
+		renderGeomShadow(shadow_cam);
+		gDeferredShadowProgram.bind();
+	}
+	else
+	{
+		renderGeomShadow(shadow_cam);
+	}
+
+	{
+		LLFastTimer ftm(FTM_SHADOW_ALPHA);
+		LLGLEnable test(GL_ALPHA_TEST);
+		gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f);
+		renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE);
+		glColor4f(1,1,1,1);
+		renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
+		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+	}
+
+	//glCullFace(GL_BACK);
+
+	gGLLastMatrix = NULL;
+	glLoadMatrixd(gGLModelView);
+	doOcclusion(shadow_cam);
+
+	if (use_shader)
+	{
+		gDeferredShadowProgram.unbind();
+	}
+	
+	gGL.setColorMask(true, true);
+			
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+	gGLLastMatrix = NULL;
+
+	LLPipeline::sUseOcclusion = occlude;
+	LLPipeline::sShadowRender = FALSE;
+}
+
+static LLFastTimer::DeclareTimer FTM_VISIBLE_CLOUD("Visible Cloud");
+BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
+{
+	LLFastTimer t(FTM_VISIBLE_CLOUD);
+	//get point cloud of intersection of frust and min, max
+
+	if (getVisibleExtents(camera, min, max))
+	{
+		return FALSE;
+	}
+
+	//get set of planes on bounding box
+	std::vector<LLPlane> bp;
+		
+	bp.push_back(LLPlane(min, LLVector3(-1,0,0)));
+	bp.push_back(LLPlane(min, LLVector3(0,-1,0)));
+	bp.push_back(LLPlane(min, LLVector3(0,0,-1)));
+	bp.push_back(LLPlane(max, LLVector3(1,0,0)));
+	bp.push_back(LLPlane(max, LLVector3(0,1,0)));
+	bp.push_back(LLPlane(max, LLVector3(0,0,1)));
+	
+	//potential points
+	std::vector<LLVector3> pp;
+
+	//add corners of AABB
+	pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2]));
+	pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2]));
+	pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2]));
+	pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2]));
+	pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2]));
+	pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2]));
+	pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2]));
+	pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2]));
+
+	//add corners of camera frustum
+	for (U32 i = 0; i < 8; i++)
+	{
+		pp.push_back(camera.mAgentFrustum[i]);
+	}
+
+
+	//bounding box line segments
+	U32 bs[] = 
+			{
+		0,1,
+		1,3,
+		3,2,
+		2,0,
+
+		4,5,
+		5,7,
+		7,6,
+		6,4,
+
+		0,4,
+		1,5,
+		3,7,
+		2,6
+	};
+
+	for (U32 i = 0; i < 12; i++)
+	{ //for each line segment in bounding box
+		for (U32 j = 0; j < 6; j++) 
+		{ //for each plane in camera frustum
+			const LLPlane& cp = camera.getAgentPlane(j);
+			const LLVector3& v1 = pp[bs[i*2+0]];
+			const LLVector3& v2 = pp[bs[i*2+1]];
+			const LLVector3 n(cp.mV);
+
+			LLVector3 line = v1-v2;
+
+			F32 d1 = line*n;
+			F32 d2 = -cp.dist(v2);
+
+			F32 t = d2/d1;
+
+			if (t > 0.f && t < 1.f)
+			{
+				LLVector3 intersect = v2+line*t;
+				pp.push_back(intersect);
+			}
+			}
+		}
+			
+	//camera frustum line segments
+	const U32 fs[] =
+	{
+		0,1,
+		1,2,
+		2,3,
+		3,1,
+
+		4,5,
+		5,6,
+		6,7,
+		7,4,
+	
+		0,4,
+		1,5,
+		2,6,
+		3,7	
+	};
+
+	LLVector3 center = (max+min)*0.5f;
+	LLVector3 size = (max-min)*0.5f;
+	
+	for (U32 i = 0; i < 12; i++)
+	{
+		for (U32 j = 0; j < 6; ++j)
+		{
+			const LLVector3& v1 = pp[fs[i*2+0]+8];
+			const LLVector3& v2 = pp[fs[i*2+1]+8];
+			const LLPlane& cp = bp[j];
+			const LLVector3 n(cp.mV);
+
+			LLVector3 line = v1-v2;
+
+			F32 d1 = line*n;
+			F32 d2 = -cp.dist(v2);
+
+			F32 t = d2/d1;
+
+			if (t > 0.f && t < 1.f)
+			{
+				LLVector3 intersect = v2+line*t;
+				pp.push_back(intersect);
+			}	
+		}
+				}
+
+	LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f),
+		max+LLVector3(0.05f,0.05f,0.05f) };
+
+	for (U32 i = 0; i < pp.size(); ++i)
+	{
+		bool found = true;
+
+		const F32* p = pp[i].mV;
+			
+		for (U32 j = 0; j < 3; ++j)
+		{
+			if (p[j] < ext[0].mV[j] ||
+				p[j] > ext[1].mV[j])
+			{
+				found = false;
+				break;
+			}
+		}
+				
+		for (U32 j = 0; j < 6; ++j)
+		{
+			const LLPlane& cp = camera.getAgentPlane(j);
+			F32 dist = cp.dist(pp[i]);
+			if (dist > 0.05f) //point is above some plane, not contained
+					{
+				found = false;
+				break;
+						}
+					}
+
+					if (found)
+					{
+			fp.push_back(pp[i]);
+		}
+	}
+	
+	if (fp.empty())
+	{
+		return FALSE;
+	}
+	
+	return TRUE;
+}
+
+void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<LLVector3>& vpc)
+{
+	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) < 3)
+	{
+		return;
+	}
+
+	LLVector3 up;
+
+	//LLGLEnable depth_clamp(GL_DEPTH_CLAMP_NV);
+
+	if (lightDir.mV[2] > 0.5f)
+	{
+		up = LLVector3(1,0,0);
+	}
+	else
+	{
+		up = LLVector3(0, 0, 1);
+	}
+
+	
+	F32 gi_range = gSavedSettings.getF32("RenderGIRange");
+
+	U32 res = mGIMap.getWidth();
+
+	F32 atten = llmax(gSavedSettings.getF32("RenderGIAttenuation"), 0.001f);
+
+	//set radius to range at which distance attenuation of incoming photons is near 0
+
+	F32 lrad = sqrtf(1.f/(atten*0.01f));
+
+	F32 lrange = lrad+gi_range*0.5f;
+
+	LLVector3 pad(lrange,lrange,lrange);
+
+	glh::matrix4f view = look(LLVector3(128.f,128.f,128.f), lightDir, up);
+
+	LLVector3 cp = camera.getOrigin()+camera.getAtAxis()*(gi_range*0.5f);
+
+	glh::vec3f scp(cp.mV);
+	view.mult_matrix_vec(scp);
+	cp.setVec(scp.v);
+
+	F32 pix_width = lrange/(res*0.5f);
+
+	//move cp to the nearest pix_width
+	for (U32 i = 0; i < 3; i++)
+	{
+		cp.mV[i] = llround(cp.mV[i], pix_width);
+	}
+	
+	LLVector3 min = cp-pad;
+	LLVector3 max = cp+pad;
+	
+	//set mGIRange to range in tc space[0,1] that covers texture block of intersecting lights around a point
+	mGIRange.mV[0] = (max.mV[0]-min.mV[0])/res;
+	mGIRange.mV[1] = (max.mV[1]-min.mV[1])/res;
+	mGILightRadius = lrad/lrange*0.5f;
+
+	glh::matrix4f proj = gl_ortho(min.mV[0], max.mV[0],
+								min.mV[1], max.mV[1],
+								-max.mV[2], -min.mV[2]);
+
+	LLCamera sun_cam = camera;
+
+	glh::matrix4f eye_view = glh_get_current_modelview();
+	
+	//get eye space to camera space matrix
+	mGIMatrix = view*eye_view.inverse();
+	mGINormalMatrix = mGIMatrix.inverse().transpose();
+	mGIInvProj = proj.inverse();
+	mGIMatrixProj = proj*mGIMatrix;
+
+	//translate and scale to [0,1]
+	glh::matrix4f trans(.5f, 0.f, 0.f, .5f,
+						0.f, 0.5f, 0.f, 0.5f,
+						0.f, 0.f, 0.5f, 0.5f,
+						0.f, 0.f, 0.f, 1.f);
+
+	mGIMatrixProj = trans*mGIMatrixProj;
+
+	glh_set_current_modelview(view);
+	glh_set_current_projection(proj);
+
+	LLViewerCamera::updateFrustumPlanes(sun_cam, TRUE, FALSE, TRUE);
+
+	sun_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
+	static LLCullResult result;
+
+	pushRenderTypeMask();
+
+	andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
+								 LLPipeline::RENDER_TYPE_FULLBRIGHT,
+								 LLPipeline::RENDER_TYPE_BUMP,
+								 LLPipeline::RENDER_TYPE_VOLUME,
+								 LLPipeline::RENDER_TYPE_TREE, 
+								 LLPipeline::RENDER_TYPE_TERRAIN,
+								 LLPipeline::RENDER_TYPE_WATER,
+								 LLPipeline::RENDER_TYPE_VOIDWATER,
+								 LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,
+								 LLPipeline::RENDER_TYPE_AVATAR,
+								 LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+								 LLPipeline::RENDER_TYPE_PASS_BUMP,
+								 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+								 LLPipeline::RENDER_TYPE_PASS_SHINY,
+								 END_RENDER_TYPES);
+
+
+	
+	S32 occlude = LLPipeline::sUseOcclusion;
+	//LLPipeline::sUseOcclusion = 0;
+	LLPipeline::sShadowRender = TRUE;
+	
+	//only render large objects into GI map
+	sMinRenderSize = gSavedSettings.getF32("RenderGIMinRenderSize");
+	
+	LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_GI_SOURCE;
+	mGIMap.bindTarget();
+	
+	F64 last_modelview[16];
+	F64 last_projection[16];
+	for (U32 i = 0; i < 16; i++)
+	{
+		last_modelview[i] = gGLLastModelView[i];
+		last_projection[i] = gGLLastProjection[i];
+		gGLLastModelView[i] = mGIModelview.m[i];
+		gGLLastProjection[i] = mGIProjection.m[i];
+	}
+
+	sun_cam.setOrigin(0.f, 0.f, 0.f);
+	updateCull(sun_cam, result);
+	stateSort(sun_cam, result);
+	
+	for (U32 i = 0; i < 16; i++)
+	{
+		gGLLastModelView[i] = last_modelview[i];
+		gGLLastProjection[i] = last_projection[i];
+	}
+
+	mGIProjection = proj;
+	mGIModelview = view;
+
+	LLGLEnable cull(GL_CULL_FACE);
+
+	//generate GI map
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	glLoadMatrixf(proj.m);
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glLoadMatrixf(view.m);
+
+	stop_glerror();
+	gGLLastMatrix = NULL;
+
+	mGIMap.clear();
+
+	{
+		//LLGLEnable enable(GL_DEPTH_CLAMP_NV);
+		renderGeomDeferred(camera);
+	}
+
+	mGIMap.flush();
+	
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+	gGLLastMatrix = NULL;
+
+	LLPipeline::sUseOcclusion = occlude;
+	LLPipeline::sShadowRender = FALSE;
+	sMinRenderSize = 0.f;
+
+	popRenderTypeMask();
+
+}
+
+void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade)
+{
+	if (obj && obj->getVolume())
+	{
+		for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter)
+		{
+			renderHighlight(*iter, fade);
+		}
+
+		LLDrawable* drawable = obj->mDrawable;
+		if (drawable)
+		{
+			for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+			{
+				LLFace* face = drawable->getFace(i);
+				if (face)
+				{
+					face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade));
+				}
+			}
+		}
+	}
+}
+
+void LLPipeline::generateHighlight(LLCamera& camera)
+{
+	//render highlighted object as white into offscreen render target
+	if (mHighlightObject.notNull())
+	{
+		mHighlightSet.insert(HighlightItem(mHighlightObject));
+	}
+	
+	if (!mHighlightSet.empty())
+	{
+		F32 transition = gFrameIntervalSeconds/gSavedSettings.getF32("RenderHighlightFadeTime");
+
+		LLGLDisable test(GL_ALPHA_TEST);
+		LLGLDepthTest depth(GL_FALSE);
+		mHighlight.bindTarget();
+		disableLights();
+		gGL.setColorMask(true, true);
+		mHighlight.clear();
+
+		gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
+		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); )
+		{
+			std::set<HighlightItem>::iterator cur_iter = iter++;
+
+			if (cur_iter->mItem.isNull())
+			{
+				mHighlightSet.erase(cur_iter);
+				continue;
+			}
+
+			if (cur_iter->mItem == mHighlightObject)
+			{
+				cur_iter->incrFade(transition); 
+			}
+			else
+			{
+				cur_iter->incrFade(-transition);
+				if (cur_iter->mFade <= 0.f)
+				{
+					mHighlightSet.erase(cur_iter);
+					continue;
+				}
+			}
+
+			renderHighlight(cur_iter->mItem->getVObj(), cur_iter->mFade);
+		}
+
+		mHighlight.flush();
+		gGL.setColorMask(true, false);
+		gViewerWindow->setup3DViewport();
+	}
+}
+
+
+void LLPipeline::generateSunShadow(LLCamera& camera)
+{
+	if (!sRenderDeferred || gSavedSettings.getS32("RenderShadowDetail") <= 0)
+	{
+		return;
+	}
+
+	F64 last_modelview[16];
+	F64 last_projection[16];
+	for (U32 i = 0; i < 16; i++)
+	{ //store last_modelview of world camera
+		last_modelview[i] = gGLLastModelView[i];
+		last_projection[i] = gGLLastProjection[i];
+	}
+
+	pushRenderTypeMask();
+	andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE,
+					LLPipeline::RENDER_TYPE_ALPHA,
+					LLPipeline::RENDER_TYPE_GRASS,
+					LLPipeline::RENDER_TYPE_FULLBRIGHT,
+					LLPipeline::RENDER_TYPE_BUMP,
+					LLPipeline::RENDER_TYPE_VOLUME,
+					LLPipeline::RENDER_TYPE_AVATAR,
+					LLPipeline::RENDER_TYPE_TREE, 
+					LLPipeline::RENDER_TYPE_TERRAIN,
+					LLPipeline::RENDER_TYPE_WATER,
+					LLPipeline::RENDER_TYPE_VOIDWATER,
+					LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,
+					LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+					LLPipeline::RENDER_TYPE_PASS_BUMP,
+					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+					LLPipeline::RENDER_TYPE_PASS_SHINY,
+					LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+					END_RENDER_TYPES);
+
+	gGL.setColorMask(false, false);
+
+	//get sun view matrix
+	
+	//store current projection/modelview matrix
+	glh::matrix4f saved_proj = glh_get_current_projection();
+	glh::matrix4f saved_view = glh_get_current_modelview();
+	glh::matrix4f inv_view = saved_view.inverse();
+
+	glh::matrix4f view[6];
+	glh::matrix4f proj[6];
+	
+	//clip contains parallel split distances for 3 splits
+	LLVector3 clip = gSavedSettings.getVector3("RenderShadowClipPlanes");
+
+	//F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
+
+	//far clip on last split is minimum of camera view distance and 128
+	mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
+
+	clip = gSavedSettings.getVector3("RenderShadowOrthoClipPlanes");
+	mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
+
+	//currently used for amount to extrude frusta corners for constructing shadow frusta
+	LLVector3 n = gSavedSettings.getVector3("RenderShadowNearDist");
+	//F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
+
+	LLVector3 lightDir = -mSunDir;
+	lightDir.normVec();
+
+	glh::vec3f light_dir(lightDir.mV);
+
+	//create light space camera matrix
+	
+	LLVector3 at = lightDir;
+
+	LLVector3 up = camera.getAtAxis();
+
+	if (fabsf(up*lightDir) > 0.75f)
+	{
+		up = camera.getUpAxis();
+	}
+
+	/*LLVector3 left = up%at;
+	up = at%left;*/
+
+	up.normVec();
+	at.normVec();
+	
+	
+	LLCamera main_camera = camera;
+	
+	F32 near_clip = 0.f;
+	{
+		//get visible point cloud
+		std::vector<LLVector3> fp;
+
+		main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum);
+		
+		LLVector3 min,max;
+		getVisiblePointCloud(main_camera,min,max,fp);
+
+		if (fp.empty())
+		{
+			if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
+			{
+				mShadowCamera[0] = main_camera;
+				mShadowExtents[0][0] = min;
+				mShadowExtents[0][1] = max;
+
+				mShadowFrustPoints[0].clear();
+				mShadowFrustPoints[1].clear();
+				mShadowFrustPoints[2].clear();
+				mShadowFrustPoints[3].clear();
+			}
+			popRenderTypeMask();
+			return;
+		}
+
+		generateGI(camera, lightDir, fp);
+
+		//get good split distances for frustum
+		for (U32 i = 0; i < fp.size(); ++i)
+		{
+			glh::vec3f v(fp[i].mV);
+			saved_view.mult_matrix_vec(v);
+			fp[i].setVec(v.v);
+		}
+
+		min = fp[0];
+		max = fp[0];
+
+		//get camera space bounding box
+		for (U32 i = 1; i < fp.size(); ++i)
+		{
+			update_min_max(min, max, fp[i]);
+		}
+
+		near_clip = -max.mV[2];
+		F32 far_clip = -min.mV[2]*2.f;
+
+		far_clip = llmin(far_clip, 128.f);
+		far_clip = llmin(far_clip, camera.getFar());
+
+		F32 range = far_clip-near_clip;
+
+		LLVector3 split_exp = gSavedSettings.getVector3("RenderShadowSplitExponent");
+
+		F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) );
+		
+		da = powf(da, split_exp.mV[2]);
+
+
+		F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da;
+
+
+		for (U32 i = 0; i < 4; ++i)
+		{
+			F32 x = (F32)(i+1)/4.f;
+			x = powf(x, sxp);
+			mSunClipPlanes.mV[i] = near_clip+range*x;
+		}
+	}
+
+	// convenience array of 4 near clip plane distances
+	F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
+	
+	for (S32 j = 0; j < 4; j++)
+	{
+		if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
+		{
+			mShadowFrustPoints[j].clear();
+		}
+
+		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j;
+
+		//restore render matrices
+		glh_set_current_modelview(saved_view);
+		glh_set_current_projection(saved_proj);
+
+		LLVector3 eye = camera.getOrigin();
+
+		//camera used for shadow cull/render
+		LLCamera shadow_cam;
+		
+		//create world space camera frustum for this split
+		shadow_cam = camera;
+		shadow_cam.setFar(16.f);
+	
+		LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+		LLVector3* frust = shadow_cam.mAgentFrustum;
+
+		LLVector3 pn = shadow_cam.getAtAxis();
+		
+		LLVector3 min, max;
+
+		//construct 8 corners of split frustum section
+		for (U32 i = 0; i < 4; i++)
+		{
+			LLVector3 delta = frust[i+4]-eye;
+			delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f;
+			delta.normVec();
+			F32 dp = delta*pn;
+			frust[i] = eye + (delta*dist[j]*0.95f)/dp;
+			frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp;
+		}
+						
+		shadow_cam.calcAgentFrustumPlanes(frust);
+		shadow_cam.mFrustumCornerDist = 0.f;
+		
+		if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+		{
+			mShadowCamera[j] = shadow_cam;
+		}
+
+		std::vector<LLVector3> fp;
+
+		if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir))
+		{
+			//no possible shadow receivers
+			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+			{
+				mShadowExtents[j][0] = LLVector3();
+				mShadowExtents[j][1] = LLVector3();
+				mShadowCamera[j+4] = shadow_cam;
+			}
+
+			mShadow[j].bindTarget();
+			{
+				LLGLDepthTest depth(GL_TRUE);
+				mShadow[j].clear();
+			}
+			mShadow[j].flush();
+
+			mShadowError.mV[j] = 0.f;
+			mShadowFOV.mV[j] = 0.f;
+
+			continue;
+		}
+
+		if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+		{
+			mShadowExtents[j][0] = min;
+			mShadowExtents[j][1] = max;
+			mShadowFrustPoints[j] = fp;
+		}
+				
+
+		//find a good origin for shadow projection
+		LLVector3 origin;
+
+		//get a temporary view projection
+		view[j] = look(camera.getOrigin(), lightDir, -up);
+
+		std::vector<LLVector3> wpf;
+
+		for (U32 i = 0; i < fp.size(); i++)
+		{
+			glh::vec3f p = glh::vec3f(fp[i].mV);
+			view[j].mult_matrix_vec(p);
+			wpf.push_back(LLVector3(p.v));
+		}
+
+		min = wpf[0];
+		max = wpf[0];
+
+		for (U32 i = 0; i < fp.size(); ++i)
+		{ //get AABB in camera space
+			update_min_max(min, max, wpf[i]);
+		}
+
+		// Construct a perspective transform with perspective along y-axis that contains
+		// points in wpf
+		//Known:
+		// - far clip plane
+		// - near clip plane
+		// - points in frustum
+		//Find:
+		// - origin
+
+		//get some "interesting" points of reference
+		LLVector3 center = (min+max)*0.5f;
+		LLVector3 size = (max-min)*0.5f;
+		LLVector3 near_center = center;
+		near_center.mV[1] += size.mV[1]*2.f;
+		
+		
+		//put all points in wpf in quadrant 0, reletive to center of min/max
+		//get the best fit line using least squares
+		F32 bfm = 0.f;
+		F32 bfb = 0.f;
+
+		for (U32 i = 0; i < wpf.size(); ++i)
+		{
+			wpf[i] -= center;
+			wpf[i].mV[0] = fabsf(wpf[i].mV[0]);
+			wpf[i].mV[2] = fabsf(wpf[i].mV[2]);
+		}
+
+		if (!wpf.empty())
+		{ 
+			F32 sx = 0.f;
+			F32 sx2 = 0.f;
+			F32 sy = 0.f;
+			F32 sxy = 0.f;
+			
+			for (U32 i = 0; i < wpf.size(); ++i)
+			{		
+				sx += wpf[i].mV[0];
+				sx2 += wpf[i].mV[0]*wpf[i].mV[0];
+				sy += wpf[i].mV[1];
+				sxy += wpf[i].mV[0]*wpf[i].mV[1]; 
+			}
+
+			bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2);
+			bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2);
+		}
+		
+		{
+			// best fit line is y=bfm*x+bfb
+		
+			//find point that is furthest to the right of line
+			F32 off_x = -1.f;
+			LLVector3 lp;
+
+			for (U32 i = 0; i < wpf.size(); ++i)
+			{
+				//y = bfm*x+bfb
+				//x = (y-bfb)/bfm
+				F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+
+				lx = wpf[i].mV[0]-lx;
+				
+				if (off_x < lx)
+				{
+					off_x = lx;
+					lp = wpf[i];
+				}
+			}
+
+			//get line with slope bfm through lp
+			// bfb = y-bfm*x
+			bfb = lp.mV[1]-bfm*lp.mV[0];
+
+			//calculate error
+			mShadowError.mV[j] = 0.f;
+
+			for (U32 i = 0; i < wpf.size(); ++i)
+			{
+				F32 lx = (wpf[i].mV[1]-bfb)/bfm;
+				mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx);
+			}
+
+			mShadowError.mV[j] /= wpf.size();
+			mShadowError.mV[j] /= size.mV[0];
+
+			if (mShadowError.mV[j] > gSavedSettings.getF32("RenderShadowErrorCutoff"))
+			{ //just use ortho projection
+				mShadowFOV.mV[j] = -1.f;
+				origin.clearVec();
+				proj[j] = gl_ortho(min.mV[0], max.mV[0],
+									min.mV[1], max.mV[1],
+									-max.mV[2], -min.mV[2]);
+			}
+			else
+			{
+				//origin is where line x = 0;
+				origin.setVec(0,bfb,0);
+
+				F32 fovz = 1.f;
+				F32 fovx = 1.f;
+				
+				LLVector3 zp;
+				LLVector3 xp;
+
+				for (U32 i = 0; i < wpf.size(); ++i)
+				{
+					LLVector3 atz = wpf[i]-origin;
+					atz.mV[0] = 0.f;
+					atz.normVec();
+					if (fovz > -atz.mV[1])
+					{
+						zp = wpf[i];
+						fovz = -atz.mV[1];
+					}
+					
+					LLVector3 atx = wpf[i]-origin;
+					atx.mV[2] = 0.f;
+					atx.normVec();
+					if (fovx > -atx.mV[1])
+					{
+						fovx = -atx.mV[1];
+						xp = wpf[i];
+					}
+				}
+
+				fovx = acos(fovx);
+				fovz = acos(fovz);
+
+				F32 cutoff = llmin(gSavedSettings.getF32("RenderShadowFOVCutoff"), 1.4f);
+				
+				mShadowFOV.mV[j] = fovx;
+				
+				if (fovx < cutoff && fovz > cutoff)
+				{
+					//x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff
+					F32 d = zp.mV[2]/tan(cutoff);
+					F32 ny = zp.mV[1] + fabsf(d);
+
+					origin.mV[1] = ny;
+
+					fovz = 1.f;
+					fovx = 1.f;
+
+					for (U32 i = 0; i < wpf.size(); ++i)
+					{
+						LLVector3 atz = wpf[i]-origin;
+						atz.mV[0] = 0.f;
+						atz.normVec();
+						fovz = llmin(fovz, -atz.mV[1]);
+
+						LLVector3 atx = wpf[i]-origin;
+						atx.mV[2] = 0.f;
+						atx.normVec();
+						fovx = llmin(fovx, -atx.mV[1]);
+					}
+
+					fovx = acos(fovx);
+					fovz = acos(fovz);
+
+					if (fovx > cutoff || llround(fovz, 0.01f) > cutoff)
+					{
+					//	llerrs << "WTF?" << llendl;
+					}
+
+					mShadowFOV.mV[j] = cutoff;
+				}
+
+				
+				origin += center;
+			
+				F32 ynear = -(max.mV[1]-origin.mV[1]);
+				F32 yfar = -(min.mV[1]-origin.mV[1]);
+				
+				if (ynear < 0.1f) //keep a sensible near clip plane
+				{
+					F32 diff = 0.1f-ynear;
+					origin.mV[1] += diff;
+					ynear += diff;
+					yfar += diff;
+				}
+								
+				if (fovx > cutoff)
+				{ //just use ortho projection
+					origin.clearVec();
+					mShadowError.mV[j] = -1.f;
+					proj[j] = gl_ortho(min.mV[0], max.mV[0],
+							min.mV[1], max.mV[1],
+							-max.mV[2], -min.mV[2]);
+				}
+				else
+				{
+					//get perspective projection
+					view[j] = view[j].inverse();
+
+					glh::vec3f origin_agent(origin.mV);
+					
+					//translate view to origin
+					view[j].mult_matrix_vec(origin_agent);
+
+					eye = LLVector3(origin_agent.v);
+
+					if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+					{
+						mShadowFrustOrigin[j] = eye;
+					}
+				
+					view[j] = look(LLVector3(origin_agent.v), lightDir, -up);
+
+					F32 fx = 1.f/tanf(fovx);
+					F32 fz = 1.f/tanf(fovz);
+
+					proj[j] = glh::matrix4f(-fx, 0, 0, 0,
+											0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar),
+											0, 0, -fz, 0,
+											0, -1.f, 0, 0);
+				}
+			}
+		}
+
+		shadow_cam.setFar(128.f);
+		shadow_cam.setOriginAndLookAt(eye, up, center);
+
+		shadow_cam.setOrigin(0,0,0);
+
+		glh_set_current_modelview(view[j]);
+		glh_set_current_projection(proj[j]);
+
+		LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+		shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
+
+		//translate and scale to from [-1, 1] to [0, 1]
+		glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+						0.f, 0.5f, 0.f, 0.5f,
+						0.f, 0.f, 0.5f, 0.5f,
+						0.f, 0.f, 0.f, 1.f);
+
+		glh_set_current_modelview(view[j]);
+		glh_set_current_projection(proj[j]);
+
+		for (U32 i = 0; i < 16; i++)
+		{
+			gGLLastModelView[i] = mShadowModelview[j].m[i];
+			gGLLastProjection[i] = mShadowProjection[j].m[i];
+		}
+
+		mShadowModelview[j] = view[j];
+		mShadowProjection[j] = proj[j];
+
+	
+		mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
+		
+		stop_glerror();
+
+		mShadow[j].bindTarget();
+		mShadow[j].getViewport(gGLViewport);
+
+		{
+			static LLCullResult result[4];
+
+			//LLGLEnable enable(GL_DEPTH_CLAMP_NV);
+			renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE);
+		}
+
+		mShadow[j].flush();
+ 
+		if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+		{
+			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+			mShadowCamera[j+4] = shadow_cam;
+		}
+	}
+
+	
+	//hack to disable projector shadows 
+	static bool clear = true;
+	bool gen_shadow = gSavedSettings.getS32("RenderShadowDetail") > 1;
+
+	if (gen_shadow)
+	{
+		clear = true;
+	F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f);
+
+	//update shadow targets
+	for (U32 i = 0; i < 2; i++)
+	{ //for each current shadow
+		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i;
+
+		if (mShadowSpotLight[i].notNull() && 
+			(mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+			mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+		{ //keep this spotlight
+			mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
+		}
+		else
+		{ //fade out this light
+			mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
+			
+			if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+			{ //faded out, grab one of the pending spots (whichever one isn't already taken)
+				if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
+				{
+					mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+				}
+				else
+				{
+					mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+				}
+			}
+		}
+	}
+
+	for (S32 i = 0; i < 2; i++)
+	{
+		glh_set_current_modelview(saved_view);
+		glh_set_current_projection(saved_proj);
+
+		if (mShadowSpotLight[i].isNull())
+		{
+			continue;
+		}
+
+		LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
+
+		if (!volume)
+		{
+			mShadowSpotLight[i] = NULL;
+			continue;
+		}
+
+		LLDrawable* drawable = mShadowSpotLight[i];
+
+		LLVector3 params = volume->getSpotLightParams();
+		F32 fov = params.mV[0];
+
+		//get agent->light space matrix (modelview)
+		LLVector3 center = drawable->getPositionAgent();
+		LLQuaternion quat = volume->getRenderRotation();
+
+		//get near clip plane
+		LLVector3 scale = volume->getScale();
+		LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
+		at_axis *= quat;
+
+		LLVector3 np = center+at_axis;
+		at_axis.normVec();
+
+		//get origin that has given fov for plane np, at_axis, and given scale
+		F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+
+		LLVector3 origin = np - at_axis*dist;
+
+		LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+
+		view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
+
+		view[i+4] = view[i+4].inverse();
+
+		//get perspective matrix
+		F32 near_clip = dist+0.01f;
+		F32 width = scale.mV[VX];
+		F32 height = scale.mV[VY];
+		F32 far_clip = dist+volume->getLightRadius()*1.5f;
+
+		F32 fovy = fov * RAD_TO_DEG;
+		F32 aspect = width/height;
+		
+		proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
+
+		//translate and scale to from [-1, 1] to [0, 1]
+		glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+						0.f, 0.5f, 0.f, 0.5f,
+						0.f, 0.f, 0.5f, 0.5f,
+						0.f, 0.f, 0.f, 1.f);
+
+		glh_set_current_modelview(view[i+4]);
+		glh_set_current_projection(proj[i+4]);
+
+		mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
+		
+		for (U32 j = 0; j < 16; j++)
+		{
+			gGLLastModelView[j] = mShadowModelview[i+4].m[j];
+			gGLLastProjection[j] = mShadowProjection[i+4].m[j];
+		}
+
+		mShadowModelview[i+4] = view[i+4];
+		mShadowProjection[i+4] = proj[i+4];
+
+		LLCamera shadow_cam = camera;
+		shadow_cam.setFar(far_clip);
+		shadow_cam.setOrigin(origin);
+
+		LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+		stop_glerror();
+
+		mShadow[i+4].bindTarget();
+		mShadow[i+4].getViewport(gGLViewport);
+
+		static LLCullResult result[2];
+
+		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4;
+
+		renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE);
+
+		mShadow[i+4].flush();
+ 	}
+	}
+	else
+	{
+		if (clear)
+		{
+			clear = false;
+			for (U32 i = 4; i < 6; i++)
+			{
+				mShadow[i].bindTarget();
+				mShadow[i].clear();
+				mShadow[i].flush();
+			}
+		}
+	}
+
+	if (!gSavedSettings.getBOOL("CameraOffset"))
+	{
+		glh_set_current_modelview(saved_view);
+		glh_set_current_projection(saved_proj);
+	}
+	else
+	{
+		glh_set_current_modelview(view[1]);
+		glh_set_current_projection(proj[1]);
+		glLoadMatrixf(view[1].m);
+		glMatrixMode(GL_PROJECTION);
+		glLoadMatrixf(proj[1].m);
+		glMatrixMode(GL_MODELVIEW);
+	}
+	gGL.setColorMask(true, false);
+
+	for (U32 i = 0; i < 16; i++)
+	{
+		gGLLastModelView[i] = last_modelview[i];
+		gGLLastProjection[i] = last_projection[i];
+	}
+
+	popRenderTypeMask();
+}
+
+void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
+{
+	for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+	{
+		LLSpatialGroup* group = *i;
+		if (!group->isDead() &&
+			(!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
+			gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) &&
+			group->mDrawMap.find(type) != group->mDrawMap.end())
+		{
+			pass->renderGroup(group,type,mask,texture);
+		}
+	}
+}
+
+void LLPipeline::generateImpostor(LLVOAvatar* avatar)
+{
+	LLMemType mt_gi(LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR);
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+
+	static LLCullResult result;
+	result.clear();
+	grabReferences(result);
+	
+	if (!avatar || !avatar->mDrawable)
+	{
+		return;
+	}
+
+	assertInitialized();
+
+	BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID());
+
+	pushRenderTypeMask();
+	
+	if (muted)
+	{
+		andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+	}
+	else
+	{
+		andRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME,
+						LLPipeline::RENDER_TYPE_AVATAR,
+						LLPipeline::RENDER_TYPE_BUMP,
+						LLPipeline::RENDER_TYPE_GRASS,
+						LLPipeline::RENDER_TYPE_SIMPLE,
+						LLPipeline::RENDER_TYPE_FULLBRIGHT,
+						LLPipeline::RENDER_TYPE_ALPHA, 
+						LLPipeline::RENDER_TYPE_INVISIBLE,
+						LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+						LLPipeline::RENDER_TYPE_PASS_ALPHA,
+						LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+						LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+						LLPipeline::RENDER_TYPE_PASS_SHINY,
+						LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
+						LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
+						END_RENDER_TYPES);
+	}
+	
+	S32 occlusion = sUseOcclusion;
+	sUseOcclusion = 0;
+	sReflectionRender = sRenderDeferred ? FALSE : TRUE;
+	sShadowRender = TRUE;
+	sImpostorRender = TRUE;
+
+	LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
+	markVisible(avatar->mDrawable, *viewer_camera);
+	LLVOAvatar::sUseImpostors = FALSE;
+
+	LLVOAvatar::attachment_map_t::iterator iter;
+	for (iter = avatar->mAttachmentPoints.begin();
+		iter != avatar->mAttachmentPoints.end();
+		++iter)
+	{
+		LLViewerJointAttachment *attachment = iter->second;
+		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+			 attachment_iter != attachment->mAttachedObjects.end();
+			 ++attachment_iter)
+		{
+			if (LLViewerObject* attached_object = (*attachment_iter))
+			{
+				markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
+			}
+		}
+	}
+
+	stateSort(*LLViewerCamera::getInstance(), result);
+	
+	const LLVector3* ext = avatar->mDrawable->getSpatialExtents();
+	LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
+
+	LLCamera camera = *viewer_camera;
+
+	camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis());
+	
+	LLVector2 tdim;
+
+	LLVector3 half_height = (ext[1]-ext[0])*0.5f;
+
+	LLVector3 left = camera.getLeftAxis();
+	left *= left;
+	left.normalize();
+
+	LLVector3 up = camera.getUpAxis();
+	up *= up;
+	up.normalize();
+
+	tdim.mV[0] = fabsf(half_height * left);
+	tdim.mV[1] = fabsf(half_height * up);
+
+	glMatrixMode(GL_PROJECTION);
+	glPushMatrix();
+	//glh::matrix4f ortho = gl_ortho(-tdim.mV[0], tdim.mV[0], -tdim.mV[1], tdim.mV[1], 1.0, 256.0);
+	F32 distance = (pos-camera.getOrigin()).length();
+	F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
+	F32 aspect = tdim.mV[0]/tdim.mV[1]; //128.f/256.f;
+	glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
+	glh_set_current_projection(persp);
+	glLoadMatrixf(persp.m);
+
+	glMatrixMode(GL_MODELVIEW);
+	glPushMatrix();
+	glh::matrix4f mat;
+	camera.getOpenGLTransform(mat.m);
+
+	mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
+
+	glLoadMatrixf(mat.m);
+	glh_set_current_modelview(mat);
+
+	glClearColor(0.0f,0.0f,0.0f,0.0f);
+	gGL.setColorMask(true, true);
+	glStencilMask(0xFFFFFFFF);
+	glClearStencil(0);
+
+	// get the number of pixels per angle
+	F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView());
+
+	//get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing)
+	U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512);
+	U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512);
+
+	if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
+		resY != avatar->mImpostor.getHeight())
+	{
+		avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE);
+		
+		if (LLPipeline::sRenderDeferred)
+		{
+			addDeferredAttachments(avatar->mImpostor);
+		}
+		
+		gGL.getTexUnit(0)->bind(&avatar->mImpostor);
+		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	}
+
+	LLGLEnable stencil(GL_STENCIL_TEST);
+	glStencilMask(0xFFFFFFFF);
+	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+	{
+		LLGLEnable scissor(GL_SCISSOR_TEST);
+		glScissor(0, 0, resX, resY);
+		avatar->mImpostor.bindTarget();
+		avatar->mImpostor.clear();
+	}
+	
+	if (LLPipeline::sRenderDeferred)
+	{
+		stop_glerror();
+		renderGeomDeferred(camera);
+		renderGeomPostDeferred(camera);
+	}
+	else
+	{
+		renderGeom(camera);
+	}
+	
+	glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+	glStencilFunc(GL_EQUAL, 1, 0xFFFFFF);
+
+	{ //create alpha mask based on stencil buffer (grey out if muted)
+		LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f;
+		LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f;
+
+		if (LLPipeline::sRenderDeferred)
+		{
+			GLuint buff = GL_COLOR_ATTACHMENT0_EXT;
+			glDrawBuffersARB(1, &buff);
+		}
+
+		LLGLEnable blend(muted ? 0 : GL_BLEND);
+
+		if (muted)
+		{
+			gGL.setColorMask(true, true);
+		}
+		else
+		{
+			gGL.setColorMask(false, true);
+		}
+		
+		gGL.setSceneBlendType(LLRender::BT_ADD);
+		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+		LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+
+		gGL.color4f(1,1,1,1);
+		gGL.color4ub(64,64,64,255);
+		gGL.begin(LLRender::QUADS);
+		gGL.vertex3fv((pos+left-up).mV);
+		gGL.vertex3fv((pos-left-up).mV);
+		gGL.vertex3fv((pos-left+up).mV);
+		gGL.vertex3fv((pos+left+up).mV);
+		gGL.end();
+		gGL.flush();
+
+		gGL.setSceneBlendType(LLRender::BT_ALPHA);
+	}
+
+
+	avatar->mImpostor.flush();
+
+	avatar->setImpostorDim(tdim);
+
+	LLVOAvatar::sUseImpostors = TRUE;
+	sUseOcclusion = occlusion;
+	sReflectionRender = FALSE;
+	sImpostorRender = FALSE;
+	sShadowRender = FALSE;
+	popRenderTypeMask();
+
+	glMatrixMode(GL_PROJECTION);
+	glPopMatrix();
+	glMatrixMode(GL_MODELVIEW);
+	glPopMatrix();
+
+	avatar->mNeedsImpostorUpdate = FALSE;
+	avatar->cacheImpostorValues();
+
+	LLVertexBuffer::unbind();
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+}
+
+BOOL LLPipeline::hasRenderBatches(const U32 type) const
+{
+	return sCull->getRenderMapSize(type) > 0;
+}
+
+LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type)
+{
+	return sCull->beginRenderMap(type);
+}
+
+LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type)
+{
+	return sCull->endRenderMap(type);
+}
+
+LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups()
+{
+	return sCull->beginAlphaGroups();
+}
+
+LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
+{
+	return sCull->endAlphaGroups();
+}
+
+BOOL LLPipeline::hasRenderType(const U32 type) const
+{
+    // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render"
+    // We then need to test that value here and return FALSE to prevent attachment to render (in mouselook for instance)
+    // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to FALSE explicitely
+	return (type == 0 ? FALSE : mRenderTypeEnabled[type]);
+}
+
+void LLPipeline::setRenderTypeMask(U32 type, ...)
+{
+	va_list args;
+
+	va_start(args, type);
+	while (type < END_RENDER_TYPES)
+	{
+		mRenderTypeEnabled[type] = TRUE;
+		type = va_arg(args, U32);
+	}
+	va_end(args);
+
+	if (type > END_RENDER_TYPES)
+	{
+		llerrs << "Invalid render type." << llendl;
+	}
+}
+
+BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const
+{
+	va_list args;
+
+	va_start(args, type);
+	while (type < END_RENDER_TYPES)
+	{
+		if (mRenderTypeEnabled[type])
+		{
+			return TRUE;
+		}
+		type = va_arg(args, U32);
+	}
+	va_end(args);
+
+	if (type > END_RENDER_TYPES)
+	{
+		llerrs << "Invalid render type." << llendl;
+	}
+
+	return FALSE;
+}
+
+void LLPipeline::pushRenderTypeMask()
+{
+	std::string cur_mask;
+	cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled));
+	mRenderTypeEnableStack.push(cur_mask);
+}
+
+void LLPipeline::popRenderTypeMask()
+{
+	if (mRenderTypeEnableStack.empty())
+	{
+		llerrs << "Depleted render type stack." << llendl;
+	}
+
+	memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled));
+	mRenderTypeEnableStack.pop();
+}
+
+void LLPipeline::andRenderTypeMask(U32 type, ...)
+{
+	va_list args;
+
+	BOOL tmp[NUM_RENDER_TYPES];
+	for (U32 i = 0; i < NUM_RENDER_TYPES; ++i)
+	{
+		tmp[i] = FALSE;
+	}
+
+	va_start(args, type);
+	while (type < END_RENDER_TYPES)
+	{
+		if (mRenderTypeEnabled[type]) 
+		{
+			tmp[type] = TRUE;
+		}
+
+		type = va_arg(args, U32);
+	}
+	va_end(args);
+
+	if (type > END_RENDER_TYPES)
+	{
+		llerrs << "Invalid render type." << llendl;
+	}
+
+	for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i)
+	{
+		mRenderTypeEnabled[i] = tmp[i];
+	}
+
+}
+
+void LLPipeline::clearRenderTypeMask(U32 type, ...)
+{
+	va_list args;
+
+	va_start(args, type);
+	while (type < END_RENDER_TYPES)
+	{
+		mRenderTypeEnabled[type] = FALSE;
+		
+		type = va_arg(args, U32);
+	}
+	va_end(args);
+
+	if (type > END_RENDER_TYPES)
+	{
+		llerrs << "Invalid render type." << llendl;
+	}
+}
+
+
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 43431ea7c1c255a3151a3faf27a9e14f86b4de7c..1a00416b2a487a0e903f9058f8435c5c8b1fb4ca 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -76,7 +76,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
      follows="all"
      height="383"
      layout="topleft"
-     left="5"
+     left="3"
      name="tabs"
      tab_group="1"
      tab_min_width="70"
@@ -84,7 +84,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
      tab_position="top"
      top_pad="10"
      halign="center"
-     width="317">
+     width="319">
      	<panel
          background_opaque="true"
        background_visible="true"
@@ -106,20 +106,20 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 			 left="3"
 			 mouse_opaque="false"
 			 name="Net Map"
-			 width="307"
+			 width="305"
 			 height="140"
-			 top="0"/>
+			 top="5"/>
 			<avatar_list
              allow_select="true"
              follows="top|left|bottom|right"
-             height="216"
+             height="211"
              ignore_online_status="true"
              layout="topleft"
              left="3"
              multi_select="true"
              name="avatar_list"
              top="145"
-             width="307" />
+             width="306" />
             <panel
              background_visible="true"
              follows="left|right|bottom"
@@ -165,7 +165,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
              layout="topleft"
              left_pad="1"
              name="dummy_icon"
-             width="241"
+             width="243"
              />
             </panel>
         </panel>
@@ -251,7 +251,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 				   top_pad="1"
 				   left="0"
 				   name="bottom_panel"
-				   width="305">
+				   width="308">
 				      <layout_panel
 				       auto_resize="false"
 				       height="25"
@@ -300,7 +300,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 				       layout="topleft"
 				       name="dummy_panel"
 				       user_resize="false"
-				       width="212">
+				       width="210">
 				          <icon
 				           follows="bottom|left|right"
 				           height="25"
@@ -309,7 +309,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
 				           left="0"
 				           top="0"
 				           name="dummy_icon"
-				           width="211" />
+				           width="210" />
 				      </layout_panel>
 				      <layout_panel
 				       auto_resize="false"
@@ -471,7 +471,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
              	 layout="topleft"
              	 left_pad="1"
              	 name="dummy_icon"
-             	 width="209"
+             	 width="212"
              />
             </panel>
         </panel>
@@ -506,7 +506,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
              height="27"
              label="bottom_panel"
              layout="topleft"
-             left="0"
+             left="3"
              name="bottom_panel"
              top_pad="0"
              width="313">
@@ -544,7 +544,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
              	 layout="topleft"
              	 left_pad="1"
              	 name="dummy_icon"
-             	 width="241"
+             	 width="244"
              />
             </panel>
         </panel>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 483c9515db146f25ab2529015d9d65ec46a8144d..e08c815218a15b9605eb5514d9e6c76e9bba17d2 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1,975 +1,975 @@
-#!/usr/bin/env python
-"""\
-@file viewer_manifest.py
-@author Ryan Williams
-@brief Description of all installer viewer files, and methods for packaging
-       them into installers for all supported platforms.
-
-$LicenseInfo:firstyear=2006&license=viewerlgpl$
-Second Life Viewer Source Code
-Copyright (C) 2006-2011, Linden Research, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation;
-version 2.1 of the License only.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
-$/LicenseInfo$
-"""
-import sys
-import os.path
-import re
-import tarfile
-import time
-viewer_dir = os.path.dirname(__file__)
-# add llmanifest library to our path so we don't have to muck with PYTHONPATH
-sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util'))
-from llmanifest import LLManifest, main, proper_windows_path, path_ancestors
-
-class ViewerManifest(LLManifest):
-    def is_packaging_viewer(self):
-        # Some commands, files will only be included
-        # if we are packaging the viewer on windows.
-        # This manifest is also used to copy
-        # files during the build (see copy_w_viewer_manifest
-        # and copy_l_viewer_manifest targets)
-        return 'package' in self.args['actions']
-    
-    def construct(self):
-        super(ViewerManifest, self).construct()
-        self.exclude("*.svn*")
-        self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg")
-        self.path(src="../../etc/message.xml", dst="app_settings/message.xml")
-
-        if self.is_packaging_viewer():
-            if self.prefix(src="app_settings"):
-                self.exclude("logcontrol.xml")
-                self.exclude("logcontrol-dev.xml")
-                self.path("*.pem")
-                self.path("*.ini")
-                self.path("*.xml")
-                self.path("*.db2")
-
-                # include the entire shaders directory recursively
-                self.path("shaders")
-                # ... and the entire windlight directory
-                self.path("windlight")
-                self.end_prefix("app_settings")
-
-            if self.prefix(src="character"):
-                self.path("*.llm")
-                self.path("*.xml")
-                self.path("*.tga")
-                self.end_prefix("character")
-
-            # Include our fonts
-            if self.prefix(src="fonts"):
-                self.path("*.ttf")
-                self.path("*.txt")
-                self.end_prefix("fonts")
-
-            # skins
-            if self.prefix(src="skins"):
-                    self.path("paths.xml")
-                    # include the entire textures directory recursively
-                    if self.prefix(src="*/textures"):
-                            self.path("*/*.tga")
-                            self.path("*/*.j2c")
-                            self.path("*/*.jpg")
-                            self.path("*/*.png")
-                            self.path("*.tga")
-                            self.path("*.j2c")
-                            self.path("*.jpg")
-                            self.path("*.png")
-                            self.path("textures.xml")
-                            self.end_prefix("*/textures")
-                    self.path("*/xui/*/*.xml")
-                    self.path("*/xui/*/widgets/*.xml")
-                    self.path("*/*.xml")
-
-                    # Local HTML files (e.g. loading screen)
-                    if self.prefix(src="*/html"):
-                            self.path("*.png")
-                            self.path("*/*/*.html")
-                            self.path("*/*/*.gif")
-                            self.end_prefix("*/html")
-                    self.end_prefix("skins")
-
-            # local_assets dir (for pre-cached textures)
-            if self.prefix(src="local_assets"):
-                self.path("*.j2c")
-                self.path("*.tga")
-                self.end_prefix("local_assets")
-
-            # Files in the newview/ directory
-            self.path("gpu_table.txt")
-
-    def login_channel(self):
-        """Channel reported for login and upgrade purposes ONLY;
-        used for A/B testing"""
-        # NOTE: Do not return the normal channel if login_channel
-        # is not specified, as some code may branch depending on
-        # whether or not this is present
-        return self.args.get('login_channel')
-
-    def grid(self):
-        return self.args['grid']
-    def channel(self):
-        return self.args['channel']
-    def channel_unique(self):
-        return self.channel().replace("Second Life", "").strip()
-    def channel_oneword(self):
-        return "".join(self.channel_unique().split())
-    def channel_lowerword(self):
-        return self.channel_oneword().lower()
-
-    def flags_list(self):
-        """ Convenience function that returns the command-line flags
-        for the grid"""
-
-        # Set command line flags relating to the target grid
-        grid_flags = ''
-        if not self.default_grid():
-            grid_flags = "--grid %(grid)s "\
-                         "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\
-                           {'grid':self.grid()}
-
-        # set command line flags for channel
-        channel_flags = ''
-        if self.login_channel() and self.login_channel() != self.channel():
-            # Report a special channel during login, but use default
-            channel_flags = '--channel "%s"' % (self.login_channel())
-        elif not self.default_channel():
-            channel_flags = '--channel "%s"' % self.channel()
-
-        # Deal with settings 
-        setting_flags = ''
-        if not self.default_channel() or not self.default_grid():
-            if self.default_grid():
-                setting_flags = '--settings settings_%s.xml'\
-                                % self.channel_lowerword()
-            else:
-                setting_flags = '--settings settings_%s_%s.xml'\
-                                % (self.grid(), self.channel_lowerword())
-                                                
-        return " ".join((channel_flags, grid_flags, setting_flags)).strip()
-
-
-class WindowsManifest(ViewerManifest):
-    def final_exe(self):
-        if self.default_channel():
-            if self.default_grid():
-                return "SecondLife.exe"
-            else:
-                return "SecondLifePreview.exe"
-        else:
-            return ''.join(self.channel().split()) + '.exe'
-
-    def test_msvcrt_and_copy_action(self, src, dst):
-        # This is used to test a dll manifest.
-        # It is used as a temporary override during the construct method
-        from test_win32_manifest import test_assembly_binding
-        if src and (os.path.exists(src) or os.path.islink(src)):
-            # ensure that destination path exists
-            self.cmakedirs(os.path.dirname(dst))
-            self.created_paths.append(dst)
-            if not os.path.isdir(src):
-                if(self.args['configuration'].lower() == 'debug'):
-                    test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "8.0.50727.4053")
-                else:
-                    test_assembly_binding(src, "Microsoft.VC80.CRT", "8.0.50727.4053")
-                self.ccopy(src,dst)
-            else:
-                raise Exception("Directories are not supported by test_CRT_and_copy_action()")
-        else:
-            print "Doesn't exist:", src
-
-    def test_for_no_msvcrt_manifest_and_copy_action(self, src, dst):
-        # This is used to test that no manifest for the msvcrt exists.
-        # It is used as a temporary override during the construct method
-        from test_win32_manifest import test_assembly_binding
-        from test_win32_manifest import NoManifestException, NoMatchingAssemblyException
-        if src and (os.path.exists(src) or os.path.islink(src)):
-            # ensure that destination path exists
-            self.cmakedirs(os.path.dirname(dst))
-            self.created_paths.append(dst)
-            if not os.path.isdir(src):
-                try:
-                    if(self.args['configuration'].lower() == 'debug'):
-                        test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "")
-                    else:
-                        test_assembly_binding(src, "Microsoft.VC80.CRT", "")
-                    raise Exception("Unknown condition")
-                except NoManifestException, err:
-                    pass
-                except NoMatchingAssemblyException, err:
-                    pass
-                    
-                self.ccopy(src,dst)
-            else:
-                raise Exception("Directories are not supported by test_CRT_and_copy_action()")
-        else:
-            print "Doesn't exist:", src
-        
-    def enable_crt_manifest_check(self):
-        if self.is_packaging_viewer():
-           WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action
-
-    def enable_no_crt_manifest_check(self):
-        if self.is_packaging_viewer():
-            WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action
-
-    def disable_manifest_check(self):
-        if self.is_packaging_viewer():
-            del WindowsManifest.copy_action
-
-    def construct(self):
-        super(WindowsManifest, self).construct()
-
-        self.enable_crt_manifest_check()
-
-        if self.is_packaging_viewer():
-            # Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe.
-            self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe())
-
-        # Plugin host application
-        self.path(os.path.join(os.pardir,
-                               'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"),
-                  "slplugin.exe")
-        
-        self.disable_manifest_check()
-
-        self.path(src="../viewer_components/updater/scripts/windows/update_install.bat", dst="update_install.bat")
-
-        # Get shared libs from the shared libs staging directory
-        if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']),
-                       dst=""):
-
-            self.enable_crt_manifest_check()
-
-            # Get llcommon and deps. If missing assume static linkage and continue.
-            try:
-                self.path('llcommon.dll')
-                self.path('libapr-1.dll')
-                self.path('libaprutil-1.dll')
-                self.path('libapriconv-1.dll')
-            except RuntimeError, err:
-                print err.message
-                print "Skipping llcommon.dll (assuming llcommon was linked statically)"
-
-            self.disable_manifest_check()
-
-            # Get fmod dll, continue if missing
-            try:
-                self.path("fmod.dll")
-            except:
-                print "Skipping fmod.dll"
-
-            # For textures
-            if self.args['configuration'].lower() == 'debug':
-                self.path("openjpegd.dll")
-            else:
-                self.path("openjpeg.dll")
-
-            # These need to be installed as a SxS assembly, currently a 'private' assembly.
-            # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx
-            if self.args['configuration'].lower() == 'debug':
-                self.path("msvcr80d.dll")
-                self.path("msvcp80d.dll")
-                self.path("Microsoft.VC80.DebugCRT.manifest")
-            else:
-                self.path("msvcr80.dll")
-                self.path("msvcp80.dll")
-                self.path("Microsoft.VC80.CRT.manifest")
-
-            # Vivox runtimes
-            self.path("SLVoice.exe")
-            self.path("vivoxsdk.dll")
-            self.path("ortp.dll")
-            self.path("libsndfile-1.dll")
-            self.path("zlib1.dll")
-            self.path("vivoxplatform.dll")
-            self.path("vivoxoal.dll")
-
-            # For google-perftools tcmalloc allocator.
-            try:
-                if self.args['configuration'].lower() == 'debug':
-                    self.path('libtcmalloc_minimal-debug.dll')
-                else:
-                    self.path('libtcmalloc_minimal.dll')
-            except:
-                print "Skipping libtcmalloc_minimal.dll"
-
-            self.end_prefix()
-
-        self.path(src="licenses-win32.txt", dst="licenses.txt")
-        self.path("featuretable.txt")
-        self.path("featuretable_xp.txt")
-
-        # For use in crash reporting (generates minidumps)
-        self.path("dbghelp.dll")
-
-        self.enable_no_crt_manifest_check()
-        
-        # Media plugins - QuickTime
-        if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
-            self.path("media_plugin_quicktime.dll")
-            self.end_prefix()
-
-        # Media plugins - WebKit/Qt
-        if self.prefix(src='../media_plugins/webkit/%s' % self.args['configuration'], dst="llplugin"):
-            self.path("media_plugin_webkit.dll")
-            self.end_prefix()
-
-        # winmm.dll shim
-        if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):
-            self.path("winmm.dll")
-            self.end_prefix()
-
-
-        if self.args['configuration'].lower() == 'debug':
-            if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'debug'),
-                           dst="llplugin"):
-                self.path("libeay32.dll")
-                self.path("qtcored4.dll")
-                self.path("qtguid4.dll")
-                self.path("qtnetworkd4.dll")
-                self.path("qtopengld4.dll")
-                self.path("qtwebkitd4.dll")
-                self.path("qtxmlpatternsd4.dll")
-                self.path("ssleay32.dll")
-
-                # For WebKit/Qt plugin runtimes (image format plugins)
-                if self.prefix(src="imageformats", dst="imageformats"):
-                    self.path("qgifd4.dll")
-                    self.path("qicod4.dll")
-                    self.path("qjpegd4.dll")
-                    self.path("qmngd4.dll")
-                    self.path("qsvgd4.dll")
-                    self.path("qtiffd4.dll")
-                    self.end_prefix()
-
-                # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
-                if self.prefix(src="codecs", dst="codecs"):
-                    self.path("qcncodecsd4.dll")
-                    self.path("qjpcodecsd4.dll")
-                    self.path("qkrcodecsd4.dll")
-                    self.path("qtwcodecsd4.dll")
-                    self.end_prefix()
-
-                self.end_prefix()
-        else:
-            if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'release'),
-                           dst="llplugin"):
-                self.path("libeay32.dll")
-                self.path("qtcore4.dll")
-                self.path("qtgui4.dll")
-                self.path("qtnetwork4.dll")
-                self.path("qtopengl4.dll")
-                self.path("qtwebkit4.dll")
-                self.path("qtxmlpatterns4.dll")
-                self.path("ssleay32.dll")
-
-                # For WebKit/Qt plugin runtimes (image format plugins)
-                if self.prefix(src="imageformats", dst="imageformats"):
-                    self.path("qgif4.dll")
-                    self.path("qico4.dll")
-                    self.path("qjpeg4.dll")
-                    self.path("qmng4.dll")
-                    self.path("qsvg4.dll")
-                    self.path("qtiff4.dll")
-                    self.end_prefix()
-
-                # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
-                if self.prefix(src="codecs", dst="codecs"):
-                    self.path("qcncodecs4.dll")
-                    self.path("qjpcodecs4.dll")
-                    self.path("qkrcodecs4.dll")
-                    self.path("qtwcodecs4.dll")
-                    self.end_prefix()
-
-                self.end_prefix()
-
-        self.disable_manifest_check()
-
-        # pull in the crash logger and updater from other projects
-        # tag:"crash-logger" here as a cue to the exporter
-        self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
-                  dst="win_crash_logger.exe")
-        self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'],
-                  dst="updater.exe")
-
-        if not self.is_packaging_viewer():
-            self.package_file = "copied_deps"    
-
-    def nsi_file_commands(self, install=True):
-        def wpath(path):
-            if path.endswith('/') or path.endswith(os.path.sep):
-                path = path[:-1]
-            path = path.replace('/', '\\')
-            return path
-
-        result = ""
-        dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])]
-        # sort deepest hierarchy first
-        dest_files.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b))
-        dest_files.reverse()
-        out_path = None
-        for pkg_file in dest_files:
-            rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,''))
-            installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file)))
-            pkg_file = wpath(os.path.normpath(pkg_file))
-            if installed_dir != out_path:
-                if install:
-                    out_path = installed_dir
-                    result += 'SetOutPath ' + out_path + '\n'
-            if install:
-                result += 'File ' + pkg_file + '\n'
-            else:
-                result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n'
-        # at the end of a delete, just rmdir all the directories
-        if not install:
-            deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list]
-            # find all ancestors so that we don't skip any dirs that happened to have no non-dir children
-            deleted_dirs = []
-            for d in deleted_file_dirs:
-                deleted_dirs.extend(path_ancestors(d))
-            # sort deepest hierarchy first
-            deleted_dirs.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b))
-            deleted_dirs.reverse()
-            prev = None
-            for d in deleted_dirs:
-                if d != prev:   # skip duplicates
-                    result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n'
-                prev = d
-
-        return result
-
-    def package_finish(self):
-        # a standard map of strings for replacing in the templates
-        substitution_strings = {
-            'version' : '.'.join(self.args['version']),
-            'version_short' : '.'.join(self.args['version'][:-1]),
-            'version_dashes' : '-'.join(self.args['version']),
-            'final_exe' : self.final_exe(),
-            'grid':self.args['grid'],
-            'grid_caps':self.args['grid'].upper(),
-            # escape quotes becase NSIS doesn't handle them well
-            'flags':self.flags_list().replace('"', '$\\"'),
-            'channel':self.channel(),
-            'channel_oneword':self.channel_oneword(),
-            'channel_unique':self.channel_unique(),
-            }
-
-        version_vars = """
-        !define INSTEXE  "%(final_exe)s"
-        !define VERSION "%(version_short)s"
-        !define VERSION_LONG "%(version)s"
-        !define VERSION_DASHES "%(version_dashes)s"
-        """ % substitution_strings
-        if self.default_channel():
-            if self.default_grid():
-                # release viewer
-                installer_file = "Second_Life_%(version_dashes)s_Setup.exe"
-                grid_vars_template = """
-                OutFile "%(installer_file)s"
-                !define INSTFLAGS "%(flags)s"
-                !define INSTNAME   "SecondLifeViewer2"
-                !define SHORTCUT   "Second Life Viewer 2"
-                !define URLNAME   "secondlife"
-                Caption "Second Life ${VERSION}"
-                """
-            else:
-                # beta grid viewer
-                installer_file = "Second_Life_%(version_dashes)s_(%(grid_caps)s)_Setup.exe"
-                grid_vars_template = """
-                OutFile "%(installer_file)s"
-                !define INSTFLAGS "%(flags)s"
-                !define INSTNAME   "SecondLife%(grid_caps)s"
-                !define SHORTCUT   "Second Life (%(grid_caps)s)"
-                !define URLNAME   "secondlife%(grid)s"
-                !define UNINSTALL_SETTINGS 1
-                Caption "Second Life %(grid)s ${VERSION}"
-                """
-        else:
-            # some other channel on some grid
-            installer_file = "Second_Life_%(version_dashes)s_%(channel_oneword)s_Setup.exe"
-            grid_vars_template = """
-            OutFile "%(installer_file)s"
-            !define INSTFLAGS "%(flags)s"
-            !define INSTNAME   "SecondLife%(channel_oneword)s"
-            !define SHORTCUT   "%(channel)s"
-            !define URLNAME   "secondlife"
-            !define UNINSTALL_SETTINGS 1
-            Caption "%(channel)s ${VERSION}"
-            """
-        if 'installer_name' in self.args:
-            installer_file = self.args['installer_name']
-        else:
-            installer_file = installer_file % substitution_strings
-        substitution_strings['installer_file'] = installer_file
-
-        tempfile = "secondlife_setup_tmp.nsi"
-        # the following replaces strings in the nsi template
-        # it also does python-style % substitution
-        self.replace_in("installers/windows/installer_template.nsi", tempfile, {
-                "%%VERSION%%":version_vars,
-                "%%SOURCE%%":self.get_src_prefix(),
-                "%%GRID_VARS%%":grid_vars_template % substitution_strings,
-                "%%INSTALL_FILES%%":self.nsi_file_commands(True),
-                "%%DELETE_FILES%%":self.nsi_file_commands(False)})
-
-        # We use the Unicode version of NSIS, available from
-        # http://www.scratchpaper.com/
-        # Check two paths, one for Program Files, and one for Program Files (x86).
-        # Yay 64bit windows.
-        NSIS_path = os.path.expandvars('${ProgramFiles}\\NSIS\\Unicode\\makensis.exe')
-        if not os.path.exists(NSIS_path):
-            NSIS_path = os.path.expandvars('${ProgramFiles(x86)}\\NSIS\\Unicode\\makensis.exe')
-        self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile))
-        # self.remove(self.dst_path_of(tempfile))
-        # If we're on a build machine, sign the code using our Authenticode certificate. JC
-        sign_py = os.path.expandvars("${SIGN}")
-        if not sign_py or sign_py == "${SIGN}":
-            sign_py = 'C:\\buildscripts\\code-signing\\sign.py'
-        else:
-            sign_py = sign_py.replace('\\', '\\\\\\\\')
-        python = os.path.expandvars("${PYTHON}")
-        if not python or python == "${PYTHON}":
-            python = 'python'
-        if os.path.exists(sign_py):
-            self.run_command("%s %s %s" % (python, sign_py, self.dst_path_of(installer_file).replace('\\', '\\\\\\\\')))
-        else:
-            print "Skipping code signing,", sign_py, "does not exist"
-        self.created_path(self.dst_path_of(installer_file))
-        self.package_file = installer_file
-
-
-class DarwinManifest(ViewerManifest):
-    def is_packaging_viewer(self):
-        # darwin requires full app bundle packaging even for debugging.
-        return True
-
-    def construct(self):
-        # copy over the build result (this is a no-op if run within the xcode script)
-        self.path(self.args['configuration'] + "/Second Life.app", dst="")
-
-        if self.prefix(src="", dst="Contents"):  # everything goes in Contents
-            self.path("Info-SecondLife.plist", dst="Info.plist")
-
-            # copy additional libs in <bundle>/Contents/MacOS/
-            self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib")
-
-            self.path("../viewer_components/updater/scripts/darwin/update_install", "MacOS/update_install")
-
-            # most everything goes in the Resources directory
-            if self.prefix(src="", dst="Resources"):
-                super(DarwinManifest, self).construct()
-
-                if self.prefix("cursors_mac"):
-                    self.path("*.tif")
-                    self.end_prefix("cursors_mac")
-
-                self.path("licenses-mac.txt", dst="licenses.txt")
-                self.path("featuretable_mac.txt")
-                self.path("SecondLife.nib")
-
-                # If we are not using the default channel, use the 'Firstlook
-                # icon' to show that it isn't a stable release.
-                if self.default_channel() and self.default_grid():
-                    self.path("secondlife.icns")
-                else:
-                    self.path("secondlife_firstlook.icns", "secondlife.icns")
-                self.path("SecondLife.nib")
-                
-                # Translations
-                self.path("English.lproj")
-                self.path("German.lproj")
-                self.path("Japanese.lproj")
-                self.path("Korean.lproj")
-                self.path("da.lproj")
-                self.path("es.lproj")
-                self.path("fr.lproj")
-                self.path("hu.lproj")
-                self.path("it.lproj")
-                self.path("nl.lproj")
-                self.path("pl.lproj")
-                self.path("pt.lproj")
-                self.path("ru.lproj")
-                self.path("tr.lproj")
-                self.path("uk.lproj")
-                self.path("zh-Hans.lproj")
-
-                # SLVoice and vivox lols
-                self.path("vivox-runtime/universal-darwin/libsndfile.dylib", "libsndfile.dylib")
-                self.path("vivox-runtime/universal-darwin/libvivoxoal.dylib", "libvivoxoal.dylib")
-                self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib")
-                self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib")
-                self.path("vivox-runtime/universal-darwin/libvivoxplatform.dylib", "libvivoxplatform.dylib")
-                self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice")
-
-                libdir = "../../libraries/universal-darwin/lib_release"
-                dylibs = {}
-
-                # Need to get the llcommon dll from any of the build directories as well
-                lib = "llcommon"
-                libfile = "lib%s.dylib" % lib
-                try:
-                    self.path(self.find_existing_file(os.path.join(os.pardir,
-                                                                    lib,
-                                                                    self.args['configuration'],
-                                                                    libfile),
-                                                      os.path.join(libdir, libfile)),
-                                                      dst=libfile)
-                except RuntimeError:
-                    print "Skipping %s" % libfile
-                    dylibs[lib] = False
-                else:
-                    dylibs[lib] = True
-
-                if dylibs["llcommon"]:
-                    for libfile in ("libapr-1.0.3.7.dylib",
-                                    "libaprutil-1.0.3.8.dylib",
-                                    "libexpat.0.5.0.dylib",
-                                    "libexception_handler.dylib",
-                                    ):
-                        self.path(os.path.join(libdir, libfile), libfile)
-
-                try:
-                    # FMOD for sound
-                    self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib")
-                except:
-                    print "Skipping FMOD - not found"
-                
-                # our apps
-                self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app")
-                self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app")
-
-                # plugin launcher
-                self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin.app", "SLPlugin.app")
-
-                # our apps dependencies on shared libs
-                if dylibs["llcommon"]:
-                    mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources")
-                    mac_updater_res_path = self.dst_path_of("mac-updater.app/Contents/Resources")
-                    slplugin_res_path = self.dst_path_of("SLPlugin.app/Contents/Resources")
-                    for libfile in ("libllcommon.dylib",
-                                    "libapr-1.0.3.7.dylib",
-                                    "libaprutil-1.0.3.8.dylib",
-                                    "libexpat.0.5.0.dylib",
-                                    "libexception_handler.dylib",
-                                    ):
-                        target_lib = os.path.join('../../..', libfile)
-                        self.run_command("ln -sf %(target)r %(link)r" % 
-                                         {'target': target_lib,
-                                          'link' : os.path.join(mac_crash_logger_res_path, libfile)}
-                                         )
-                        self.run_command("ln -sf %(target)r %(link)r" % 
-                                         {'target': target_lib,
-                                          'link' : os.path.join(mac_updater_res_path, libfile)}
-                                         )
-                        self.run_command("ln -sf %(target)r %(link)r" % 
-                                         {'target': target_lib,
-                                          'link' : os.path.join(slplugin_res_path, libfile)}
-                                         )
-
-                # plugins
-                if self.prefix(src="", dst="llplugin"):
-                    self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib")
-                    self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib")
-                    self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib")
-
-                    self.end_prefix("llplugin")
-
-                # command line arguments for connecting to the proper grid
-                self.put_in_file(self.flags_list(), 'arguments.txt')
-
-                self.end_prefix("Resources")
-
-            self.end_prefix("Contents")
-
-        # NOTE: the -S argument to strip causes it to keep enough info for
-        # annotated backtraces (i.e. function names in the crash log).  'strip' with no
-        # arguments yields a slightly smaller binary but makes crash logs mostly useless.
-        # This may be desirable for the final release.  Or not.
-        if ("package" in self.args['actions'] or 
-            "unpacked" in self.args['actions']):
-            self.run_command('strip -S %(viewer_binary)r' %
-                             { 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')})
-
-    def copy_finish(self):
-        # Force executable permissions to be set for scripts
-        # see CHOP-223 and http://mercurial.selenic.com/bts/issue1802
-        for script in 'Contents/MacOS/update_install',:
-            self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))
-
-    def package_finish(self):
-        channel_standin = 'Second Life Viewer 2'  # hah, our default channel is not usable on its own
-        if not self.default_channel():
-            channel_standin = self.channel()
-
-        imagename="SecondLife_" + '_'.join(self.args['version'])
-
-        # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning.
-        #  If we really need differently named volumes, we'll need to create multiple DS_Store file images, or use some other trick.
-
-        volname="Second Life Installer"  # DO NOT CHANGE without understanding comment above
-
-        if self.default_channel():
-            if not self.default_grid():
-                # beta case
-                imagename = imagename + '_' + self.args['grid'].upper()
-        else:
-            # first look, etc
-            imagename = imagename + '_' + self.channel_oneword().upper()
-
-        sparsename = imagename + ".sparseimage"
-        finalname = imagename + ".dmg"
-        # make sure we don't have stale files laying about
-        self.remove(sparsename, finalname)
-
-        self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % {
-                'sparse':sparsename,
-                'vol':volname})
-
-        # mount the image and get the name of the mount point and device node
-        hdi_output = self.run_command('hdiutil attach -private %r' % sparsename)
-        try:
-            devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()
-            volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip()
-
-            if devfile != '/dev/disk1':
-                # adding more debugging info based upon nat's hunches to the
-                # logs to help track down 'SetFile -a V' failures -brad
-                print "WARNING: 'SetFile -a V' command below is probably gonna fail"
-
-            # Copy everything in to the mounted .dmg
-
-            if self.default_channel() and not self.default_grid():
-                app_name = "Second Life " + self.args['grid']
-            else:
-                app_name = channel_standin.strip()
-
-            # Hack:
-            # Because there is no easy way to coerce the Finder into positioning
-            # the app bundle in the same place with different app names, we are
-            # adding multiple .DS_Store files to svn. There is one for release,
-            # one for release candidate and one for first look. Any other channels
-            # will use the release .DS_Store, and will look broken.
-            # - Ambroff 2008-08-20
-            dmg_template = os.path.join(
-                'installers', 
-                'darwin',
-                '%s-dmg' % "".join(self.channel_unique().split()).lower())
-
-            if not os.path.exists (self.src_path_of(dmg_template)):
-                dmg_template = os.path.join ('installers', 'darwin', 'release-dmg')
-
-            for s,d in {self.get_dst_prefix():app_name + ".app",
-                        os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns",
-                        os.path.join(dmg_template, "background.jpg"): "background.jpg",
-                        os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items():
-                print "Copying to dmg", s, d
-                self.copy_action(self.src_path_of(s), os.path.join(volpath, d))
-
-            # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit)
-            for f in ".VolumeIcon.icns", "background.jpg", ".DS_Store":
-                pathname = os.path.join(volpath, f)
-                # We've observed mysterious "no such file" failures of the SetFile
-                # command, especially on the first file listed above -- yet
-                # subsequent inspection of the target directory confirms it's
-                # there. Timing problem with copy command? Try to handle.
-                for x in xrange(3):
-                    if os.path.exists(pathname):
-                        print "Confirmed existence: %r" % pathname
-                        break
-                    print "Waiting for %s copy command to complete (%s)..." % (f, x+1)
-                    sys.stdout.flush()
-                    time.sleep(1)
-                # If we fall out of the loop above without a successful break, oh
-                # well, possibly we've mistaken the nature of the problem. In any
-                # case, don't hang up the whole build looping indefinitely, let
-                # the original problem manifest by executing the desired command.
-                self.run_command('SetFile -a V %r' % pathname)
-
-            # Create the alias file (which is a resource file) from the .r
-            self.run_command('Rez %r -o %r' %
-                             (self.src_path_of("installers/darwin/release-dmg/Applications-alias.r"),
-                              os.path.join(volpath, "Applications")))
-
-            # Set the alias file's alias and custom icon bits
-            self.run_command('SetFile -a AC %r' % os.path.join(volpath, "Applications"))
-
-            # Set the disk image root's custom icon bit
-            self.run_command('SetFile -a C %r' % volpath)
-        finally:
-            # Unmount the image even if exceptions from any of the above 
-            self.run_command('hdiutil detach -force %r' % devfile)
-
-        print "Converting temp disk image to final disk image"
-        self.run_command('hdiutil convert %(sparse)r -format UDZO -imagekey zlib-level=9 -o %(final)r' % {'sparse':sparsename, 'final':finalname})
-        # get rid of the temp file
-        self.package_file = finalname
-        self.remove(sparsename)
-
-class LinuxManifest(ViewerManifest):
-    def construct(self):
-        super(LinuxManifest, self).construct()
-        self.path("licenses-linux.txt","licenses.txt")
-        self.path("res/ll_icon.png","secondlife_icon.png")
-        if self.prefix("linux_tools", dst=""):
-            self.path("client-readme.txt","README-linux.txt")
-            self.path("client-readme-voice.txt","README-linux-voice.txt")
-            self.path("client-readme-joystick.txt","README-linux-joystick.txt")
-            self.path("wrapper.sh","secondlife")
-            self.path("handle_secondlifeprotocol.sh", "etc/handle_secondlifeprotocol.sh")
-            self.path("register_secondlifeprotocol.sh", "etc/register_secondlifeprotocol.sh")
-            self.path("refresh_desktop_app_entry.sh", "etc/refresh_desktop_app_entry.sh")
-            self.path("launch_url.sh","etc/launch_url.sh")
-            self.path("install.sh")
-            self.end_prefix("linux_tools")
-
-        # Create an appropriate gridargs.dat for this package, denoting required grid.
-        self.put_in_file(self.flags_list(), 'etc/gridargs.dat')
-
-        self.path("secondlife-bin","bin/do-not-directly-run-secondlife-bin")
-        self.path("../linux_crash_logger/linux-crash-logger","bin/linux-crash-logger.bin")
-        self.path("../linux_updater/linux-updater", "bin/linux-updater.bin")
-        self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin")
-
-        if self.prefix("res-sdl"):
-            self.path("*")
-            # recurse
-            self.end_prefix("res-sdl")
-
-        self.path("../viewer_components/updater/scripts/linux/update_install", "bin/update_install")
-
-        # plugins
-        if self.prefix(src="", dst="bin/llplugin"):
-            self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so")
-            self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
-            self.end_prefix("bin/llplugin")
-
-        try:
-            self.path("../llcommon/libllcommon.so", "lib/libllcommon.so")
-        except:
-            print "Skipping llcommon.so (assuming llcommon was linked statically)"
-
-        self.path("featuretable_linux.txt")
-
-    def copy_finish(self):
-        # Force executable permissions to be set for scripts
-        # see CHOP-223 and http://mercurial.selenic.com/bts/issue1802
-        for script in 'secondlife', 'bin/update_install':
-            self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))
-
-    def package_finish(self):
-        if 'installer_name' in self.args:
-            installer_name = self.args['installer_name']
-        else:
-            installer_name_components = ['SecondLife_', self.args.get('arch')]
-            installer_name_components.extend(self.args['version'])
-            installer_name = "_".join(installer_name_components)
-            if self.default_channel():
-                if not self.default_grid():
-                    installer_name += '_' + self.args['grid'].upper()
-            else:
-                installer_name += '_' + self.channel_oneword().upper()
-
-        if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():
-            print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"
-            self.run_command("find %(d)r/bin %(d)r/lib -type f \\! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
-
-        # Fix access permissions
-        self.run_command("""
-                find %(dst)s -type d | xargs --no-run-if-empty chmod 755;
-                find %(dst)s -type f -perm 0700 | xargs --no-run-if-empty chmod 0755;
-                find %(dst)s -type f -perm 0500 | xargs --no-run-if-empty chmod 0555;
-                find %(dst)s -type f -perm 0600 | xargs --no-run-if-empty chmod 0644;
-                find %(dst)s -type f -perm 0400 | xargs --no-run-if-empty chmod 0444;
-                true""" %  {'dst':self.get_dst_prefix() })
-        self.package_file = installer_name + '.tar.bz2'
-
-        # temporarily move directory tree so that it has the right
-        # name in the tarfile
-        self.run_command("mv %(dst)s %(inst)s" % {
-            'dst': self.get_dst_prefix(),
-            'inst': self.build_path_of(installer_name)})
-        try:
-            # only create tarball if it's a release build.
-            if self.args['buildtype'].lower() == 'release':
-                # --numeric-owner hides the username of the builder for
-                # security etc.
-                self.run_command('tar -C %(dir)s --numeric-owner -cjf '
-                                 '%(inst_path)s.tar.bz2 %(inst_name)s' % {
-                        'dir': self.get_build_prefix(),
-                        'inst_name': installer_name,
-                        'inst_path':self.build_path_of(installer_name)})
-            else:
-                print "Skipping %s.tar.bz2 for non-Release build (%s)" % \
-                      (installer_name, self.args['buildtype'])
-        finally:
-            self.run_command("mv %(inst)s %(dst)s" % {
-                'dst': self.get_dst_prefix(),
-                'inst': self.build_path_of(installer_name)})
-
-class Linux_i686Manifest(LinuxManifest):
-    def construct(self):
-        super(Linux_i686Manifest, self).construct()
-
-        if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"):
-            self.path("libapr-1.so.0")
-            self.path("libaprutil-1.so.0")
-            self.path("libbreakpad_client.so.0.0.0", "libbreakpad_client.so.0")
-            self.path("libdb-4.2.so")
-            self.path("libcrypto.so.0.9.7")
-            self.path("libexpat.so.1")
-            self.path("libssl.so.0.9.7")
-            self.path("libuuid.so.1")
-            self.path("libSDL-1.2.so.0")
-            self.path("libELFIO.so")
-            self.path("libopenjpeg.so.1.3.0", "libopenjpeg.so.1.3")
-            self.path("libalut.so")
-            self.path("libopenal.so", "libopenal.so.1")
-            self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
-            try:
-                    self.path("libfmod-3.75.so")
-                    pass
-            except:
-                    print "Skipping libfmod-3.75.so - not found"
-                    pass
-            self.end_prefix("lib")
-
-            # Vivox runtimes
-            if self.prefix(src="vivox-runtime/i686-linux", dst="bin"):
-                    self.path("SLVoice")
-                    self.end_prefix()
-            if self.prefix(src="vivox-runtime/i686-linux", dst="lib"):
-                    self.path("libortp.so")
-                    self.path("libsndfile.so.1")
-                    #self.path("libvivoxoal.so.1") # no - we'll re-use the viewer's own OpenAL lib
-                    self.path("libvivoxsdk.so")
-                    self.path("libvivoxplatform.so")
-                    self.end_prefix("lib")
-
-class Linux_x86_64Manifest(LinuxManifest):
-    def construct(self):
-        super(Linux_x86_64Manifest, self).construct()
-
-        # support file for valgrind debug tool
-        self.path("secondlife-i686.supp")
-
-################################################################
-
-if __name__ == "__main__":
-    main()
+#!/usr/bin/env python
+"""\
+@file viewer_manifest.py
+@author Ryan Williams
+@brief Description of all installer viewer files, and methods for packaging
+       them into installers for all supported platforms.
+
+$LicenseInfo:firstyear=2006&license=viewerlgpl$
+Second Life Viewer Source Code
+Copyright (C) 2006-2011, Linden Research, Inc.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation;
+version 2.1 of the License only.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+$/LicenseInfo$
+"""
+import sys
+import os.path
+import re
+import tarfile
+import time
+viewer_dir = os.path.dirname(__file__)
+# add llmanifest library to our path so we don't have to muck with PYTHONPATH
+sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util'))
+from llmanifest import LLManifest, main, proper_windows_path, path_ancestors
+
+class ViewerManifest(LLManifest):
+    def is_packaging_viewer(self):
+        # Some commands, files will only be included
+        # if we are packaging the viewer on windows.
+        # This manifest is also used to copy
+        # files during the build (see copy_w_viewer_manifest
+        # and copy_l_viewer_manifest targets)
+        return 'package' in self.args['actions']
+    
+    def construct(self):
+        super(ViewerManifest, self).construct()
+        self.exclude("*.svn*")
+        self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg")
+        self.path(src="../../etc/message.xml", dst="app_settings/message.xml")
+
+        if self.is_packaging_viewer():
+            if self.prefix(src="app_settings"):
+                self.exclude("logcontrol.xml")
+                self.exclude("logcontrol-dev.xml")
+                self.path("*.pem")
+                self.path("*.ini")
+                self.path("*.xml")
+                self.path("*.db2")
+
+                # include the entire shaders directory recursively
+                self.path("shaders")
+                # ... and the entire windlight directory
+                self.path("windlight")
+                self.end_prefix("app_settings")
+
+            if self.prefix(src="character"):
+                self.path("*.llm")
+                self.path("*.xml")
+                self.path("*.tga")
+                self.end_prefix("character")
+
+            # Include our fonts
+            if self.prefix(src="fonts"):
+                self.path("*.ttf")
+                self.path("*.txt")
+                self.end_prefix("fonts")
+
+            # skins
+            if self.prefix(src="skins"):
+                    self.path("paths.xml")
+                    # include the entire textures directory recursively
+                    if self.prefix(src="*/textures"):
+                            self.path("*/*.tga")
+                            self.path("*/*.j2c")
+                            self.path("*/*.jpg")
+                            self.path("*/*.png")
+                            self.path("*.tga")
+                            self.path("*.j2c")
+                            self.path("*.jpg")
+                            self.path("*.png")
+                            self.path("textures.xml")
+                            self.end_prefix("*/textures")
+                    self.path("*/xui/*/*.xml")
+                    self.path("*/xui/*/widgets/*.xml")
+                    self.path("*/*.xml")
+
+                    # Local HTML files (e.g. loading screen)
+                    if self.prefix(src="*/html"):
+                            self.path("*.png")
+                            self.path("*/*/*.html")
+                            self.path("*/*/*.gif")
+                            self.end_prefix("*/html")
+                    self.end_prefix("skins")
+
+            # local_assets dir (for pre-cached textures)
+            if self.prefix(src="local_assets"):
+                self.path("*.j2c")
+                self.path("*.tga")
+                self.end_prefix("local_assets")
+
+            # Files in the newview/ directory
+            self.path("gpu_table.txt")
+
+    def login_channel(self):
+        """Channel reported for login and upgrade purposes ONLY;
+        used for A/B testing"""
+        # NOTE: Do not return the normal channel if login_channel
+        # is not specified, as some code may branch depending on
+        # whether or not this is present
+        return self.args.get('login_channel')
+
+    def grid(self):
+        return self.args['grid']
+    def channel(self):
+        return self.args['channel']
+    def channel_unique(self):
+        return self.channel().replace("Second Life", "").strip()
+    def channel_oneword(self):
+        return "".join(self.channel_unique().split())
+    def channel_lowerword(self):
+        return self.channel_oneword().lower()
+
+    def flags_list(self):
+        """ Convenience function that returns the command-line flags
+        for the grid"""
+
+        # Set command line flags relating to the target grid
+        grid_flags = ''
+        if not self.default_grid():
+            grid_flags = "--grid %(grid)s "\
+                         "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\
+                           {'grid':self.grid()}
+
+        # set command line flags for channel
+        channel_flags = ''
+        if self.login_channel() and self.login_channel() != self.channel():
+            # Report a special channel during login, but use default
+            channel_flags = '--channel "%s"' % (self.login_channel())
+        elif not self.default_channel():
+            channel_flags = '--channel "%s"' % self.channel()
+
+        # Deal with settings 
+        setting_flags = ''
+        if not self.default_channel() or not self.default_grid():
+            if self.default_grid():
+                setting_flags = '--settings settings_%s.xml'\
+                                % self.channel_lowerword()
+            else:
+                setting_flags = '--settings settings_%s_%s.xml'\
+                                % (self.grid(), self.channel_lowerword())
+                                                
+        return " ".join((channel_flags, grid_flags, setting_flags)).strip()
+
+
+class WindowsManifest(ViewerManifest):
+    def final_exe(self):
+        if self.default_channel():
+            if self.default_grid():
+                return "SecondLife.exe"
+            else:
+                return "SecondLifePreview.exe"
+        else:
+            return ''.join(self.channel().split()) + '.exe'
+
+    def test_msvcrt_and_copy_action(self, src, dst):
+        # This is used to test a dll manifest.
+        # It is used as a temporary override during the construct method
+        from test_win32_manifest import test_assembly_binding
+        if src and (os.path.exists(src) or os.path.islink(src)):
+            # ensure that destination path exists
+            self.cmakedirs(os.path.dirname(dst))
+            self.created_paths.append(dst)
+            if not os.path.isdir(src):
+                if(self.args['configuration'].lower() == 'debug'):
+                    test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "8.0.50727.4053")
+                else:
+                    test_assembly_binding(src, "Microsoft.VC80.CRT", "8.0.50727.4053")
+                self.ccopy(src,dst)
+            else:
+                raise Exception("Directories are not supported by test_CRT_and_copy_action()")
+        else:
+            print "Doesn't exist:", src
+
+    def test_for_no_msvcrt_manifest_and_copy_action(self, src, dst):
+        # This is used to test that no manifest for the msvcrt exists.
+        # It is used as a temporary override during the construct method
+        from test_win32_manifest import test_assembly_binding
+        from test_win32_manifest import NoManifestException, NoMatchingAssemblyException
+        if src and (os.path.exists(src) or os.path.islink(src)):
+            # ensure that destination path exists
+            self.cmakedirs(os.path.dirname(dst))
+            self.created_paths.append(dst)
+            if not os.path.isdir(src):
+                try:
+                    if(self.args['configuration'].lower() == 'debug'):
+                        test_assembly_binding(src, "Microsoft.VC80.DebugCRT", "")
+                    else:
+                        test_assembly_binding(src, "Microsoft.VC80.CRT", "")
+                    raise Exception("Unknown condition")
+                except NoManifestException, err:
+                    pass
+                except NoMatchingAssemblyException, err:
+                    pass
+                    
+                self.ccopy(src,dst)
+            else:
+                raise Exception("Directories are not supported by test_CRT_and_copy_action()")
+        else:
+            print "Doesn't exist:", src
+        
+    def enable_crt_manifest_check(self):
+        if self.is_packaging_viewer():
+           WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action
+
+    def enable_no_crt_manifest_check(self):
+        if self.is_packaging_viewer():
+            WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action
+
+    def disable_manifest_check(self):
+        if self.is_packaging_viewer():
+            del WindowsManifest.copy_action
+
+    def construct(self):
+        super(WindowsManifest, self).construct()
+
+        self.enable_crt_manifest_check()
+
+        if self.is_packaging_viewer():
+            # Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe.
+            self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe())
+
+        # Plugin host application
+        self.path(os.path.join(os.pardir,
+                               'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"),
+                  "slplugin.exe")
+        
+        self.disable_manifest_check()
+
+        self.path(src="../viewer_components/updater/scripts/windows/update_install.bat", dst="update_install.bat")
+
+        # Get shared libs from the shared libs staging directory
+        if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']),
+                       dst=""):
+
+            self.enable_crt_manifest_check()
+
+            # Get llcommon and deps. If missing assume static linkage and continue.
+            try:
+                self.path('llcommon.dll')
+                self.path('libapr-1.dll')
+                self.path('libaprutil-1.dll')
+                self.path('libapriconv-1.dll')
+            except RuntimeError, err:
+                print err.message
+                print "Skipping llcommon.dll (assuming llcommon was linked statically)"
+
+            self.disable_manifest_check()
+
+            # Get fmod dll, continue if missing
+            try:
+                self.path("fmod.dll")
+            except:
+                print "Skipping fmod.dll"
+
+            # For textures
+            if self.args['configuration'].lower() == 'debug':
+                self.path("openjpegd.dll")
+            else:
+                self.path("openjpeg.dll")
+
+            # These need to be installed as a SxS assembly, currently a 'private' assembly.
+            # See http://msdn.microsoft.com/en-us/library/ms235291(VS.80).aspx
+            if self.args['configuration'].lower() == 'debug':
+                self.path("msvcr80d.dll")
+                self.path("msvcp80d.dll")
+                self.path("Microsoft.VC80.DebugCRT.manifest")
+            else:
+                self.path("msvcr80.dll")
+                self.path("msvcp80.dll")
+                self.path("Microsoft.VC80.CRT.manifest")
+
+            # Vivox runtimes
+            self.path("SLVoice.exe")
+            self.path("vivoxsdk.dll")
+            self.path("ortp.dll")
+            self.path("libsndfile-1.dll")
+            self.path("zlib1.dll")
+            self.path("vivoxplatform.dll")
+            self.path("vivoxoal.dll")
+
+            # For google-perftools tcmalloc allocator.
+            try:
+                if self.args['configuration'].lower() == 'debug':
+                    self.path('libtcmalloc_minimal-debug.dll')
+                else:
+                    self.path('libtcmalloc_minimal.dll')
+            except:
+                print "Skipping libtcmalloc_minimal.dll"
+
+            self.end_prefix()
+
+        self.path(src="licenses-win32.txt", dst="licenses.txt")
+        self.path("featuretable.txt")
+        self.path("featuretable_xp.txt")
+
+        # For use in crash reporting (generates minidumps)
+        self.path("dbghelp.dll")
+
+        self.enable_no_crt_manifest_check()
+        
+        # Media plugins - QuickTime
+        if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
+            self.path("media_plugin_quicktime.dll")
+            self.end_prefix()
+
+        # Media plugins - WebKit/Qt
+        if self.prefix(src='../media_plugins/webkit/%s' % self.args['configuration'], dst="llplugin"):
+            self.path("media_plugin_webkit.dll")
+            self.end_prefix()
+
+        # winmm.dll shim
+        if self.prefix(src='../media_plugins/winmmshim/%s' % self.args['configuration'], dst=""):
+            self.path("winmm.dll")
+            self.end_prefix()
+
+
+        if self.args['configuration'].lower() == 'debug':
+            if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'debug'),
+                           dst="llplugin"):
+                self.path("libeay32.dll")
+                self.path("qtcored4.dll")
+                self.path("qtguid4.dll")
+                self.path("qtnetworkd4.dll")
+                self.path("qtopengld4.dll")
+                self.path("qtwebkitd4.dll")
+                self.path("qtxmlpatternsd4.dll")
+                self.path("ssleay32.dll")
+
+                # For WebKit/Qt plugin runtimes (image format plugins)
+                if self.prefix(src="imageformats", dst="imageformats"):
+                    self.path("qgifd4.dll")
+                    self.path("qicod4.dll")
+                    self.path("qjpegd4.dll")
+                    self.path("qmngd4.dll")
+                    self.path("qsvgd4.dll")
+                    self.path("qtiffd4.dll")
+                    self.end_prefix()
+
+                # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
+                if self.prefix(src="codecs", dst="codecs"):
+                    self.path("qcncodecsd4.dll")
+                    self.path("qjpcodecsd4.dll")
+                    self.path("qkrcodecsd4.dll")
+                    self.path("qtwcodecsd4.dll")
+                    self.end_prefix()
+
+                self.end_prefix()
+        else:
+            if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'release'),
+                           dst="llplugin"):
+                self.path("libeay32.dll")
+                self.path("qtcore4.dll")
+                self.path("qtgui4.dll")
+                self.path("qtnetwork4.dll")
+                self.path("qtopengl4.dll")
+                self.path("qtwebkit4.dll")
+                self.path("qtxmlpatterns4.dll")
+                self.path("ssleay32.dll")
+
+                # For WebKit/Qt plugin runtimes (image format plugins)
+                if self.prefix(src="imageformats", dst="imageformats"):
+                    self.path("qgif4.dll")
+                    self.path("qico4.dll")
+                    self.path("qjpeg4.dll")
+                    self.path("qmng4.dll")
+                    self.path("qsvg4.dll")
+                    self.path("qtiff4.dll")
+                    self.end_prefix()
+
+                # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
+                if self.prefix(src="codecs", dst="codecs"):
+                    self.path("qcncodecs4.dll")
+                    self.path("qjpcodecs4.dll")
+                    self.path("qkrcodecs4.dll")
+                    self.path("qtwcodecs4.dll")
+                    self.end_prefix()
+
+                self.end_prefix()
+
+        self.disable_manifest_check()
+
+        # pull in the crash logger and updater from other projects
+        # tag:"crash-logger" here as a cue to the exporter
+        self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
+                  dst="win_crash_logger.exe")
+        self.path(src='../win_updater/%s/windows-updater.exe' % self.args['configuration'],
+                  dst="updater.exe")
+
+        if not self.is_packaging_viewer():
+            self.package_file = "copied_deps"    
+
+    def nsi_file_commands(self, install=True):
+        def wpath(path):
+            if path.endswith('/') or path.endswith(os.path.sep):
+                path = path[:-1]
+            path = path.replace('/', '\\')
+            return path
+
+        result = ""
+        dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])]
+        # sort deepest hierarchy first
+        dest_files.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b))
+        dest_files.reverse()
+        out_path = None
+        for pkg_file in dest_files:
+            rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,''))
+            installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file)))
+            pkg_file = wpath(os.path.normpath(pkg_file))
+            if installed_dir != out_path:
+                if install:
+                    out_path = installed_dir
+                    result += 'SetOutPath ' + out_path + '\n'
+            if install:
+                result += 'File ' + pkg_file + '\n'
+            else:
+                result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n'
+        # at the end of a delete, just rmdir all the directories
+        if not install:
+            deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list]
+            # find all ancestors so that we don't skip any dirs that happened to have no non-dir children
+            deleted_dirs = []
+            for d in deleted_file_dirs:
+                deleted_dirs.extend(path_ancestors(d))
+            # sort deepest hierarchy first
+            deleted_dirs.sort(lambda a,b: cmp(a.count(os.path.sep),b.count(os.path.sep)) or cmp(a,b))
+            deleted_dirs.reverse()
+            prev = None
+            for d in deleted_dirs:
+                if d != prev:   # skip duplicates
+                    result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n'
+                prev = d
+
+        return result
+
+    def package_finish(self):
+        # a standard map of strings for replacing in the templates
+        substitution_strings = {
+            'version' : '.'.join(self.args['version']),
+            'version_short' : '.'.join(self.args['version'][:-1]),
+            'version_dashes' : '-'.join(self.args['version']),
+            'final_exe' : self.final_exe(),
+            'grid':self.args['grid'],
+            'grid_caps':self.args['grid'].upper(),
+            # escape quotes becase NSIS doesn't handle them well
+            'flags':self.flags_list().replace('"', '$\\"'),
+            'channel':self.channel(),
+            'channel_oneword':self.channel_oneword(),
+            'channel_unique':self.channel_unique(),
+            }
+
+        version_vars = """
+        !define INSTEXE  "%(final_exe)s"
+        !define VERSION "%(version_short)s"
+        !define VERSION_LONG "%(version)s"
+        !define VERSION_DASHES "%(version_dashes)s"
+        """ % substitution_strings
+        if self.default_channel():
+            if self.default_grid():
+                # release viewer
+                installer_file = "Second_Life_%(version_dashes)s_Setup.exe"
+                grid_vars_template = """
+                OutFile "%(installer_file)s"
+                !define INSTFLAGS "%(flags)s"
+                !define INSTNAME   "SecondLifeViewer2"
+                !define SHORTCUT   "Second Life Viewer 2"
+                !define URLNAME   "secondlife"
+                Caption "Second Life ${VERSION}"
+                """
+            else:
+                # beta grid viewer
+                installer_file = "Second_Life_%(version_dashes)s_(%(grid_caps)s)_Setup.exe"
+                grid_vars_template = """
+                OutFile "%(installer_file)s"
+                !define INSTFLAGS "%(flags)s"
+                !define INSTNAME   "SecondLife%(grid_caps)s"
+                !define SHORTCUT   "Second Life (%(grid_caps)s)"
+                !define URLNAME   "secondlife%(grid)s"
+                !define UNINSTALL_SETTINGS 1
+                Caption "Second Life %(grid)s ${VERSION}"
+                """
+        else:
+            # some other channel on some grid
+            installer_file = "Second_Life_%(version_dashes)s_%(channel_oneword)s_Setup.exe"
+            grid_vars_template = """
+            OutFile "%(installer_file)s"
+            !define INSTFLAGS "%(flags)s"
+            !define INSTNAME   "SecondLife%(channel_oneword)s"
+            !define SHORTCUT   "%(channel)s"
+            !define URLNAME   "secondlife"
+            !define UNINSTALL_SETTINGS 1
+            Caption "%(channel)s ${VERSION}"
+            """
+        if 'installer_name' in self.args:
+            installer_file = self.args['installer_name']
+        else:
+            installer_file = installer_file % substitution_strings
+        substitution_strings['installer_file'] = installer_file
+
+        tempfile = "secondlife_setup_tmp.nsi"
+        # the following replaces strings in the nsi template
+        # it also does python-style % substitution
+        self.replace_in("installers/windows/installer_template.nsi", tempfile, {
+                "%%VERSION%%":version_vars,
+                "%%SOURCE%%":self.get_src_prefix(),
+                "%%GRID_VARS%%":grid_vars_template % substitution_strings,
+                "%%INSTALL_FILES%%":self.nsi_file_commands(True),
+                "%%DELETE_FILES%%":self.nsi_file_commands(False)})
+
+        # We use the Unicode version of NSIS, available from
+        # http://www.scratchpaper.com/
+        # Check two paths, one for Program Files, and one for Program Files (x86).
+        # Yay 64bit windows.
+        NSIS_path = os.path.expandvars('${ProgramFiles}\\NSIS\\Unicode\\makensis.exe')
+        if not os.path.exists(NSIS_path):
+            NSIS_path = os.path.expandvars('${ProgramFiles(x86)}\\NSIS\\Unicode\\makensis.exe')
+        self.run_command('"' + proper_windows_path(NSIS_path) + '" ' + self.dst_path_of(tempfile))
+        # self.remove(self.dst_path_of(tempfile))
+        # If we're on a build machine, sign the code using our Authenticode certificate. JC
+        sign_py = os.path.expandvars("${SIGN}")
+        if not sign_py or sign_py == "${SIGN}":
+            sign_py = 'C:\\buildscripts\\code-signing\\sign.py'
+        else:
+            sign_py = sign_py.replace('\\', '\\\\\\\\')
+        python = os.path.expandvars("${PYTHON}")
+        if not python or python == "${PYTHON}":
+            python = 'python'
+        if os.path.exists(sign_py):
+            self.run_command("%s %s %s" % (python, sign_py, self.dst_path_of(installer_file).replace('\\', '\\\\\\\\')))
+        else:
+            print "Skipping code signing,", sign_py, "does not exist"
+        self.created_path(self.dst_path_of(installer_file))
+        self.package_file = installer_file
+
+
+class DarwinManifest(ViewerManifest):
+    def is_packaging_viewer(self):
+        # darwin requires full app bundle packaging even for debugging.
+        return True
+
+    def construct(self):
+        # copy over the build result (this is a no-op if run within the xcode script)
+        self.path(self.args['configuration'] + "/Second Life.app", dst="")
+
+        if self.prefix(src="", dst="Contents"):  # everything goes in Contents
+            self.path("Info-SecondLife.plist", dst="Info.plist")
+
+            # copy additional libs in <bundle>/Contents/MacOS/
+            self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib")
+
+            self.path("../viewer_components/updater/scripts/darwin/update_install", "MacOS/update_install")
+
+            # most everything goes in the Resources directory
+            if self.prefix(src="", dst="Resources"):
+                super(DarwinManifest, self).construct()
+
+                if self.prefix("cursors_mac"):
+                    self.path("*.tif")
+                    self.end_prefix("cursors_mac")
+
+                self.path("licenses-mac.txt", dst="licenses.txt")
+                self.path("featuretable_mac.txt")
+                self.path("SecondLife.nib")
+
+                # If we are not using the default channel, use the 'Firstlook
+                # icon' to show that it isn't a stable release.
+                if self.default_channel() and self.default_grid():
+                    self.path("secondlife.icns")
+                else:
+                    self.path("secondlife_firstlook.icns", "secondlife.icns")
+                self.path("SecondLife.nib")
+                
+                # Translations
+                self.path("English.lproj")
+                self.path("German.lproj")
+                self.path("Japanese.lproj")
+                self.path("Korean.lproj")
+                self.path("da.lproj")
+                self.path("es.lproj")
+                self.path("fr.lproj")
+                self.path("hu.lproj")
+                self.path("it.lproj")
+                self.path("nl.lproj")
+                self.path("pl.lproj")
+                self.path("pt.lproj")
+                self.path("ru.lproj")
+                self.path("tr.lproj")
+                self.path("uk.lproj")
+                self.path("zh-Hans.lproj")
+
+                # SLVoice and vivox lols
+                self.path("vivox-runtime/universal-darwin/libsndfile.dylib", "libsndfile.dylib")
+                self.path("vivox-runtime/universal-darwin/libvivoxoal.dylib", "libvivoxoal.dylib")
+                self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib")
+                self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib")
+                self.path("vivox-runtime/universal-darwin/libvivoxplatform.dylib", "libvivoxplatform.dylib")
+                self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice")
+
+                libdir = "../../libraries/universal-darwin/lib_release"
+                dylibs = {}
+
+                # Need to get the llcommon dll from any of the build directories as well
+                lib = "llcommon"
+                libfile = "lib%s.dylib" % lib
+                try:
+                    self.path(self.find_existing_file(os.path.join(os.pardir,
+                                                                    lib,
+                                                                    self.args['configuration'],
+                                                                    libfile),
+                                                      os.path.join(libdir, libfile)),
+                                                      dst=libfile)
+                except RuntimeError:
+                    print "Skipping %s" % libfile
+                    dylibs[lib] = False
+                else:
+                    dylibs[lib] = True
+
+                if dylibs["llcommon"]:
+                    for libfile in ("libapr-1.0.3.7.dylib",
+                                    "libaprutil-1.0.3.8.dylib",
+                                    "libexpat.0.5.0.dylib",
+                                    "libexception_handler.dylib",
+                                    ):
+                        self.path(os.path.join(libdir, libfile), libfile)
+
+                try:
+                    # FMOD for sound
+                    self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib")
+                except:
+                    print "Skipping FMOD - not found"
+                
+                # our apps
+                self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app")
+                self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app")
+
+                # plugin launcher
+                self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin.app", "SLPlugin.app")
+
+                # our apps dependencies on shared libs
+                if dylibs["llcommon"]:
+                    mac_crash_logger_res_path = self.dst_path_of("mac-crash-logger.app/Contents/Resources")
+                    mac_updater_res_path = self.dst_path_of("mac-updater.app/Contents/Resources")
+                    slplugin_res_path = self.dst_path_of("SLPlugin.app/Contents/Resources")
+                    for libfile in ("libllcommon.dylib",
+                                    "libapr-1.0.3.7.dylib",
+                                    "libaprutil-1.0.3.8.dylib",
+                                    "libexpat.0.5.0.dylib",
+                                    "libexception_handler.dylib",
+                                    ):
+                        target_lib = os.path.join('../../..', libfile)
+                        self.run_command("ln -sf %(target)r %(link)r" % 
+                                         {'target': target_lib,
+                                          'link' : os.path.join(mac_crash_logger_res_path, libfile)}
+                                         )
+                        self.run_command("ln -sf %(target)r %(link)r" % 
+                                         {'target': target_lib,
+                                          'link' : os.path.join(mac_updater_res_path, libfile)}
+                                         )
+                        self.run_command("ln -sf %(target)r %(link)r" % 
+                                         {'target': target_lib,
+                                          'link' : os.path.join(slplugin_res_path, libfile)}
+                                         )
+
+                # plugins
+                if self.prefix(src="", dst="llplugin"):
+                    self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib")
+                    self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib")
+                    self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib")
+
+                    self.end_prefix("llplugin")
+
+                # command line arguments for connecting to the proper grid
+                self.put_in_file(self.flags_list(), 'arguments.txt')
+
+                self.end_prefix("Resources")
+
+            self.end_prefix("Contents")
+
+        # NOTE: the -S argument to strip causes it to keep enough info for
+        # annotated backtraces (i.e. function names in the crash log).  'strip' with no
+        # arguments yields a slightly smaller binary but makes crash logs mostly useless.
+        # This may be desirable for the final release.  Or not.
+        if ("package" in self.args['actions'] or 
+            "unpacked" in self.args['actions']):
+            self.run_command('strip -S %(viewer_binary)r' %
+                             { 'viewer_binary' : self.dst_path_of('Contents/MacOS/Second Life')})
+
+    def copy_finish(self):
+        # Force executable permissions to be set for scripts
+        # see CHOP-223 and http://mercurial.selenic.com/bts/issue1802
+        for script in 'Contents/MacOS/update_install',:
+            self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))
+
+    def package_finish(self):
+        channel_standin = 'Second Life Viewer 2'  # hah, our default channel is not usable on its own
+        if not self.default_channel():
+            channel_standin = self.channel()
+
+        imagename="SecondLife_" + '_'.join(self.args['version'])
+
+        # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning.
+        #  If we really need differently named volumes, we'll need to create multiple DS_Store file images, or use some other trick.
+
+        volname="Second Life Installer"  # DO NOT CHANGE without understanding comment above
+
+        if self.default_channel():
+            if not self.default_grid():
+                # beta case
+                imagename = imagename + '_' + self.args['grid'].upper()
+        else:
+            # first look, etc
+            imagename = imagename + '_' + self.channel_oneword().upper()
+
+        sparsename = imagename + ".sparseimage"
+        finalname = imagename + ".dmg"
+        # make sure we don't have stale files laying about
+        self.remove(sparsename, finalname)
+
+        self.run_command('hdiutil create %(sparse)r -volname %(vol)r -fs HFS+ -type SPARSE -megabytes 700 -layout SPUD' % {
+                'sparse':sparsename,
+                'vol':volname})
+
+        # mount the image and get the name of the mount point and device node
+        hdi_output = self.run_command('hdiutil attach -private %r' % sparsename)
+        try:
+            devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()
+            volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip()
+
+            if devfile != '/dev/disk1':
+                # adding more debugging info based upon nat's hunches to the
+                # logs to help track down 'SetFile -a V' failures -brad
+                print "WARNING: 'SetFile -a V' command below is probably gonna fail"
+
+            # Copy everything in to the mounted .dmg
+
+            if self.default_channel() and not self.default_grid():
+                app_name = "Second Life " + self.args['grid']
+            else:
+                app_name = channel_standin.strip()
+
+            # Hack:
+            # Because there is no easy way to coerce the Finder into positioning
+            # the app bundle in the same place with different app names, we are
+            # adding multiple .DS_Store files to svn. There is one for release,
+            # one for release candidate and one for first look. Any other channels
+            # will use the release .DS_Store, and will look broken.
+            # - Ambroff 2008-08-20
+            dmg_template = os.path.join(
+                'installers', 
+                'darwin',
+                '%s-dmg' % "".join(self.channel_unique().split()).lower())
+
+            if not os.path.exists (self.src_path_of(dmg_template)):
+                dmg_template = os.path.join ('installers', 'darwin', 'release-dmg')
+
+            for s,d in {self.get_dst_prefix():app_name + ".app",
+                        os.path.join(dmg_template, "_VolumeIcon.icns"): ".VolumeIcon.icns",
+                        os.path.join(dmg_template, "background.jpg"): "background.jpg",
+                        os.path.join(dmg_template, "_DS_Store"): ".DS_Store"}.items():
+                print "Copying to dmg", s, d
+                self.copy_action(self.src_path_of(s), os.path.join(volpath, d))
+
+            # Hide the background image, DS_Store file, and volume icon file (set their "visible" bit)
+            for f in ".VolumeIcon.icns", "background.jpg", ".DS_Store":
+                pathname = os.path.join(volpath, f)
+                # We've observed mysterious "no such file" failures of the SetFile
+                # command, especially on the first file listed above -- yet
+                # subsequent inspection of the target directory confirms it's
+                # there. Timing problem with copy command? Try to handle.
+                for x in xrange(3):
+                    if os.path.exists(pathname):
+                        print "Confirmed existence: %r" % pathname
+                        break
+                    print "Waiting for %s copy command to complete (%s)..." % (f, x+1)
+                    sys.stdout.flush()
+                    time.sleep(1)
+                # If we fall out of the loop above without a successful break, oh
+                # well, possibly we've mistaken the nature of the problem. In any
+                # case, don't hang up the whole build looping indefinitely, let
+                # the original problem manifest by executing the desired command.
+                self.run_command('SetFile -a V %r' % pathname)
+
+            # Create the alias file (which is a resource file) from the .r
+            self.run_command('Rez %r -o %r' %
+                             (self.src_path_of("installers/darwin/release-dmg/Applications-alias.r"),
+                              os.path.join(volpath, "Applications")))
+
+            # Set the alias file's alias and custom icon bits
+            self.run_command('SetFile -a AC %r' % os.path.join(volpath, "Applications"))
+
+            # Set the disk image root's custom icon bit
+            self.run_command('SetFile -a C %r' % volpath)
+        finally:
+            # Unmount the image even if exceptions from any of the above 
+            self.run_command('hdiutil detach -force %r' % devfile)
+
+        print "Converting temp disk image to final disk image"
+        self.run_command('hdiutil convert %(sparse)r -format UDZO -imagekey zlib-level=9 -o %(final)r' % {'sparse':sparsename, 'final':finalname})
+        # get rid of the temp file
+        self.package_file = finalname
+        self.remove(sparsename)
+
+class LinuxManifest(ViewerManifest):
+    def construct(self):
+        super(LinuxManifest, self).construct()
+        self.path("licenses-linux.txt","licenses.txt")
+        self.path("res/ll_icon.png","secondlife_icon.png")
+        if self.prefix("linux_tools", dst=""):
+            self.path("client-readme.txt","README-linux.txt")
+            self.path("client-readme-voice.txt","README-linux-voice.txt")
+            self.path("client-readme-joystick.txt","README-linux-joystick.txt")
+            self.path("wrapper.sh","secondlife")
+            self.path("handle_secondlifeprotocol.sh", "etc/handle_secondlifeprotocol.sh")
+            self.path("register_secondlifeprotocol.sh", "etc/register_secondlifeprotocol.sh")
+            self.path("refresh_desktop_app_entry.sh", "etc/refresh_desktop_app_entry.sh")
+            self.path("launch_url.sh","etc/launch_url.sh")
+            self.path("install.sh")
+            self.end_prefix("linux_tools")
+
+        # Create an appropriate gridargs.dat for this package, denoting required grid.
+        self.put_in_file(self.flags_list(), 'etc/gridargs.dat')
+
+        self.path("secondlife-bin","bin/do-not-directly-run-secondlife-bin")
+        self.path("../linux_crash_logger/linux-crash-logger","bin/linux-crash-logger.bin")
+        self.path("../linux_updater/linux-updater", "bin/linux-updater.bin")
+        self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin")
+
+        if self.prefix("res-sdl"):
+            self.path("*")
+            # recurse
+            self.end_prefix("res-sdl")
+
+        self.path("../viewer_components/updater/scripts/linux/update_install", "bin/update_install")
+
+        # plugins
+        if self.prefix(src="", dst="bin/llplugin"):
+            self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so")
+            self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
+            self.end_prefix("bin/llplugin")
+
+        try:
+            self.path("../llcommon/libllcommon.so", "lib/libllcommon.so")
+        except:
+            print "Skipping llcommon.so (assuming llcommon was linked statically)"
+
+        self.path("featuretable_linux.txt")
+
+    def copy_finish(self):
+        # Force executable permissions to be set for scripts
+        # see CHOP-223 and http://mercurial.selenic.com/bts/issue1802
+        for script in 'secondlife', 'bin/update_install':
+            self.run_command("chmod +x %r" % os.path.join(self.get_dst_prefix(), script))
+
+    def package_finish(self):
+        if 'installer_name' in self.args:
+            installer_name = self.args['installer_name']
+        else:
+            installer_name_components = ['SecondLife_', self.args.get('arch')]
+            installer_name_components.extend(self.args['version'])
+            installer_name = "_".join(installer_name_components)
+            if self.default_channel():
+                if not self.default_grid():
+                    installer_name += '_' + self.args['grid'].upper()
+            else:
+                installer_name += '_' + self.channel_oneword().upper()
+
+        if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():
+            print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"
+            self.run_command("find %(d)r/bin %(d)r/lib -type f \\! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
+
+        # Fix access permissions
+        self.run_command("""
+                find %(dst)s -type d | xargs --no-run-if-empty chmod 755;
+                find %(dst)s -type f -perm 0700 | xargs --no-run-if-empty chmod 0755;
+                find %(dst)s -type f -perm 0500 | xargs --no-run-if-empty chmod 0555;
+                find %(dst)s -type f -perm 0600 | xargs --no-run-if-empty chmod 0644;
+                find %(dst)s -type f -perm 0400 | xargs --no-run-if-empty chmod 0444;
+                true""" %  {'dst':self.get_dst_prefix() })
+        self.package_file = installer_name + '.tar.bz2'
+
+        # temporarily move directory tree so that it has the right
+        # name in the tarfile
+        self.run_command("mv %(dst)s %(inst)s" % {
+            'dst': self.get_dst_prefix(),
+            'inst': self.build_path_of(installer_name)})
+        try:
+            # only create tarball if it's a release build.
+            if self.args['buildtype'].lower() == 'release':
+                # --numeric-owner hides the username of the builder for
+                # security etc.
+                self.run_command('tar -C %(dir)s --numeric-owner -cjf '
+                                 '%(inst_path)s.tar.bz2 %(inst_name)s' % {
+                        'dir': self.get_build_prefix(),
+                        'inst_name': installer_name,
+                        'inst_path':self.build_path_of(installer_name)})
+            else:
+                print "Skipping %s.tar.bz2 for non-Release build (%s)" % \
+                      (installer_name, self.args['buildtype'])
+        finally:
+            self.run_command("mv %(inst)s %(dst)s" % {
+                'dst': self.get_dst_prefix(),
+                'inst': self.build_path_of(installer_name)})
+
+class Linux_i686Manifest(LinuxManifest):
+    def construct(self):
+        super(Linux_i686Manifest, self).construct()
+
+        if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"):
+            self.path("libapr-1.so.0")
+            self.path("libaprutil-1.so.0")
+            self.path("libbreakpad_client.so.0.0.0", "libbreakpad_client.so.0")
+            self.path("libdb-4.2.so")
+            self.path("libcrypto.so.0.9.7")
+            self.path("libexpat.so.1")
+            self.path("libssl.so.0.9.7")
+            self.path("libuuid.so.1")
+            self.path("libSDL-1.2.so.0")
+            self.path("libELFIO.so")
+            self.path("libopenjpeg.so.1.3.0", "libopenjpeg.so.1.3")
+            self.path("libalut.so")
+            self.path("libopenal.so", "libopenal.so.1")
+            self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
+            try:
+                    self.path("libfmod-3.75.so")
+                    pass
+            except:
+                    print "Skipping libfmod-3.75.so - not found"
+                    pass
+            self.end_prefix("lib")
+
+            # Vivox runtimes
+            if self.prefix(src="vivox-runtime/i686-linux", dst="bin"):
+                    self.path("SLVoice")
+                    self.end_prefix()
+            if self.prefix(src="vivox-runtime/i686-linux", dst="lib"):
+                    self.path("libortp.so")
+                    self.path("libsndfile.so.1")
+                    #self.path("libvivoxoal.so.1") # no - we'll re-use the viewer's own OpenAL lib
+                    self.path("libvivoxsdk.so")
+                    self.path("libvivoxplatform.so")
+                    self.end_prefix("lib")
+
+class Linux_x86_64Manifest(LinuxManifest):
+    def construct(self):
+        super(Linux_x86_64Manifest, self).construct()
+
+        # support file for valgrind debug tool
+        self.path("secondlife-i686.supp")
+
+################################################################
+
+if __name__ == "__main__":
+    main()