From 6aa63dce3367a60a5f8ae58d0651844ec7a0a79e Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 5 Mar 2015 16:17:45 -0500
Subject: [PATCH] SL-103 WIP - viewer enforces wearable limits based on total
 articles of clothing rather than per-type limit. Limit is artificially low
 for testing, will bump before release.

---
 indra/llappearance/llwearabledata.cpp   | 59 +++++++++++++-----
 indra/llappearance/llwearabledata.h     | 14 +++--
 indra/llappearance/llwearabletype.cpp   |  2 +-
 indra/newview/llagentwearables.cpp      | 23 ++++---
 indra/newview/llappearancemgr.cpp       | 83 ++++++++++++++-----------
 indra/newview/llappearancemgr.h         |  5 +-
 indra/newview/llinventorybridge.cpp     |  2 +-
 indra/newview/lllocalbitmaps.cpp        | 14 +++--
 indra/newview/llpaneleditwearable.cpp   | 44 ++++++++-----
 indra/newview/llsidepanelappearance.cpp |  3 +-
 indra/newview/llvoavatarself.cpp        | 12 +++-
 indra/newview/llwearableitemslist.cpp   | 25 ++------
 12 files changed, 175 insertions(+), 111 deletions(-)
 mode change 100644 => 100755 indra/llappearance/llwearabledata.h
 mode change 100644 => 100755 indra/llappearance/llwearabletype.cpp

diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp
index cf1ee435a89..39d4179a807 100755
--- a/indra/llappearance/llwearabledata.cpp
+++ b/indra/llappearance/llwearabledata.cpp
@@ -92,7 +92,7 @@ void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LL
 	}
 }
 
-U32 LLWearableData::pushWearable(const LLWearableType::EType type, 
+void LLWearableData::pushWearable(const LLWearableType::EType type, 
 								   LLWearable *wearable,
 								   bool trigger_updated /* = true */)
 {
@@ -100,9 +100,8 @@ U32 LLWearableData::pushWearable(const LLWearableType::EType type,
 	{
 		// no null wearables please!
 		LL_WARNS() << "Null wearable sent for type " << type << LL_ENDL;
-		return MAX_CLOTHING_PER_TYPE;
 	}
-	if (type < LLWearableType::WT_COUNT || mWearableDatas[type].size() < MAX_CLOTHING_PER_TYPE)
+	if (canAddWearable(type))
 	{
 		mWearableDatas[type].push_back(wearable);
 		if (trigger_updated)
@@ -110,9 +109,7 @@ U32 LLWearableData::pushWearable(const LLWearableType::EType type,
 			const BOOL removed = FALSE;
 			wearableUpdated(wearable, removed);
 		}
-		return mWearableDatas[type].size()-1;
 	}
-	return MAX_CLOTHING_PER_TYPE;
 }
 
 // virtual
@@ -125,7 +122,7 @@ void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed)
 	}
 }
 
-void LLWearableData::popWearable(LLWearable *wearable)
+void LLWearableData::eraseWearable(LLWearable *wearable)
 {
 	if (wearable == NULL)
 	{
@@ -133,16 +130,16 @@ void LLWearableData::popWearable(LLWearable *wearable)
 		return;
 	}
 
-	U32 index = getWearableIndex(wearable);
 	const LLWearableType::EType type = wearable->getType();
 
-	if (index < MAX_CLOTHING_PER_TYPE && index < getWearableCount(type))
+	U32 index;
+	if (getWearableIndex(wearable,index))
 	{
-		popWearable(type, index);
+		eraseWearable(type, index);
 	}
 }
 
-void LLWearableData::popWearable(const LLWearableType::EType type, U32 index)
+void LLWearableData::eraseWearable(const LLWearableType::EType type, U32 index)
 {
 	LLWearable *wearable = getWearable(type, index);
 	if (wearable)
@@ -203,11 +200,11 @@ void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type)
 }
 
 
