Commits

Anonymous committed 63b8074 Merge

merge from PE's viewer-trunk

Comments (0)

Files changed (24)

indra/newview/llappearancemgr.cpp

 	}
 
 	//preparing the list of wearables in the correct order for LLAgentWearables
-	std::sort(wear_items.begin(), wear_items.end(), sort_by_description);
+	sortItemsByActualDescription(wear_items);
+
 
 	LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
 
 	return result;
 }
 
+//static
+void LLAppearanceMgr::sortItemsByActualDescription(LLInventoryModel::item_array_t& items)
+{
+	if (items.size() < 2) return;
+
+	std::sort(items.begin(), items.end(), sort_by_description);
+}
 
 //#define DUMP_CAT_VERBOSE
 

indra/newview/llappearancemgr.h

 	friend class LLSingleton<LLAppearanceMgr>;
 	
 public:
+	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
+
 	void updateAppearanceFromCOF();
 	bool needToSaveCOF();
 	void updateCOF(const LLUUID& category, bool append = false);
 
 	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body);
 
+	static void sortItemsByActualDescription(LLInventoryModel::item_array_t& items);
+
+	//Divvy items into arrays by wearable type
+	static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type);
+
 protected:
 	LLAppearanceMgr();
 	~LLAppearanceMgr();
 
 private:
 
-	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
-
-	//Divvy items into arrays by wearable type
-	static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type);
-
 	//Check ordering information on wearables stored in links' descriptions and update if it is invalid
 	void updateClothingOrderingInfo();
 

indra/newview/llcofwearables.cpp

 	clear();
 
 	LLInventoryModel::cat_array_t cats;
-	LLInventoryModel::item_array_t items;
+	LLInventoryModel::item_array_t cof_items;
+
+	gInventory.collectDescendents(LLAppearanceMgr::getInstance()->getCOF(), cats, cof_items, LLInventoryModel::EXCLUDE_TRASH);
+
+	populateAttachmentsAndBodypartsLists(cof_items);
+
+
+	LLAppearanceMgr::wearables_by_type_t clothing_by_type(WT_COUNT);
+	LLAppearanceMgr::getInstance()->divvyWearablesByType(cof_items, clothing_by_type);
 	
-	gInventory.collectDescendents(LLAppearanceMgr::getInstance()->getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
-	if (items.empty()) return;
+	populateClothingList(clothing_by_type);
+}
 
-	for (U32 i = 0; i < items.size(); ++i)
+
+void LLCOFWearables::populateAttachmentsAndBodypartsLists(const LLInventoryModel::item_array_t& cof_items)
+{
+	for (U32 i = 0; i < cof_items.size(); ++i)
 	{
-		LLViewerInventoryItem* item = items.get(i);
+		LLViewerInventoryItem* item = cof_items.get(i);
 		if (!item) continue;
 
+		const LLAssetType::EType item_type = item->getType();
+		if (item_type == LLAssetType::AT_CLOTHING) continue;
+
 		LLPanelInventoryListItem* item_panel = LLPanelInventoryListItem::createItemPanel(item);
 		if (!item_panel) continue;
 
-		switch (item->getType())
+		if (item_type == LLAssetType::AT_OBJECT)
 		{
-			case LLAssetType::AT_OBJECT:
-				mAttachments->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);
-				break;
-
-			case LLAssetType::AT_BODYPART:
-				mBodyParts->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);
-				break;
-
-			case LLAssetType::AT_CLOTHING:
-				mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);
-				break;
-
-			default: break;
+			mAttachments->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);
+		}
+		else if (item_type == LLAssetType::AT_BODYPART)
+		{
+			mBodyParts->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);
+			addWearableTypeSeparator(mBodyParts);
 		}
 	}
 
-	mAttachments->sort(); //*TODO by Name
-	mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false)
-	
-	mClothing->sort(); //*TODO by actual inventory item description
-	mClothing->notify(REARRANGE);
-	
-	mBodyParts->sort(); //*TODO by name
+	if (mAttachments->size())
+	{
+		mAttachments->sort(); //*TODO by Name
+		mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false)
+	}
+
+	if (mBodyParts->size())
+	{
+		mBodyParts->sort(); //*TODO by name
+	}
+
+	addListButtonBar(mBodyParts, "panel_bodyparts_list_button_bar.xml");
 	mBodyParts->notify(REARRANGE);
 }
 
 
+void LLCOFWearables::populateClothingList(LLAppearanceMgr::wearables_by_type_t& clothing_by_type)
+{
+	llassert(clothing_by_type.size() == WT_COUNT);
+
+	addListButtonBar(mClothing, "panel_clothing_list_button_bar.xml");
+
+	for (U32 type = WT_SHIRT; type < WT_COUNT; ++type)
+	{
+		U32 size = clothing_by_type[type].size();
+		if (!size) continue;
+
+		LLAppearanceMgr::sortItemsByActualDescription(clothing_by_type[type]);
+
+		for (U32 i = 0; i < size; i++)
+		{
+			LLViewerInventoryItem* item = clothing_by_type[type][i];
+
+			LLPanelInventoryListItem* item_panel = LLPanelInventoryListItem::createItemPanel(item);
+			if (!item_panel) continue;
+
+			mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);
+		}
+
+		addWearableTypeSeparator(mClothing);
+	}
+
+	addClothingTypesDummies(clothing_by_type);
+
+	mClothing->notify(REARRANGE);
+}
+
+void LLCOFWearables::addListButtonBar(LLFlatListView* list, std::string xml_filename)
+{
+	llassert(list);
+	llassert(xml_filename.length());
+	
+	LLPanel::Params params;
+	LLPanel* button_bar = LLUICtrlFactory::create<LLPanel>(params);
+	LLUICtrlFactory::instance().buildPanel(button_bar, xml_filename);
+
+	LLRect rc = button_bar->getRect();
+	button_bar->reshape(list->getItemsRect().getWidth(), rc.getHeight());
+
+	list->addItem(button_bar, LLUUID::null, ADD_TOP, false);
+}
+
+//adding dummy items for missing wearable types
+void LLCOFWearables::addClothingTypesDummies(const LLAppearanceMgr::wearables_by_type_t& clothing_by_type)
+{
+	llassert(clothing_by_type.size() == WT_COUNT);
+	
+	for (U32 type = WT_SHIRT; type < WT_COUNT; type++)
+	{
+		U32 size = clothing_by_type[type].size();
+		if (size) continue;
+
+		//*TODO create dummy item panel
+		
+		//*TODO add dummy item panel -> mClothing->addItem(dummy_item_panel, item->getUUID(), ADD_BOTTOM, false);
+
+		addWearableTypeSeparator(mClothing);
+	}
+}
+
+void LLCOFWearables::addWearableTypeSeparator(LLFlatListView* list)
+{
+	llassert(list);
+	
+	static LLXMLNodePtr separator_xml_node = getXMLNode("panel_wearable_type_separator.xml");
+	if (separator_xml_node->isNull()) return;
+
+	LLPanel* separator = LLUICtrlFactory::defaultBuilder<LLPanel>(separator_xml_node, NULL, NULL);
+
+	LLRect rc = separator->getRect();
+	rc.setOriginAndSize(0, 0, list->getItemsRect().getWidth(), rc.getHeight());
+	separator->setRect(rc);
+
+	list->addItem(separator, LLUUID::null, ADD_BOTTOM, false);
+}
+
 LLUUID LLCOFWearables::getSelectedUUID()
 {
 	if (!mLastSelectedList) return LLUUID::null;
 	mBodyParts->clear();
 }
 
