From b232919c0a6d66582b57c8997fee7a99ab9bbddb Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 21 Aug 2012 17:03:42 -0400
Subject: [PATCH] SH-3625 WIP - consolidating code paths for
 wearable/attachment removal

---
 indra/newview/llappearancemgr.cpp     | 51 ++++++++++++---------------
 indra/newview/llappearancemgr.h       |  1 +
 indra/newview/llcofwearables.cpp      |  6 ++--
 indra/newview/llinventorybridge.cpp   | 34 +++---------------
 indra/newview/llpanelwearing.cpp      | 15 +++-----
 indra/newview/llviewermenu.cpp        |  6 ++--
 indra/newview/llwearableitemslist.cpp | 11 +++---
 7 files changed, 45 insertions(+), 79 deletions(-)
 mode change 100644 => 100755 indra/newview/llcofwearables.cpp
 mode change 100644 => 100755 indra/newview/llinventorybridge.cpp
 mode change 100644 => 100755 indra/newview/llpanelwearing.cpp
 mode change 100644 => 100755 indra/newview/llviewermenu.cpp
 mode change 100644 => 100755 indra/newview/llwearableitemslist.cpp

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 0b425b656c..933049fa79 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2215,6 +2215,29 @@ void LLAppearanceMgr::addEnsembleLink( LLInventoryCategory* cat, bool do_update
 #endif
 }
 
+void LLAppearanceMgr::removeAllClothesFromAvatar()
+{
+	// Fetch worn clothes (i.e. the ones in COF).
+	LLInventoryModel::item_array_t clothing_items;
+	LLInventoryModel::cat_array_t dummy;
+	LLIsType is_clothing(LLAssetType::AT_CLOTHING);
+	gInventory.collectDescendentsIf(getCOF(),
+									dummy,
+									clothing_items,
+									LLInventoryModel::EXCLUDE_TRASH,
+									is_clothing,
+									false);
+	uuid_vec_t item_ids;
+	for (LLInventoryModel::item_array_t::iterator it = clothing_items.begin();
+		it != clothing_items.end(); ++it)
+	{
+		item_ids.push_back((*it).get()->getLinkedUUID());
+	}
+
+	// Take them off by removing from COF.
+	removeItemsFromAvatar(item_ids);
+}
+
 void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, bool do_update)
 {
 	gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
@@ -2721,37 +2744,9 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove)
 
 void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)
 {
-#if 1
 	LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove);
 	removeCOFItemLinks(linked_item_id,false);
 	updateAppearanceFromCOF();
-#else
-	LLViewerInventoryItem * item_to_remove = gInventory.getItem(id_to_remove);
-	if (!item_to_remove) return;
-
-	switch (item_to_remove->getType())
-	{
-		case LLAssetType::AT_CLOTHING:
-			if (get_is_item_worn(id_to_remove))
-			{
-				//*TODO move here the exact removing code from LLWearableBridge::removeItemFromAvatar in the future
-				LLWearableBridge::removeItemFromAvatar(item_to_remove);
-			}
-			break;
-		case LLAssetType::AT_OBJECT:
-			LLVOAvatarSelf::detachAttachmentIntoInventory(item_to_remove->getLinkedUUID());
-		default:
-			break;
-	}
-
-	// *HACK: Force to remove garbage from COF.
-	// Unworn links or objects can't be processed by existed removing functionality
-	// since it is not designed for such cases. As example attachment object can't be removed
-	// since sever don't sends message _PREHASH_KillObject in that case.
-	// Also we can't check is link was successfully removed from COF since in case
-	// deleting attachment link removing performs asynchronously in process_kill_object callback.
-	removeCOFItemLinks(id_to_remove,false);
-#endif
 }
 
 bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body)
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index c0f41075aa..7734eba144 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -135,6 +135,7 @@ public:
 	// Remove COF entries
 	void removeCOFItemLinks(const LLUUID& item_id, bool do_update = true);
 	void removeCOFLinksOfType(LLWearableType::EType type, bool do_update = true);
