diff options
| author | Igor Borovkov <iborovkov@productengine.com> | 2010-04-28 17:47:08 +0300 | 
|---|---|---|
| committer | Igor Borovkov <iborovkov@productengine.com> | 2010-04-28 17:47:08 +0300 | 
| commit | f9a120e8983a72b6de2f146acec55e079255b70e (patch) | |
| tree | 4dabbf42f91339dcf68feb5b94fa630509a2d55e | |
| parent | 8e0a73f0edea77c6fac4303a5a77a72f1db4a233 (diff) | |
partial implementation of EXT-6723 Create specialized view of inventory for "clothing" accordion tab of outfit editor
- added grouping clothing items by wearable type (shirt, jeans etc.)
- added sorting clothing items by wearing order in groups
- added separators between items of the same wearable type (lists: clothing, body parts)
- added list specific button bars
- partially added dummy items for missing wearable types in the COF (clothing list)
Reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/322
--HG--
branch : product-engine
| -rw-r--r-- | indra/newview/llappearancemgr.cpp | 10 | ||||
| -rw-r--r-- | indra/newview/llappearancemgr.h | 12 | ||||
| -rw-r--r-- | indra/newview/llcofwearables.cpp | 149 | ||||
| -rw-r--r-- | indra/newview/llcofwearables.h | 10 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml | 36 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml | 37 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_cof_wearables.xml | 1 | 
7 files changed, 227 insertions, 28 deletions
| diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5586b3cd4d..e93e29ecde 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1092,7 +1092,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF()  	}  	//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; @@ -1910,6 +1911,13 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b  	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 diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index a308a3efa9..516dada39d 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -48,6 +48,8 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>  	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); @@ -143,17 +145,17 @@ public:  	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(); diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index f0442ee3f6..e21644e119 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -94,47 +94,139 @@ void LLCOFWearables::refresh()  	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; +			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); +		} +	} + +	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) +	} -			case LLAssetType::AT_BODYPART: -				mBodyParts->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); -				break; +	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]; -			case LLAssetType::AT_CLOTHING: -				mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); -				break; +			LLPanelInventoryListItem* item_panel = LLPanelInventoryListItem::createItemPanel(item); +			if (!item_panel) continue; -			default: break; +			mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false);  		} + +		addWearableTypeSeparator(mClothing);  	} -	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 +	addClothingTypesDummies(clothing_by_type); +  	mClothing->notify(REARRANGE); +} + +void LLCOFWearables::addListButtonBar(LLFlatListView* list, std::string xml_filename) +{ +	llassert(list); +	llassert(xml_filename.length()); -	mBodyParts->sort(); //*TODO by name -	mBodyParts->notify(REARRANGE); +	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()  { @@ -150,4 +242,17 @@ void LLCOFWearables::clear()  	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 diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h index 58d67ed32f..28d58887da 100644 --- a/indra/newview/llcofwearables.h +++ b/indra/newview/llcofwearables.h @@ -34,6 +34,8 @@  #define LL_LLCOFWEARABLES_H  #include "llpanel.h" +#include "llinventorymodel.h" +#include "llappearancemgr.h"  class LLFlatListView; @@ -52,8 +54,16 @@ public:  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 LLCOFWearables::getXMLNode(std::string xml_filename); +  	LLFlatListView* mAttachments;  	LLFlatListView* mClothing;  	LLFlatListView* mBodyParts; diff --git a/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml b/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml new file mode 100644 index 0000000000..9d19b89a61 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml @@ -0,0 +1,36 @@ +<?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> diff --git a/indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml b/indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml new file mode 100644 index 0000000000..2359719c2a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml @@ -0,0 +1,37 @@ +<?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> diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index 01c7ae61d2..d8a8dbbea4 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -14,6 +14,7 @@       height="373"       layout="topleft"       left="3" +     single_expansion="true"       top="0"       name="cof_wearables_accordion"       background_visible="true" | 