+LLXMLNodePtr LLCOFWearables::getXMLNode(std::string xml_filename)
+{
+	LLXMLNodePtr xmlNode = NULL;
+	bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, xmlNode);
+	if (!success)
+	{
+		llwarning("Failed to read xml", 0);
+		return NULL;
+	}
+
+	return xmlNode;
+}
+
 //EOF

indra/newview/llcofwearables.h

 #define LL_LLCOFWEARABLES_H
 
 #include "llpanel.h"
+#include "llinventorymodel.h"
+#include "llappearancemgr.h"
 
 class LLFlatListView;
 
 
 protected:
 
+	void populateAttachmentsAndBodypartsLists(const LLInventoryModel::item_array_t& cof_items);
+	void populateClothingList(LLAppearanceMgr::wearables_by_type_t& clothing_by_type);
+	
+	void addListButtonBar(LLFlatListView* list, std::string xml_filename);
+	void addClothingTypesDummies(const LLAppearanceMgr::wearables_by_type_t& clothing_by_type);
+	void addWearableTypeSeparator(LLFlatListView* list);
 	void onSelectionChange(LLFlatListView* selected_list);
 
+	LLXMLNodePtr getXMLNode(std::string xml_filename);
+
 	LLFlatListView* mAttachments;
 	LLFlatListView* mClothing;
 	LLFlatListView* mBodyParts;

indra/newview/llimview.cpp

 
 void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)
 {
-	std::string you = LLTrans::getString("You");
-	std::string started_call = LLTrans::getString("started_call");
-	std::string joined_call = LLTrans::getString("joined_call");
+	std::string you_joined_call = LLTrans::getString("you_joined_call");
+	std::string you_started_call = LLTrans::getString("you_started_call");
 	std::string other_avatar_name = "";
 
 	std::string message;
 			switch(new_state)
 			{
 			case LLVoiceChannel::STATE_CALL_STARTED :
-				message = other_avatar_name + " " + started_call;
-				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message);
-				
-				break;
+				{
+					LLStringUtil::format_map_t string_args;
+					string_args["[NAME]"] = other_avatar_name;
+					message = LLTrans::getString("name_started_call", string_args);
+					LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message);				
+					break;
+				}
 			case LLVoiceChannel::STATE_CONNECTED :
-				message = you + " " + joined_call;
-				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_joined_call);
 			default:
 				break;
 			}
 			switch(new_state)
 			{
 			case LLVoiceChannel::STATE_CALL_STARTED :
-				message = you + " " + started_call;
-				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_started_call);
 				break;
 			case LLVoiceChannel::STATE_CONNECTED :
 				message = LLTrans::getString("answered_call");
 			switch(new_state)
 			{
 			case LLVoiceChannel::STATE_CONNECTED :
-				message = you + " " + joined_call;
-				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_joined_call);
 			default:
 				break;
 			}
 			switch(new_state)
 			{
 			case LLVoiceChannel::STATE_CALL_STARTED :
-				message = you + " " + started_call;
-				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message);
+				LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_started_call);
 				break;
 			default:
 				break;
 				// send notification message to the corresponding chat 
 				if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc")
 				{
-					std::string started_call = LLTrans::getString("started_call");
-					std::string message = mPayload["caller_name"].asString() + " " + started_call;
+					LLStringUtil::format_map_t string_args;
+					string_args["[NAME]"] = mPayload["caller_name"].asString();
+					std::string message = LLTrans::getString("name_started_call", string_args);
 					LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message);
 				}
 			}

indra/newview/llpaneleditwearable.cpp

 #include "llagentwearables.h"
 #include "llscrollingpanelparam.h"
 
+#include "llcolorswatch.h"
+#include "lltexturectrl.h"
+#include "lltextureentry.h"
+#include "llviewercontrol.h"	// gSavedSettings
+#include "llviewertexturelist.h"
+
 // register panel with appropriate XML
 static LLRegisterPanelClassWrapper<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable");
 
 	SUBPART_TATTOO
  };
 
+using namespace LLVOAvatarDefines;
+
 typedef std::vector<ESubpart> subpart_vec_t;
 
 // Locally defined classes
 		WearableEntry(EWearableType type,
 					  const std::string &title,
 					  const std::string &desc_title,
-					  U8 num_subparts, ... ); // number of subparts followed by a list of ESubparts
+					  U8 num_color_swatches,  // number of 'color_swatches'
+					  U8 num_texture_pickers, // number of 'texture_pickers'
+					  U8 num_subparts, ... ); // number of subparts followed by a list of ETextureIndex and ESubparts
 
 
 		const EWearableType mWearableType;
 		const std::string   mTitle;
 		const std::string	mDescTitle;
 		subpart_vec_t		mSubparts;
