diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/newview/llappearancemgr.cpp | 200 | ||||
| -rw-r--r-- | indra/newview/llappearancemgr.h | 15 | 
2 files changed, 193 insertions, 22 deletions
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4e022aeb29..8e1f7775d2 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -296,15 +296,28 @@ struct LLWearableHoldingPattern  	bool append;  }; +/* static */ void removeDuplicateItems(LLInventoryModel::item_array_t& items) +{ +	LLInventoryModel::item_array_t new_items; +	std::set<LLUUID> items_seen; +	for (S32 i=0; i<items.count(); i++) +	{ +		LLViewerInventoryItem *item = items.get(i); +		LLUUID item_id = item->getLinkedUUID(); +		if (items_seen.find(item_id)!=items_seen.end()) +			continue; +		items_seen.insert(item_id); +		new_items.push_back(item); +	} +	items = new_items; +}  void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventoryModel::item_array_t& src)  {  	LLInventoryModel::item_array_t new_dst;  	std::set<LLUUID> mark_inventory; -	std::set<LLUUID> mark_asset;  	S32 inventory_dups = 0; -	S32 asset_dups = 0;  	for (LLInventoryModel::item_array_t::const_iterator src_pos = src.begin();  		  src_pos != src.end(); @@ -312,8 +325,6 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory  	{  		LLUUID src_item_id = (*src_pos)->getLinkedUUID();  		mark_inventory.insert(src_item_id); -		LLUUID src_asset_id = (*src_pos)->getAssetUUID(); -		mark_asset.insert(src_asset_id);  	}  	for (LLInventoryModel::item_array_t::const_iterator dst_pos = dst.begin(); @@ -324,32 +335,21 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory  		if (mark_inventory.find(dst_item_id) == mark_inventory.end())  		{ -		} -		else -		{ -			inventory_dups++; -		} - -		LLUUID dst_asset_id = (*dst_pos)->getAssetUUID(); - -		if (mark_asset.find(dst_asset_id) == mark_asset.end()) -		{  			// Item is not already present in COF.  			new_dst.put(*dst_pos); -			mark_asset.insert(dst_item_id); +			mark_inventory.insert(dst_item_id);  		}  		else  		{ -			asset_dups++; +			inventory_dups++;  		}  	}  	llinfos << "removeDups, original " << dst.count() << " final " << new_dst.count() -			<< " inventory dups " << inventory_dups << " asset_dups " << asset_dups << llendl; +			<< " inventory dups " << inventory_dups << llendl;  	dst = new_dst;  } -  /* static */   LLUUID LLAppearanceManager::getCOF()  { @@ -363,6 +363,9 @@ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, boo  	if (!proceed)  		return; +#if 1  +	updateCOF(category,append); +#else  	if (append)  	{  		updateCOFFromCategory(category, append); // append is true - add non-duplicates to COF. @@ -380,6 +383,7 @@ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, boo  			rebuildCOFFromOutfit(category);  		}  	} +#endif  }  // Append to current COF contents by recursively traversing a folder. @@ -520,6 +524,130 @@ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID  		}  	}  } +/* static */ void LLAppearanceManager::purgeCategory(const LLUUID& category, bool keep_outfit_links) +{ +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendents(getCOF(), cats, items, +								  LLInventoryModel::EXCLUDE_TRASH); +	for (S32 i = 0; i < items.count(); ++i) +	{ +		LLViewerInventoryItem *item = items.get(i); +		if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER)) +			continue; +		gInventory.purgeObject(item->getUUID()); +	} +} + +// Keep the last N wearables of each type.  For viewer 2.0, N is 1 for +// both body parts and clothing items. +/* static */ void LLAppearanceManager::filterWearableItems( +	LLInventoryModel::item_array_t& items, S32 max_per_type) +{ +	// Divvy items into arrays by wearable type. +	std::vector<LLInventoryModel::item_array_t> items_by_type(WT_COUNT); +	for (S32 i=0; i<items.count(); i++) +	{ +		LLViewerInventoryItem *item = items.get(i); +		// Ignore non-wearables. +		if (!item->isWearableType()) +			continue; +		EWearableType type = item->getWearableType(); +		items_by_type[type].push_back(item); +	} + +	// rebuild items list, retaining the last max_per_type of each array +	items.clear(); +	for (S32 i=0; i<WT_COUNT; i++) +	{ +		S32 size = items_by_type[i].size(); +		if (size <= 0) +			continue; +		S32 start_index = max(0,size-max_per_type); +		for (S32 j = start_index; j<size; j++) +		{ +			items.push_back(items_by_type[i][j]); +		} +	} +} + +// Create links to all listed items. +/* static */ void LLAppearanceManager::linkAll(const LLUUID& category, +											   LLInventoryModel::item_array_t& items, +											   LLPointer<LLInventoryCallback> cb) +{ +	for (S32 i=0; i<items.count(); i++) +	{ +		const LLInventoryItem* item = items.get(i).get(); +		link_inventory_item(gAgent.getID(), +							item->getLinkedUUID(), +							category, +							item->getName(), +							LLAssetType::AT_LINK, +							cb); +	} +} + +/* static */ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) +{ +	const LLUUID cof = getCOF(); + +	// Collect and filter descendents to determine new COF contents. + +	// - Body parts: always include COF contents as a fallback in case any +	// required parts are missing. +	LLInventoryModel::item_array_t body_items; +	getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false); +	getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false); +	// Reduce body items to max of one per type. +	removeDuplicateItems(body_items); +	filterWearableItems(body_items, 1); + +	// - Wearables: include COF contents only if appending. +	LLInventoryModel::item_array_t wear_items; +	if (append) +		getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING, false); +	getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING, false); +	// Reduce wearables to max of one per type. +	removeDuplicateItems(wear_items); +	filterWearableItems(wear_items, 1); + +	// - Attachments: include COF contents only if appending. +	LLInventoryModel::item_array_t obj_items; +	if (append) +		getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT, false); +	getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT, false); +	removeDuplicateItems(obj_items); + +	// - Gestures: include COF contents only if appending. +	LLInventoryModel::item_array_t gest_items; +	if (append) +		getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false); +	getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false); +	removeDuplicateItems(gest_items); +	 +	// Remove current COF contents. +	bool keep_outfit_links = append; +	purgeCategory(cof, keep_outfit_links); +	gInventory.notifyObservers(); + +	// Create links to new COF contents. +	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; + +	linkAll(cof, body_items, link_waiter); +	linkAll(cof, wear_items, link_waiter); +	linkAll(cof, obj_items, link_waiter); +	linkAll(cof, gest_items, link_waiter); + +	// Add link to outfit if category is an outfit.  +	LLViewerInventoryCategory* catp = gInventory.getCategory(category); +	if (!append && catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT) +	{ +		link_inventory_item(gAgent.getID(), category, cof, catp->getName(), +							LLAssetType::AT_LINK_FOLDER, link_waiter); +	} +							   +}  /* static */   bool LLAppearanceManager::isMandatoryWearableType(EWearableType type) @@ -792,6 +920,22 @@ void LLAppearanceManager::getCOFValidDescendents(const LLUUID& category,  									follow_folder_links);  } +/* static */ +void LLAppearanceManager::getDescendentsOfAssetType(const LLUUID& category, +													LLInventoryModel::item_array_t& items, +													LLAssetType::EType type, +													bool follow_folder_links) +{ +	LLInventoryModel::cat_array_t cats; +	LLIsType is_of_type(type); +	gInventory.collectDescendentsIf(category, +									cats, +									items, +									LLInventoryModel::EXCLUDE_TRASH, +									is_of_type, +									follow_folder_links); +} +  /* static */   void LLAppearanceManager::getUserDescendents(const LLUUID& category,   											 LLInventoryModel::item_array_t& wear_items, @@ -998,14 +1142,16 @@ void LLAppearanceManager::removeItemLinks(const LLUUID& item_id, bool do_update)  	}  } +//#define DUMP_CAT_VERBOSE +  /* static */ -void LLAppearanceManager::dumpCat(const LLUUID& cat_id, std::string str) +void LLAppearanceManager::dumpCat(const LLUUID& cat_id, const std::string& msg)  {  	LLInventoryModel::cat_array_t cats;  	LLInventoryModel::item_array_t items;  	gInventory.collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); -#if 0 +#ifdef DUMP_CAT_VERBOSE  	llinfos << llendl;  	llinfos << str << llendl;  	S32 hitcount = 0; @@ -1017,6 +1163,18 @@ void LLAppearanceManager::dumpCat(const LLUUID& cat_id, std::string str)  		llinfos << i <<" "<< item->getName() <<llendl;  	}  #endif -	llinfos << str << " count " << items.count() << llendl; +	llinfos << msg << " count " << items.count() << llendl;  } +/* static */ +void LLAppearanceManager::dumpItemArray(const LLInventoryModel::item_array_t& items, +										const std::string& msg) +{ +	llinfos << msg << llendl; +	for (S32 i=0; i<items.count(); i++) +	{ +		LLViewerInventoryItem *item = items.get(i); +		llinfos << i <<" " << item->getName() << llendl; +	} +	llinfos << llendl; +} diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 828af32101..ea3ebdf4ea 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -46,6 +46,7 @@ public:  	static void updateAppearanceFromCOF();  	static bool needToSaveCOF();  	static void changeOutfit(bool proceed, const LLUUID& category, bool append); +	static void updateCOF(const LLUUID& category, bool append = false);  	static void updateCOFFromCategory(const LLUUID& category, bool append);  	static void rebuildCOFFromOutfit(const LLUUID& category);  	static void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append); @@ -65,9 +66,20 @@ public:  	static void removeItemLinks(const LLUUID& item_id, bool do_update = true);  	// For debugging - could be moved elsewhere. -	static void dumpCat(const LLUUID& cat_id, std::string str); +	static void dumpCat(const LLUUID& cat_id, const std::string& msg); +	static void dumpItemArray(const LLInventoryModel::item_array_t& items, const std::string& msg);  private: +	static void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type); +	static void linkAll(const LLUUID& category, +						LLInventoryModel::item_array_t& items, +						LLPointer<LLInventoryCallback> cb); +	 +	static void getDescendentsOfAssetType(const LLUUID& category,  +										  LLInventoryModel::item_array_t& items, +										  LLAssetType::EType type, +										  bool follow_folder_links); +  	static void getCOFValidDescendents(const LLUUID& category,   									   LLInventoryModel::item_array_t& items); @@ -81,6 +93,7 @@ private:  	static bool isMandatoryWearableType(EWearableType type);  	static void checkMandatoryWearableTypes(const LLUUID& category, std::set<EWearableType>& types_found);  	static void purgeCOFBeforeRebuild(const LLUUID& category); +	static void purgeCategory(const LLUUID& category, bool keep_outfit_links);  };  #define SUPPORT_ENSEMBLES 0  | 
