diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 47f290ad3b2afc6da6f7f365db45db6059c7616c..644363826a00173b0984da911007761e1cd72987 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -2360,7 +2360,6 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came
 				mAnimationDuration = gSavedSettings.getF32("ZoomTime");
 			}
 		}
-		setFocusGlobal(LLVector3d::zero);
 	}
 	else
 	{
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 8d0e3d46478ca708bdeed37bcb008be30c930fe4..6a84886e3b514a1c1d96f35347afe67545a9c8cb 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -51,6 +51,7 @@
 #include "llagentwearables.h"
 #include "llscrollingpanelparam.h"
 #include "llradiogroup.h"
+#include "llnotificationsutil.h"
 
 #include "llcolorswatch.h"
 #include "lltexturectrl.h"
@@ -624,6 +625,7 @@ BOOL LLPanelEditWearable::postBuild()
 	mDescTitle = getChild<LLTextBox>("description_text");
 
 	getChild<LLRadioGroup>("sex_radio")->setCommitCallback(boost::bind(&LLPanelEditWearable::onCommitSexChange, this));
+	getChild<LLButton>("save_as_button")->setCommitCallback(boost::bind(&LLPanelEditWearable::onSaveAsButtonClicked, this));
 
 	// The following panels will be shown/hidden based on what wearable we're editing
 	// body parts
@@ -744,6 +746,28 @@ void LLPanelEditWearable::onRevertButtonClicked(void* userdata)
 	panel->revertChanges();
 }
 
+void LLPanelEditWearable::onSaveAsButtonClicked()
+{
+	LLSD args;
+	args["DESC"] = mTextEditor->getText();
+
+	LLNotificationsUtil::add("SaveWearableAs", args, LLSD(), boost::bind(&LLPanelEditWearable::saveAsCallback, this, _1, _2));
+}
+
+void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& response)
+{
+	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+	if (0 == option)
+	{
+		std::string wearable_name = response["message"].asString();
+		LLStringUtil::trim(wearable_name);
+		if( !wearable_name.empty() )
+		{
+			mTextEditor->setText(wearable_name);
+			saveChanges();
+		}
+	}
+}
 
 void LLPanelEditWearable::onCommitSexChange()
 {
diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h
index 6b376fe3d9ca8c7350fb0c83945b5d1716f5ac45..1ee150621a98be6383616c8d072b1ee494d3ba09 100644
--- a/indra/newview/llpaneleditwearable.h
+++ b/indra/newview/llpaneleditwearable.h
@@ -72,6 +72,8 @@ class LLPanelEditWearable : public LLPanel
 
 	static void			onRevertButtonClicked(void* userdata);
 	void				onCommitSexChange();
+	void				onSaveAsButtonClicked();
+	void				saveAsCallback(const LLSD& notification, const LLSD& response);
 
 
 private:
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index edd9ae16a9bfa60993d7a0c17996a04029a5ae54..d001d692a328f816e7c220cb0100b6eb83521a0f 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -317,11 +317,26 @@ BOOL LLTexLayerSetBuffer::render()
 	return success;
 }
 
-bool LLTexLayerSetBuffer::isInitialized(void) const
+BOOL LLTexLayerSetBuffer::isInitialized(void) const
 {
 	return mGLTexturep.notNull() && mGLTexturep->isGLTextureCreated();
 }
 