-U32	LLWearableData::getWearableIndex(const LLWearable *wearable) const
+BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_found) const
 {
 	if (wearable == NULL)
 	{
-		return MAX_CLOTHING_PER_TYPE;
+		return FALSE;
 	}
 
 	const LLWearableType::EType type = wearable->getType();
@@ -215,18 +212,50 @@ U32	LLWearableData::getWearableIndex(const LLWearable *wearable) const
 	if (wearable_iter == mWearableDatas.end())
 	{
 		LL_WARNS() << "tried to get wearable index with an invalid type!" << LL_ENDL;
-		return MAX_CLOTHING_PER_TYPE;
+		return FALSE;
 	}
 	const wearableentry_vec_t& wearable_vec = wearable_iter->second;
 	for(U32 index = 0; index < wearable_vec.size(); index++)
 	{
 		if (wearable_vec[index] == wearable)
 		{
-			return index;
+			index_found = index;
+			return TRUE;
 		}
 	}
 
-	return MAX_CLOTHING_PER_TYPE;
+	return FALSE;
+}
+
+U32 LLWearableData::getClothingLayerCount() const
+{
+	U32 count = 0;
+	for (S32 i = 0; i < LLWearableType::WT_COUNT; i++)
+	{
+		LLWearableType::EType type = (LLWearableType::EType)i;
+		if (LLWearableType::getAssetType(type)==LLAssetType::AT_CLOTHING)
+		{
+			count += getWearableCount(type);
+		}
+	}
+	return count;
+}
+
+BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const
+{
+	LLAssetType::EType a_type = LLWearableType::getAssetType(type);
+	if (a_type==LLAssetType::AT_CLOTHING)
+	{
+		return (getClothingLayerCount() < MAX_CLOTHING_LAYERS);
+	}
+	else if (a_type==LLAssetType::AT_BODYPART)
+	{
+		return (getWearableCount(type) < 1);
+	}
+	else
+	{
+		return FALSE;
+	}
 }
 
 BOOL LLWearableData::isOnTop(LLWearable* wearable) const
diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h
old mode 100644
new mode 100755
index 03bd179f258..cb6cb954f0a
--- a/indra/llappearance/llwearabledata.h
+++ b/indra/llappearance/llwearabledata.h
@@ -60,11 +60,13 @@ class LLWearableData
 	const LLWearable*	getBottomWearable(const LLWearableType::EType type) const;
 	U32				getWearableCount(const LLWearableType::EType type) const;
 	U32				getWearableCount(const U32 tex_index) const;
-	U32				getWearableIndex(const LLWearable *wearable) const;
+	BOOL			getWearableIndex(const LLWearable *wearable, U32& index) const;
+	U32				getClothingLayerCount() const;
+	BOOL			canAddWearable(const LLWearableType::EType type) const;
 
 	BOOL			isOnTop(LLWearable* wearable) const;
-
-	static const U32 MAX_CLOTHING_PER_TYPE = 5; 
+	
+	static const U32 MAX_CLOTHING_LAYERS = 10;
 
 	//--------------------------------------------------------------------
 	// Setters
@@ -72,11 +74,11 @@ class LLWearableData
 protected:
 	// Low-level data structure setter - public access is via setWearableItem, etc.
 	void 			setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable);
-	U32 			pushWearable(const LLWearableType::EType type, LLWearable *wearable, 
+	void 			pushWearable(const LLWearableType::EType type, LLWearable *wearable, 
 								 bool trigger_updated = true);
 	virtual void	wearableUpdated(LLWearable *wearable, BOOL removed);
-	void 			popWearable(LLWearable *wearable);
-	void			popWearable(const LLWearableType::EType type, U32 index);
+	void 			eraseWearable(LLWearable *wearable);
+	void			eraseWearable(const LLWearableType::EType type, U32 index);
 	void			clearWearableType(const LLWearableType::EType type);
 	bool			swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b);
 
diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp
old mode 100644
new mode 100755
index 618e2a1941b..58c446e586a
--- a/indra/llappearance/llwearabletype.cpp
+++ b/indra/llappearance/llwearabletype.cpp
@@ -160,7 +160,7 @@ BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)
 	return entry->mDisableCameraSwitch;
 }
 