-
+		texture_vec_t		mColorSwatchCtrls;
+		texture_vec_t		mTextureCtrls;
 	};
 
 	struct Wearables : public LLDictionary<EWearableType, WearableEntry>
 	} mSubparts;
 
 	const SubpartEntry*  getSubpart(ESubpart subpart) const { return mSubparts.lookup(subpart); }
+
+	//--------------------------------------------------------------------
+	// Picker Control Entries
+	//--------------------------------------------------------------------
+public:
+	struct PickerControlEntry : public LLDictionaryEntry
+	{
+		PickerControlEntry(ETextureIndex tex_index,
+						   const std::string name,
+						   const LLUUID default_image_id = LLUUID::null,
+						   const bool allow_no_texture = false);
+		ETextureIndex		mTextureIndex;
+		const std::string	mControlName;
+		const LLUUID		mDefaultImageId;
+		const bool			mAllowNoTexture;
+	};
+
+	struct ColorSwatchCtrls : public LLDictionary<ETextureIndex, PickerControlEntry>
+	{
+		ColorSwatchCtrls();
+	} mColorSwatchCtrls;
+
+	struct TextureCtrls : public LLDictionary<ETextureIndex, PickerControlEntry>
+	{
+		TextureCtrls();
+	} mTextureCtrls;
+
+	const PickerControlEntry* getTexturePicker(ETextureIndex index) const { return mTextureCtrls.lookup(index); }
+	const PickerControlEntry* getColorSwatch(ETextureIndex index) const { return mColorSwatchCtrls.lookup(index); }
 };
 
 LLEditWearableDictionary::LLEditWearableDictionary()
 
 LLEditWearableDictionary::Wearables::Wearables()
 {
-	addEntry(WT_SHAPE, new WearableEntry(WT_SHAPE,"edit_shape_title","shape_desc_text",9,	SUBPART_SHAPE_HEAD,	SUBPART_SHAPE_EYES,	SUBPART_SHAPE_EARS,	SUBPART_SHAPE_NOSE,	SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS, SUBPART_SHAPE_WHOLE));
-	addEntry(WT_SKIN, new WearableEntry(WT_SKIN,"edit_skin_title","skin_desc_text",4, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL));
-	addEntry(WT_HAIR, new WearableEntry(WT_HAIR,"edit_hair_title","hair_desc_text",4, SUBPART_HAIR_COLOR,	SUBPART_HAIR_STYLE,	SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL));
-	addEntry(WT_EYES, new WearableEntry(WT_EYES,"edit_eyes_title","eyes_desc_text",1, SUBPART_EYES));
-	addEntry(WT_SHIRT, new WearableEntry(WT_SHIRT,"edit_shirt_title","shirt_desc_text",1, SUBPART_SHIRT));
-	addEntry(WT_PANTS, new WearableEntry(WT_PANTS,"edit_pants_title","pants_desc_text",1, SUBPART_PANTS));
-	addEntry(WT_SHOES, new WearableEntry(WT_SHOES,"edit_shoes_title","shoes_desc_text",1, SUBPART_SHOES));
-	addEntry(WT_SOCKS, new WearableEntry(WT_SOCKS,"edit_socks_title","socks_desc_text",1, SUBPART_SOCKS));
-	addEntry(WT_JACKET, new WearableEntry(WT_JACKET,"edit_jacket_title","jacket_desc_text",1, SUBPART_JACKET));
-	addEntry(WT_GLOVES, new WearableEntry(WT_GLOVES,"edit_gloves_title","gloves_desc_text",1, SUBPART_GLOVES));
-	addEntry(WT_UNDERSHIRT, new WearableEntry(WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text",1, SUBPART_UNDERSHIRT));
-	addEntry(WT_UNDERPANTS, new WearableEntry(WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text",1, SUBPART_UNDERPANTS));
-	addEntry(WT_SKIRT, new WearableEntry(WT_SKIRT,"edit_skirt_title","skirt_desc_text",1, SUBPART_SKIRT));
-	addEntry(WT_ALPHA, new WearableEntry(WT_ALPHA,"edit_alpha_title","alpha_desc_text",1, SUBPART_ALPHA));
-	addEntry(WT_TATTOO, new WearableEntry(WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",1, SUBPART_TATTOO));
+	addEntry(WT_SHAPE, new WearableEntry(WT_SHAPE,"edit_shape_title","shape_desc_text",0,0,9,	SUBPART_SHAPE_HEAD,	SUBPART_SHAPE_EYES,	SUBPART_SHAPE_EARS,	SUBPART_SHAPE_NOSE,	SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS, SUBPART_SHAPE_WHOLE));
+	addEntry(WT_SKIN, new WearableEntry(WT_SKIN,"edit_skin_title","skin_desc_text",0,3,4, TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL));
+	addEntry(WT_HAIR, new WearableEntry(WT_HAIR,"edit_hair_title","hair_desc_text",0,1,4, TEX_HAIR, SUBPART_HAIR_COLOR,	SUBPART_HAIR_STYLE,	SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL));
+	addEntry(WT_EYES, new WearableEntry(WT_EYES,"edit_eyes_title","eyes_desc_text",0,1,1, TEX_EYES_IRIS, SUBPART_EYES));
+	addEntry(WT_SHIRT, new WearableEntry(WT_SHIRT,"edit_shirt_title","shirt_desc_text",1,1,1, TEX_UPPER_SHIRT, TEX_UPPER_SHIRT, SUBPART_SHIRT));
+	addEntry(WT_PANTS, new WearableEntry(WT_PANTS,"edit_pants_title","pants_desc_text",1,1,1, TEX_LOWER_PANTS, TEX_LOWER_PANTS, SUBPART_PANTS));
+	addEntry(WT_SHOES, new WearableEntry(WT_SHOES,"edit_shoes_title","shoes_desc_text",1,1,1, TEX_LOWER_SHOES, TEX_LOWER_SHOES, SUBPART_SHOES));
+	addEntry(WT_SOCKS, new WearableEntry(WT_SOCKS,"edit_socks_title","socks_desc_text",1,1,1, TEX_LOWER_SOCKS, TEX_LOWER_SOCKS, SUBPART_SOCKS));
+	addEntry(WT_JACKET, new WearableEntry(WT_JACKET,"edit_jacket_title","jacket_desc_text",1,2,1, TEX_UPPER_JACKET, TEX_UPPER_JACKET, TEX_LOWER_JACKET, SUBPART_JACKET));
+	addEntry(WT_GLOVES, new WearableEntry(WT_GLOVES,"edit_gloves_title","gloves_desc_text",1,1,1, TEX_UPPER_GLOVES, TEX_UPPER_GLOVES, SUBPART_GLOVES));
+	addEntry(WT_UNDERSHIRT, new WearableEntry(WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text",1,1,1, TEX_UPPER_UNDERSHIRT, TEX_UPPER_UNDERSHIRT, SUBPART_UNDERSHIRT));
+	addEntry(WT_UNDERPANTS, new WearableEntry(WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text",1,1,1, TEX_LOWER_UNDERPANTS, TEX_LOWER_UNDERPANTS, SUBPART_UNDERPANTS));
+	addEntry(WT_SKIRT, new WearableEntry(WT_SKIRT,"edit_skirt_title","skirt_desc_text",1,1,1, TEX_SKIRT, TEX_SKIRT, SUBPART_SKIRT));
+	addEntry(WT_ALPHA, new WearableEntry(WT_ALPHA,"edit_alpha_title","alpha_desc_text",0,5,1, TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA, SUBPART_ALPHA));
+	addEntry(WT_TATTOO, new WearableEntry(WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",0,3,1, TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO, SUBPART_TATTOO));
 }
 
 LLEditWearableDictionary::WearableEntry::WearableEntry(EWearableType type,
 					  const std::string &title,
 					  const std::string &desc_title,
+					  U8 num_color_swatches,
+					  U8 num_texture_pickers,
 					  U8 num_subparts, ... ) :
 	LLDictionaryEntry(title),
 	mWearableType(type),
 	va_list argp;
 	va_start(argp, num_subparts);
 
+	for (U8 i = 0; i < num_color_swatches; ++i)
+	{
+		ETextureIndex index = (ETextureIndex)va_arg(argp,int);
+		mColorSwatchCtrls.push_back(index);
+	}
+
+	for (U8 i = 0; i < num_texture_pickers; ++i)
+	{
+		ETextureIndex index = (ETextureIndex)va_arg(argp,int);
+		mTextureCtrls.push_back(index);
+	}
+
 	for (U8 i = 0; i < num_subparts; ++i)
 	{
 		ESubpart part = (ESubpart)va_arg(argp,int);
 {
 }
 
+LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls()
+{
+	addEntry ( TEX_UPPER_SHIRT,  new PickerControlEntry (TEX_UPPER_SHIRT, "Color/Tint" ));
+	addEntry ( TEX_LOWER_PANTS,  new PickerControlEntry (TEX_LOWER_PANTS, "Color/Tint" ));
+	addEntry ( TEX_LOWER_SHOES,  new PickerControlEntry (TEX_LOWER_SHOES, "Color/Tint" ));
+	addEntry ( TEX_LOWER_SOCKS,  new PickerControlEntry (TEX_LOWER_SOCKS, "Color/Tint" ));
+	addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Color/Tint" ));
+	addEntry ( TEX_SKIRT,  new PickerControlEntry (TEX_SKIRT, "Color/Tint" ));
+	addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Color/Tint" ));
+	addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Color/Tint" ));
+	addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Color/Tint" ));
+}
+
+LLEditWearableDictionary::TextureCtrls::TextureCtrls()
+{
+	addEntry ( TEX_HEAD_BODYPAINT,  new PickerControlEntry (TEX_HEAD_BODYPAINT,  "Head Tattoos", LLUUID::null, TRUE ));
+	addEntry ( TEX_UPPER_BODYPAINT, new PickerControlEntry (TEX_UPPER_BODYPAINT, "Upper Tattoos", LLUUID::null, TRUE ));
+	addEntry ( TEX_LOWER_BODYPAINT, new PickerControlEntry (TEX_LOWER_BODYPAINT, "Lower Tattoos", LLUUID::null, TRUE ));
+	addEntry ( TEX_HAIR, new PickerControlEntry (TEX_HAIR, "Texture", LLUUID( gSavedSettings.getString( "UIImgDefaultHairUUID" ) ), FALSE ));
+	addEntry ( TEX_EYES_IRIS, new PickerControlEntry (TEX_EYES_IRIS, "Iris", LLUUID( gSavedSettings.getString( "UIImgDefaultEyesUUID" ) ), FALSE ));
+	addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShirtUUID" ) ), FALSE ));
+	addEntry ( TEX_LOWER_PANTS, new PickerControlEntry (TEX_LOWER_PANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultPantsUUID" ) ), FALSE ));
+	addEntry ( TEX_LOWER_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShoesUUID" ) ), FALSE ));
+	addEntry ( TEX_LOWER_SOCKS, new PickerControlEntry (TEX_LOWER_SOCKS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSocksUUID" ) ), FALSE ));
+	addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Upper Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE ));
+	addEntry ( TEX_LOWER_JACKET, new PickerControlEntry (TEX_LOWER_JACKET, "Lower Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE ));
+	addEntry ( TEX_SKIRT, new PickerControlEntry (TEX_SKIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSkirtUUID" ) ), FALSE ));
+	addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultGlovesUUID" ) ), FALSE ));
+	addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE ));
+	addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE ));
+	addEntry ( TEX_LOWER_ALPHA, new PickerControlEntry (TEX_LOWER_ALPHA, "Lower Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE ));
+	addEntry ( TEX_UPPER_ALPHA, new PickerControlEntry (TEX_UPPER_ALPHA, "Upper Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE ));
+	addEntry ( TEX_HEAD_ALPHA, new PickerControlEntry (TEX_HEAD_ALPHA, "Head Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE ));
+	addEntry ( TEX_EYES_ALPHA, new PickerControlEntry (TEX_EYES_ALPHA, "Eye Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE ));
+	addEntry ( TEX_HAIR_ALPHA, new PickerControlEntry (TEX_HAIR_ALPHA, "Hair Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE ));
+	addEntry ( TEX_LOWER_TATTOO, new PickerControlEntry (TEX_LOWER_TATTOO, "Lower Tattoo", LLUUID::null, TRUE ));
+	addEntry ( TEX_UPPER_TATTOO, new PickerControlEntry (TEX_UPPER_TATTOO, "Upper Tattoo", LLUUID::null, TRUE ));
+	addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry (TEX_HEAD_TATTOO, "Head Tattoo", LLUUID::null, TRUE ));
+}
+
+LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex tex_index,
+					 const std::string name,
+					 const LLUUID default_image_id,
+					 const bool allow_no_texture) :
+	LLDictionaryEntry(name),
+	mTextureIndex(tex_index),
+	mControlName(name),
+	mDefaultImageId(default_image_id),
+	mAllowNoTexture(allow_no_texture)
+{
+}
+
+// Helper functions.
+static const texture_vec_t null_texture_vec;
+
+// Specializations of this template function return a vector of texture indexes of particular control type
+// (i.e. LLColorSwatchCtrl or LLTextureCtrl) which are contained in given WearableEntry.
+template <typename T>
+const texture_vec_t&
+get_pickers_indexes(const LLEditWearableDictionary::WearableEntry *wearable_entry) { return null_texture_vec; }
+
+// Specializations of this template function return picker control entry for particular control type.
+template <typename T>
+const LLEditWearableDictionary::PickerControlEntry*
+get_picker_entry (const ETextureIndex index) { return NULL; }
+
+typedef boost::function<void(LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry*)> function_t;
+
+typedef struct PickerControlEntryNamePredicate
+{
+	PickerControlEntryNamePredicate(const std::string name) : mName (name) {};
+	bool operator()(const LLEditWearableDictionary::PickerControlEntry* entry) const
+	{
+		return (entry && entry->mName == mName);
+	}
+private:
+	const std::string mName;
+} PickerControlEntryNamePredicate;
+
+// A full specialization of get_pickers_indexes for LLColorSwatchCtrl
+template <>
+const texture_vec_t&
+get_pickers_indexes<LLColorSwatchCtrl> (const LLEditWearableDictionary::WearableEntry *wearable_entry)
+{
+	if (!wearable_entry)
+	{
+		llwarns << "could not get LLColorSwatchCtrl indexes for null wearable entry." << llendl;
+		return null_texture_vec;
+	}
+	return wearable_entry->mColorSwatchCtrls;
+}
+
+// A full specialization of get_pickers_indexes for LLTextureCtrl
+template <>
+const texture_vec_t&
+get_pickers_indexes<LLTextureCtrl> (const LLEditWearableDictionary::WearableEntry *wearable_entry)
+{
+	if (!wearable_entry)
+	{
+		llwarns << "could not get LLTextureCtrl indexes for null wearable entry." << llendl;
+		return null_texture_vec;
+	}
+	return wearable_entry->mTextureCtrls;
+}
+
+// A full specialization of get_picker_entry for LLColorSwatchCtrl
+template <>
+const LLEditWearableDictionary::PickerControlEntry*
+get_picker_entry<LLColorSwatchCtrl> (const ETextureIndex index)
+{
+	return LLEditWearableDictionary::getInstance()->getColorSwatch(index);
+}
+
+// A full specialization of get_picker_entry for LLTextureCtrl
+template <>
+const LLEditWearableDictionary::PickerControlEntry*
+get_picker_entry<LLTextureCtrl> (const ETextureIndex index)
+{
+	return LLEditWearableDictionary::getInstance()->getTexturePicker(index);
+}
+
+template <typename CtrlType, class Predicate>
+const LLEditWearableDictionary::PickerControlEntry*
+find_picker_ctrl_entry_if(EWearableType type, const Predicate pred)
+{
+	const LLEditWearableDictionary::WearableEntry *wearable_entry
+		= LLEditWearableDictionary::getInstance()->getWearable(type);
+	if (!wearable_entry)
+	{
+		llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl;
+		return NULL;
+	}
+	const texture_vec_t& indexes = get_pickers_indexes<CtrlType>(wearable_entry);
+	for (texture_vec_t::const_iterator
+			 iter = indexes.begin(),
+			 iter_end = indexes.end();
+		 iter != iter_end; ++iter)
+	{
+		const ETextureIndex te = *iter;
+		const LLEditWearableDictionary::PickerControlEntry*	entry
+			= get_picker_entry<CtrlType>(te);
+		if (!entry)
+		{
+			llwarns << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << llendl;
+			continue;
+		}
+		if (pred(entry))
+		{
+			return entry;
+		}
+	}
+	return NULL;
+}
+
+template <typename CtrlType>
+void
+for_each_picker_ctrl_entry(LLPanel* panel, EWearableType type, function_t fun)
+{
+	if (!panel)
+	{
+		llwarns << "the panel wasn't passed for wearable of type: " << type << llendl;
+		return;
+	}
+	const LLEditWearableDictionary::WearableEntry *wearable_entry
+		= LLEditWearableDictionary::getInstance()->getWearable(type);
+	if (!wearable_entry)
+	{
+		llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl;
+		return;
+	}
+	const texture_vec_t& indexes = get_pickers_indexes<CtrlType>(wearable_entry);
+	for (texture_vec_t::const_iterator
+			 iter = indexes.begin(),
+			 iter_end = indexes.end();
+		 iter != iter_end; ++iter)
+	{
+		const ETextureIndex te = *iter;
+		const LLEditWearableDictionary::PickerControlEntry*	entry
+			= get_picker_entry<CtrlType>(te);
+		if (!entry)
+		{
+			llwarns << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << llendl;
+			continue;
+		}
+		fun (panel, entry);
+	}
+}
+
+// The helper functions for pickers management
+static void init_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry)
+{
+	LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild<LLColorSwatchCtrl>(entry->mControlName);
+	if (color_swatch_ctrl)
+	{
+		color_swatch_ctrl->setOriginal(self->getWearable()->getClothesColor(entry->mTextureIndex));
+	}
+}
+
+static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry)
+{
+	LLTextureCtrl* texture_ctrl = panel->getChild<LLTextureCtrl>(entry->mControlName);
+	if (texture_ctrl)
+	{
+		texture_ctrl->setDefaultImageAssetID(entry->mDefaultImageId);
+		texture_ctrl->setAllowNoTexture(entry->mAllowNoTexture);
+		// Don't allow (no copy) or (notransfer) textures to be selected.
+		texture_ctrl->setImmediateFilterPermMask(PERM_NONE);
+		texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE);
+	}
+}
+
+static void update_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry)
+{
+	LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild<LLColorSwatchCtrl>(entry->mControlName);
+	if (color_swatch_ctrl)
+	{
+		color_swatch_ctrl->set(self->getWearable()->getClothesColor(entry->mTextureIndex));
+	}
+}
+
+static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry)
+{
+	LLTextureCtrl* texture_ctrl = panel->getChild<LLTextureCtrl>(entry->mControlName);
+	if (texture_ctrl)
+	{
+		LLUUID new_id;
+		LLLocalTextureObject *lto = self->getWearable()->getLocalTextureObject(entry->mTextureIndex);
+		if( lto && (lto->getID() != IMG_DEFAULT_AVATAR) )
+		{
+			new_id = lto->getID();
+		}
+		else
+		{
+			new_id = LLUUID::null;
+		}
+		LLUUID old_id = texture_ctrl->getImageAssetID();
+		if (old_id != new_id)
+		{
+			// texture has changed, close the floater to avoid DEV-22461
+			texture_ctrl->closeDependentFloater();
+		}
+		texture_ctrl->setImageAssetID(new_id);
+	}
+}
+
+static void set_enabled_color_swatch_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry)
+{
+	LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild<LLColorSwatchCtrl>(entry->mControlName);
+	if (color_swatch_ctrl)
+	{
+		color_swatch_ctrl->setEnabled(enabled);
+	}
+}
+
+static void set_enabled_texture_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry)
+{
+	LLTextureCtrl* texture_ctrl = panel->getChild<LLTextureCtrl>(entry->mControlName);
+	if (texture_ctrl)
+	{
+		texture_ctrl->setEnabled(enabled);
+	}
+}
 
 // LLPanelEditWearable
 
 	, mWearablePtr(NULL)
 	, mWearableItem(NULL)
 {
+	mCommitCallbackRegistrar.add("ColorSwatch.Commit", boost::bind(&LLPanelEditWearable::onColorSwatchCommit, this, _1));
+	mCommitCallbackRegistrar.add("TexturePicker.Commit", boost::bind(&LLPanelEditWearable::onTexturePickerCommit, this, _1));
 }
 
 //virtual
 void LLPanelEditWearable::draw()
 {
 	updateVerbs();
+	if (getWearable())
+	{
+		updatePanelPickerControls(getWearable()->getType());
+	}
 
 	LLPanel::draw();
 }
 	panel->revertChanges();
 }
 
+void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
+{
+	const LLTextureCtrl* texture_ctrl = dynamic_cast<const LLTextureCtrl*>(ctrl);
+	if (!texture_ctrl)
+	{
+		llwarns << "got commit signal from not LLTextureCtrl." << llendl;
+		return;
+	}
+
+	if (getWearable())
+	{
+		EWearableType type = getWearable()->getType();
+		const PickerControlEntryNamePredicate name_pred(texture_ctrl->getName());
+		const LLEditWearableDictionary::PickerControlEntry* entry
+			= find_picker_ctrl_entry_if<LLTextureCtrl, PickerControlEntryNamePredicate>(type, name_pred);
+		if (entry)
+		{
+			// Set the new version
+			LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID());
+			if( image->getID().isNull() )
+			{
+				image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
+			}
+			if (getWearable())
+			{
+				U32 index = gAgentWearables.getWearableIndex(getWearable());
+				gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
+				LLVisualParamHint::requestHintUpdates();
+				gAgentAvatarp->wearableUpdated(type, FALSE);
+			}
+		}
+		else
+		{
+			llwarns << "could not get texture picker dictionary entry for wearable of type: " << type << llendl;
+		}
+	}
+}
+
+void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl)
+{
+	if (getWearable())
+	{
+		EWearableType type = getWearable()->getType();
+		const PickerControlEntryNamePredicate name_pred(ctrl->getName());
+		const LLEditWearableDictionary::PickerControlEntry* entry
+			= find_picker_ctrl_entry_if<LLColorSwatchCtrl, PickerControlEntryNamePredicate>(type, name_pred);
+		if (entry)
+		{
+			const LLColor4& old_color = getWearable()->getClothesColor(entry->mTextureIndex);
+			const LLColor4& new_color = LLColor4(ctrl->getValue());
+			if( old_color != new_color )
+			{
+				getWearable()->setClothesColor(entry->mTextureIndex, new_color, TRUE);
+				LLVisualParamHint::requestHintUpdates();
+				gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE);
+			}
+		}
+		else
+		{
+			llwarns << "could not get color swatch dictionary entry for wearable of type: " << type << llendl;
+		}
+	}
+}
+
+void LLPanelEditWearable::updatePanelPickerControls(EWearableType type)
+{
+	LLPanel* panel = getPanel(type);
+	if (!panel)
+		return;
+
+	bool is_modifiable = false;
+	bool is_complete   = false;
+	bool is_copyable   = false;
+
+	if(mWearableItem)
+	{
+		const LLPermissions& perm = mWearableItem->getPermissions();
+		is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID());
+		is_copyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID());
+		is_complete = mWearableItem->isFinished();
+	}
+
+	if (is_modifiable && is_complete)
+	{
+		// Update picker controls
+		for_each_picker_ctrl_entry <LLColorSwatchCtrl> (panel, type, boost::bind(update_color_swatch_ctrl, this, _1, _2));
+		for_each_picker_ctrl_entry <LLTextureCtrl>     (panel, type, boost::bind(update_texture_ctrl, this, _1, _2));
+	}
+
+	if (!is_modifiable || !is_complete || !is_copyable)
+	{
+		// Disable controls
+		for_each_picker_ctrl_entry <LLColorSwatchCtrl> (panel, type, boost::bind(set_enabled_color_swatch_ctrl, false, _1, _2));
+		for_each_picker_ctrl_entry <LLTextureCtrl>     (panel, type, boost::bind(set_enabled_texture_ctrl, false, _1, _2));
+	}
+}
 
 void LLPanelEditWearable::saveChanges()
 {
 		mDescTitle->setText(description_title);
 	}
 
+	// Update picker controls state
+	for_each_picker_ctrl_entry <LLColorSwatchCtrl> (targetPanel, type, boost::bind(set_enabled_color_swatch_ctrl, show, _1, _2));
+	for_each_picker_ctrl_entry <LLTextureCtrl>     (targetPanel, type, boost::bind(set_enabled_texture_ctrl, show, _1, _2));
 }
 
 void LLPanelEditWearable::initializePanel()
 
 		updateScrollingPanelUI();
 	}
+
+	// initialize texture and color picker controls
+	for_each_picker_ctrl_entry <LLColorSwatchCtrl> (getPanel(type), type, boost::bind(init_color_swatch_ctrl, this, _1, _2));
+	for_each_picker_ctrl_entry <LLTextureCtrl>     (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2));
+
 	updateVerbs();
 }
 

indra/newview/llpaneleditwearable.h

 	// update bottom bar buttons ("Save", "Revert", etc)
 	void				updateVerbs();
 
+	void				onColorSwatchCommit(const LLUICtrl*);
+	void				onTexturePickerCommit(const LLUICtrl*);
+	void				updatePanelPickerControls(EWearableType type);
+
 	// the pointer to the wearable we're editing. NULL means we're not editing a wearable.
 	LLWearable *mWearablePtr;
 	LLViewerInventoryItem* mWearableItem;
 	LLPanel *mPanelSkirt;
 	LLPanel *mPanelAlpha;
 	LLPanel *mPanelTattoo;
-
 };
 
 #endif

indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml

+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+
+<panel
+ follows="left|right|top"
+ height="35"
+ layout="topleft"
+ left="0"
+ name="clothing_list_button_bar_panel"
+ top="0"
+ visible="true"
+ width="300">
+    <button
+     follows="top|left"
+     height="25"
+     image_hover_unselected="Toolbar_Middle_Over"
+     image_selected="Toolbar_Middle_Selected"
+     image_unselected="Toolbar_Middle_Off"
+     label="Switch"
+     layout="topleft"
+     left="5"
+     name="switch_btn"
+     top="5"
+     width="45" />
+    <button
+     follows="top|right"
+     height="25"
+     image_hover_unselected="Toolbar_Middle_Over"
+     image_selected="Toolbar_Middle_Selected"
+     image_unselected="Toolbar_Middle_Off"
+     label="Shop >" 
+     layout="topleft"
+     right="-5"
+     name="bodyparts_shop_btn"
+     top="5"
+     width="61" />
+</panel>

indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml

+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+
+<panel
+ follows="left|right|top"
+ height="35"
+ layout="topleft"
+ left="0"
+ name="clothing_list_button_bar_panel"
+ top="0"
+ visible="true"
+ width="500">
+    <button
+     follows="top|left"
+     height="25"
+     image_hover_unselected="Toolbar_Middle_Over"
+     image_selected="Toolbar_Middle_Selected"
+     image_unselected="Toolbar_Middle_Off"
+     is_toggle="true"
+     label="Add +"
+     layout="topleft"
+     left="5"
+     name="add_btn"
+     top="5"
+     width="45" />
+    <button
+     follows="top|right"
+     height="25"
+     image_hover_unselected="Toolbar_Middle_Over"
+     image_selected="Toolbar_Middle_Selected"
+     image_unselected="Toolbar_Middle_Off"
+     label="Shop >" 
+     layout="topleft"
+     right="-5"
+     name="clothing_shop_btn"
+     top="5"
+     width="61" />
+</panel>

indra/newview/skins/default/xui/en/panel_cof_wearables.xml

      height="373"
      layout="topleft"
      left="3"
+     single_expansion="true"
      top="0"
      name="cof_wearables_accordion"
      background_visible="true"

indra/newview/skins/default/xui/en/panel_edit_alpha.xml

         name="Lower Alpha"
         tool_tip="Click to choose a picture"
         top="10"
-        width="94" />
+        width="94" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <check_box
         control_name="LowerAlphaTextureInvisible"
         follows="left"
         name="Upper Alpha"
         tool_tip="Click to choose a picture"
         top="10"
-        width="94" />
+        width="94">
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <check_box
         control_name="UpperAlphaTextureInvisible"
         follows="left"
         name="Head Alpha"
         tool_tip="Click to choose a picture"
         top="120"
-        width="94" />
+        width="94" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <check_box
         control_name="HeadAlphaTextureInvisible"
         follows="left"
         name="Eye Alpha"
         tool_tip="Click to choose a picture"
         top="120"
-        width="94" />
+        width="94" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <check_box
         control_name="Eye AlphaTextureInvisible"
         follows="left"
         name="Hair Alpha"
         tool_tip="Click to choose a picture"
         top="230"
-        width="94" />
+        width="94" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <check_box
         control_name="HairAlphaTextureInvisible"
         follows="left"

indra/newview/skins/default/xui/en/panel_edit_eyes.xml

              name="Iris"
              tool_tip="Click to choose a picture"
              top="10"
-             width="64" />
-	 </panel>
+             width="64" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
+     </panel>
      <panel
          border="false"
          bg_alpha_color="DkGray2"

indra/newview/skins/default/xui/en/panel_edit_gloves.xml

         name="Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="64" />
+        width="64" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <color_swatch
         can_apply_immediately="true"
         follows="left|top"
         name="Color/Tint"
         tool_tip="Click to open color picker"
         top="10"
-        width="64" />
-	 </panel>
-	 <panel
+        width="64" >
+         <color_swatch.commit_callback
+             function="ColorSwatch.Commit" />
+       </color_swatch>
+     </panel>
+     <panel
          border="false"
          bg_alpha_color="DkGray2"
          bg_opaque_color="DkGray2"

indra/newview/skins/default/xui/en/panel_edit_hair.xml

              name="Texture"
              tool_tip="Click to choose a picture"
              top="10"
-             width="64" />
-	 </panel>
+             width="64" >
+              <texture_picker.commit_callback
+                  function="TexturePicker.Commit" />
+            </texture_picker>
+     </panel>
    <panel
          border="false"
          bg_alpha_color="DkGray2"

indra/newview/skins/default/xui/en/panel_edit_jacket.xml

         name="Upper Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="74" />
+        width="74" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <texture_picker
         can_apply_immediately="true"
         default_image_name="Default"
         name="Lower Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="74" />
+        width="74" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <color_swatch
         can_apply_immediately="true"
         follows="left|top"
         name="Color/Tint"
         tool_tip="Click to open color picker"
         top="10"
-        width="74" />
+        width="74" >
+         <color_swatch.commit_callback
+             function="ColorSwatch.Commit" />
+       </color_swatch>
 	 </panel>
 	 <panel
          border="false"

indra/newview/skins/default/xui/en/panel_edit_pants.xml

         name="Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="64" />
+        width="64" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <color_swatch
         can_apply_immediately="true"
         follows="left|top"
         name="Color/Tint"
         tool_tip="Click to open color picker"
         top="10"
-        width="64" />
+        width="64" >
+         <color_swatch.commit_callback
+             function="ColorSwatch.Commit" />
+       </color_swatch>
 	 </panel>
      <panel
          border="false"

indra/newview/skins/default/xui/en/panel_edit_shirt.xml

         name="Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="64" />
+        width="64" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <color_swatch
         can_apply_immediately="true"
         follows="left|top"
         name="Color/Tint"
         tool_tip="Click to open color picker"
         top="10"
-        width="64" />
+        width="64" >
+         <color_swatch.commit_callback
+             function="ColorSwatch.Commit" />
+       </color_swatch>
 	 </panel>
      <panel
          border="false"

indra/newview/skins/default/xui/en/panel_edit_shoes.xml

         name="Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="64" />
+        width="64" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <color_swatch
         can_apply_immediately="true"
         follows="left|top"
         name="Color/Tint"
         tool_tip="Click to open color picker"
         top="10"
-        width="64" />
+        width="64" >
+         <color_swatch.commit_callback
+             function="ColorSwatch.Commit" />
+       </color_swatch>
 	 </panel>
      <panel
          border="false"

indra/newview/skins/default/xui/en/panel_edit_skin.xml

         name="Head Tattoos"
         tool_tip="Click to choose a picture"
         top="10"
-        width="74" />
+        width="74" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <texture_picker
         allow_no_texture="true"
         can_apply_immediately="true"
         name="Upper Tattoos"
         tool_tip="Click to choose a picture"
         top="10"
-        width="74" />
+        width="74" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <texture_picker
         allow_no_texture="true"
         can_apply_immediately="true"
         name="Lower Tattoos"
         tool_tip="Click to choose a picture"
         top="10"
-        width="74" />
-	 </panel>
+        width="74" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
+     </panel>
      <panel
          border="false"
          bg_alpha_color="DkGray2"

indra/newview/skins/default/xui/en/panel_edit_skirt.xml

         name="Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="64" />
+        width="64" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <color_swatch
         can_apply_immediately="true"
         follows="left|top"
         name="Color/Tint"
         tool_tip="Click to open color picker"
         top="10"
-        width="64" />
+        width="64" >
+         <color_swatch.commit_callback
+             function="ColorSwatch.Commit" />
+       </color_swatch>
 	 </panel>
 	 <panel
          border="false"

indra/newview/skins/default/xui/en/panel_edit_socks.xml

         name="Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="64" />
+        width="64" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <color_swatch
         can_apply_immediately="true"
         follows="left|top"
         name="Color/Tint"
         tool_tip="Click to open color picker"
         top="10"
-        width="64" />
+        width="64" >
+         <color_swatch.commit_callback
+             function="ColorSwatch.Commit" />
+       </color_swatch>
 	 </panel>
 	 <panel
          border="false"

indra/newview/skins/default/xui/en/panel_edit_underpants.xml

              name="Fabric"
              tool_tip="Click to choose a picture"
              top="10"
-             width="64" />
+             width="64" >
+              <texture_picker.commit_callback
+                  function="TexturePicker.Commit" />
+            </texture_picker>
             <color_swatch
              can_apply_immediately="true"
              follows="left|top"
              name="Color/Tint"
              tool_tip="Click to open color picker"
              top="10"
-             width="64" />
+             width="64" >
+              <color_swatch.commit_callback
+                  function="ColorSwatch.Commit" />
+            </color_swatch>
 	 </panel>
 	 <panel
          border="false"

indra/newview/skins/default/xui/en/panel_edit_undershirt.xml

         name="Fabric"
         tool_tip="Click to choose a picture"
         top="10"
-        width="64" />
+        width="64" >
+         <texture_picker.commit_callback
+             function="TexturePicker.Commit" />
+       </texture_picker>
        <color_swatch
         can_apply_immediately="true"
         follows="left|top"
         name="Color/Tint"
         tool_tip="Click to open Color Picker"
         top="10"
-        width="64" />
+        width="64" >
+         <color_swatch.commit_callback
+             function="ColorSwatch.Commit" />
+       </color_swatch>
        </panel>
 	 <panel
          border="false"

indra/newview/skins/default/xui/en/strings.xml

 
 	<!-- voice calls -->
 	<string name="answered_call">Your call has been answered</string>
-	<string name="started_call">Started a voice call</string>
-	<string name="joined_call">Joined the voice call</string>
+	<string name="you_started_call">You started a voice call</string>
+	<string name="you_joined_call">You joined the voice call</string>
+	<string name="name_started_call">[NAME] started a voice call</string>
 
   <string name="ringing-im">
     Joining voice call...