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: 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/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 ++--------
 9 files changed, 122 insertions(+), 89 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index f06ffb4fb3..5589ab4aa7 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 d7ef5fcba7..b5af1af5bc 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 7742a19c07..399cd6388f 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -67,7 +67,8 @@ public:
 	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 @@ protected:
 
 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 1910656066..42f26332d3 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 897ee8429a..a93bd32cfd 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 19a86cdcea..9bd6007772 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 64f24cd291..ea7cf82674 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 3f3cd25f95..bb536275d4 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 fac0fd63ee..98559e7782 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
-- 
cgit v1.2.3


From 738195a98d3009becd5dbeaae7f77e70fff7de3e Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Mon, 9 Mar 2015 18:52:59 -0400
Subject: SL-103 WIP - fix for some inventory items not enabling add

---
 indra/newview/llinventorybridge.cpp | 2 +-
 indra/newview/llinventoryicon.cpp   | 2 +-
 indra/newview/llviewerinventory.cpp | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 42f26332d3..958bc7d558 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1120,7 +1120,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
 			{
 				LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
 			}
-			new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, (LLWearableType::EType)flags);
+			new_listener = new LLWearableBridge(inventory, root, uuid, asset_type, inv_type, LLWearableType::inventoryFlagsToWearableType(flags));
 			break;
 		case LLAssetType::AT_CATEGORY:
 			if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index b7c4ec6f8b..013a5a7629 100755
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -183,6 +183,6 @@ const std::string& LLInventoryIcon::getIconName(LLInventoryType::EIconName idx)
 
 LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag)
 {
-	const LLWearableType::EType wearable_type = LLWearableType::EType(LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK & misc_flag);
+	const LLWearableType::EType wearable_type = LLWearableType::inventoryFlagsToWearableType(misc_flag);
 	return LLWearableType::getIconName(wearable_type);
 }
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index d6c8ba10f6..d112118082 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -2106,7 +2106,7 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const
 	{
 		return LLWearableType::WT_INVALID;
 	}
-	return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);
+	return LLWearableType::inventoryFlagsToWearableType(getFlags());
 }
 
 
-- 
cgit v1.2.3


From fb072c91485a484e3d0740113ee753b58c439900 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 13 Mar 2015 16:38:23 -0400
Subject: MAINT-4980 WIP - add context menu filtering based on the selection
 group

---
 indra/newview/llinventorybridge.cpp | 86 ++++++++++++++++++++++++++++++++++++-
 indra/newview/llinventorybridge.h   |  8 ++++
 indra/newview/llinventorypanel.cpp  |  4 +-
 indra/newview/llinventorypanel.h    |  2 +
 indra/newview/llwearableitemslist.h |  3 +-
 5 files changed, 100 insertions(+), 3 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 958bc7d558..3ec8bb0ab9 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -74,6 +74,7 @@
 #include "llviewerwindow.h"
 #include "llvoavatarself.h"
 #include "llwearablelist.h"
+#include "llwearableitemslist.h"
 #include "lllandmarkactions.h"
 #include "llpanellandmarks.h"
 
@@ -557,6 +558,46 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
 	return TRUE;
 }
 
+void disable_context_entries_if_present(LLMenuGL& menu,
+                                        const menuentry_vec_t &disabled_entries)
+{
+	const LLView::child_list_t *list = menu.getChildList();
+	for (LLView::child_list_t::const_iterator itor = list->begin(); 
+		 itor != list->end(); 
+		 ++itor)
+	{
+		LLView *menu_item = (*itor);
+		std::string name = menu_item->getName();
+
+		// descend into split menus:
+		LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(menu_item);
+		if ((name == "More") && branchp)
+		{
+			disable_context_entries_if_present(*branchp->getBranch(), disabled_entries);
+		}
+
+		bool found = false;
+		menuentry_vec_t::const_iterator itor2;
+		for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
+		{
+			if (*itor2 == name)
+			{
+				found = true;
+				break;
+			}
+		}
+
+        if (found)
+        {
+			menu_item->setVisible(TRUE);
+			// A bit of a hack so we can remember that some UI element explicitly set this to be visible
+			// so that some other UI element from multi-select doesn't later set this invisible.
+			menu_item->pushVisible(TRUE);
+
+			menu_item->setEnabled(FALSE);
+        }
+    }
+}
 void hide_context_entries(LLMenuGL& menu, 
 						  const menuentry_vec_t &entries_to_show,
 						  const menuentry_vec_t &disabled_entries)