-// static 
+// static
 BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
 {
 	const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index f06ffb4fb39..5589ab4aa70 100755
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -633,10 +633,13 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable, BOOL removed)
 		// the versions themselves are compatible. This code can be removed before release.
 		if( wearable->getDefinitionVersion() == 24 )
 		{
-			wearable->setDefinitionVersion(22);
-			U32 index = getWearableIndex(wearable);
-			LL_INFOS() << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << LL_ENDL;
-			saveWearable(wearable->getType(),index);
+			U32 index;
+			if (getWearableIndex(wearable,index))
+			{
+				LL_INFOS() << "forcing wearable type " << wearable->getType() << " to version 22 from 24" << LL_ENDL;
+				wearable->setDefinitionVersion(22);
+				saveWearable(wearable->getType(),index);
+			}
 		}
 
 		checkWearableAgainstInventory(viewer_wearable);
@@ -949,7 +952,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 			LLViewerWearable* old_wearable = getViewerWearable(type,i);
 			if (old_wearable)
 			{
-				popWearable(old_wearable);
+				eraseWearable(old_wearable);
 				old_wearable->removeFromAvatar();
 			}
 		}
@@ -961,7 +964,7 @@ void LLAgentWearables::removeWearableFinal(const LLWearableType::EType type, boo
 
 		if (old_wearable)
 		{
-			popWearable(old_wearable);
+			eraseWearable(old_wearable);
 			old_wearable->removeFromAvatar();
 		}
 	}
@@ -1163,7 +1166,13 @@ bool LLAgentWearables::onSetWearableDialog(const LLSD& notification, const LLSD&
 {
 	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 	LLInventoryItem* new_item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-	U32 index = gAgentWearables.getWearableIndex(wearable);
+	U32 index;
+	if (!gAgentWearables.getWearableIndex(wearable,index))
+	{
+		LL_WARNS() << "Wearable not found" << LL_ENDL;
+		delete wearable;
+		return false;
+	}
 	if (!new_item)
 	{
 		delete wearable;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index d7ef5fcba7f..b5af1af5bc8 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1388,9 +1388,9 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
 			{
 				cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
 			}
-			S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType());
-			if ((replace && wearable_count != 0) ||
-				(wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) )
+			LLWearableType::EType type = item_to_wear->getWearableType();
+			S32 wearable_count = gAgentWearables.getWearableCount(type);
+			if ((replace && wearable_count != 0) || !gAgentWearables.canAddWearable(type))
 			{
 				LLUUID item_id = gAgentWearables.getWearableItemID(item_to_wear->getWearableType(),
 																   wearable_count-1);
@@ -1804,25 +1804,39 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLIn
 // Keep the last N wearables of each type.  For viewer 2.0, N is 1 for
 // both body parts and clothing items.
 void LLAppearanceMgr::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(LLWearableType::WT_COUNT);
-	divvyWearablesByType(items, items_by_type);
-
-	// rebuild items list, retaining the last max_per_type of each array
-	items.clear();
-	for (S32 i=0; i<LLWearableType::WT_COUNT; i++)
-	{
-		S32 size = items_by_type[i].size();
-		if (size <= 0)
-			continue;
-		S32 start_index = llmax(0,size-max_per_type);
-		for (S32 j = start_index; j<size; j++)
-		{
-			items.push_back(items_by_type[i][j]);
-		}
-	}
+	LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total)
+{
+    // Restrict by max total items first.
+    if ((max_total > 0) && (items.size() > max_total))
+    {
+        LLInventoryModel::item_array_t items_to_keep;
+        for (S32 i=0; i<max_total; i++)
+        {
+            items_to_keep.push_back(items[i]);
+        }
+        items = items_to_keep;
+    }
+
+    if (max_per_type > 0)
+    {
+        // Divvy items into arrays by wearable type.
+        std::vector<LLInventoryModel::item_array_t> items_by_type(LLWearableType::WT_COUNT);
+        divvyWearablesByType(items, items_by_type);
+
+        // rebuild items list, retaining the last max_per_type of each array
+        items.clear();
+        for (S32 i=0; i<LLWearableType::WT_COUNT; i++)
+        {
+            S32 size = items_by_type[i].size();
+            if (size <= 0)
+                continue;
+            S32 start_index = llmax(0,size-max_per_type);
+            for (S32 j = start_index; j<size; j++)
+            {
+                items.push_back(items_by_type[i][j]);
+            }
+        }
+    }
 }
 
 void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
@@ -1864,7 +1878,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 		reverse(body_items.begin(), body_items.end());
 	// Reduce body items to max of one per type.
 	removeDuplicateItems(body_items);
-	filterWearableItems(body_items, 1);
+	filterWearableItems(body_items, 1, 0);
 
 	// - Wearables: include COF contents only if appending.
 	LLInventoryModel::item_array_t wear_items;
@@ -1873,7 +1887,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 	getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING);
 	// Reduce wearables to max of one per type.
 	removeDuplicateItems(wear_items);
-	filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE);
+	filterWearableItems(wear_items, 0, LLAgentWearables::MAX_CLOTHING_LAYERS);
 
 	// - Attachments: include COF contents only if appending.
 	LLInventoryModel::item_array_t obj_items;
