From 5df728d42b7e45b99b575fa10283129cafdbde78 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 24 Feb 2015 21:08:15 +0100 Subject: [PATCH] Fix link replace creating dirty outfits --- indra/newview/fsfloaterlinkreplace.cpp | 94 ++++++++++++++++++++++++-- indra/newview/fsfloaterlinkreplace.h | 9 ++- 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/indra/newview/fsfloaterlinkreplace.cpp b/indra/newview/fsfloaterlinkreplace.cpp index a5a8ab49e6..e11c07a8d5 100644 --- a/indra/newview/fsfloaterlinkreplace.cpp +++ b/indra/newview/fsfloaterlinkreplace.cpp @@ -30,6 +30,7 @@ #include "fsdroptarget.h" #include "llagent.h" +#include "llappearancemgr.h" #include "llinventoryfunctions.h" #include "lllineeditor.h" #include "lltextbox.h" @@ -147,16 +148,34 @@ void FSFloaterLinkReplace::onStartClicked() mStatusText->setText(getString("ItemsRemaining", args)); const LLUUID cof_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const LLUUID outfit_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it) { - if ((*it)->getParentUUID() != cof_folder_id) + LLPointer source_item = *it; + + if (source_item->getParentUUID() != cof_folder_id) { + bool is_outfit_folder = gInventory.isObjectDescendentOf(source_item->getParentUUID(), outfit_folder_id); + // If either the new or old item in the COF is a wearable, we need to update wearable ordering after the link has been replaced + bool needs_wearable_ordering_update = is_outfit_folder && source_item->getType() == LLAssetType::AT_CLOTHING || target_item->getType() == LLAssetType::AT_CLOTHING; + // Other items in the COF need a description update (description of the actual link item must be empty) + bool needs_description_update = is_outfit_folder && target_item->getType() != LLAssetType::AT_CLOTHING; + + LL_DEBUGS() << "is_outfit_folder = " << (is_outfit_folder ? "true" : "false") << LL_NEWLINE + << "needs_wearable_ordering_update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_NEWLINE + << "needs_description_update = " << (needs_description_update ? "true" : "false") << LL_ENDL; + LLInventoryObject::const_object_list_t obj_array; obj_array.push_back(LLConstPointer(target_item)); - link_inventory_array((*it)->getParentUUID(), + link_inventory_array(source_item->getParentUUID(), obj_array, - new LLBoostFuncInventoryCallback(boost::bind(&FSFloaterLinkReplace::linkCreatedCallback, this, (*it)->getUUID()))); - + new LLBoostFuncInventoryCallback(boost::bind(&FSFloaterLinkReplace::linkCreatedCallback, + this, + source_item->getUUID(), + target_item->getUUID(), + needs_wearable_ordering_update, + needs_description_update, + (is_outfit_folder ? source_item->getParentUUID() : LLUUID::null) ))); } else { @@ -172,10 +191,71 @@ void FSFloaterLinkReplace::onStartClicked() } } -void FSFloaterLinkReplace::linkCreatedCallback(const LLUUID& old_item_id) +void FSFloaterLinkReplace::linkCreatedCallback(const LLUUID& old_item_id, + const LLUUID& target_item_id, + bool needs_wearable_ordering_update, + bool needs_description_update, + const LLUUID& outfit_folder_id) { - LL_DEBUGS() << "Inventory link replace: old_item_id = " << old_item_id.asString() << LL_ENDL; - remove_inventory_object(old_item_id, NULL); + LL_DEBUGS() << "Inventory link replace:" << LL_NEWLINE + << " - old_item_id = " << old_item_id.asString() << LL_NEWLINE + << " - target_item_id = " << target_item_id.asString() << LL_NEWLINE + << " - order update = " << (needs_wearable_ordering_update ? "true" : "false") << LL_NEWLINE + << " - description update = " << (needs_description_update ? "true" : "false") << LL_NEWLINE + << " - outfit_folder_id = " << outfit_folder_id.asString() << LL_ENDL; + + // If we are replacing an object, bodypart or gesture link within an outfit folder, + // we need to change the actual description of the link itself. LLAppearanceMgr *should* + // have created COF links that will be used to save the outfit with an empty description. + // Since link_inventory_array() will set the description of the linked item for the link + // itself, this will lead to a dirty outfit state when the outfit with the replaced + // link is worn. So we have to correct this. + if (needs_description_update && outfit_folder_id.notNull()) + { + LLInventoryModel::item_array_t items; + LLInventoryModel::cat_array_t cats; + LLLinkedItemIDMatches is_target_link(target_item_id); + gInventory.collectDescendentsIf(outfit_folder_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_target_link); + + for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it) + { + LLPointer item = *it; + + if ((item->getType() == LLAssetType::AT_BODYPART || + item->getType() == LLAssetType::AT_OBJECT || + item->getType() == LLAssetType::AT_GESTURE) + && !item->getActualDescription().empty()) + { + LL_DEBUGS() << "Updating description for " << item->getName() << LL_ENDL; + + LLSD updates; + updates["desc"] = ""; + update_inventory_item(item->getUUID(), updates, LLPointer(NULL)); + } + } + } + + if (needs_wearable_ordering_update && outfit_folder_id.notNull()) + { + // If a wearable item was involved in the link replace operation and replaced + // a link in an outfit folder, we need to update the clothing ordering information + // *after* the original link has been removed. LLAppearanceMgr abuses the actual link + // description to store the clothing ordering information it. We will have to update + // the clothing ordering information or the outfit will be in dirty state when worn. + remove_inventory_object(old_item_id, new LLBoostFuncInventoryCallback(boost::bind(&LLAppearanceMgr::updateClothingOrderingInfo, + LLAppearanceMgr::getInstance(), + outfit_folder_id, + LLPointer(NULL)))); + } + else + { + remove_inventory_object(old_item_id, NULL); + } + decreaseOpenItemCount(); } diff --git a/indra/newview/fsfloaterlinkreplace.h b/indra/newview/fsfloaterlinkreplace.h index 933dc8f47a..cd457a83ba 100644 --- a/indra/newview/fsfloaterlinkreplace.h +++ b/indra/newview/fsfloaterlinkreplace.h @@ -35,6 +35,8 @@ class LLTextBox; class FSFloaterLinkReplace : public LLFloater { + LOG_CLASS(FSFloaterLinkReplace); + public: FSFloaterLinkReplace(const LLSD& key); virtual ~FSFloaterLinkReplace(); @@ -48,7 +50,12 @@ private: void decreaseOpenItemCount(); void updateFoundLinks(); - void linkCreatedCallback(const LLUUID& old_item_id); + void linkCreatedCallback(const LLUUID& old_item_id, + const LLUUID& target_item_id, + bool needs_wearable_ordering_update, + bool needs_description_update, + const LLUUID& outfit_folder_id); + void onSourceItemDrop(const LLUUID& source_item_id); void onTargetItemDrop(const LLUUID& target_item_id);