From 2caa710a46d3baa1e6a884961f1ff756d35ef5df Mon Sep 17 00:00:00 2001
From: "Nyx (Neal Orman)" <nyx@lindenlab.com>
Date: Thu, 3 Jun 2010 20:06:25 -0400
Subject: [PATCH] VWR-19699 WIP Correct operations for wear and replace on
 wearables

Resident-submitted patch, cleaned up so it matches style and compiles/builds
well. Appears to work for stated goals but will need some more UI work to
ensure consistency.

WIP checkin, will be code reviewed before pushing.
---
 doc/contributions.txt                         |   2 +
 indra/newview/llappearancemgr.cpp             |  33 +++++-
 indra/newview/llinventorybridge.cpp           | 112 +-----------------
 indra/newview/llinventorybridge.h             |   2 -
 indra/newview/llinventorymodel.cpp            |   3 +-
 indra/newview/lltooldraganddrop.cpp           |  19 +--
 indra/newview/llviewerinventory.cpp           |   2 +-
 indra/newview/llviewerinventory.h             |   6 +
 .../skins/default/xui/en/menu_inventory.xml   |   8 ++
 9 files changed, 53 insertions(+), 134 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 3f33763ce07..5667b69c281 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -323,6 +323,8 @@ Khyota Wulluf
 	VWR-8885
 	VWR-9256
 	VWR-9966
+Kitty Barnett
+	VWR-19699
 Kunnis Basiat
 	VWR-82
 	VWR-102
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index e6f363028af..5071b1c14ad 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -656,15 +656,40 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
 {
 	if (item_id_to_wear.isNull()) return false;
 
-	//only the item from a user's inventory is allowed
-	if (!gInventory.isObjectDescendentOf(item_id_to_wear, gInventory.getRootFolderID())) return false;
-
 	LLViewerInventoryItem* item_to_wear = gInventory.getItem(item_id_to_wear);
 	if (!item_to_wear) return false;
 
+	if (!item_to_wear->isFinished())
+	{
+		LLNotificationsUtil::add("CannotWearInfoNotComplete");
+		return false;
+	}
+	else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), gInventory.getLibraryRootFolderID()))
+	{
+		LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(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");
+	}
+
 	switch (item_to_wear->getType())
 	{
 	case LLAssetType::AT_CLOTHING:
+		if (replace && gAgentWearables.areWearablesLoaded())
+		{
+			S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType());
+			if (wearable_count != 0)
+			{
+				removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1), false);
+			}
+		}
 	case LLAssetType::AT_BODYPART:
 		// Don't wear anything until initial wearables are loaded, can
 		// destroy clothing items.
@@ -676,7 +701,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
 
 		// 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.
-		if (replace || item_to_wear->getType() == LLAssetType::AT_BODYPART)
+		if (item_to_wear->getType() == LLAssetType::AT_BODYPART)
 		{
 			removeCOFLinksOfType(item_to_wear->getWearableType(), false);
 		}
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index b7495f7dbe0..827688ec296 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -103,7 +103,6 @@ void dec_busy_count()
 }
 
 // Function declarations
-void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
 void remove_inventory_category_from_avatar(LLInventoryCategory* category);
 void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
 bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
@@ -4295,33 +4294,6 @@ LLWearableBridge::LLWearableBridge(LLInventoryPanel* inventory,
 	mInvType = inv_type;
 }
 
-// *NOTE: hack to get from avatar inventory to avatar
-void wear_inventory_item_on_avatar( LLInventoryItem* item )
-{
-	if(item)
-	{
-		lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
-				 << " )" << llendl;
-
-		LLAppearanceMgr::getInstance()->wearItemOnAvatar(item->getUUID(), true, false);
-	}
-}
-
-void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
-{
-	if(item)
-	{
-		lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
-				 << " )" << llendl;
-
-		LLWearableList::instance().getAsset(item->getAssetUUID(),
-											item->getName(),
-											item->getType(),
-											LLWearableBridge::onWearAddOnAvatarArrived,
-											new LLUUID(item->getUUID()));
-	}
-}
-
 void remove_inventory_category_from_avatar( LLInventoryCategory* category )
 {
 	if(!category) return;
@@ -4637,21 +4609,7 @@ void LLWearableBridge::wearOnAvatar()
 	LLViewerInventoryItem* item = getItem();
 	if(item)
 	{
-		if(!isAgentInventory())
-		{
-			LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
-			copy_inventory_item(
-				gAgent.getID(),
-				item->getPermissions().getOwner(),
-				item->getUUID(),
-				LLUUID::null,
-				std::string(),
-				cb);
-		}
-		else
-		{
-			wear_inventory_item_on_avatar(item);
-		}
+		LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true);
 	}
 }
 
@@ -4668,21 +4626,7 @@ void LLWearableBridge::wearAddOnAvatar()
 	LLViewerInventoryItem* item = getItem();
 	if(item)
 	{
-		if(!isAgentInventory())
-		{
-			LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
-			copy_inventory_item(
-				gAgent.getID(),
-				item->getPermissions().getOwner(),
-				item->getUUID(),
-				LLUUID::null,
-				std::string(),
-				cb);
-		}
-		else
-		{
-			wear_add_inventory_item_on_avatar(item);
-		}
+		LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, false);
 	}
 }
 
