diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index be58a562c0c5e1b197c681c66a396eb092243829..4e96372da93ed2339dd1ba6f476da3bf5da391d5 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1068,7 +1068,7 @@ void LLAppearanceMgr::takeOffOutfit(const LLUUID& cat_id)
 {
 	LLInventoryModel::cat_array_t cats;
 	LLInventoryModel::item_array_t items;
-	LLFindWorn collector;
+	LLFindWearablesEx collector(/*is_worn=*/ true, /*include_body_parts=*/ false);
 
 	gInventory.collectDescendentsIf(cat_id, cats, items, FALSE, collector);
 
@@ -1224,6 +1224,34 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id)
 	return true;
 }
 
+// static
+bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id)
+{
+	LLInventoryModel::cat_array_t cats;
+	LLInventoryModel::item_array_t items;
+	LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false);
+	gInventory.collectDescendentsIf(outfit_cat_id,
+		cats,
+		items,
+		LLInventoryModel::EXCLUDE_TRASH,
+		is_worn);
+	return items.size() > 0;
+}
+
+// static
+bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id)
+{
+	LLInventoryModel::cat_array_t cats;
+	LLInventoryModel::item_array_t items;
+	LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false);
+	gInventory.collectDescendentsIf(outfit_cat_id,
+		cats,
+		items,
+		LLInventoryModel::EXCLUDE_TRASH,
+		not_worn);
+	return items.size() > 0;
+}
+
 void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category)
 {
 	LLInventoryModel::cat_array_t cats;
@@ -1338,9 +1366,12 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
 
 	// - Body parts: always include COF contents as a fallback in case any
 	// required parts are missing.
+	// Preserve body parts from COF if appending.
 	LLInventoryModel::item_array_t body_items;
 	getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false);
 	getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false);
+	if (append)
+		reverse(body_items.begin(), body_items.end());
 	// Reduce body items to max of one per type.
 	removeDuplicateItems(body_items);
 	filterWearableItems(body_items, 1);
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index e42f9f7d6f4bd02900479c5333ecb18fd730509e..8ded32a53d4e957deda365e1c4a9682ba0d75571 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -75,6 +75,12 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	// Determine whether a given outfit can be removed.
 	bool getCanRemoveOutfit(const LLUUID& outfit_cat_id);
 
+	// Determine whether we're wearing any of the outfit contents (excluding body parts).
+	static bool getCanRemoveFromCOF(const LLUUID& outfit_cat_id);
+
+	// Determine whether we can add anything (but body parts) from the outfit contents to COF.
+	static bool getCanAddToCOF(const LLUUID& outfit_cat_id);
+
 	// 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 ec367c1746f0b6ed517ef836144f8eb2a05b41ae..1881d0d780e0c291c7df3bfe728adcbd75fb258f 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2489,7 +2489,7 @@ void LLFolderBridge::folderOptionsMenu()
 			mItems.push_back(std::string("Wear As Ensemble"));
 		}
 		mItems.push_back(std::string("Remove From Outfit"));
-		if (!areAnyContentsWorn(model))
+		if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID))
 		{
 			disabled_items.push_back(std::string("Remove From Outfit"));
 		}
@@ -2514,19 +2514,6 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv
 	return ((item_array.count() > 0) ? TRUE : FALSE );
 }
 
-BOOL LLFolderBridge::areAnyContentsWorn(LLInventoryModel* model) const
-{
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t item_array;
-	LLFindWorn is_worn;
-	model->collectDescendentsIf(mUUID,
-								cat_array,
-								item_array,
-								LLInventoryModel::EXCLUDE_TRASH,
-								is_worn);
-	return (item_array.size() > 0);
-}
-
 // Flags unused
 void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 {
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 757808eb93cf50d80cf94e91302e9155dfb59e00..64d0f8d25452339586c5557589a42f7dbf7b1eaa 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -295,7 +295,6 @@ class LLFolderBridge : public LLInvFVBridge
 	static void createNewEyes(void* user_data);
 
 	BOOL checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& typeToCheck);
-	BOOL areAnyContentsWorn(LLInventoryModel* model) const;
 
 	void modifyOutfit(BOOL append);
 	void determineFolderType();
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index de24bd92d0c0b06ecd9497cac2003d27034d44c3..469d1888dde13b4d735d516955bc82f7e988b1b5 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -573,6 +573,31 @@ bool LLFindWearables::operator()(LLInventoryCategory* cat,
 	return FALSE;
 }
 