@@ -765,6 +806,31 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	hide_context_entries(menu, items, disabled_items);
 }
 
+bool get_selection_item_uuids(LLFolderView::selected_items_t& selected_items, uuid_vec_t& ids)
+{
+	uuid_vec_t results;
+    S32 non_item = 0;
+	for(LLFolderView::selected_items_t::iterator it = selected_items.begin(); it != selected_items.end(); ++it)
+	{
+		LLItemBridge *view_model = dynamic_cast<LLItemBridge *>((*it)->getViewModelItem());
+
+		if(view_model && view_model->getUUID().notNull())
+		{
+			results.push_back(view_model->getUUID());
+		}
+        else
+        {
+            non_item++;
+        }
+	}
+	if (non_item == 0)
+	{
+		ids = results;
+		return true;
+	}
+	return false;
+}
+
 void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items,
 											   menuentry_vec_t &disabled_items)
 {
@@ -3585,7 +3651,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	if(!model) return;
 
 	buildContextMenuOptions(flags, items, disabled_items);
-        hide_context_entries(menu, items, disabled_items);
+    hide_context_entries(menu, items, disabled_items);
 
 	// Reposition the menu, in case we're adding items to an existing menu.
 	menu.needsArrange();
@@ -6439,4 +6505,22 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(
 	return new_listener;
 }
 
+LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge()
+{
+}
+
+void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu)
+{
+    uuid_vec_t ids;
+	menuentry_vec_t disabled_items;
+    if (get_selection_item_uuids(selected_items, ids))
+    {
+        if (!LLWearableItemsList::ContextMenu::canAddWearables(ids))
+        {
+			disabled_items.push_back(std::string("Wearable Add"));
+        }
+    }
+	disable_context_entries_if_present(menu, disabled_items);
+}
+
 // EOF
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index e8d5db4437..6a8478e64b 100755
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -37,6 +37,7 @@
 #include "llviewerwearable.h"
 #include "lltooldraganddrop.h"
 #include "lllandmarklist.h"
+#include "llfolderviewitem.h"
 
 class LLInventoryFilter;
 class LLInventoryPanel;
@@ -687,4 +688,11 @@ void hide_context_entries(LLMenuGL& menu,
 						  const menuentry_vec_t &entries_to_show, 
 						  const menuentry_vec_t &disabled_entries);
 
+class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel
+{
+public:
+    LLFolderViewGroupedItemBridge();
+    virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu);
+};
+
 #endif // LL_LLINVENTORYBRIDGE_H
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 3546317471..4a230accb6 100755
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -146,7 +146,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mShowEmptyMessage(p.show_empty_message),
 	mViewsInitialized(false),
 	mInvFVBridgeBuilder(NULL),
-	mInventoryViewModel(p.name)
+	mInventoryViewModel(p.name),
+	mGroupedItemBridge(new LLFolderViewGroupedItemBridge)
 {
 	mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
 
@@ -186,6 +187,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
 																	NULL,
 																	root_id);
     p.view_model = &mInventoryViewModel;
+	p.grouped_item_model = mGroupedItemBridge;
     p.use_label_suffix = mParams.use_label_suffix;
     p.allow_multiselect = mAllowMultiSelect;
     p.show_empty_message = mShowEmptyMessage;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index a490dfce5d..bc4c10e441 100755
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -43,6 +43,7 @@ class LLInvFVBridge;
 class LLInventoryFolderViewModelBuilder;
 class LLInvPanelComplObserver;
 class LLFolderViewModelInventory;
