diff options
| -rw-r--r-- | autobuild.xml | 4 | ||||
| -rw-r--r-- | indra/cmake/Variables.cmake | 8 | ||||
| -rw-r--r-- | indra/llappearance/lltexlayer.cpp | 50 | ||||
| -rw-r--r-- | indra/llappearance/lltexlayer.h | 2 | ||||
| -rw-r--r-- | indra/llimage/llimage.cpp | 23 | ||||
| -rw-r--r-- | indra/llimage/llimage.h | 5 | ||||
| -rwxr-xr-x | indra/newview/app_settings/settings.xml | 12 | ||||
| -rw-r--r-- | indra/newview/llpaneleditwearable.cpp | 9 | ||||
| -rw-r--r-- | indra/newview/llsidepanelappearance.cpp | 1089 | ||||
| -rw-r--r-- | indra/newview/llviewerdisplay.cpp | 11 | 
10 files changed, 644 insertions, 569 deletions
| diff --git a/autobuild.xml b/autobuild.xml index 098140db85..3c503997cc 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1290,9 +1290,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>8180c6f8d96a76c0c4b7746eb9e98964</string> +              <string>17bcc2481fe362e297376d9c46888de8</string>                <key>url</key> -              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/268052/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121212.tar.bz2</string> +              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearanceutility-source/rev/268501/arch/Linux/installer/llappearanceutility_source-0.1-linux-20121220.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 54c77da64e..6ec621632b 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -118,10 +118,10 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")    if (INSTALL_PROPRIETARY)      # Only turn on headless if we can find osmesa libraries.      include(FindPkgConfig) -    pkg_check_modules(OSMESA osmesa) -    if (OSMESA_FOUND) -      set(BUILD_HEADLESS ON CACHE BOOL "Build headless libraries.") -    endif (OSMESA_FOUND) +    #pkg_check_modules(OSMESA osmesa) +    #if (OSMESA_FOUND) +    #  set(BUILD_HEADLESS ON CACHE BOOL "Build headless libraries.") +    #endif (OSMESA_FOUND)    endif (INSTALL_PROPRIETARY)  endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index d1edd4f095..15d531259f 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -150,6 +150,10 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet()  		gAlphaMaskProgram.bind();  		gAlphaMaskProgram.setMinimumAlpha(0.004f);  	} +	else +	{ +		gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.00f); +	}  	LLVertexBuffer::unbind(); @@ -1132,7 +1136,8 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)  			}  		}//*/ -		renderMorphMasks(x, y, width, height, net_color); +		const bool force_render = true; +		renderMorphMasks(x, y, width, height, net_color, force_render);  		alpha_mask_specified = TRUE;  		gGL.flush();  		gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); @@ -1381,8 +1386,13 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)  }  static LLFastTimer::DeclareTimer FTM_RENDER_MORPH_MASKS("renderMorphMasks"); -BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color) +void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render)  { +	if (!force_render && !hasMorph()) +	{ +		lldebugs << "skipping renderMorphMasks for " << getUUID() << llendl; +		return; +	}  	LLFastTimer t(FTM_RENDER_MORPH_MASKS);  	BOOL success = TRUE; @@ -1419,6 +1429,11 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC  	{  		LLTexLayerParamAlpha* param = *iter;  		success &= param->render( x, y, width, height ); +		if (!success && !force_render) +		{ +			lldebugs << "Failed to render param " << param->getID() << " ; skipping morph mask." << llendl; +			return; +		}  	}  	// Approximates a min() function @@ -1444,25 +1459,29 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC  		}  	} -	if( !getInfo()->mStaticImageFileName.empty() ) +	if( !getInfo()->mStaticImageFileName.empty() && getInfo()->mStaticImageIsMask )  	{  		LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);  		if( tex )  		{ -			if(	(tex->getComponents() == 4) || -				( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) +			if(	(tex->getComponents() == 4) || (tex->getComponents() == 1) )  			{  				LLGLSNoAlphaTest gls_no_alpha_test;  				gGL.getTexUnit(0)->bind(tex, TRUE);  				gl_rect_2d_simple_tex( width, height );  				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  			} +			else +			{ +				llwarns << "Skipping rendering of " << getInfo()->mStaticImageFileName  +						<< "; expected 1 or 4 components." << llendl; +			}  		}  	}  	// Draw a rectangle with the layer color to multiply the alpha by that color's alpha.  	// Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); -	if (layer_color.mV[VW] != 1.f) +	if ( !is_approx_equal(layer_color.mV[VW], 1.f) )  	{  		LLGLDisable no_alpha(GL_ALPHA_TEST);  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -1515,8 +1534,6 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC  		mMorphMasksValid = TRUE;  		getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1);  	} - -	return success;  }  static LLFastTimer::DeclareTimer FTM_ADD_ALPHA_MASK("addAlphaMask"); @@ -1531,7 +1548,8 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32  		findNetColor( &net_color );  		// TODO: eliminate need for layer morph mask valid flag  		invalidateMorphMasks(); -		renderMorphMasks(originX, originY, width, height, net_color); +		const bool force_render = false; +		renderMorphMasks(originX, originY, width, height, net_color, force_render);  		alphaData = getAlphaData();  	}  	if (alphaData) @@ -1540,7 +1558,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32  		{  			U8 curAlpha = data[i];  			U16 resultAlpha = curAlpha; -			resultAlpha *= (alphaData[i] + 1); +			resultAlpha *= ( ((U16)alphaData[i]) + 1);  			resultAlpha = resultAlpha >> 8;  			data[i] = (U8)resultAlpha;  		} @@ -1915,9 +1933,15 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name,  		{  			if( (image_raw->getComponents() == 1) && is_mask )  			{ -				// Note: these are static, unchanging images so it's ok to assume -				// that once an image is a mask it's always a mask. -				tex->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); +				// Convert grayscale alpha masks from single channel into RGBA. +				// Fill RGB with black to allow fixed function gl calls +				// to match shader implementation. +				LLPointer<LLImageRaw> alpha_image_raw = image_raw; +				image_raw = new LLImageRaw(image_raw->getWidth(), +										   image_raw->getHeight(), +										   4); + +				image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black);  			}  			tex->createGLTexture(0, image_raw, 0, TRUE, LLGLTexture::LOCAL); diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 405d2c7df4..959d6e499a 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -160,7 +160,7 @@ public:  	BOOL					findNetColor(LLColor4* color) const;  	/*virtual*/ BOOL		blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer  	/*virtual*/ void		gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height); -	BOOL					renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color); +	void					renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render);  	void					addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height);  	/*virtual*/ BOOL		isInvisibleAlphaMask() const; diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 916c346b7a..79949df2d0 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -673,6 +673,29 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )  	}  } +void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill) +{ +	LLImageRaw* dst = this;  // Just for clarity. + +	llassert( 1 == src->getComponents() ); +	llassert( 4 == dst->getComponents() ); +	llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + +	S32 pixels = getWidth() * getHeight(); +	U8* src_data = src->getData(); +	U8* dst_data = dst->getData(); +	for ( S32 i = 0; i < pixels; i++ ) +	{ +		dst_data[0] = fill.mV[0]; +		dst_data[1] = fill.mV[1]; +		dst_data[2] = fill.mV[2]; +		dst_data[3] = src_data[0]; +		src_data += 1; +		dst_data += 4; +	} +} + +  // Fill the buffer with a constant color  void LLImageRaw::fill( const LLColor4U& color )  { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 5f54585005..2d98f02aa6 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -230,6 +230,11 @@ public:  	// Src and dst are same size.  Src has 3 components.  Dst has 4 components.  	void copyUnscaled3onto4( LLImageRaw* src ); +	// Src and dst are same size.  Src has 1 component.  Dst has 4 components. +	// Alpha component is set to source alpha mask component. +	// RGB components are set to fill color. +	void copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill); +  	// Src and dst can be any size.  Src and dst have same number of components.  	void copyScaled( LLImageRaw* src ); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c817579e9e..4b93cef57f 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14170,5 +14170,17 @@      <key>Value</key>      <integer>0</integer>    </map> + +  <key>DisablePrecacheDelayAfterTeleporting</key> +  <map> +    <key>Comment</key> +    <string>Disables the artificial delay in the viewer that precaches some incoming assets</string> +    <key>Persist</key> +    <integer>0</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map>  </map>  </llsd> diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 786b215fdf..606e78bd58 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -882,9 +882,12 @@ void LLPanelEditWearable::setWearable(LLViewerWearable *wearable, BOOL disable_c  //static   void LLPanelEditWearable::onBackButtonClicked(void* userdata) -{ -    LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata; -	panel->saveChanges(true); +{	 +	LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata;     +	if ( panel->isDirty() ) +	{ +		LLAppearanceMgr::instance().setOutfitDirty( true );		 +	}  }  //static  diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 98dc2c0e09..f0844dd9a4 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -1,544 +1,545 @@ -/**
 - * @file llsidepanelappearance.cpp
 - * @brief Side Bar "Appearance" panel
 - *
 - * $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"
 -#include "llsidepanelappearance.h"
 -
 -#include "llaccordionctrltab.h"
 -#include "llagent.h"
 -#include "llagentcamera.h"
 -#include "llagentwearables.h"
 -#include "llappearancemgr.h"
 -#include "llfloatersidepanelcontainer.h"
 -#include "llfolderview.h"
 -#include "llinventorypanel.h"
 -#include "llfiltereditor.h"
 -#include "llfloaterreg.h"
 -#include "llfloaterworldmap.h"
 -#include "llfoldervieweventlistener.h"
 -#include "lloutfitobserver.h"
 -#include "llpaneleditwearable.h"
 -#include "llpaneloutfitsinventory.h"
 -#include "lltextbox.h"
 -#include "lluictrlfactory.h"
 -#include "llviewercontrol.h"
 -#include "llviewerregion.h"
 -#include "llvoavatarself.h"
 -#include "llviewerwearable.h"
 -
 -static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance");
 -
 -class LLCurrentlyWornFetchObserver : public LLInventoryFetchItemsObserver
 -{
 -public:
 -	LLCurrentlyWornFetchObserver(const uuid_vec_t &ids,
 -								 LLSidepanelAppearance *panel) :
 -		LLInventoryFetchItemsObserver(ids),
 -		mPanel(panel)
 -	{}
 -	~LLCurrentlyWornFetchObserver() {}
 -	virtual void done()
 -	{
 -		mPanel->inventoryFetched();
 -		gInventory.removeObserver(this);
 -		delete this;
 -	}
 -private:
 -	LLSidepanelAppearance *mPanel;
 -};
 -
 -LLSidepanelAppearance::LLSidepanelAppearance() :
 -	LLPanel(),
 -	mFilterSubString(LLStringUtil::null),
 -	mFilterEditor(NULL),
 -	mOutfitEdit(NULL),
 -	mCurrOutfitPanel(NULL),
 -	mOpened(false)
 -{
 -	LLOutfitObserver& outfit_observer =  LLOutfitObserver::instance();
 -	outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));
 -	outfit_observer.addBOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));
 -	outfit_observer.addCOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, ""));
 -
 -	gAgentWearables.addLoadingStartedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, true));
 -	gAgentWearables.addLoadedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, false));
 -}
 -
 -LLSidepanelAppearance::~LLSidepanelAppearance()
 -{
 -}
 -
 -// virtual
 -BOOL LLSidepanelAppearance::postBuild()
 -{
 -	mOpenOutfitBtn = getChild<LLButton>("openoutfit_btn");
 -	mOpenOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onOpenOutfitButtonClicked, this));
 -
 -	mEditAppearanceBtn = getChild<LLButton>("editappearance_btn");
 -	mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this));
 -
 -	childSetAction("edit_outfit_btn", boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this));
 -
 -	mNewOutfitBtn = getChild<LLButton>("newlook_btn");
 -	mNewOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this));
 -	mNewOutfitBtn->setEnabled(false);
 -
 -	mFilterEditor = getChild<LLFilterEditor>("Filter");
 -	if (mFilterEditor)
 -	{
 -		mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2));
 -	}
 -
 -	mPanelOutfitsInventory = dynamic_cast<LLPanelOutfitsInventory *>(getChild<LLPanel>("panel_outfits_inventory"));
 -
 -	mOutfitEdit = dynamic_cast<LLPanelOutfitEdit*>(getChild<LLPanel>("panel_outfit_edit"));
 -	if (mOutfitEdit)
 -	{
 -		LLButton* back_btn = mOutfitEdit->getChild<LLButton>("back_btn");
 -		if (back_btn)
 -		{
 -			back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitsInventoryPanel, this));
 -		}
 -
 -	}
 -
 -	mEditWearable = dynamic_cast<LLPanelEditWearable*>(getChild<LLPanel>("panel_edit_wearable"));
 -	if (mEditWearable)
 -	{
 -		LLButton* edit_wearable_back_btn = mEditWearable->getChild<LLButton>("back_btn");
 -		if (edit_wearable_back_btn)
 -		{
 -			edit_wearable_back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this));
 -		}
 -	}
 -
 -	mCurrentLookName = getChild<LLTextBox>("currentlook_name");
 -
 -	mOutfitStatus = getChild<LLTextBox>("currentlook_status");
 -	
 -	mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook");
 -
 -
 -	setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2));
 -
 -	return TRUE;
 -}
 -
 -// virtual
 -void LLSidepanelAppearance::onOpen(const LLSD& key)
 -{
 -	if (!key.has("type"))
 -	{
 -		// No specific panel requested.
 -		// If we're opened for the first time then show My Outfits.
 -		// Else do nothing.
 -		if (!mOpened)
 -		{
 -			showOutfitsInventoryPanel();
 -		}
 -	}
 -	else
 -	{
 -		// Switch to the requested panel.
 -		std::string type = key["type"].asString();
 -		if (type == "my_outfits")
 -		{
 -			showOutfitsInventoryPanel();
 -		}
 -		else if (type == "edit_outfit")
 -		{
 -			showOutfitEditPanel();
 -		}
 -		else if (type == "edit_shape")
 -		{
 -			showWearableEditPanel();
 -		}
 -	}
 -
 -	mOpened = true;
 -}
 -
 -void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility)
 -{
 -	LLSD visibility;
 -	visibility["visible"] = new_visibility.asBoolean();
 -	visibility["reset_accordion"] = false;
 -	updateToVisibility(visibility);
 -}
 -
 -void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
 -{
 -	if (new_visibility["visible"].asBoolean())
 -	{
 -		const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible();
 -		const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible();
 -
 -		if (is_outfit_edit_visible || is_wearable_edit_visible)
 -		{
 -			const LLViewerWearable *wearable_ptr = mEditWearable->getWearable();
 -			if (!wearable_ptr)
 -			{
 -				llwarns << "Visibility change to invalid wearable" << llendl;
 -				return;
 -			}
 -			// Disable camera switch is currently just for WT_PHYSICS type since we don't want to freeze the avatar
 -			// when editing its physics.
 -			if (!gAgentCamera.cameraCustomizeAvatar())
 -			{
 -				LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType()));
 -			}
 -			if (is_wearable_edit_visible)
 -			{
 -				if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
 -				{
 -					// we're no longer wearing the wearable we were last editing, switch back to outfit editor
 -					showOutfitEditPanel();
 -				}
 -			}
 -
 -			if (is_outfit_edit_visible && new_visibility["reset_accordion"].asBoolean())
 -			{
 -				mOutfitEdit->resetAccordionState();
 -			}
 -		}
 -	}
 -	else
 -	{
 -		if (gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement"))
 -		{
 -			gAgentCamera.changeCameraToDefault();
 -			gAgentCamera.resetView();
 -		}	
 -	}
 -}
 -
 -void LLSidepanelAppearance::onFilterEdit(const std::string& search_string)
 -{
 -	if (mFilterSubString != search_string)
 -	{
 -		mFilterSubString = search_string;
 -
 -		// Searches are case-insensitive
 -		// but we don't convert the typed string to upper-case so that it can be fed to the web search as-is.
 -
 -		mPanelOutfitsInventory->onSearchEdit(mFilterSubString);
 -	}
 -}
 -
 -void LLSidepanelAppearance::onOpenOutfitButtonClicked()
 -{
 -	const LLViewerInventoryItem *outfit_link = LLAppearanceMgr::getInstance()->getBaseOutfitLink();
 -	if (!outfit_link)
 -		return;
 -	if (!outfit_link->getIsLinkType())
 -		return;
 -
 -	LLAccordionCtrlTab* tab_outfits = mPanelOutfitsInventory->findChild<LLAccordionCtrlTab>("tab_outfits");
 -	if (tab_outfits)
 -	{
 -		tab_outfits->changeOpenClose(FALSE);
 -		LLInventoryPanel *inventory_panel = tab_outfits->findChild<LLInventoryPanel>("outfitslist_tab");
 -		if (inventory_panel)
 -		{
 -			LLFolderView* root = inventory_panel->getRootFolder();
 -			LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID());
 -			if (outfit_folder)
 -			{
 -				outfit_folder->setOpen(!outfit_folder->isOpen());
 -				root->setSelectionFromRoot(outfit_folder,TRUE);
 -				root->scrollToShowSelection();
 -			}
 -		}
 -	}
 -}
 -
 -// *TODO: obsolete?
 -void LLSidepanelAppearance::onEditAppearanceButtonClicked()
 -{
 -	if (gAgentWearables.areWearablesLoaded())
 -	{
 -		LLVOAvatarSelf::onCustomizeStart();
 -	}
 -}
 -
 -void LLSidepanelAppearance::onNewOutfitButtonClicked()
 -{
 -	if (!mOutfitEdit->getVisible())
 -	{
 -		mPanelOutfitsInventory->onSave();
 -	}
 -}
 -
 -void LLSidepanelAppearance::showOutfitsInventoryPanel()
 -{
 -	toggleWearableEditPanel(FALSE);
 -	toggleOutfitEditPanel(FALSE);
 -	toggleMyOutfitsPanel(TRUE);
 -}
 -
 -void LLSidepanelAppearance::showOutfitEditPanel()
 -{
 -	if (mOutfitEdit && mOutfitEdit->getVisible()) return;
 -
 -	// Accordion's state must be reset in all cases except the one when user
 -	// is returning back to the mOutfitEdit panel from the mEditWearable panel.
 -	// The simplest way to control this is to check the visibility state of the mEditWearable
 -	// BEFORE it is changed by the call to the toggleWearableEditPanel(FALSE, NULL, TRUE).
 -	if (mEditWearable != NULL && !mEditWearable->getVisible() && mOutfitEdit != NULL)
 -	{
 -		mOutfitEdit->resetAccordionState();
 -	}
 -
 -	// If we're exiting the edit wearable view, and the camera was not focused on the avatar
 -	// (e.g. such as if we were editing a physics param), then skip the outfits edit mode since
 -	// otherwise this would trigger the camera focus mode.
 -	if (mEditWearable != NULL && mEditWearable->getVisible() && !gAgentCamera.cameraCustomizeAvatar())
 -	{
 -		showOutfitsInventoryPanel();
 -		return;
 -	}
 -
 -	toggleMyOutfitsPanel(FALSE);
 -	toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode
 -	toggleOutfitEditPanel(TRUE);
 -}
 -
 -void LLSidepanelAppearance::showWearableEditPanel(LLViewerWearable *wearable /* = NULL*/, BOOL disable_camera_switch)
 -{
 -	toggleMyOutfitsPanel(FALSE);
 -	toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode
 -	toggleWearableEditPanel(TRUE, wearable, disable_camera_switch);
 -}
 -
 -void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible)
 -{
 -	if (!mPanelOutfitsInventory || mPanelOutfitsInventory->getVisible() == visible)
 -	{
 -		// visibility isn't changing, hence nothing to do
 -		return;
 -	}
 -
 -	mPanelOutfitsInventory->setVisible(visible);
 -
 -	// *TODO: Move these controls to panel_outfits_inventory.xml
 -	// so that we don't need to toggle them explicitly.
 -	mFilterEditor->setVisible(visible);
 -	mNewOutfitBtn->setVisible(visible);
 -	mCurrOutfitPanel->setVisible(visible);
 -
 -	if (visible)
 -	{
 -		mPanelOutfitsInventory->onOpen(LLSD());
 -	}
 -}
 -
 -void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch)
 -{
 -	if (!mOutfitEdit || mOutfitEdit->getVisible() == visible)
 -	{
 -		// visibility isn't changing, hence nothing to do
 -		return;
 -	}
 -
 -	mOutfitEdit->setVisible(visible);
 -
 -	if (visible)
 -	{
 -		mOutfitEdit->onOpen(LLSD());
 -		LLVOAvatarSelf::onCustomizeStart(disable_camera_switch);
 -	}
 -	else 
 -	{
 -		if (!disable_camera_switch)   // if we're just switching between outfit and wearable editing, don't end customization.
 -		{
 -			LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch);
 -		}
 -	}
 -}
 -
 -void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch)
 -{
 -	if (!mEditWearable || mEditWearable->getVisible() == visible)
 -	{
 -		// visibility isn't changing, hence nothing to do
 -		return;
 -	}
 -
 -	if (!wearable)
 -	{
 -		wearable = gAgentWearables.getViewerWearable(LLWearableType::WT_SHAPE, 0);
 -	}
 -	if (!wearable)
 -	{
 -		return;
 -	}
 -
 -	// Toggle panel visibility.
 -	mEditWearable->setVisible(visible);
 -
 -	if (visible)
 -	{
 -		LLVOAvatarSelf::onCustomizeStart(disable_camera_switch);
 -		mEditWearable->setWearable(wearable, disable_camera_switch);
 -		mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency
 -	}
 -	else
 -	{
 -		// Save changes if closing.
 -		mEditWearable->saveChanges();
 -		if (!disable_camera_switch)   // if we're just switching between outfit and wearable editing, don't end customization.
 -		{
 -			LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch);
 -		}
 -	}
 -}
 -
 -void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name)
 -{
 -	// Set current outfit status (wearing/unsaved).
 -	bool dirty = LLAppearanceMgr::getInstance()->isOutfitDirty();
 -	std::string cof_status_str = getString(dirty ? "Unsaved Changes" : "Now Wearing");
 -	mOutfitStatus->setText(cof_status_str);
 -
 -	if (name == "")
 -	{
 -		std::string outfit_name;
 -		if (LLAppearanceMgr::getInstance()->getBaseOutfitName(outfit_name))
 -		{
 -				mCurrentLookName->setText(outfit_name);
 -				return;
 -		}
 -
 -		std::string string_name = gAgentWearables.isCOFChangeInProgress() ? "Changing outfits" : "No Outfit";
 -		mCurrentLookName->setText(getString(string_name));
 -		mOpenOutfitBtn->setEnabled(FALSE);
 -	}
 -	else
 -	{
 -		mCurrentLookName->setText(name);
 -		// Can't just call update verbs since the folder link may not have been created yet.
 -		mOpenOutfitBtn->setEnabled(TRUE);
 -	}
 -}
 -
 -//static
 -void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *data, BOOL disable_camera_switch)
 -{
 -	LLFloaterSidePanelContainer::showPanel("appearance", LLSD());
 -
 -	LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(data);
 -	if (panel)
 -	{
 -		panel->showWearableEditPanel(wearable, disable_camera_switch);
 -	}
 -}
 -
 -// Fetch currently worn items and only enable the New Look button after everything's been
 -// fetched.  Alternatively, we could stuff this logic into llagentwearables::makeNewOutfitLinks.
 -void LLSidepanelAppearance::fetchInventory()
 -{
 -
 -	mNewOutfitBtn->setEnabled(false);
 -	uuid_vec_t ids;
 -	LLUUID item_id;
 -	for(S32 type = (S32)LLWearableType::WT_SHAPE; type < (S32)LLWearableType::WT_COUNT; ++type)
 -	{
 -		for (U32 index = 0; index < gAgentWearables.getWearableCount((LLWearableType::EType)type); ++index)
 -		{
 -			item_id = gAgentWearables.getWearableItemID((LLWearableType::EType)type, index);
 -			if(item_id.notNull())
 -			{
 -				ids.push_back(item_id);
 -			}
 -		}
 -	}
 -
 -	if (isAgentAvatarValid())
 -	{
 -		for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); 
 -			 iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter)
 -		{
 -			LLViewerJointAttachment* attachment = iter->second;
 -			if (!attachment) continue;
 -			for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
 -				 attachment_iter != attachment->mAttachedObjects.end();
 -				 ++attachment_iter)
 -			{
 -				LLViewerObject* attached_object = (*attachment_iter);
 -				if (!attached_object) continue;
 -				const LLUUID& item_id = attached_object->getAttachmentItemID();
 -				if (item_id.isNull()) continue;
 -				ids.push_back(item_id);
 -			}
 -		}
 -	}
 -
 -	LLCurrentlyWornFetchObserver *fetch_worn = new LLCurrentlyWornFetchObserver(ids, this);
 -	fetch_worn->startFetch();
 -	// If no items to be fetched, done will never be triggered.
 -	// TODO: Change LLInventoryFetchItemsObserver::fetchItems to trigger done() on this condition.
 -	if (fetch_worn->isFinished())
 -	{
 -		fetch_worn->done();
 -	}
 -	else
 -	{
 -		gInventory.addObserver(fetch_worn);
 -	}
 -}
 -
 -void LLSidepanelAppearance::inventoryFetched()
 -{
 -	mNewOutfitBtn->setEnabled(true);
 -}
 -
 -void LLSidepanelAppearance::setWearablesLoading(bool val)
 -{
 -	getChildView("wearables_loading_indicator")->setVisible( val);
 -	getChildView("edit_outfit_btn")->setVisible( !val);
 -
 -	if (!val)
 -	{
 -		// refresh outfit name when COF is already changed.
 -		refreshCurrentOutfitName();
 -	}
 -}
 -
 -void LLSidepanelAppearance::showDefaultSubpart()
 -{
 -	if (mEditWearable->getVisible())
 -	{
 -		mEditWearable->showDefaultSubpart();
 -	}
 -}
 -
 -void LLSidepanelAppearance::updateScrollingPanelList()
 -{
 -	if (mEditWearable->getVisible())
 -	{
 -		mEditWearable->updateScrollingPanelList();
 -	}
 -}
 +/** + * @file llsidepanelappearance.cpp + * @brief Side Bar "Appearance" panel + * + * $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" +#include "llsidepanelappearance.h" + +#include "llaccordionctrltab.h" +#include "llagent.h" +#include "llagentcamera.h" +#include "llagentwearables.h" +#include "llappearancemgr.h" +#include "llfloatersidepanelcontainer.h" +#include "llfolderview.h" +#include "llinventorypanel.h" +#include "llfiltereditor.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llfoldervieweventlistener.h" +#include "lloutfitobserver.h" +#include "llpaneleditwearable.h" +#include "llpaneloutfitsinventory.h" +#include "lltextbox.h" +#include "lluictrlfactory.h" +#include "llviewercontrol.h" +#include "llviewerregion.h" +#include "llvoavatarself.h" +#include "llviewerwearable.h" + +static LLRegisterPanelClassWrapper<LLSidepanelAppearance> t_appearance("sidepanel_appearance"); + +class LLCurrentlyWornFetchObserver : public LLInventoryFetchItemsObserver +{ +public: +	LLCurrentlyWornFetchObserver(const uuid_vec_t &ids, +								 LLSidepanelAppearance *panel) : +		LLInventoryFetchItemsObserver(ids), +		mPanel(panel) +	{} +	~LLCurrentlyWornFetchObserver() {} +	virtual void done() +	{ +		mPanel->inventoryFetched(); +		gInventory.removeObserver(this); +		delete this; +	} +private: +	LLSidepanelAppearance *mPanel; +}; + +LLSidepanelAppearance::LLSidepanelAppearance() : +	LLPanel(), +	mFilterSubString(LLStringUtil::null), +	mFilterEditor(NULL), +	mOutfitEdit(NULL), +	mCurrOutfitPanel(NULL), +	mOpened(false) +{ +	LLOutfitObserver& outfit_observer =  LLOutfitObserver::instance(); +	outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); +	outfit_observer.addBOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); +	outfit_observer.addCOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); + +	gAgentWearables.addLoadingStartedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, true)); +	gAgentWearables.addLoadedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, false)); +} + +LLSidepanelAppearance::~LLSidepanelAppearance() +{ +} + +// virtual +BOOL LLSidepanelAppearance::postBuild() +{ +	mOpenOutfitBtn = getChild<LLButton>("openoutfit_btn"); +	mOpenOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onOpenOutfitButtonClicked, this)); + +	mEditAppearanceBtn = getChild<LLButton>("editappearance_btn"); +	mEditAppearanceBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onEditAppearanceButtonClicked, this)); + +	childSetAction("edit_outfit_btn", boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this)); + +	mNewOutfitBtn = getChild<LLButton>("newlook_btn"); +	mNewOutfitBtn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onNewOutfitButtonClicked, this)); +	mNewOutfitBtn->setEnabled(false); + +	mFilterEditor = getChild<LLFilterEditor>("Filter"); +	if (mFilterEditor) +	{ +		mFilterEditor->setCommitCallback(boost::bind(&LLSidepanelAppearance::onFilterEdit, this, _2)); +	} + +	mPanelOutfitsInventory = dynamic_cast<LLPanelOutfitsInventory *>(getChild<LLPanel>("panel_outfits_inventory")); + +	mOutfitEdit = dynamic_cast<LLPanelOutfitEdit*>(getChild<LLPanel>("panel_outfit_edit")); +	if (mOutfitEdit) +	{ +		LLButton* back_btn = mOutfitEdit->getChild<LLButton>("back_btn"); +		if (back_btn) +		{ +			back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitsInventoryPanel, this)); +		} + +	} + +	mEditWearable = dynamic_cast<LLPanelEditWearable*>(getChild<LLPanel>("panel_edit_wearable")); +	if (mEditWearable) +	{ +		LLButton* edit_wearable_back_btn = mEditWearable->getChild<LLButton>("back_btn"); +		if (edit_wearable_back_btn) +		{ +			edit_wearable_back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitEditPanel, this)); +		} +	} + +	mCurrentLookName = getChild<LLTextBox>("currentlook_name"); + +	mOutfitStatus = getChild<LLTextBox>("currentlook_status"); +	 +	mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook"); + + +	setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2)); + +	return TRUE; +} + +// virtual +void LLSidepanelAppearance::onOpen(const LLSD& key) +{ +	if (!key.has("type")) +	{ +		// No specific panel requested. +		// If we're opened for the first time then show My Outfits. +		// Else do nothing. +		if (!mOpened) +		{ +			showOutfitsInventoryPanel(); +		} +	} +	else +	{ +		// Switch to the requested panel. +		std::string type = key["type"].asString(); +		if (type == "my_outfits") +		{ +			showOutfitsInventoryPanel(); +		} +		else if (type == "edit_outfit") +		{ +			showOutfitEditPanel(); +		} +		else if (type == "edit_shape") +		{ +			showWearableEditPanel(); +		} +	} + +	mOpened = true; +} + +void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility) +{ +	LLSD visibility; +	visibility["visible"] = new_visibility.asBoolean(); +	visibility["reset_accordion"] = false; +	updateToVisibility(visibility); +} + +void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) +{ +	if (new_visibility["visible"].asBoolean()) +	{ +		const BOOL is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible(); +		const BOOL is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible(); + +		if (is_outfit_edit_visible || is_wearable_edit_visible) +		{ +			const LLViewerWearable *wearable_ptr = mEditWearable->getWearable(); +			if (!wearable_ptr) +			{ +				llwarns << "Visibility change to invalid wearable" << llendl; +				return; +			} +			// Disable camera switch is currently just for WT_PHYSICS type since we don't want to freeze the avatar +			// when editing its physics. +			if (!gAgentCamera.cameraCustomizeAvatar()) +			{ +				LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType())); +			} +			if (is_wearable_edit_visible) +			{ +				if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE) +				{ +					// we're no longer wearing the wearable we were last editing, switch back to outfit editor +					showOutfitEditPanel(); +				} +			} + +			if (is_outfit_edit_visible && new_visibility["reset_accordion"].asBoolean()) +			{ +				mOutfitEdit->resetAccordionState(); +			} +		} +	} +	else +	{ +		if (gAgentCamera.cameraCustomizeAvatar() && gSavedSettings.getBOOL("AppearanceCameraMovement")) +		{ +			gAgentCamera.changeCameraToDefault(); +			gAgentCamera.resetView(); +		}	 +	} +} + +void LLSidepanelAppearance::onFilterEdit(const std::string& search_string) +{ +	if (mFilterSubString != search_string) +	{ +		mFilterSubString = search_string; + +		// Searches are case-insensitive +		// but we don't convert the typed string to upper-case so that it can be fed to the web search as-is. + +		mPanelOutfitsInventory->onSearchEdit(mFilterSubString); +	} +} + +void LLSidepanelAppearance::onOpenOutfitButtonClicked() +{ +	const LLViewerInventoryItem *outfit_link = LLAppearanceMgr::getInstance()->getBaseOutfitLink(); +	if (!outfit_link) +		return; +	if (!outfit_link->getIsLinkType()) +		return; + +	LLAccordionCtrlTab* tab_outfits = mPanelOutfitsInventory->findChild<LLAccordionCtrlTab>("tab_outfits"); +	if (tab_outfits) +	{ +		tab_outfits->changeOpenClose(FALSE); +		LLInventoryPanel *inventory_panel = tab_outfits->findChild<LLInventoryPanel>("outfitslist_tab"); +		if (inventory_panel) +		{ +			LLFolderView* root = inventory_panel->getRootFolder(); +			LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID()); +			if (outfit_folder) +			{ +				outfit_folder->setOpen(!outfit_folder->isOpen()); +				root->setSelectionFromRoot(outfit_folder,TRUE); +				root->scrollToShowSelection(); +			} +		} +	} +} + +// *TODO: obsolete? +void LLSidepanelAppearance::onEditAppearanceButtonClicked() +{ +	if (gAgentWearables.areWearablesLoaded()) +	{ +		LLVOAvatarSelf::onCustomizeStart(); +	} +} + +void LLSidepanelAppearance::onNewOutfitButtonClicked() +{ +	if (!mOutfitEdit->getVisible()) +	{ +		mPanelOutfitsInventory->onSave(); +	} +} + +void LLSidepanelAppearance::showOutfitsInventoryPanel() +{ +	toggleWearableEditPanel(FALSE); +	toggleOutfitEditPanel(FALSE); +	toggleMyOutfitsPanel(TRUE); +} + +void LLSidepanelAppearance::showOutfitEditPanel() +{ +	if (mOutfitEdit && mOutfitEdit->getVisible()) return; + +	// Accordion's state must be reset in all cases except the one when user +	// is returning back to the mOutfitEdit panel from the mEditWearable panel. +	// The simplest way to control this is to check the visibility state of the mEditWearable +	// BEFORE it is changed by the call to the toggleWearableEditPanel(FALSE, NULL, TRUE). +	if (mEditWearable != NULL && !mEditWearable->getVisible() && mOutfitEdit != NULL) +	{ +		mOutfitEdit->resetAccordionState(); +	} + +	// If we're exiting the edit wearable view, and the camera was not focused on the avatar +	// (e.g. such as if we were editing a physics param), then skip the outfits edit mode since +	// otherwise this would trigger the camera focus mode. +	if (mEditWearable != NULL && mEditWearable->getVisible() && !gAgentCamera.cameraCustomizeAvatar()) +	{ +		showOutfitsInventoryPanel(); +		return; +	} + +	toggleMyOutfitsPanel(FALSE); +	toggleWearableEditPanel(FALSE, NULL, TRUE); // don't switch out of edit appearance mode +	toggleOutfitEditPanel(TRUE); +} + +void LLSidepanelAppearance::showWearableEditPanel(LLViewerWearable *wearable /* = NULL*/, BOOL disable_camera_switch) +{ +	toggleMyOutfitsPanel(FALSE); +	toggleOutfitEditPanel(FALSE, TRUE); // don't switch out of edit appearance mode +	toggleWearableEditPanel(TRUE, wearable, disable_camera_switch); +} + +void LLSidepanelAppearance::toggleMyOutfitsPanel(BOOL visible) +{ +	if (!mPanelOutfitsInventory || mPanelOutfitsInventory->getVisible() == visible) +	{ +		// visibility isn't changing, hence nothing to do +		return; +	} + +	mPanelOutfitsInventory->setVisible(visible); + +	// *TODO: Move these controls to panel_outfits_inventory.xml +	// so that we don't need to toggle them explicitly. +	mFilterEditor->setVisible(visible); +	mNewOutfitBtn->setVisible(visible); +	mCurrOutfitPanel->setVisible(visible); + +	if (visible) +	{ +		mPanelOutfitsInventory->onOpen(LLSD()); +	} +} + +void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_camera_switch) +{ +	if (!mOutfitEdit || mOutfitEdit->getVisible() == visible) +	{ +		// visibility isn't changing, hence nothing to do +		return; +	} + +	mOutfitEdit->setVisible(visible); + +	if (visible) +	{ +		mOutfitEdit->onOpen(LLSD()); +		LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); +	} +	else  +	{ +		if (!disable_camera_switch)   // if we're just switching between outfit and wearable editing, don't end customization. +		{ +			LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); +			LLAppearanceMgr::getInstance()->setOutfitDirty( FALSE ); +		} +	} +} + +void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) +{ +	if (!mEditWearable || mEditWearable->getVisible() == visible) +	{ +		// visibility isn't changing, hence nothing to do +		return; +	} + +	if (!wearable) +	{ +		wearable = gAgentWearables.getViewerWearable(LLWearableType::WT_SHAPE, 0); +	} +	if (!wearable) +	{ +		return; +	} + +	// Toggle panel visibility. +	mEditWearable->setVisible(visible); + +	if (visible) +	{ +		LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); +		mEditWearable->setWearable(wearable, disable_camera_switch); +		mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency +	} +	else +	{ +		// Save changes if closing. +		mEditWearable->saveChanges(); +		if (!disable_camera_switch)   // if we're just switching between outfit and wearable editing, don't end customization. +		{ +			LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); +		} +	} +} + +void LLSidepanelAppearance::refreshCurrentOutfitName(const std::string& name) +{ +	// Set current outfit status (wearing/unsaved). +	bool dirty = LLAppearanceMgr::getInstance()->isOutfitDirty(); +	std::string cof_status_str = getString(dirty ? "Unsaved Changes" : "Now Wearing"); +	mOutfitStatus->setText(cof_status_str); + +	if (name == "") +	{ +		std::string outfit_name; +		if (LLAppearanceMgr::getInstance()->getBaseOutfitName(outfit_name)) +		{ +				mCurrentLookName->setText(outfit_name); +				return; +		} + +		std::string string_name = gAgentWearables.isCOFChangeInProgress() ? "Changing outfits" : "No Outfit"; +		mCurrentLookName->setText(getString(string_name)); +		mOpenOutfitBtn->setEnabled(FALSE); +	} +	else +	{ +		mCurrentLookName->setText(name); +		// Can't just call update verbs since the folder link may not have been created yet. +		mOpenOutfitBtn->setEnabled(TRUE); +	} +} + +//static +void LLSidepanelAppearance::editWearable(LLViewerWearable *wearable, LLView *data, BOOL disable_camera_switch) +{ +	LLFloaterSidePanelContainer::showPanel("appearance", LLSD()); + +	LLSidepanelAppearance *panel = dynamic_cast<LLSidepanelAppearance*>(data); +	if (panel) +	{ +		panel->showWearableEditPanel(wearable, disable_camera_switch); +	} +} + +// Fetch currently worn items and only enable the New Look button after everything's been +// fetched.  Alternatively, we could stuff this logic into llagentwearables::makeNewOutfitLinks. +void LLSidepanelAppearance::fetchInventory() +{ + +	mNewOutfitBtn->setEnabled(false); +	uuid_vec_t ids; +	LLUUID item_id; +	for(S32 type = (S32)LLWearableType::WT_SHAPE; type < (S32)LLWearableType::WT_COUNT; ++type) +	{ +		for (U32 index = 0; index < gAgentWearables.getWearableCount((LLWearableType::EType)type); ++index) +		{ +			item_id = gAgentWearables.getWearableItemID((LLWearableType::EType)type, index); +			if(item_id.notNull()) +			{ +				ids.push_back(item_id); +			} +		} +	} + +	if (isAgentAvatarValid()) +	{ +		for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin();  +			 iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) +		{ +			LLViewerJointAttachment* attachment = iter->second; +			if (!attachment) continue; +			for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); +				 attachment_iter != attachment->mAttachedObjects.end(); +				 ++attachment_iter) +			{ +				LLViewerObject* attached_object = (*attachment_iter); +				if (!attached_object) continue; +				const LLUUID& item_id = attached_object->getAttachmentItemID(); +				if (item_id.isNull()) continue; +				ids.push_back(item_id); +			} +		} +	} + +	LLCurrentlyWornFetchObserver *fetch_worn = new LLCurrentlyWornFetchObserver(ids, this); +	fetch_worn->startFetch(); +	// If no items to be fetched, done will never be triggered. +	// TODO: Change LLInventoryFetchItemsObserver::fetchItems to trigger done() on this condition. +	if (fetch_worn->isFinished()) +	{ +		fetch_worn->done(); +	} +	else +	{ +		gInventory.addObserver(fetch_worn); +	} +} + +void LLSidepanelAppearance::inventoryFetched() +{ +	mNewOutfitBtn->setEnabled(true); +} + +void LLSidepanelAppearance::setWearablesLoading(bool val) +{ +	getChildView("wearables_loading_indicator")->setVisible( val); +	getChildView("edit_outfit_btn")->setVisible( !val); + +	if (!val) +	{ +		// refresh outfit name when COF is already changed. +		refreshCurrentOutfitName(); +	} +} + +void LLSidepanelAppearance::showDefaultSubpart() +{ +	if (mEditWearable->getVisible()) +	{ +		mEditWearable->showDefaultSubpart(); +	} +} + +void LLSidepanelAppearance::updateScrollingPanelList() +{ +	if (mEditWearable->getVisible()) +	{ +		mEditWearable->updateScrollingPanelList(); +	} +} diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index bd8377e281..25abf768cb 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -417,14 +417,21 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  			gAgent.setTeleportMessage(  				LLAgent::sTeleportProgressMessages["arriving"]);  			gTextureList.mForceResetTextureStats = TRUE; -			gAgentCamera.resetView(TRUE, TRUE); -			 +			gAgentCamera.resetView(TRUE, TRUE);	 +			if ( gSavedSettings.getBOOL("DisablePrecacheDelayAfterTeleporting") ) +			{ +				gViewerWindow->setShowProgress(FALSE); +				gTeleportDisplay = FALSE; +				gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); +			} +				  			break;  		case LLAgent::TELEPORT_ARRIVING:  			// Make the user wait while content "pre-caches"  			{  				F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); +			  				if( arrival_fraction > 1.f )  				{  					arrival_fraction = 1.f; | 