@@ -2062,7 +2076,8 @@ void item_array_diff(LLInventoryModel::item_array_t& full_list,
 
 S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 												 LLAssetType::EType type,
-												 S32 max_items,
+												 S32 max_items_per_type,
+												 S32 max_items_total,
 												 LLInventoryObject::object_list_t& items_to_kill)
 {
 	S32 to_kill_count = 0;
@@ -2071,9 +2086,9 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
 	getDescendentsOfAssetType(cat_id, items, type);
 	LLInventoryModel::item_array_t curr_items = items;
 	removeDuplicateItems(items);
-	if (max_items > 0)
+	if (max_items_per_type > 0 || max_items_total > 0)
 	{
-		filterWearableItems(items, max_items);
+		filterWearableItems(items, max_items_per_type, max_items_total);
 	}
 	LLInventoryModel::item_array_t kill_items;
 	item_array_diff(curr_items,items,kill_items);
@@ -2092,11 +2107,11 @@ void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id,
 													LLInventoryObject::object_list_t& items_to_kill)
 {
 	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_BODYPART,
-							   1, items_to_kill);
+							   1, 0, items_to_kill);
 	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_CLOTHING,
-							   LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill);
+							   0, LLAgentWearables::MAX_CLOTHING_LAYERS, items_to_kill);
 	findExcessOrDuplicateItems(cat_id,LLAssetType::AT_OBJECT,
-							   -1, items_to_kill);
+							   0, 0, items_to_kill);
 }
 
 void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb)
@@ -2588,7 +2603,6 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
 								  item_array,
 								  LLInventoryModel::EXCLUDE_TRASH);
 	bool linked_already = false;
-	U32 count = 0;
 	for (S32 i=0; i<item_array.size(); i++)
 	{
 		// Are these links to the same object?
@@ -2608,14 +2622,13 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item,
 		// type? If so, new item will replace old.
 		else if ((vitem->isWearableType()) && (vitem->getWearableType() == wearable_type))
 		{
-			++count;
-			if (is_body_part && inv_item->getIsLinkType()  && (vitem->getWearableType() == wearable_type))
+			if (is_body_part && inv_item->getIsLinkType())
 			{
 				remove_inventory_item(inv_item->getUUID(), cb);
 			}
-			else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
+			else if (!gAgentWearables.canAddWearable(wearable_type))
 			{
-				// MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE
+				// MULTI-WEARABLES: make sure we don't go over clothing limits
 				remove_inventory_item(inv_item->getUUID(), cb);
 			}
 		}
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 7742a19c07f..399cd6388fd 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -67,7 +67,8 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	void addCategoryToCurrentOutfit(const LLUUID& cat_id);
 	S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
 								   LLAssetType::EType type,
-								   S32 max_items,
+								   S32 max_items_per_type,
+								   S32 max_items_total,
 								   LLInventoryObject::object_list_t& items_to_kill);
 	void findAllExcessOrDuplicateItems(const LLUUID& cat_id,
 									  LLInventoryObject::object_list_t& items_to_kill);