+class LLFolderViewGroupedItemBridge;
 
 namespace LLInitParam
 {
@@ -240,6 +241,7 @@ protected:
 	LLScrollContainer*			mScroller;
 
 	LLFolderViewModelInventory	mInventoryViewModel;
+    LLPointer<LLFolderViewGroupedItemBridge> mGroupedItemBridge;
 	Params						mParams;	// stored copy of parameter block
 
 	std::map<LLUUID, LLFolderViewItem*> mItemMap;
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 58a00c5be0..eb975b6301 100755
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -410,6 +410,8 @@ public:
 		ContextMenu();
 		/*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y);
 
+        // FIXME logic should live somewhere more generally useful.
+		static bool canAddWearables(const uuid_vec_t& item_ids);
 	protected:
 		enum {
 			MASK_CLOTHING		= 0x01,
@@ -425,7 +427,6 @@ public:
 		static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val);
 		static void updateMask(U32& mask, LLAssetType::EType at);
 		static void createNewWearable(const LLUUID& item_id);
-		static bool canAddWearables(const uuid_vec_t& item_ids);
 
 		LLWearableItemsList*	mParent;
 	};
-- 
cgit v1.2.3


From dd7f0e2954a80e39eba50b7a06e167a50a248632 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 13 Mar 2015 16:55:19 -0400
Subject: MAINT-4980 WIP - moved canAddWearables() to LLAppearanceMgr

---
 indra/newview/llappearancemgr.cpp     | 43 +++++++++++++++++++++++++++++++
 indra/newview/llappearancemgr.h       |  3 +++
 indra/newview/llinventorybridge.cpp   |  2 +-
 indra/newview/llwearableitemslist.cpp | 48 ++---------------------------------
 indra/newview/llwearableitemslist.h   |  2 --
 5 files changed, 49 insertions(+), 49 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index b5af1af5bc..2c166b6001 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1782,6 +1782,49 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
 	return items.size() > 0;
 }
 
+// Moved from LLWearableList::ContextMenu for wider utility.
+bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids)
+{
+	// TODO: investigate wearables may not be loaded at this point EXT-8231
+
+	U32 n_objects = 0;
+	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)
+	{
+		LLViewerInventoryItem* item = gInventory.getItem(*it);
+		if (!item)
+		{
+			return false;
+		}
+
+		if (item->getType() == LLAssetType::AT_OBJECT)
+		{
+			++n_objects;
+		}
+		else if (item->getType() == LLAssetType::AT_CLOTHING)
+		{
+			++n_clothes;
+		}
+		else
+		{
+			LL_WARNS() << "Unexpected wearable type" << LL_ENDL;
+			return false;
+		}
+	}
+
+	// Check whether we can add all the objects.
+	if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects))
+	{
+		return false;
+	}
+
+	// Check whether we can add all the clothes.
+    U32 sum_clothes = n_clothes + gAgentWearables.getClothingLayerCount();
+    return sum_clothes <= LLAgentWearables::MAX_CLOTHING_LAYERS;
+}
+
 void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer<LLInventoryCallback> cb)
 {
 	LLInventoryModel::cat_array_t cats;
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 399cd6388f..10d97bb8cb 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -100,6 +100,9 @@ public:
 	// Determine whether we can replace current outfit with the given one.
 	bool getCanReplaceCOF(const LLUUID& outfit_cat_id);
 
+    // Can we add all referenced items to the avatar?
+    bool canAddWearables(const uuid_vec_t& item_ids);
+    
 	// Copy all items in a category.
 	void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
 									 LLPointer<LLInventoryCallback> cb);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3ec8bb0ab9..cd45d0a4f3 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -6515,7 +6515,7 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ
 	menuentry_vec_t disabled_items;
     if (get_selection_item_uuids(selected_items, ids))
     {
-        if (!LLWearableItemsList::ContextMenu::canAddWearables(ids))
+        if (!LLAppearanceMgr::instance().canAddWearables(ids))
         {
 			disabled_items.push_back(std::string("Wearable Add"));
         }
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index 98559e7782..888ead0613 100755
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -894,13 +894,13 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu
 	setMenuItemVisible(menu, "wear_wear", 			n_already_worn == 0 && n_worn == 0 && can_be_worn);
 	setMenuItemEnabled(menu, "wear_wear", 			n_already_worn == 0 && n_worn == 0);
 	setMenuItemVisible(menu, "wear_add",			wear_add_visible);
-	setMenuItemEnabled(menu, "wear_add",			canAddWearables(ids));
+	setMenuItemEnabled(menu, "wear_add",			LLAppearanceMgr::instance().canAddWearables(ids));
 	setMenuItemVisible(menu, "wear_replace",		n_worn == 0 && n_already_worn != 0 && can_be_worn);
 	//visible only when one item selected and this item is worn
 	setMenuItemVisible(menu, "edit",				!standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1);
 	setMenuItemEnabled(menu, "edit",				n_editable == 1 && n_worn == 1 && n_items == 1);
 	setMenuItemVisible(menu, "create_new",			mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1);
-	setMenuItemEnabled(menu, "create_new",			canAddWearables(ids));
+	setMenuItemEnabled(menu, "create_new",			LLAppearanceMgr::instance().canAddWearables(ids));
 	setMenuItemVisible(menu, "show_original",		!standalone);
 	setMenuItemEnabled(menu, "show_original",		n_items == 1 && n_links == n_items);
 	setMenuItemVisible(menu, "take_off",			mask == MASK_CLOTHING && n_worn == n_items);
@@ -1004,48 +1004,4 @@ void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id)
 	LLAgentWearables::createWearable(item->getWearableType(), true);
 }
 
-// Returns true if all the given objects and clothes can be added.
-// static
-bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_ids)
-{
-	// TODO: investigate wearables may not be loaded at this point EXT-8231
-
-	U32 n_objects = 0;
-	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)
-	{
-		LLViewerInventoryItem* item = gInventory.getItem(*it);
-		if (!item)
-		{
-			return false;
-		}
-
-		if (item->getType() == LLAssetType::AT_OBJECT)
-		{
-			++n_objects;
-		}
-		else if (item->getType() == LLAssetType::AT_CLOTHING)
-		{
-			++n_clothes;
-		}
-		else
-		{
-			LL_WARNS() << "Unexpected wearable type" << LL_ENDL;
-			return false;
-		}
-	}
-
-	// Check whether we can add all the objects.
-	if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects))
-	{
-		return false;
-	}
-
-	// Check whether we can add all the clothes.
-    U32 sum_clothes = n_clothes + gAgentWearables.getClothingLayerCount();
-    return sum_clothes <= LLAgentWearables::MAX_CLOTHING_LAYERS;
-}
-
 // EOF
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index eb975b6301..715c249616 100755
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -410,8 +410,6 @@ public:
 		ContextMenu();
 		/*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y);
 
-        // FIXME logic should live somewhere more generally useful.
-		static bool canAddWearables(const uuid_vec_t& item_ids);
 	protected:
 		enum {
 			MASK_CLOTHING		= 0x01,
-- 
cgit v1.2.3


From c6af736035513581c36a65da3a0adec1546c8264 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 14 Apr 2015 15:46:49 -0400
Subject: MAINT-5082 WIP, MAINT-5083 WIP - batch up wear/add/take off/detach
 requests in inventory panel the same way we do now in appearance tab

---
 indra/newview/llinventoryfunctions.cpp | 40 +++++++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 10 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 1abc09bf3b..2546db546b 100755
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -45,6 +45,7 @@
 // newview includes
 #include "llappearancemgr.h"
 #include "llappviewer.h"
+#include "llavataractions.h"
 #include "llclipboard.h"
 #include "lldonotdisturbnotificationstorage.h"
 #include "llfloaterinventory.h"
@@ -1114,16 +1115,35 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 		LLFloater::setFloaterHost(multi_propertiesp);
 	}
 
-	std::set<LLFolderViewItem*>::iterator set_iter;
-
-	for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
-	{
-		LLFolderViewItem* folder_item = *set_iter;
-		if(!folder_item) continue;
-		LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
-		if(!bridge) continue;
-		bridge->performAction(model, action);
-	}
+    
+	std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs();
+    uuid_vec_t ids;
+    std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids));
+    // Check for actions that get handled in bulk
+    if (action == "wear")
+    {
+        wear_multiple(ids, true);
+    }
+    else if (action == "wear_add")
+    {
+        wear_multiple(ids, false);
+    }
+    else if (action == "take_off" || action == "detach")
+    {
+        LLAppearanceMgr::instance().removeItemsFromAvatar(ids);
+    }
+    else
+    {
+        std::set<LLFolderViewItem*>::iterator set_iter;
+        for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+        {
+            LLFolderViewItem* folder_item = *set_iter;
+            if(!folder_item) continue;
+            LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
+            if(!bridge) continue;
+            bridge->performAction(model, action);
+        }
+    }
 
 	LLFloater::setFloaterHost(NULL);
 	if (multi_previewp)
-- 
cgit v1.2.3


From 326b9d111ec101e3a8945c57f2eed317c8e2745b Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 16 Apr 2015 15:28:35 -0400
Subject: MAINT-5082 WIP, MAINT-5083 WIP - consolidate COF link creation calls
 during mass add of wearables/objects

---
 indra/newview/llappearancemgr.cpp | 178 ++++++++++++++++++++------------------
 indra/newview/llappearancemgr.h   |   7 +-
 2 files changed, 102 insertions(+), 83 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 2c166b6001..45f57d2c82 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1338,90 +1338,113 @@ void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace = false)
 	}
 }
 
-bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
-									   bool do_update,
-									   bool replace,
-									   LLPointer<LLInventoryCallback> cb)
+void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,
+                                        bool do_update,
+                                        bool replace,
+                                        LLPointer<LLInventoryCallback> cb)
 {
+    bool first = true;
 
-	if (item_id_to_wear.isNull()) return false;
+    LLInventoryObject::const_object_list_t items_to_link;
 
-	// *TODO: issue with multi-wearable should be fixed:
-	// in this case this method will be called N times - loading started for each item
-	// and than N times will be called - loading completed for each item.
-	// That means subscribers will be notified that loading is done after first item in a batch is worn.
-	// (loading indicator disappears for example before all selected items are worn)
-	// Have not fix this issue for 2.1 because of stability reason. EXT-7777.
+    for (uuid_vec_t::const_iterator it = item_ids_to_wear.begin();
+         it != item_ids_to_wear.end();
+         ++it)
+    {
+        replace = first && replace;
+        first = false;
 
-	// Disabled for now because it is *not* acceptable to call updateAppearanceFromCOF() multiple times
-//	gAgentWearables.notifyLoadingStarted();
+        const LLUUID& item_id_to_wear = *it;
 
-	LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear);
-	if (!item_to_wear) return false;
+        if (item_id_to_wear.isNull()) continue;
 
-	if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
-	{
-		LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace));
-		copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb);
-		return false;
-	} 
-	else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))
-	{
-		return false; // not in library and not in agent's inventory
-	}
-	else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))
-	{
-		LLNotificationsUtil::add("CannotWearTrash");
-		return false;
-	}
-	else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911
-	{
-		return false;
-	}
+        LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear);
+        if (!item_to_wear) continue;
 
-	switch (item_to_wear->getType())
-	{
-		case LLAssetType::AT_CLOTHING:
-		if (gAgentWearables.areWearablesLoaded())
-		{
-			if (!cb && do_update)
-			{
-				cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
-			}
-			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);
-				removeCOFItemLinks(item_id, cb);
-			}
+        if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
+        {
+            LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(wear_on_avatar_cb,_1,replace));
+            copy_inventory_item(gAgent.getID(), item_to_wear->getPermissions().getOwner(), item_to_wear->getUUID(), LLUUID::null, std::string(), cb);
+            continue;
+        } 
+        else if (!gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getRootFolderID()))
+        {
+            continue; // not in library and not in agent's inventory
+        }
+        else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))
+        {
+            LLNotificationsUtil::add("CannotWearTrash");
+            continue;
+        }
+        else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911
+        {
+            continue;
+        }
 
-			addCOFItemLink(item_to_wear, cb);
-		} 
-		break;
+        switch (item_to_wear->getType())
+        {
+            case LLAssetType::AT_CLOTHING:
+            {
+                if (gAgentWearables.areWearablesLoaded())
+                {
+                    if (!cb && do_update)
+                    {
+                        cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
+                    }
+                    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);
+                        removeCOFItemLinks(item_id, cb);
+                    }
+                    
+                    items_to_link.push_back(item_to_wear);
+                } 
+            }
+            break;
 
-		case LLAssetType::AT_BODYPART:
-		// TODO: investigate wearables may not be loaded at this point EXT-8231
-		
-		// Remove the existing wearables of the same type.
-		// Remove existing body parts anyway because we must not be able to wear e.g. two skins.
-		removeCOFLinksOfType(item_to_wear->getWearableType());
-		if (!cb && do_update)
-		{
-			cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
-		}
-		addCOFItemLink(item_to_wear, cb);
-		break;
+            case LLAssetType::AT_BODYPART:
+            {
+                // TODO: investigate wearables may not be loaded at this point EXT-8231
+                
+                // Remove the existing wearables of the same type.
+                // Remove existing body parts anyway because we must not be able to wear e.g. two skins.
+                removeCOFLinksOfType(item_to_wear->getWearableType());
+                if (!cb && do_update)
+                {
+                    cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear);
+                }
+                items_to_link.push_back(item_to_wear);
+            }
+            break;
+                
+            case LLAssetType::AT_OBJECT:
+            {
+                rez_attachment(item_to_wear, NULL, replace);
+            }
+            break;
 
-		case LLAssetType::AT_OBJECT:
-		rez_attachment(item_to_wear, NULL, replace);
-		break;
+            default: continue;
+        }
+    }
 
-		default: return false;;
-	}
+    // Batch up COF link creation - more efficient if using AIS.
+    if (items_to_link.size())
+    {
+        link_inventory_array(getCOF(), items_to_link, cb); 
+    }
+}
 
-	return true;
+void LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
+									   bool do_update,
+									   bool replace,
+									   LLPointer<LLInventoryCallback> cb)
+{
+    uuid_vec_t ids;
+    ids.push_back(item_id_to_wear);
+    wearItemsOnAvatar(ids, do_update, replace, cb);
 }
 
 // Update appearance from outfit folder.
@@ -4127,16 +4150,7 @@ void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb)
 void wear_multiple(const uuid_vec_t& ids, bool replace)
 {
 	LLPointer<LLInventoryCallback> cb = new LLUpdateAppearanceOnDestroy;
-	
-	bool first = true;
-	uuid_vec_t::const_iterator it;
-	for (it = ids.begin(); it != ids.end(); ++it)
-	{
-		// if replace is requested, the first item worn will replace the current top
-		// item, and others will be added.
-		LLAppearanceMgr::instance().wearItemOnAvatar(*it,false,first && replace,cb);
-		first = false;
-	}
+    LLAppearanceMgr::instance().wearItemsOnAvatar(ids, false, replace, cb);
 }
 
 // SLapp for easy-wearing of a stock (library) avatar
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 10d97bb8cb..0e9967175b 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -121,8 +121,13 @@ public:
 	// find the UUID of the currently worn outfit (Base Outfit)
 	const LLUUID getBaseOutfitUUID();
 
+    void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,
+                                        bool do_update,
+                                        bool replace,
+                                        LLPointer<LLInventoryCallback> cb = NULL);
+
 	// Wear/attach an item (from a user's inventory) on the agent
-	bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false,
+	void wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false,
 						  LLPointer<LLInventoryCallback> cb = NULL);
 
 	// Update the displayed outfit name in UI.
-- 
cgit v1.2.3


From 39b17157f9c31a4b911113561d4fc8f86396c430 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 16 Apr 2015 15:45:33 -0400
Subject: Fix for bad syntax that displeased linux more than windows.

---
 indra/newview/llappearancemgr.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra/newview')

diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 0e9967175b..ee9d3b7209 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -121,10 +121,10 @@ public:
 	// find the UUID of the currently worn outfit (Base Outfit)
 	const LLUUID getBaseOutfitUUID();
 
-    void LLAppearanceMgr::wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,
-                                        bool do_update,
-                                        bool replace,
-                                        LLPointer<LLInventoryCallback> cb = NULL);
+    void wearItemsOnAvatar(const uuid_vec_t& item_ids_to_wear,
+                           bool do_update,
+                           bool replace,
+                           LLPointer<LLInventoryCallback> cb = NULL);
 
 	// Wear/attach an item (from a user's inventory) on the agent
 	void wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false,
-- 
cgit v1.2.3


From f3c58f765c0168f25bb13c4427e34b4bdad2f671 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 26 May 2015 16:36:45 -0400
Subject: increment viewer version to 3.7.30

---
 indra/newview/VIEWER_VERSION.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/newview')

diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 1523336b0d..ef239df8cd 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.29
+3.7.30
-- 
cgit v1.2.3