From 6db6d81b0a90fe7b48a3ccf64ba768e5772397c8 Mon Sep 17 00:00:00 2001
From: Eric Tulla <tulla@lindenlab.com>
Date: Thu, 5 Mar 2009 00:29:27 +0000
Subject: Merging in Avatar Pipeline work for Viewer 1.23 (QAR-1272). No
 conflicts in the merge.

Result of:
svn merge -r113372:113479 $branches/avatar-pipeline/avatar-pipeline-merge-r113370 .
---
 doc/contributions.txt                     |    1 +
 indra/llcommon/imageids.h                 |    1 +
 indra/llrender/llimagegl.cpp              |    4 +-
 indra/llrender/llrender.cpp               |   20 +-
 indra/llui/llpanel.cpp                    |    6 +-
 indra/llui/llpanel.h                      |    2 +-
 indra/llui/lltabcontainer.cpp             |   47 +-
 indra/llui/lltabcontainer.h               |   10 +-
 indra/newview/CMakeLists.txt              |    4 +-
 indra/newview/app_settings/settings.xml   |   33 +-
 indra/newview/llagent.cpp                 |  107 +-
 indra/newview/llappearance.h              |    8 +-
 indra/newview/llassetuploadresponders.cpp |   44 +
 indra/newview/llassetuploadresponders.h   |   16 +
 indra/newview/lldrawpoolavatar.cpp        |    2 +-
 indra/newview/lldrawpoolavatar.h          |    7 +-
 indra/newview/llfloateranimpreview.cpp    |    2 +-
 indra/newview/llfloateravatartextures.cpp |   56 +-
 indra/newview/llfloateravatartextures.h   |   22 +-
 indra/newview/llhudtext.cpp               |   18 +-
 indra/newview/llinventorybridge.cpp       |    4 +-
 indra/newview/llprogressview.cpp          |    2 +-
 indra/newview/lltexlayer.cpp              |  129 +-
 indra/newview/lltexlayer.h                |    3 +-
 indra/newview/lltooldraganddrop.cpp       |    2 +-
 indra/newview/lltoolfocus.cpp             |    2 +-
 indra/newview/lltoolmorph.cpp             |    4 +
 indra/newview/llviewercontrol.cpp         |   26 +-
 indra/newview/llviewerjoint.cpp           |   10 +
 indra/newview/llviewerjoint.h             |    7 +
 indra/newview/llviewerjointmesh.cpp       |    7 +-
 indra/newview/llviewermenu.cpp            |   37 +-
 indra/newview/llviewermessage.cpp         |    2 +-
 indra/newview/llviewerobject.cpp          |    2 +-
 indra/newview/llviewerregion.cpp          |    3 +-
 indra/newview/llvoavatar.cpp              | 4005 +++++++++++------------------
 indra/newview/llvoavatar.h                |  967 +++----
 indra/newview/llvoavatardefines.cpp       |  227 ++
 indra/newview/llvoavatardefines.h         |  209 ++
 indra/newview/llwearable.cpp              |   39 +-
 indra/newview/llwearable.h                |   12 +-
 indra/newview/llwearablelist.cpp          |   11 +-
 indra/newview/pipeline.cpp                |    1 +
 indra/newview/pipeline.h                  |    1 +
 44 files changed, 2715 insertions(+), 3407 deletions(-)
 create mode 100644 indra/newview/llvoavatardefines.cpp
 create mode 100644 indra/newview/llvoavatardefines.h

diff --git a/doc/contributions.txt b/doc/contributions.txt
index b66298371c..56b3159559 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -380,6 +380,7 @@ Robin Cornelius
 	VWR-2488
 	VWR-9557
 Ryozu Kojima
+	VWR-53
 	VWR-287
 Sammy Frederix
 	VWR-6186
diff --git a/indra/llcommon/imageids.h b/indra/llcommon/imageids.h
index 57507b3a30..d65701e376 100644
--- a/indra/llcommon/imageids.h
+++ b/indra/llcommon/imageids.h
@@ -56,6 +56,7 @@ const LLUUID IMG_SPARK			("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
 const LLUUID IMG_FIRE			("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
 const LLUUID IMG_FACE_SELECT    ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
 const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
+const LLUUID IMG_INVISIBLE		("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // dataserver
 
 const LLUUID IMG_EXPLOSION				("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
 const LLUUID IMG_EXPLOSION_2			("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 307147798e..c784019cd9 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -510,10 +510,8 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
 		is_compressed = true;
 	}
 
-	{
 // 		LLFastTimer t2(LLFastTimer::FTM_TEMP2);
-		llverify(gGL.getTexUnit(0)->bind(this));
-	}
+	gGL.getTexUnit(0)->bind(this);
 	
 	if (mUseMipMaps)
 	{
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index bee41f556e..ba95a19787 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -197,8 +197,8 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind)
 
 		return texture->bindDefaultImage(mIndex);
 	}
-	
-	if (texture != NULL && ((mCurrTexture != texture->getTexName()) || forceBind))
+
+	if ((mCurrTexture != texture->getTexName()) || forceBind)
 	{
 		activate();
 		enable(texture->getTarget());
@@ -213,9 +213,8 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind)
 			setTextureAddressMode(texture->mAddressMode);
 			setTextureFilteringOption(texture->mFilterOption);
 		}
-		return true;
 	}
-	return false;
+	return true;
 }
 
 bool LLTexUnit::bind(LLCubeMap* cubeMap)
@@ -224,7 +223,13 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
 
 	gGL.flush();
 
-	if (cubeMap != NULL && mCurrTexture != cubeMap->mImages[0]->getTexName())
+	if (cubeMap == NULL)
+	{
+		llwarns << "NULL LLTexUnit::bind cubemap" << llendl;
+		return false;
+	}
+
+	if (mCurrTexture != cubeMap->mImages[0]->getTexName())
 	{
 		if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
 		{
@@ -244,10 +249,11 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
 		}
 		else
 		{
-			llwarns << "Using cube map without extension!" << llendl
+			llwarns << "Using cube map without extension!" << llendl;
+			return false;
 		}
 	}
-	return false;
+	return true;
 }
 
 // LLRenderTarget is unavailible on the mapserver since it uses FBOs.
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 76664d93a7..92d045d114 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -907,7 +907,7 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
 	return NULL;
 }
 
-void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata)
+void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool))
 {
 	LLTabContainer* child = getChild<LLTabContainer>(id);
 	if (child)
@@ -917,6 +917,10 @@ void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string
 		{
 			child->setTabChangeCallback(panel, on_tab_clicked);
 			child->setTabUserData(panel, userdata);
+			if (on_precommit)
+			{
+				child->setTabPrecommitChangeCallback(panel, on_precommit);
+			}
 		}
 	}
 }
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index b8cb8f1417..756d02ef7d 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -196,7 +196,7 @@ public:
 	// LLTabContainer
 	void childShowTab(const std::string& id, const std::string& tabname, bool visible = true);
 	LLPanel *childGetVisibleTab(const std::string& id) const;
-	void childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata);
+	void childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool) = NULL);
 
 	// LLTextBox
 	void childSetWrappedText(const std::string& id, const std::string& text, bool visible = true);
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 1796dd1150..e3ebd0057d 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -71,6 +71,7 @@ LLTabContainer::LLTabContainer(const std::string& name, const LLRect& rect, TabP
 	: 
 	LLPanel(name, rect, bordered),
 	mCurrentTabIdx(-1),
+	mNextTabIdx(-1),
 	mTabsHidden(FALSE),
 	mScrolled(FALSE),
 	mScrollPos(0),
@@ -1150,9 +1151,37 @@ BOOL LLTabContainer::selectTab(S32 which)
 	{
 		return FALSE;
 	}
-	
+
+	if (!selected_tuple->mPrecommitChangeCallback)
+	{
+		return setTab(which);
+	}
+
+	mNextTabIdx = which;
+	selected_tuple->mPrecommitChangeCallback(selected_tuple->mUserData, false);
+	return TRUE;
+}
+
+BOOL LLTabContainer::setTab(S32 which)
+{
+	if (which == -1)
+	{
+		if (mNextTabIdx == -1)
+		{
+			return FALSE;
+		}
+		which = mNextTabIdx;
+		mNextTabIdx = -1;
+	}
+
+	LLTabTuple* selected_tuple = getTab(which);
+	if (!selected_tuple)
+	{
+		return FALSE;
+	}
+
 	BOOL is_visible = FALSE;
-	if (getTab(which)->mButton->getEnabled())
+	if (selected_tuple->mButton->getEnabled())
 	{
 		setCurrentPanelIndex(which);
 
@@ -1332,6 +1361,15 @@ void LLTabContainer::setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(v
 	}
 }
 
+void LLTabContainer::setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool))
+{
+	LLTabTuple* tuplep = getTabByPanel(tab);
+	if (tuplep)
+	{
+		tuplep->mPrecommitChangeCallback = on_precommit;
+	}
+}
+
 void LLTabContainer::setTabUserData(LLPanel* tab, void* userdata)
 {
 	LLTabTuple* tuplep = getTabByPanel(tab);
@@ -1371,11 +1409,6 @@ void LLTabContainer::onTabBtn( void* userdata )
 	LLTabTuple* tuple = (LLTabTuple*) userdata;
 	LLTabContainer* self = tuple->mTabContainer;
 	self->selectTabPanel( tuple->mTabPanel );
-	
-	if( tuple->mOnChangeCallback )
-	{
-		tuple->mOnChangeCallback( tuple->mUserData, true );
-	}
 
 	tuple->mTabPanel->setFocus(TRUE);
 }
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 001b399938..8117cdee9b 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -108,6 +108,7 @@ public:
 	BOOL 		selectTabPanel( LLPanel* child );
 	BOOL 		selectTab(S32 which);
 	BOOL 		selectTabByName(const std::string& title);
+	BOOL		setTab(S32 which);
 
 	BOOL        getTabPanelFlashing(LLPanel* child);
 	void		setTabPanelFlashing(LLPanel* child, BOOL state);
@@ -119,6 +120,7 @@ public:
 	S32			getTopBorderHeight() const;
 	
 	void 		setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*,bool));
+	void		setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool));
 	void 		setTabUserData(LLPanel* tab, void* userdata);
 
 	void 		setRightTabBtnOffset( S32 offset );
@@ -148,12 +150,14 @@ private:
 	struct LLTabTuple
 	{
 		LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b,
-					void (*cb)(void*,bool), void* userdata, LLTextBox* placeholder = NULL )
+					void (*cb)(void*,bool), void* userdata, LLTextBox* placeholder = NULL, 
+					void (*pcb)(void*,bool) = NULL)
 			:
 			mTabContainer(c),
 			mTabPanel(p),
 			mButton(b),
 			mOnChangeCallback( cb ),
+			mPrecommitChangeCallback( pcb ),
 			mUserData( userdata ),
 			mOldState(FALSE),
 			mPlaceholderText(placeholder),
@@ -164,6 +168,9 @@ private:
 		LLPanel*		 mTabPanel;
 		LLButton*		 mButton;
 		void			 (*mOnChangeCallback)(void*, bool);
+		void			 (*mPrecommitChangeCallback)(void*,bool);		// Precommit callback gets called before tab is changed and 
+																		// can prevent it from being changed. onChangeCallback is called
+																		// immediately after tab is actually changed - Nyx
 		void*			 mUserData;
 		BOOL			 mOldState;
 		LLTextBox*		 mPlaceholderText;
@@ -200,6 +207,7 @@ private:
 	tuple_list_t					mTabList;
 	
 	S32								mCurrentTabIdx;
+	S32								mNextTabIdx;
 	BOOL							mTabsHidden;
 
 	BOOL							mScrolled;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 9ec54f1851..76be212c95 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -203,7 +203,6 @@ set(viewer_SOURCE_FILES
     llfollowcam.cpp
     llframestats.cpp
     llframestatview.cpp
-    llgenepool.cpp
     llgesturemgr.cpp
     llgivemoney.cpp
     llglsandbox.cpp
@@ -406,6 +405,7 @@ set(viewer_SOURCE_FILES
     llvlcomposition.cpp
     llvlmanager.cpp
     llvoavatar.cpp
+    llvoavatardefines.cpp
     llvocache.cpp
     llvoclouds.cpp
     llvograss.cpp
@@ -605,7 +605,6 @@ set(viewer_HEADER_FILES
     llfollowcam.h
     llframestats.h
     llframestatview.h
-    llgenepool.h
     llgesturemgr.h
     llgivemoney.h
     llgroupmgr.h
@@ -810,6 +809,7 @@ set(viewer_HEADER_FILES
     llvlcomposition.h
     llvlmanager.h
     llvoavatar.h
+    llvoavatardefines.h
     llvocache.h
     llvoclouds.h
     llvograss.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index e964799e4c..993033aa2c 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -561,17 +561,6 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <key>AvatarCompositeLimit</key>
-    <map>
-      <key>Comment</key>
-      <string>Maximum number of avatars to display appearance changes on the fly</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>S32</string>
-      <key>Value</key>
-      <integer>5</integer>
-    </map>
     <key>AvatarFeathering</key>
     <map>
       <key>Comment</key>
@@ -6152,6 +6141,17 @@
       <key>Value</key>
       <integer>35</integer>
     </map>
+    <key>RenderAvatarInvisible</key>
+    <map>
+      <key>Comment</key>
+      <string>Set your avatar as Invisible</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
     <key>RenderAvatarVP</key>
     <map>
       <key>Comment</key>
@@ -9921,6 +9921,17 @@
       <string>String</string>
       <key>Value</key>
       <string>c80260ba-41fd-8a46-768a-6bf236360e3a</string>
+    </map>
+	<key>UploadBakedTexOld</key>
+    <map>
+      <key>Comment</key>
+      <string>Forces the baked texture pipeline to upload using the old method.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
     </map>
     <key>UseAltKeyForMenus</key>
     <map>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 569de267e7..d4978566da 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -133,6 +133,8 @@
 #include "llviewerjoystick.h"
 #include "llfollowcam.h"
 
+using namespace LLVOAvatarDefines;
+
 extern LLMenuBarGL* gMenuBarView;
 
 //drone wandering constants
@@ -207,26 +209,6 @@ const F32 MIN_RADIUS_ALPHA_SIZZLE = 0.5f;
 
 const F64 CHAT_AGE_FAST_RATE = 3.0;
 
-const S32 MAX_WEARABLES_PER_LAYERSET = 7;
-
-const EWearableType WEARABLE_BAKE_TEXTURE_MAP[BAKED_TEXTURE_COUNT][MAX_WEARABLES_PER_LAYERSET] = 
-{
-	{ WT_SHAPE,	WT_SKIN,	WT_HAIR,	WT_INVALID,	WT_INVALID,	WT_INVALID,		WT_INVALID    },	// TEX_HEAD_BAKED
-	{ WT_SHAPE, WT_SKIN,	WT_SHIRT,	WT_JACKET,	WT_GLOVES,	WT_UNDERSHIRT,	WT_INVALID	  },	// TEX_UPPER_BAKED
-	{ WT_SHAPE, WT_SKIN,	WT_PANTS,	WT_SHOES,	WT_SOCKS,	WT_JACKET,		WT_UNDERPANTS },	// TEX_LOWER_BAKED
-	{ WT_EYES,	WT_INVALID,	WT_INVALID,	WT_INVALID,	WT_INVALID,	WT_INVALID,		WT_INVALID    },	// TEX_EYES_BAKED
-	{ WT_SKIRT,	WT_INVALID,	WT_INVALID,	WT_INVALID,	WT_INVALID,	WT_INVALID,		WT_INVALID    }		// TEX_SKIRT_BAKED
-};
-
-const LLUUID BAKED_TEXTURE_HASH[BAKED_TEXTURE_COUNT] = 
-{
-	LLUUID("18ded8d6-bcfc-e415-8539-944c0f5ea7a6"),
-	LLUUID("338c29e3-3024-4dbb-998d-7c04cf4fa88f"),
-	LLUUID("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f"),
-	LLUUID("b2cf28af-b840-1071-3c6a-78085d8128b5"),
-	LLUUID("ea800387-ea1a-14e0-56cb-24f2022f969a")
-};
-
 // The agent instance.
 LLAgent gAgent;
 
@@ -424,8 +406,8 @@ LLAgent::LLAgent() :
 		mControlsTakenPassedOnCount[i] = 0;
 	}
 
-	mActiveCacheQueries = new S32[BAKED_TEXTURE_COUNT];
-	for (i = 0; i < (U32)BAKED_TEXTURE_COUNT; i++)
+	mActiveCacheQueries = new S32[BAKED_NUM_INDICES];
+	for (i = 0; i < (U32)BAKED_NUM_INDICES; i++)
 	{
 		mActiveCacheQueries[i] = 0;
 	}
@@ -5756,11 +5738,11 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
 		mesgsys->getU8Fast(_PREHASH_WearableData, _PREHASH_TextureIndex, texture_index, texture_block);
 
 		if (texture_id.notNull() 
-			&& (S32)texture_index < BAKED_TEXTURE_COUNT 
+			&& (S32)texture_index < BAKED_NUM_INDICES 
 			&& gAgent.mActiveCacheQueries[ texture_index ] == query_id)
 		{
 			//llinfos << "Received cached texture " << (U32)texture_index << ": " << texture_id << llendl;
-			avatarp->setCachedBakedTexture((LLVOAvatar::ETextureIndex)LLVOAvatar::sBakedTextureIndices[texture_index], texture_id);
+			avatarp->setCachedBakedTexture(getTextureIndex((EBakedTextureIndex)texture_index), texture_id);
 			//avatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id );
 			gAgent.mActiveCacheQueries[ texture_index ] = 0;
 			num_results++;
@@ -7053,11 +7035,8 @@ void LLAgent::sendAgentSetAppearance()
 		return;
 	}
 
-	llinfos << "TAT: Sent AgentSetAppearance: " <<
-		(( mAvatarObject->getTEImage( LLVOAvatar::TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR )  ? "HEAD " : "head " ) <<
-		(( mAvatarObject->getTEImage( LLVOAvatar::TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "UPPER " : "upper " ) <<
-		(( mAvatarObject->getTEImage( LLVOAvatar::TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "LOWER " : "lower " ) <<
-		(( mAvatarObject->getTEImage( LLVOAvatar::TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR )  ? "EYES" : "eyes" ) << llendl;
+
+	llinfos << "TAT: Sent AgentSetAppearance: " << mAvatarObject->getBakedStatusForPrintout() << llendl;
 	//dumpAvatarTEs( "sendAgentSetAppearance()" );
 
 	LLMessageSystem* msg = gMessageSystem;
@@ -7071,7 +7050,7 @@ void LLAgent::sendAgentSetAppearance()
 	// NOTE -- when we start correcting all of the other Havok geometry 
 	// to compensate for the COLLISION_TOLERANCE ugliness we will have 
 	// to tweak this number again
-	LLVector3 body_size = mAvatarObject->mBodySize;
+	const LLVector3 body_size = mAvatarObject->mBodySize;
 	msg->addVector3Fast(_PREHASH_Size, body_size);	
 
 	// To guard against out of order packets
@@ -7083,19 +7062,18 @@ void LLAgent::sendAgentSetAppearance()
 	// KLW - TAT this will probably need to check the local queue.
 	BOOL textures_current = !mAvatarObject->hasPendingBakedUploads() && mWearablesLoaded;
 
-	S32 baked_texture_index;
-	for( baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++ )
+	for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ )
 	{
-		S32 tex_index = LLVOAvatar::sBakedTextureIndices[baked_texture_index];
+		const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index);
 
 		// if we're not wearing a skirt, we don't need the texture to be baked
-		if (tex_index == LLVOAvatar::TEX_SKIRT_BAKED && !mAvatarObject->isWearingWearableType(WT_SKIRT))
+		if (texture_index == TEX_SKIRT_BAKED && !mAvatarObject->isWearingWearableType(WT_SKIRT))
 		{
 			continue;
 		}
 
 		// IMG_DEFAULT_AVATAR means not baked
-		if (mAvatarObject->getTEImage( tex_index)->getID() == IMG_DEFAULT_AVATAR)
+		if (!mAvatarObject->isTextureDefined(texture_index))
 		{
 			textures_current = FALSE;
 			break;
@@ -7106,50 +7084,56 @@ void LLAgent::sendAgentSetAppearance()
 	if (textures_current)
 	{
 		llinfos << "TAT: Sending cached texture data" << llendl;
-		for (baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++)
+		for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
 		{
+			const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index);
 			LLUUID hash;
-
-			for( S32 wearable_num = 0; wearable_num < MAX_WEARABLES_PER_LAYERSET; wearable_num++ )
+			for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++)
 			{
-				EWearableType wearable_type = WEARABLE_BAKE_TEXTURE_MAP[baked_texture_index][wearable_num];
-
-				LLWearable* wearable = getWearable( wearable_type );
+				// EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num];
+				const EWearableType wearable_type = wearable_dict->mWearablesVec[i];
+				const LLWearable* wearable = getWearable(wearable_type);
 				if (wearable)
 				{
 					hash ^= wearable->getID();
 				}
 			}
-
 			if (hash.notNull())
 			{
-				hash ^= BAKED_TEXTURE_HASH[baked_texture_index];
+				hash ^= wearable_dict->mHashID;
 			}
 
-			S32 tex_index = LLVOAvatar::sBakedTextureIndices[baked_texture_index];
+			const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index);
 
 			msg->nextBlockFast(_PREHASH_WearableData);
 			msg->addUUIDFast(_PREHASH_CacheID, hash);
-			msg->addU8Fast(_PREHASH_TextureIndex, (U8)tex_index);
+			msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index);
 		}
+		msg->nextBlockFast(_PREHASH_ObjectData);
+		mAvatarObject->packTEMessage( gMessageSystem );
+	}
+	else
+	{
+		// If the textures aren't baked, send NULL for texture IDs
+		// This means the baked texture IDs on the server will be untouched.
+		// Once all textures are baked, another AvatarAppearance message will be sent to update the TEs
+		msg->nextBlockFast(_PREHASH_ObjectData);
+		gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, NULL, 0);
 	}
 
-	msg->nextBlockFast(_PREHASH_ObjectData);
-	mAvatarObject->packTEMessage( gMessageSystem );
 
 	S32 transmitted_params = 0;
 	for (LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarObject->getFirstVisualParam();
 		 param;
 		 param = (LLViewerVisualParam*)mAvatarObject->getNextVisualParam())
 	{
-		F32 param_value = param->getWeight();
-	
 		if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
 		{
 			msg->nextBlockFast(_PREHASH_VisualParam );
 			
 			// We don't send the param ids.  Instead, we assume that the receiver has the same params in the same sequence.
-			U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight());
+			const F32 param_value = param->getWeight();
+			const U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight());
 			msg->addU8Fast(_PREHASH_ParamValue, new_weight );
 			transmitted_params++;
 		}
@@ -7388,8 +7372,6 @@ void LLAgent::setWearableOutfit(
 		wearables[i]->writeToAvatar( TRUE );
 	}
 
-	LLFloaterCustomize::setCurrentWearableType( WT_SHAPE );
-
 	// Start rendering & update the server
 	mWearablesLoaded = TRUE; 
 	sendAgentWearablesUpdate();
@@ -7511,14 +7493,15 @@ void LLAgent::queryWearableCache()
 	gMessageSystem->addS32Fast(_PREHASH_SerialNum, mTextureCacheQueryID);
 
 	S32 num_queries = 0;
-	for (S32 baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++)
+	for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ )
 	{
+		const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index);
 		LLUUID hash;
-		for (S32 wearable_num = 0; wearable_num < MAX_WEARABLES_PER_LAYERSET; wearable_num++)
+		for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++)
 		{
-			EWearableType wearable_type = WEARABLE_BAKE_TEXTURE_MAP[baked_texture_index][wearable_num];
-				
-			LLWearable* wearable = getWearable( wearable_type );
+			// EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num];
+			const EWearableType wearable_type = wearable_dict->mWearablesVec[i];
+			const LLWearable* wearable = getWearable(wearable_type);
 			if (wearable)
 			{
 				hash ^= wearable->getID();
@@ -7526,17 +7509,17 @@ void LLAgent::queryWearableCache()
 		}
 		if (hash.notNull())
 		{
-			hash ^= BAKED_TEXTURE_HASH[baked_texture_index];
+			hash ^= wearable_dict->mHashID;
 			num_queries++;
 			// *NOTE: make sure at least one request gets packed
 
-			//llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_texture_index << llendl;
+			//llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl;
 			gMessageSystem->nextBlockFast(_PREHASH_WearableData);
 			gMessageSystem->addUUIDFast(_PREHASH_ID, hash);
-			gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_texture_index);
+			gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_index);
 		}
 
-		mActiveCacheQueries[ baked_texture_index ] = mTextureCacheQueryID;
+		mActiveCacheQueries[ baked_index ] = mTextureCacheQueryID;
 	}
 
 	llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl;
@@ -7563,7 +7546,7 @@ void LLAgent::userRemoveAllClothes( void* userdata )
 	// We have to do this up front to avoid having to deal with the case of multiple wearables being dirty.
 	if( gFloaterCustomize )
 	{
-		gFloaterCustomize->askToSaveAllIfDirty( LLAgent::userRemoveAllClothesStep2, NULL );
+		gFloaterCustomize->askToSaveIfDirty( LLAgent::userRemoveAllClothesStep2, NULL );
 	}
 	else
 	{
diff --git a/indra/newview/llappearance.h b/indra/newview/llappearance.h
index 949b9e59fc..9018150146 100644
--- a/indra/newview/llappearance.h
+++ b/indra/newview/llappearance.h
@@ -44,14 +44,14 @@ public:
 	void	addParam( S32 id, F32 value )				{ mParamMap[id] = value; }
 	F32		getParam( S32 id, F32 defval )				{ return get_if_there(mParamMap, id, defval ); }
 
-	void	addTexture( S32 te, const LLUUID& uuid )	{ if( te < LLVOAvatar::TEX_NUM_ENTRIES ) mTextures[te] = uuid; }
-	const LLUUID& getTexture( S32 te )					{ return ( te < LLVOAvatar::TEX_NUM_ENTRIES ) ? mTextures[te] : LLUUID::null; }
+	void	addTexture( S32 te, const LLUUID& uuid )	{ if( te < LLVOAvatarDefines::TEX_NUM_INDICES ) mTextures[te] = uuid; }
+	const LLUUID& getTexture( S32 te )					{ return ( te < LLVOAvatarDefines::TEX_NUM_INDICES ) ? mTextures[te] : LLUUID::null; }
 	
-	void	clear()										{ mParamMap.clear(); for( S32 i=0; i<LLVOAvatar::TEX_NUM_ENTRIES; i++ ) mTextures[i].setNull(); }
+	void	clear()										{ mParamMap.clear(); for( S32 i=0; i<LLVOAvatarDefines::TEX_NUM_INDICES; i++ ) mTextures[i].setNull(); }
 
 	typedef std::map<S32, F32> param_map_t;
 	param_map_t mParamMap;
-	LLUUID	mTextures[LLVOAvatar::TEX_NUM_ENTRIES];
+	LLUUID	mTextures[LLVOAvatarDefines::TEX_NUM_INDICES];
 };
 
 #endif  // LL_LLAPPEARANCE_H
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index 9dd0668787..481a6ceb26 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -56,6 +56,7 @@
 #include "llviewerobjectlist.h"
 #include "llviewermenufile.h"
 #include "llviewerwindow.h"
+#include "lltexlayer.h"
 
 // When uploading multiple files, don't display any of them when uploading more than this number.
 static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5;
@@ -139,6 +140,7 @@ void LLAssetUploadResponder::result(const LLSD& content)
 		if (mFileName.empty())
 		{
 			// rename the file in the VFS to the actual asset id
+			// llinfos << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << llendl;
 			gVFS->renameFile(mVFileID, mAssetType, content["new_asset"].asUUID(), mAssetType);
 		}
 		uploadComplete(content);
@@ -332,6 +334,48 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
 	}
 }
 
+LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data,
+														   const LLUUID& vfile_id,
+														   LLAssetType::EType asset_type,
+														   LLBakedUploadData * baked_upload_data)
+												: LLAssetUploadResponder(post_data, vfile_id, asset_type),
+												mBakedUploadData(baked_upload_data)
+{
+}
+
+LLSendTexLayerResponder::~LLSendTexLayerResponder()
+{
+	// mBakedUploadData is normally deleted by calls to LLTexLayerSetBuffer::onTextureUploadComplete() below
+	if (mBakedUploadData)
+	{	// ...but delete it in the case where uploadComplete() is never called
+		delete mBakedUploadData;
+		mBakedUploadData = NULL;
+	}
+}
+
+
+// Baked texture upload completed
+void LLSendTexLayerResponder::uploadComplete(const LLSD& content)
+{
+	LLUUID item_id = mPostData["item_id"];
+
+	std::string result = content["state"];
+	LLUUID new_id = content["new_asset"];
+
+	llinfos << "LLSendTexLayerResponder::result from capabilities: " << result << llendl;
+	if (result == "complete"
+		&& mBakedUploadData != NULL)
+	{	// Invoke 
+		LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE);
+		mBakedUploadData = NULL;	// deleted in onTextureUploadComplete()
+	}
+	else
+	{	// Invoke the original callback with an error result
+		LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE);
+		mBakedUploadData = NULL;	// deleted in onTextureUploadComplete()
+	}
+}
+
 
 LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data,
 																 const LLUUID& vfile_id,
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index 42b3a9d27d..9ab571ae99 100644
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -71,6 +71,22 @@ public:
 	virtual void uploadComplete(const LLSD& content);
 };
 
+class LLBakedUploadData;
+class LLSendTexLayerResponder : public LLAssetUploadResponder
+{
+public:
+	LLSendTexLayerResponder(const LLSD& post_data,
+							const LLUUID& vfile_id,
+							LLAssetType::EType asset_type,
+							LLBakedUploadData * baked_upload_data);
+
+	~LLSendTexLayerResponder();
+
+	virtual void uploadComplete(const LLSD& content);
+
+	LLBakedUploadData * mBakedUploadData;
+};
+
 class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder
 {
 public:
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 9db9197500..0de21f03f2 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -758,7 +758,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 			avatarp->renderCollisionVolumes();
 		}
 
-		if (avatarp->mIsSelf && LLAgent::sDebugDisplayTarget)
+		if (avatarp->isSelf() && LLAgent::sDebugDisplayTarget)
 		{
 			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 			LLVector3 pos = avatarp->getPositionAgent();
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 0dc95ff536..1e2630e1fb 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -114,7 +114,12 @@ public:
 	static BOOL sSkipTransparent;
 };
 
-
+class LLVertexBufferAvatar : public LLVertexBuffer
+{
+public:
+	LLVertexBufferAvatar();
+	virtual void setupVertexBuffer(U32 data_mask) const;
+};
 
 extern S32 AVATAR_OFFSET_POS;
 extern S32 AVATAR_OFFSET_NORMAL;
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp
index 747b685b5e..162456b8ce 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloateranimpreview.cpp
@@ -1041,7 +1041,7 @@ LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLDynamicTexture
 	mDummyAvatar->updateJointLODs();
 	mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
 	mDummyAvatar->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET);
-	mDummyAvatar->mSkirtLOD.setVisible(FALSE, TRUE);
+	mDummyAvatar->hideSkirt();
 	gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance());
 
 	// stop extraneous animations
diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp
index 6ff34fbfb9..e81b5d7fce 100644
--- a/indra/newview/llfloateravatartextures.cpp
+++ b/indra/newview/llfloateravatartextures.cpp
@@ -40,6 +40,8 @@
 #include "llviewerobjectlist.h"
 #include "llvoavatar.h"
 
+using namespace LLVOAvatarDefines;
+
 LLFloaterAvatarTextures::LLFloaterAvatarTextures(const LLUUID& id) : 
 	LLFloater(std::string("avatar_texture_debug")),
 	mID(id)
@@ -68,26 +70,11 @@ LLFloaterAvatarTextures* LLFloaterAvatarTextures::show(const LLUUID &id)
 
 BOOL LLFloaterAvatarTextures::postBuild()
 {
-	mBakedHead = getChild<LLTextureCtrl>("baked_head");
-	mBakedEyes = getChild<LLTextureCtrl>("baked_eyes");
-	mBakedUpper = getChild<LLTextureCtrl>("baked_upper_body");
-	mBakedLower = getChild<LLTextureCtrl>("baked_lower_body");
-	mBakedSkirt = getChild<LLTextureCtrl>("baked_skirt");
-	mHair = getChild<LLTextureCtrl>("hair");
-	mMakeup = getChild<LLTextureCtrl>("head_bodypaint");
-	mEye = getChild<LLTextureCtrl>("eye_texture");
-	mShirt = getChild<LLTextureCtrl>("shirt");
-	mUpperTattoo = getChild<LLTextureCtrl>("upper_bodypaint");
-	mUpperJacket = getChild<LLTextureCtrl>("upper_jacket");
-	mGloves = getChild<LLTextureCtrl>("gloves");
-	mUndershirt = getChild<LLTextureCtrl>("undershirt");
-	mPants = getChild<LLTextureCtrl>("pants");
-	mLowerTattoo = getChild<LLTextureCtrl>("lower_bodypaint");
-	mShoes = getChild<LLTextureCtrl>("shoes");
-	mSocks = getChild<LLTextureCtrl>("socks");
-	mJacket = getChild<LLTextureCtrl>("jacket");
-	mUnderpants = getChild<LLTextureCtrl>("underpants");
-	mSkirt = getChild<LLTextureCtrl>("skirt_texture");
+	for (U32 i=0; i < TEX_NUM_INDICES; i++)
+	{
+		const std::string tex_name = LLVOAvatarDictionary::getInstance()->getTexture(ETextureIndex(i))->mName;
+		mTextures[i] = getChild<LLTextureCtrl>(tex_name);
+	}
 	mTitle = getTitle();
 
 	childSetAction("Dump", onClickDump, this);
@@ -105,7 +92,7 @@ void LLFloaterAvatarTextures::draw()
 #if !LL_RELEASE_FOR_DOWNLOAD
 static void update_texture_ctrl(LLVOAvatar* avatarp,
 								 LLTextureCtrl* ctrl,
-								 LLVOAvatar::ETextureIndex te)
+								 ETextureIndex te)
 {
 	LLUUID id = avatarp->getTE(te)->getID();
 	if (id == IMG_DEFAULT_AVATAR)
@@ -148,29 +135,10 @@ void LLFloaterAvatarTextures::refresh()
 		{
 			setTitle(mTitle + ": " + fullname);
 		}
-		update_texture_ctrl(avatarp, mBakedHead,	LLVOAvatar::TEX_HEAD_BAKED);
-		update_texture_ctrl(avatarp, mBakedEyes,	LLVOAvatar::TEX_EYES_BAKED);
-		update_texture_ctrl(avatarp, mBakedUpper,	LLVOAvatar::TEX_UPPER_BAKED);
-		update_texture_ctrl(avatarp, mBakedLower,	LLVOAvatar::TEX_LOWER_BAKED);
-		update_texture_ctrl(avatarp, mBakedSkirt,	LLVOAvatar::TEX_SKIRT_BAKED);
-
-		update_texture_ctrl(avatarp, mMakeup,		LLVOAvatar::TEX_HEAD_BODYPAINT);
-		update_texture_ctrl(avatarp, mHair,			LLVOAvatar::TEX_HAIR);
-		update_texture_ctrl(avatarp, mEye,			LLVOAvatar::TEX_EYES_IRIS);
-
-		update_texture_ctrl(avatarp, mShirt,		LLVOAvatar::TEX_UPPER_SHIRT);
-		update_texture_ctrl(avatarp, mUpperTattoo,	LLVOAvatar::TEX_UPPER_BODYPAINT);
-		update_texture_ctrl(avatarp, mUpperJacket,	LLVOAvatar::TEX_UPPER_JACKET);
-		update_texture_ctrl(avatarp, mGloves,		LLVOAvatar::TEX_UPPER_GLOVES);
-		update_texture_ctrl(avatarp, mUndershirt,	LLVOAvatar::TEX_UPPER_UNDERSHIRT);
-
-		update_texture_ctrl(avatarp, mPants,		LLVOAvatar::TEX_LOWER_PANTS);
-		update_texture_ctrl(avatarp, mLowerTattoo,	LLVOAvatar::TEX_LOWER_BODYPAINT);
-		update_texture_ctrl(avatarp, mShoes,		LLVOAvatar::TEX_LOWER_SHOES);
-		update_texture_ctrl(avatarp, mSocks,		LLVOAvatar::TEX_LOWER_SOCKS);
-		update_texture_ctrl(avatarp, mJacket,		LLVOAvatar::TEX_LOWER_JACKET);
-		update_texture_ctrl(avatarp, mUnderpants,	LLVOAvatar::TEX_LOWER_UNDERPANTS);
-		update_texture_ctrl(avatarp, mSkirt,		LLVOAvatar::TEX_SKIRT);
+		for (U32 i=0; i < TEX_NUM_INDICES; i++)
+		{
+			update_texture_ctrl(avatarp, mTextures[i], ETextureIndex(i));
+		}
 	}
 	else
 	{
diff --git a/indra/newview/llfloateravatartextures.h b/indra/newview/llfloateravatartextures.h
index fbcf47bf7d..4138edeb4d 100644
--- a/indra/newview/llfloateravatartextures.h
+++ b/indra/newview/llfloateravatartextures.h
@@ -36,6 +36,7 @@
 #include "llfloater.h"
 #include "lluuid.h"
 #include "llstring.h"
+#include "llvoavatardefines.h"
 
 class LLTextureCtrl;
 
@@ -58,26 +59,7 @@ private:
 private:
 	LLUUID	mID;
 	std::string mTitle;
-	LLTextureCtrl* mBakedHead;
-	LLTextureCtrl* mBakedEyes;
-	LLTextureCtrl* mBakedUpper;
-	LLTextureCtrl* mBakedLower;
-	LLTextureCtrl* mBakedSkirt;
-	LLTextureCtrl* mHair;
-	LLTextureCtrl* mMakeup;
-	LLTextureCtrl* mEye;
-	LLTextureCtrl* mShirt;
-	LLTextureCtrl* mUpperTattoo;
-	LLTextureCtrl* mUpperJacket;
-	LLTextureCtrl* mGloves;
-	LLTextureCtrl* mUndershirt;
-	LLTextureCtrl* mPants;
-	LLTextureCtrl* mLowerTattoo;
-	LLTextureCtrl* mShoes;
-	LLTextureCtrl* mSocks;
-	LLTextureCtrl* mJacket;
-	LLTextureCtrl* mUnderpants;
-	LLTextureCtrl* mSkirt;
+	LLTextureCtrl* mTextures[LLVOAvatarDefines::TEX_NUM_INDICES];
 };
 
 #endif
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 2e59240c49..6497821349 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -1072,16 +1072,20 @@ void LLHUDText::renderAllHUD()
 	LLGLState::checkStates();
 	LLGLState::checkTextureChannels();
 	LLGLState::checkClientArrays();
-	
-	LLGLEnable color_mat(GL_COLOR_MATERIAL);
-	LLGLDepthTest depth(GL_FALSE, GL_FALSE);
-	
-	VisibleTextObjectIterator text_it;
 
-	for (text_it = sVisibleHUDTextObjects.begin(); text_it != sVisibleHUDTextObjects.end(); ++text_it)
 	{
-		(*text_it)->renderText(FALSE);
+		LLGLEnable color_mat(GL_COLOR_MATERIAL);
+		LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+		
+		VisibleTextObjectIterator text_it;
+
+		for (text_it = sVisibleHUDTextObjects.begin(); text_it != sVisibleHUDTextObjects.end(); ++text_it)
+		{
+			(*text_it)->renderText(FALSE);
+		}
 	}
+	
+	LLVertexBuffer::unbind();
 
 	LLGLState::checkStates();
 	LLGLState::checkTextureChannels();
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3ac7deb3df..0aa406dff1 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3883,7 +3883,7 @@ void wear_inventory_category_on_avatar( LLInventoryCategory* category, BOOL appe
 
 	if( gFloaterCustomize )
 	{
-		gFloaterCustomize->askToSaveAllIfDirty(
+		gFloaterCustomize->askToSaveIfDirty(
 			wear_inventory_category_on_avatar_step2,
 			userdata);
 	}
@@ -4154,7 +4154,7 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category )
 
 	if( gFloaterCustomize )
 	{
-		gFloaterCustomize->askToSaveAllIfDirty(
+		gFloaterCustomize->askToSaveIfDirty(
 			remove_inventory_category_from_avatar_step2,
 			uuid);
 	}
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 031f4ab304..cdcd68de38 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -241,7 +241,7 @@ void LLProgressView::onCancelButtonClicked(void*)
 void LLProgressView::onClickMessage(void* data)
 {
 	LLProgressView* viewp = (LLProgressView*)data;
-	if ( ! viewp->mMessage.empty() )
+	if ( viewp != NULL && ! viewp->mMessage.empty() )
 	{
 		std::string url_to_open( "" );
 
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 6a7ba7b7f4..b376eed814 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -47,6 +47,7 @@
 #include "llvfile.h"
 #include "llviewerimagelist.h"
 #include "llviewerimagelist.h"
+#include "llviewerregion.h"
 #include "llviewerstats.h"
 #include "llviewerwindow.h"
 #include "llvoavatar.h"
@@ -54,9 +55,12 @@
 #include "pipeline.h"
 #include "v4coloru.h"
 #include "llrender.h"
+#include "llassetuploadresponders.h"
 
 //#include "../tools/imdebug/imdebug.h"
 
+using namespace LLVOAvatarDefines;
+
 // static
 S32 LLTexLayerSetBuffer::sGLByteCount = 0;
 S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
@@ -64,11 +68,12 @@ S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
 //-----------------------------------------------------------------------------
 // LLBakedUploadData()
 //-----------------------------------------------------------------------------
-LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer ) : 
+LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer, const LLUUID & id ) : 
 	mAvatar( avatar ),
-	mLayerSetBuffer( layerset_buffer )
+	mLayerSetBuffer( layerset_buffer ),
+	mID(id)
 { 
-	mID.generate();
+	mStartTime = LLFrameTimer::getTotalTime();		// Record starting time
 	for( S32 i = 0; i < WT_COUNT; i++ )
 	{
 		LLWearable* wearable = gAgent.getWearable( (EWearableType)i);
@@ -221,7 +226,7 @@ BOOL LLTexLayerSetBuffer::needsRender()
 	BOOL needs_update = gAgent.mNumPendingQueries == 0 && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating;
 	if (needs_update)
 	{
-		BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatar::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT);
+		BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT);
 		if (invalid_skirt)
 		{
 			// we were trying to create a skirt texture
@@ -393,7 +398,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
 					baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
 					baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
 					baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
-					baked_image_data[5*i + 3] = baked_color_data[4*i + 3] < 255 ? baked_color_data[4*i + 3] : baked_bump_data[4*i];
+					baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes.
 					baked_image_data[5*i + 4] = baked_mask_data[i];
 					i++;
 				}
@@ -409,7 +414,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
 					baked_image_data[5*i + 0] = baked_color_data[4*i + 0];
 					baked_image_data[5*i + 1] = baked_color_data[4*i + 1];
 					baked_image_data[5*i + 2] = baked_color_data[4*i + 2];
-					baked_image_data[5*i + 3] = baked_bump_data[4*i];
+					baked_image_data[5*i + 3] = 255; // reserve for alpha 
 					baked_image_data[5*i + 4] = baked_mask_data[i];
 					i++;
 				}
@@ -418,7 +423,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
 	}
 	else
 	{	
-		if (mTexLayerSet->getBodyRegion() == "skirt")
+		if (mTexLayerSet->getBodyRegion() == "skirt" || mTexLayerSet->getBodyRegion() == "hair")
 		{
 			S32 i = 0;
 			for( S32 u = 0; u < mWidth; u++ )
@@ -443,7 +448,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
 					baked_image_data[4*i + 0] = baked_color_data[4*i + 0];
 					baked_image_data[4*i + 1] = baked_color_data[4*i + 1];
 					baked_image_data[4*i + 2] = baked_color_data[4*i + 2];
-					baked_image_data[4*i + 3] = baked_mask_data[i];
+					baked_image_data[4*i + 3] = 255; // eyes should have no mask - reserve for alpha 
 					i++;
 				}
 			}
@@ -479,16 +484,34 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data)
 			
 			if( valid )
 			{
-				LLBakedUploadData* baked_upload_data = new LLBakedUploadData( gAgent.getAvatarObject(), this );
-				mUploadID = baked_upload_data->mID;
-
-				gAssetStorage->storeAssetData(tid,
-											  LLAssetType::AT_TEXTURE,
-											  LLTexLayerSetBuffer::onTextureUploadComplete,
-											  baked_upload_data,
-											  TRUE,		// temp_file
-											  FALSE,	// is_priority
-											  TRUE);	// store_local
+				// baked_upload_data is owned by the responder and deleted after the request completes
+				LLBakedUploadData* baked_upload_data = new LLBakedUploadData( gAgent.getAvatarObject(), this, asset_id );
+				mUploadID = asset_id;
+				
+				// upload the image
+				std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture");
+
+				if(!url.empty()
+					&& !LLPipeline::sForceOldBakedUpload) // Toggle the debug setting UploadBakedTexOld to change between the new caps method and old method
+				{
+					llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl;
+
+					LLSD body = LLSD::emptyMap();
+					LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data));
+					// Responder will call LLTexLayerSetBuffer::onTextureUploadComplete()
+				} 
+				else
+				{
+					llinfos << "Baked texture upload via Asset Store." <<  llendl;
+					// gAssetStorage->storeAssetData(mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)this, FALSE);
+					gAssetStorage->storeAssetData(tid,
+												  LLAssetType::AT_TEXTURE,
+												  LLTexLayerSetBuffer::onTextureUploadComplete,
+												  baked_upload_data,
+												  TRUE,		// temp_file
+												  TRUE,		// is_priority
+												  TRUE);	// store_local
+				}
 		
 				mNeedsUpload = FALSE;
 			}
@@ -541,15 +564,10 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* user
 
 				if( result >= 0 )
 				{
-					LLVOAvatar::ETextureIndex baked_te = avatar->getBakedTE( layerset_buffer->mTexLayerSet );
-					if( !gAgent.cameraCustomizeAvatar() )
-					{
-						avatar->setNewBakedTexture( baked_te, uuid );
-					}
-					else
-					{
-						llinfos << "LLTexLayerSetBuffer::onTextureUploadComplete() when in Customize Avatar" << llendl;
-					}
+					ETextureIndex baked_te = avatar->getBakedTE( layerset_buffer->mTexLayerSet );
+					U64 now = LLFrameTimer::getTotalTime();		// Record starting time
+					llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl;
+					avatar->setNewBakedTexture( baked_te, uuid );
 				}
 				else
 				{
@@ -800,6 +818,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
 			{
 				LLGLSUIDefault gls_ui;
 				gGL.getTexUnit(0)->bind(image_gl);
+				gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE );
 				gl_rect_2d_simple_tex( width, height );
 			}
 			else
@@ -807,9 +826,10 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
 				success = FALSE;
 			}
 		}
+		gGL.flush();
 		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
-		gGL.flush();
+		gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 		gGL.setColorMask(true, true);
 		gGL.setSceneBlendType(LLRender::BT_ALPHA);
 	}
@@ -895,7 +915,7 @@ void LLTexLayerSet::createComposite()
 		S32 width = mInfo->mWidth;
 		S32 height = mInfo->mHeight;
 		// Composite other avatars at reduced resolution
-		if( !mAvatar->mIsSelf )
+		if( !mAvatar->isSelf() )
 		{
 			width /= 2;
 			height /= 2;
@@ -1049,59 +1069,63 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
 
 			if( "upper_shirt" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_UPPER_SHIRT;
+				mLocalTexture = TEX_UPPER_SHIRT;
 			}
 			else if( "upper_bodypaint" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_UPPER_BODYPAINT;
+				mLocalTexture = TEX_UPPER_BODYPAINT;
 			}
 			else if( "lower_pants" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_LOWER_PANTS;
+				mLocalTexture = TEX_LOWER_PANTS;
 			}
 			else if( "lower_bodypaint" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_LOWER_BODYPAINT;
+				mLocalTexture = TEX_LOWER_BODYPAINT;
 			}
 			else if( "lower_shoes" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SHOES;
+				mLocalTexture = TEX_LOWER_SHOES;
 			}
 			else if( "head_bodypaint" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_HEAD_BODYPAINT;
+				mLocalTexture = TEX_HEAD_BODYPAINT;
 			}
 			else if( "lower_socks" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SOCKS;
+				mLocalTexture = TEX_LOWER_SOCKS;
 			}
 			else if( "upper_jacket" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_UPPER_JACKET;
+				mLocalTexture = TEX_UPPER_JACKET;
 			}
 			else if( "lower_jacket" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_LOWER_JACKET;
+				mLocalTexture = TEX_LOWER_JACKET;
 			}
 			else if( "upper_gloves" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_UPPER_GLOVES;
+				mLocalTexture = TEX_UPPER_GLOVES;
 			}
 			else if( "upper_undershirt" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_UPPER_UNDERSHIRT;
+				mLocalTexture = TEX_UPPER_UNDERSHIRT;
 			}
 			else if( "lower_underpants" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_LOWER_UNDERPANTS;
+				mLocalTexture = TEX_LOWER_UNDERPANTS;
 			}
 			else if( "eyes_iris" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_EYES_IRIS;
+				mLocalTexture = TEX_EYES_IRIS;
 			}
 			else if( "skirt" == local_texture )
 			{
-				mLocalTexture = LLVOAvatar::LOCTEX_SKIRT;
+				mLocalTexture = TEX_SKIRT;
+			}			
+			else if( "hair_grain" == local_texture )
+			{
+				mLocalTexture = TEX_HAIR;
 			}
 			else
 			{
@@ -1364,7 +1388,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
 	{
 		{
 			LLImageGL* image_gl = NULL;
-			if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) )
+			if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
 			{
 				if( image_gl )
 				{
@@ -1434,7 +1458,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height )
 U8*	LLTexLayer::getAlphaData()
 {
 	LLCRC alpha_mask_crc;
-	const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture);
+	const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture);
 	alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES);
 
 	for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
@@ -1563,7 +1587,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
 	{
 		{
 			LLImageGL* image_gl = NULL;
-			if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) )
+			if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) )
 			{
 				if( image_gl && (image_gl->getComponents() == 4) )
 				{
@@ -1627,7 +1651,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
 	if (!mMorphMasksValid && !mMaskedMorphs.empty())
 	{
 		LLCRC alpha_mask_crc;
-		const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture);
+		const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture);
 		alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES);
 		
 		for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ )
@@ -1648,7 +1672,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4
 		else
 		{
 			// clear out a slot if we have filled our cache
-			S32 max_cache_entries = getTexLayerSet()->getAvatar()->mIsSelf ? 4 : 1;
+			S32 max_cache_entries = getTexLayerSet()->getAvatar()->isSelf() ? 4 : 1;
 			while ((S32)mAlphaCache.size() >= max_cache_entries)
 			{
 				iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry
@@ -1701,7 +1725,7 @@ BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 i
 		format = GL_ALPHA;
 	}
 
-	if( (in_width != VOAVATAR_SCRATCH_TEX_WIDTH) || (in_height != VOAVATAR_SCRATCH_TEX_HEIGHT) )
+	if( (in_width != SCRATCH_TEX_WIDTH) || (in_height != SCRATCH_TEX_HEIGHT) )
 	{
 		LLGLSNoAlphaTest gls_no_alpha_test;
 
@@ -1918,8 +1942,13 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
 		LLVOAvatar* avatar = mTexLayer->getTexLayerSet()->getAvatar();
 		if( avatar->getSex() & getSex() )
 		{
+			if ( gAgent.cameraCustomizeAvatar() )
+			{
+				set_by_user = FALSE;
+			}
 			avatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user );
 			mTexLayer->invalidateMorphMasks();
+			avatar->updateMeshTextures();
 		}
 	}
 }
@@ -2053,7 +2082,7 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height )
 
 		// Don't keep the cache for other people's avatars
 		// (It's not really a "cache" in that case, but the logic is the same)
-		if( !mTexLayer->getTexLayerSet()->getAvatar()->mIsSelf )
+		if( !mTexLayer->getTexLayerSet()->getAvatar()->isSelf() )
 		{
 			mCachedProcessedImageGL = NULL;
 		}
diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h
index 5ab8c91f72..18e6d6b24f 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/newview/lltexlayer.h
@@ -537,13 +537,14 @@ public:
 class LLBakedUploadData
 {
 public:
-	LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer );
+	LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer, const LLUUID & id);
 	~LLBakedUploadData() {}
 
 	LLUUID					mID;
 	LLVOAvatar*				mAvatar;	 // just backlink, don't LLPointer 
 	LLTexLayerSetBuffer*	mLayerSetBuffer;
 	LLUUID					mWearableAssets[WT_COUNT];
+	U64						mStartTime;		// Used to measure time baked texture upload requires
 };
 
 extern LLTexStaticImageList gTexStaticImageList;
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index db864765b1..fcad86e498 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -955,7 +955,7 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info)
 
 		if(hit_obj->isAvatar())
 		{
-			if(((LLVOAvatar*) hit_obj)->mIsSelf)
+			if(((LLVOAvatar*) hit_obj)->isSelf())
 			{
 				target = DT_SELF;
 				hit_face = -1;
diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp
index 6069f1ffc6..351c02b4c0 100644
--- a/indra/newview/lltoolfocus.cpp
+++ b/indra/newview/lltoolfocus.cpp
@@ -221,7 +221,7 @@ void LLToolCamera::pickCallback(const LLPickInfo& pick_info)
 			gViewerWindow->getLeftMouseDown() && 
 			!gSavedSettings.getBOOL("FreezeTime") &&
 			(hit_obj == gAgent.getAvatarObject() || 
-				(hit_obj && hit_obj->isAttachment() && LLVOAvatar::findAvatarFromAttachment(hit_obj)->mIsSelf)))
+				(hit_obj && hit_obj->isAttachment() && LLVOAvatar::findAvatarFromAttachment(hit_obj)->isSelf())))
 		{
 			LLToolCamera::getInstance()->mMouseSteering = TRUE;
 		}
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index f15f0f44b0..75e19645a6 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -237,7 +237,11 @@ BOOL LLVisualParamHint::render()
 	{
 		LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool();
 		LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
+		gGL.setAlphaRejectSettings(LLRender::CF_ALWAYS);
+		gGL.setSceneBlendType(LLRender::BT_REPLACE);
 		avatarPoolp->renderAvatars(avatarp);  // renders only one avatar
+		gGL.setSceneBlendType(LLRender::BT_ALPHA);
+		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 	}
 	avatarp->setVisualParamWeight(mVisualParam, mLastParamWeight);
 	gGL.color4f(1,1,1,1);
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 6b99cfbeaf..c0d3466fab 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -119,6 +119,12 @@ static bool handleSetShaderChanged(const LLSD& newvalue)
 	return true;
 }
 
+static bool handleSetSelfInvisible( const LLSD& newvalue)
+{
+	LLVOAvatar::onChangeSelfInvisible( newvalue.asBoolean() );
+	return true;
+}
+
 static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
 {
 	if (gPipeline.isInit())
@@ -205,16 +211,6 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue)
 	return true;
 }
 
-const S32 MAX_USER_COMPOSITE_LIMIT = 100;
-const S32 MIN_USER_COMPOSITE_LIMIT = 0;
-
-static bool handleCompositeLimitChanged(const LLSD& newvalue)
-{
-	S32 composite_limit = llmax(MIN_USER_COMPOSITE_LIMIT,  llmin((S32)newvalue.asInteger(), MAX_USER_COMPOSITE_LIMIT));
-	LLVOAvatar::sMaxOtherAvatarsToComposite = composite_limit;
-	return true;
-}
-
 static bool handleVideoMemoryChanged(const LLSD& newvalue)
 {
 	gImageList.updateMaxResidentTexMem(newvalue.asInteger());
@@ -297,6 +293,13 @@ static bool handleUseOcclusionChanged(const LLSD& newvalue)
 	return true;
 }
 
+static bool handleUploadBakedTexOldChanged(const LLSD& newvalue)
+{
+	LLPipeline::sForceOldBakedUpload = newvalue.asBoolean();
+	return true;
+}
+
+
 static bool handleNumpadControlChanged(const LLSD& newvalue)
 {
 	if (gKeyboard)
@@ -453,6 +456,7 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
 	gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
 	gSavedSettings.getControl("RenderAvatarMaxVisible")->getSignal()->connect(boost::bind(&handleAvatarMaxVisibleChanged, _1));
+	gSavedSettings.getControl("RenderAvatarInvisible")->getSignal()->connect(boost::bind(&handleSetSelfInvisible, _1));
 	gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _1));
 	gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _1));
 	gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _1));
@@ -474,11 +478,11 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _1));
 	gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _1));
 	gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1));
-	gSavedSettings.getControl("AvatarCompositeLimit")->getSignal()->connect(boost::bind(&handleCompositeLimitChanged, _1));
 	gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _1));
 	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _1));
 	gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _1));
 	gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _1));
+	gSavedSettings.getControl("UploadBakedTexOld")->getSignal()->connect(boost::bind(&handleUploadBakedTexOldChanged, _1));
 	gSavedSettings.getControl("UseOcclusion")->getSignal()->connect(boost::bind(&handleUseOcclusionChanged, _1));
 	gSavedSettings.getControl("AudioLevelMaster")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
  	gSavedSettings.getControl("AudioLevelSFX")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1));
diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp
index 89490e08bf..1cc062dbd2 100644
--- a/indra/newview/llviewerjoint.cpp
+++ b/indra/newview/llviewerjoint.cpp
@@ -514,6 +514,16 @@ void LLViewerJoint::setVisible(BOOL visible, BOOL recursive)
 	}
 }
 
+
+void LLViewerJoint::setMeshesToChildren()
+{
+	removeAllChildren();
+	for (std::vector<LLViewerJointMesh*>::iterator iter = mMeshParts.begin();
+		iter != mMeshParts.end(); iter++)
+	{
+		addChild((LLViewerJointMesh *) *iter);
+	}
+}
 //-----------------------------------------------------------------------------
 // LLViewerJointCollisionVolume()
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h
index 0430a91833..a07902e582 100644
--- a/indra/newview/llviewerjoint.h
+++ b/indra/newview/llviewerjoint.h
@@ -40,6 +40,7 @@
 #include "llapr.h"
 
 class LLFace;
+class LLViewerJointMesh;
 
 //-----------------------------------------------------------------------------
 // class LLViewerJoint
@@ -133,8 +134,13 @@ public:
 
 	void setVisible( BOOL visible, BOOL recursive );
 
+	// Takes meshes in mMeshParts and sets each one as a child joint
+	void setMeshesToChildren();
+
 public:
 	static BOOL	sDisableLOD;
+	std::vector<LLViewerJointMesh*> mMeshParts;
+	void setMeshID( S32 id ) {mMeshID = id;}
 
 protected:
 	BOOL		mValid;
@@ -142,6 +148,7 @@ protected:
 	F32			mMinPixelArea;
 	PickName	mPickName;
 	BOOL		mVisible;
+	S32			mMeshID;
 };
 
 class LLViewerJointCollisionVolume : public LLViewerJoint
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 4cacc5c97b..c0e02921cf 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -558,7 +558,12 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass)
 		}
 		else
 		{
-			llwarns << "Layerset without composite" << llendl;
+			// This warning will always trigger if you've hacked the avatar to show as incomplete.
+			// Ignore the warning if that's the case.
+			if (!gSavedSettings.getBOOL("RenderUnloadedAvatar"))
+			{
+				llwarns << "Layerset without composite" << llendl;
+			}
 			gGL.getTexUnit(0)->bind(gImageList.getImage(IMG_DEFAULT));
 		}
 	}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index de16bbf8a1..47a887e909 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -212,6 +212,7 @@
 
 #include "lltexlayer.h"
 
+using namespace LLVOAvatarDefines;
 void init_client_menu(LLMenuGL* menu);
 void init_server_menu(LLMenuGL* menu);
 
@@ -1313,8 +1314,6 @@ void init_debug_rendering_menu(LLMenuGL* menu)
 	menu->createJumpKeys();
 }
 
-extern BOOL gDebugAvatarRotation;
-
 void init_debug_avatar_menu(LLMenuGL* menu)
 {
 	LLMenuGL* sub_menu = new LLMenuGL("Grab Baked Texture");
@@ -1361,7 +1360,7 @@ void init_debug_avatar_menu(LLMenuGL* menu)
 	//menu->append(new LLMenuItemToggleGL("Show Collision Plane", &LLVOAvatar::sShowFootPlane));
 	menu->append(new LLMenuItemToggleGL("Show Collision Skeleton", &LLVOAvatar::sShowCollisionVolumes));
 	menu->append(new LLMenuItemToggleGL( "Display Agent Target", &LLAgent::sDebugDisplayTarget));
-	menu->append(new LLMenuItemToggleGL( "Debug Rotation", &gDebugAvatarRotation));
+	menu->append(new LLMenuItemToggleGL( "Debug Rotation", &LLVOAvatar::sDebugAvatarRotation));
 	menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments));
 	menu->append(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures, NULL, NULL, 'R', MASK_ALT | MASK_CONTROL ));
 #ifndef LL_RELEASE_FOR_DOWNLOAD
@@ -1373,11 +1372,12 @@ void init_debug_avatar_menu(LLMenuGL* menu)
 
 void init_debug_baked_texture_menu(LLMenuGL* menu)
 {
-	menu->append(new LLMenuItemCallGL("Iris", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_EYES_BAKED));
-	menu->append(new LLMenuItemCallGL("Head", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_HEAD_BAKED));
-	menu->append(new LLMenuItemCallGL("Upper Body", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_UPPER_BAKED));
-	menu->append(new LLMenuItemCallGL("Lower Body", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_LOWER_BAKED));
-	menu->append(new LLMenuItemCallGL("Skirt", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_SKIRT_BAKED));
+	menu->append(new LLMenuItemCallGL("Iris", handle_grab_texture, enable_grab_texture, (void*) TEX_EYES_BAKED));
+	menu->append(new LLMenuItemCallGL("Head", handle_grab_texture, enable_grab_texture, (void*) TEX_HEAD_BAKED));
+	menu->append(new LLMenuItemCallGL("Upper Body", handle_grab_texture, enable_grab_texture, (void*) TEX_UPPER_BAKED));
+	menu->append(new LLMenuItemCallGL("Lower Body", handle_grab_texture, enable_grab_texture, (void*) TEX_LOWER_BAKED));
+	menu->append(new LLMenuItemCallGL("Skirt", handle_grab_texture, enable_grab_texture, (void*) TEX_SKIRT_BAKED));
+	menu->append(new LLMenuItemCallGL("Hair", handle_grab_texture, enable_grab_texture, (void*) TEX_HAIR_BAKED));
 	menu->createJumpKeys();
 }
 
@@ -3082,7 +3082,7 @@ void handle_reset_view()
 	if( (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgent.getCameraMode()) && gFloaterCustomize )
 	{
 		// Show dialog box if needed.
-		gFloaterCustomize->askToSaveAllIfDirty( reset_view_final, NULL );
+		gFloaterCustomize->askToSaveIfDirty( reset_view_final, NULL );
 	}
 	else
 	{
@@ -6727,12 +6727,12 @@ void handle_debug_avatar_textures(void*)
 
 void handle_grab_texture(void* data)
 {
-	LLVOAvatar::ETextureIndex index = (LLVOAvatar::ETextureIndex)((intptr_t)data);
+	ETextureIndex index = (ETextureIndex)((intptr_t)data);
 	LLVOAvatar* avatar = gAgent.getAvatarObject();
 	if ( avatar )
 	{
 		const LLUUID& asset_id = avatar->grabLocalTexture(index);
-		llinfos << "Adding baked texture " << asset_id << " to inventory." << llendl;
+		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;
 		LLUUID folder_id(gInventory.findCategoryUUIDForType(asset_type));
@@ -6741,21 +6741,24 @@ void handle_grab_texture(void* data)
 			std::string name = "Baked ";
 			switch (index)
 			{
-			case LLVOAvatar::TEX_EYES_BAKED:
+			case TEX_EYES_BAKED:
 				name.append("Iris");
 				break;
-			case LLVOAvatar::TEX_HEAD_BAKED:
+			case TEX_HEAD_BAKED:
 				name.append("Head");
 				break;
-			case LLVOAvatar::TEX_UPPER_BAKED:
+			case TEX_UPPER_BAKED:
 				name.append("Upper Body");
 				break;
-			case LLVOAvatar::TEX_LOWER_BAKED:
+			case TEX_LOWER_BAKED:
 				name.append("Lower Body");
 				break;
-			case LLVOAvatar::TEX_SKIRT_BAKED:
+			case TEX_SKIRT_BAKED:
 				name.append("Skirt");
 				break;
+			case TEX_HAIR_BAKED:
+				name.append("Hair");
+				break;
 			default:
 				name.append("Unknown");
 				break;
@@ -6817,7 +6820,7 @@ void handle_grab_texture(void* data)
 
 BOOL enable_grab_texture(void* data)
 {
-	LLVOAvatar::ETextureIndex index = (LLVOAvatar::ETextureIndex)((intptr_t)data);
+	ETextureIndex index = (ETextureIndex)((intptr_t)data);
 	LLVOAvatar* avatar = gAgent.getAvatarObject();
 	if ( avatar )
 	{
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index c840557f01..77b69d0ad4 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -3671,7 +3671,7 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
 
 	avatarp->mSignaledAnimations.clear();
 	
-	if (avatarp->mIsSelf)
+	if (avatarp->isSelf())
 	{
 		LLUUID object_id;
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index e4ddbd42dd..4a81c06efb 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -1889,7 +1889,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 
 	if ( gShowObjectUpdates )
 	{
-		if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->mIsSelf))
+		if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->isSelf()))
 			&& mRegionp)
 		{
 			LLViewerObject* object = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, mRegionp);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 50fe66ea5e..e822c81500 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1420,6 +1420,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("SendUserReportWithScreenshot");
 	capabilityNames.append("ServerReleaseNotes");
 	capabilityNames.append("StartGroupProposal");
+	capabilityNames.append("UntrustedSimulatorMessage");
 	capabilityNames.append("UpdateAgentLanguage");
 	capabilityNames.append("UpdateGestureAgentInventory");
 	capabilityNames.append("UpdateNotecardAgentInventory");
@@ -1427,8 +1428,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("UpdateGestureTaskInventory");
 	capabilityNames.append("UpdateNotecardTaskInventory");
 	capabilityNames.append("UpdateScriptTask");
+	capabilityNames.append("UploadBakedTexture");
 	capabilityNames.append("ViewerStartAuction");
-	capabilityNames.append("UntrustedSimulatorMessage");
 	capabilityNames.append("ViewerStats");
 	// Please add new capabilities alphabetically to reduce
 	// merge conflicts.
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 3757923e27..8d20e4e91c 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -32,175 +32,112 @@
 
 #include "llviewerprecompiledheaders.h"
 
-#include <algorithm>
-#include <vector>
-#include "llstl.h"
-
 #include "llvoavatar.h"
 
-#include "llrender.h"
+#include <stdio.h>
+#include <ctype.h>
+
 #include "audioengine.h"
-#include "imageids.h"
-#include "indra_constants.h"
-#include "llchat.h"
-#include "llfontgl.h"
-#include "llprimitive.h"
-#include "lltextureentry.h"
-#include "message.h"
 #include "noise.h"
-#include "sound_ids.h"
-#include "lltimer.h"
-#include "timing.h"
 
-#include "llagent.h"			//  Get state values from here
+#include "llagent.h" //  Get state values from here
 #include "llviewercontrol.h"
-#include "llcriticaldamp.h"
-#include "lldir.h"
-#include "lldrawable.h"
 #include "lldrawpoolavatar.h"
-#include "lldrawpoolalpha.h"
-#include "lldrawpoolbump.h"
 #include "lldriverparam.h"
 #include "lleditingmotion.h"
 #include "llemote.h"
-#include "llface.h"
-#include "llfasttimer.h"
 #include "llfirstuse.h"
-#include "llfloatercustomize.h"
-#include "llfloatertools.h"
-#include "llgldbg.h"
-#include "llhandmotion.h"
 #include "llheadrotmotion.h"
-#include "llhudeffectbeam.h"
-#include "llhudeffectlookat.h"
 #include "llhudeffecttrail.h"
 #include "llhudmanager.h"
-#include "llhudtext.h"
-#include "llinventorymodel.h"
 #include "llinventoryview.h"
 #include "llkeyframefallmotion.h"
-#include "llkeyframemotion.h"
-#include "llkeyframemotionparam.h"
 #include "llkeyframestandmotion.h"
 #include "llkeyframewalkmotion.h"
-#include "llmenugl.h"
 #include "llmutelist.h"
-#include "llnetmap.h"
-#include "llnotify.h"
-#include "llquantize.h"
-#include "llregionhandle.h"
-#include "llresmgr.h"
 #include "llselectmgr.h"
-#include "llsky.h"
 #include "llsprite.h"
-#include "llstatusbar.h"
 #include "lltargetingmotion.h"
 #include "lltexlayer.h"
-#include "lltoolgrab.h"		// for needsRenderBeam
-#include "lltoolmgr.h"		// for needsRenderBeam
+#include "lltoolgrab.h"	// for needsRenderBeam
+#include "lltoolmgr.h" // for needsRenderBeam
 #include "lltoolmorph.h"
 #include "llviewercamera.h"
 #include "llviewerimagelist.h"
-#include "llviewerinventory.h"
 #include "llviewermenu.h"
 #include "llviewerobjectlist.h"
 #include "llviewerparcelmgr.h"
-#include "llviewerregion.h"
 #include "llviewerstats.h"
-#include "llviewerwindow.h"
-#include "llvosky.h"
 #include "llvovolume.h"
-#include "llwearable.h"
-#include "llwearablelist.h"
 #include "llworld.h"
 #include "pipeline.h"
-#include "llspatialpartition.h"
 #include "llviewershadermgr.h"
-#include "llappviewer.h"
 #include "llsky.h"
 #include "llanimstatelabels.h"
-
-//#include "vtune/vtuneapi.h"
-
 #include "llgesturemgr.h" //needed to trigger the voice gesticulations
-#include "llvoicevisualizer.h" 
 #include "llvoiceclient.h"
+#include "llvoicevisualizer.h" // Ventrella
 
-LLXmlTree LLVOAvatar::sXMLTree;
-LLXmlTree LLVOAvatar::sSkeletonXMLTree;
-LLVOAvatarSkeletonInfo* LLVOAvatar::sSkeletonInfo = NULL;
-LLVOAvatarInfo* 		LLVOAvatar::sAvatarInfo = NULL;
+#include "boost/lexical_cast.hpp"
+
+using namespace LLVOAvatarDefines;
 
-BOOL gDebugAvatarRotation = FALSE;
-S32 LLVOAvatar::sFreezeCounter = 0 ;
+//-----------------------------------------------------------------------------
+// Global constants
+//-----------------------------------------------------------------------------
+const LLUUID ANIM_AGENT_BODY_NOISE = LLUUID("9aa8b0a6-0c6f-9518-c7c3-4f41f2c001ad"); //"body_noise"
+const LLUUID ANIM_AGENT_BREATHE_ROT	= LLUUID("4c5a103e-b830-2f1c-16bc-224aa0ad5bc8");  //"breathe_rot"
+const LLUUID ANIM_AGENT_EDITING	= LLUUID("2a8eba1d-a7f8-5596-d44a-b4977bf8c8bb");  //"editing"
+const LLUUID ANIM_AGENT_EYE	= LLUUID("5c780ea8-1cd1-c463-a128-48c023f6fbea");  //"eye"
+const LLUUID ANIM_AGENT_FLY_ADJUST = LLUUID("db95561f-f1b0-9f9a-7224-b12f71af126e");  //"fly_adjust"
+const LLUUID ANIM_AGENT_HAND_MOTION	= LLUUID("ce986325-0ba7-6e6e-cc24-b17c4b795578");  //"hand_motion"
+const LLUUID ANIM_AGENT_HEAD_ROT = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d");  //"head_rot"
+const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b");  //"pelvis_fix"
+const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55");  //"target"
+const LLUUID ANIM_AGENT_WALK_ADJUST	= LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d");  //"walk_adjust"
 
-//extern BOOL gVelocityInterpolate;
 
 //-----------------------------------------------------------------------------
 // Constants
 //-----------------------------------------------------------------------------
-const F32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024;
+const std::string AVATAR_DEFAULT_CHAR = "avatar";
 
-F32 SHADOW_OFFSET_AMT = 0.03f;
+const S32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024;
+const F32 SHADOW_OFFSET_AMT = 0.03f;
 
-#define DELTA_TIME_MIN			0.01f	// we clamp measured deltaTime to this
-#define DELTA_TIME_MAX			0.2f	// range to insure stability of computations.
+const F32 DELTA_TIME_MIN = 0.01f;	// we clamp measured deltaTime to this
+const F32 DELTA_TIME_MAX = 0.2f;	// range to insure stability of computations.
 
 const F32 PELVIS_LAG_FLYING		= 0.22f;// pelvis follow half life while flying
-
 const F32 PELVIS_LAG_WALKING	= 0.4f;	// ...while walking
-
 const F32 PELVIS_LAG_MOUSELOOK = 0.15f;
 const F32 MOUSELOOK_PELVIS_FOLLOW_FACTOR = 0.5f;
-
 const F32 PELVIS_LAG_WHEN_FOLLOW_CAM_IS_ON = 0.0001f; // not zero! - something gets divided by this!
 
-#define PELVIS_ROT_THRESHOLD_SLOW	60.0f	// amount of deviation allowed between
-#define PELVIS_ROT_THRESHOLD_FAST	2.0f	// the pelvis and the view direction
+const F32 PELVIS_ROT_THRESHOLD_SLOW = 60.0f;	// amount of deviation allowed between
+const F32 PELVIS_ROT_THRESHOLD_FAST = 2.0f;	// the pelvis and the view direction
 											// when moving fast & slow
-
-const F32 MIN_SPEED_PELVIS_FOLLOW = 0.1f;
-
-#define TORSO_NOISE_AMOUNT		1.f	// Amount of deviation from up-axis, in degrees
-#define TORSO_NOISE_SPEED		0.2f	// Time scale factor on torso noise.
+const F32 TORSO_NOISE_AMOUNT = 1.0f;	// Amount of deviation from up-axis, in degrees
+const F32 TORSO_NOISE_SPEED = 0.2f;	// Time scale factor on torso noise.
 
 const F32 BREATHE_ROT_MOTION_STRENGTH = 0.05f;
-
 const F32 BREATHE_SCALE_MOTION_STRENGTH = 0.005f;
 
-#define PELVIS_NOISE_FACTOR		0.5f	// amount of random noise
-
-#define AUDIO_STEP_PRI			0xC0000000
-#define AUDIO_STEP_LO_SPEED		0.01f	// as average speed goes from lo to hi,
-#define AUDIO_STEP_HI_SPEED		3.0f    // from lo to hi
-#define AUDIO_STEP_LO_GAIN		0.15f	// the resulting gain will ramp linearly
-#define AUDIO_STEP_HI_GAIN		0.15f
-
-const F32 DAMPED_MOTION_TIME_SCALE = 0.15f;
-
-const F32 LOOKAT_CAMERA_DIST_SQUARED = 25.f;
-
-#define AVATAR_HEADER		"Linden Avatar 1.0"
-#define AVATAR_SECTION		"[avatar]"
-
-#define AVATAR_DEFAULT_CHAR	"avatar"
-
 const F32 MIN_SHADOW_HEIGHT = 0.f;
 const F32 MAX_SHADOW_HEIGHT = 0.3f;
 
-#define MIN_REQUIRED_PIXEL_AREA_BODY_NOISE (10000.f)
-#define MIN_REQUIRED_PIXEL_AREA_BREATHE (10000.f)
-#define MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX (40.f)
+const S32 MIN_REQUIRED_PIXEL_AREA_BODY_NOISE = 10000;
+const S32 MIN_REQUIRED_PIXEL_AREA_BREATHE = 10000;
+const S32 MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX = 40;
 
-const S32 LOCTEX_IMAGE_SIZE_SELF = 512;
-const S32 LOCTEX_IMAGE_AREA_SELF = LOCTEX_IMAGE_SIZE_SELF * LOCTEX_IMAGE_SIZE_SELF;
-const S32 LOCTEX_IMAGE_SIZE_OTHER = LOCTEX_IMAGE_SIZE_SELF / 4;  // The size of local textures for other (!mIsSelf) avatars
-const S32 LOCTEX_IMAGE_AREA_OTHER = LOCTEX_IMAGE_SIZE_OTHER * LOCTEX_IMAGE_SIZE_OTHER;
+const S32 TEX_IMAGE_SIZE_SELF = 512;
+const S32 TEX_IMAGE_AREA_SELF = TEX_IMAGE_SIZE_SELF * TEX_IMAGE_SIZE_SELF;
+const S32 TEX_IMAGE_SIZE_OTHER = TEX_IMAGE_SIZE_SELF / 4;  // The size of local textures for other (!mIsSelf) avatars
+const S32 TEX_IMAGE_AREA_OTHER = TEX_IMAGE_SIZE_OTHER * TEX_IMAGE_SIZE_OTHER;
 
 const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f;
 
 const S32 MORPH_MASK_REQUESTED_DISCARD = 0;
-const S32 MIN_PIXEL_AREA_BUMP = 500;
 
 // Discard level at which to switch to baked textures
 // Should probably be 4 or 3, but didn't want to change it while change other logic - SJB
@@ -210,95 +147,34 @@ const F32 FOOT_COLLIDE_FUDGE = 0.04f;
 
 const F32 HOVER_EFFECT_MAX_SPEED = 3.f;
 const F32 HOVER_EFFECT_STRENGTH = 0.f;
-F32 UNDERWATER_EFFECT_STRENGTH = 0.1f;
+const F32 UNDERWATER_EFFECT_STRENGTH = 0.1f;
 const F32 UNDERWATER_FREQUENCY_DAMP = 0.33f;
 const F32 APPEARANCE_MORPH_TIME = 0.65f;
-const F32 CAMERA_SHAKE_ACCEL_THRESHOLD_SQUARED = 5.f * 5.f;
 const F32 TIME_BEFORE_MESH_CLEANUP = 5.f; // seconds
 const S32 AVATAR_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing memory
 const F32 FOOT_GROUND_COLLISION_TOLERANCE = 0.25f;
 const F32 AVATAR_LOD_TWEAK_RANGE = 0.7f;
-const S32 MAX_LOD_CHANGES_PER_FRAME = 2;
 const S32 MAX_BUBBLE_CHAT_LENGTH = 1023;
 const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12;
 const F32 CHAT_FADE_TIME = 8.0;
 const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f;
-const S32 MAX_BUBBLES = 7;
-
-S32 LLVOAvatar::sMaxVisible = 50;
 
-LLVOAvatar::ETextureIndex LLVOAvatar::sBakedTextureIndices[BAKED_TEXTURE_COUNT] = 
+enum ERenderName
 {
-	LLVOAvatar::TEX_HEAD_BAKED,
-	LLVOAvatar::TEX_UPPER_BAKED,
-	LLVOAvatar::TEX_LOWER_BAKED,
-	LLVOAvatar::TEX_EYES_BAKED,
-	LLVOAvatar::TEX_SKIRT_BAKED
+	RENDER_NAME_NEVER,
+	RENDER_NAME_FADE,
+	RENDER_NAME_ALWAYS
 };
 
 //-----------------------------------------------------------------------------
-// Utility functions
-//-----------------------------------------------------------------------------
-
-static F32 calc_bouncy_animation(F32 x)
-{
-	return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f;
-}
-
-BOOL LLLineSegmentCapsuleIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& p1, const LLVector3& p2, const F32& radius, LLVector3& result)
-{
-	return FALSE;
-}
-
-//-----------------------------------------------------------------------------
-// Static Data
+// Callback data
 //-----------------------------------------------------------------------------
-S32 LLVOAvatar::sMaxOtherAvatarsToComposite = 1;  // Only this many avatars (other than yourself) can be composited at a time.  Set in initClass().
-LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames;
-LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime;
-S32 LLVOAvatar::sScratchTexBytes = 0;
-F32 LLVOAvatar::sRenderDistance = 256.f;
-S32	LLVOAvatar::sNumVisibleAvatars = 0;
-S32	LLVOAvatar::sNumLODChangesThisFrame = 0;
-
-LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df");
-LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] =
-{
-	LLUUID(SND_STONE_RUBBER),
-	LLUUID(SND_METAL_RUBBER),
-	LLUUID(SND_GLASS_RUBBER),
-	LLUUID(SND_WOOD_RUBBER),
-	LLUUID(SND_FLESH_RUBBER),
-	LLUUID(SND_RUBBER_PLASTIC),
-	LLUUID(SND_RUBBER_RUBBER)
-};
-
-// static
-S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS;
-BOOL LLVOAvatar::sRenderGroupTitles = TRUE;
-S32 LLVOAvatar::sNumVisibleChatBubbles = 0;
-BOOL LLVOAvatar::sDebugInvisible = FALSE;
-BOOL LLVOAvatar::sShowAttachmentPoints = FALSE;
-BOOL LLVOAvatar::sShowAnimationDebug = FALSE;
-BOOL LLVOAvatar::sShowFootPlane = FALSE;
-BOOL LLVOAvatar::sShowCollisionVolumes = FALSE;
-BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE;
-F32 LLVOAvatar::sLODFactor = 1.f;
-BOOL LLVOAvatar::sUseImpostors = FALSE;
-BOOL LLVOAvatar::sJointDebug = FALSE;
-S32 LLVOAvatar::sCurJoint = 0;
-S32 LLVOAvatar::sCurVolume = 0;
-F32 LLVOAvatar::sUnbakedTime = 0.f;
-F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
-F32 LLVOAvatar::sGreyTime = 0.f;
-F32 LLVOAvatar::sGreyUpdateTime = 0.f;
-
 struct LLAvatarTexData
 {
-	LLAvatarTexData( const LLUUID& id, LLVOAvatar::ELocTexIndex index )
+	LLAvatarTexData( const LLUUID& id, ETextureIndex index )
 		: mAvatarID(id), mIndex(index) {}
 	LLUUID				mAvatarID;
-	LLVOAvatar::ELocTexIndex	mIndex;
+	ETextureIndex	mIndex;
 };
 
 struct LLTextureMaskData
@@ -309,6 +185,142 @@ struct LLTextureMaskData
 	S32					mLastDiscardLevel;
 };
 
+/*********************************************************************************
+ **                                                                             **
+ ** Begin LLVOAvatar Support classes
+ **
+ **/
+
+//------------------------------------------------------------------------
+// LLVOBoneInfo
+// Trans/Scale/Rot etc. info about each avatar bone.  Used by LLVOAvatarSkeleton.
+//------------------------------------------------------------------------
+class LLVOAvatarBoneInfo
+{
+	friend class LLVOAvatar;
+	friend class LLVOAvatarSkeletonInfo;
+public:
+	LLVOAvatarBoneInfo() : mIsJoint(FALSE) {}
+	~LLVOAvatarBoneInfo()
+	{
+		std::for_each(mChildList.begin(), mChildList.end(), DeletePointer());
+	}
+	BOOL parseXml(LLXmlTreeNode* node);
+	
+private:
+	std::string mName;
+	BOOL mIsJoint;
+	LLVector3 mPos;
+	LLVector3 mRot;
+	LLVector3 mScale;
+	LLVector3 mPivot;
+	typedef std::vector<LLVOAvatarBoneInfo*> child_list_t;
+	child_list_t mChildList;
+};
+
+//------------------------------------------------------------------------
+// LLVOAvatarSkeletonInfo
+// Overall avatar skeleton
+//------------------------------------------------------------------------
+class LLVOAvatarSkeletonInfo
+{
+	friend class LLVOAvatar;
+public:
+	LLVOAvatarSkeletonInfo() :
+		mNumBones(0), mNumCollisionVolumes(0) {}
+	~LLVOAvatarSkeletonInfo()
+	{
+		std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer());
+	}
+	BOOL parseXml(LLXmlTreeNode* node);
+	S32 getNumBones() const { return mNumBones; }
+	S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; }
+	
+private:
+	S32 mNumBones;
+	S32 mNumCollisionVolumes;
+	typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t;
+	bone_info_list_t mBoneInfoList;
+};
+
+
+//------------------------------------------------------------------------
+// LLVOAvatarXmlInfo
+// One instance (in LLVOAvatar) with common data parsed from the XML files
+//------------------------------------------------------------------------
+class LLVOAvatarXmlInfo
+{
+	friend class LLVOAvatar;
+public:
+	LLVOAvatarXmlInfo();
+	~LLVOAvatarXmlInfo();
+	
+private:
+	BOOL 	parseXmlSkeletonNode(LLXmlTreeNode* root);
+	BOOL 	parseXmlMeshNodes(LLXmlTreeNode* root);
+	BOOL 	parseXmlColorNodes(LLXmlTreeNode* root);
+	BOOL 	parseXmlLayerNodes(LLXmlTreeNode* root);
+	BOOL 	parseXmlDriverNodes(LLXmlTreeNode* root);
+	
+	struct LLVOAvatarMeshInfo
+	{
+		typedef std::pair<LLPolyMorphTargetInfo*,BOOL> morph_info_pair_t;
+		typedef std::vector<morph_info_pair_t> morph_info_list_t;
+
+		LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {}
+		~LLVOAvatarMeshInfo()
+		{
+			morph_info_list_t::iterator iter;
+			for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++)
+			{
+				delete iter->first;
+			}
+			mPolyMorphTargetInfoList.clear();
+		}
+
+		std::string mType;
+		S32			mLOD;
+		std::string	mMeshFileName;
+		std::string	mReferenceMeshName;
+		F32			mMinPixelArea;
+		morph_info_list_t mPolyMorphTargetInfoList;
+	};
+	typedef std::vector<LLVOAvatarMeshInfo*> mesh_info_list_t;
+	mesh_info_list_t mMeshInfoList;
+
+	typedef std::vector<LLPolySkeletalDistortionInfo*> skeletal_distortion_info_list_t;
+	skeletal_distortion_info_list_t mSkeletalDistortionInfoList;
+	
+	struct LLVOAvatarAttachmentInfo
+	{
+		LLVOAvatarAttachmentInfo()
+			: mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE),
+			  mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {}
+		std::string mName;
+		std::string mJointName;
+		LLVector3 mPosition;
+		LLVector3 mRotationEuler;
+		S32 mGroup;
+		S32 mAttachmentID;
+		S32 mPieMenuSlice;
+		BOOL mVisibleFirstPerson;
+		BOOL mIsHUDAttachment;
+		BOOL mHasPosition;
+		BOOL mHasRotation;
+	};
+	typedef std::vector<LLVOAvatarAttachmentInfo*> attachment_info_list_t;
+	attachment_info_list_t mAttachmentInfoList;
+	
+	LLTexGlobalColorInfo *mTexSkinColorInfo;
+	LLTexGlobalColorInfo *mTexHairColorInfo;
+	LLTexGlobalColorInfo *mTexEyeColorInfo;
+
+	typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t;
+	layer_info_list_t mLayerInfoList;
+
+	typedef std::vector<LLDriverParamInfo*> driver_info_list_t;
+	driver_info_list_t mDriverInfoList;
+};
 
 //-----------------------------------------------------------------------------
 // class LLBodyNoiseMotion
@@ -322,7 +334,6 @@ public:
 		: LLMotion(id)
 	{
 		mName = "body_noise";
-
 		mTorsoState = new LLJointState;
 	}
 
@@ -409,7 +420,7 @@ public:
 	// called when a motion is deactivated
 	virtual void onDeactivate() {}
 
-public:
+private:
 	//-------------------------------------------------------------------------
 	// joint states to be animated
 	//-------------------------------------------------------------------------
@@ -430,12 +441,11 @@ public:
 		mCharacter(NULL)
 	{
 		mName = "breathe_rot";
-
 		mChestState = new LLJointState;
 	}
 
 	// Destructor
-	virtual ~LLBreatheMotionRot() { }
+	virtual ~LLBreatheMotionRot() {}
 
 public:
 	//-------------------------------------------------------------------------
@@ -518,7 +528,7 @@ public:
 	// called when a motion is deactivated
 	virtual void onDeactivate() {}
 
-public:
+private:
 	//-------------------------------------------------------------------------
 	// joint states to be animated
 	//-------------------------------------------------------------------------
@@ -615,7 +625,7 @@ public:
 	// called when a motion is deactivated
 	virtual void onDeactivate() {}
 
-public:
+private:
 	//-------------------------------------------------------------------------
 	// joint states to be animated
 	//-------------------------------------------------------------------------
@@ -623,20 +633,74 @@ public:
 	LLCharacter*		mCharacter;
 };
 
+/**
+ **
+ ** End LLVOAvatar Support classes
+ **                                                                             **
+ *********************************************************************************/
+
+
+//-----------------------------------------------------------------------------
+// Static Data
+//-----------------------------------------------------------------------------
+LLXmlTree LLVOAvatar::sXMLTree;
+LLXmlTree LLVOAvatar::sSkeletonXMLTree;
+BOOL LLVOAvatar::sDebugAvatarRotation = FALSE;
+LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL;
+LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;
+LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL;
+S32 LLVOAvatar::sFreezeCounter = 0;
+S32 LLVOAvatar::sMaxVisible = 50;
+LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames;
+LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime;
+S32 LLVOAvatar::sScratchTexBytes = 0;
+F32 LLVOAvatar::sRenderDistance = 256.f;
+S32	LLVOAvatar::sNumVisibleAvatars = 0;
+S32	LLVOAvatar::sNumLODChangesThisFrame = 0;
+
+const LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df");
+const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] =
+{
+	LLUUID(SND_STONE_RUBBER),
+	LLUUID(SND_METAL_RUBBER),
+	LLUUID(SND_GLASS_RUBBER),
+	LLUUID(SND_WOOD_RUBBER),
+	LLUUID(SND_FLESH_RUBBER),
+	LLUUID(SND_RUBBER_PLASTIC),
+	LLUUID(SND_RUBBER_RUBBER)
+};
+
+S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS;
+BOOL LLVOAvatar::sRenderGroupTitles = TRUE;
+S32 LLVOAvatar::sNumVisibleChatBubbles = 0;
+BOOL LLVOAvatar::sDebugInvisible = FALSE;
+BOOL LLVOAvatar::sShowAttachmentPoints = FALSE;
+BOOL LLVOAvatar::sShowAnimationDebug = FALSE;
+BOOL LLVOAvatar::sShowFootPlane = FALSE;
+BOOL LLVOAvatar::sShowCollisionVolumes = FALSE;
+BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE;
+F32 LLVOAvatar::sLODFactor = 1.f;
+BOOL LLVOAvatar::sUseImpostors = FALSE;
+BOOL LLVOAvatar::sJointDebug = FALSE;
+
+F32 LLVOAvatar::sUnbakedTime = 0.f;
+F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
+F32 LLVOAvatar::sGreyTime = 0.f;
+F32 LLVOAvatar::sGreyUpdateTime = 0.f;
+
+//-----------------------------------------------------------------------------
+// Helper functions
+//-----------------------------------------------------------------------------
+static F32 calc_bouncy_animation(F32 x);
+static U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures);
+
 //-----------------------------------------------------------------------------
 // LLVOAvatar()
 //-----------------------------------------------------------------------------
-LLVOAvatar::LLVOAvatar(
-	const LLUUID& id,
-	const LLPCode pcode,
-	LLViewerRegion* regionp)
-	:
+LLVOAvatar::LLVOAvatar(const LLUUID& id,
+					   const LLPCode pcode,
+					   LLViewerRegion* regionp) :
 	LLViewerObject(id, pcode, regionp),
-	mLastHeadBakedID( IMG_DEFAULT_AVATAR ),
-	mLastUpperBodyBakedID( IMG_DEFAULT_AVATAR ),
-	mLastLowerBodyBakedID( IMG_DEFAULT_AVATAR ),
-	mLastEyesBakedID( IMG_DEFAULT_AVATAR ),
-	mLastSkirtBakedID( IMG_DEFAULT_AVATAR ),
 	mIsDummy(FALSE),
 	mSpecialRenderMode(0),
 	mTurning(FALSE),
@@ -654,12 +718,6 @@ LLVOAvatar::LLVOAvatar(
 	mAppearanceAnimSetByUser(FALSE),
 	mLastAppearanceBlendTime(0.f),
 	mAppearanceAnimating(FALSE),
-	mHeadLayerSet( NULL ),
-	mUpperBodyLayerSet( NULL ),
-	mLowerBodyLayerSet( NULL ),
-	mEyesLayerSet( NULL ),
-	mSkirtLayerSet( NULL ),
-	mRenderPriority(1.0f),
 	mNameString(),
 	mTitle(),
 	mNameAway(FALSE),
@@ -671,17 +729,6 @@ LLVOAvatar::LLVOAvatar(
 	mRegionCrossingCount(0),
 	mFirstTEMessageReceived( FALSE ),
 	mFirstAppearanceMessageReceived( FALSE ),
-	mHeadBakedLoaded(FALSE),
-	mHeadMaskDiscard(-1),
-	mUpperBakedLoaded(FALSE),
-	mUpperMaskDiscard(-1),
-	mLowerBakedLoaded(FALSE),
-	mLowerMaskDiscard(-1),
-	mEyesBakedLoaded(FALSE),
-	mSkirtBakedLoaded(FALSE),
-	mHeadMaskTexName(0),
-	mUpperMaskTexName(0),
-	mLowerMaskTexName(0),
 	mCulled( FALSE ),
 	mVisibilityRank(0),
 	mTexSkinColor( NULL ),
@@ -689,24 +736,36 @@ LLVOAvatar::LLVOAvatar(
 	mTexEyeColor( NULL ),
 	mNeedsSkin(FALSE),
 	mUpdatePeriod(1),
-	mFullyLoadedInitialized(FALSE)
+	mFullyLoadedInitialized(FALSE),
+	mHasBakedHair( FALSE )
 {
 	LLMemType mt(LLMemType::MTYPE_AVATAR);
-	
 	//VTResume();  // VTune
 	
 	// mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline
-	bool needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
+	const bool needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
 	mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
 
 	lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl;
 
 	mPelvisp = NULL;
 
-	for( S32 i=0; i<LOCTEX_NUM_ENTRIES; i++ )
+	for( S32 i=0; i<TEX_NUM_INDICES; i++ )
+	{
+		if (isIndexLocalTexture((ETextureIndex)i))
+		{
+			mLocalTextureData[(ETextureIndex)i] = LocalTextureData();
+		}
+	}
+
+	mBakedTextureData.resize(BAKED_NUM_INDICES);
+	for (U32 i = 0; i < mBakedTextureData.size(); i++ )
 	{
-		mLocalTextureBaked[i] = FALSE;
-		mLocalTextureDiscard[i] = MAX_DISCARD_LEVEL+1;
+		mBakedTextureData[i].mLastTextureIndex = IMG_DEFAULT_AVATAR;
+		mBakedTextureData[i].mTexLayerSet = NULL;
+		mBakedTextureData[i].mIsLoaded = false;
+		mBakedTextureData[i].mMaskTexName = 0;
+		mBakedTextureData[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i);
 	}
 
 	mDirtyMesh = TRUE;	// Dirty geometry, need to regenerate.
@@ -744,7 +803,7 @@ LLVOAvatar::LLVOAvatar(
 	mImpostorDistance = 0;
 	mImpostorPixelArea = 0;
 
-	setNumTEs(TEX_NUM_ENTRIES);
+	setNumTEs(TEX_NUM_INDICES);
 
 	mbCanSelect = TRUE;
 
@@ -777,118 +836,71 @@ LLVOAvatar::LLVOAvatar(
 	//-------------------------------------------------------------------------
 	mRoot.setName( "mRoot" );
 
-	// skinned mesh objects
-	mHairLOD.setName("mHairLOD");
-	mHairMesh0.setName("mHairMesh0");
-	mHairMesh0.setMeshID(MESH_ID_HAIR);
-	mHairMesh1.setName("mHairMesh1");
-	mHairMesh2.setName("mHairMesh2");
-	mHairMesh3.setName("mHairMesh3");
-	mHairMesh4.setName("mHairMesh4");
-	mHairMesh5.setName("mHairMesh5");
-	
-	mHairMesh0.setIsTransparent(TRUE);
-	mHairMesh1.setIsTransparent(TRUE);
-	mHairMesh2.setIsTransparent(TRUE);
-	mHairMesh3.setIsTransparent(TRUE);
-	mHairMesh4.setIsTransparent(TRUE);
-	mHairMesh5.setIsTransparent(TRUE);
-
-	mHeadLOD.setName("mHeadLOD");
-	mHeadMesh0.setName("mHeadMesh0");
-	mHeadMesh0.setMeshID(MESH_ID_HEAD);
-	mHeadMesh1.setName("mHeadMesh1");
-	mHeadMesh2.setName("mHeadMesh2");
-	mHeadMesh3.setName("mHeadMesh3");
-	mHeadMesh4.setName("mHeadMesh4");
-	
-	mEyeLashLOD.setName("mEyeLashLOD");
-	mEyeLashMesh0.setName("mEyeLashMesh0");
-	mEyeLashMesh0.setMeshID(MESH_ID_HEAD);
-	mEyeLashMesh0.setIsTransparent(TRUE);
-
-	mUpperBodyLOD.setName("mUpperBodyLOD");
-	mUpperBodyMesh0.setName("mUpperBodyMesh0");
-	mUpperBodyMesh0.setMeshID(MESH_ID_UPPER_BODY);
-	mUpperBodyMesh1.setName("mUpperBodyMesh1");
-	mUpperBodyMesh2.setName("mUpperBodyMesh2");
-	mUpperBodyMesh3.setName("mUpperBodyMesh3");
-	mUpperBodyMesh4.setName("mUpperBodyMesh4");
-
-	mLowerBodyLOD.setName("mLowerBodyLOD");
-	mLowerBodyMesh0.setName("mLowerBodyMesh0");
-	mLowerBodyMesh0.setMeshID(MESH_ID_LOWER_BODY);
-	mLowerBodyMesh1.setName("mLowerBodyMesh1");
-	mLowerBodyMesh2.setName("mLowerBodyMesh2");
-	mLowerBodyMesh3.setName("mLowerBodyMesh3");
-	mLowerBodyMesh4.setName("mLowerBodyMesh4");
-
-	mEyeBallLeftLOD.setName("mEyeBallLeftLOD");
-	mEyeBallLeftMesh0.setName("mEyeBallLeftMesh0");
-	mEyeBallLeftMesh1.setName("mEyeBallLeftMesh1");
-
-	mEyeBallRightLOD.setName("mEyeBallRightLOD");
-	mEyeBallRightMesh0.setName("mEyeBallRightMesh0");
-	mEyeBallRightMesh1.setName("mEyeBallRightMesh1");
-
-	mSkirtLOD.setName("mSkirtLOD");
-	mSkirtMesh0.setName("mSkirtMesh0");
-	mSkirtMesh0.setMeshID(MESH_ID_SKIRT);
-	mSkirtMesh1.setName("mSkirtMesh1");
-	mSkirtMesh2.setName("mSkirtMesh2");
-	mSkirtMesh3.setName("mSkirtMesh3");
-	mSkirtMesh4.setName("mSkirtMesh4");
-
-	mSkirtMesh0.setIsTransparent(TRUE);
-	mSkirtMesh1.setIsTransparent(TRUE);
-	mSkirtMesh2.setIsTransparent(TRUE);
-	mSkirtMesh3.setIsTransparent(TRUE);
-	mSkirtMesh4.setIsTransparent(TRUE);
-
-	// set the pick names for the avatar
-	mHeadMesh0.setPickName( LLViewerJoint::PN_0 );
-	mHeadMesh1.setPickName( LLViewerJoint::PN_0 );
-	mHeadMesh2.setPickName( LLViewerJoint::PN_0 );
-	mHeadMesh3.setPickName( LLViewerJoint::PN_0 );
-	mHeadMesh4.setPickName( LLViewerJoint::PN_0 );
-	mEyeLashMesh0.setPickName( LLViewerJoint::PN_0 );
-
-	mUpperBodyMesh0.setPickName( LLViewerJoint::PN_1 );
-	mUpperBodyMesh1.setPickName( LLViewerJoint::PN_1 );
-	mUpperBodyMesh2.setPickName( LLViewerJoint::PN_1 );
-	mUpperBodyMesh3.setPickName( LLViewerJoint::PN_1 );
-	mUpperBodyMesh4.setPickName( LLViewerJoint::PN_1 );
-
-	mLowerBodyMesh0.setPickName( LLViewerJoint::PN_2 );
-	mLowerBodyMesh1.setPickName( LLViewerJoint::PN_2 );
-	mLowerBodyMesh2.setPickName( LLViewerJoint::PN_2 );
-	mLowerBodyMesh3.setPickName( LLViewerJoint::PN_2 );
-	mLowerBodyMesh4.setPickName( LLViewerJoint::PN_2 );
-
-	mEyeBallLeftMesh0.setPickName( LLViewerJoint::PN_3 );
-	mEyeBallLeftMesh1.setPickName( LLViewerJoint::PN_3 );
-	mEyeBallRightMesh0.setPickName( LLViewerJoint::PN_3 );
-	mEyeBallRightMesh1.setPickName( LLViewerJoint::PN_3 );
-
-	mHairMesh0.setPickName( LLViewerJoint::PN_4);
-	mHairMesh1.setPickName( LLViewerJoint::PN_4);
-	mHairMesh2.setPickName( LLViewerJoint::PN_4);
-	mHairMesh3.setPickName( LLViewerJoint::PN_4);
-	mHairMesh4.setPickName( LLViewerJoint::PN_4);
-	mHairMesh5.setPickName( LLViewerJoint::PN_4);
-
-	mSkirtMesh0.setPickName( LLViewerJoint::PN_5 );
-	mSkirtMesh1.setPickName( LLViewerJoint::PN_5 );
-	mSkirtMesh2.setPickName( LLViewerJoint::PN_5 );
-	mSkirtMesh3.setPickName( LLViewerJoint::PN_5 );
-	mSkirtMesh4.setPickName( LLViewerJoint::PN_5 );
-
-	// material settings
-
-	mEyeBallLeftMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
-	mEyeBallLeftMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
-	mEyeBallRightMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
-	mEyeBallRightMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
+	for (LLVOAvatarDictionary::mesh_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
+		 iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
+		 iter++)
+	{
+		const EMeshIndex mesh_index = iter->first;
+		const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = iter->second;
+
+		LLViewerJoint* joint = new LLViewerJoint();
+		joint->setName(mesh_dict->mName);
+		joint->setMeshID(mesh_index);
+		mMeshLOD.push_back(joint);
+		
+		/* mHairLOD.setName("mHairLOD");
+		   mHairMesh0.setName("mHairMesh0");
+		   mHairMesh0.setMeshID(MESH_ID_HAIR);
+		   mHairMesh1.setName("mHairMesh1"); */
+		for (U32 lod = 0; lod < mesh_dict->mLOD; lod++)
+		{
+			LLViewerJointMesh* mesh = new LLViewerJointMesh();
+			std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast<std::string>(lod);
+			// We pre-pended an m - need to capitalize first character for camelCase
+			mesh_name[1] = toupper(mesh_name[1]);
+			mesh->setName(mesh_name);
+			mesh->setMeshID(mesh_index);
+			mesh->setPickName(mesh_dict->mPickName);
+			switch((int)mesh_index)
+			{
+				case MESH_ID_HAIR:
+					mesh->setIsTransparent(TRUE);
+					break;
+				case MESH_ID_SKIRT:
+					mesh->setIsTransparent(TRUE);
+					break;
+				case MESH_ID_EYEBALL_LEFT:
+				case MESH_ID_EYEBALL_RIGHT:
+					mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f );
+					break;
+			}
+
+			joint->mMeshParts.push_back(mesh);
+		}
+	}
+
+	//-------------------------------------------------------------------------
+	// associate baked textures with meshes
+	//-------------------------------------------------------------------------
+	for (LLVOAvatarDictionary::mesh_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
+		 iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
+		 iter++)
+	{
+		const EMeshIndex mesh_index = iter->first;
+		const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = iter->second;
+		const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID;
+
+		// Skip it if there's no associated baked texture.
+		if (baked_texture_index == BAKED_NUM_INDICES) continue;
+
+		for (std::vector<LLViewerJointMesh* >::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin();
+			 iter != mMeshLOD[mesh_index]->mMeshParts.end(); iter++)
+		{
+			LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter;
+			mBakedTextureData[(int)baked_texture_index].mMeshes.push_back(mesh);
+		}
+	}
+
 
 	//-------------------------------------------------------------------------
 	// register motions
@@ -987,20 +999,11 @@ LLVOAvatar::~LLVOAvatar()
 
 	mNumJoints = 0;
 
-	delete mHeadLayerSet;
-	mHeadLayerSet = NULL;
-
-	delete mUpperBodyLayerSet;
-	mUpperBodyLayerSet = NULL;
-
-	delete mLowerBodyLayerSet;
-	mLowerBodyLayerSet = NULL;
-
-	delete mEyesLayerSet;
-	mEyesLayerSet = NULL;
-
-	delete mSkirtLayerSet;
-	mSkirtLayerSet = NULL;
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
+	{
+		delete mBakedTextureData[i].mTexLayerSet;
+		mBakedTextureData[i].mTexLayerSet = NULL;
+	}
 
 	std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer());
 	mAttachmentPoints.clear();
@@ -1014,6 +1017,16 @@ LLVOAvatar::~LLVOAvatar()
 
 	std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer());
 	mMeshes.clear();
+
+	for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
+		jointIter != mMeshLOD.end(); jointIter++)
+	{
+		LLViewerJoint* joint = (LLViewerJoint *) *jointIter;
+		std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer());
+		joint->mMeshParts.clear();
+	}
+	std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer());
+	mMeshLOD.clear();
 	
 	mDead = TRUE;
 	
@@ -1045,45 +1058,34 @@ BOOL LLVOAvatar::isFullyBaked()
 {
 	if (mIsDummy) return TRUE;
 	if (getNumTEs() == 0) return FALSE;
-	
-	BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR );
 
-	if (isWearingWearableType(WT_SKIRT))
-	{
-		return head_baked && upper_baked && lower_baked && eyes_baked && skirt_baked;
-	}
-	else
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		return head_baked && upper_baked && lower_baked && eyes_baked;
+		if (!isTextureDefined(mBakedTextureData[i].mTextureIndex)
+			&& ( (i != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ) )
+		{
+			return FALSE;
+		}
 	}
+	return TRUE;
 }
 
-void LLVOAvatar::deleteLayerSetCaches()
+void LLVOAvatar::deleteLayerSetCaches(bool clearAll)
 {
-	if( mHeadLayerSet )			mHeadLayerSet->deleteCaches();
-	if( mUpperBodyLayerSet )	mUpperBodyLayerSet->deleteCaches();
-	if( mLowerBodyLayerSet )	mLowerBodyLayerSet->deleteCaches();
-	if( mEyesLayerSet )			mEyesLayerSet->deleteCaches();
-	if( mSkirtLayerSet )		mSkirtLayerSet->deleteCaches();
-
-	if(mUpperMaskTexName)
-	{
-		glDeleteTextures(1, (GLuint*)&mUpperMaskTexName);
-		mUpperMaskTexName = 0 ;
-	}
-	if(mHeadMaskTexName)
-	{
-		glDeleteTextures(1, (GLuint*)&mHeadMaskTexName);
-		mHeadMaskTexName = 0 ;
-	}
-	if(mLowerMaskTexName)
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		glDeleteTextures(1, (GLuint*)&mLowerMaskTexName);
-		mLowerMaskTexName = 0 ;
+		if (mBakedTextureData[i].mTexLayerSet)
+		{
+			if ((i != BAKED_HAIR || mIsSelf) && !clearAll)		// Backwards compatibility - can be removed after hair baking is mandatory on the grid
+			{
+				mBakedTextureData[i].mTexLayerSet->deleteCaches();
+			}
+		}
+		if (mBakedTextureData[i].mMaskTexName)
+		{
+			glDeleteTextures(1, (GLuint*)&(mBakedTextureData[i].mMaskTexName));
+			mBakedTextureData[i].mMaskTexName = 0 ;
+		}
 	}
 }
 
@@ -1154,7 +1156,7 @@ void LLVOAvatar::dumpBakedStatus()
 			llcont << " DEAD ("<< inst->getNumRefs() << " refs)";
 		}
 
-		if( inst->mIsSelf )
+		if( inst->isSelf() )
 		{
 			llcont << " (self)";
 		}
@@ -1181,154 +1183,49 @@ void LLVOAvatar::dumpBakedStatus()
 		else
 		{
 			llcont << " Unbaked (";
-			if( inst->getTEImage( TEX_HEAD_BAKED )->getID()  == IMG_DEFAULT_AVATAR )
-			{
-				llcont << " head";
-			}
-
-			if( inst->getTEImage( TEX_UPPER_BAKED )->getID() == IMG_DEFAULT_AVATAR )
-			{
-				llcont << " upper";
-			}
-
-			if( inst->getTEImage( TEX_LOWER_BAKED )->getID() == IMG_DEFAULT_AVATAR )
-			{
-				llcont << " lower";
-			}
-
-			if( inst->getTEImage( TEX_EYES_BAKED )->getID()  == IMG_DEFAULT_AVATAR )
-			{
-				llcont << " eyes";
-			}
-
-			if (inst->isWearingWearableType(WT_SKIRT))
+			
+			for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+				 iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
+				 iter++)
 			{
-				if( inst->getTEImage( TEX_SKIRT_BAKED )->getID()  == IMG_DEFAULT_AVATAR )
+				const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second;
+				const ETextureIndex index = baked_dict->mTextureIndex;
+				if (!inst->isTextureDefined(index))
 				{
-					llcont << " skirt";
+					llcont << " " << LLVOAvatarDictionary::getInstance()->getTexture(index)->mName;
 				}
 			}
 
-			llcont << " ) " << inst->getUnbakedPixelAreaRank() << "/" << LLVOAvatar::sMaxOtherAvatarsToComposite;
+			llcont << " ) " << inst->getUnbakedPixelAreaRank();
 			if( inst->isCulled() )
 			{
 				llcont << " culled";
 			}
 		}
 		llcont << llendl;
-/*
-		if( inst->isDead() )
+	}
+}
+
+//static
+void LLVOAvatar::restoreGL()
+{
+	for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+		iter != LLCharacter::sInstances.end(); ++iter)
+	{
+		LLVOAvatar* inst = (LLVOAvatar*) *iter;
+		inst->setCompositeUpdatesEnabled( TRUE );
+		for (U32 i = 0; i < inst->mBakedTextureData.size(); i++)
 		{
-			llinfos << "DEAD LIST " << llendl;
+			inst->invalidateComposite( inst->mBakedTextureData[i].mTexLayerSet, FALSE );
+		}
+		inst->updateMeshTextures();
+	}
+}
 
-			
-			for( S32 i = 0; i < inst->mOwners.count(); i++ )
-			{
-				llinfos << i << llendl;
-				LLPointer<LLViewerObject>* owner = (LLPointer<LLViewerObject>*)(inst->mOwners[i]);
-				LLPointer<LLViewerObject>* cur;
-				if( !owner->mName.isEmpty() )
-				{
-					llinfos << "    " << owner->mName << llendl;
-				}
-
-				LLViewerObject* key_vo;
-				for( key_vo = gObjectList.mActiveObjects.getFirstKey(); key_vo; key_vo = gObjectList.mActiveObjects.getNextKey() )
-				{
-					cur = &(gObjectList.mActiveObjects.getCurrentDataWithoutIncrement());
-					if( cur == owner )
-					{
-						llinfos << "    gObjectList.mActiveObjects" << llendl;
-					}
-				}
-
-				for( key_vo = gObjectList.mAvatarObjects.getFirstKey(); key_vo; key_vo = gObjectList.mAvatarObjects.getNextKey() )
-				{
-					cur = &(gObjectList.mAvatarObjects.getCurrentDataWithoutIncrement());	
-					if( cur == owner )
-					{
-						llinfos << "    gObjectList.mAvatarObjects" << llendl;
-					}
-				}
-
-				LLUUID id;
-				for( id = gObjectList.mDeadObjects.getFirstKey(); id; id = gObjectList.mDeadObjects.getNextKey() )
-				{
-					cur = &(gObjectList.mDeadObjects.getCurrentDataWithoutIncrement());
-					if( cur == owner )
-					{
-						llinfos << "    gObjectList.mDeadObjects" << llendl;
-					}
-				}
-
-
-				for( id = gObjectList.mUUIDObjectMap.getFirstKey(); id; id = gObjectList.mUUIDObjectMap.getNextKey() )
-				{
-					cur = &(gObjectList.mUUIDObjectMap.getCurrentDataWithoutIncrement());
-					if( cur == owner )
-					{
-						llinfos << "    gObjectList.mUUIDObjectMap" << llendl;
-					}
-				}
-
-				S32 j;
-				S32 k;
-				for( j = 0; j < 16; j++ )
-				{
-					for( k = 0; k < 10; k++ )
-					{
-						cur = &(gObjectList.mCloseObjects[j][k]);
-						if( cur == owner )
-						{
-							llinfos << "    gObjectList.mCloseObjects" << llendl;
-						}
-					}
-				}
-
-				for( j = 0; j < gObjectList.mObjects.count(); j++ )
-				{
-					cur = &(gObjectList.mObjects[j]);
-					if( cur == owner )
-					{
-						llinfos << "    gObjectList.mObjects" << llendl;
-					}
-				}
-
-				for( j = 0; j < gObjectList.mMapObjects.count(); j++ )
-				{
-					cur = &(gObjectList.mMapObjects[j]);
-					if( cur == owner )
-					{
-						llinfos << "    gObjectList.mMapObjects" << llendl;
-					}
-				}
-			}
-		}
-		*/
-	}
-}
-
-//static
-void LLVOAvatar::restoreGL()
-{
-	for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
-		iter != LLCharacter::sInstances.end(); ++iter)
-	{
-		LLVOAvatar* inst = (LLVOAvatar*) *iter;
-		inst->setCompositeUpdatesEnabled( TRUE );
-		inst->invalidateComposite( inst->mHeadLayerSet,		FALSE );
-		inst->invalidateComposite( inst->mLowerBodyLayerSet,	FALSE );
-		inst->invalidateComposite( inst->mUpperBodyLayerSet,	FALSE );
-		inst->invalidateComposite( inst->mEyesLayerSet,	FALSE );
-		inst->invalidateComposite( inst->mSkirtLayerSet,	FALSE );
-		inst->updateMeshTextures();
-	}
-}
-
-//static
-void LLVOAvatar::destroyGL()
-{
-	deleteCachedImages();
+//static
+void LLVOAvatar::destroyGL()
+{
+	deleteCachedImages();
 
 	resetImpostors();
 }
@@ -1345,7 +1242,7 @@ void LLVOAvatar::resetImpostors()
 }
 
 // static
-void LLVOAvatar::deleteCachedImages()
+void LLVOAvatar::deleteCachedImages(bool clearAll)
 {
 	if (LLTexLayerSet::sHasCaches)
 	{
@@ -1354,12 +1251,12 @@ void LLVOAvatar::deleteCachedImages()
 		iter != LLCharacter::sInstances.end(); ++iter)
 		{
 			LLVOAvatar* inst = (LLVOAvatar*) *iter;
-			inst->deleteLayerSetCaches();
+			inst->deleteLayerSetCaches(clearAll);
 		}
 		LLTexLayerSet::sHasCaches = FALSE;
 	}
 	
-	for( LLGLuint * namep = sScratchTexNames.getFirstData(); 
+	for( LLGLuint* namep = sScratchTexNames.getFirstData(); 
 		 namep; 
 		 namep = sScratchTexNames.getNextData() )
 	{
@@ -1387,8 +1284,6 @@ void LLVOAvatar::deleteCachedImages()
 //------------------------------------------------------------------------
 void LLVOAvatar::initClass()
 { 
-	LLVOAvatar::sMaxOtherAvatarsToComposite = gSavedSettings.getS32("AvatarCompositeLimit");
-
 	std::string xmlFile;
 
 	xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml";
@@ -1452,44 +1347,45 @@ void LLVOAvatar::initClass()
 	// Process XML data
 
 	// avatar_skeleton.xml
-	llassert(!sSkeletonInfo);
-	sSkeletonInfo = new LLVOAvatarSkeletonInfo;
-	if (!sSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot()))
+	llassert(!sAvatarSkeletonInfo);
+	sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo;
+	if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot()))
 	{
 		llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl;
 	}
 	// parse avatar_lad.xml
-	llassert(!sAvatarInfo);
-	sAvatarInfo = new LLVOAvatarInfo;
-	if (!sAvatarInfo->parseXmlSkeletonNode(root))
+	llassert(!sAvatarXmlInfo);
+	sAvatarXmlInfo = new LLVOAvatarXmlInfo;
+	if (!sAvatarXmlInfo->parseXmlSkeletonNode(root))
 	{
 		llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
 	}
-	if (!sAvatarInfo->parseXmlMeshNodes(root))
+	if (!sAvatarXmlInfo->parseXmlMeshNodes(root))
 	{
 		llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
 	}
-	if (!sAvatarInfo->parseXmlColorNodes(root))
+	if (!sAvatarXmlInfo->parseXmlColorNodes(root))
 	{
 		llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
 	}
-	if (!sAvatarInfo->parseXmlLayerNodes(root))
+	if (!sAvatarXmlInfo->parseXmlLayerNodes(root))
 	{
 		llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
 	}
-	if (!sAvatarInfo->parseXmlDriverNodes(root))
+	if (!sAvatarXmlInfo->parseXmlDriverNodes(root))
 	{
 		llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
 	}
+
 }
 
 
 void LLVOAvatar::cleanupClass()
 {
-	delete sAvatarInfo;
-	sAvatarInfo = NULL;
-	delete sSkeletonInfo;
-	sSkeletonInfo = NULL;
+	delete sAvatarXmlInfo;
+	sAvatarXmlInfo = NULL;
+	delete sAvatarSkeletonInfo;
+	sAvatarSkeletonInfo = NULL;
 	sSkeletonXMLTree.cleanup();
 	sXMLTree.cleanup();
 }
@@ -1552,7 +1448,7 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
 	newMax = pos + buffer;
 	
 	//stretch bounding box by joint positions
-	for (mesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i)
+	for (polymesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i)
 	{
 		LLPolyMesh* mesh = i->second;
 		for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.count(); joint_num++)
@@ -1571,7 +1467,7 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
 	{
 		LLViewerJointAttachment* attachment = iter->second;
 
-		if(!attachment->getValid())
+		if (!attachment->getValid())
 		{
 			continue ;
 		}
@@ -1688,7 +1584,6 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
 	return FALSE;
 }
 
-
 //-----------------------------------------------------------------------------
 // parseSkeletonFile()
 //-----------------------------------------------------------------------------
@@ -1732,7 +1627,7 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)
 //-----------------------------------------------------------------------------
 // setupBone()
 //-----------------------------------------------------------------------------
-BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent)
+BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num)
 {
 	LLMemType mt(LLMemType::MTYPE_AVATAR);
 	
@@ -1740,7 +1635,7 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent)
 
 	if (info->mIsJoint)
 	{
-		joint = (LLViewerJoint*)getCharacterJoint(sCurJoint);
+		joint = (LLViewerJoint*)getCharacterJoint(joint_num);
 		if (!joint)
 		{
 			llwarns << "Too many bones" << llendl;
@@ -1750,12 +1645,12 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent)
 	}
 	else // collision volume
 	{
-		if (sCurVolume >= (S32)mNumCollisionVolumes)
+		if (volume_num >= (S32)mNumCollisionVolumes)
 		{
 			llwarns << "Too many bones" << llendl;
 			return FALSE;
 		}
-		joint = (LLViewerJoint*)(&mCollisionVolumes[sCurVolume]);
+		joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]);
 
 		joint->setName( info->mName );
 	}
@@ -1777,19 +1672,19 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent)
 	if (info->mIsJoint)
 	{
 		joint->setSkinOffset( info->mPivot );
-		sCurJoint++;
+		joint_num++;
 	}
 	else // collision volume
 	{
-		sCurVolume++;
+		volume_num++;
 	}
 
 	// setup children
-	LLVOAvatarBoneInfo::child_list_t::iterator iter;
+	LLVOAvatarBoneInfo::child_list_t::const_iterator iter;
 	for (iter = info->mChildList.begin(); iter != info->mChildList.end(); iter++)
 	{
 		LLVOAvatarBoneInfo *child_info = *iter;
-		if (!setupBone(child_info, joint))
+		if (!setupBone(child_info, joint, volume_num, joint_num))
 		{
 			return FALSE;
 		}
@@ -1801,7 +1696,7 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent)
 //-----------------------------------------------------------------------------
 // buildSkeleton()
 //-----------------------------------------------------------------------------
-BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info)
+BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)
 {
 	LLMemType mt(LLMemType::MTYPE_AVATAR);
 	
@@ -1826,14 +1721,13 @@ BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info)
 		}
 	}
 
-	sCurJoint = 0;
-	sCurVolume = 0;
-
-	LLVOAvatarSkeletonInfo::bone_info_list_t::iterator iter;
+	S32 current_joint_num = 0;
+	S32 current_volume_num = 0;
+	LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter;
 	for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); iter++)
 	{
 		LLVOAvatarBoneInfo *info = *iter;
-		if (!setupBone(info, NULL))
+		if (!setupBone(info, NULL, current_volume_num, current_joint_num))
 		{
 			llerrs << "Error parsing bone in skeleton file" << llendl;
 			return FALSE;
@@ -1899,43 +1793,17 @@ void LLVOAvatar::buildCharacter()
 	//-------------------------------------------------------------------------
 	// clear mesh data
 	//-------------------------------------------------------------------------
-	mHairMesh0.setMesh(NULL);
-	mHairMesh1.setMesh(NULL);
-	mHairMesh2.setMesh(NULL);
-	mHairMesh3.setMesh(NULL);
-	mHairMesh4.setMesh(NULL);
-	mHairMesh5.setMesh(NULL);
-
-	mHeadMesh0.setMesh(NULL);
-	mHeadMesh1.setMesh(NULL);
-	mHeadMesh2.setMesh(NULL);
-	mHeadMesh3.setMesh(NULL);
-	mHeadMesh4.setMesh(NULL);
-
-	mEyeLashMesh0.setMesh(NULL);
-
-	mUpperBodyMesh0.setMesh(NULL);
-	mUpperBodyMesh1.setMesh(NULL);
-	mUpperBodyMesh2.setMesh(NULL);
-	mUpperBodyMesh3.setMesh(NULL);
-	mUpperBodyMesh4.setMesh(NULL);
-
-	mLowerBodyMesh0.setMesh(NULL);
-	mLowerBodyMesh1.setMesh(NULL);
-	mLowerBodyMesh2.setMesh(NULL);
-	mLowerBodyMesh3.setMesh(NULL);
-	mLowerBodyMesh4.setMesh(NULL);
-
-	mEyeBallLeftMesh0.setMesh(NULL);
-	mEyeBallLeftMesh1.setMesh(NULL);
-	mEyeBallRightMesh0.setMesh(NULL);
-	mEyeBallRightMesh1.setMesh(NULL);
-
-	mSkirtMesh0.setMesh(NULL);
-	mSkirtMesh1.setMesh(NULL);
-	mSkirtMesh2.setMesh(NULL);
-	mSkirtMesh3.setMesh(NULL);
-	mSkirtMesh4.setMesh(NULL);	
+	for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
+		jointIter != mMeshLOD.end(); jointIter++)
+	{
+		LLViewerJoint* joint = (LLViewerJoint*) *jointIter;
+		for (std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin();
+			meshIter != joint->mMeshParts.end(); meshIter++)
+		{
+			LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter;
+			mesh->setMesh(NULL);
+		}
+	}
 
 	//-------------------------------------------------------------------------
 	// (re)load our skeleton and meshes
@@ -2046,7 +1914,12 @@ void LLVOAvatar::buildCharacter()
 	}
 
 	startDefaultMotions();
-	
+
+	//-------------------------------------------------------------------------
+	// restart any currently active motions
+	//-------------------------------------------------------------------------
+	processAnimationStateChanges();
+
 	mIsBuilt = TRUE;
 	stop_glerror();
 
@@ -2260,21 +2133,18 @@ void LLVOAvatar::releaseMeshData()
 	//llinfos << "Releasing" << llendl;
 
 	// cleanup mesh data
-	mHairLOD.setValid(FALSE, TRUE);
-	mHeadLOD.setValid(FALSE, TRUE);
-	mEyeLashLOD.setValid(FALSE, TRUE);
-	mUpperBodyLOD.setValid(FALSE, TRUE);
-	mLowerBodyLOD.setValid(FALSE, TRUE);
-	mEyeBallLeftLOD.setValid(FALSE, TRUE);
-	mEyeBallRightLOD.setValid(FALSE, TRUE);
-	mSkirtLOD.setValid(FALSE, TRUE);
+	for (std::vector<LLViewerJoint*>::iterator iter = mMeshLOD.begin();
+		iter != mMeshLOD.end(); iter++)
+	{
+		LLViewerJoint* joint = (LLViewerJoint*) *iter;
+		joint->setValid(FALSE, TRUE);
+	}
 
 	//cleanup data
 	if (mDrawable.notNull())
 	{
 		LLFace* facep = mDrawable->getFace(0);
 		facep->setSize(0, 0);
-
 		for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++)
 		{
 			facep = mDrawable->getFace(i);
@@ -2337,34 +2207,25 @@ void LLVOAvatar::updateMeshData()
 	{
 		stop_glerror();
 
-		LLViewerJoint* av_parts[8] ;
-		av_parts[0] = &mEyeBallLeftLOD ;
-		av_parts[1] = &mEyeBallRightLOD ;
-		av_parts[2] = &mEyeLashLOD ;
-		av_parts[3] = &mHeadLOD ;
-		av_parts[4] = &mLowerBodyLOD ;
-		av_parts[5] = &mSkirtLOD ;
-		av_parts[6] = &mUpperBodyLOD ;
-		av_parts[7] = &mHairLOD ;
-		
 		S32 f_num = 0 ;
 		const U32 VERTEX_NUMBER_THRESHOLD = 128 ;//small number of this means each part of an avatar has its own vertex buffer.
+		const S32 num_parts = mMeshLOD.size();
 
 		// this order is determined by number of LODS
 		// if a mesh earlier in this list changed LODs while a later mesh doesn't,
 		// the later mesh's index offset will be inaccurate
-		for(S32 part_index = 0 ; part_index < 8 ;)
+		for(S32 part_index = 0 ; part_index < num_parts ;)
 		{
 			S32 j = part_index ;
 			U32 last_v_num = 0, num_vertices = 0 ;
 			U32 last_i_num = 0, num_indices = 0 ;
 
-			while(part_index < 8 && num_vertices < VERTEX_NUMBER_THRESHOLD)
+			while(part_index < num_parts && num_vertices < VERTEX_NUMBER_THRESHOLD)
 			{
 				last_v_num = num_vertices ;
 				last_i_num = num_indices ;
 
-				av_parts[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
+				mMeshLOD[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea);
 			}
 			if(num_vertices < 1)//skip empty meshes
 			{
@@ -2412,7 +2273,7 @@ void LLVOAvatar::updateMeshData()
 
 			for(S32 k = j ; k < part_index ; k++)
 			{
-				av_parts[k]->updateFaceData(facep, mAdjustedPixelArea, (k == 7));
+				mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR);
 			}
 
 			stop_glerror();
@@ -2536,27 +2397,6 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys,
 
 	//llinfos << getRotation() << llendl;
 	//llinfos << getPosition() << llendl;
-	if (update_type == OUT_FULL )
-	{
-		if( !mIsSelf || !mFirstTEMessageReceived )
-		{
-//			dumpAvatarTEs( "PRE   processUpdateMessage()" );
-			unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
-//			dumpAvatarTEs( "POST  processUpdateMessage()" );
-
-			if( !mFirstTEMessageReceived )
-			{
-				onFirstTEMessageReceived();
-			}
-
-			// Disable updates to composites.  We'll decide whether we need to do
-			// any updates after we find out whether this update message has any
-			// "baked" (pre-composited) textures.
-			setCompositeUpdatesEnabled( FALSE );
-			updateMeshTextures(); 
-			setCompositeUpdatesEnabled( TRUE );
-		}
-	}
 
 	return retval;
 }
@@ -2566,7 +2406,7 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid)
 {
 	// The core setTETexture() method requests images, so we need
 	// to redirect certain avatar texture requests to different sims.
-	if (isTextureIndexBaked(te))
+	if (isIndexBakedTexture((ETextureIndex)te))
 	{
 		LLHost target_host = getObjectHost();
 		return setTETextureCore(te, uuid, target_host);
@@ -2865,15 +2705,12 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
 		}
 	}
 
-	if (mDrawable.notNull())
+	mDrawable->movePartition();
+	
+	//force a move if sitting on an active object
+	if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
 	{
-		mDrawable->movePartition();
-		
-		//force a move if sitting on an active object
-		if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
-		{
-			gPipeline.markMoved(mDrawable, TRUE);
-		}
+		gPipeline.markMoved(mDrawable, TRUE);
 	}
 }
 
@@ -3765,7 +3602,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 			F32 root_roll, root_pitch, root_yaw;
 			root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw);
 
-			if (gDebugAvatarRotation)
+			if (sDebugAvatarRotation)
 			{
 				llinfos << "root_roll " << RAD_TO_DEG * root_roll 
 					<< " root_pitch " << RAD_TO_DEG * root_pitch
@@ -3955,7 +3792,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 //							AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN );
 
 			const F32 STEP_VOLUME = 0.5f;
-			LLUUID& step_sound_id = getStepSound();
+			const LLUUID& step_sound_id = getStepSound();
 
 			LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent);
 
@@ -4189,19 +4026,19 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
 		if (mNeedsSkin)
 		{
 			//generate animated mesh
-			mLowerBodyLOD.updateJointGeometry();
-			mUpperBodyLOD.updateJointGeometry();
+			mMeshLOD[MESH_ID_LOWER_BODY]->updateJointGeometry();
+			mMeshLOD[MESH_ID_UPPER_BODY]->updateJointGeometry();
 
 			if( isWearingWearableType( WT_SKIRT ) )
 			{
-				mSkirtLOD.updateJointGeometry();
+				mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry();
 			}
 
 			if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
 			{
-				mEyeLashLOD.updateJointGeometry();
-				mHeadLOD.updateJointGeometry();
-				mHairLOD.updateJointGeometry();				
+				mMeshLOD[MESH_ID_EYELASH]->updateJointGeometry();
+				mMeshLOD[MESH_ID_HEAD]->updateJointGeometry();
+				mMeshLOD[MESH_ID_HAIR]->updateJointGeometry();
 			}
 			mNeedsSkin = FALSE;
 			
@@ -4289,7 +4126,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
 		gGL.flush();
 	}
 	//--------------------------------------------------------------------
-	// render all geomety attached to the skeleton
+	// render all geometry attached to the skeleton
 	//--------------------------------------------------------------------
 	static LLStat render_stat;
 
@@ -4297,18 +4134,42 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
 
 	if (pass == AVATAR_RENDER_PASS_SINGLE)
 	{
+		bool should_alpha_mask = mHasBakedHair && isTextureDefined(TEX_HEAD_BAKED) && isTextureDefined(TEX_UPPER_BAKED) 
+								&& isTextureDefined(TEX_LOWER_BAKED) && mBakedTextureData[BAKED_HEAD].mIsLoaded
+								&& mBakedTextureData[BAKED_UPPER].mIsLoaded && mBakedTextureData[BAKED_LOWER].mIsLoaded;
+		LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
+
+		if (should_alpha_mask)
+		{
+			gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+		}
+		
 		BOOL first_pass = TRUE;
 		if (!LLDrawPoolAvatar::sSkipOpaque)
 		{
 			if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
 			{
-				num_indices += mHeadLOD.render(mAdjustedPixelArea);
+				if (isTextureVisible(TEX_HEAD_BAKED))
+				{
+					num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea);
+					first_pass = FALSE;
+				}
+			}
+			if (isTextureVisible(TEX_UPPER_BAKED))
+			{
+				num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass);
+				first_pass = FALSE;
+			}
+			
+			if (isTextureVisible(TEX_LOWER_BAKED))
+			{
+				num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass);
 				first_pass = FALSE;
 			}
-			num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass);
-			num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE);
 		}
 
+		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+
 		if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender)
 		{
 			LLGLEnable blend(GL_BLEND);
@@ -4329,10 +4190,10 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
 U32 LLVOAvatar::renderTransparent(BOOL first_pass)
 {
 	U32 num_indices = 0;
-	if( isWearingWearableType( WT_SKIRT ) )
+	if( isWearingWearableType( WT_SKIRT ) && isTextureVisible(TEX_SKIRT_BAKED) )
 	{
 		gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f);
-		num_indices += mSkirtLOD.render(mAdjustedPixelArea, FALSE);
+		num_indices += mMeshLOD[MESH_ID_SKIRT]->render(mAdjustedPixelArea, FALSE);
 		first_pass = FALSE;
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 	}
@@ -4343,8 +4204,17 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
 		{
 			gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
 		}
-		num_indices += mEyeLashLOD.render(mAdjustedPixelArea, first_pass);
-		num_indices += mHairLOD.render(mAdjustedPixelArea, FALSE);
+		
+		if (isTextureVisible(TEX_HEAD_BAKED))
+		{
+			num_indices += mMeshLOD[MESH_ID_EYELASH]->render(mAdjustedPixelArea, first_pass);
+			first_pass = FALSE;
+		}
+		if (isTextureVisible(TEX_HAIR_BAKED))
+		{
+			num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass);
+			first_pass = FALSE;
+		}
 		if (LLPipeline::sImpostorRender)
 		{
 			gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
@@ -4376,8 +4246,22 @@ U32 LLVOAvatar::renderRigid()
 		return 0;
 	}
 
-	num_indices += mEyeBallLeftLOD.render(mAdjustedPixelArea);
-	num_indices += mEyeBallRightLOD.render(mAdjustedPixelArea);
+	if (isTextureVisible(TEX_EYES_BAKED))
+	{
+		// If the meshes need to be drawn, enable alpha masking but not blending
+		bool should_alpha_mask = mHasBakedHair && mBakedTextureData[BAKED_EYES].mIsLoaded;
+		LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
+		
+		if (should_alpha_mask)
+		{
+			gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
+		}
+
+		num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea);
+		num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea);
+
+		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+	}
 	
 	return num_indices;
 }
@@ -4400,6 +4284,13 @@ U32 LLVOAvatar::renderFootShadows()
 	{
 		return 0;
 	}
+	
+	// Don't render foot shadows if your lower body is completely invisible.
+	// (non-humanoid avatars rule!)
+	if (! isTextureVisible(TEX_LOWER_BAKED))
+	{
+		return 0;
+	}
 
 	// Update the shadow, tractor, and text label geometry.
 	if (mDrawable->isState(LLDrawable::REBUILD_SHADOW) && !isImpostor())
@@ -4470,12 +4361,6 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
 	{
 		return;
 	}
-	
-	BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR );
 
 	if( mIsSelf )
 	{
@@ -4486,30 +4371,18 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
 		render_avatar = isVisible() && !mCulled;
 	}
 
-	// bind the texture so that they'll be decoded
-	// slightly inefficient, we can short-circuit this
-	// if we have to
-	if( render_avatar && !gGLManager.mIsDisabled )
+	std::vector<bool> layer_baked;
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		if( head_baked && ! mHeadBakedLoaded )
-		{
-			gGL.getTexUnit(0)->bind(getTEImage( TEX_HEAD_BAKED ));
-		}
-		if( upper_baked && ! mUpperBakedLoaded )
-		{
-			gGL.getTexUnit(0)->bind(getTEImage( TEX_UPPER_BAKED ));
-		}
-		if( lower_baked && ! mLowerBakedLoaded )
-		{
-			gGL.getTexUnit(0)->bind(getTEImage( TEX_LOWER_BAKED ));
-		}
-		if( eyes_baked && ! mEyesBakedLoaded )
-		{
-			gGL.getTexUnit(0)->bind(getTEImage( TEX_EYES_BAKED ));
-		}
-		if( skirt_baked && ! mSkirtBakedLoaded )
+		layer_baked.push_back(isTextureDefined(mBakedTextureData[i].mTextureIndex));
+		// bind the texture so that they'll be decoded slightly 
+		// inefficient, we can short-circuit this if we have to
+		if( render_avatar && !gGLManager.mIsDisabled )
 		{
-			gGL.getTexUnit(0)->bind(getTEImage( TEX_SKIRT_BAKED ));
+			if (layer_baked[i] && !mBakedTextureData[i].mIsLoaded)
+			{
+				gGL.getTexUnit(0)->bind(getTEImage( mBakedTextureData[i].mTextureIndex ));
+			}
 		}
 	}
 
@@ -4541,9 +4414,9 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
 	mMaxPixelArea = 0.f;
 	mMinPixelArea = 99999999.f;
 	mHasGrey = FALSE; // debug
-	for (U32 i = 0; i < getNumTEs(); i++)
+	for (U32 index = 0; index < getNumTEs(); index++)
 	{
-		LLViewerImage *imagep = getTEImage(i);
+		LLViewerImage *imagep = getTEImage(index);
 		if (imagep)
 		{
 			// Debugging code - maybe non-self avatars are downloading textures?
@@ -4555,131 +4428,39 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
 			//	<< " desired " << imagep->getDesiredDiscardLevel()
 			//	<< llendl;
 			
-			const LLTextureEntry *te = getTE(i);
+			const LLTextureEntry *te = getTE(index);
 			F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
 			S32 boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_BAKED_SELF : LLViewerImage::BOOST_AVATAR_BAKED;
 			
 			// Spam if this is a baked texture, not set to default image, without valid host info
-			if (isTextureIndexBaked(i)
+			if (isIndexBakedTexture((ETextureIndex)index)
 				&& imagep->getID() != IMG_DEFAULT_AVATAR
 				&& !imagep->getTargetHost().isOk())
 			{
-				llwarns << "LLVOAvatar::updateTextures No host for texture "
+				LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture "
 					<< imagep->getID() << " for avatar "
 					<< (mIsSelf ? "<myself>" : getID().asString()) 
 					<< " on host " << getRegion()->getHost() << llendl;
 			}
-			
-			switch( i )
-			{
-			// Head
-			case TEX_HEAD_BODYPAINT:
-				addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked );
-				break;
-
-			// Upper
-			case TEX_UPPER_JACKET:
-				addLocalTextureStats( LOCTEX_UPPER_JACKET, imagep, texel_area_ratio, render_avatar, upper_baked );
-				break;
-
-			case TEX_UPPER_SHIRT:
-				addLocalTextureStats( LOCTEX_UPPER_SHIRT, imagep, texel_area_ratio, render_avatar, upper_baked );
-				break;
-
-			case TEX_UPPER_GLOVES:
-				addLocalTextureStats( LOCTEX_UPPER_GLOVES, imagep, texel_area_ratio, render_avatar, upper_baked );
-				break;
-			
-			case TEX_UPPER_UNDERSHIRT:
-				addLocalTextureStats( LOCTEX_UPPER_UNDERSHIRT, imagep, texel_area_ratio, render_avatar, upper_baked );
-				break;
-
-			case TEX_UPPER_BODYPAINT:
-				addLocalTextureStats( LOCTEX_UPPER_BODYPAINT, imagep, texel_area_ratio, render_avatar, upper_baked );
-				break;
-
-			// Lower
-			case TEX_LOWER_JACKET:
-				addLocalTextureStats( LOCTEX_LOWER_JACKET, imagep, texel_area_ratio, render_avatar, lower_baked );
-				break;
-
-			case TEX_LOWER_PANTS:
-				addLocalTextureStats( LOCTEX_LOWER_PANTS, imagep, texel_area_ratio, render_avatar, lower_baked );
-				break;
-
-			case TEX_LOWER_SHOES:
-				addLocalTextureStats( LOCTEX_LOWER_SHOES, imagep, texel_area_ratio, render_avatar, lower_baked );
-				break;
-
-			case TEX_LOWER_SOCKS:
-				addLocalTextureStats( LOCTEX_LOWER_SOCKS, imagep, texel_area_ratio, render_avatar, lower_baked );
-				break;
-
-			case TEX_LOWER_UNDERPANTS:
-				addLocalTextureStats( LOCTEX_LOWER_UNDERPANTS, imagep, texel_area_ratio, render_avatar, lower_baked );
-				break;
-
-			case TEX_LOWER_BODYPAINT:
-				addLocalTextureStats( LOCTEX_LOWER_BODYPAINT, imagep, texel_area_ratio, render_avatar, lower_baked );
-				break;
-
-			// Eyes
-			case TEX_EYES_IRIS:
-				addLocalTextureStats( LOCTEX_EYES_IRIS, imagep, texel_area_ratio, render_avatar, eyes_baked );
-				break;
 
-			// Skirt
-			case TEX_SKIRT:
-				addLocalTextureStats( LOCTEX_SKIRT, imagep, texel_area_ratio, render_avatar, skirt_baked );
-				break;
-
-			// Baked
-			case TEX_HEAD_BAKED:
-				if (head_baked)
-				{
-					addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
-				}
-				break;
-
-			case TEX_UPPER_BAKED:
-				if (upper_baked)
-				{
-					addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
-				}
-				break;
-			
-			case TEX_LOWER_BAKED:
-				if (lower_baked)
-				{
-					addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
-				}
-				break;
-			
-			case TEX_EYES_BAKED:
-				if (eyes_baked)
+			/* switch(index)
+				case TEX_HEAD_BODYPAINT:
+					addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked ); */
+			const LLVOAvatarDictionary::TextureDictionaryEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)index);
+			if (texture_dict->mIsUsedByBakedTexture)
+			{
+				const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+				if (texture_dict->mIsLocalTexture)
 				{
-					addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
+					addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
 				}
-				break;
-
-			case TEX_SKIRT_BAKED:
-				if (skirt_baked)
+				else if (texture_dict->mIsBakedTexture)
 				{
-					addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
+					if (layer_baked[baked_index])
+					{
+						addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
+					}
 				}
-				break;
-
-			case TEX_HAIR:
-				// Hair is neither a local texture used for baking, nor the output
-				// of the baking process.  It's just a texture that happens to be
-				// used to draw avatars.  Hence BOOST_AVATAR.  JC
-			  	boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_SELF : LLViewerImage::BOOST_AVATAR;
-			  	addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
-				break;
-			
-			default:
-				llassert(0);
-				break;
 			}
 		}
 	}
@@ -4696,22 +4477,24 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
 }
 
 
-void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerImage* imagep,
+void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerImage* imagep,
 									   F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked )
 {
+	if (!isIndexLocalTexture(idx)) return;
+
 	if (!covered_by_baked && render_avatar) // render_avatar is always true if mIsSelf
 	{
-		if (mLocalTexture[ idx ].notNull() && mLocalTexture[idx]->getID() != IMG_DEFAULT_AVATAR)
+		if (getLocalTextureID(idx) != IMG_DEFAULT_AVATAR)
 		{
 			F32 desired_pixels;
 			if( mIsSelf )
 			{
-				desired_pixels = llmin(mPixelArea, (F32)LOCTEX_IMAGE_AREA_SELF );
+				desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_SELF );
 				imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR_SELF);
 			}
 			else
 			{
-				desired_pixels = llmin(mPixelArea, (F32)LOCTEX_IMAGE_AREA_OTHER );
+				desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_OTHER );
 				imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR);
 			}
 			imagep->addTextureStats( desired_pixels / texel_area_ratio );
@@ -4722,11 +4505,8 @@ void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerIma
 		}
 		else
 		{
-			if (mLocalTexture[idx]->getID() == IMG_DEFAULT_AVATAR)
-			{
-				// texture asset is missing
-				mHasGrey = TRUE; // for statistics gathering
-			}
+			// texture asset is missing
+			mHasGrey = TRUE; // for statistics gathering
 		}
 	}
 }
@@ -4794,7 +4574,7 @@ void LLVOAvatar::resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos
 //-----------------------------------------------------------------------------
 // getStepSound()
 //-----------------------------------------------------------------------------
-LLUUID& LLVOAvatar::getStepSound()
+const LLUUID& LLVOAvatar::getStepSound() const
 {
 	if ( mStepOnLand )
 	{
@@ -5232,7 +5012,7 @@ F32 LLVOAvatar::getPixelArea() const
 //-----------------------------------------------------------------------------
 LLPolyMesh*	LLVOAvatar::getHeadMesh()
 {
-	return mHeadMesh0.getMesh();
+	return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh();
 }
 
 
@@ -5241,7 +5021,7 @@ LLPolyMesh*	LLVOAvatar::getHeadMesh()
 //-----------------------------------------------------------------------------
 LLPolyMesh*	LLVOAvatar::getUpperBodyMesh()
 {
-	return mUpperBodyMesh0.getMesh();
+	return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh();
 }
 
 
@@ -5340,7 +5120,7 @@ BOOL LLVOAvatar::loadAvatar()
 // 	LLFastTimer t(LLFastTimer::FTM_LOAD_AVATAR);
 	
 	// avatar_skeleton.xml
-	if( !buildSkeleton(sSkeletonInfo) )
+	if( !buildSkeleton(sAvatarSkeletonInfo) )
 	{
 		llwarns << "avatar file: buildSkeleton() failed" << llendl;
 		return FALSE;
@@ -5361,10 +5141,10 @@ BOOL LLVOAvatar::loadAvatar()
 	}
 	
 	// avatar_lad.xml : <global_color>
-	if( sAvatarInfo->mTexSkinColorInfo )
+	if( sAvatarXmlInfo->mTexSkinColorInfo )
 	{
 		mTexSkinColor = new LLTexGlobalColor( this );
-		if( !mTexSkinColor->setInfo( sAvatarInfo->mTexSkinColorInfo ) )
+		if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) )
 		{
 			llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl;
 			return FALSE;
@@ -5375,10 +5155,10 @@ BOOL LLVOAvatar::loadAvatar()
 		llwarns << "<global_color> name=\"skin_color\" not found" << llendl;
 		return FALSE;
 	}
-	if( sAvatarInfo->mTexHairColorInfo )
+	if( sAvatarXmlInfo->mTexHairColorInfo )
 	{
 		mTexHairColor = new LLTexGlobalColor( this );
-		if( !mTexHairColor->setInfo( sAvatarInfo->mTexHairColorInfo ) )
+		if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) )
 		{
 			llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl;
 			return FALSE;
@@ -5389,10 +5169,10 @@ BOOL LLVOAvatar::loadAvatar()
 		llwarns << "<global_color> name=\"hair_color\" not found" << llendl;
 		return FALSE;
 	}
-	if( sAvatarInfo->mTexEyeColorInfo )
+	if( sAvatarXmlInfo->mTexEyeColorInfo )
 	{
 		mTexEyeColor = new LLTexGlobalColor( this );
-		if( !mTexEyeColor->setInfo( sAvatarInfo->mTexEyeColorInfo ) )
+		if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) )
 		{
 			llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl;
 			return FALSE;
@@ -5405,15 +5185,15 @@ BOOL LLVOAvatar::loadAvatar()
 	}
 	
 	// avatar_lad.xml : <layer_set>
-	if (sAvatarInfo->mLayerInfoList.empty())
+	if (sAvatarXmlInfo->mLayerInfoList.empty())
 	{
 		llwarns << "avatar file: missing <layer_set> node" << llendl;
 	}
 	else
 	{
-		LLVOAvatarInfo::layer_info_list_t::iterator iter;
-		for (iter = sAvatarInfo->mLayerInfoList.begin();
-			 iter != sAvatarInfo->mLayerInfoList.end(); iter++)
+		LLVOAvatarXmlInfo::layer_info_list_t::iterator iter;
+		for (iter = sAvatarXmlInfo->mLayerInfoList.begin();
+			 iter != sAvatarXmlInfo->mLayerInfoList.end(); iter++)
 		{
 			LLTexLayerSetInfo *info = *iter;
 			LLTexLayerSet* layer_set = new LLTexLayerSet( this );
@@ -5424,27 +5204,20 @@ BOOL LLVOAvatar::loadAvatar()
 				llwarns << "avatar file: layer_set->parseData() failed" << llendl;
 				return FALSE;
 			}
-			if( layer_set->isBodyRegion( "head" ) )
-			{
-				mHeadLayerSet = layer_set;
-			}
-			else if( layer_set->isBodyRegion( "upper_body" ) )
-			{
-				mUpperBodyLayerSet = layer_set;
-			}
-			else if( layer_set->isBodyRegion( "lower_body" ) )
-			{
-				mLowerBodyLayerSet = layer_set;
-			}
-			else if( layer_set->isBodyRegion( "eyes" ) )
-			{
-				mEyesLayerSet = layer_set;
-			}
-			else if( layer_set->isBodyRegion( "skirt" ) )
+			bool found_baked_entry = false;
+			for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+				 baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
+				 baked_iter++)
 			{
-				mSkirtLayerSet = layer_set;
+				const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second;
+				if (layer_set->isBodyRegion(baked_dict->mName))
+				{
+					mBakedTextureData[baked_iter->first].mTexLayerSet = layer_set;
+					found_baked_entry = true;
+					break;
+				}
 			}
-			else
+			if (!found_baked_entry)
 			{
 				llwarns << "<layer_set> has invalid body_region attribute" << llendl;
 				delete layer_set;
@@ -5455,9 +5228,9 @@ BOOL LLVOAvatar::loadAvatar()
 	
 	// avatar_lad.xml : <driver_parameters>
 	{
-		LLVOAvatarInfo::driver_info_list_t::iterator iter;
-		for (iter = sAvatarInfo->mDriverInfoList.begin();
-			 iter != sAvatarInfo->mDriverInfoList.end(); iter++)
+		LLVOAvatarXmlInfo::driver_info_list_t::iterator iter;
+		for (iter = sAvatarXmlInfo->mDriverInfoList.begin();
+			 iter != sAvatarXmlInfo->mDriverInfoList.end(); iter++)
 		{
 			LLDriverParamInfo *info = *iter;
 			LLDriverParam* driver_param = new LLDriverParam( this );
@@ -5484,78 +5257,44 @@ BOOL LLVOAvatar::loadSkeletonNode ()
 {
 	mRoot.addChild( &mSkeleton[0] );
 
-	mRoot.addChild( &mHeadLOD );
-		mHeadLOD.mUpdateXform = FALSE;
-		mHeadLOD.addChild( &mHeadMesh0 );
-		mHeadLOD.addChild( &mHeadMesh1 );
-		mHeadLOD.addChild( &mHeadMesh2 );
-		mHeadLOD.addChild( &mHeadMesh3 );
-		mHeadLOD.addChild( &mHeadMesh4 );
-	
-	mRoot.addChild( &mEyeLashLOD );
-		mEyeLashLOD.mUpdateXform = FALSE;
-		mEyeLashLOD.addChild( &mEyeLashMesh0 );
-
-	mRoot.addChild( &mUpperBodyLOD );
-		mUpperBodyLOD.mUpdateXform = FALSE;
-		mUpperBodyLOD.addChild( &mUpperBodyMesh0 );
-		mUpperBodyLOD.addChild( &mUpperBodyMesh1 );
-		mUpperBodyLOD.addChild( &mUpperBodyMesh2 );
-		mUpperBodyLOD.addChild( &mUpperBodyMesh3 );
-		mUpperBodyLOD.addChild( &mUpperBodyMesh4 );
-
-	mRoot.addChild( &mLowerBodyLOD );
-		mLowerBodyLOD.mUpdateXform = FALSE;
-		mLowerBodyLOD.addChild( &mLowerBodyMesh0 );
-		mLowerBodyLOD.addChild( &mLowerBodyMesh1 );
-		mLowerBodyLOD.addChild( &mLowerBodyMesh2 );
-		mLowerBodyLOD.addChild( &mLowerBodyMesh3 );
-		mLowerBodyLOD.addChild( &mLowerBodyMesh4 );
-
-	mRoot.addChild( &mSkirtLOD );
-		mSkirtLOD.mUpdateXform = FALSE;
-		mSkirtLOD.addChild( &mSkirtMesh0 );
-		mSkirtLOD.addChild( &mSkirtMesh1 );
-		mSkirtLOD.addChild( &mSkirtMesh2 );
-		mSkirtLOD.addChild( &mSkirtMesh3 );
-		mSkirtLOD.addChild( &mSkirtMesh4 );
+	for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin();
+		iter != mMeshLOD.end(); iter++)
+	{
+		LLViewerJoint *joint = (LLViewerJoint *) *iter;
+		joint->mUpdateXform = FALSE;
+		joint->setMeshesToChildren();
+	}
+
+	mRoot.addChild(mMeshLOD[MESH_ID_HEAD]);
+	mRoot.addChild(mMeshLOD[MESH_ID_EYELASH]);
+	mRoot.addChild(mMeshLOD[MESH_ID_UPPER_BODY]);
+	mRoot.addChild(mMeshLOD[MESH_ID_LOWER_BODY]);
+	mRoot.addChild(mMeshLOD[MESH_ID_SKIRT]);
+	mRoot.addChild(mMeshLOD[MESH_ID_HEAD]);
 
 	LLViewerJoint *skull = (LLViewerJoint*)mRoot.findJoint("mSkull");
 	if (skull)
 	{
-		skull->addChild( &mHairLOD );
-			mHairLOD.mUpdateXform = FALSE;
-			mHairLOD.addChild( &mHairMesh0 );
-			mHairLOD.addChild( &mHairMesh1 );
-			mHairLOD.addChild( &mHairMesh2 );
-			mHairLOD.addChild( &mHairMesh3 );
-			mHairLOD.addChild( &mHairMesh4 );
-			mHairLOD.addChild( &mHairMesh5 );
+		skull->addChild(mMeshLOD[MESH_ID_HAIR] );
 	}
 
 	LLViewerJoint *eyeL = (LLViewerJoint*)mRoot.findJoint("mEyeLeft");
 	if (eyeL)
 	{
-		eyeL->addChild( &mEyeBallLeftLOD );
-			mEyeBallLeftLOD.mUpdateXform = FALSE;
-			mEyeBallLeftLOD.addChild( &mEyeBallLeftMesh0 );
-			mEyeBallLeftLOD.addChild( &mEyeBallLeftMesh1 );
+		eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] );
 	}
 
 	LLViewerJoint *eyeR = (LLViewerJoint*)mRoot.findJoint("mEyeRight");
 	if (eyeR)
 	{
-		eyeR->addChild( &mEyeBallRightLOD );
-			mEyeBallRightLOD.mUpdateXform = FALSE;
-			mEyeBallRightLOD.addChild( &mEyeBallRightMesh0 );
-			mEyeBallRightLOD.addChild( &mEyeBallRightMesh1 );
+		eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] );
 	}
 
 	// SKELETAL DISTORTIONS
 	{
-		LLVOAvatarInfo::skeletal_distortion_info_list_t::iterator iter;
-		for (iter = sAvatarInfo->mSkeletalDistortionInfoList.begin();
-			 iter != sAvatarInfo->mSkeletalDistortionInfoList.end(); iter++)
+		LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter;
+		for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin();
+			 iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); iter++)
 		{
 			LLPolySkeletalDistortionInfo *info = *iter;
 			LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this);
@@ -5573,11 +5312,11 @@ BOOL LLVOAvatar::loadSkeletonNode ()
 	
 	// ATTACHMENTS
 	{
-		LLVOAvatarInfo::attachment_info_list_t::iterator iter;
-		for (iter = sAvatarInfo->mAttachmentInfoList.begin();
-			 iter != sAvatarInfo->mAttachmentInfoList.end(); iter++)
+		LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter;
+		for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin();
+			 iter != sAvatarXmlInfo->mAttachmentInfoList.end(); iter++)
 		{
-			LLVOAvatarInfo::LLVOAvatarAttachmentInfo *info = *iter;
+			LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter;
 			if (!isSelf() && info->mJointName == "mScreen")
 			{ //don't process screen joint for other avatars
 				continue;
@@ -5654,177 +5393,52 @@ BOOL LLVOAvatar::loadSkeletonNode ()
 //-----------------------------------------------------------------------------
 BOOL LLVOAvatar::loadMeshNodes()
 {
-	LLVOAvatarInfo::mesh_info_list_t::iterator iter;
-	for (iter = sAvatarInfo->mMeshInfoList.begin();
-		 iter != sAvatarInfo->mMeshInfoList.end(); iter++)
+	for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin();
+		 meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end(); 
+		 meshinfo_iter++)
 	{
-		LLVOAvatarInfo::LLVOAvatarMeshInfo *info = *iter;
-		std::string &type = info->mType;
+		const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter;
+		const std::string &type = info->mType;
 		S32 lod = info->mLOD;
 
 		LLViewerJointMesh* mesh = NULL;
-		if (type == "hairMesh")
-		{
-			switch (lod)
-			{
-			  case 0:
-				mesh = &mHairMesh0;
-				break;
-			  case 1:
-				mesh = &mHairMesh1;
-				break;
-			  case 2:
-				mesh = &mHairMesh2;
-				break;
-			  case 3:
-				mesh = &mHairMesh3;
-				break;
-			  case 4:
-				mesh = &mHairMesh4;
-				break;
-			  case 5:
-				mesh = &mHairMesh5;
-				break;
-			  default:
-				llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
-				return FALSE;
-			}
-		}
-		else if (type == "headMesh")
-		{
-			switch (lod)
-			{
+		U8 mesh_id = 0;
+		BOOL found_mesh_id = FALSE;
+
+		/* if (type == "hairMesh")
+			switch(lod)
 			  case 0:
-				mesh = &mHeadMesh0;
-				break;
-			  case 1:
-				mesh = &mHeadMesh1;
-				break;
-			  case 2:
-				mesh = &mHeadMesh2;
-				break;
-			  case 3:
-				mesh = &mHeadMesh3;
-				break;
-			  case 4:
-				mesh = &mHeadMesh4;
-				break;
-			  default:
-				llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
-				return FALSE;
-			}
-		}
-		else if (type == "upperBodyMesh")
+				mesh = &mHairMesh0; */
+		for (LLVOAvatarDictionary::mesh_map_t::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
+			 mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
+			 mesh_iter++)
 		{
-			switch (lod)
+			const EMeshIndex mesh_index = mesh_iter->first;
+			const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = mesh_iter->second;
+			if (type.compare(mesh_dict->mName) == 0)
 			{
-			  case 0:
-				mesh = &mUpperBodyMesh0;
-				break;
-			  case 1:
-				mesh = &mUpperBodyMesh1;
-				break;
-			  case 2:
-				mesh = &mUpperBodyMesh2;
+				mesh_id = mesh_index;
+				found_mesh_id = TRUE;
 				break;
-			  case 3:
-				mesh = &mUpperBodyMesh3;
-				break;
-			  case 4:
-				mesh = &mUpperBodyMesh4;
-				break;
-			  default:
-				llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
-				return FALSE;
 			}
 		}
-		else if (type == "lowerBodyMesh")
+
+		if (found_mesh_id)
 		{
-			switch (lod)
+			if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size())
 			{
-			  case 0:
-				mesh = &mLowerBodyMesh0;
-				break;
-			  case 1:
-				mesh = &mLowerBodyMesh1;
-				break;
-			  case 2:
-				mesh = &mLowerBodyMesh2;
-				break;
-			  case 3:
-				mesh = &mLowerBodyMesh3;
-				break;
-			  case 4:
-				mesh = &mLowerBodyMesh4;
-				break;
-			  default:
-				llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
-				return FALSE;
+				mesh = mMeshLOD[mesh_id]->mMeshParts[lod];
 			}
-		}	
-		else if (type == "skirtMesh")
-		{
-			switch (lod)
+			else
 			{
-			  case 0:
-				mesh = &mSkirtMesh0;
-				break;
-			  case 1:
-				mesh = &mSkirtMesh1;
-				break;
-			  case 2:
-				mesh = &mSkirtMesh2;
-				break;
-			  case 3:
-				mesh = &mSkirtMesh3;
-				break;
-			  case 4:
-				mesh = &mSkirtMesh4;
-				break;
-			  default:
 				llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
 				return FALSE;
 			}
 		}
-		else if (type == "eyelashMesh")
+		else 
 		{
-			mesh = &mEyeLashMesh0;
-		}
-		else if (type == "eyeBallLeftMesh")
-		{
-			switch (lod)
-			{
-			  case 0:
-				mesh = &mEyeBallLeftMesh0;
-				break;
-			  case 1:
-				mesh = &mEyeBallLeftMesh1;
-				break;
-			  default:
-				llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
-				return FALSE;
-			}
-		}
-		else if (type == "eyeBallRightMesh")
-		{
-			switch (lod)
-			{
-			  case 0:
-				mesh = &mEyeBallRightMesh0;
-				break;
-			  case 1:
-				mesh = &mEyeBallRightMesh1;
-				break;
-			  default:
-				llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
-				return FALSE;
-			}
-		}
-
-		if( !mesh )
-		{
-			llwarns << "Ignoring unrecognized mesh type: " << type << llendl;
-			return FALSE;
+			llwarns << "Ignoring unrecognized mesh type: " << type << llendl;
+			return FALSE;
 		}
 
 		//	llinfos << "Parsing mesh data for " << type << "..." << llendl;
@@ -5837,15 +5451,16 @@ BOOL LLVOAvatar::loadMeshNodes()
 
 		if (!info->mReferenceMeshName.empty())
 		{
-			mesh_map_t::iterator iter = mMeshes.find(info->mReferenceMeshName);
-			if (iter != mMeshes.end())
+			polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName);
+			if (polymesh_iter != mMeshes.end())
 			{
-				poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, iter->second);
+				poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second);
 				poly_mesh->setAvatar(this);
 			}
 			else
 			{
 				// This should never happen
+				LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL;
 			}
 		}
 		else
@@ -5864,14 +5479,13 @@ BOOL LLVOAvatar::loadMeshNodes()
 		mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh));
 	
 		mesh->setMesh( poly_mesh );
-
 		mesh->setLOD( info->mMinPixelArea );
 
-		LLVOAvatarInfo::LLVOAvatarMeshInfo::morph_info_list_t::iterator iter;
-		for (iter = info->mPolyMorphTargetInfoList.begin();
-			 iter != info->mPolyMorphTargetInfoList.end(); iter++)
+		for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin();
+			 xmlinfo_iter != info->mPolyMorphTargetInfoList.end(); 
+			 xmlinfo_iter++)
 		{
-			LLVOAvatarInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*iter);
+			const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter);
 			LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh());
 			if (!param->setInfo(info_pair->first))
 			{
@@ -5961,7 +5575,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent)
 	// We always want to look good to ourselves
 	if( mIsSelf )
 	{
-		mPixelArea = llmax( mPixelArea, F32(LOCTEX_IMAGE_SIZE_SELF / 16) );
+		mPixelArea = llmax( mPixelArea, F32(TEX_IMAGE_SIZE_SELF / 16) );
 	}
 }
 
@@ -6078,7 +5692,7 @@ void LLVOAvatar::updateShadowFaces()
 	//
 	// render avatar shadows
 	//
-	if (mInAir || mUpdatePeriod >= VOAVATAR_IMPOSTOR_PERIOD)
+	if (mInAir || mUpdatePeriod >= IMPOSTOR_PERIOD)
 	{
 		face0p->setSize(0, 0);
 		face1p->setSize(0, 0);
@@ -6173,9 +5787,9 @@ void LLVOAvatar::updateShadowFaces()
 //-----------------------------------------------------------------------------
 void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user )
 {
-	invalidateComposite( mHeadLayerSet,			set_by_user );
-	invalidateComposite( mLowerBodyLayerSet,	set_by_user );
-	invalidateComposite( mUpperBodyLayerSet,	set_by_user );
+	invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet,  set_by_user );
+	invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet,	set_by_user );
+	invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet,	set_by_user );
 	updateMeshTextures();
 }
 
@@ -6188,74 +5802,32 @@ void LLVOAvatar::dirtyMesh()
 }
 
 //-----------------------------------------------------------------------------
-// requestLayerSetUpdate()
+// hideSkirt()
 //-----------------------------------------------------------------------------
-void LLVOAvatar::requestLayerSetUpdate( LLVOAvatar::ELocTexIndex i )
+void LLVOAvatar::hideSkirt()
 {
-	switch( i )
-	{
-	case LOCTEX_HEAD_BODYPAINT:
-		if( mHeadLayerSet )
-		{
-			mHeadLayerSet->requestUpdate();
-		}
-		break;
-
-	case LOCTEX_UPPER_BODYPAINT:  
-	case LOCTEX_UPPER_SHIRT:
-	case LOCTEX_UPPER_GLOVES:
-	case LOCTEX_UPPER_UNDERSHIRT:
-		if( mUpperBodyLayerSet )
-		{
-			mUpperBodyLayerSet->requestUpdate();
-		}
-		break;
-
-	case LOCTEX_LOWER_BODYPAINT:  
-	case LOCTEX_LOWER_PANTS:
-	case LOCTEX_LOWER_SHOES:
-	case LOCTEX_LOWER_SOCKS:
-	case LOCTEX_LOWER_UNDERPANTS:
-		if( mLowerBodyLayerSet )
-		{
-			mLowerBodyLayerSet->requestUpdate();
-		}
-		break;
-
-	case LOCTEX_EYES_IRIS:
-		if( mEyesLayerSet )
-		{
-			mEyesLayerSet->requestUpdate();
-		}
-		break;
-
-
-	case LOCTEX_SKIRT:
-		if( mSkirtLayerSet )
-		{
-			mSkirtLayerSet->requestUpdate();
-		}
-		break;
-
-
-	case LOCTEX_UPPER_JACKET:
-	case LOCTEX_LOWER_JACKET:
-		if( mUpperBodyLayerSet )
-		{
-			mUpperBodyLayerSet->requestUpdate();
-		}
+	mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE);
+}
 
-		if( mLowerBodyLayerSet )
-		{
-			mLowerBodyLayerSet->requestUpdate();
-		}
-		break;
 
-	case LOCTEX_NUM_ENTRIES:
-		llerrs << "Bogus texture value " << i << llendl;
-		break;
+//-----------------------------------------------------------------------------
+// requestLayerSetUpdate()
+//-----------------------------------------------------------------------------
+void LLVOAvatar::requestLayerSetUpdate(ETextureIndex index )
+{
+	/* switch(index)
+		case LOCTEX_UPPER_BODYPAINT:  
+		case LOCTEX_UPPER_SHIRT:
+			if( mUpperBodyLayerSet )
+				mUpperBodyLayerSet->requestUpdate(); */
+	const LLVOAvatarDictionary::TextureDictionaryEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
+	if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture)
+		return;
+	const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+	if (mBakedTextureData[baked_index].mTexLayerSet)
+	{
+		mBakedTextureData[baked_index].mTexLayerSet->requestUpdate();
 	}
-
 }
 
 void LLVOAvatar::setParent(LLViewerObject* parent)
@@ -6616,6 +6188,7 @@ const std::string LLVOAvatar::getAttachedPointName(const LLUUID& inv_item_id)
 // static 
 // onLocalTextureLoaded()
 //-----------------------------------------------------------------------------
+
 void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
 {
 	//llinfos << "onLocalTextureLoaded: " << src_vi->getID() << llendl;
@@ -6625,37 +6198,47 @@ void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLIm
 	if (success)
 	{
 		LLVOAvatar *self = (LLVOAvatar *)gObjectList.findObject(data->mAvatarID);
-		LLVOAvatar::ELocTexIndex idx = data->mIndex;
-		if( self &&
-			(!self->mLocalTextureBaked[ idx ]) &&
-			(self->mLocalTexture[ idx ].notNull()) &&
-			(self->mLocalTexture[ idx ]->getID() == src_id) &&
-			(discard_level < self->mLocalTextureDiscard[idx]))
-		{
-			self->mLocalTextureDiscard[idx] = discard_level;
-			self->requestLayerSetUpdate( idx );
-			if( self->mIsSelf && gAgent.cameraCustomizeAvatar() )
-			{
-				LLVisualParamHint::requestHintUpdates();
+		if (self)
+		{
+			ETextureIndex index = data->mIndex;
+			if (!self->isIndexLocalTexture(index)) return;
+			LocalTextureData &local_tex_data = self->mLocalTextureData[index];
+			if(!local_tex_data.mIsBakedReady &&
+			   local_tex_data.mImage.notNull() &&
+			   (local_tex_data.mImage->getID() == src_id) &&
+			   discard_level < local_tex_data.mDiscard)
+			{
+				local_tex_data.mDiscard = discard_level;
+				if ( self->isSelf() && !gAgent.cameraCustomizeAvatar() )
+				{
+					self->requestLayerSetUpdate( index );
+				}
+				else if( self->isSelf() && gAgent.cameraCustomizeAvatar() )
+				{
+					LLVisualParamHint::requestHintUpdates();
+				}
+				self->updateMeshTextures();
 			}
-			self->updateMeshTextures();
 		}
 	}
 	else if (final)
 	{
 		LLVOAvatar *self = (LLVOAvatar *)gObjectList.findObject(data->mAvatarID);
-		LLVOAvatar::ELocTexIndex idx = data->mIndex;
-		// Failed: asset is missing
-		if( self &&
-			(!self->mLocalTextureBaked[ idx ]) &&
-			(self->mLocalTexture[ idx ].notNull()) &&
-			(self->mLocalTexture[ idx ]->getID() == src_id))
+		if (self)
 		{
-			self->mLocalTextureDiscard[idx] = 0; // we check that it's missing later
-			self->requestLayerSetUpdate( idx );
-			self->updateMeshTextures();
+			ETextureIndex index = data->mIndex;
+			if (!self->isIndexLocalTexture(index)) return;
+			LocalTextureData &local_tex_data = self->mLocalTextureData[index];
+			// Failed: asset is missing
+			if(!local_tex_data.mIsBakedReady &&
+			   local_tex_data.mImage.notNull() &&
+			   local_tex_data.mImage->getID() == src_id)
+			{
+				local_tex_data.mDiscard = 0;
+				self->requestLayerSetUpdate( index );
+				self->updateMeshTextures();
+			}
 		}
-		
 	}
 
 	if( final || !success )
@@ -6666,29 +6249,13 @@ void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLIm
 
 void LLVOAvatar::updateComposites()
 {
-	if( mHeadLayerSet )
-	{
-		mHeadLayerSet->updateComposite();
-	}
-
-	if( mUpperBodyLayerSet )
-	{
-		mUpperBodyLayerSet->updateComposite();
-	}
-
-	if( mLowerBodyLayerSet )
-	{
-		mLowerBodyLayerSet->updateComposite();
-	}
-
-	if( mEyesLayerSet )
-	{
-		mEyesLayerSet->updateComposite();
-	}
-
-	if( mSkirtLayerSet && isWearingWearableType( WT_SKIRT ))
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		mSkirtLayerSet->updateComposite();
+		if ( mBakedTextureData[i].mTexLayerSet 
+			&& ((i != BAKED_SKIRT) || isWearingWearableType( WT_SKIRT )) )
+		{
+			mBakedTextureData[i].mTexLayerSet->updateComposite();
+		}
 	}
 }
 
@@ -6740,6 +6307,10 @@ void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user
 	{
 		layer_name = "eyes";
 	}
+	else if (layerset == mHairLayerSet)
+	{
+		layer_name = "hair";
+	}
 	else if (layerset == mSkirtLayerSet)
 	{
 		layer_name = "skirt";
@@ -6758,47 +6329,52 @@ void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user
 		llassert( mIsSelf );
 
 		ETextureIndex baked_te = getBakedTE( layerset );
-		if( gAgent.cameraCustomizeAvatar() )
-		{
-			mSavedTE[ baked_te ].setNull();  
-		}
-		else
-		{
-			setTEImage( baked_te, gImageList.getImage(IMG_DEFAULT_AVATAR) );
-			layerset->requestUpload();
-		}
+		setTEImage( baked_te, gImageList.getImage(IMG_DEFAULT_AVATAR) );
+		layerset->requestUpload();
 	}
 }
 
+void LLVOAvatar::invalidateAll()
+{
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
+	{
+		invalidateComposite(mBakedTextureData[i].mTexLayerSet, TRUE);
+	}
+	updateMeshTextures();
+}
 
 void LLVOAvatar::onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user )
 {
 	if( global_color == mTexSkinColor )
 	{
 //		llinfos << "invalidateComposite cause: onGlobalColorChanged( skin color )" << llendl; 
-		invalidateComposite( mHeadLayerSet,			set_by_user );
-		invalidateComposite( mUpperBodyLayerSet,	set_by_user );
-		invalidateComposite( mLowerBodyLayerSet,	set_by_user );
+		invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet,  set_by_user );
+		invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet,	set_by_user );
+		invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet,	set_by_user );
 	}
 	else
 	if( global_color == mTexHairColor )
 	{
 //		llinfos << "invalidateComposite cause: onGlobalColorChanged( hair color )" << llendl; 
-		invalidateComposite( mHeadLayerSet, set_by_user );
-
-		LLColor4 color = mTexHairColor->getColor();
-		mHairMesh0.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh1.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh2.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh3.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh4.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh5.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
+		invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet,  set_by_user );
+		invalidateComposite( mBakedTextureData[BAKED_HAIR].mTexLayerSet,  set_by_user );
+		
+		// ! BACKWARDS COMPATIBILITY !
+		// Fix for dealing with avatars from viewers that don't bake hair.
+		if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex))
+		{
+			LLColor4 color = mTexHairColor->getColor();
+			for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++)
+			{
+				mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
+			}
+		}
 	}
 	else
 	if( global_color == mTexEyeColor )
 	{
 //		llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl; 
-		invalidateComposite( mEyesLayerSet, set_by_user );
+		invalidateComposite( mBakedTextureData[BAKED_EYES].mTexLayerSet,  set_by_user );
 	}
 	updateMeshTextures();
 }
@@ -6807,9 +6383,9 @@ void LLVOAvatar::forceBakeAllTextures(bool slam_for_debug)
 {
 	llinfos << "TAT: forced full rebake. " << llendl;
 
-	for (S32 i = 0; i < BAKED_TEXTURE_COUNT; i++)
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		ETextureIndex baked_index = sBakedTextureIndices[i];
+		ETextureIndex baked_index = mBakedTextureData[i].mTextureIndex;
 		LLTexLayerSet* layer_set = getLayerSet(baked_index);
 		if (layer_set)
 		{
@@ -6846,20 +6422,30 @@ void LLVOAvatar::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
 	// If this is a texture corresponding to one of our baked entries, 
 	// just rebake that layer set.
 	BOOL found = FALSE;
-	for (S32 i = 0; i < BAKED_TEXTURE_COUNT; i++)
+
+	/* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] =
+			TEX_HEAD_BAKED,
+			TEX_UPPER_BAKED, */
+	for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+		 iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+		 iter++)
 	{
-		ETextureIndex baked_index = sBakedTextureIndices[i];
-		if (texture_id == self->getTEImage(baked_index)->getID())
+		const ETextureIndex index = iter->first;
+		const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
+		if (text_dict->mIsBakedTexture)
 		{
-			LLTexLayerSet* layer_set = self->getLayerSet(baked_index);
-			if (layer_set)
+			if (texture_id == self->getTEImage(index)->getID())
 			{
-				llinfos << "TAT: rebake - matched entry " << (S32)baked_index << llendl;
-				// Apparently set_by_user == force upload
-				BOOL set_by_user = TRUE;
-				self->invalidateComposite(layer_set, set_by_user);
-				found = TRUE;
-				LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
+				LLTexLayerSet* layer_set = self->getLayerSet(index);
+				if (layer_set)
+				{
+					llinfos << "TAT: rebake - matched entry " << (S32)index << llendl;
+					// Apparently set_by_user == force upload
+					BOOL set_by_user = TRUE;
+					self->invalidateComposite(layer_set, set_by_user);
+					found = TRUE;
+					LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES);
+				}
 			}
 		}
 	}
@@ -6877,48 +6463,48 @@ void LLVOAvatar::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
 }
 
 
-BOOL LLVOAvatar::getLocalTextureRaw(S32 index, LLImageRaw* image_raw)
+BOOL LLVOAvatar::getLocalTextureRaw(ETextureIndex index, LLImageRaw* image_raw)
 {
+	if (!isIndexLocalTexture(index)) return FALSE;
+
     BOOL success = FALSE;
 
-	if( (0 <= index) && (index < LOCTEX_NUM_ENTRIES) )
+	if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR)
 	{
-		if (mLocalTexture[ index ].isNull() || mLocalTexture[ index ]->getID() == IMG_DEFAULT_AVATAR )
+		success = TRUE;
+	}
+	else
+	{
+		LocalTextureData &local_tex_data = mLocalTextureData[index];
+		if(local_tex_data.mImage->readBackRaw(-1, image_raw, false))
 		{
 			success = TRUE;
 		}
 		else
 		{
-			if( mLocalTexture[ index ]->readBackRaw(-1, image_raw, false) )
-			{
-				success = TRUE;
-			}
-			else
-			{
-				// No data loaded yet
-				setLocalTexture( (ELocTexIndex)index, getTEImage( index ), FALSE );
-			}
+			// No data loaded yet
+			setLocalTexture( (ETextureIndex)index, getTEImage( index ), FALSE );
 		}
 	}
 	return success;
 }
 
-BOOL LLVOAvatar::getLocalTextureGL(S32 index, LLImageGL** image_gl_pp)
+BOOL LLVOAvatar::getLocalTextureGL(ETextureIndex index, LLImageGL** image_gl_pp)
 {
+	if (!isIndexLocalTexture(index)) return FALSE;
+
 	BOOL success = FALSE;
 	*image_gl_pp = NULL;
 
-	if( (0 <= index) && (index < LOCTEX_NUM_ENTRIES) )
+	if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR)
 	{
-		if( mLocalTexture[ index ].isNull() || mLocalTexture[ index ]->getID() == IMG_DEFAULT_AVATAR)
-		{
-			success = TRUE;
-		}
-		else
-		{
-			*image_gl_pp = mLocalTexture[ index ];
-			success = TRUE;
-		}
+		success = TRUE;
+	}
+	else
+	{
+		LocalTextureData &local_tex_data = mLocalTextureData[index];
+		*image_gl_pp = local_tex_data.mImage;
+		success = TRUE;
 	}
 
 	if( !success )
@@ -6928,11 +6514,13 @@ BOOL LLVOAvatar::getLocalTextureGL(S32 index, LLImageGL** image_gl_pp)
 	return success;
 }
 
-const LLUUID& LLVOAvatar::getLocalTextureID( S32 index )
+const LLUUID& LLVOAvatar::getLocalTextureID(ETextureIndex index)
 {
-	if (index >= 0 && mLocalTexture[index].notNull())
+	if (!isIndexLocalTexture(index)) return IMG_DEFAULT_AVATAR;
+	
+	if (mLocalTextureData[index].mImage.notNull())
 	{
-		return mLocalTexture[index]->getID();
+		return mLocalTextureData[index].mImage->getID();
 	}
 	else
 	{
@@ -6977,8 +6565,15 @@ BOOL LLVOAvatar::updateIsFullyLoaded()
 		loading = TRUE;
 	}
 
-	// are our texture settings still default?
-	if ((getTEImage( TEX_HAIR )->getID() == IMG_DEFAULT))
+	// 
+	if (mIsSelf)
+	{
+		if (!isTextureDefined(TEX_HAIR))
+		{
+			loading = TRUE;
+		}
+	}
+	else if (!isTextureDefined(TEX_LOWER_BAKED) || !isTextureDefined(TEX_UPPER_BAKED) || !isTextureDefined(TEX_HEAD_BAKED))
 	{
 		loading = TRUE;
 	}
@@ -6998,14 +6593,14 @@ BOOL LLVOAvatar::updateIsFullyLoaded()
 	// texture info for our shirt/pants, stay unloaded:
 	if (!mPreviousFullyLoaded)
 	{
-		if ((!isLocalTextureDataAvailable(mLowerBodyLayerSet)) &&
-			(getTEImage(TEX_LOWER_BAKED)->getID() == IMG_DEFAULT_AVATAR))
+		if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_LOWER].mTexLayerSet)) &&
+			(!isTextureDefined(TEX_LOWER_BAKED)))
 		{
 			loading = TRUE;
 		}
 
-		if ((!isLocalTextureDataAvailable(mUpperBodyLayerSet)) &&
-			(getTEImage(TEX_UPPER_BAKED)->getID() == IMG_DEFAULT_AVATAR))
+		if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_UPPER].mTexLayerSet)) &&
+			(!isTextureDefined(TEX_UPPER_BAKED)))
 		{
 			loading = TRUE;
 		}
@@ -7057,9 +6652,10 @@ LLMotion*		LLVOAvatar::findMotion(const LLUUID& id)
 void LLVOAvatar::getLocalTextureByteCount( S32* gl_bytes )
 {
 	*gl_bytes = 0;
-	for( S32 i = 0; i < LOCTEX_NUM_ENTRIES; i++ )
+	for( S32 i = 0; i < TEX_NUM_INDICES; i++ )
 	{
-		LLViewerImage* image_gl = mLocalTexture[i];
+		if (!isIndexLocalTexture((ETextureIndex)i)) continue;
+		LLViewerImage* image_gl = mLocalTextureData[(ETextureIndex)i].mImage;
 		if( image_gl )
 		{
 			S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents();
@@ -7122,7 +6718,7 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes )
 	default:	llassert(0);	components = 4; internal_format = GL_RGBA8;				break;
 	}
 
-	*texture_bytes = components * VOAVATAR_SCRATCH_TEX_WIDTH * VOAVATAR_SCRATCH_TEX_HEIGHT;
+	*texture_bytes = components * SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT;
 	
 	if( LLVOAvatar::sScratchTexNames.checkData( format ) )
 	{
@@ -7142,7 +6738,7 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes )
 
 		LLImageGL::setManualImage(
 			GL_TEXTURE_2D, 0, internal_format, 
-			VOAVATAR_SCRATCH_TEX_WIDTH, VOAVATAR_SCRATCH_TEX_HEIGHT,
+			SCRATCH_TEX_WIDTH, SCRATCH_TEX_HEIGHT,
 			format, GL_UNSIGNED_BYTE, NULL );
 		stop_glerror();
 
@@ -7174,7 +6770,7 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user )
 		return;
 	}
 
-	if( te >= TEX_NUM_ENTRIES )
+	if( te >= TEX_NUM_INDICES )
 	{
 		llassert(0);
 		return;
@@ -7185,7 +6781,7 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user )
 		return;
 	}
 
-	if (isTextureIndexBaked(te))
+	if (isIndexBakedTexture((ETextureIndex)te))
 	{
 		llassert(0);
 		return;
@@ -7208,32 +6804,13 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user )
 
 void LLVOAvatar::setupComposites()
 {
-	// Don't invalidate the baked textures we had on start-up.
-	BOOL head_baked =  ( getTEImage( TEX_HEAD_BAKED  )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL eyes_baked =  ( getTEImage( TEX_EYES_BAKED  )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	
-	if (mHeadLayerSet)
-	{
-		mHeadLayerSet->setUpdatesEnabled(		!head_baked  );
-	}
-	if (mUpperBodyLayerSet)
-	{
-		mUpperBodyLayerSet->setUpdatesEnabled(	!upper_baked );
-	}
-	if (mLowerBodyLayerSet)
-	{
-		mLowerBodyLayerSet->setUpdatesEnabled(	!lower_baked );
-	}
-	if (mEyesLayerSet)
-	{
-		mEyesLayerSet->setUpdatesEnabled(		!eyes_baked  );
-	}
-	if (mSkirtLayerSet)
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		mSkirtLayerSet->setUpdatesEnabled(		!skirt_baked  );
+		bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex);
+		if (mBakedTextureData[i].mTexLayerSet)
+		{
+			mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( !layer_baked );
+		}
 	}
 }
 
@@ -7243,517 +6820,223 @@ void LLVOAvatar::setupComposites()
 //-----------------------------------------------------------------------------
 void LLVOAvatar::updateMeshTextures()
 {
-//	llinfos << "updateMeshTextures" << llendl;
-	if (gNoRender)
-	{
-		return;
-	}
+    // llinfos << "updateMeshTextures" << llendl;
+	if (gNoRender) return;
+
 	// if user has never specified a texture, assign the default
-	LLViewerImage* default_tex = gImageList.getImage(IMG_DEFAULT);
-	U8 num_TEs = getNumTEs();
-	for (U32 i=0; i<num_TEs; i++)
+	for (U32 i=0; i < getNumTEs(); i++)
 	{
-		LLViewerImage* te_image = getTEImage(i);
-		if( (NULL == te_image) || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT) )
+		const LLViewerImage* te_image = getTEImage(i);
+		if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT))
 		{
-			if( TEX_HAIR == i )
-			{
-				setTEImage(i, default_tex );
-			}
-			else
-			{
-				setTEImage(i, gImageList.getImage(IMG_DEFAULT_AVATAR)); // a special texture that's never rendered.
-			}
+			setTEImage(i, gImageList.getImage(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR)); // IMG_DEFAULT_AVATAR = a special texture that's never rendered.
 		}
 	}
 
-	// During face edit mode, we don't use baked textures
-	BOOL self_customize = mIsSelf && gAgent.cameraCustomizeAvatar();
-
-	BOOL head_baked = (getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL upper_baked = (getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL lower_baked = (getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL eyes_baked = (getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL skirt_baked = (getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR );
+	const BOOL self_customizing = mIsSelf && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures
+	const BOOL other_culled = !mIsSelf && mCulled;
 
-	// Nothing should be baked if we're in customize avatar mode.
-	llassert( !( self_customize && 
-		( head_baked || upper_baked || lower_baked || eyes_baked ) ) );
+	std::vector<bool> is_layer_baked;
+	is_layer_baked.resize(mBakedTextureData.size(), false);
 
-	BOOL use_lkg_head_baked =  FALSE;
-	BOOL use_lkg_upper_baked = FALSE;
-	BOOL use_lkg_lower_baked = FALSE;
-	BOOL use_lkg_eyes_baked =  FALSE;
-	BOOL use_lkg_skirt_baked =  FALSE;
+	std::vector<bool> use_lkg_baked_layer; // lkg = "last known good"
+	use_lkg_baked_layer.resize(mBakedTextureData.size(), false);
 
-	BOOL other_culled = !mIsSelf && mCulled;
-	if( other_culled )
+	for (U32 i=0; i < mBakedTextureData.size(); i++)
 	{
-		use_lkg_head_baked =  !head_baked  && (mLastHeadBakedID != IMG_DEFAULT_AVATAR);
-		use_lkg_upper_baked = !upper_baked && (mLastUpperBodyBakedID != IMG_DEFAULT_AVATAR);
-		use_lkg_lower_baked = !lower_baked && (mLastLowerBodyBakedID != IMG_DEFAULT_AVATAR);
-		use_lkg_eyes_baked =  !eyes_baked  && (mLastEyesBakedID != IMG_DEFAULT_AVATAR);
-		use_lkg_skirt_baked = !skirt_baked && (mLastSkirtBakedID != IMG_DEFAULT_AVATAR);
+		is_layer_baked[i] = isTextureDefined(mBakedTextureData[i].mTextureIndex);
 
-		if( mHeadLayerSet )
+		if (!other_culled)
 		{
-			mHeadLayerSet->destroyComposite();
+			// When an avatar is changing clothes and not in Appearance mode,
+			// use the last-known good baked texture until it finish the first
+			// render of the new layerset.
+			use_lkg_baked_layer[i] = (!is_layer_baked[i] 
+									  && (mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) 
+									  && mBakedTextureData[i].mTexLayerSet 
+									  && !mBakedTextureData[i].mTexLayerSet->getComposite()->isInitialized());
+			if (use_lkg_baked_layer[i])
+			{
+				mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled(TRUE);
+			}
 		}
-
-		if( mUpperBodyLayerSet )
+		else
 		{
-			mUpperBodyLayerSet->destroyComposite();
+			use_lkg_baked_layer[i] = (!is_layer_baked[i] 
+									  && mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR);
+			if (mBakedTextureData[i].mTexLayerSet)
+			{
+				mBakedTextureData[i].mTexLayerSet->destroyComposite();
+			}
 		}
 
-		if( mLowerBodyLayerSet )
+	}
+
+	// Baked textures should be requested from the sim this avatar is on. JC
+	const LLHost target_host = getObjectHost();
+	if (!target_host.isOk())
+	{
+		llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl;
+	}
+
+	for (U32 i=0; i < mBakedTextureData.size(); i++)
+	{
+		if (use_lkg_baked_layer[i])
 		{
-			mLowerBodyLayerSet->destroyComposite();
+			LLViewerImage* baked_img = gImageList.getImageFromHost( mBakedTextureData[i].mLastTextureIndex, target_host );
+			for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++)
+			{
+				mBakedTextureData[i].mMeshes[k]->setTexture( baked_img );
+			}
 		}
-
-		if( mEyesLayerSet )
+		else if (!self_customizing && is_layer_baked[i])
 		{
-			mEyesLayerSet->destroyComposite();
+			LLViewerImage* baked_img = getTEImage( mBakedTextureData[i].mTextureIndex );
+			if( baked_img->getID() == mBakedTextureData[i].mLastTextureIndex )
+			{
+				// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
+				useBakedTexture( baked_img->getID() );
+			}
+			else
+			{
+				mBakedTextureData[i].mIsLoaded = FALSE;
+				if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
+				{
+					baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));	
+				}
+				baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
+			}
 		}
-
-		if( mSkirtLayerSet )
+		else if (mBakedTextureData[i].mTexLayerSet 
+				 && !other_culled 
+				 && (i != BAKED_HAIR || is_layer_baked[i] || mIsSelf)) // ! BACKWARDS COMPATIBILITY ! workaround for old viewers.
 		{
-			mSkirtLayerSet->destroyComposite();
+			mBakedTextureData[i].mTexLayerSet->createComposite();
+			mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( TRUE );
+			for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++)
+			{
+				mBakedTextureData[i].mMeshes[k]->setLayerSet( mBakedTextureData[i].mTexLayerSet );
+			}
 		}
-
 	}
-	else
-	if( !self_customize )
+	
+	// ! BACKWARDS COMPATIBILITY !
+	// Workaround for viewing avatars from old viewers that haven't baked hair textures.
+	// if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex))
+	if (!is_layer_baked[BAKED_HAIR])
 	{
-		// When you're changing clothes and you're not in Appearance mode,
-		// use the last-known good baked texture until you finish the first
-		// render of the new layerset.
-		use_lkg_head_baked =  !head_baked  && (mLastHeadBakedID      != IMG_DEFAULT_AVATAR) && mHeadLayerSet      && !mHeadLayerSet->getComposite()->isInitialized();
-		use_lkg_upper_baked = !upper_baked && (mLastUpperBodyBakedID != IMG_DEFAULT_AVATAR) && mUpperBodyLayerSet && !mUpperBodyLayerSet->getComposite()->isInitialized();
-		use_lkg_lower_baked = !lower_baked && (mLastLowerBodyBakedID != IMG_DEFAULT_AVATAR) && mLowerBodyLayerSet && !mLowerBodyLayerSet->getComposite()->isInitialized();
-		use_lkg_eyes_baked =  !eyes_baked  && (mLastEyesBakedID      != IMG_DEFAULT_AVATAR) && mEyesLayerSet      && !mEyesLayerSet->getComposite()->isInitialized();
-		use_lkg_skirt_baked = !skirt_baked && (mLastSkirtBakedID     != IMG_DEFAULT_AVATAR) && mSkirtLayerSet     && !mSkirtLayerSet->getComposite()->isInitialized();
-
-		if( use_lkg_head_baked ) 
+		const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1);
+		LLViewerImage* hair_img = getTEImage( TEX_HAIR );
+		for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++)
 		{
-			mHeadLayerSet->setUpdatesEnabled( TRUE );
+			mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
+			mBakedTextureData[BAKED_HAIR].mMeshes[i]->setTexture( hair_img );
 		}
-
-		if( use_lkg_upper_baked ) 
+		mHasBakedHair = FALSE;
+	} 
+	else 
+	{
+		for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++)
 		{
-			mUpperBodyLayerSet->setUpdatesEnabled( TRUE );
+			mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f );
 		}
-
-		if( use_lkg_lower_baked )
+		mHasBakedHair = TRUE;
+	}
+	
+	/* // Head
+	   BOOL head_baked_ready = (is_layer_baked[BAKED_HEAD] && mBakedTextureData[BAKED_HEAD].mIsLoaded) || other_culled;
+	   setLocalTexture( TEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), head_baked_ready ); */
+	for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+		 baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
+		 baked_iter++)
+	{
+		const EBakedTextureIndex baked_index = baked_iter->first;
+		const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second;
+		
+		for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
+			 local_tex_iter != baked_dict->mLocalTextures.end();
+			 local_tex_iter++)
 		{
-			mLowerBodyLayerSet->setUpdatesEnabled( TRUE );
+			const ETextureIndex texture_index = *local_tex_iter;
+			const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureData[baked_index].mIsLoaded) || other_culled;
+			setLocalTexture(texture_index, getTEImage(texture_index), is_baked_ready );
 		}
+	}
+	removeMissingBakedTextures();
+}
+
+//-----------------------------------------------------------------------------
+// setLocalTexture()
+//-----------------------------------------------------------------------------
+void LLVOAvatar::setLocalTexture( ETextureIndex index, LLViewerImage* tex, BOOL baked_version_ready )
+{
+	if (!isIndexLocalTexture(index)) return;
 
-		if( use_lkg_eyes_baked )  
+	S32 desired_discard = mIsSelf ? 0 : 2;
+	LocalTextureData &local_tex_data = mLocalTextureData[index];
+	if (!baked_version_ready)
+	{
+		if (tex != local_tex_data.mImage || local_tex_data.mIsBakedReady)
 		{
-			mEyesLayerSet->setUpdatesEnabled( TRUE );
+			local_tex_data.mDiscard = MAX_DISCARD_LEVEL+1;
 		}
-
-		if( use_lkg_skirt_baked )  
+		if (tex->getID() != IMG_DEFAULT_AVATAR)
 		{
-			mSkirtLayerSet->setUpdatesEnabled( TRUE );
+			if (local_tex_data.mDiscard > desired_discard)
+			{
+				S32 tex_discard = tex->getDiscardLevel();
+				if (tex_discard >= 0 && tex_discard <= desired_discard)
+				{
+					local_tex_data.mDiscard = tex_discard;
+					if( mIsSelf && !gAgent.cameraCustomizeAvatar() )
+					{
+						requestLayerSetUpdate( index );
+					}
+					else if( mIsSelf && gAgent.cameraCustomizeAvatar() )
+					{
+						LLVisualParamHint::requestHintUpdates();
+					}
+				}
+				else
+				{
+					tex->setLoadedCallback( onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), index) );
+				}
+			}
+			tex->setMinDiscardLevel(desired_discard);
 		}
 	}
+	local_tex_data.mIsBakedReady = baked_version_ready;
+	local_tex_data.mImage = tex;
+}
 
-	// Baked textures should be requested from the sim this avatar is on. JC
-	LLHost target_host = getObjectHost();
-	if (!target_host.isOk())
-	{
-		llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl;
-	}
-		
-	// Head
-	if( use_lkg_head_baked )
-	{
-		LLViewerImage* baked = gImageList.getImageFromHost( mLastHeadBakedID, target_host );
-		mHeadMesh0.setTexture( baked );
-		mHeadMesh1.setTexture( baked );
-		mHeadMesh2.setTexture( baked );
-		mHeadMesh3.setTexture( baked );
-		mHeadMesh4.setTexture( baked );
-		mEyeLashMesh0.setTexture( baked );
-	}
-	else
-	if( !self_customize && head_baked )
+//-----------------------------------------------------------------------------
+// requestLayerSetUploads()
+//-----------------------------------------------------------------------------
+void LLVOAvatar::requestLayerSetUploads()
+{
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		LLViewerImage* baked = getTEImage( TEX_HEAD_BAKED );
-		if( baked->getID() == mLastHeadBakedID )
-		{
-			// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
-			useBakedTexture( baked->getID() );
-		}
-		else
+		bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex);
+		if ( !layer_baked && mBakedTextureData[i].mTexLayerSet )
 		{
-			mHeadBakedLoaded = FALSE;
-			mHeadMaskDiscard = -1;
-			baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));	
-			baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
+			mBakedTextureData[i].mTexLayerSet->requestUpload();
 		}
 	}
-	else
-	if( mHeadLayerSet && !other_culled )
-	{
-		mHeadLayerSet->createComposite();
-		mHeadLayerSet->setUpdatesEnabled( TRUE );
-		mHeadMesh0.setLayerSet( mHeadLayerSet );
-		mHeadMesh1.setLayerSet( mHeadLayerSet );
-		mHeadMesh2.setLayerSet( mHeadLayerSet );
-		mHeadMesh3.setLayerSet( mHeadLayerSet );
-		mHeadMesh4.setLayerSet( mHeadLayerSet );
-		mEyeLashMesh0.setLayerSet( mHeadLayerSet );
-	}
-	else
-	{
-		mHeadMesh0.setTexture( default_tex );
-		mHeadMesh1.setTexture( default_tex );
-		mHeadMesh2.setTexture( default_tex );
-		mHeadMesh3.setTexture( default_tex );
-		mHeadMesh4.setTexture( default_tex );
-		mEyeLashMesh0.setTexture( default_tex );
-	}
+}
+
 
-	// Upper body
-	if( use_lkg_upper_baked )
+//-----------------------------------------------------------------------------
+// setCompositeUpdatesEnabled()
+//-----------------------------------------------------------------------------
+void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b )
+{
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		LLViewerImage* baked = gImageList.getImageFromHost( mLastUpperBodyBakedID, target_host );
-		mUpperBodyMesh0.setTexture( baked );
-		mUpperBodyMesh1.setTexture( baked );
-		mUpperBodyMesh2.setTexture( baked );
-		mUpperBodyMesh3.setTexture( baked );
-		mUpperBodyMesh4.setTexture( baked );
+		if (mBakedTextureData[i].mTexLayerSet )
+		{
+			mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( b );
+		}
 	}
-	else
-	if( !self_customize && upper_baked )
-	{
-		LLViewerImage* baked = getTEImage( TEX_UPPER_BAKED );
-
-		if( baked->getID() == mLastUpperBodyBakedID )
-		{
-			// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
-			useBakedTexture( baked->getID() );
-		}
-		else
-		{
-			mUpperBakedLoaded = FALSE;
-			mUpperMaskDiscard = -1;
-			baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
-			baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
-		}
-	}
-	else
-	if( mUpperBodyLayerSet && !other_culled )
-	{
-		mUpperBodyLayerSet->createComposite();
-		mUpperBodyLayerSet->setUpdatesEnabled( TRUE );
-		mUpperBodyMesh0.setLayerSet( mUpperBodyLayerSet );
-		mUpperBodyMesh1.setLayerSet( mUpperBodyLayerSet );
-		mUpperBodyMesh2.setLayerSet( mUpperBodyLayerSet );
-		mUpperBodyMesh3.setLayerSet( mUpperBodyLayerSet );
-		mUpperBodyMesh4.setLayerSet( mUpperBodyLayerSet );
-	}
-	else
-	{
-		mUpperBodyMesh0.setTexture( default_tex );
-		mUpperBodyMesh1.setTexture(	default_tex );
-		mUpperBodyMesh2.setTexture(	default_tex );
-		mUpperBodyMesh3.setTexture(	default_tex );
-		mUpperBodyMesh4.setTexture(	default_tex );
-	}
-
-	// Lower body
-	if( use_lkg_lower_baked )
-	{
-		LLViewerImage* baked = gImageList.getImageFromHost( mLastLowerBodyBakedID, target_host );
-		mLowerBodyMesh0.setTexture( baked );
-		mLowerBodyMesh1.setTexture( baked );
-		mLowerBodyMesh2.setTexture( baked );
-		mLowerBodyMesh3.setTexture( baked );
-		mLowerBodyMesh4.setTexture( baked );
-	}
-	else
-	if( !self_customize && lower_baked )
-	{
-		LLViewerImage* baked = getTEImage( TEX_LOWER_BAKED );
-		if( baked->getID() == mLastLowerBodyBakedID )
-		{
-			// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
-			useBakedTexture( baked->getID() );
-		}
-		else
-		{
-			mLowerBakedLoaded = FALSE;
-			mLowerMaskDiscard = -1;
-			baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
-			baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
-		}
-	}
-	else
-	if( mLowerBodyLayerSet && !other_culled )
-	{
-		mLowerBodyLayerSet->createComposite();
-		mLowerBodyLayerSet->setUpdatesEnabled( TRUE );
-		mLowerBodyMesh0.setLayerSet( mLowerBodyLayerSet );
-		mLowerBodyMesh1.setLayerSet( mLowerBodyLayerSet );
-		mLowerBodyMesh2.setLayerSet( mLowerBodyLayerSet );
-		mLowerBodyMesh3.setLayerSet( mLowerBodyLayerSet );
-		mLowerBodyMesh4.setLayerSet( mLowerBodyLayerSet );
-	}
-	else
-	{
-		mLowerBodyMesh0.setTexture(	default_tex );
-		mLowerBodyMesh1.setTexture(	default_tex );
-		mLowerBodyMesh2.setTexture(	default_tex );
-		mLowerBodyMesh3.setTexture(	default_tex );
-		mLowerBodyMesh4.setTexture(	default_tex );
-	}
-
-	// Eyes
-	if( use_lkg_eyes_baked )
-	{
-		LLViewerImage* baked = gImageList.getImageFromHost( mLastEyesBakedID, target_host );
-		mEyeBallLeftMesh0.setTexture(  baked );
-		mEyeBallLeftMesh1.setTexture(  baked );
-		mEyeBallRightMesh0.setTexture( baked );
-		mEyeBallRightMesh1.setTexture( baked );
-	}
-	else
-	if( !self_customize && eyes_baked )
-	{
-		LLViewerImage* baked = getTEImage( TEX_EYES_BAKED );
-		if( baked->getID() == mLastEyesBakedID )
-		{
-			// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
-			useBakedTexture( baked->getID() );
-		}
-		else
-		{
-			mEyesBakedLoaded = FALSE;
-			baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
-		}
-	}
-	else
-	if( mEyesLayerSet && !other_culled )
-	{
-		mEyesLayerSet->createComposite();
-		mEyesLayerSet->setUpdatesEnabled( TRUE );
-		mEyeBallLeftMesh0.setLayerSet( mEyesLayerSet );
-		mEyeBallLeftMesh1.setLayerSet( mEyesLayerSet );
-		mEyeBallRightMesh0.setLayerSet( mEyesLayerSet );
-		mEyeBallRightMesh1.setLayerSet( mEyesLayerSet );
-	}
-	else
-	{
-		mEyeBallLeftMesh0.setTexture( default_tex );
-		mEyeBallLeftMesh1.setTexture( default_tex );
-		mEyeBallRightMesh0.setTexture( default_tex );
-		mEyeBallRightMesh1.setTexture( default_tex );
-	}
-
-	// Skirt
-	if( use_lkg_skirt_baked )
-	{
-		LLViewerImage* baked = gImageList.getImageFromHost( mLastSkirtBakedID, target_host );
-		mSkirtMesh0.setTexture(  baked );
-		mSkirtMesh1.setTexture(  baked );
-		mSkirtMesh2.setTexture(  baked );
-		mSkirtMesh3.setTexture(  baked );
-		mSkirtMesh4.setTexture(  baked );
-	}
-	else
-	if( !self_customize && skirt_baked )
-	{
-		LLViewerImage* baked = getTEImage( TEX_SKIRT_BAKED );
-		if( baked->getID() == mLastSkirtBakedID )
-		{
-			// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
-			useBakedTexture( baked->getID() );
-		}
-		else
-		{
-			mSkirtBakedLoaded = FALSE;
-			baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
-		}
-	}
-	else
-	if( mSkirtLayerSet && !other_culled)
-	{
-		mSkirtLayerSet->createComposite();
-		mSkirtLayerSet->setUpdatesEnabled( TRUE );
-		mSkirtMesh0.setLayerSet( mSkirtLayerSet );
-		mSkirtMesh1.setLayerSet( mSkirtLayerSet );
-		mSkirtMesh2.setLayerSet( mSkirtLayerSet );
-		mSkirtMesh3.setLayerSet( mSkirtLayerSet );
-		mSkirtMesh4.setLayerSet( mSkirtLayerSet );
-	}
-	else
-	{
-		mSkirtMesh0.setTexture( default_tex );
-		mSkirtMesh1.setTexture( default_tex );
-		mSkirtMesh2.setTexture( default_tex );
-		mSkirtMesh3.setTexture( default_tex );
-		mSkirtMesh4.setTexture( default_tex );
-	}
-
-	mHairMesh0.setTexture(						getTEImage( TEX_HAIR ) );
-	mHairMesh1.setTexture(						getTEImage( TEX_HAIR ) );
-	mHairMesh2.setTexture(						getTEImage( TEX_HAIR ) );
-	mHairMesh3.setTexture(						getTEImage( TEX_HAIR ) );
-	mHairMesh4.setTexture(						getTEImage( TEX_HAIR ) );
-	mHairMesh5.setTexture(						getTEImage( TEX_HAIR ) );
-
-	if( mTexHairColor )
-	{
-		LLColor4 color = mTexHairColor->getColor();
-		mHairMesh0.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh1.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh2.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh3.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh4.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-		mHairMesh5.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
-	}
-
-	// Head
-	BOOL head_baked_ready = (head_baked && mHeadBakedLoaded) || other_culled;
-	setLocalTexture( LOCTEX_HEAD_BODYPAINT,		getTEImage( TEX_HEAD_BODYPAINT ),	head_baked_ready );
-
-	// Upper body
-	BOOL upper_baked_ready = (upper_baked && mUpperBakedLoaded) || other_culled;
-	setLocalTexture( LOCTEX_UPPER_SHIRT,		getTEImage( TEX_UPPER_SHIRT ),		upper_baked_ready );
-	setLocalTexture( LOCTEX_UPPER_BODYPAINT,	getTEImage( TEX_UPPER_BODYPAINT ),	upper_baked_ready );
-	setLocalTexture( LOCTEX_UPPER_JACKET,		getTEImage( TEX_UPPER_JACKET ),		upper_baked_ready );
-	setLocalTexture( LOCTEX_UPPER_GLOVES,		getTEImage( TEX_UPPER_GLOVES ),		upper_baked_ready );
-	setLocalTexture( LOCTEX_UPPER_UNDERSHIRT,	getTEImage( TEX_UPPER_UNDERSHIRT ),	upper_baked_ready );
-
-	// Lower body
-	BOOL lower_baked_ready = (lower_baked && mLowerBakedLoaded) || other_culled;
-	setLocalTexture( LOCTEX_LOWER_PANTS,		getTEImage( TEX_LOWER_PANTS ),		lower_baked_ready );
-	setLocalTexture( LOCTEX_LOWER_BODYPAINT,	getTEImage( TEX_LOWER_BODYPAINT ),	lower_baked_ready );
-	setLocalTexture( LOCTEX_LOWER_SHOES,		getTEImage( TEX_LOWER_SHOES ),		lower_baked_ready );
-	setLocalTexture( LOCTEX_LOWER_SOCKS,		getTEImage( TEX_LOWER_SOCKS ),		lower_baked_ready );
-	setLocalTexture( LOCTEX_LOWER_JACKET,		getTEImage( TEX_LOWER_JACKET ),		lower_baked_ready );
-	setLocalTexture( LOCTEX_LOWER_UNDERPANTS,	getTEImage( TEX_LOWER_UNDERPANTS ),	lower_baked_ready );
-
-	// Eyes
-	BOOL eyes_baked_ready = (eyes_baked && mEyesBakedLoaded) || other_culled;
-	setLocalTexture( LOCTEX_EYES_IRIS,			getTEImage( TEX_EYES_IRIS ),		eyes_baked_ready );
-
-	// Skirt
-	BOOL skirt_baked_ready = (skirt_baked && mSkirtBakedLoaded) || other_culled;
-	setLocalTexture( LOCTEX_SKIRT,				getTEImage( TEX_SKIRT ),			skirt_baked_ready );
-
-	removeMissingBakedTextures();
-}
-
-//-----------------------------------------------------------------------------
-// setLocalTexture()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::setLocalTexture( ELocTexIndex idx, LLViewerImage* tex, BOOL baked_version_ready )
-{
-	S32 desired_discard = mIsSelf ? 0 : 2;
-	if (!baked_version_ready)
-	{
-		if (tex != mLocalTexture[idx] || mLocalTextureBaked[idx])
-		{
-			mLocalTextureDiscard[idx] = MAX_DISCARD_LEVEL+1;
-		}
-		if (tex->getID() != IMG_DEFAULT_AVATAR)
-		{
-			if (mLocalTextureDiscard[idx] > desired_discard)
-			{
-				S32 tex_discard = tex->getDiscardLevel();
-				if (tex_discard >= 0 && tex_discard <= desired_discard)
-				{
-					mLocalTextureDiscard[idx] = tex_discard;
-					requestLayerSetUpdate( idx );
-					if( mIsSelf && gAgent.cameraCustomizeAvatar() )
-					{
-						LLVisualParamHint::requestHintUpdates();
-					}
-				}
-				else
-				{
-					tex->setLoadedCallback( onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), idx) );
-				}
-			}
-			tex->setMinDiscardLevel(desired_discard);
-		}
-	}
-	mLocalTextureBaked[idx] = baked_version_ready;
-	mLocalTexture[idx] = tex;
-}
-
-//-----------------------------------------------------------------------------
-// requestLayerSetUploads()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::requestLayerSetUploads()
-{
-	BOOL upper_baked = (getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL lower_baked = (getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL head_baked = (getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL eyes_baked = (getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-	BOOL skirt_baked = (getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-
-	if( !head_baked && mHeadLayerSet )
-	{
-		mHeadLayerSet->requestUpload();
-	}
-
-	if( !upper_baked && mUpperBodyLayerSet )
-	{
-		mUpperBodyLayerSet->requestUpload();
-	}
-
-	if( !lower_baked && mLowerBodyLayerSet )
-	{
-		mLowerBodyLayerSet->requestUpload();
-	}
-
-	if( !eyes_baked && mEyesLayerSet )
-	{
-		mEyesLayerSet->requestUpload();
-	}
-
-	if( !skirt_baked && mSkirtLayerSet )
-	{
-		mSkirtLayerSet->requestUpload();
-	}
-}
-
-
-//-----------------------------------------------------------------------------
-// setCompositeUpdatesEnabled()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b )
-{
-	if( mHeadLayerSet )
-	{
-		mHeadLayerSet->setUpdatesEnabled( b );
-	}
-	
-	if( mUpperBodyLayerSet )
-	{
-		mUpperBodyLayerSet->setUpdatesEnabled( b );
-	}
-
-	if( mLowerBodyLayerSet )
-	{
-		mLowerBodyLayerSet->setUpdatesEnabled( b );
-	}
-
-	if( mEyesLayerSet )
-	{
-		mEyesLayerSet->setUpdatesEnabled( b );
-	}
-
-	if( mSkirtLayerSet )
-	{
-		mSkirtLayerSet->setUpdatesEnabled( b );
-	}
-
 }
 
 void LLVOAvatar::addChat(const LLChat& chat)
@@ -7785,14 +7068,16 @@ void LLVOAvatar::clearChat()
 	mChats.clear();
 }
 
-S32 LLVOAvatar::getLocalDiscardLevel( S32 index )
+S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index )
 {
+	if (!isIndexLocalTexture(index)) return FALSE;
+
+	LocalTextureData &local_tex_data = mLocalTextureData[index];
 	if (index >= 0
-		&& mLocalTexture[index].notNull()
-		&& (mLocalTexture[index]->getID() != IMG_DEFAULT_AVATAR)
-		&& !mLocalTexture[index]->isMissingAsset())
+		&& getLocalTextureID(index) != IMG_DEFAULT_AVATAR
+		&& !local_tex_data.mImage->isMissingAsset())
 	{
-		return mLocalTexture[index]->getDiscardLevel();
+		return local_tex_data.mImage->getDiscardLevel();
 	}
 	else
 	{
@@ -7803,39 +7088,27 @@ S32 LLVOAvatar::getLocalDiscardLevel( S32 index )
 
 //-----------------------------------------------------------------------------
 // isLocalTextureDataFinal()
-// Returns true is the highest quality discard level exists for every texture
+// Returns true if the highest quality discard level exists for every texture
 // in the layerset.
 //-----------------------------------------------------------------------------
 BOOL LLVOAvatar::isLocalTextureDataFinal( LLTexLayerSet* layerset )
 {
-	if( layerset == mHeadLayerSet )
-	{
-		return getLocalDiscardLevel( LOCTEX_HEAD_BODYPAINT ) == 0;
-	}
-	else if( layerset == mUpperBodyLayerSet )
-	{
-		return getLocalDiscardLevel( LOCTEX_UPPER_SHIRT ) == 0 &&
-			getLocalDiscardLevel( LOCTEX_UPPER_BODYPAINT ) == 0 &&
-			getLocalDiscardLevel( LOCTEX_UPPER_JACKET ) == 0 && 
-			getLocalDiscardLevel( LOCTEX_UPPER_GLOVES ) == 0 && 
-			getLocalDiscardLevel( LOCTEX_UPPER_UNDERSHIRT ) == 0;
-	}
-	else if( layerset == mLowerBodyLayerSet )
-	{
-		return getLocalDiscardLevel( LOCTEX_LOWER_PANTS ) == 0 &&
-			getLocalDiscardLevel( LOCTEX_LOWER_BODYPAINT ) == 0 && 
-			getLocalDiscardLevel( LOCTEX_LOWER_SHOES ) == 0 && 
-			getLocalDiscardLevel( LOCTEX_LOWER_SOCKS ) == 0 && 
-			getLocalDiscardLevel( LOCTEX_LOWER_JACKET ) == 0 && 
-			getLocalDiscardLevel( LOCTEX_LOWER_UNDERPANTS ) == 0;
-	}
-	else if( layerset == mEyesLayerSet )
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		return getLocalDiscardLevel( LOCTEX_EYES_IRIS ) == 0;
-	}
-	else if( layerset == mSkirtLayerSet )
-	{
-		return getLocalDiscardLevel( LOCTEX_SKIRT ) == 0;
+		if (layerset == mBakedTextureData[i].mTexLayerSet)
+		{
+			const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
+			for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
+				 local_tex_iter != baked_dict->mLocalTextures.end();
+				 local_tex_iter++)
+			{
+				if (getLocalDiscardLevel(*local_tex_iter) != 0)
+				{
+					return FALSE;
+				}
+			}
+			return TRUE;
+		}
 	}
 
 	llassert(0);
@@ -7844,41 +7117,31 @@ BOOL LLVOAvatar::isLocalTextureDataFinal( LLTexLayerSet* layerset )
 
 //-----------------------------------------------------------------------------
 // isLocalTextureDataAvailable()
-// Returns true is at least the lowest quality discard level exists for every texture
+// Returns true if at least the lowest quality discard level exists for every texture
 // in the layerset.
 //-----------------------------------------------------------------------------
 BOOL LLVOAvatar::isLocalTextureDataAvailable( LLTexLayerSet* layerset )
 {
-	if( layerset == mHeadLayerSet )
-	{
-		return getLocalDiscardLevel( LOCTEX_HEAD_BODYPAINT ) >= 0;
-	}
-	else if( layerset == mUpperBodyLayerSet )
-	{
-		return getLocalDiscardLevel( LOCTEX_UPPER_SHIRT ) >= 0 &&
-			getLocalDiscardLevel( LOCTEX_UPPER_BODYPAINT ) >= 0 &&
-			getLocalDiscardLevel( LOCTEX_UPPER_JACKET ) >= 0 && 
-			getLocalDiscardLevel( LOCTEX_UPPER_GLOVES ) >= 0 && 
-			getLocalDiscardLevel( LOCTEX_UPPER_UNDERSHIRT ) >= 0;
-	}
-	else if( layerset == mLowerBodyLayerSet )
+	/* if( layerset == mBakedTextureData[BAKED_HEAD].mTexLayerSet )
+	   return getLocalDiscardLevel( TEX_HEAD_BODYPAINT ) >= 0; */
+	for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+		 baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
+		 baked_iter++)
 	{
-		return getLocalDiscardLevel( LOCTEX_LOWER_PANTS ) >= 0 &&
-			getLocalDiscardLevel( LOCTEX_LOWER_BODYPAINT ) >= 0 && 
-			getLocalDiscardLevel( LOCTEX_LOWER_SHOES ) >= 0 && 
-			getLocalDiscardLevel( LOCTEX_LOWER_SOCKS ) >= 0 && 
-			getLocalDiscardLevel( LOCTEX_LOWER_JACKET ) >= 0 && 
-			getLocalDiscardLevel( LOCTEX_LOWER_UNDERPANTS ) >= 0;
-	}
-	else if( layerset == mEyesLayerSet )
-	{
-		return getLocalDiscardLevel( LOCTEX_EYES_IRIS ) >= 0;
-	}
-	else if( layerset == mSkirtLayerSet )
-	{
-		return getLocalDiscardLevel( LOCTEX_SKIRT ) >= 0;
+		const EBakedTextureIndex baked_index = baked_iter->first;
+		if (layerset == mBakedTextureData[baked_index].mTexLayerSet)
+		{
+			bool ret = true;
+			const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second;
+			for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
+				 local_tex_iter != baked_dict->mLocalTextures.end();
+				 local_tex_iter++)
+			{
+				ret &= (getLocalDiscardLevel(*local_tex_iter) >= 0);
+			}
+			return ret;
+		}
 	}
-
 	llassert(0);
 	return FALSE;
 }
@@ -7888,31 +7151,14 @@ BOOL LLVOAvatar::isLocalTextureDataAvailable( LLTexLayerSet* layerset )
 // getBakedTE()
 // Used by the LayerSet.  (Layer sets don't in general know what textures depend on them.)
 //-----------------------------------------------------------------------------
-LLVOAvatar::ETextureIndex LLVOAvatar::getBakedTE( LLTexLayerSet* layerset )
+ETextureIndex LLVOAvatar::getBakedTE( LLTexLayerSet* layerset )
 {
-	if( layerset == mHeadLayerSet )
-	{
-		return TEX_HEAD_BAKED;
-	}
-	else
-	if( layerset == mUpperBodyLayerSet )
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		return TEX_UPPER_BAKED;
-	}
-	else
-	if( layerset == mLowerBodyLayerSet )
-	{
-		return TEX_LOWER_BAKED;
-	}
-	else
-	if( layerset == mEyesLayerSet )
-	{
-		return TEX_EYES_BAKED;
-	}
-	else
-	if( layerset == mSkirtLayerSet )
-	{
-		return TEX_SKIRT_BAKED;
+		if (layerset == mBakedTextureData[i].mTexLayerSet )
+		{
+			return mBakedTextureData[i].mTextureIndex;
+		}
 	}
 
 	llassert(0);
@@ -7933,26 +7179,17 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
 
 	LLVOAvatar::cullAvatarsByPixelArea();
 
-	switch( te )
+	/* switch(te)
+		case TEX_HEAD_BAKED:
+			llinfos << "New baked texture: HEAD" << llendl; */
+	const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(te);
+	if (text_dict->mIsBakedTexture)
+	{
+		llinfos << "New baked texture: " << text_dict->mName << " UUID: " << uuid <<llendl;
+	}
+	else
 	{
-	case TEX_HEAD_BAKED:
-		llinfos << "New baked texture: HEAD" << llendl;
-		break;
-	case TEX_UPPER_BAKED:
-		llinfos << "New baked texture: UPPER" << llendl;
-		break;
-	case TEX_LOWER_BAKED:
-		llinfos << "New baked texture: LOWER" << llendl;
-		break;
-	case TEX_EYES_BAKED:
-		llinfos << "New baked texture: EYES" << llendl;
-		break;
-	case TEX_SKIRT_BAKED:
-		llinfos << "New baked texture: SKIRT" << llendl;
-		break;
-	default:
 		llwarns << "New baked texture: unknown te " << te << llendl;
-		break;
 	}
 	
 	//	dumpAvatarTEs( "setNewBakedTexture() send" );
@@ -7965,28 +7202,15 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid )
 
 bool LLVOAvatar::hasPendingBakedUploads()
 {
-	bool head_pending = (mHeadLayerSet && mHeadLayerSet->getComposite()->uploadPending());
-	bool upper_pending = (mUpperBodyLayerSet && mUpperBodyLayerSet->getComposite()->uploadPending());
-	bool lower_pending = (mLowerBodyLayerSet && mLowerBodyLayerSet->getComposite()->uploadPending());
-	bool eyes_pending = (mEyesLayerSet && mEyesLayerSet->getComposite()->uploadPending());
-	bool skirt_pending = (mSkirtLayerSet && mSkirtLayerSet->getComposite()->uploadPending());
-
-	//llinfos << "TAT: LLVOAvatar::hasPendingBakedUploads()"
-	//	<< " head_pending " << head_pending
-	//	<< " upper_pending " << upper_pending
-	//	<< " lower_pending " << lower_pending
-	//	<< " eyes_pending " << eyes_pending
-	//	<< " skirt_pending " << skirt_pending
-	//	<< llendl;
-
-	if (head_pending || upper_pending || lower_pending || eyes_pending || skirt_pending)
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		return true;
-	}
-	else
-	{
-		return false;
+		bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending());
+		if (upload_pending)
+		{
+			return true;
+		}
 	}
+	return false;
 }
 
 //-----------------------------------------------------------------------------
@@ -7997,56 +7221,50 @@ void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid )
 {
 	setTETexture( te, uuid );
 
-	switch(te)
+	/* switch(te)
+		case TEX_HEAD_BAKED:
+			if( mHeadLayerSet )
+				mHeadLayerSet->cancelUpload(); */
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-	case TEX_HEAD_BAKED:
-		if( mHeadLayerSet )
+		if ( mBakedTextureData[i].mTextureIndex == te && mBakedTextureData[i].mTexLayerSet)
 		{
-			mHeadLayerSet->cancelUpload();
-		}		
-		break;
-	case TEX_UPPER_BAKED:
-		if( mUpperBodyLayerSet )
-		{
-			mUpperBodyLayerSet->cancelUpload();
+			mBakedTextureData[i].mTexLayerSet->cancelUpload();
 		}
-		break;
-	case TEX_LOWER_BAKED:
-		if( mLowerBodyLayerSet )
+	}
+}
+
+//-----------------------------------------------------------------------------
+// releaseUnneccesaryTextures()
+// release any component texture UUIDs for which we have a baked texture
+//-----------------------------------------------------------------------------
+void LLVOAvatar::releaseUnnecessaryTextures()
+{
+	// Backwards Compat: detect if the baked hair texture actually wasn't sent, and if so set to default
+	if (isTextureDefined(TEX_HAIR_BAKED) && getTEImage(TEX_HAIR_BAKED)->getID() == getTEImage(TEX_SKIRT_BAKED)->getID())
+	{
+		if (getTEImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE)
 		{
-			mLowerBodyLayerSet->cancelUpload();
+			// Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default
+			setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR);
 		}
-		break;
-	case TEX_EYES_BAKED:
-		if( mEyesLayerSet )
+	}
+
+	for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
+	{
+		const LLVOAvatarDictionary::BakedDictionaryEntry * bakedDicEntry = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
+		// skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID
+		if (!isTextureDefined(bakedDicEntry->mTextureIndex)
+			&& ( (baked_index != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ))
 		{
-			mEyesLayerSet->cancelUpload();
+			continue;
 		}
-		break;
-	case TEX_SKIRT_BAKED:
-		if( mSkirtLayerSet )
+
+		for (U8 texture = 0; texture < bakedDicEntry->mLocalTextures.size(); texture++)
 		{
-			mSkirtLayerSet->cancelUpload();
+			const U8 te = (ETextureIndex)bakedDicEntry->mLocalTextures[texture];
+			setTETexture(te, IMG_DEFAULT_AVATAR);
 		}
-		break;
-
-		case TEX_HEAD_BODYPAINT:
-		case TEX_UPPER_SHIRT:
-		case TEX_LOWER_PANTS:
-		case TEX_EYES_IRIS:
-		case TEX_HAIR:
-		case TEX_UPPER_BODYPAINT:
-		case TEX_LOWER_BODYPAINT:
-		case TEX_LOWER_SHOES:
-		case TEX_LOWER_SOCKS:
-		case TEX_UPPER_JACKET:
-		case TEX_LOWER_JACKET:
-		case TEX_UPPER_GLOVES:
-		case TEX_UPPER_UNDERSHIRT:
-		case TEX_LOWER_UNDERPANTS:
-		case TEX_SKIRT:
-		case TEX_NUM_ENTRIES:
-			break;
 	}
 }
 
@@ -8056,21 +7274,9 @@ void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid )
 //-----------------------------------------------------------------------------
 void LLVOAvatar::onCustomizeStart()
 {
-	LLVOAvatar* avatar = gAgent.getAvatarObject();
-	if( avatar )
-	{
-		for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ )
-		{
-			S32 tex_index = sBakedTextureIndices[i];
-			avatar->mSavedTE[ tex_index ] = avatar->getTEImage(tex_index)->getID();
-			avatar->setTEImage( tex_index, gImageList.getImage(IMG_DEFAULT_AVATAR) );
-		}
-
-		avatar->updateMeshTextures();
-
-//		avatar->dumpAvatarTEs( "onCustomizeStart() send" );
-		gAgent.sendAgentSetAppearance();
-	}
+	// We're no longer doing any baking or invalidating on entering 
+	// appearance editing mode. Leaving function in place in case 
+	// further changes require us to do something at this point - Nyx
 }
 
 //-----------------------------------------------------------------------------
@@ -8079,29 +7285,31 @@ void LLVOAvatar::onCustomizeStart()
 //-----------------------------------------------------------------------------
 void LLVOAvatar::onCustomizeEnd()
 {
-	LLVOAvatar* avatar = gAgent.getAvatarObject();
-	if( !avatar ) return;
+	LLVOAvatar *avatarp = gAgent.getAvatarObject();
+	if (avatarp)
+	{
+		avatarp->invalidateAll();
+		avatarp->requestLayerSetUploads();
+	}
+}
 
-	LLHost target_host = avatar->getObjectHost();
-		for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ )
+void LLVOAvatar::onChangeSelfInvisible(BOOL newvalue)
+{
+	LLVOAvatar *avatarp = gAgent.getAvatarObject();
+	if (avatarp)
+	{
+		if (newvalue)
 		{
-			S32 tex_index = sBakedTextureIndices[i];
-			const LLUUID& saved = avatar->mSavedTE[ tex_index ];
-			if( !saved.isNull() )
-			{
-			avatar->setTEImage( tex_index, gImageList.getImageFromHost( saved, target_host ) );
-			}
+			// we have just requested to set the avatar's baked textures to invisible
+			avatarp->setInvisible(TRUE);
 		}
-
-		avatar->updateMeshTextures();
-
-		if( !LLApp::isExiting())
+		else
 		{
-			avatar->requestLayerSetUploads();
+			avatarp->setInvisible(FALSE);
 		}
-
-		gAgent.sendAgentSetAppearance();
 	}
+}
+
 
 BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] )
 {
@@ -8181,7 +7389,7 @@ void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, B
 	}
 }
 
-LLColor4  LLVOAvatar::getClothesColor( ETextureIndex te )
+LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te )
 {
 	LLColor4 color;
 	const char* param_name[3];
@@ -8198,56 +7406,36 @@ LLColor4  LLVOAvatar::getClothesColor( ETextureIndex te )
 
 
 void LLVOAvatar::dumpAvatarTEs( const std::string& context )
-{
+{	
+	/* const char* te_name[] = {
+			"TEX_HEAD_BODYPAINT   ",
+			"TEX_UPPER_SHIRT      ", */
 	llinfos << (mIsSelf ? "Self: " : "Other: ") << context << llendl;
-	for( S32 i=0; i<TEX_NUM_ENTRIES; i++ )
+	for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+		 iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+		 iter++)
 	{
-		const char* te_name[] = {
-			"TEX_HEAD_BODYPAINT   ",
-			"TEX_UPPER_SHIRT      ",
-			"TEX_LOWER_PANTS      ",
-			"TEX_EYES_IRIS        ",
-			"TEX_HAIR             ",
-			"TEX_UPPER_BODYPAINT  ",
-			"TEX_LOWER_BODYPAINT  ",
-			"TEX_LOWER_SHOES      ",
-			"TEX_HEAD_BAKED       ",
-			"TEX_UPPER_BAKED      ",
-			"TEX_LOWER_BAKED      ",
-			"TEX_EYES_BAKED       ",
-			"TEX_LOWER_SOCKS      ",
-			"TEX_UPPER_JACKET     ",
-			"TEX_LOWER_JACKET     ",
-			"TEX_UPPER_GLOVES     ",
-			"TEX_UPPER_UNDERSHIRT ",
-			"TEX_LOWER_UNDERPANTS ",
-			"TEX_SKIRT            ",
-			"TEX_SKIRT_BAKED      "
-		};
-
-		LLViewerImage* te_image = getTEImage(i);
+		const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
+		const LLViewerImage* te_image = getTEImage(iter->first);
 		if( !te_image )
 		{
-			llinfos << "       " << te_name[i] << ": null ptr" << llendl;
+			llinfos << "       " << text_dict->mName << ": null ptr" << llendl;
 		}
-		else
-		if( te_image->getID().isNull() )
+		else if( te_image->getID().isNull() )
 		{
-			llinfos << "       " << te_name[i] << ": null UUID" << llendl;
+			llinfos << "       " << text_dict->mName << ": null UUID" << llendl;
 		}
-		else
-		if( te_image->getID() == IMG_DEFAULT )
+		else if( te_image->getID() == IMG_DEFAULT )
 		{
-			llinfos << "       " << te_name[i] << ": IMG_DEFAULT" << llendl;
+			llinfos << "       " << text_dict->mName << ": IMG_DEFAULT" << llendl;
 		}
-		else
-		if( te_image->getID() == IMG_DEFAULT_AVATAR )
+		else if( te_image->getID() == IMG_DEFAULT_AVATAR )
 		{
-			llinfos << "       " << te_name[i] << ": IMG_DEFAULT_AVATAR" << llendl;
+			llinfos << "       " << text_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl;
 		}
 		else
 		{
-			llinfos << "       " << te_name[i] << ": " << te_image->getID() << llendl;
+			llinfos << "       " << text_dict->mName << ": " << te_image->getID() << llendl;
 		}
 	}
 }
@@ -8290,80 +7478,51 @@ void LLVOAvatar::updateAttachmentVisibility(U32 camera_mode)
 
 // Given a texture entry, determine which wearable type owns it.
 // static
-LLUUID LLVOAvatar::getDefaultTEImageID( S32 te )
+LLUUID LLVOAvatar::getDefaultTEImageID(ETextureIndex index )
 {
-	switch( te )
+	/* switch( index )
+		case TEX_UPPER_SHIRT:		return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); */
+	const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
+	const std::string &default_image_name = text_dict->mDefaultImageName;
+	if (default_image_name == "")
 	{
-	case TEX_UPPER_SHIRT:		return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") );
-	case TEX_LOWER_PANTS:		return LLUUID( gSavedSettings.getString("UIImgDefaultPantsUUID") );
-	case TEX_EYES_IRIS:			return LLUUID( gSavedSettings.getString("UIImgDefaultEyesUUID") );
-	case TEX_HAIR:				return LLUUID( gSavedSettings.getString("UIImgDefaultHairUUID") );
-	case TEX_LOWER_SHOES:		return LLUUID( gSavedSettings.getString("UIImgDefaultShoesUUID") );
-	case TEX_LOWER_SOCKS:		return LLUUID( gSavedSettings.getString("UIImgDefaultSocksUUID") );
-	case TEX_UPPER_GLOVES:		return LLUUID( gSavedSettings.getString("UIImgDefaultGlovesUUID") );
-	
-	case TEX_UPPER_JACKET:
-	case TEX_LOWER_JACKET:		return LLUUID( gSavedSettings.getString("UIImgDefaultJacketUUID") );
-
-	case TEX_UPPER_UNDERSHIRT:
-	case TEX_LOWER_UNDERPANTS:	return LLUUID( gSavedSettings.getString("UIImgDefaultUnderwearUUID") );
-
-	case TEX_SKIRT:				return LLUUID( gSavedSettings.getString("UIImgDefaultSkirtUUID") );
-
-	default:					return IMG_DEFAULT_AVATAR;
+		return IMG_DEFAULT_AVATAR;
+	}
+	else
+	{
+		return LLUUID(gSavedSettings.getString(default_image_name));
 	}
 }
 
 
+void LLVOAvatar::setInvisible(BOOL newvalue)
+{
+	if (newvalue)
+	{
+		setCompositeUpdatesEnabled(FALSE);
+		for (U32 i = 0; i < mBakedTextureData.size(); i++ )
+		{
+			setNewBakedTexture(mBakedTextureData[i].mTextureIndex, IMG_INVISIBLE);
+		}
+		gAgent.sendAgentSetAppearance();
+	}
+	else
+	{
+		setCompositeUpdatesEnabled(TRUE);
+		invalidateAll();
+		requestLayerSetUploads();
+		gAgent.sendAgentSetAppearance();
+	}
+}
 
 // Given a texture entry, determine which wearable type owns it.
 // static
-EWearableType LLVOAvatar::getTEWearableType( S32 te )
+EWearableType LLVOAvatar::getTEWearableType(ETextureIndex index )
 {
-	switch( te )
-	{
-	case TEX_UPPER_SHIRT:
-		return WT_SHIRT;
-
-	case TEX_LOWER_PANTS:
-		return WT_PANTS;
-
-	case TEX_EYES_IRIS:
-		return WT_EYES;
-
-	case TEX_HAIR:
-		return WT_HAIR;
-	
-	case TEX_HEAD_BODYPAINT:
-	case TEX_UPPER_BODYPAINT:
-	case TEX_LOWER_BODYPAINT:
-		return WT_SKIN;
-
-	case TEX_LOWER_SHOES:
-		return WT_SHOES;
-
-	case TEX_LOWER_SOCKS:
-		return WT_SOCKS;
-
-	case TEX_UPPER_JACKET:
-	case TEX_LOWER_JACKET:
-		return WT_JACKET;
-
-	case TEX_UPPER_GLOVES:
-		return WT_GLOVES;
-
-	case TEX_UPPER_UNDERSHIRT:
-		return WT_UNDERSHIRT;
-
-	case TEX_LOWER_UNDERPANTS:
-		return WT_UNDERPANTS;
-
-	case TEX_SKIRT:
-		return WT_SKIRT;
-
-	default:
-		return WT_INVALID;
-	}
+	/* switch(index)
+		case TEX_UPPER_SHIRT:
+			return WT_SHIRT; */
+	return LLVOAvatarDictionary::getInstance()->getTexture(index)->mWearableType;
 }
 
 // Unlike most wearable functions, this works for both self and other.
@@ -8371,57 +7530,68 @@ BOOL LLVOAvatar::isWearingWearableType( EWearableType type )
 {
 	if (mIsDummy) return TRUE;
 
-	ETextureIndex indicator_te;
 	switch( type )
 	{
-		case WT_SHIRT:
-			indicator_te = TEX_UPPER_SHIRT;
-			break;
-
-		case WT_PANTS: 
-			indicator_te = TEX_LOWER_PANTS;
-			break;
-
-		case WT_SHOES:
-			indicator_te = TEX_LOWER_SHOES;
-			break;
-
-		case WT_SOCKS:
-			indicator_te = TEX_LOWER_SOCKS;
-			break;
-
-		case WT_JACKET:
-			indicator_te = TEX_UPPER_JACKET;
-			// Note: no need to test both upper and lower jacket
-			break;
-
-		case WT_GLOVES:
-			indicator_te = TEX_UPPER_GLOVES;
-			break;
-
-		case WT_UNDERSHIRT:
-			indicator_te = TEX_UPPER_UNDERSHIRT;
-			break;
-
-		case WT_UNDERPANTS:
-			indicator_te = TEX_LOWER_UNDERPANTS;
-			break;
-
-		case WT_SKIRT:
-			indicator_te = TEX_SKIRT;
-			break;
-		
 		case WT_SHAPE:
 		case WT_SKIN:
 		case WT_HAIR:
 		case WT_EYES:
 			return TRUE;  // everyone has all bodyparts
-
 		default:
-			return FALSE;
+			break; // Do nothing
 	}
 
-	return ( getTEImage(indicator_te)->getID() != IMG_DEFAULT_AVATAR );
+	/* switch(type)
+		case WT_SHIRT:
+			indicator_te = TEX_UPPER_SHIRT; */
+	for (LLVOAvatarDictionary::texture_map_t::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+		 tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+		 tex_iter++)
+	{
+		const LLVOAvatarDefines::ETextureIndex index = tex_iter->first;
+		const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = tex_iter->second;
+		if (text_dict->mWearableType == type)
+		{
+			// If you're checking your own clothing, check the component texture
+			if (mIsSelf)
+			{
+				if (isTextureDefined(index))
+				{
+					return TRUE;
+				}
+				else
+				{
+					return FALSE;
+				}
+			}
+
+			// If you're checking another avatar's clothing, you don't have component textures.
+			// Thus, you must check to see if the corresponding baked texture is defined.
+			// NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing
+			// this works for detecting a skirt (most important), but is ineffective at any piece of clothing that
+			// gets baked into a texture that always exists (upper or lower).
+			const std::string name = text_dict->mName;
+			for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
+				iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
+				iter++)
+			{
+				const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second;
+				if (baked_dict->mName == name)
+				{
+					if (isTextureDefined(baked_dict->mTextureIndex))
+					{
+						return TRUE;
+					}
+					else
+					{
+						return FALSE;
+					}
+				}
+			}
+			return FALSE;
+		}
+	}
+	return FALSE;
 }
 
 
@@ -8446,12 +7616,12 @@ void LLVOAvatar::clampAttachmentPositions()
 	}
 }
 
-BOOL LLVOAvatar::hasHUDAttachment()
+BOOL LLVOAvatar::hasHUDAttachment() const
 {
-	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
+	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); 
 		 iter != mAttachmentPoints.end(); )
 	{
-		attachment_map_t::iterator curiter = iter++;
+		attachment_map_t::const_iterator curiter = iter++;
 		LLViewerJointAttachment* attachment = curiter->second;
 		if (attachment->getIsHUDAttachment() && attachment->getObject())
 		{
@@ -8461,13 +7631,13 @@ BOOL LLVOAvatar::hasHUDAttachment()
 	return FALSE;
 }
 
-LLBBox LLVOAvatar::getHUDBBox()
+LLBBox LLVOAvatar::getHUDBBox() const
 {
 	LLBBox bbox;
-	for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); 
+	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); 
 		 iter != mAttachmentPoints.end(); )
 	{
-		attachment_map_t::iterator curiter = iter++;
+		attachment_map_t::const_iterator curiter = iter++;
 		LLViewerJointAttachment* attachment = curiter->second;
 		if (attachment->getIsHUDAttachment() && attachment->getObject())
 		{
@@ -8503,50 +7673,23 @@ void LLVOAvatar::onFirstTEMessageReceived()
 	{
 		mFirstTEMessageReceived = TRUE;
 
-		BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-		BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-		BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-		BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-		BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR );
-
-		// Use any baked textures that we have even if they haven't downloaded yet.
-		// (That is, don't do a transition from unbaked to baked.)
-		if( head_baked )
-		{
-			mLastHeadBakedID = getTEImage( TEX_HEAD_BAKED )->getID();
-			LLViewerImage* image = getTEImage( TEX_HEAD_BAKED );
-			image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));	
-			image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) );
-		}
-
-		if( upper_baked )
-		{
-			mLastUpperBodyBakedID = getTEImage( TEX_UPPER_BAKED )->getID();
-			LLViewerImage* image = getTEImage( TEX_UPPER_BAKED );
-			image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));	
-			image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) );
-		}
-		
-		if( lower_baked )
-		{
-			mLastLowerBodyBakedID = getTEImage( TEX_LOWER_BAKED )->getID();
-			LLViewerImage* image = getTEImage( TEX_LOWER_BAKED );
-			image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));	
-			image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) );
-		}
-
-		if( eyes_baked )
-		{
-			mLastEyesBakedID = getTEImage( TEX_EYES_BAKED )->getID();
-			LLViewerImage* image = getTEImage( TEX_EYES_BAKED );
-			image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) );
-		}
-
-		if( skirt_baked )
+		for (U32 i = 0; i < mBakedTextureData.size(); i++)
 		{
-			mLastSkirtBakedID = getTEImage( TEX_SKIRT_BAKED )->getID();
-			LLViewerImage* image = getTEImage( TEX_SKIRT_BAKED );
-			image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) );
+			bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex);
+
+			// Use any baked textures that we have even if they haven't downloaded yet.
+			// (That is, don't do a transition from unbaked to baked.)
+			if (layer_baked)
+			{
+				LLViewerImage* image = getTEImage( mBakedTextureData[i].mTextureIndex );
+				mBakedTextureData[i].mLastTextureIndex = image->getID();
+				// If we have more than one texture for the other baked layers, we'll want to call this for them too.
+				if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
+				{
+					image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
+				}
+				image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) );
+			}
 		}
 
 		updateMeshTextures();
@@ -8593,11 +7736,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	unpackTEMessage(mesgsys, _PREHASH_ObjectData);
 //	dumpAvatarTEs( "POST processAvatarAppearance()" );
 
-//	llinfos << "Received AvatarAppearance: " << (mIsSelf ? "(self): " : "(other): " ) << 
-//		(( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR )  ? "HEAD " : "head " ) <<
-//		(( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "UPPER " : "upper " ) <<
-//		(( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "LOWER " : "lower " ) <<
-//		(( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR )  ? "EYES" : "eyes" ) << llendl;
+	//llinfos << "Received AvatarAppearance: " << (mIsSelf ? "(self): " : "(other): ")  << std::endl <<
+	//	(isTextureDefined(TEX_HEAD_BAKED)  ? "HEAD " : "head " ) << (getTEImage(TEX_HEAD_BAKED)->getID()) << std::endl <<
+	//	(isTextureDefined(TEX_UPPER_BAKED) ? "UPPER " : "upper " ) << (getTEImage(TEX_UPPER_BAKED)->getID()) << std::endl <<
+	//	(isTextureDefined(TEX_LOWER_BAKED) ? "LOWER " : "lower " ) << (getTEImage(TEX_LOWER_BAKED)->getID()) << std::endl <<
+	//	(isTextureDefined(TEX_SKIRT_BAKED) ? "SKIRT " : "skirt " ) << (getTEImage(TEX_SKIRT_BAKED)->getID()) << std::endl <<
+	//	(isTextureDefined(TEX_HAIR_BAKED) ? "HAIR" : "hair " ) << (getTEImage(TEX_HAIR_BAKED)->getID()) << std::endl <<
+	//	(isTextureDefined(TEX_EYES_BAKED)  ? "EYES" : "eyes" ) << (getTEImage(TEX_EYES_BAKED)->getID()) << llendl ;
  
 	if( !mFirstTEMessageReceived )
 	{
@@ -8605,6 +7750,12 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 	}
 
 	setCompositeUpdatesEnabled( FALSE );
+
+	if (!mIsSelf)
+	{
+		releaseUnnecessaryTextures();
+	}
+	
 	updateMeshTextures(); // enables updates for laysets without baked textures.
 
 	// parse visual params
@@ -8652,7 +7803,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
 						param->setAnimationTarget(newWeight, FALSE);
 					}
 				}
-				
 				param = getNextVisualParam();
 			}
 		}
@@ -8726,28 +7876,20 @@ void LLVOAvatar::getAnimNames( LLDynamicArray<std::string>* names )
 
 void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
 {
-	//llinfos << "onBakedTextureMasksLoaded: " << src_vi->getID() << llendl;
-	LLMemType mt(LLMemType::MTYPE_AVATAR);
-	
-	LLUUID id = src_vi->getID();
+	if (!userdata) return;
 
-	if (!userdata)
-	{
-		return;
-	}
+	//llinfos << "onBakedTextureMasksLoaded: " << src_vi->getID() << llendl;
+	const LLMemType mt(LLMemType::MTYPE_AVATAR);
+	const LLUUID id = src_vi->getID();
  
 	LLTextureMaskData* maskData = (LLTextureMaskData*) userdata;
 	LLVOAvatar* self = (LLVOAvatar*) gObjectList.findObject( maskData->mAvatarID );
 
 	// if discard level is 2 less than last discard level we processed, or we hit 0,
 	// then generate morph masks
-	if( self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0) )
+	if(self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0))
 	{
-		LLViewerImage* head_baked =		self->getTEImage( TEX_HEAD_BAKED );
-		LLViewerImage* upper_baked =	self->getTEImage( TEX_UPPER_BAKED );
-		LLViewerImage* lower_baked =	self->getTEImage( TEX_LOWER_BAKED );
-	
-		if( aux_src && aux_src->getComponents() == 1 )
+		if(aux_src && aux_src->getComponents() == 1)
 		{
 			if (!aux_src->getData())
 			{
@@ -8770,70 +7912,49 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
 
 			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
 
-			if( id == head_baked->getID() )
-			{
-				if (self->mHeadLayerSet)
-				{
-					//llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl;
-					self->mHeadLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
-					maskData->mLastDiscardLevel = discard_level;
-					self->mHeadMaskDiscard = discard_level;
-					if (self->mHeadMaskTexName)
-					{
-						LLImageGL::deleteTextures(1, &self->mHeadMaskTexName);
-					}
-					self->mHeadMaskTexName = gl_name;
-				}
-				else
-				{
-					llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl;
-				}
-			}
-			else
-			if( id == upper_baked->getID() )
-			{
-				if ( self->mUpperBodyLayerSet)
-				{
-					//llinfos << "onBakedTextureMasksLoaded for upper body " << id << " discard = " << discard_level << llendl;
-					self->mUpperBodyLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
-					maskData->mLastDiscardLevel = discard_level;
-					self->mUpperMaskDiscard = discard_level;
-					if (self->mUpperMaskTexName)
-					{
-						LLImageGL::deleteTextures(1, &self->mUpperMaskTexName);
-					}
-					self->mUpperMaskTexName = gl_name;
-				}
-				else
-				{
-					llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl;
-				}
-			}
-			else
-			if( id == lower_baked->getID() )
+			/* if( id == head_baked->getID() )
+			     if (self->mBakedTextureData[BAKED_HEAD].mTexLayerSet)
+				     //llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl;
+					 self->mBakedTextureData[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
+					 maskData->mLastDiscardLevel = discard_level; */
+			bool found_texture_id = false;
+			for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+				 iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+				 iter++)
 			{
-				if ( self->mLowerBodyLayerSet )
+
+				const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
+				if (text_dict->mIsUsedByBakedTexture)
 				{
-					//llinfos << "onBakedTextureMasksLoaded for lower body " << id << " discard = " << discard_level << llendl;
-					self->mLowerBodyLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
-					maskData->mLastDiscardLevel = discard_level;
-					self->mLowerMaskDiscard = discard_level;
-					if (self->mLowerMaskTexName)
+					const ETextureIndex texture_index = iter->first;
+					const LLViewerImage *baked_img = self->getTEImage(texture_index);
+					if (id == baked_img->getID())
 					{
-						LLImageGL::deleteTextures(1, &self->mLowerMaskTexName);
+						const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
+						if (self->mBakedTextureData[baked_index].mTexLayerSet)
+						{
+							//llinfos << "onBakedTextureMasksLoaded for " << text_dict->mName << " " << id << " discard = " << discard_level << llendl;
+							self->mBakedTextureData[baked_index].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
+							maskData->mLastDiscardLevel = discard_level;
+							if (self->mBakedTextureData[baked_index].mMaskTexName)
+							{
+								LLImageGL::deleteTextures(1, &(self->mBakedTextureData[baked_index].mMaskTexName));
+							}
+							self->mBakedTextureData[baked_index].mMaskTexName = gl_name;
+						}
+						else
+						{
+							llwarns << "onBakedTextureMasksLoaded: no LayerSet for " << text_dict->mName << "." << llendl;
+						}
+						found_texture_id = true;
+						break;
 					}
-					self->mLowerMaskTexName = gl_name;
-				}
-				else
-				{
-					llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl;
 				}
 			}
-			else
+			if (!found_texture_id)
 			{
 				llinfos << "onBakedTextureMasksLoaded(): unexpected image id: " << id << llendl;
 			}
-
 			self->dirtyMesh();
 		}
 		else
@@ -8848,7 +7969,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
 	{
 		delete maskData;
 	}
-
 }
 
 // static
@@ -8895,109 +8015,34 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLIma
 // Called when baked texture is loaded and also when we start up with a baked texture
 void LLVOAvatar::useBakedTexture( const LLUUID& id )
 {
-//	llinfos << "useBakedTexture" << llendl;
-	LLViewerImage* head_baked =		getTEImage( TEX_HEAD_BAKED );
-	LLViewerImage* upper_baked =	getTEImage( TEX_UPPER_BAKED );
-	LLViewerImage* lower_baked =	getTEImage( TEX_LOWER_BAKED );
-	LLViewerImage* eyes_baked =		getTEImage( TEX_EYES_BAKED );
-	LLViewerImage* skirt_baked =	getTEImage( TEX_SKIRT_BAKED );
-
-	if( id == head_baked->getID() )
-	{
-		mHeadBakedLoaded = TRUE;
-		
-		mLastHeadBakedID = id;
-		mHeadMesh0.setTexture( head_baked );
-		mHeadMesh1.setTexture( head_baked );
-		mHeadMesh2.setTexture( head_baked );
-		mHeadMesh3.setTexture( head_baked );
-		mHeadMesh4.setTexture( head_baked );
-		mEyeLashMesh0.setTexture( head_baked );
-		if( mHeadLayerSet )
-		{
-			mHeadLayerSet->destroyComposite();
-		}
-		setLocalTexture( LOCTEX_HEAD_BODYPAINT,		getTEImage( TEX_HEAD_BODYPAINT ),	TRUE );
-	}
-	else
-	if( id == upper_baked->getID() )
-	{
-		mUpperBakedLoaded = TRUE;
-
-		mLastUpperBodyBakedID = id;
-		mUpperBodyMesh0.setTexture( upper_baked );
-		mUpperBodyMesh1.setTexture( upper_baked );
-		mUpperBodyMesh2.setTexture( upper_baked );
-		mUpperBodyMesh3.setTexture( upper_baked );
-		mUpperBodyMesh4.setTexture( upper_baked );
-		if( mUpperBodyLayerSet )
-		{
-			mUpperBodyLayerSet->destroyComposite();
-		}
-
-		setLocalTexture( LOCTEX_UPPER_SHIRT,		getTEImage( TEX_UPPER_SHIRT ),		TRUE );
-		setLocalTexture( LOCTEX_UPPER_BODYPAINT,	getTEImage( TEX_UPPER_BODYPAINT ),	TRUE );
-		setLocalTexture( LOCTEX_UPPER_JACKET,		getTEImage( TEX_UPPER_JACKET ),		TRUE );
-		setLocalTexture( LOCTEX_UPPER_GLOVES,		getTEImage( TEX_UPPER_GLOVES ),		TRUE );
-		setLocalTexture( LOCTEX_UPPER_UNDERSHIRT,	getTEImage( TEX_UPPER_UNDERSHIRT ),	TRUE );
-	}
-	else
-	if( id == lower_baked->getID() )
-	{
-		mLowerBakedLoaded = TRUE;
-
-		mLastLowerBodyBakedID = id;
-		mLowerBodyMesh0.setTexture( lower_baked );
-		mLowerBodyMesh1.setTexture( lower_baked );
-		mLowerBodyMesh2.setTexture( lower_baked );
-		mLowerBodyMesh3.setTexture( lower_baked );
-		mLowerBodyMesh4.setTexture( lower_baked );
-		if( mLowerBodyLayerSet )
-		{
-			mLowerBodyLayerSet->destroyComposite();
-		}
-
-		setLocalTexture( LOCTEX_LOWER_PANTS,		getTEImage( TEX_LOWER_PANTS ),		TRUE );
-		setLocalTexture( LOCTEX_LOWER_BODYPAINT,	getTEImage( TEX_LOWER_BODYPAINT ),	TRUE );
-		setLocalTexture( LOCTEX_LOWER_SHOES,		getTEImage( TEX_LOWER_SHOES ),		TRUE );
-		setLocalTexture( LOCTEX_LOWER_SOCKS,		getTEImage( TEX_LOWER_SOCKS ),		TRUE );
-		setLocalTexture( LOCTEX_LOWER_JACKET,		getTEImage( TEX_LOWER_JACKET ),		TRUE );
-		setLocalTexture( LOCTEX_LOWER_UNDERPANTS,	getTEImage( TEX_LOWER_UNDERPANTS ),	TRUE );
-	}
-	else
-	if( id == eyes_baked->getID() )
-	{
-		mEyesBakedLoaded = TRUE;
-
-		mLastEyesBakedID = id;
-		mEyeBallLeftMesh0.setTexture(  eyes_baked );
-		mEyeBallLeftMesh1.setTexture(  eyes_baked );
-		mEyeBallRightMesh0.setTexture( eyes_baked );
-		mEyeBallRightMesh1.setTexture( eyes_baked );
-		if( mEyesLayerSet )
-		{
-			mEyesLayerSet->destroyComposite();
-		}
-
-		setLocalTexture( LOCTEX_EYES_IRIS,			getTEImage( TEX_EYES_IRIS ), TRUE );
-	}
-	else
-	if( id == skirt_baked->getID() )
+	/* if(id == head_baked->getID())
+		 mHeadBakedLoaded = TRUE;
+		 mLastHeadBakedID = id;
+		 mHeadMesh0.setTexture( head_baked );
+		 mHeadMesh1.setTexture( head_baked ); */
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		mSkirtBakedLoaded = TRUE;
-
-		mLastSkirtBakedID = id;
-		mSkirtMesh0.setTexture( skirt_baked );
-		mSkirtMesh1.setTexture( skirt_baked );
-		mSkirtMesh2.setTexture( skirt_baked );
-		mSkirtMesh3.setTexture( skirt_baked );
-		mSkirtMesh4.setTexture( skirt_baked );
-		if( mSkirtLayerSet )
+		LLViewerImage* image_baked = getTEImage( mBakedTextureData[i].mTextureIndex );
+		if (id == image_baked->getID())
 		{
-			mSkirtLayerSet->destroyComposite();
+			mBakedTextureData[i].mIsLoaded = true;
+			mBakedTextureData[i].mLastTextureIndex = id;
+			for (U32 k = 0; k < mBakedTextureData[i].mMeshes.size(); k++)
+			{
+				mBakedTextureData[i].mMeshes[k]->setTexture( image_baked );
+			}
+			if (mBakedTextureData[i].mTexLayerSet)
+			{
+				mBakedTextureData[i].mTexLayerSet->destroyComposite();
+			}
+			const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
+			for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
+				 local_tex_iter != baked_dict->mLocalTextures.end();
+				 local_tex_iter++)
+			{
+				setLocalTexture(*local_tex_iter, getTEImage(*local_tex_iter), TRUE);
+			}
 		}
-
-		setLocalTexture( LOCTEX_SKIRT,				getTEImage( TEX_SKIRT ), TRUE );
 	}
 
 	dirtyMesh();
@@ -9036,11 +8081,11 @@ void LLVOAvatar::dumpArchetypeXML( void* )
 			}
 		}
 
-		for( S32 te = 0; te < TEX_NUM_ENTRIES; te++ )
+		for(U8 te = 0; te < TEX_NUM_INDICES; te++)
 		{
-			if( LLVOAvatar::getTEWearableType( te ) == type )
+			if( LLVOAvatar::getTEWearableType((ETextureIndex)te) == type )
 			{
-				LLViewerImage* te_image = avatar->getTEImage( te );
+				LLViewerImage* te_image = avatar->getTEImage((ETextureIndex)te);
 				if( te_image )
 				{
 					std::string uuid_str;
@@ -9093,39 +8138,39 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank()
 	return 0;
 }
 
+struct CompareScreenAreaGreater
+{
+	bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs)
+	{
+		return lhs->getPixelArea() > rhs->getPixelArea();
+	}
+};
+
 // static
 void LLVOAvatar::cullAvatarsByPixelArea()
 {
 	std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater());
 	
 	// Update the avatars that have changed status
-	S32 comp_rank = 1;
 	U32 rank = 0;
 	for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
 		iter != LLCharacter::sInstances.end(); ++iter)
 	{
 		LLVOAvatar* inst = (LLVOAvatar*) *iter;
 		BOOL culled;
-		if( inst->isDead() )
-		{
-			culled = TRUE;
-		}
-		else if( inst->isSelf() || inst->isFullyBaked() )
+		if (inst->isSelf() || inst->isFullyBaked())
 		{
 			culled = FALSE;
 		}
-		else
+		else 
 		{
-			culled = (comp_rank > LLVOAvatar::sMaxOtherAvatarsToComposite) || (inst->mPixelArea < MIN_PIXEL_AREA_FOR_COMPOSITE);
-			comp_rank++;
+			culled = TRUE;
 		}
 
-		if( inst->mCulled != culled )
+		if (inst->mCulled != culled)
 		{
 			inst->mCulled = culled;
-
 			lldebugs << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled" ) << llendl;
-
 			inst->updateMeshTextures();
 		}
 
@@ -9140,9 +8185,9 @@ void LLVOAvatar::cullAvatarsByPixelArea()
 	}
 
 	S32 grey_avatars = 0;
-	if( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) )
+	if ( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) )
 	{
-		LLVOAvatar::deleteCachedImages();
+		LLVOAvatar::deleteCachedImages(false);
 	}
 	else
 	{
@@ -9174,52 +8219,31 @@ const LLUUID& LLVOAvatar::grabLocalTexture(ETextureIndex index)
 BOOL LLVOAvatar::canGrabLocalTexture(ETextureIndex index)
 {
 	// Check if the texture hasn't been baked yet.
-	if ( getTEImage( index )->getID() == IMG_DEFAULT_AVATAR )
+	if (!isTextureDefined(index))
 	{
 		lldebugs << "getTEImage( " << (U32) index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl;
 		return FALSE;
 	}
 
+	if (gAgent.isGodlike())
+		return TRUE;
+
 	// Check permissions of textures that show up in the
 	// baked texture.  We don't want people copying people's
 	// work via baked textures.
-	std::vector<ETextureIndex> textures;
-	switch (index)
-	{
-	case TEX_EYES_BAKED:
-		textures.push_back(TEX_EYES_IRIS);
-		break;
-	case TEX_HEAD_BAKED:
-		textures.push_back(TEX_HEAD_BODYPAINT);
-		break;
-	case TEX_UPPER_BAKED:
-		textures.push_back(TEX_UPPER_BODYPAINT);
-		textures.push_back(TEX_UPPER_UNDERSHIRT);
-		textures.push_back(TEX_UPPER_SHIRT);
-		textures.push_back(TEX_UPPER_JACKET);
-		textures.push_back(TEX_UPPER_GLOVES);
-		break;
-	case TEX_LOWER_BAKED:
-		textures.push_back(TEX_LOWER_BODYPAINT);
-		textures.push_back(TEX_LOWER_UNDERPANTS);
-		textures.push_back(TEX_LOWER_PANTS);
-		textures.push_back(TEX_LOWER_JACKET);
-		textures.push_back(TEX_LOWER_SOCKS);
-		textures.push_back(TEX_LOWER_SHOES);
-		break;
-	case TEX_SKIRT_BAKED:
-		textures.push_back(TEX_SKIRT);
-		break;
-	default:
-		return FALSE;
-		break;
-	}
-
-	std::vector<ETextureIndex>::iterator iter = textures.begin();
-	std::vector<ETextureIndex>::iterator end  = textures.end();
-	for (; iter != end; ++iter)
-	{
-		ETextureIndex t_index = (*iter);
+	/* switch(index)
+		case TEX_EYES_BAKED:
+			textures.push_back(TEX_EYES_IRIS); */
+	const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
+	if (!text_dict->mIsUsedByBakedTexture) return FALSE;
+
+	const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
+	const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index);
+	for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin();
+		 iter != baked_dict->mLocalTextures.end();
+		 iter++)
+	{
+		const ETextureIndex t_index = (*iter);
 		lldebugs << "Checking index " << (U32) t_index << llendl;
 		const LLUUID& texture_id = getTEImage( t_index )->getID();
 		if (texture_id != IMG_DEFAULT_AVATAR)
@@ -9266,62 +8290,43 @@ void LLVOAvatar::dumpLocalTextures()
 {
 	llinfos << "Local Textures:" << llendl;
 
-	const char* names[] = {
-		"Shirt     ",
-		"UpperTatoo",
-		"Pants     ",
-		"LowerTatoo",
-		"Head Tatoo",
-		"Shoes     ",
-		"Socks     ",
-		"Upper Jckt",
-		"Lower Jckt",
-		"Gloves    ",
-		"Undershirt",
-		"Underpants",
-		"Iris      ",
-		"Skirt      "};
-
-	ETextureIndex baked_equiv[] = {
-		TEX_UPPER_BAKED,
-		TEX_UPPER_BAKED,
-		TEX_LOWER_BAKED,
-		TEX_LOWER_BAKED,
-		TEX_HEAD_BAKED,
-		TEX_LOWER_BAKED,
-		TEX_LOWER_BAKED,
-		TEX_UPPER_BAKED,
-		TEX_LOWER_BAKED,
-		TEX_UPPER_BAKED,
+	/* ETextureIndex baked_equiv[] = {
 		TEX_UPPER_BAKED,
-		TEX_LOWER_BAKED,
-		TEX_EYES_BAKED,
-		TEX_SKIRT_BAKED };
+	   if (isTextureDefined(baked_equiv[i])) */
+	for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+		 iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+		 iter++)
+	{
+		const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
+		if (!text_dict->mIsLocalTexture || !text_dict->mIsUsedByBakedTexture)
+			continue;
 
+		const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
+		const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex;
 
-	for( S32 i = 0; i < LOCTEX_NUM_ENTRIES; i++ )
-	{
-		if( getTEImage( baked_equiv[i] )->getID() != IMG_DEFAULT_AVATAR )
+		const std::string &name = text_dict->mName;
+		const LocalTextureData &local_tex_data = mLocalTextureData[iter->first];
+		if (isTextureDefined(baked_equiv))
 		{
 #if LL_RELEASE_FOR_DOWNLOAD
 			// End users don't get to trivially see avatar texture IDs, makes textures
 			// easier to steal. JC
-			llinfos << "LocTex " << names[i] << ": Baked " << llendl;
+			llinfos << "LocTex " << name << ": Baked " << llendl;
 #else
-			llinfos << "LocTex " << names[i] << ": Baked " << getTEImage( baked_equiv[i] )->getID() << llendl;
+			llinfos << "LocTex " << name << ": Baked " << getTEImage( baked_equiv )->getID() << llendl;
 #endif
 		}
-		else if (mLocalTexture[i].notNull())
+		else if (local_tex_data.mImage.notNull())
 		{
-			if( mLocalTexture[i]->getID() == IMG_DEFAULT_AVATAR )
+			if( local_tex_data.mImage->getID() == IMG_DEFAULT_AVATAR )
 			{
-				llinfos << "LocTex " << names[i] << ": None" << llendl;
+				llinfos << "LocTex " << name << ": None" << llendl;
 			}
 			else
 			{
-				LLViewerImage* image = mLocalTexture[i];
+				const LLViewerImage* image = local_tex_data.mImage;
 
-				llinfos << "LocTex " << names[i] << ": "
+				llinfos << "LocTex " << name << ": "
 						<< "Discard " << image->getDiscardLevel() << ", "
 						<< "(" << image->getWidth() << ", " << image->getHeight() << ") " 
 #if !LL_RELEASE_FOR_DOWNLOAD
@@ -9335,7 +8340,7 @@ void LLVOAvatar::dumpLocalTextures()
 		}
 		else
 		{
-			llinfos << "LocTex " << names[i] << ": No LLViewerImage" << llendl;
+			llinfos << "LocTex " << name << ": No LLViewerImage" << llendl;
 		}
 	}
 }
@@ -9354,30 +8359,25 @@ void LLVOAvatar::startAppearanceAnimation(BOOL set_by_user, BOOL play_sound)
 
 void LLVOAvatar::removeMissingBakedTextures()
 {	
-	if (!mIsSelf)
-	{
-		return;
-	}
-	BOOL removed = FALSE;
+	if (!mIsSelf) return;
 
-	for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ )
+	BOOL removed = FALSE;
+	for (U32 i = 0; i < mBakedTextureData.size(); i++)
 	{
-		S32 te = sBakedTextureIndices[i];
-
-		if( getTEImage( te )->isMissingAsset() )
+		const S32 te = mBakedTextureData[i].mTextureIndex;
+		if (getTEImage(te)->isMissingAsset())
 		{
-			setTEImage( te, gImageList.getImage(IMG_DEFAULT_AVATAR) );
+			setTEImage(te, gImageList.getImage(IMG_DEFAULT_AVATAR));
 			removed = TRUE;
 		}
 	}
 
-	if( removed )
+	if (removed)
 	{
-		invalidateComposite( mEyesLayerSet,			FALSE );
-		invalidateComposite( mHeadLayerSet,			FALSE );
-		invalidateComposite( mUpperBodyLayerSet,	FALSE );
-		invalidateComposite( mLowerBodyLayerSet,	FALSE );
-		invalidateComposite( mSkirtLayerSet,		FALSE );
+		for(U32 i = 0; i < mBakedTextureData.size(); i++)
+		{
+			invalidateComposite(mBakedTextureData[i].mTexLayerSet, FALSE);
+		}
 		updateMeshTextures();
 		requestLayerSetUploads();
 	}
@@ -9385,15 +8385,15 @@ void LLVOAvatar::removeMissingBakedTextures()
 
 
 //-----------------------------------------------------------------------------
-// LLVOAvatarInfo
+// LLVOAvatarXmlInfo
 //-----------------------------------------------------------------------------
 
-LLVOAvatarInfo::LLVOAvatarInfo()
+LLVOAvatarXmlInfo::LLVOAvatarXmlInfo()
 	: mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0)
 {
 }
 
-LLVOAvatarInfo::~LLVOAvatarInfo()
+LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo()
 {
 	std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer());
 	std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer());		
@@ -9514,7 +8514,7 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
 //-----------------------------------------------------------------------------
 // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree
 //-----------------------------------------------------------------------------
-BOOL LLVOAvatarInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
+BOOL LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
 {
 	LLXmlTreeNode* node = root->getChildByName( "skeleton" );
 	if( !node )
@@ -9620,7 +8620,7 @@ BOOL LLVOAvatarInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
 //-----------------------------------------------------------------------------
 // parseXmlMeshNodes(): parses <mesh> nodes from XML tree
 //-----------------------------------------------------------------------------
-BOOL LLVOAvatarInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
+BOOL LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
 {
 	for (LLXmlTreeNode* node = root->getChildByName( "mesh" );
 		 node;
@@ -9710,7 +8710,7 @@ BOOL LLVOAvatarInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
 //-----------------------------------------------------------------------------
 // parseXmlColorNodes(): parses <global_color> nodes from XML tree
 //-----------------------------------------------------------------------------
-BOOL LLVOAvatarInfo::parseXmlColorNodes(LLXmlTreeNode* root)
+BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
 {
 	for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" );
 		 color_node;
@@ -9772,7 +8772,7 @@ BOOL LLVOAvatarInfo::parseXmlColorNodes(LLXmlTreeNode* root)
 //-----------------------------------------------------------------------------
 // parseXmlLayerNodes(): parses <layer_set> nodes from XML tree
 //-----------------------------------------------------------------------------
-BOOL LLVOAvatarInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
+BOOL LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
 {
 	for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" );
 		 layer_node;
@@ -9796,7 +8796,7 @@ BOOL LLVOAvatarInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
 //-----------------------------------------------------------------------------
 // parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
 //-----------------------------------------------------------------------------
-BOOL LLVOAvatarInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
+BOOL LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
 {
 	LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" );
 	if( driver )
@@ -9874,41 +8874,17 @@ std::string LLVOAvatar::getFullname() const
 
 LLTexLayerSet* LLVOAvatar::getLayerSet(ETextureIndex index) const
 {
-	switch( index )
+	/* switch(index)
+		case TEX_HEAD_BAKED:
+		case TEX_HEAD_BODYPAINT:
+			return mHeadLayerSet; */
+	const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
+	if (text_dict->mIsUsedByBakedTexture)
 	{
-	case TEX_HEAD_BAKED:
-	case TEX_HEAD_BODYPAINT:
-		return mHeadLayerSet;
-
-	case TEX_UPPER_BAKED:
-	case TEX_UPPER_SHIRT:
-	case TEX_UPPER_BODYPAINT:
-	case TEX_UPPER_JACKET:
-	case TEX_UPPER_GLOVES:
-	case TEX_UPPER_UNDERSHIRT:
-		return mUpperBodyLayerSet;
-
-	case TEX_LOWER_BAKED:
-	case TEX_LOWER_PANTS:
-	case TEX_LOWER_BODYPAINT:
-	case TEX_LOWER_SHOES:
-	case TEX_LOWER_SOCKS:
-	case TEX_LOWER_JACKET:
-	case TEX_LOWER_UNDERPANTS:
-		return mLowerBodyLayerSet;
-	
-	case TEX_EYES_BAKED:
-	case TEX_EYES_IRIS:
-		return mEyesLayerSet;
-
-	case TEX_SKIRT_BAKED:
-	case TEX_SKIRT:
-		return mSkirtLayerSet;
-
-	case TEX_HAIR:
-	default:
-		return NULL;
+		const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex;
+		return mBakedTextureData[baked_index].mTexLayerSet;
 	}
+	return NULL;
 }
 
 LLHost LLVOAvatar::getObjectHost() const
@@ -9929,15 +8905,15 @@ void LLVOAvatar::updateFreezeCounter(S32 counter)
 {
 	if(counter)
 	{
-		sFreezeCounter = counter ;
+		sFreezeCounter = counter;
 	}
 	else if(sFreezeCounter > 0)
 	{
-		sFreezeCounter-- ;
+		sFreezeCounter--;
 	}
 	else
 	{
-		sFreezeCounter = 0 ;
+		sFreezeCounter = 0;
 	}
 }
 
@@ -9989,7 +8965,7 @@ void LLVOAvatar::updateImpostors()
 
 BOOL LLVOAvatar::isImpostor() const
 {
-	return (sUseImpostors && mUpdatePeriod >= VOAVATAR_IMPOSTOR_PERIOD) ? TRUE : FALSE;
+	return (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD) ? TRUE : FALSE;
 }
 
 
@@ -10018,7 +8994,7 @@ void LLVOAvatar::cacheImpostorValues()
 	getImpostorValues(mImpostorExtents, mImpostorAngle, mImpostorDistance);
 }
 
-void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance)
+void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const
 {
 	const LLVector3* ext = mDrawable->getSpatialExtents();
 	extents[0] = ext[0];
@@ -10032,6 +9008,85 @@ void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& di
 	angle.mV[2] = da;
 }
 
+void LLVOAvatar::idleUpdateRenderCost()
+{
+	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
+	{
+		return;
+	}
+
+	U32 shame = 1;
+
+	std::set<LLUUID> textures;
+
+	attachment_map_t::const_iterator iter;
+	for (iter = mAttachmentPoints.begin(); 
+		iter != mAttachmentPoints.end();
+		++iter)
+	{
+		LLViewerJointAttachment* attachment = iter->second;
+		LLViewerObject* object = attachment->getObject();
+		if (object && !object->isHUDAttachment())
+		{
+			LLDrawable* drawable = object->mDrawable;
+			if (drawable)
+			{
+				shame += 10;
+				LLVOVolume* volume = drawable->getVOVolume();
+				if (volume)
+				{
+					shame += calc_shame(volume, textures);
+				}
+			}
+		}
+	}	
+
+	shame += textures.size() * 5;
+
+	setDebugText(llformat("%d", shame));
+	F32 green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f);
+	F32 red = llmin((F32) shame/1024.f, 1.f);
+	mText->setColor(LLColor4(red,green,0,1));
+}
+
+// static
+BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index)
+{
+	if (index < 0 || index >= TEX_NUM_INDICES) return false;
+	return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsLocalTexture;
+}
+
+// static
+BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index)
+{
+	if (index < 0 || index >= TEX_NUM_INDICES) return false;
+	return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsBakedTexture;
+}
+
+const std::string LLVOAvatar::getBakedStatusForPrintout() const
+{
+	std::string line;
+
+	for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+		 iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+		 iter++)
+	{
+		const ETextureIndex index = iter->first;
+		const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second;
+		if (text_dict->mIsBakedTexture)
+		{
+			line += text_dict->mName;
+			if (isTextureDefined(index))
+			{
+				line += "_baked";
+			}
+			line += " ";
+		}
+	}
+	return line;
+}
+
+
 U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
 {
 	if (!volume)
@@ -10136,45 +9191,11 @@ U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
 	return shame;
 }
 
-void LLVOAvatar::idleUpdateRenderCost()
-{
-	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
-	{
-		return;
-	}
-
-	U32 shame = 1;
-
-	std::set<LLUUID> textures;
-
-	attachment_map_t::const_iterator iter;
-	for (iter = mAttachmentPoints.begin(); 
-		iter != mAttachmentPoints.end();
-		++iter)
-	{
-		LLViewerJointAttachment* attachment = iter->second;
-		LLViewerObject* object = attachment->getObject();
-		if (object && !object->isHUDAttachment())
-		{
-			LLDrawable* drawable = object->mDrawable;
-			if (drawable)
-			{
-				shame += 10;
-				LLVOVolume* volume = drawable->getVOVolume();
-				if (volume)
-				{
-					shame += calc_shame(volume, textures);
-				}
-			}
-		}
-	}	
-
-	shame += textures.size() * 5;
+//-----------------------------------------------------------------------------
+// Utility functions
+//-----------------------------------------------------------------------------
 
-	setDebugText(llformat("%d", shame));
-	F32 green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f);
-	F32 red = llmin((F32) shame/1024.f, 1.f);
-	mText->setColor(LLColor4(red,green,0,1));
+F32 calc_bouncy_animation(F32 x)
+{
+	return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f;
 }
-
-
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 14f7bd6dcc..bdb32319f8 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -1,4 +1,4 @@
-/** 
+/**
  * @file llvoavatar.h
  * @brief Declaration of LLVOAvatar class which is a derivation fo
  * LLViewerObject
@@ -34,210 +34,40 @@
 #ifndef LL_LLVOAVATAR_H
 #define LL_LLVOAVATAR_H
 
-// May help Visual Studio avoid opening this file.
-
-#include <set>
 #include <map>
-#include <algorithm>
 #include <deque>
+#include <string>
+#include <vector>
 
 #include "llchat.h"
 #include "llviewerobject.h"
-#include "lljointsolverrp3.h"
+#include "llcharacter.h"
 #include "llviewerjointmesh.h"
 #include "llviewerjointattachment.h"
-#include "llcharacter.h"
-#include "material_codes.h"
-#include "llanimationstates.h"
-#include "v4coloru.h"
-#include "llstring.h"
-#include "llframetimer.h"
-#include "llxmltree.h"
-#include "llwearable.h"
 #include "llrendertarget.h"
+#include "llwearable.h"
+#include "llvoavatardefines.h"
+
+extern const LLUUID ANIM_AGENT_BODY_NOISE;
+extern const LLUUID ANIM_AGENT_BREATHE_ROT;
+extern const LLUUID ANIM_AGENT_EDITING;
+extern const LLUUID ANIM_AGENT_EYE;
+extern const LLUUID ANIM_AGENT_FLY_ADJUST;
+extern const LLUUID ANIM_AGENT_HAND_MOTION;
+extern const LLUUID ANIM_AGENT_HEAD_ROT;
+extern const LLUUID ANIM_AGENT_PELVIS_FIX;
+extern const LLUUID ANIM_AGENT_TARGET;
+extern const LLUUID ANIM_AGENT_WALK_ADJUST;
 
-//Ventrella
-//#include "llvoiceclient.h"
-#include "llvoicevisualizer.h"
-//End Ventrella
-
-const S32 VOAVATAR_SCRATCH_TEX_WIDTH = 512;
-const S32 VOAVATAR_SCRATCH_TEX_HEIGHT = 512;
-const S32 VOAVATAR_IMPOSTOR_PERIOD = 2;
-
-const LLUUID ANIM_AGENT_BODY_NOISE		=	LLUUID("9aa8b0a6-0c6f-9518-c7c3-4f41f2c001ad"); //"body_noise"
-const LLUUID ANIM_AGENT_BREATHE_ROT	=	LLUUID("4c5a103e-b830-2f1c-16bc-224aa0ad5bc8");  //"breathe_rot"
-const LLUUID ANIM_AGENT_EDITING		=	LLUUID("2a8eba1d-a7f8-5596-d44a-b4977bf8c8bb");  //"editing"
-const LLUUID ANIM_AGENT_EYE			=	LLUUID("5c780ea8-1cd1-c463-a128-48c023f6fbea");  //"eye"
-const LLUUID ANIM_AGENT_FLY_ADJUST		=	LLUUID("db95561f-f1b0-9f9a-7224-b12f71af126e");  //"fly_adjust"
-const LLUUID ANIM_AGENT_HAND_MOTION	=	LLUUID("ce986325-0ba7-6e6e-cc24-b17c4b795578");  //"hand_motion"
-const LLUUID ANIM_AGENT_HEAD_ROT		=	LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d");  //"head_rot"
-const LLUUID ANIM_AGENT_PELVIS_FIX		=	LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b");  //"pelvis_fix"
-const LLUUID ANIM_AGENT_TARGET			=	LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55");  //"target"
-const LLUUID ANIM_AGENT_WALK_ADJUST	=	LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d");  //"walk_adjust"
-
-class LLChat;
-class LLXmlTreeNode;
 class LLTexLayerSet;
-class LLTexGlobalColor;
-class LLTexGlobalColorInfo;
-class LLTexLayerSetInfo;
-class LLDriverParamInfo;
-
+class LLVoiceVisualizer;
 class LLHUDText;
 class LLHUDEffectSpiral;
+class LLTexGlobalColor;
 
-class LLVertexBufferAvatar : public LLVertexBuffer
-{
-public:
-	LLVertexBufferAvatar();
-	virtual void setupVertexBuffer(U32 data_mask) const;
-};
-
-typedef enum e_mesh_id
-{
-	MESH_ID_HAIR,
-	MESH_ID_HEAD,
-	MESH_ID_UPPER_BODY,
-	MESH_ID_LOWER_BODY,
-	MESH_ID_SKIRT
-} eMeshID;
-
-typedef enum e_render_name
-{
-	RENDER_NAME_NEVER,
-	RENDER_NAME_FADE,
-	RENDER_NAME_ALWAYS
-} eRenderName;
-
-const S32 BAKED_TEXTURE_COUNT = 5;  // number of values in ETextureIndex that are pre-composited
-
-//------------------------------------------------------------------------
-// LLVOAvatar Support classes
-//------------------------------------------------------------------------
-
-class LLVOAvatarBoneInfo
-{
-	friend class LLVOAvatar;
-	friend class LLVOAvatarSkeletonInfo;
-public:
-	LLVOAvatarBoneInfo() : mIsJoint(FALSE) {}
-	~LLVOAvatarBoneInfo()
-	{
-		std::for_each(mChildList.begin(), mChildList.end(), DeletePointer());
-	}
-	BOOL parseXml(LLXmlTreeNode* node);
-	
-protected:
-	std::string mName;
-	BOOL mIsJoint;
-	LLVector3 mPos;
-	LLVector3 mRot;
-	LLVector3 mScale;
-	LLVector3 mPivot;
-	typedef std::vector<LLVOAvatarBoneInfo*> child_list_t;
-	child_list_t mChildList;
-};
-
-class LLVOAvatarSkeletonInfo
-{
-	friend class LLVOAvatar;
-public:
-	LLVOAvatarSkeletonInfo() :
-		mNumBones(0), mNumCollisionVolumes(0) {}
-	~LLVOAvatarSkeletonInfo()
-	{
-		std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer());
-	}
-	BOOL parseXml(LLXmlTreeNode* node);
-	S32 getNumBones() { return mNumBones; }
-	S32 getNumCollisionVolumes() { return mNumCollisionVolumes; }
-	
-protected:
-	S32 mNumBones;
-	S32 mNumCollisionVolumes;
-	typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t;
-	bone_info_list_t mBoneInfoList;
-};
-
-
-//------------------------------------------------------------------------
-// LLVOAvatarInfo
-// One instance (in LLVOAvatar) with common data parsed from the XML files
-//------------------------------------------------------------------------
-class LLVOAvatarInfo
-{
-	friend class LLVOAvatar;
-public:
-	LLVOAvatarInfo();
-	~LLVOAvatarInfo();
-	
-protected:
-	BOOL 	parseXmlSkeletonNode(LLXmlTreeNode* root);
-	BOOL 	parseXmlMeshNodes(LLXmlTreeNode* root);
-	BOOL 	parseXmlColorNodes(LLXmlTreeNode* root);
-	BOOL 	parseXmlLayerNodes(LLXmlTreeNode* root);
-	BOOL 	parseXmlDriverNodes(LLXmlTreeNode* root);
-	
-	struct LLVOAvatarMeshInfo
-	{
-		typedef std::pair<LLPolyMorphTargetInfo*,BOOL> morph_info_pair_t;
-		typedef std::vector<morph_info_pair_t> morph_info_list_t;
-
-		LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {}
-		~LLVOAvatarMeshInfo()
-		{
-			morph_info_list_t::iterator iter;
-			for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++)
-			{
-				delete iter->first;
-			}
-			mPolyMorphTargetInfoList.clear();
-		}
-
-		std::string mType;
-		S32			mLOD;
-		std::string	mMeshFileName;
-		std::string	mReferenceMeshName;
-		F32			mMinPixelArea;
-		morph_info_list_t mPolyMorphTargetInfoList;
-	};
-	typedef std::vector<LLVOAvatarMeshInfo*> mesh_info_list_t;
-	mesh_info_list_t mMeshInfoList;
-
-	typedef std::vector<LLPolySkeletalDistortionInfo*> skeletal_distortion_info_list_t;
-	skeletal_distortion_info_list_t mSkeletalDistortionInfoList;
-	
-	struct LLVOAvatarAttachmentInfo
-	{
-		LLVOAvatarAttachmentInfo()
-			: mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE),
-			  mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {}
-		std::string mName;
-		std::string mJointName;
-		LLVector3 mPosition;
-		LLVector3 mRotationEuler;
-		S32 mGroup;
-		S32 mAttachmentID;
-		S32 mPieMenuSlice;
-		BOOL mVisibleFirstPerson;
-		BOOL mIsHUDAttachment;
-		BOOL mHasPosition;
-		BOOL mHasRotation;
-	};
-	typedef std::vector<LLVOAvatarAttachmentInfo*> attachment_info_list_t;
-	attachment_info_list_t mAttachmentInfoList;
-	
-	LLTexGlobalColorInfo *mTexSkinColorInfo;
-	LLTexGlobalColorInfo *mTexHairColorInfo;
-	LLTexGlobalColorInfo *mTexEyeColorInfo;
-
-	typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t;
-	layer_info_list_t mLayerInfoList;
-
-	typedef std::vector<LLDriverParamInfo*> driver_info_list_t;
-	driver_info_list_t mDriverInfoList;
-};
+class LLVOAvatarBoneInfo;
+class LLVOAvatarSkeletonInfo;
+class LLVOAvatarXmlInfo;
 
 //------------------------------------------------------------------------
 // LLVOAvatar
@@ -246,44 +76,28 @@ class LLVOAvatar :
 	public LLViewerObject,
 	public LLCharacter
 {
-protected:	
+protected:
 	virtual ~LLVOAvatar();
 
 public:
-
-	struct CompareScreenAreaGreater
-	{		
-		bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs)
-		{
-			return lhs->getPixelArea() > rhs->getPixelArea();
-		}
-	};
-
-	enum 
-	{
-		VERTEX_DATA_MASK =	(1 << LLVertexBuffer::TYPE_VERTEX) |
-							(1 << LLVertexBuffer::TYPE_NORMAL) |
-							(1 << LLVertexBuffer::TYPE_TEXCOORD0) |
-							(1 << LLVertexBuffer::TYPE_WEIGHT) |
-							(1 << LLVertexBuffer::TYPE_CLOTHWEIGHT)							
-	};
-
 	LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
 	/*virtual*/ void markDead();
+	void startDefaultMotions();
 
 	static void updateImpostors();
 
 	//--------------------------------------------------------------------
 	// LLViewerObject interface
 	//--------------------------------------------------------------------
-	static void initClass();	// Initialize data that's only inited once per class.
-	static void cleanupClass();	// Cleanup data that's only inited once per class.
+public:
+	static void initClass(); // Initialize data that's only init'd once per class.
+	static void cleanupClass();	// Cleanup data that's only init'd once per class.
 	static BOOL parseSkeletonFile(const std::string& filename);
-	virtual U32 processUpdateMessage(	LLMessageSystem *mesgsys,
-										void **user_data,
-										U32 block_num,
-										const EObjectUpdateType update_type,
-										LLDataPacker *dp);
+	virtual U32 processUpdateMessage(LLMessageSystem *mesgsys,
+									 void **user_data,
+									 U32 block_num,
+									 const EObjectUpdateType update_type,
+									 LLDataPacker *dp);
 	/*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
 	void idleUpdateVoiceVisualizer(bool voice_enabled);
 	void idleUpdateMisc(bool detailed_update);
@@ -296,12 +110,11 @@ public:
 	void idleUpdateTractorBeam();
 	void idleUpdateBelowWater();
 
+public:
 	virtual BOOL updateLOD();
-	void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; }
-	/*virtual*/ BOOL    isActive() const; // Whether this object needs to do an idleUpdate.
+	/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
 
 	// Graphical stuff for objects - maybe broken out into render class later?
-
 	U32 renderFootShadows();
 	U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255));
 	U32 renderRigid();
@@ -310,13 +123,13 @@ public:
 	void renderCollisionVolumes();
 	
 	/*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
-									  S32 face = -1,                          // which face to check, -1 = ALL_SIDES
-									  BOOL pick_transparent = FALSE,
-									  S32* face_hit = NULL,                   // which face was hit
-									  LLVector3* intersection = NULL,         // return the intersection point
-									  LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point
-									  LLVector3* normal = NULL,               // return the surface normal at the intersection point
-									  LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point
+										  S32 face = -1,                          // which face to check, -1 = ALL_SIDES
+										  BOOL pick_transparent = FALSE,
+										  S32* face_hit = NULL,                   // which face was hit
+										  LLVector3* intersection = NULL,         // return the intersection point
+										  LLVector2* tex_coord = NULL,            // return the texture coordinates of the intersection point
+										  LLVector3* normal = NULL,               // return the surface normal at the intersection point
+										  LLVector3* bi_normal = NULL             // return the surface bi-normal at the intersection point
 		);
 
 	/*virtual*/ void updateTextures(LLAgent &agent);
@@ -328,19 +141,18 @@ public:
 	void updateVisibility();
 	void updateAttachmentVisibility(U32 camera_mode);
 	void clampAttachmentPositions();
-	S32 getAttachmentCount();	// Warning: order(N) not order(1)
+	S32 getAttachmentCount(); // Warning: order(N) not order(1)
 
-	BOOL hasHUDAttachment();
-	LLBBox getHUDBBox();
-// 	void renderHUD(BOOL for_select); // old
+	// HUD functions
+	BOOL hasHUDAttachment() const;
+	LLBBox getHUDBBox() const;
 	void rebuildHUD();
 
 	/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
-	/*virtual*/ BOOL		updateGeometry(LLDrawable *drawable);
-	void updateShadowFaces();
+	/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
 
-	/*virtual*/ void		setPixelAreaAndAngle(LLAgent &agent);
-	BOOL					updateJointLODs();
+	/*virtual*/ void setPixelAreaAndAngle(LLAgent &agent);
+	BOOL updateJointLODs();
 
 	virtual void updateRegion(LLViewerRegion *regionp);
 	
@@ -352,57 +164,14 @@ public:
 	BOOL needsImpostorUpdate() const;
 	const LLVector3& getImpostorOffset() const;
 	const LLVector2& getImpostorDim() const;
-	void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance);
+	void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const;
 	void cacheImpostorValues();
 	void setImpostorDim(const LLVector2& dim);
 
-	//--------------------------------------------------------------------
-	// texture entry assignment
-	//--------------------------------------------------------------------
-	enum ETextureIndex
-	{
-		TEX_HEAD_BODYPAINT = 0,
-		TEX_UPPER_SHIRT = 1,
-		TEX_LOWER_PANTS = 2,
-		TEX_EYES_IRIS = 3,
-		TEX_HAIR = 4,
-		TEX_UPPER_BODYPAINT = 5,
-		TEX_LOWER_BODYPAINT = 6,
-		TEX_LOWER_SHOES = 7,
-		TEX_HEAD_BAKED = 8,			// Pre-composited
-		TEX_UPPER_BAKED = 9,		// Pre-composited
-		TEX_LOWER_BAKED = 10,		// Pre-composited
-		TEX_EYES_BAKED = 11,		// Pre-composited
-		TEX_LOWER_SOCKS = 12,
-		TEX_UPPER_JACKET = 13,
-		TEX_LOWER_JACKET = 14,
-		TEX_UPPER_GLOVES = 15,
-		TEX_UPPER_UNDERSHIRT = 16,
-		TEX_LOWER_UNDERPANTS = 17,
-		TEX_SKIRT = 18,
-		TEX_SKIRT_BAKED = 19,		// Pre-composited
-		TEX_NUM_ENTRIES = 20
-	};
-	// Note: if TEX_NUM_ENTRIES changes, update AGENT_TEXTURES in llagentinfo.h, mTextureIndexBaked, and BAKED_TEXTURE_COUNT
-
-	static BOOL isTextureIndexBaked( S32 i )
-		{
-			switch(i)
-			{
-			case TEX_HEAD_BAKED:
-			case TEX_UPPER_BAKED:
-			case TEX_LOWER_BAKED:
-			case TEX_EYES_BAKED:
-			case TEX_SKIRT_BAKED:
-				return TRUE;
-			default:
-				return FALSE;
-			}
-		}
-
 	//--------------------------------------------------------------------
 	// LLCharacter interface
 	//--------------------------------------------------------------------
+public:
 	virtual const char *getAnimationPrefix() { return "avatar"; }
 	virtual LLJoint *getRootJoint() { return &mRoot; }
 	virtual LLVector3 getCharacterPosition();
@@ -417,8 +186,8 @@ public:
 	virtual F32 getPixelArea() const;
 	virtual LLPolyMesh*	getHeadMesh();
 	virtual LLPolyMesh*	getUpperBodyMesh();
-	virtual LLVector3d	getPosGlobalFromAgent(const LLVector3 &position);
-	virtual LLVector3	getPosAgentFromGlobal(const LLVector3d &position);
+	virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position);
+	virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position);
 	virtual void updateVisualParams();
 	virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f);
 	virtual BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE);
@@ -433,30 +202,35 @@ public:
 	//--------------------------------------------------------------------
 	// Other public functions
 	//--------------------------------------------------------------------
-	BOOL			allocateCollisionVolumes( U32 num );
-	void			resetHUDAttachments();
-	static void		getAnimLabels( LLDynamicArray<std::string>* labels );
-	static void		getAnimNames( LLDynamicArray<std::string>* names );
-
+public:
 	static void		onCustomizeStart();
 	static void		onCustomizeEnd();
 
-	void			getLocalTextureByteCount( S32* gl_byte_count );
+public:
 	static void		dumpTotalLocalTextureByteCount();
+protected:
+	void			getLocalTextureByteCount( S32* gl_byte_count );
+
+public:
 	LLMotion*		findMotion(const LLUUID& id);
 
 	BOOL			isVisible();
-	BOOL			isSelf() { return mIsSelf; }
-	BOOL			isCulled() { return mCulled; }
-	
-	S32				getUnbakedPixelAreaRank();
-	void			setVisibilityRank(U32 rank);
-	U32				getVisibilityRank();
+	BOOL			isSelf() const { return mIsSelf; }
+	BOOL			isCulled() const { return mCulled; }
+
+public:
 	static void		cullAvatarsByPixelArea();
+	void			setVisibilityRank(U32 rank); 
+	U32				getVisibilityRank(); // unused
+protected:
+	S32				getUnbakedPixelAreaRank();
 
+public:
 	void			dumpLocalTextures();
-	const LLUUID&	grabLocalTexture(ETextureIndex index);
-	BOOL			canGrabLocalTexture(ETextureIndex index);
+	const LLUUID&	grabLocalTexture(LLVOAvatarDefines::ETextureIndex index);
+	BOOL			canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex index);
+	BOOL            isTextureDefined(U8 te) const;
+	BOOL			isTextureVisible(U8 te) const;
 	void			startAppearanceAnimation(BOOL set_by_user, BOOL play_sound);
 
 	void			setCompositeUpdatesEnabled(BOOL b);
@@ -469,46 +243,31 @@ public:
 	// Returns "FirstName LastName"
 	std::string		getFullname() const;
 
-	//--------------------------------------------------------------------
-	// internal (pseudo-private) functions
-	//--------------------------------------------------------------------
-	F32 getPelvisToFoot() { return mPelvisToFoot; }
-	
-	void startDefaultMotions();
-	void buildCharacter();
-	void releaseMeshData();
-	void restoreMeshData();
-	void updateMeshData();
-
-	void computeBodySize();
-
 	BOOL updateCharacter(LLAgent &agent);
 	void updateHeadOffset();
 
-	LLUUID& getStepSound();
+	F32 getPelvisToFoot() const { return mPelvisToFoot; }
+
+public:
+	BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims);
 	void processAnimationStateChanges();
+protected:
 	BOOL processSingleAnimationStateChange(const LLUUID &anim_id, BOOL start);
 	void resetAnimations();
-	BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims);
 
-	BOOL needsRenderBeam();
-
-	// Utility functions
+public:
 	void resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm);
 	void resolveHeightAgent(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm);
 	void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm);
-
+	
 	void slamPosition(); // Slam position to transmitted position (for teleport);
 
-	BOOL loadAvatar();
-	BOOL setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent);
-	BOOL buildSkeleton(LLVOAvatarSkeletonInfo *info);
-
 	// morph targets and such
 	void processAvatarAppearance( LLMessageSystem* mesgsys );
 	void onFirstTEMessageReceived();
 	void updateSexDependentLayerSets( BOOL set_by_user );
 	void dirtyMesh(); // Dirty the avatar mesh
+	void hideSkirt();
 
 	virtual void setParent(LLViewerObject* parent);
 	virtual void addChild(LLViewerObject *childp);
@@ -530,411 +289,310 @@ public:
 
 	void			updateMeshTextures();
 
-	//--------------------------------------------------------------------
-	// local textures for compositing.
-	//--------------------------------------------------------------------
-	enum ELocTexIndex
-	{
-		LOCTEX_UPPER_SHIRT = 0,
-		LOCTEX_UPPER_BODYPAINT = 1,
-		LOCTEX_LOWER_PANTS = 2,
-		LOCTEX_LOWER_BODYPAINT = 3,
-		LOCTEX_HEAD_BODYPAINT = 4,
-		LOCTEX_LOWER_SHOES = 5,
-		LOCTEX_LOWER_SOCKS = 6,
-		LOCTEX_UPPER_JACKET = 7,
-		LOCTEX_LOWER_JACKET = 8,
-		LOCTEX_UPPER_GLOVES = 9,
-		LOCTEX_UPPER_UNDERSHIRT = 10,
-		LOCTEX_LOWER_UNDERPANTS = 11,
-		LOCTEX_EYES_IRIS = 12,
-		LOCTEX_SKIRT = 13,
-		LOCTEX_NUM_ENTRIES = 14
-	};
-
 	//--------------------------------------------------------------------
 	// texture compositing (used only by the LLTexLayer series of classes)
 	//--------------------------------------------------------------------
+public:
 	LLColor4		getGlobalColor( const std::string& color_name );
 	BOOL			isLocalTextureDataAvailable( LLTexLayerSet* layerset );
 	BOOL			isLocalTextureDataFinal( LLTexLayerSet* layerset );
-	ETextureIndex	getBakedTE( LLTexLayerSet* layerset );
+	LLVOAvatarDefines::ETextureIndex	getBakedTE( LLTexLayerSet* layerset );
 	void			updateComposites();
 	void			onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user );
-	BOOL			getLocalTextureRaw( S32 index, LLImageRaw* image_raw_pp );
-	BOOL			getLocalTextureGL( S32 index, LLImageGL** image_gl_pp );
-	const LLUUID&	getLocalTextureID( S32 index );
+	BOOL			getLocalTextureRaw( LLVOAvatarDefines::ETextureIndex index, LLImageRaw* image_raw_pp );
+	BOOL			getLocalTextureGL( LLVOAvatarDefines::ETextureIndex index, LLImageGL** image_gl_pp );
+	const LLUUID&	getLocalTextureID( LLVOAvatarDefines::ETextureIndex index );
 	LLGLuint		getScratchTexName( LLGLenum format, U32* texture_bytes );
 	BOOL			bindScratchTexture( LLGLenum format );
 	void			invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user );
+	void			invalidateAll();
 	void			forceBakeAllTextures(bool slam_for_debug = false);
 	static void		processRebakeAvatarTextures(LLMessageSystem* msg, void**);
-	void			setNewBakedTexture( ETextureIndex i, const LLUUID& uuid );
-	void			setCachedBakedTexture( ETextureIndex i, const LLUUID& uuid );
+	void			setNewBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid );
+	void			setCachedBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid );
+	void			releaseUnnecessaryTextures();
 	void			requestLayerSetUploads();
 	bool			hasPendingBakedUploads();
 	static void		onLocalTextureLoaded( BOOL succcess, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
 	static void		dumpArchetypeXML( void* );
 	static void		dumpScratchTextureByteCount();
 	static void		dumpBakedStatus();
-	static void		deleteCachedImages();
+	static void		deleteCachedImages(bool clearAll=true);
 	static void		destroyGL();
 	static void		restoreGL();
 	static void		resetImpostors();
-	static enum EWearableType	getTEWearableType( S32 te );
-	static LLUUID			getDefaultTEImageID( S32 te );
+	static enum EWearableType	getTEWearableType(LLVOAvatarDefines::ETextureIndex te );
+	static LLUUID			getDefaultTEImageID(LLVOAvatarDefines::ETextureIndex te );
+	static void		onChangeSelfInvisible(BOOL newvalue);
+	void			setInvisible(BOOL newvalue);
+
+
 
 	//--------------------------------------------------------------------
 	// Clothing colors (conventience functions to access visual parameters
 	//--------------------------------------------------------------------
-	void			setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL set_by_user );
-	LLColor4		getClothesColor( ETextureIndex te );
-	BOOL			teToColorParams( ETextureIndex te, const char* param_name[3] );
+public:
+	void			setClothesColor( LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL set_by_user );
+	LLColor4		getClothesColor( LLVOAvatarDefines::ETextureIndex te );
+	BOOL			teToColorParams( LLVOAvatarDefines::ETextureIndex te, const char* param_name[3] );
 
 	BOOL			isWearingWearableType( EWearableType type );
 
 	//--------------------------------------------------------------------
 	// texture compositing
 	//--------------------------------------------------------------------
+public:
 	void			setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user );
 	void			setupComposites();
 
 	//--------------------------------------------------------------------
-	// member variables
-	//--------------------------------------------------------------------
-
-	BOOL mDirtyMesh;
-
-	LLFace *mShadow0Facep;
-	LLFace *mShadow1Facep;
-
-	LLFrameTimer mUpdateLODTimer; // controls frequency of LOD change calculations
-	
-	//--------------------------------------------------------------------
-	// State of deferred character building
+	// Handling partially loaded avatars (Ruth)
 	//--------------------------------------------------------------------
-	BOOL mIsBuilt;
+public:
+	BOOL            isFullyLoaded();
+	BOOL            updateIsFullyLoaded();
+private:
+	BOOL            mFullyLoaded;
+	BOOL            mPreviousFullyLoaded;
+	BOOL            mFullyLoadedInitialized;
+	S32             mFullyLoadedFrameCounter;
+	LLFrameTimer    mFullyLoadedTimer;
 
 	//--------------------------------------------------------------------
-	// skeleton for skinned avatar
+	// Collision Volumes
 	//--------------------------------------------------------------------
-	S32				mNumJoints;
-	LLViewerJoint	*mSkeleton;
-
+public:
 	S32								mNumCollisionVolumes;
 	LLViewerJointCollisionVolume*	mCollisionVolumes;
 
 	//--------------------------------------------------------------------
 	// cached pointers to well known joints
 	//--------------------------------------------------------------------
-	LLViewerJoint *mPelvisp;
-	LLViewerJoint *mTorsop;
-	LLViewerJoint *mChestp;
-	LLViewerJoint *mNeckp;
-	LLViewerJoint *mHeadp;
-	LLViewerJoint *mSkullp;
-	LLViewerJoint *mEyeLeftp;
-	LLViewerJoint *mEyeRightp;
-	LLViewerJoint *mHipLeftp;
-	LLViewerJoint *mHipRightp;
-	LLViewerJoint *mKneeLeftp;
-	LLViewerJoint *mKneeRightp;
-	LLViewerJoint *mAnkleLeftp;
-	LLViewerJoint *mAnkleRightp;
-	LLViewerJoint *mFootLeftp;
-	LLViewerJoint *mFootRightp;
-	LLViewerJoint *mWristLeftp;
-	LLViewerJoint *mWristRightp;
-
-	//--------------------------------------------------------------------
-	// special purpose joint for HUD attachments
-	//--------------------------------------------------------------------
-	LLViewerJoint *mScreenp;
-
-	//--------------------------------------------------------------------
-	// mesh objects for skinned avatar
-	//--------------------------------------------------------------------
-	LLViewerJoint		mHairLOD;
-	LLViewerJointMesh		mHairMesh0;
-	LLViewerJointMesh		mHairMesh1;
-	LLViewerJointMesh		mHairMesh2;
-	LLViewerJointMesh		mHairMesh3;
-	LLViewerJointMesh		mHairMesh4;
-	LLViewerJointMesh		mHairMesh5;
-
-	LLViewerJoint		mHeadLOD;
-	LLViewerJointMesh		mHeadMesh0;
-	LLViewerJointMesh		mHeadMesh1;
-	LLViewerJointMesh		mHeadMesh2;
-	LLViewerJointMesh		mHeadMesh3;
-	LLViewerJointMesh		mHeadMesh4;
-
-	LLViewerJoint		mEyeLashLOD;
-	LLViewerJointMesh		mEyeLashMesh0;
-
-	LLViewerJoint		mUpperBodyLOD;
-	LLViewerJointMesh		mUpperBodyMesh0;
-	LLViewerJointMesh		mUpperBodyMesh1;
-	LLViewerJointMesh		mUpperBodyMesh2;
-	LLViewerJointMesh		mUpperBodyMesh3;
-	LLViewerJointMesh		mUpperBodyMesh4;
-
-	LLViewerJoint		mLowerBodyLOD;
-	LLViewerJointMesh		mLowerBodyMesh0;
-	LLViewerJointMesh		mLowerBodyMesh1;
-	LLViewerJointMesh		mLowerBodyMesh2;
-	LLViewerJointMesh		mLowerBodyMesh3;
-	LLViewerJointMesh		mLowerBodyMesh4;
-
-	LLViewerJoint		mEyeBallLeftLOD;
-	LLViewerJointMesh		mEyeBallLeftMesh0;
-	LLViewerJointMesh		mEyeBallLeftMesh1;
-
-	LLViewerJoint		mEyeBallRightLOD;
-	LLViewerJointMesh		mEyeBallRightMesh0;
-	LLViewerJointMesh		mEyeBallRightMesh1;
-
-	LLViewerJoint		mSkirtLOD;
-	LLViewerJointMesh		mSkirtMesh0;
-	LLViewerJointMesh		mSkirtMesh1;
-	LLViewerJointMesh		mSkirtMesh2;
-	LLViewerJointMesh		mSkirtMesh3;
-	LLViewerJointMesh		mSkirtMesh4;
-
-	typedef std::multimap<std::string, LLPolyMesh*> mesh_map_t;
-	mesh_map_t				mMeshes;
-
-	S32                 mNumInitFaces ; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.
-	//--------------------------------------------------------------------
-	// true if this avatar is for this viewers agent
-	//--------------------------------------------------------------------
-	BOOL			mIsSelf;
-
-	//--------------------------------------------------------------------
-	// texture ids and pointers
-	//--------------------------------------------------------------------
-	LLPointer<LLViewerImage> mShadowImagep;
-
-	LLUUID			mLastHeadBakedID;
-	LLUUID			mLastUpperBodyBakedID;
-	LLUUID			mLastLowerBodyBakedID;
-	LLUUID			mLastEyesBakedID;
-	LLUUID			mLastSkirtBakedID;
+public:
+	LLViewerJoint* mPelvisp;
+	LLViewerJoint* mTorsop;
+	LLViewerJoint* mChestp;
+	LLViewerJoint* mNeckp;
+	LLViewerJoint* mHeadp;
+	LLViewerJoint* mSkullp;
+	LLViewerJoint* mEyeLeftp;
+	LLViewerJoint* mEyeRightp;
+	LLViewerJoint* mHipLeftp;
+	LLViewerJoint* mHipRightp;
+	LLViewerJoint* mKneeLeftp;
+	LLViewerJoint* mKneeRightp;
+	LLViewerJoint* mAnkleLeftp;
+	LLViewerJoint* mAnkleRightp;
+	LLViewerJoint* mFootLeftp;
+	LLViewerJoint* mFootRightp;
+	LLViewerJoint* mWristLeftp;
+	LLViewerJoint* mWristRightp;
 
 	//--------------------------------------------------------------------
 	// impostor state
 	//--------------------------------------------------------------------
+public:
 	LLRenderTarget	mImpostor;
+	BOOL			mNeedsImpostorUpdate;
+private:
 	LLVector3		mImpostorOffset;
 	LLVector2		mImpostorDim;
-	BOOL			mNeedsImpostorUpdate;
 	BOOL			mNeedsAnimUpdate;
 	LLVector3		mImpostorExtents[2];
 	LLVector3		mImpostorAngle;
 	F32				mImpostorDistance;
 	F32				mImpostorPixelArea;
 	LLVector3		mLastAnimExtents[2];  
-	
+
 	//--------------------------------------------------------------------
 	// Misc Render State
 	//--------------------------------------------------------------------
+public:
 	BOOL			mIsDummy; // For special views
 	S32				mSpecialRenderMode; // Special lighting
 
-	//--------------------------------------------------------------------
-	// Animation timer
-	//--------------------------------------------------------------------
-	LLTimer		mAnimTimer;
-	F32			mTimeLast;
-
-	//--------------------------------------------------------------------
-	// Measures speed (for diagnostics mostly).
-	//--------------------------------------------------------------------
-	F32 mSpeedAccum;
-
 	//--------------------------------------------------------------------
 	// animation state data
 	//--------------------------------------------------------------------
+public:
 	typedef std::map<LLUUID, S32>::iterator AnimIterator;
 
-	std::map<LLUUID, S32> mSignaledAnimations;		// requested state of Animation name/value
-	std::map<LLUUID, S32> mPlayingAnimations;		// current state of Animation name/value
+	std::map<LLUUID, S32> mSignaledAnimations; // requested state of Animation name/value
+	std::map<LLUUID, S32> mPlayingAnimations; // current state of Animation name/value
 
 	typedef std::multimap<LLUUID, LLUUID> AnimationSourceMap;
 	typedef AnimationSourceMap::iterator AnimSourceIterator;
-	AnimationSourceMap mAnimationSources;	// object ids that triggered anim ids
-
-	BOOL				mTurning;		// controls hysteresis on avatar rotation
-
-	//--------------------------------------------------------------------
-	// misc. animation related state
-	//--------------------------------------------------------------------
-	F32				mSpeed;
+	AnimationSourceMap mAnimationSources; // object ids that triggered anim ids
 
 	//--------------------------------------------------------------------
-	// Shadow stuff
+	// Shadowing
 	//--------------------------------------------------------------------
+public:
+	void updateShadowFaces();
 	LLDrawable*		mShadow;
-	BOOL			mInAir;
-	LLFrameTimer	mTimeInAir;
+private:
+	LLFace* mShadow0Facep;
+	LLFace* mShadow1Facep;
+	LLPointer<LLViewerImage> mShadowImagep;
 
 	//--------------------------------------------------------------------
 	// Keeps track of foot step state for generating sounds
 	//--------------------------------------------------------------------
+public:
+	void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; }
+	LLVector4		mFootPlane;
+private:
 	BOOL			mWasOnGroundLeft;
 	BOOL			mWasOnGroundRight;
-	LLVector4		mFootPlane;
-
-	//--------------------------------------------------------------------
-	// Keep track of the material being stepped on
-	//--------------------------------------------------------------------
-	BOOL			mStepOnLand;
-	U8				mStepMaterial;
-	LLVector3		mStepObjectVelocity;
 
 	//--------------------------------------------------------------------
 	// Pelvis height adjustment members.
 	//--------------------------------------------------------------------
-	F32				mPelvisToFoot;
+public:
 	LLVector3		mBodySize;
 	S32				mLastSkeletonSerialNum;
-
-	//--------------------------------------------------------------------
-	// current head position
-	//--------------------------------------------------------------------
-	LLVector3		mHeadOffset;
-
-	//--------------------------------------------------------------------
-	// avatar skeleton
-	//--------------------------------------------------------------------
-	LLViewerJoint	mRoot;
-
-	//--------------------------------------------------------------------
-	// sitting state
-	//--------------------------------------------------------------------
-	BOOL			mIsSitting;
+private:
+	F32				mPelvisToFoot;
 
 	//--------------------------------------------------------------------
 	// Display the name, then optionally fade it out
 	//--------------------------------------------------------------------
-	LLFrameTimer				mTimeVisible;
+public:
+	LLFrameTimer				mChatTimer;
 	LLPointer<LLHUDText>		mNameText;
+private:
+	LLFrameTimer				mTimeVisible;
 	std::deque<LLChat>			mChats;
-	LLFrameTimer				mChatTimer;
 	BOOL						mTyping;
 	LLFrameTimer				mTypingTimer;
 
-	//--------------------------------------------------------------------
-	// destroy mesh data after being invisible for a while
-	//--------------------------------------------------------------------
-	BOOL			mMeshValid;
-	BOOL			mVisible;
-	LLFrameTimer	mMeshInvisibleTime;
-
 	//--------------------------------------------------------------------
 	// wind rippling in clothes
 	//--------------------------------------------------------------------
+public:
 	LLVector4		mWindVec;
-	F32				mWindFreq;
 	F32				mRipplePhase;
+	BOOL			mBelowWater;
+private:
+	F32				mWindFreq;
 	LLFrameTimer	mRippleTimer;
 	F32				mRippleTimeLast;
 	LLVector3		mRippleAccel;
 	LLVector3		mLastVel;
-	BOOL			mBelowWater;
 
 	//--------------------------------------------------------------------
 	// appearance morphing
 	//--------------------------------------------------------------------
+public:
+	BOOL			mAppearanceAnimating;
+private:
 	LLFrameTimer	mAppearanceMorphTimer;
 	BOOL			mAppearanceAnimSetByUser;
 	F32				mLastAppearanceBlendTime;
-	BOOL			mAppearanceAnimating;
-
-	//--------------------------------------------------------------------
-	// we're morphing for lip sync
-	//--------------------------------------------------------------------
-	bool					mLipSyncActive;
 
 	//--------------------------------------------------------------------
-	// cached pointers morphs for lip sync
+	// Attachments
 	//--------------------------------------------------------------------
-	LLVisualParam		   *mOohMorph;
-	LLVisualParam		   *mAahMorph;
+public:
+	// map of attachment points, by ID
+	typedef std::map<S32, LLViewerJointAttachment*> attachment_map_t;
+	attachment_map_t mAttachmentPoints;
+	std::vector<LLPointer<LLViewerObject> > mPendingAttachment;
 
 	//--------------------------------------------------------------------
-	// static members
+	// static preferences that are controlled by user settings/menus
 	//--------------------------------------------------------------------
+public:
+	static S32		sRenderName;
+	static BOOL		sRenderGroupTitles;
 	static S32		sMaxVisible;
 	static F32		sRenderDistance; //distance at which avatars will render (affected by control "RenderAvatarMaxVisible")
-	static S32		sCurJoint;
-	static S32		sCurVolume;
 	static BOOL		sShowAnimationDebug; // show animation debug info
 	static BOOL		sUseImpostors; //use impostors for far away avatars
 	static BOOL		sShowFootPlane;	// show foot collision plane reported by server
 	static BOOL		sShowCollisionVolumes;	// show skeletal collision volumes
 	static BOOL		sVisibleInFirstPerson;
-	static S32		sMaxOtherAvatarsToComposite;
-
 	static S32		sNumLODChangesThisFrame;
-
-	// global table of sound ids per material, and the ground
-	static LLUUID	sStepSounds[LL_MCODE_END];
-	static LLUUID	sStepSoundOnLand;
-
-	static S32		sRenderName;
-	static BOOL		sRenderGroupTitles;
 	static S32		sNumVisibleChatBubbles;
 	static BOOL		sDebugInvisible;
 	static BOOL		sShowAttachmentPoints;
+	static F32		sLODFactor; // user-settable LOD factor
+	static BOOL		sJointDebug; // output total number of joints being touched for each avatar
+	static BOOL     sDebugAvatarRotation;
+
+	static S32 sNumVisibleAvatars; // Number of instances of this class
+	
+	//--------------------------------------------------------------------
+	// Miscellaneous public variables.
+	//--------------------------------------------------------------------
+public:
+	BOOL			mInAir;
+	LLFrameTimer	mTimeInAir;
+	LLVector3 mHeadOffset; // current head position
+	LLViewerJoint mRoot; // avatar skeleton
+	BOOL mIsSitting; // sitting state
+
+	//--------------------------------------------------------------------
+	// Private member variables.
+	//--------------------------------------------------------------------
+private:
+	BOOL mIsSelf; // True if this avatar is for this viewer's agent
+
+	LLViewerJoint *mScreenp; // special purpose joint for HUD attachments
+	BOOL mIsBuilt; // state of deferred character building
+	F32 mSpeedAccum; // measures speed (for diagnostics mostly).
+
+	
+	// LLFrameTimer mUpdateLODTimer; // controls frequency of LOD change calculations
+	BOOL mDirtyMesh;
+	BOOL mTurning; // controls hysteresis on avatar rotation
+	F32	mSpeed; // misc. animation repeated state
 
-	// Number of instances of this class
-	static S32		sNumVisibleAvatars;
+	// Keep track of the material being stepped on
+	BOOL mStepOnLand;
+	U8 mStepMaterial;
+	LLVector3 mStepObjectVelocity;
+
+	// Destroy mesh data after being invisible for a while
+	BOOL			mMeshValid;
+	BOOL			mVisible;
+	LLFrameTimer	mMeshInvisibleTime;
+
+	// Lip synch morph stuff
+	bool mLipSyncActive; // we're morphing for lip sync
+	LLVisualParam* mOohMorph; // cached pointers morphs for lip sync
+	LLVisualParam* mAahMorph; // cached pointers morphs for lip sync
+
+	// Skeleton for skinned avatar
+	S32				mNumJoints;
+	LLViewerJoint*	mSkeleton;
 
 	// Scratch textures used for compositing
 	static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;
 	static LLMap< LLGLenum, F32*> sScratchTexLastBindTime;
 	static S32 sScratchTexBytes;
 
-	// map of attachment points, by ID
-	typedef std::map<S32, LLViewerJointAttachment*> attachment_map_t;
-	attachment_map_t mAttachmentPoints;
+	// Global table of sound ids per material, and the ground
+	const static LLUUID	sStepSounds[LL_MCODE_END];
+	const static LLUUID	sStepSoundOnLand;
 
-	std::vector<LLPointer<LLViewerObject> > mPendingAttachment;
-
-	// xml parse tree of avatar config file
+	// Xml parse tree of avatar config file
 	static LLXmlTree sXMLTree;
-	// xml parse tree of avatar skeleton file
+	// Xml parse tree of avatar skeleton file
 	static LLXmlTree sSkeletonXMLTree;
 
-	// user-settable LOD factor
-	static F32		sLODFactor;
-
-	// output total number of joints being touched for each avatar
-	static BOOL		sJointDebug;
-	static ETextureIndex sBakedTextureIndices[BAKED_TEXTURE_COUNT];
-
-	static F32 		sUnbakedTime; // Total seconds with >=1 unbaked avatars
-	static F32 		sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) 
-	static F32 		sGreyTime; // Total seconds with >=1 grey avatars
-	static F32 		sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) 
+	// Voice Visualizer is responsible for detecting the user's voice signal, and when the
+	// user speaks, it puts a voice symbol over the avatar's head, and triggering gesticulations
+	LLVoiceVisualizer*  mVoiceVisualizer;
+	int					mCurrentGesticulationLevel;
 	
-	//--------------------------------------------------------------------
-	// Texture Layer Sets and Global Colors
-	//--------------------------------------------------------------------	
-	LLTexLayerSet*		mHeadLayerSet;
-	LLTexLayerSet*		mUpperBodyLayerSet;
-	LLTexLayerSet*		mLowerBodyLayerSet;
-	LLTexLayerSet*		mEyesLayerSet;
-	LLTexLayerSet*		mSkirtLayerSet;
-
+	// Animation timer
+	LLTimer		mAnimTimer;
+	F32			mTimeLast;	
 
-protected:
 	LLPointer<LLHUDEffectSpiral> mBeam;
 	LLFrameTimer mBeamTimer;
-	LLFrameTimer mEditEffectTimer;
 
-	F32		mRenderPriority;
 	F32		mAdjustedPixelArea;
 
 	LLWString mNameString;
@@ -954,27 +612,11 @@ protected:
 	//--------------------------------------------------------------------
 	// local textures for compositing.
 	//--------------------------------------------------------------------
-
-	LLPointer<LLViewerImage> mLocalTexture[ LOCTEX_NUM_ENTRIES ];
-	BOOL 				mLocalTextureBaked[ LOCTEX_NUM_ENTRIES ]; // Texture is covered by a baked texture
-	S32 				mLocalTextureDiscard[ LOCTEX_NUM_ENTRIES ];
-	LLUUID				mSavedTE[ TEX_NUM_ENTRIES ];
+private:
+	LLUUID				mSavedTE[ LLVOAvatarDefines::TEX_NUM_INDICES ];
 	BOOL				mFirstTEMessageReceived;
 	BOOL				mFirstAppearanceMessageReceived;
-
-	BOOL				mHeadBakedLoaded;
-	S32					mHeadMaskDiscard;
-	BOOL				mUpperBakedLoaded;
-	S32					mUpperMaskDiscard;
-	BOOL				mLowerBakedLoaded;
-	S32					mLowerMaskDiscard;
-	BOOL				mEyesBakedLoaded;
-	BOOL				mSkirtBakedLoaded;
-
-	//RN: testing 2 pass rendering
-	U32					mHeadMaskTexName;
-	U32					mUpperMaskTexName;
-	U32					mLowerMaskTexName;
+	BOOL				mHasBakedHair;
 
 	BOOL				mCulled;
 	U32					mVisibilityRank;
@@ -985,6 +627,7 @@ protected:
 	//--------------------------------------------------------------------
 	// Global Colors
 	//--------------------------------------------------------------------
+private:
 	LLTexGlobalColor*	mTexSkinColor;
 	LLTexGlobalColor*	mTexHairColor;
 	LLTexGlobalColor*	mTexEyeColor;
@@ -992,61 +635,127 @@ protected:
 	BOOL				mNeedsSkin;  //if TRUE, avatar has been animated and verts have not been updated
 	S32					mUpdatePeriod;
 
-	static LLVOAvatarSkeletonInfo*	sSkeletonInfo;
-	static LLVOAvatarInfo*			sAvatarInfo;
-
-	
 	//--------------------------------------------------------------------
-	// Handling partially loaded avatars (Ruth)
+	// Internal functions
 	//--------------------------------------------------------------------
-public:
-	BOOL            isFullyLoaded();
-	BOOL            updateIsFullyLoaded();
-private:
-	BOOL            mFullyLoaded;
-	BOOL            mPreviousFullyLoaded;
-	BOOL            mFullyLoadedInitialized;
-	S32             mFullyLoadedFrameCounter;
-	LLFrameTimer    mFullyLoadedTimer;
-
 protected:
+	void buildCharacter();
+	void releaseMeshData();
+	void restoreMeshData();
+	void updateMeshData();
+	void computeBodySize();
+	const LLUUID& getStepSound() const;
+	BOOL needsRenderBeam();
+
+	BOOL			allocateCollisionVolumes( U32 num );
+	void			resetHUDAttachments();
+	static void		getAnimLabels( LLDynamicArray<std::string>* labels );
+	static void		getAnimNames( LLDynamicArray<std::string>* names );
 
+	//--------------------------------------------------------------------
+	// Textures and Layers
+	//--------------------------------------------------------------------
+protected:
 	BOOL			loadSkeletonNode();
 	BOOL			loadMeshNodes();
-	
 	BOOL			isFullyBaked();
-	void			deleteLayerSetCaches();
+	void			deleteLayerSetCaches(bool clearAll = true);
 	static BOOL		areAllNearbyInstancesBaked(S32& grey_avatars);
-
 	static void		onBakedTextureMasksLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
-
-	void			setLocalTexture(ELocTexIndex i, LLViewerImage* tex, BOOL baked_version_exits);
-	
-	void			requestLayerSetUpdate(LLVOAvatar::ELocTexIndex i);
-	void			addLocalTextureStats(LLVOAvatar::ELocTexIndex i, LLViewerImage* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked);
+	void			setLocalTexture(LLVOAvatarDefines::ETextureIndex i, LLViewerImage* tex, BOOL baked_version_exits);
+	void			requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i);
+	void			addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerImage* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked);
 	void			addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level);
 	static void		onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata );
 	static void		onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata);
 	void			useBakedTexture(const LLUUID& id);
 	void			dumpAvatarTEs(const std::string& context);
 	void			removeMissingBakedTextures();
-	LLTexLayerSet*	getLayerSet(ETextureIndex index) const;
+	LLTexLayerSet*	getLayerSet(LLVOAvatarDefines::ETextureIndex index) const;
 	LLHost			getObjectHost() const;
-	S32				getLocalDiscardLevel( S32 index);
+	S32				getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex index);
+public:
+	static void updateFreezeCounter(S32 counter = 0 );
+private:
+	static S32 sFreezeCounter;
 	
+	//-----------------------------------------------------------------------------------------------
+	// Avatar skeleton setup.
+	//-----------------------------------------------------------------------------------------------
+private:
+	BOOL loadAvatar();
+	BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
+	BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info);
 
 	//-----------------------------------------------------------------------------------------------
-	// the Voice Visualizer is responsible for detecting the user's voice signal, and when the
-	// user speaks, it puts a voice symbol over the avatar's head, and triggering gesticulations
+	// Per-avatar information about texture data.
+	// To-do: Move this to private implementation class
 	//-----------------------------------------------------------------------------------------------
-	private:
-	LLVoiceVisualizer * mVoiceVisualizer;
-	int					mCurrentGesticulationLevel;
+private:
+	struct BakedTextureData
+	{
+		LLUUID			mLastTextureIndex;
+		LLTexLayerSet*	mTexLayerSet;
+		bool			mIsLoaded;
+		LLVOAvatarDefines::ETextureIndex	mTextureIndex;
+		U32				mMaskTexName;
+		// Stores pointers to the joint meshes that this baked texture deals with
+		std::vector< LLViewerJointMesh * > mMeshes;  // std::vector<LLViewerJointMesh> mJoints[i]->mMeshParts
+	};
+	typedef std::vector<BakedTextureData> bakedtexturedata_vec_t;
+	bakedtexturedata_vec_t mBakedTextureData;
+
+	struct LocalTextureData
+	{
+		LocalTextureData() : mIsBakedReady(FALSE), mDiscard(MAX_DISCARD_LEVEL+1), mImage(NULL)
+		{}
+		LLPointer<LLViewerImage> mImage;
+		BOOL mIsBakedReady;
+		S32 mDiscard;
+	};
+	typedef std::map<LLVOAvatarDefines::ETextureIndex, LocalTextureData> localtexture_map_t;
+	localtexture_map_t mLocalTextureData;
+
+	typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t;
+	polymesh_map_t mMeshes;
+	std::vector<LLViewerJoint *> mMeshLOD;
+	S32 mNumInitFaces ; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.
 
+	//-----------------------------------------------------------------------------------------------
+	// Static texture/mesh/baked dictionary for avatars
+	//-----------------------------------------------------------------------------------------------
+public:
+	static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i);
+	static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i);
 private:
-	static  S32 sFreezeCounter ;
+	static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; }
+	static LLVOAvatarDefines::LLVOAvatarDictionary *sAvatarDictionary;
+	static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo;
+	static LLVOAvatarXmlInfo* sAvatarXmlInfo;
+
+	//-----------------------------------------------------------------------------------------------
+	// Diagnostics
+	//-----------------------------------------------------------------------------------------------
 public:
-	static void updateFreezeCounter(S32 counter = 0 ) ;
+	static F32 		sUnbakedTime; // Total seconds with >=1 unbaked avatars
+	static F32 		sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) 
+	static F32 		sGreyTime; // Total seconds with >=1 grey avatars
+	static F32 		sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) 
+
+	const std::string getBakedStatusForPrintout() const;
 };
 
+//-----------------------------------------------------------------------------------------------
+// Inlines
+//-----------------------------------------------------------------------------------------------
+inline BOOL LLVOAvatar::isTextureDefined(U8 te) const
+{
+	return (getTEImage(te)->getID() != IMG_DEFAULT_AVATAR && getTEImage(te)->getID() != IMG_DEFAULT);
+}
+
+inline BOOL LLVOAvatar::isTextureVisible(U8 te) const
+{
+	return (!isTextureDefined(te) || getTEImage(te)->getID() != IMG_INVISIBLE);
+}
+
 #endif // LL_VO_AVATAR_H
diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp
new file mode 100644
index 0000000000..19ad90a8e2
--- /dev/null
+++ b/indra/newview/llvoavatardefines.cpp
@@ -0,0 +1,227 @@
+/** 
+ * @file llvoavatar.cpp
+ * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2007, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llvoavatardefines.h"
+
+const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512;
+const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512;
+const S32 LLVOAvatarDefines::IMPOSTOR_PERIOD = 2;
+
+using namespace LLVOAvatarDefines;
+
+/*********************************************************************************
+ * Edit this function to add/remove/change textures and mesh definitions for avatars.
+ */
+void LLVOAvatarDictionary::initData()
+{
+	// Textures
+	mTextureMap[TEX_HEAD_BODYPAINT] =            new TextureDictionaryEntry("head bodypaint",   TRUE,  BAKED_NUM_INDICES, "",                          WT_SKIN);
+	mTextureMap[TEX_UPPER_SHIRT] =               new TextureDictionaryEntry("shirt",            TRUE,  BAKED_NUM_INDICES, "UIImgDefaultShirtUUID",     WT_SHIRT);
+	mTextureMap[TEX_LOWER_PANTS] =               new TextureDictionaryEntry("pants",            TRUE,  BAKED_NUM_INDICES, "UIImgDefaultPantsUUID",     WT_PANTS);
+	mTextureMap[TEX_EYES_IRIS] =                 new TextureDictionaryEntry("iris",             TRUE,  BAKED_NUM_INDICES, "UIImgDefaultEyesUUID",      WT_EYES);
+	mTextureMap[TEX_HAIR] =                      new TextureDictionaryEntry("hair",             TRUE,  BAKED_NUM_INDICES, "UIImgDefaultHairUUID",      WT_HAIR);
+	mTextureMap[TEX_UPPER_BODYPAINT] =           new TextureDictionaryEntry("upper bodypaint",  TRUE,  BAKED_NUM_INDICES, "",                          WT_SKIN);
+	mTextureMap[TEX_LOWER_BODYPAINT] =           new TextureDictionaryEntry("lower bodypaint",  TRUE,  BAKED_NUM_INDICES, "",                          WT_SKIN);
+	mTextureMap[TEX_LOWER_SHOES] =               new TextureDictionaryEntry("shoes",            TRUE,  BAKED_NUM_INDICES, "UIImgDefaultShoesUUID",     WT_SHOES);
+	mTextureMap[TEX_LOWER_SOCKS] =               new TextureDictionaryEntry("socks",            TRUE,  BAKED_NUM_INDICES, "UIImgDefaultSocksUUID",     WT_SOCKS);
+	mTextureMap[TEX_UPPER_JACKET] =              new TextureDictionaryEntry("upper jacket",     TRUE,  BAKED_NUM_INDICES, "UIImgDefaultJacketUUID",    WT_JACKET);
+	mTextureMap[TEX_LOWER_JACKET] =              new TextureDictionaryEntry("lower jacket",     TRUE,  BAKED_NUM_INDICES, "UIImgDefaultJacketUUID",    WT_JACKET);
+	mTextureMap[TEX_UPPER_GLOVES] =              new TextureDictionaryEntry("gloves",           TRUE,  BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID",    WT_GLOVES);
+	mTextureMap[TEX_UPPER_UNDERSHIRT] =          new TextureDictionaryEntry("undershirt",       TRUE,  BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERSHIRT);
+	mTextureMap[TEX_LOWER_UNDERPANTS] =          new TextureDictionaryEntry("underpants",       TRUE,  BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERPANTS);
+	mTextureMap[TEX_SKIRT] =                     new TextureDictionaryEntry("skirt",            TRUE,  BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID",     WT_SKIRT);
+	mTextureMap[TEX_HEAD_BAKED] =                new TextureDictionaryEntry("head-baked",       FALSE, BAKED_HEAD);
+	mTextureMap[TEX_UPPER_BAKED] =               new TextureDictionaryEntry("upper-baked",      FALSE, BAKED_UPPER);
+	mTextureMap[TEX_LOWER_BAKED] =               new TextureDictionaryEntry("lower-baked",      FALSE, BAKED_LOWER);
+	mTextureMap[TEX_EYES_BAKED] =                new TextureDictionaryEntry("eyes-baked",       FALSE, BAKED_EYES);
+	mTextureMap[TEX_HAIR_BAKED] =                new TextureDictionaryEntry("hair-baked",       FALSE, BAKED_HAIR);
+	mTextureMap[TEX_SKIRT_BAKED] =               new TextureDictionaryEntry("skirt-baked",      FALSE, BAKED_SKIRT);
+
+	// Baked textures
+	mBakedTextureMap[BAKED_HEAD] =     new BakedDictionaryEntry(TEX_HEAD_BAKED,  "head",       1, TEX_HEAD_BODYPAINT);
+	mBakedTextureMap[BAKED_UPPER] =    new BakedDictionaryEntry(TEX_UPPER_BAKED, "upper_body", 5, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT,TEX_UPPER_JACKET,TEX_UPPER_GLOVES,TEX_UPPER_UNDERSHIRT);
+	mBakedTextureMap[BAKED_LOWER] =    new BakedDictionaryEntry(TEX_LOWER_BAKED, "lower_body", 6, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES,TEX_LOWER_SOCKS,TEX_LOWER_JACKET,TEX_LOWER_UNDERPANTS);
+	mBakedTextureMap[BAKED_EYES] =     new BakedDictionaryEntry(TEX_EYES_BAKED,  "eyes",       1, TEX_EYES_IRIS);
+	mBakedTextureMap[BAKED_SKIRT] =    new BakedDictionaryEntry(TEX_SKIRT_BAKED, "skirt",      1, TEX_SKIRT);
+	mBakedTextureMap[BAKED_HAIR] =     new BakedDictionaryEntry(TEX_HAIR_BAKED,  "hair",       1, TEX_HAIR);
+		
+	// Meshes
+	mMeshMap[MESH_ID_HAIR] =           new MeshDictionaryEntry(BAKED_HAIR,  "hairMesh",         6, LLViewerJoint::PN_4);
+	mMeshMap[MESH_ID_HEAD] =           new MeshDictionaryEntry(BAKED_HEAD,  "headMesh",         5, LLViewerJoint::PN_5);
+	mMeshMap[MESH_ID_EYELASH] =        new MeshDictionaryEntry(BAKED_HEAD,  "eyelashMesh",      1, LLViewerJoint::PN_0); // no baked mesh associated currently
+	mMeshMap[MESH_ID_UPPER_BODY] =     new MeshDictionaryEntry(BAKED_UPPER, "upperBodyMesh",    5, LLViewerJoint::PN_1);
+	mMeshMap[MESH_ID_LOWER_BODY] =     new MeshDictionaryEntry(BAKED_LOWER, "lowerBodyMesh",    5, LLViewerJoint::PN_2);
+	mMeshMap[MESH_ID_EYEBALL_LEFT] =   new MeshDictionaryEntry(BAKED_EYES,  "eyeBallLeftMesh",  2, LLViewerJoint::PN_3);
+	mMeshMap[MESH_ID_EYEBALL_RIGHT] =  new MeshDictionaryEntry(BAKED_EYES,  "eyeBallRightMesh", 2, LLViewerJoint::PN_3);
+	mMeshMap[MESH_ID_SKIRT] =          new MeshDictionaryEntry(BAKED_SKIRT, "skirtMesh",        5, LLViewerJoint::PN_5);
+
+	// Wearables
+	mWearableMap[BAKED_HEAD] =   new WearableDictionaryEntry("18ded8d6-bcfc-e415-8539-944c0f5ea7a6", 3, WT_SHAPE, WT_SKIN, WT_HAIR);
+	mWearableMap[BAKED_UPPER] =  new WearableDictionaryEntry("338c29e3-3024-4dbb-998d-7c04cf4fa88f", 6, WT_SHAPE, WT_SKIN,	WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT);
+	mWearableMap[BAKED_LOWER] =  new WearableDictionaryEntry("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f", 7, WT_SHAPE, WT_SKIN,	WT_PANTS, WT_SHOES,	 WT_SOCKS,  WT_JACKET,		WT_UNDERPANTS);
+	mWearableMap[BAKED_EYES] =   new WearableDictionaryEntry("b2cf28af-b840-1071-3c6a-78085d8128b5", 1, WT_EYES);
+	mWearableMap[BAKED_SKIRT] =  new WearableDictionaryEntry("ea800387-ea1a-14e0-56cb-24f2022f969a", 1, WT_SKIRT);
+	mWearableMap[BAKED_HAIR] =   new WearableDictionaryEntry("0af1ef7c-ad24-11dd-8790-001f5bf833e8", 1, WT_HAIR);
+}
+
+/*
+ *
+ *********************************************************************************/
+
+LLVOAvatarDictionary::LLVOAvatarDictionary()
+{
+	initData();
+	createAssociations();
+}
+
+// Baked textures are composites of textures; for each such composited texture,
+// map it to the baked texture.
+void LLVOAvatarDictionary::createAssociations()
+{
+	for (baked_map_t::const_iterator iter = mBakedTextureMap.begin(); iter != mBakedTextureMap.end(); iter++)
+	{
+		const EBakedTextureIndex baked_index = (iter->first);
+		const BakedDictionaryEntry *dict = (iter->second);
+
+		// For each texture that this baked texture index affects, associate those textures
+		// with this baked texture index.
+		for (texture_vec_t::const_iterator local_texture_iter = dict->mLocalTextures.begin();
+			 local_texture_iter != dict->mLocalTextures.end();
+			 local_texture_iter++)
+		{
+			const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter;
+			mTextureMap[local_texture_index]->mIsUsedByBakedTexture = true;
+			mTextureMap[local_texture_index]->mBakedTextureIndex = baked_index;
+		}
+	}
+		
+}
+
+LLVOAvatarDictionary::TextureDictionaryEntry::TextureDictionaryEntry(const std::string &name, 
+																	 bool is_local_texture, 
+																	 EBakedTextureIndex baked_texture_index,
+																	 const std::string &default_image_name,
+																	 EWearableType wearable_type) :
+	mName(name),
+	mIsLocalTexture(is_local_texture),
+	mIsBakedTexture(!is_local_texture),
+	mIsUsedByBakedTexture(baked_texture_index != BAKED_NUM_INDICES),
+	mBakedTextureIndex(baked_texture_index),
+	mDefaultImageName(default_image_name),
+	mWearableType(wearable_type)
+{
+}
+
+LLVOAvatarDictionary::MeshDictionaryEntry::MeshDictionaryEntry(EBakedTextureIndex baked_index, 
+															   const std::string &name, 
+															   U8 level,
+															   LLViewerJoint::PickName pick) :
+	mBakedID(baked_index),
+	mName(name),
+	mLOD(level),
+	mPickName(pick)
+{
+}
+LLVOAvatarDictionary::BakedDictionaryEntry::BakedDictionaryEntry(ETextureIndex tex_index, 
+																 const std::string &name, 
+																 U32 num_local_textures, ... ) :
+	mName(name),
+	mTextureIndex(tex_index)
+
+{
+	va_list argp;
+	va_start(argp, num_local_textures);
+	for (U8 i=0; i < num_local_textures; i++)
+	{
+		ETextureIndex t = (ETextureIndex)va_arg(argp,int);
+		mLocalTextures.push_back(t);
+	}
+}
+
+LLVOAvatarDictionary::WearableDictionaryEntry::WearableDictionaryEntry(const std::string &hash_name, 
+																	   U32 num_wearables, ... ) :
+	mHashID(LLUUID(hash_name))
+{
+	va_list argp;
+	va_start(argp, num_wearables);
+	for (U8 i=0; i < num_wearables; i++)
+	{
+		EWearableType t = (EWearableType)va_arg(argp,int);
+		mWearablesVec.push_back(t);
+	}
+}
+
+//virtual 
+LLVOAvatarDictionary::~LLVOAvatarDictionary()
+{
+	for (mesh_map_t::iterator iter = mMeshMap.begin(); iter != mMeshMap.end(); iter++)
+		delete (iter->second);
+	for (baked_map_t::iterator iter = mBakedTextureMap.begin(); iter != mBakedTextureMap.end(); iter++)
+		delete (iter->second);
+	for (texture_map_t::iterator iter = mTextureMap.begin(); iter != mTextureMap.end(); iter++)
+		delete (iter->second);
+}
+
+const LLVOAvatarDictionary::MeshDictionaryEntry *LLVOAvatarDictionary::getMesh(EMeshIndex index) const
+{
+	mesh_map_t::const_iterator mesh_iter = mMeshMap.find(index);
+	if (mesh_iter == mMeshMap.end()) return NULL;
+	return mesh_iter->second; 
+}
+
+const LLVOAvatarDictionary::BakedDictionaryEntry *LLVOAvatarDictionary::getBakedTexture(EBakedTextureIndex index) const
+{
+	baked_map_t::const_iterator baked_iter = mBakedTextureMap.find(index);
+	if (baked_iter == mBakedTextureMap.end()) return NULL;
+	return baked_iter->second; 
+}
+
+const LLVOAvatarDictionary::TextureDictionaryEntry *LLVOAvatarDictionary::getTexture(ETextureIndex index) const
+{
+	texture_map_t::const_iterator texture_iter = mTextureMap.find(index);
+	if (texture_iter == mTextureMap.end()) return NULL;
+	return texture_iter->second;
+}
+
+const LLVOAvatarDictionary::WearableDictionaryEntry *LLVOAvatarDictionary::getWearable(EBakedTextureIndex index) const
+{
+	wearable_map_t::const_iterator wearable_iter = mWearableMap.find(index);
+	if (wearable_iter == mWearableMap.end()) return NULL;
+	return wearable_iter->second;
+}
+
+
+
+ETextureIndex LLVOAvatarDefines::getTextureIndex(EBakedTextureIndex index)
+{
+	return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex;
+}
diff --git a/indra/newview/llvoavatardefines.h b/indra/newview/llvoavatardefines.h
new file mode 100644
index 0000000000..bc1a1f1c1f
--- /dev/null
+++ b/indra/newview/llvoavatardefines.h
@@ -0,0 +1,209 @@
+/** 
+ * @file llvoavatar.h
+ * @brief Declaration of LLVOAvatar class which is a derivation fo
+ * LLViewerObject
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2007, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLVOAVATAR_DEFINES_H
+#define LLVOAVATAR_DEFINES_H
+
+#include <vector>
+#include "llwearable.h"
+#include "llviewerjoint.h"
+
+namespace LLVOAvatarDefines
+{
+
+extern const S32 SCRATCH_TEX_WIDTH;
+extern const S32 SCRATCH_TEX_HEIGHT;
+extern const S32 IMPOSTOR_PERIOD;
+
+//--------------------------------------------------------------------
+// texture entry assignment
+//--------------------------------------------------------------------
+enum ETextureIndex
+{
+	TEX_HEAD_BODYPAINT = 0,
+	TEX_UPPER_SHIRT,
+	TEX_LOWER_PANTS,
+	TEX_EYES_IRIS,
+	TEX_HAIR,
+	TEX_UPPER_BODYPAINT,
+	TEX_LOWER_BODYPAINT,
+	TEX_LOWER_SHOES,
+	TEX_HEAD_BAKED,			// Pre-composited
+	TEX_UPPER_BAKED,		// Pre-composited
+	TEX_LOWER_BAKED,		// Pre-composited
+	TEX_EYES_BAKED,		// Pre-composited
+	TEX_LOWER_SOCKS,
+	TEX_UPPER_JACKET,
+	TEX_LOWER_JACKET,
+	TEX_UPPER_GLOVES,
+	TEX_UPPER_UNDERSHIRT,
+	TEX_LOWER_UNDERPANTS,
+	TEX_SKIRT,
+	TEX_SKIRT_BAKED,		// Pre-composited
+	TEX_HAIR_BAKED,     // Pre-composited
+	TEX_NUM_INDICES
+}; // "Note: if TEX_NUM_ENTRIES changes, update AGENT_TEXTURES in llagentinfo.h, mTextureIndexBaked, and BAKED_TEXTURE_COUNT"
+// Seraph - Above comment about order is probably obsolete.
+
+typedef std::vector<ETextureIndex> texture_vec_t;
+	
+enum EBakedTextureIndex
+{
+	BAKED_HEAD = 0,
+	BAKED_UPPER,
+	BAKED_LOWER,
+	BAKED_EYES,
+	BAKED_SKIRT,
+	BAKED_HAIR,
+	BAKED_NUM_INDICES
+};
+typedef std::vector<EBakedTextureIndex> bakedtexture_vec_t;
+
+// Reference IDs for each mesh. Used as indices for vector of joints
+enum EMeshIndex
+{
+	MESH_ID_HAIR = 0,
+	MESH_ID_HEAD,
+	MESH_ID_EYELASH,
+	MESH_ID_UPPER_BODY,
+	MESH_ID_LOWER_BODY,
+	MESH_ID_EYEBALL_LEFT,
+	MESH_ID_EYEBALL_RIGHT,
+	MESH_ID_SKIRT,
+	MESH_ID_NUM_INDICES
+};
+typedef std::vector<EMeshIndex> mesh_vec_t;
+
+typedef std::vector<EWearableType> wearables_vec_t;
+
+//--------------------------------------------------------------------------------
+// Convenience Functions
+//--------------------------------------------------------------------------------
+
+// Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED
+ETextureIndex getTextureIndex(EBakedTextureIndex t);
+
+
+
+//------------------------------------------------------------------------
+// LLVOAvatarDictionary
+// 
+// Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e.
+// information that is common to all avatars.
+// 
+// This holds const data - it is initialized once and the contents never change after that.
+//------------------------------------------------------------------------
+class LLVOAvatarDictionary : public LLSingleton<LLVOAvatarDictionary>
+{
+public:
+	LLVOAvatarDictionary();
+	virtual ~LLVOAvatarDictionary();
+	
+	struct TextureDictionaryEntry
+	{
+		TextureDictionaryEntry(const std::string &name, 
+							   bool is_local_texture, 
+							   EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES,
+							   const std::string &default_image_name = "",
+							   EWearableType wearable_type = WT_INVALID);
+		const std::string mName;
+		const std::string mDefaultImageName;
+		const EWearableType mWearableType;
+		// It's either a local texture xor baked
+		BOOL mIsLocalTexture;
+		BOOL mIsBakedTexture;
+		// If it's a local texture, it may be used by a baked texture
+		BOOL mIsUsedByBakedTexture;
+		EBakedTextureIndex mBakedTextureIndex;
+	};
+	
+	struct MeshDictionaryEntry
+	{
+		MeshDictionaryEntry(EBakedTextureIndex baked_index, 
+							const std::string &name, 
+							U8 level,
+							LLViewerJoint::PickName pick);
+		const std::string mName; // names of mesh types as they are used in avatar_lad.xml
+		// Levels of Detail for each mesh.  Must match levels of detail present in avatar_lad.xml
+        // Otherwise meshes will be unable to be found, or levels of detail will be ignored
+		const U8 mLOD;
+		const EBakedTextureIndex mBakedID;
+		const LLViewerJoint::PickName mPickName;
+	};
+
+	struct BakedDictionaryEntry
+	{
+		BakedDictionaryEntry(ETextureIndex tex_index, 
+							 const std::string &name, 
+							 U32 num_local_textures, ... );
+		const ETextureIndex mTextureIndex;
+		const std::string mName;
+		texture_vec_t mLocalTextures;
+	};
+	
+	struct WearableDictionaryEntry
+	{
+		WearableDictionaryEntry(const std::string &hash_name,
+								U32 num_wearables, ... );
+		const LLUUID mHashID;
+		wearables_vec_t mWearablesVec;
+	};
+
+	typedef std::map<EBakedTextureIndex, BakedDictionaryEntry*> baked_map_t;
+	typedef std::map<ETextureIndex, TextureDictionaryEntry*> texture_map_t;
+	typedef std::map<EMeshIndex, MeshDictionaryEntry*> mesh_map_t;
+	typedef std::map<EBakedTextureIndex, WearableDictionaryEntry*> wearable_map_t;
+
+	const MeshDictionaryEntry *getMesh(EMeshIndex index) const;
+	const BakedDictionaryEntry *getBakedTexture(EBakedTextureIndex index) const;
+	const TextureDictionaryEntry *getTexture(ETextureIndex index) const;
+	const WearableDictionaryEntry *getWearable(EBakedTextureIndex index) const;
+
+	const texture_map_t &getTextures() const { return mTextureMap; }
+	const baked_map_t &getBakedTextures() const { return mBakedTextureMap; }
+	const mesh_map_t &getMeshes() const { return mMeshMap; }
+	const wearable_map_t &getWearables() const { return mWearableMap; }
+	
+private:
+	void initData();
+	void createAssociations();
+
+	texture_map_t mTextureMap;
+	baked_map_t mBakedTextureMap;
+	mesh_map_t mMeshMap;
+	wearable_map_t mWearableMap;
+
+}; // End LLVOAvatarDictionary
+
+} // End namespace LLVOAvatarDefines
+
+#endif
diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp
index d69830b5c3..a5f4dc934a 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -49,6 +49,8 @@
 #include "llvoavatar.h"
 #include "llwearable.h"
 
+using namespace LLVOAvatarDefines;
+
 // static
 S32 LLWearable::sCurrentDefinitionVersion = 1;
 
@@ -392,6 +394,7 @@ BOOL LLWearable::importFile( LLFILE* file )
 	}
 	else
 	{
+		mType = WT_COUNT;
 		llwarns << "Bad Wearable asset: bad type #" << type <<  llendl;
 		return FALSE;
 	}
@@ -501,9 +504,9 @@ BOOL LLWearable::isOldVersion()
 
 
 	S32 te_count = 0;
-	for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
+	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
 	{
-		if( LLVOAvatar::getTEWearableType( te ) == mType )
+		if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
 		{
 			te_count++;
 			if( !is_in_map(mTEMap, te ) )
@@ -555,9 +558,9 @@ BOOL LLWearable::isDirty()
 		}
 	}
 
-	for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
+	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
 	{
-		if( LLVOAvatar::getTEWearableType( te ) == mType )
+		if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
 		{
 			LLViewerImage* avatar_image = avatar->getTEImage( te );
 			if( !avatar_image )
@@ -565,7 +568,7 @@ BOOL LLWearable::isDirty()
 				llassert( 0 );
 				continue;
 			}
-			const LLUUID& image_id = get_if_there(mTEMap,  te, LLVOAvatar::getDefaultTEImageID( te ) );
+			const LLUUID& image_id = get_if_there(mTEMap,  te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) );
 			if( avatar_image->getID() != image_id )
 			{
 				return TRUE;
@@ -607,11 +610,11 @@ void LLWearable::setParamsToDefaults()
 void LLWearable::setTexturesToDefaults()
 {
 	mTEMap.clear();
-	for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
+	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
 	{
-		if( LLVOAvatar::getTEWearableType( te ) == mType )
+		if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
 		{
-			mTEMap[te] = LLVOAvatar::getDefaultTEImageID( te );
+			mTEMap[te] = LLVOAvatar::getDefaultTEImageID((ETextureIndex) te );
 		}
 	}
 }
@@ -654,11 +657,11 @@ void LLWearable::writeToAvatar( BOOL set_by_user )
 	}
 
 	// Pull texture entries
-	for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
+	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
 	{
-		if( LLVOAvatar::getTEWearableType( te ) == mType )
+		if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
 		{
-			const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatar::getDefaultTEImageID( te ) );
+			const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) );
 			LLViewerImage* image = gImageList.getImage( image_id );
 			avatar->setLocTexTE( te, image, set_by_user );
 		}
@@ -731,9 +734,9 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
 
 	// Pull textures
 	LLViewerImage* image = gImageList.getImage( IMG_DEFAULT_AVATAR );
-	for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
+	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
 	{
-		if( LLVOAvatar::getTEWearableType( te ) == type )
+		if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == type )
 		{
 			avatar->setLocTexTE( te, image, set_by_user );
 		}
@@ -777,9 +780,9 @@ void LLWearable::readFromAvatar()
 	}
 
 	mTEMap.clear();
-	for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
+	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
 	{
-		if( LLVOAvatar::getTEWearableType( te ) == mType )
+		if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
 		{
 			LLViewerImage* image = avatar->getTEImage( te );
 			if( image )
@@ -828,11 +831,11 @@ void LLWearable::copyDataFrom( LLWearable* src )
 	}
 
 	// Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
-	for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
+	for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
 	{
-		if( LLVOAvatar::getTEWearableType( te ) == mType )
+		if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType )
 		{
-			const LLUUID& image_id = get_if_there(src->mTEMap, te, LLVOAvatar::getDefaultTEImageID( te ) );
+			const LLUUID& image_id = get_if_there(src->mTEMap, te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) );
 			mTEMap[te] = image_id;
 		}
 	}
diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h
index dc1a6744e0..683a8fa928 100644
--- a/indra/newview/llwearable.h
+++ b/indra/newview/llwearable.h
@@ -66,8 +66,8 @@ class LLWearable
 public:
 	~LLWearable();
 
-	const LLAssetID&		getID() { return mAssetID; }
-	const LLTransactionID&		getTransactionID() { return mTransactionID; }
+	const LLAssetID&		getID() const { return mAssetID; }
+	const LLTransactionID&		getTransactionID() const { return mTransactionID; }
 
 	BOOL				isDirty();
 	BOOL				isOldVersion();
@@ -84,16 +84,16 @@ public:
 	void				setType( EWearableType type )			{ mType = type; }
 
 	void				setName( const std::string& name )			{ mName = name; }
-	const std::string&	getName()								{ return mName; }
+	const std::string&	getName() const								{ return mName; }
 
 	void				setDescription( const std::string& desc )	{ mDescription = desc; }
-	const std::string&	getDescription()						{ return mDescription; }
+	const std::string&	getDescription() const						{ return mDescription; }
 
 	void				setPermissions( const LLPermissions& p ) { mPermissions = p; }
-	const LLPermissions& getPermissions()						{ return mPermissions; }
+	const LLPermissions& getPermissions() const						{ return mPermissions; }
 
 	void				setSaleInfo( const LLSaleInfo& info )	{ mSaleInfo = info; }
-	const LLSaleInfo&	getSaleInfo()							{ return mSaleInfo; }
+	const LLSaleInfo&	getSaleInfo() const							{ return mSaleInfo; }
 
 	const std::string&	getTypeLabel() const					{ return LLWearable::sTypeLabel[ mType ]; }
 	const std::string&	getTypeName() const						{ return LLWearable::sTypeName[ mType ]; }
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index 083d7e1581..512c03fa4d 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -102,6 +102,7 @@ void LLWearableList::getAsset( const LLAssetID& assetID, const std::string& wear
 // static
 void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID& uuid, void* userdata, S32 status, LLExtStat ext_status )
 {
+	BOOL isNewWearable = FALSE;
 	LLWearableArrivedData* data = (LLWearableArrivedData*) userdata;
 	LLWearable* wearable = NULL; // NULL indicates failure
 	
@@ -124,6 +125,10 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
 			bool res = wearable->importFile( fp );
 			if (!res)
 			{
+				if (wearable->getType() == WT_COUNT)
+				{
+					isNewWearable = TRUE;
+				}
 				delete wearable;
 				wearable = NULL;
 			}
@@ -184,7 +189,11 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
 		LLSD args;
 		// *TODO:translate
 		args["TYPE"] = LLAssetType::lookupHumanReadable(data->mAssetType);
-		if (data->mName.empty())
+		if (isNewWearable)
+		{
+			LLNotifications::instance().add("InvalidWearable");
+		}
+		else if (data->mName.empty())
 		{
 			LLNotifications::instance().add("FailedToFindWearableUnnamed", args);
 		}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 3a5e41e3ca..d90eaa9d9b 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -232,6 +232,7 @@ 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::sFastAlpha = TRUE;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index e8673c7d4c..ca0f4af1ac 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -391,6 +391,7 @@ public:
 	static S32				sCompiles;
 
 	static BOOL				sShowHUDAttachments;
+	static BOOL				sForceOldBakedUpload; // If true will not use capabilities to upload baked textures.
 	static S32				sUseOcclusion;  // 0 = no occlusion, 1 = read only, 2 = read/write
 	static BOOL				sDelayVBUpdate;
 	static BOOL				sFastAlpha;
-- 
cgit v1.2.3