+	void removeAllClothesFromAvatar();
 
 	// Add COF link to ensemble folder.
 	void addEnsembleLink(LLInventoryCategory* item, bool do_update = true);
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
old mode 100644
new mode 100755
index e9c7a3fa03..e86d6930e8
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -139,8 +139,7 @@ protected:
 	{
 		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 
-		functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1);
-		registrar.add("Attachment.Detach", boost::bind(handleMultiple, take_off, mUUIDs));
+		registrar.add("Attachment.Detach", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
 
 		return createFromFile("menu_cof_attachment.xml");
 	}
@@ -173,9 +172,8 @@ protected:
 		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
 		LLUUID selected_id = mUUIDs.back();
-		functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1);
 
-		registrar.add("Clothing.TakeOff", boost::bind(handleMultiple, take_off, mUUIDs));
+		registrar.add("Clothing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
 		registrar.add("Clothing.Replace", boost::bind(replaceWearable, selected_id));
 		registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id));
 		registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id));
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
old mode 100644
new mode 100755
index b819100b9b..e07365109b
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2764,7 +2764,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
 		LLViewerInventoryCategory* cat = getCategory();
 		if(!cat) return;
 
-		remove_inventory_category_from_avatar ( cat );
+		LLAppearanceMgr::instance().takeOffOutfit( cat->getLinkedUUID() );
 		return;
 	}
 	else if ("purge" == action)
@@ -5073,11 +5073,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
 	}
 	else if (isRemoveAction(action))
 	{
-		LLInventoryItem* item = gInventory.getItem(mUUID);
-		if(item)
-		{
-			LLVOAvatarSelf::detachAttachmentIntoInventory(item->getLinkedUUID());
-		}
+		LLAppearanceMgr::instance().removeItemFromAvatar(mUUID);
 	}
 	else LLItemBridge::performAction(model, action);
 }
@@ -5827,30 +5823,10 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
 	delete on_remove_struct;
 }
 
