diff options
| -rw-r--r-- | .hgtags | 2 | ||||
| -rw-r--r-- | BuildParams | 58 | ||||
| -rw-r--r-- | doc/contributions.txt | 1 | ||||
| -rw-r--r-- | indra/llcommon/llversionviewer.h | 2 | ||||
| -rw-r--r-- | indra/llui/lldockcontrol.cpp | 722 | ||||
| -rw-r--r-- | indra/llui/llfloater.cpp | 7 | ||||
| -rw-r--r-- | indra/llui/llfloater.h | 1 | ||||
| -rw-r--r-- | indra/media_plugins/winmmshim/CMakeLists.txt | 12 | ||||
| -rw-r--r-- | indra/newview/llappviewer.cpp | 10274 | ||||
| -rw-r--r-- | indra/newview/llbottomtray.cpp | 3700 | ||||
| -rw-r--r-- | indra/newview/llnearbychatbar.cpp | 11 | ||||
| -rw-r--r-- | indra/newview/llnearbychatbar.h | 2 | ||||
| -rw-r--r-- | indra/newview/llpanellogin.cpp | 2366 | ||||
| -rw-r--r-- | indra/newview/llsidetray.cpp | 37 | ||||
| -rw-r--r-- | indra/newview/llviewermenu.cpp | 16357 | ||||
| -rw-r--r-- | indra/newview/llviewerwindow.cpp | 10068 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 18048 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_people.xml | 26 | ||||
| -rw-r--r-- | indra/newview/viewer_manifest.py | 1950 | 
19 files changed, 31828 insertions, 31816 deletions
@@ -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 1172fe1c71..3ce41adc3a 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 4c2a836b4c..560bedd518 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 7d5afe92dc..117d96ffa6 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 3f81c2b28f..b1c27126d9 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 35e0d9d890..d19e33ea55 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 0e83b80c89..5b7b020881 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -144,6 +144,7 @@ public:  	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 3e3a988310..bf74f81809 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 6d61be84ef..d0f9cae078 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", ¬ify_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", ¬ify_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 0c0df14ac1..1fb83fe567 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 836ae9a0cf..162e465fef 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 033d1dd5a2..96ab45071b 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -72,6 +72,8 @@ public:  	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 b472698a49..903cf4780d 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 8aaa7f0e13..a9bb01ac70 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 @@ protected:  	void			undock(LLFloater* floater_tab);  	LLSideTray*		getSideTray(); + +	void			onFloaterClose(LLSD::Boolean app_quitting);  public:  	virtual ~LLSideTrayTab(); @@ -140,6 +143,8 @@ public:  	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 @@ private:  	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 add24e5216..75cf2efc69 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 2843e4e9ae..147163a9c0 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 99feb9a061..65fdc12f0a 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 ¢er, 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 ¢er, 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 43431ea7c1..1a00416b2a 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 483c9515db..e08c815218 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()  | 