+BOOL LLTexLayerSetBuffer::uploadPending() const
+{
+	return mUploadPending;
+}
+
+BOOL LLTexLayerSetBuffer::uploadNeeded() const
+{
+	return mNeedsUpload;
+}
+
+BOOL LLTexLayerSetBuffer::uploadInProgress() const
+{
+	return !mUploadID.isNull();
+}
+
 BOOL LLTexLayerSetBuffer::isReadyToUpload() const
 {
 	if (!mNeedsUpload) return FALSE; // Don't need to upload if we haven't requested one.
@@ -2287,10 +2302,15 @@ const std::string LLTexLayerSetBuffer::dumpTextureInfo() const
 	const BOOL is_high_res = !mNeedsUpload;
 	const U32 num_low_res = mNumLowresUploads;
 	const U32 upload_time = (U32)mNeedsUploadTimer.getElapsedTimeF32();
-	const BOOL is_uploaded = !mUploadPending;
 	const std::string local_texture_info = gAgentAvatarp->debugDumpLocalTextureDataInfo(mTexLayerSet);
-	std::string text = llformat("[ HiRes:%d LoRes:%d Uploaded:%d ] [ Timer:%d ] %s",
-								is_high_res, num_low_res, is_uploaded,
+
+	std::string status 				= "CREATING ";
+	if (!uploadNeeded()) status 	= "DONE     ";
+	if (uploadInProgress()) status 	= "UPLOADING";
+
+	std::string text = llformat("[%s] [HiRes:%d LoRes:%d] [Elapsed:%d] %s",
+								status.c_str(),
+								is_high_res, num_low_res,
 								upload_time, 
 								local_texture_info.c_str());
 	return text;
diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h
index 821e718347c784540b3da64e1a1ae0ca160c51d7..cb2e1faaa68ff6311d260083e05373d67ec6c7d1 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/newview/lltexlayer.h
@@ -275,12 +275,16 @@ class LLTexLayerSetBuffer : public LLViewerDynamicTexture
 	virtual void			postRender(BOOL success);
 	virtual BOOL			render();
 	BOOL					updateImmediate();
-	bool					isInitialized(void) const;
+
+	BOOL					isInitialized(void) const;
+	BOOL					uploadPending() const; // We are expecting a new texture to be uploaded at some point
+	BOOL					uploadNeeded() const; // We need to upload a new texture
+	BOOL					uploadInProgress() const; // We have started uploading a new texture and are awaiting the result
+
 	/*virtual*/ BOOL		needsRender();
 	void					requestUpdate();
 	void					requestUpload();
 	void					cancelUpload();
-	BOOL					uploadPending() const { return mUploadPending; }
 	BOOL					render(S32 x, S32 y, S32 width, S32 height);
 	void					readBackAndUpload();
 	static void				onTextureUploadComplete(const LLUUID& uuid,
@@ -290,6 +294,8 @@ class LLTexLayerSetBuffer : public LLViewerDynamicTexture
 	const std::string		dumpTextureInfo() const;
 	virtual void 			restoreGLTexture();
 	virtual void 			destroyGLTexture();
+
+
 protected:
 	void					pushProjection() const;
 	void					popProjection() const;
@@ -300,7 +306,7 @@ class LLTexLayerSetBuffer : public LLViewerDynamicTexture
 	LLTexLayerSet* const    mTexLayerSet;
 	BOOL					mNeedsUpdate; // whether we need to update our baked textures
 	BOOL					mNeedsUpload; // whether we need to send our baked textures to the server
-	U32						mNumLowresUploads; // mumber of times we've sent a lowres version of our baked textures to the server
+	U32						mNumLowresUploads; // number of times we've sent a lowres version of our baked textures to the server
 	BOOL					mUploadPending; // whether we have received back the new baked textures
 	LLUUID					mUploadID; // the current upload process (null if none).  Used to avoid overlaps, e.g. when the user rapidly makes two changes outside of Face Edit.
 	static S32				sGLByteCount;
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 377449cc8bc7246f2d5281f5030562ff22253da6..8ea4dbeb04d66d3c1bc76d130223128061ad3109 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -418,10 +418,10 @@ void LLAvatarTexBar::draw()
 
 	const S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
 	const S32 v_offset = 0;
+	const S32 l_offset = 3;
 
 	//----------------------------------------------------------------------------
 	LLGLSUIDefault gls_ui;
-	LLColor4 text_color(1.f, 1.f, 1.f, 1.f);
 	LLColor4 color;
 	
 	U32 line_num = 1;
@@ -434,19 +434,36 @@ void LLAvatarTexBar::draw()
 		if (!layerset) continue;
 		const LLTexLayerSetBuffer *layerset_buffer = layerset->getComposite();
 		if (!layerset_buffer) continue;
+
+		LLColor4 text_color = LLColor4::white;
+		
+		if (layerset_buffer->uploadNeeded())
+		{
+			text_color = LLColor4::red;
+		}
+ 		if (layerset_buffer->uploadInProgress())
+		{
+			text_color = LLColor4::magenta;
+		}
 		std::string text = layerset_buffer->dumpTextureInfo();
-		LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*line_num,
+		LLFontGL::getFontMonospace()->renderUTF8(text, 0, l_offset, v_offset + line_height*line_num,
 												 text_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
 		line_num++;
 	}
 	const U32 texture_timeout = gSavedSettings.getU32("AvatarBakedTextureTimeout");
 	const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel");
 	
+	LLColor4 header_color(1.f, 1.f, 1.f, 0.9f);
+
 	const std::string texture_timeout_str = texture_timeout ? llformat("%d",texture_timeout) : "Disabled";
 	const std::string override_tex_discard_level_str = override_tex_discard_level ? llformat("%d",override_tex_discard_level) : "Disabled";
 	std::string header_text = llformat("[ Timeout('AvatarBakedTextureTimeout'):%s ] [ LOD_Override('TextureDiscardLevel'):%s ]", texture_timeout_str.c_str(), override_tex_discard_level_str.c_str());
-	LLFontGL::getFontMonospace()->renderUTF8(header_text, 0, 0, v_offset + line_height*line_num,
-											 text_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
+	LLFontGL::getFontMonospace()->renderUTF8(header_text, 0, l_offset, v_offset + line_height*line_num,
+											 header_color, LLFontGL::LEFT, LLFontGL::TOP); //, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
+	line_num++;
+	std::string section_text = "Avatar Textures Information:";
+	LLFontGL::getFontMonospace()->renderUTF8(section_text, 0, 0, v_offset + line_height*line_num,
+											 header_color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD, LLFontGL::DROP_SHADOW_SOFT);
 }
 
 BOOL LLAvatarTexBar::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -457,7 +474,7 @@ BOOL LLAvatarTexBar::handleMouseDown(S32 x, S32 y, MASK mask)
 LLRect LLAvatarTexBar::getRequiredRect()
 {
 	LLRect rect;
-	rect.mTop = 85;
+	rect.mTop = 100;
 	if (!gSavedSettings.getBOOL("DebugAvatarRezTime")) rect.mTop = 0;
 	return rect;
 }
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index e18b617120afa7c5a9f30a2206d0724a3260a856..4a04ec22c4b85626ac82b1156345a55b5031f7c7 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1884,7 +1884,7 @@ const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLTexLayer
 		if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet)
 		{
 			const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
-			text += llformat("[%d] '%s' ( ",baked_index, baked_dict->mName.c_str());
+			text += llformat("%d-%s ( ",baked_index, baked_dict->mName.c_str());
 			for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
 				 local_tex_iter != baked_dict->mLocalTextures.end();
 				 ++local_tex_iter)
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 5ead756d208cd7684db81976c5922cc7db22dcd2..9af358eff389d71a616e61aee5005bc56cab99a6 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2068,6 +2068,29 @@ Would you be my friend?
     </form>
   </notification>
 
+  <notification
+ icon="alertmodal.tga"
+ label="Save Wearable"
+ name="SaveWearableAs"
+ type="alertmodal">
+    Save item to my inventory as:
+    <form name="form">
+      <input name="message" type="text">
+        [DESC] (new)
+      </input>
+      <button
+       default="true"
+       index="0"
+       name="Offer"
+       text="OK"/>
+      <button
+       index="1"
+       name="Cancel"
+       text="Cancel"/>
+    </form>
+  </notification>
+
+
   <notification
    icon="alertmodal.tga"
    label="Rename Outfit"