@@ -235,7 +236,7 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 
 private:
 
-	void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type);
+	void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type, S32 max_total);
 	
 	void getDescendentsOfAssetType(const LLUUID& category, 
 										  LLInventoryModel::item_array_t& items,
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 19106560663..42f26332d39 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -5770,7 +5770,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 					if (LLWearableType::getAllowMultiwear(mWearableType))
 					{
 						items.push_back(std::string("Wearable Add"));
-						if (gAgentWearables.getWearableCount(mWearableType) >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
+						if (!gAgentWearables.canAddWearable(mWearableType))
 						{
 							disabled_items.push_back(std::string("Wearable Add"));
 						}
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 897ee8429a7..a93bd32cfde 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -544,12 +544,14 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp
 					LLAvatarAppearanceDefines::ETextureIndex reg_texind = getTexIndex(type, baked_texind);
 					if (reg_texind != LLAvatarAppearanceDefines::TEX_NUM_INDICES)
 					{
-						U32 index = gAgentWearables.getWearableIndex(wearable);
-						gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index);
-						gAgentAvatarp->wearableUpdated(type);
-
-						/* telling the manager to rebake once update cycle is fully done */
-						LLLocalBitmapMgr::setNeedsRebake();
+						U32 index;
+						if (gAgentWearables.getWearableIndex(wearable,index))
+						{
+							gAgentAvatarp->setLocalTexture(reg_texind, gTextureList.getImage(new_id), FALSE, index);
+							gAgentAvatarp->wearableUpdated(type);
+							/* telling the manager to rebake once update cycle is fully done */
+							LLLocalBitmapMgr::setNeedsRebake();
+						}
 					}
 
 				}
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 19a86cdceae..9bd6007772d 100755
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -925,17 +925,17 @@ void LLPanelEditWearable::onCommitSexChange()
         if (!isAgentAvatarValid()) return;
 
         LLWearableType::EType type = mWearablePtr->getType();
-        U32 index = gAgentWearables.getWearableIndex(mWearablePtr);
-
-        if( !gAgentWearables.isWearableModifiable(type, index))
+        U32 index;
+        if( !gAgentWearables.getWearableIndex(mWearablePtr, index) ||
+			!gAgentWearables.isWearableModifiable(type, index))
         {
-                return;
+			return;
         }
 
         LLViewerVisualParam* param = static_cast<LLViewerVisualParam*>(gAgentAvatarp->getVisualParam( "male" ));
         if( !param )
         {
-                return;
+			return;
         }
 
         bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE;
@@ -978,10 +978,17 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
                         }
                         if (getWearable())
                         {
-                                U32 index = gAgentWearables.getWearableIndex(getWearable());
-                                gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
-                                LLVisualParamHint::requestHintUpdates();
-                                gAgentAvatarp->wearableUpdated(type);
+							U32 index;
+							if (gAgentWearables.getWearableIndex(getWearable(), index))
+							{
+								gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
+								LLVisualParamHint::requestHintUpdates();
+								gAgentAvatarp->wearableUpdated(type);
+							}
+							else
+							{
+								LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL;
+							}
                         }
                 }
                 else
@@ -1058,7 +1065,12 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
                 return;
         }
 
-        U32 index = gAgentWearables.getWearableIndex(mWearablePtr);
+        U32 index;
+		if (!gAgentWearables.getWearableIndex(mWearablePtr, index))
+		{
+			LL_WARNS() << "wearable not found" << LL_ENDL;
+			return;
+		}
 
         std::string new_name = mNameEditor->getText();
 