@@ -5207,41 +5151,7 @@ class LLWearableBridgeAction: public LLInvFVBridgeAction
 public:
 	virtual void doIt()
 	{
-		if(isItemInTrash())
-		{
-			LLNotificationsUtil::add("CannotWearTrash");
-		}
-		else if(isAgentInventory())
-		{
-			if(!get_is_item_worn(mUUID))
-			{
-				wearOnAvatar();
-			}
-		}
-		else
-		{
-			// must be in the inventory library. copy it to our inventory
-			// and put it on right away.
-			LLViewerInventoryItem* item = getItem();
-			if(item && item->isFinished())
-			{
-				LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
-				copy_inventory_item(
-					gAgent.getID(),
-					item->getPermissions().getOwner(),
-					item->getUUID(),
-					LLUUID::null,
-					std::string(),
-					cb);
-			}
-			else if(item)
-			{
-				// *TODO: We should fetch the item details, and then do
-				// the operation above.
-				LLNotificationsUtil::add("CannotWearInfoNotComplete");
-			}
-		}
-		LLInvFVBridgeAction::doIt();
+		wearOnAvatar();
 	}
 	virtual ~LLWearableBridgeAction(){}
 protected:
@@ -5280,21 +5190,7 @@ void LLWearableBridgeAction::wearOnAvatar()
 	LLViewerInventoryItem* item = getItem();
 	if(item)
 	{
-		if(!isAgentInventory())
-		{
-			LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
-			copy_inventory_item(
-				gAgent.getID(),
-				item->getPermissions().getOwner(),
-				item->getUUID(),
-				LLUUID::null,
-				std::string(),
-				cb);
-		}
-		else
-		{
-			wear_inventory_item_on_avatar(item);
-		}
+		LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(), true, true);
 	}
 }
 
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 59c1f3d6fb5..dcf04872509 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -592,8 +592,6 @@ class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder
 		U32 flags = 0x00) const;
 };
 
-void wear_inventory_item_on_avatar(LLInventoryItem* item);
-
 void rez_attachment(LLViewerInventoryItem* item, 
 					LLViewerJointAttachment* attachment);
 
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 2e1c5238d36..6fc5804a488 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -35,6 +35,7 @@
 
 #include "llagent.h"
 #include "llagentwearables.h"
+#include "llappearancemgr.h"
 #include "llinventorypanel.h"
 #include "llinventorybridge.h"
 #include "llinventoryfunctions.h"
@@ -2561,7 +2562,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
 		{
 			LLViewerInventoryItem* wearable_item;
 			wearable_item = gInventory.getItem(wearable_ids[i]);
-			wear_inventory_item_on_avatar(wearable_item);
+			LLAppearanceMgr::instance().wearItemOnAvatar(wearable_item->getUUID(), true, true);
 		}
 	}
 
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index bc77ac5fd13..c862c02b82b 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1878,24 +1878,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem(
 				LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded");
 				return ACCEPT_NO;
 			}
-
-			if (mSource == SOURCE_LIBRARY)
-			{
-				// create item based on that one, and put it on if that
-				// was a success.
-				LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
-				copy_inventory_item(
-					gAgent.getID(),
-					item->getPermissions().getOwner(),
-					item->getUUID(),
-					LLUUID::null,
-					std::string(),
-					cb);
-			}
-			else
-			{
-				wear_inventory_item_on_avatar( item );
-			}
+			LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(),true, !(mask & MASK_CONTROL));
 		}
 		return ACCEPT_YES_MULTI;
 	}
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index d745356dcdc..face7124c21 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -875,7 +875,7 @@ void WearOnAvatarCallback::fire(const LLUUID& inv_item)
 	LLViewerInventoryItem *item = gInventory.getItem(inv_item);
 	if (item)
 	{
-		wear_inventory_item_on_avatar(item);
+		LLAppearanceMgr::instance().wearItemOnAvatar(inv_item, true, mReplace);
 	}
 }
 
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 8ab7c9710d4..d0d3ad693e1 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -243,7 +243,13 @@ class LLInventoryCallback : public LLRefCount
 
 class WearOnAvatarCallback : public LLInventoryCallback
 {
+public:
+	WearOnAvatarCallback(bool do_replace = false) : mReplace(do_replace) {}
+	
 	void fire(const LLUUID& inv_item);
+
+protected:
+	bool mReplace;
 };
 
 class ModifiedCOFCallback : public LLInventoryCallback
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 11459ad0e61..221457ac1fa 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -661,6 +661,14 @@
          function="Inventory.DoToSelected"
          parameter="wear" />
     </menu_item_call>
+    <menu_item_call
+     label="Add"
+     layout="topleft"
+     name="Wearable Add">
+        <menu_item_call.on_click
+         function="Inventory.DoToSelected"
+         parameter="wear_add" />
+    </menu_item_call>
     <menu_item_call
      label="Take Off"
      layout="topleft"
-- 
GitLab