+LLFindWearablesEx::LLFindWearablesEx(bool is_worn, bool include_body_parts)
+:	mIsWorn(is_worn)
+,	mIncludeBodyParts(include_body_parts)
+{}
+
+bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+{
+	LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
+	if (!vitem) return false;
+
+	// Skip non-wearables.
+	if (!vitem->isWearableType() && vitem->getType() != LLAssetType::AT_OBJECT)
+	{
+		return false;
+	}
+
+	// Skip body parts if requested.
+	if (!mIncludeBodyParts && vitem->getType() == LLAssetType::AT_BODYPART)
+	{
+		return false;
+	}
+
+	return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;
+}
+
 bool LLFindWearablesOfType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 {
 	if (!item) return false;
@@ -593,11 +618,6 @@ void LLFindWearablesOfType::setType(LLWearableType::EType type)
 	mWearableType = type;
 }
 
-bool LLFindWorn::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
-{
-	return item && get_is_item_worn(item->getUUID());
-}
-
 bool LLFindNonRemovableObjects::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
 {
 	if (item)
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 93c56e1b8a6075dde112fdaaf443ce2ff6422b4b..1795b546797e55223a41f03bf7672d477baf0354 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -337,6 +337,21 @@ class LLFindWearables : public LLInventoryCollectFunctor
 							LLInventoryItem* item);
 };
 
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFindWearablesEx
+//
+// Collects wearables based on given criteria.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFindWearablesEx : public LLInventoryCollectFunctor
+{
+public:
+	LLFindWearablesEx(bool is_worn, bool include_body_parts = true);
+	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+private:
+	bool mIncludeBodyParts;
+	bool mIsWorn;
+};
+
 //Inventory collect functor collecting wearables of a specific wearable type
 class LLFindWearablesOfType : public LLInventoryCollectFunctor
 {
@@ -363,15 +378,6 @@ class LLFindActualWearablesOfType : public LLFindWearablesOfType
 	}
 };
 
-// Find worn items.
-class LLFindWorn : public LLInventoryCollectFunctor
-{
-public:
-	LLFindWorn() {}
-	virtual ~LLFindWorn() {}
-	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
-};
-
 // Collect non-removable folders and items.
 class LLFindNonRemovableObjects : public LLInventoryCollectFunctor
 {
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 8c6189353e196ec16ca9804c47473339cea20512..73c850e1fb2a51c51fc2df295544a37607b69c18 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -102,6 +102,14 @@ class OutfitContextMenu : public LLListContextMenu
 		{
 			return get_is_category_renameable(&gInventory, outfit_cat_id);
 		}
+		else if ("wear_add" == param)
+		{
+			return LLAppearanceMgr::getCanAddToCOF(outfit_cat_id);
+		}
+		else if ("take_off" == param)
+		{
+			return LLAppearanceMgr::getCanRemoveFromCOF(outfit_cat_id);
+		}
 
 		return true;
 	}
@@ -119,14 +127,6 @@ class OutfitContextMenu : public LLListContextMenu
 		{
 			return !is_worn;
 		}
-		else if ("wear_add" == param)
-		{
-			return !is_worn;
-		}
-		else if ("take_off" == param)
-		{
-			return is_worn;
-		}
 		else if ("delete" == param)
 		{
 			return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id);
diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp
index e2563efb7d573d405dff588e4d27f6791ab1c3b0..2405b95e7ddb5f8da7ac3894239bc1eef7df0529 100644
--- a/indra/newview/llpaneloutfitsinventory.cpp
+++ b/indra/newview/llpaneloutfitsinventory.cpp
@@ -191,6 +191,10 @@ class LLOutfitListGearMenu
 		{
 			return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id);
 		}
+		else if ("take_off" == param)
+		{
+			return LLAppearanceMgr::getCanRemoveFromCOF(selected_outfit_id);
+		}
 
 		return true;
 	}
@@ -209,10 +213,6 @@ class LLOutfitListGearMenu
 		{
 			return !is_worn;
 		}
-		else if ("take_off" == param)
-		{
-			return is_worn;
-		}
 
 		return true;
 	}
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_outfit_tab.xml
index e084216a69d2c80db722f74a85a4adebc57c5b32..9206969b2f27d54cbd9c7142d85d5bfe4781dd21 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_tab.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_tab.xml
@@ -18,6 +18,9 @@
      name="wear_add">
         <on_click
          function="Outfit.WearAdd" />
+        <on_enable
+         function="Outfit.OnEnable"
+         parameter="wear_add" />
         <on_visible
          function="Outfit.OnVisible"
          parameter="wear_add" />
@@ -28,6 +31,9 @@
      name="take_off">
         <on_click
          function="Outfit.TakeOff" />
+        <on_enable
+         function="Outfit.OnEnable"
+         parameter="take_off" />
         <on_visible
          function="Outfit.OnVisible"
          parameter="take_off" />