@@ -1574,6 +1586,12 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
 
         LL_INFOS() << "onInvisibilityCommit, self " << this << " checkbox_ctrl " << checkbox_ctrl << LL_ENDL;
 
+		U32 index;
+		if (!gAgentWearables.getWearableIndex(getWearable(),index))
+		{
+			LL_WARNS() << "wearable not found" << LL_ENDL;
+			return;
+		}
         bool new_invis_state = checkbox_ctrl->get();
         if (new_invis_state)
         {
@@ -1581,9 +1599,8 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
                 mPreviousAlphaTexture[te] = lto->getID();
                 
                 LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE );
-                U32 index = gAgentWearables.getWearableIndex(getWearable());
-                gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
-                gAgentAvatarp->wearableUpdated(getWearable()->getType());
+				gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
+				gAgentAvatarp->wearableUpdated(getWearable()->getType());
         }
         else
         {
@@ -1598,7 +1615,6 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
                 LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(prev_id);
                 if (!image) return;
 
-                U32 index = gAgentWearables.getWearableIndex(getWearable());
                 gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
                 gAgentAvatarp->wearableUpdated(getWearable()->getType());
         }
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 64f24cd2912..ea7cf826746 100755
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -212,7 +212,8 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
 			}
 			if (is_wearable_edit_visible)
 			{
-				if (gAgentWearables.getWearableIndex(wearable_ptr) == LLAgentWearables::MAX_CLOTHING_PER_TYPE)
+				U32 index;
+				if (!gAgentWearables.getWearableIndex(wearable_ptr,index))
 				{
 					// we're no longer wearing the wearable we were last editing, switch back to outfit editor
 					showOutfitEditPanel();
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 3f3cd25f956..bb536275d4e 100755
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -1503,8 +1503,16 @@ BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex t
 		return LLVOAvatar::isTextureVisible(type);
 	}
 
-	U32 index = gAgentWearables.getWearableIndex(wearable);
-	return isTextureVisible(type,index);
+	U32 index;
+	if (gAgentWearables.getWearableIndex(wearable,index))
+	{
+		return isTextureVisible(type,index);
+	}
+	else
+	{
+		LL_WARNS() << "Wearable not found" << LL_ENDL;
+		return FALSE;
+	}
 }
 
 bool LLVOAvatarSelf::areTexturesCurrent() const
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index fac0fd63eea..98559e7782c 100755
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -1011,7 +1011,7 @@ bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_id
 	// TODO: investigate wearables may not be loaded at this point EXT-8231
 
 	U32 n_objects = 0;
-	boost::unordered_map<LLWearableType::EType, U32> clothes_by_type;
+	U32 n_clothes = 0;
 
 	// Count given clothes (by wearable type) and objects.
 	for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it)
@@ -1028,7 +1028,7 @@ bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_id
 		}
 		else if (item->getType() == LLAssetType::AT_CLOTHING)
 		{
-			++clothes_by_type[item->getWearableType()];
+			++n_clothes;
 		}
 		else
 		{
@@ -1044,25 +1044,8 @@ bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_id
 	}
 
 	// Check whether we can add all the clothes.
-	boost::unordered_map<LLWearableType::EType, U32>::const_iterator m_it;
-	for (m_it = clothes_by_type.begin(); m_it != clothes_by_type.end(); ++m_it)
-	{
-		LLWearableType::EType w_type	= m_it->first;
-		U32 n_clothes					= m_it->second;
-
-		U32 wearable_count = gAgentWearables.getWearableCount(w_type);
-		if ((wearable_count > 0) && !LLWearableType::getAllowMultiwear(w_type))
-		{
-			return false;
-		}
-		if ((wearable_count + n_clothes) > LLAgentWearables::MAX_CLOTHING_PER_TYPE)
-		{
-			return false;
-		}
-
-	}
-
-	return true;
+    U32 sum_clothes = n_clothes + gAgentWearables.getClothingLayerCount();
+    return sum_clothes <= LLAgentWearables::MAX_CLOTHING_LAYERS;
 }
 
 // EOF
-- 
GitLab