-// static
-void LLWearableBridge::removeAllClothesFromAvatar()
-{
-	// Fetch worn clothes (i.e. the ones in COF).
-	LLInventoryModel::item_array_t clothing_items;
-	LLInventoryModel::cat_array_t dummy;
-	LLIsType is_clothing(LLAssetType::AT_CLOTHING);
-	gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(),
-									dummy,
-									clothing_items,
-									LLInventoryModel::EXCLUDE_TRASH,
-									is_clothing,
-									false);
-
-	// Take them off by removing from COF.
-	for (LLInventoryModel::item_array_t::const_iterator it = clothing_items.begin(); it != clothing_items.end(); ++it)
-	{
-		LLAppearanceMgr::instance().removeItemFromAvatar((*it)->getUUID());
-	}
-}
-
 // static
 void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item)
 {
+	llwarns << "safe to remove?" << llendl;
 	if (item)
 	{
 		LLWearableList::instance().getAsset(item->getAssetUUID(),
@@ -5863,10 +5839,10 @@ void LLWearableBridge::removeItemFromAvatar(LLViewerInventoryItem *item)
 
 void LLWearableBridge::removeFromAvatar()
 {
+	llwarns << "safe to remove?" << llendl;
 	if (get_is_item_worn(mUUID))
 	{
-		LLViewerInventoryItem* item = getItem();
-		removeItemFromAvatar(item);
+		LLAppearanceMgr::instance().removeItemFromAvatar(mUUID);
 	}
 }
 
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
old mode 100644
new mode 100755
index 3b9934d4be..aa3ed22bee
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -77,11 +77,7 @@ private:
 	{
 		uuid_vec_t selected_uuids;
 		mPanelWearing->getSelectedItemsUUIDs(selected_uuids);
-
-		for (uuid_vec_t::const_iterator it=selected_uuids.begin(); it != selected_uuids.end(); ++it)
-		{
-				LLAppearanceMgr::instance().removeItemFromAvatar(*it);
-		}
+		LLAppearanceMgr::instance().removeItemsFromAvatar(selected_uuids);
 	}
 
 	LLToggleableMenu*		mMenu;
@@ -97,12 +93,11 @@ protected:
 	{
 		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 
-		functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1);
-
 		registrar.add("Wearing.Edit", boost::bind(&edit_outfit));
-		registrar.add("Wearing.TakeOff", boost::bind(handleMultiple, take_off, mUUIDs));
-		registrar.add("Wearing.Detach", boost::bind(handleMultiple, take_off, mUUIDs));
-
+		registrar.add("Wearing.TakeOff",
+					  boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
+		registrar.add("Wearing.Detach", 
+					  boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs));
 		LLContextMenu* menu = createFromFile("menu_wearing_tab.xml");
 
 		updateMenuItemsVisibility(menu);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
old mode 100644
new mode 100755
index 01a54509ef..5bed2eccb5
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7897,7 +7897,7 @@ class LLEditTakeOff : public view_listener_t
 	{
 		std::string clothing = userdata.asString();
 		if (clothing == "all")
-			LLWearableBridge::removeAllClothesFromAvatar();
+			LLAppearanceMgr::instance().removeAllClothesFromAvatar();
 		else
 		{
 			LLWearableType::EType type = LLWearableType::typeNameToType(clothing);
@@ -7907,8 +7907,8 @@ class LLEditTakeOff : public view_listener_t
 			{
 				// MULTI-WEARABLES: assuming user wanted to remove top shirt.
 				U32 wearable_index = gAgentWearables.getWearableCount(type) - 1;
-				LLViewerInventoryItem *item = dynamic_cast<LLViewerInventoryItem*>(gAgentWearables.getWearableInventoryItem(type,wearable_index));
-				LLWearableBridge::removeItemFromAvatar(item);
+				LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index);
+				LLAppearanceMgr::instance().removeItemFromAvatar(item_id);
 			}
 				
 		}
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
old mode 100644
new mode 100755
index 92697fb2eb..c7e9215643
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -788,23 +788,24 @@ LLContextMenu* LLWearableItemsList::ContextMenu::createMenu()
 	const uuid_vec_t& ids = mUUIDs;		// selected items IDs
 	LLUUID selected_id = ids.front();	// ID of the first selected item
 
-	functor_t take_off = boost::bind(&LLAppearanceMgr::removeItemFromAvatar, LLAppearanceMgr::getInstance(), _1);
-
 	// Register handlers common for all wearable types.
 	registrar.add("Wearable.Wear", boost::bind(wear_multiple, ids, true));
 	registrar.add("Wearable.Add", boost::bind(wear_multiple, ids, false));
 	registrar.add("Wearable.Edit", boost::bind(handleMultiple, LLAgentWearables::editWearable, ids));
 	registrar.add("Wearable.CreateNew", boost::bind(createNewWearable, selected_id));
 	registrar.add("Wearable.ShowOriginal", boost::bind(show_item_original, selected_id));
-	registrar.add("Wearable.TakeOffDetach", boost::bind(handleMultiple, take_off, ids));
+	registrar.add("Wearable.TakeOffDetach", 
+				  boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids));
 
 	// Register handlers for clothing.
-	registrar.add("Clothing.TakeOff", boost::bind(handleMultiple, take_off, ids));
+	registrar.add("Clothing.TakeOff", 
+				  boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids));
 
 	// Register handlers for body parts.
 
 	// Register handlers for attachments.
-	registrar.add("Attachment.Detach", boost::bind(handleMultiple, take_off, ids));
+	registrar.add("Attachment.Detach", 
+				  boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), ids));
 	registrar.add("Attachment.Profile", boost::bind(show_item_profile, selected_id));
 	registrar.add("Object.Attach", boost::bind(LLViewerAttachMenu::attachObjects, ids, _2));
 
-- 
GitLab