From 7eca974a11cba4c4ed0bc89bccb937b044770c29 Mon Sep 17 00:00:00 2001 From: Bradley Payne Date: Thu, 24 Sep 2009 18:05:38 +0000 Subject: Merging down avatar-pipeline/currently-worn-folder-8. Includes fixes for EXT-1121: Attaching / detaching objects doesn't affect the Current Outfit folder, and EXT-1090: Attachments detach on login, as well as work in progress for ensemble support and look details. --- indra/newview/llagentwearables.cpp | 99 ++-------- indra/newview/llagentwearables.h | 2 +- indra/newview/llappearancemgr.cpp | 205 ++++++++++++++++----- indra/newview/llappearancemgr.h | 16 +- indra/newview/llfloaterinventory.cpp | 14 +- indra/newview/llinventorybridge.cpp | 123 ++++++++++--- indra/newview/llinventorymodel.cpp | 9 +- indra/newview/llinventorymodel.h | 15 ++ indra/newview/llstartup.cpp | 4 - indra/newview/llviewermenu.cpp | 2 +- indra/newview/llvoavatar.cpp | 13 ++ indra/newview/llvoavatarself.cpp | 6 + .../skins/default/xui/en/menu_inventory.xml | 8 + 13 files changed, 351 insertions(+), 165 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index c4e01808f7..6eb248ef74 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1172,99 +1172,24 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name, return LLUUID::null; } - // First, make a folder in the Clothes directory. + // First, make a folder in the My Outfits directory. + LLUUID parent_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_MY_OUTFITS); LLUUID folder_id = gInventory.createNewCategory( - gInventory.findCategoryUUIDForType(LLAssetType::AT_MY_OUTFITS), + parent_id, LLAssetType::AT_OUTFIT, new_folder_name); -// bool found_first_item = false; - - /////////////////// - // Wearables + LLAppearanceManager::shallowCopyCategory(LLAppearanceManager::getCOF(),folder_id, NULL); - if (wearables_to_include.count()) +#if 0 + LLViewerInventoryCategory *parent_category = gInventory.getCategory(parent_id); + if (parent_category) { - // Then, iterate though each of the wearables and save links to them in the folder. - S32 i; - S32 count = wearables_to_include.count(); - LLDynamicArray delete_items; - LLPointer cbdone = NULL; - for (i = 0; i < count; ++i) - { - const S32 type = wearables_to_include[i]; - for (U32 j=0; j cb = NULL; - link_inventory_item(gAgent.getID(), - item->getLinkedUUID(), - folder_id, - item->getName(), - LLAssetType::AT_LINK, - cb); - } - } - } - gInventory.notifyObservers(); + parent_category->setSelectionByID(folder_id,TRUE); + parent_category->setNeedsAutoRename(TRUE); } +#endif - - /////////////////// - // Attachments - - if (attachments_to_include.count()) - { - for (S32 i = 0; i < attachments_to_include.count(); i++) - { - S32 attachment_pt = attachments_to_include[i]; - LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL); - if (!attachment) continue; - LLViewerObject* attached_object = attachment->getObject(); - if (!attached_object) continue; - const LLUUID& item_id = attachment->getItemID(); - if (item_id.isNull()) continue; - LLInventoryItem* item = gInventory.getItem(item_id); - if (!item) continue; - - LLPointer cb = NULL; - link_inventory_item(gAgent.getID(), - item->getLinkedUUID(), - folder_id, - item->getName(), - LLAssetType::AT_LINK, - cb); - } - } - - /////////////////// - // Gestures - - /* Disabling this for now, otherwise this adds all your default gestures and all previous - active gestures. Need to rethink the intended behavior. - for (LLGestureManager::item_map_t::iterator iter = LLGestureManager::instance().mActive.begin(); - iter != LLGestureManager::instance().mActive.end(); - ++iter) - { - const LLUUID &gesture_id = (*iter).first; - LLViewerInventoryItem* item = gInventory.getItem(gesture_id); - if (item) - { - LLPointer cb = NULL; - link_inventory_item(gAgent.getID(), - item->getUUID(), - folder_id, - item->getName(), - LLAssetType::AT_LINK, - cb); - } - } - */ - return folder_id; } @@ -1759,7 +1684,7 @@ void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed) } } -void LLAgentWearables::userRemoveAllAttachments(void* userdata) +void LLAgentWearables::userRemoveAllAttachments() { LLVOAvatar* avatarp = gAgent.getAvatarObject(); if (!avatarp) @@ -1819,7 +1744,7 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra msg->nextBlockFast(_PREHASH_HeaderData); msg->addUUIDFast(_PREHASH_CompoundMsgID, compound_msg_id ); msg->addU8Fast(_PREHASH_TotalObjects, obj_count ); - msg->addBOOLFast(_PREHASH_FirstDetachAll, true ); + msg->addBOOLFast(_PREHASH_FirstDetachAll, true ); // BAP changing this doesn't seem to matter? } const LLInventoryItem* item = obj_item_array.get(i).get(); diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index cb4de555d5..f34b23e220 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -181,7 +181,7 @@ public: // MULTI-WEARABLE: assuming one wearable per type. Need upstream changes. static void userRemoveWearable(void* userdata); // userdata is EWearableType static void userRemoveAllClothes(void* userdata); // userdata is NULL - static void userRemoveAllAttachments(void* userdata); // userdata is NULL + static void userRemoveAllAttachments(); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); BOOL itemUpdatePending(const LLUUID& item_id) const; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6c234f23fe..74a8d8fe15 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -239,33 +239,25 @@ void LLOutfitFetch::done() } } -class LLUpdateAppearanceOnCount: public LLInventoryCallback +class LLUpdateAppearanceOnDestroy: public LLInventoryCallback { public: - LLUpdateAppearanceOnCount(S32 count): - mCount(count) + LLUpdateAppearanceOnDestroy(): + mFireCount(0) { } - virtual ~LLUpdateAppearanceOnCount() + virtual ~LLUpdateAppearanceOnDestroy() { + LLAppearanceManager::updateAppearanceFromCOF(); } /* virtual */ void fire(const LLUUID& inv_item) { - mCount--; - if (mCount==0) - { - done(); - } - } - - void done() - { - LLAppearanceManager::updateAppearanceFromCOF(); + mFireCount++; } private: - S32 mCount; + U32 mFireCount; }; struct LLFoundData @@ -362,25 +354,42 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory } // Update appearance from outfit folder. -/* static */ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append, bool follow_folder_links) +/* static */ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append) { if (!proceed) return; - - updateCOFFromOutfit(category, append, follow_folder_links); + + if (append) + { + updateCOFFromCategory(category, append); // append is true - add non-duplicates to COF. + } + else + { + LLViewerInventoryCategory* catp = gInventory.getCategory(category); + if (catp->getPreferredType() == LLAssetType::AT_NONE || + LLAssetType::lookupIsEnsembleCategoryType(catp->getPreferredType())) + { + updateCOFFromCategory(category, append); // append is false - rebuild COF. + } + else if (catp->getPreferredType() == LLAssetType::AT_OUTFIT) + { + rebuildCOFFromOutfit(category); + } + } } -// Update COF contents from outfit folder. -/* static */ void LLAppearanceManager::updateCOFFromOutfit(const LLUUID& category, bool append, bool follow_folder_links) +// Append to current COF contents by recursively traversing a folder. +/* static */ void LLAppearanceManager::updateCOFFromCategory(const LLUUID& category, bool append) { - // BAP consolidate into one "get all 3 types of descendents" function, use both places. + // BAP consolidate into one "get all 3 types of descendents" function, use both places. LLInventoryModel::item_array_t wear_items; - LLInventoryModel::item_array_t obj_items; - LLInventoryModel::item_array_t gest_items; + LLInventoryModel::item_array_t obj_items; + LLInventoryModel::item_array_t gest_items; + bool follow_folder_links = false; getUserDescendents(category, wear_items, obj_items, gest_items, follow_folder_links); // Find all the wearables that are in the category's subtree. - lldebugs << "updateCOFFromOutfit()" << llendl; + lldebugs << "appendCOFFromCategory()" << llendl; if( !wear_items.count() && !obj_items.count() && !gest_items.count()) { LLNotifications::instance().add("CouldNotPutOnOutfit"); @@ -395,31 +404,26 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory LLInventoryModel::item_array_t cof_items; gInventory.collectDescendents(current_outfit_id, cof_cats, cof_items, LLInventoryModel::EXCLUDE_TRASH); + // Remove duplicates if (append) { - // Remove duplicates removeDuplicateItems(wear_items, cof_items); removeDuplicateItems(obj_items, cof_items); removeDuplicateItems(gest_items, cof_items); } - - if (wear_items.count() > 0 || obj_items.count() > 0) + S32 total_links = gest_items.count() + wear_items.count() + obj_items.count(); + + if (!append && total_links > 0) { - if (!append) + // Remove all current outfit folder links since we're now replacing the contents. + for (S32 i = 0; i < cof_items.count(); ++i) { - // Remove all current outfit folder links if we're now replacing the contents. - for (S32 i = 0; i < cof_items.count(); ++i) - { - gInventory.purgeObject(cof_items.get(i)->getUUID()); - } + gInventory.purgeObject(cof_items.get(i)->getUUID()); } } - // BAP should we just link all contents, rather than restricting to these 3 types? - - S32 total_links = gest_items.count() + wear_items.count() + obj_items.count(); - LLPointer link_waiter = new LLUpdateAppearanceOnCount(total_links); + LLPointer link_waiter = new LLUpdateAppearanceOnDestroy; // Link all gestures in this folder if (gest_items.count() > 0) @@ -469,11 +473,86 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory } } } +} + +/* static */ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id, + LLPointer cb) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(src_id, cats, items, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i = 0; i < items.count(); ++i) + { + const LLViewerInventoryItem* item = items.get(i).get(); + if (item->getActualType() == LLAssetType::AT_LINK) + { + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + dst_id, + item->getName(), + LLAssetType::AT_LINK, cb); + } + else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER) + { + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + dst_id, + item->getName(), + LLAssetType::AT_LINK_FOLDER, cb); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + dst_id, + item->getName(), + cb); + } + } +} + +// Replace COF contents from a given outfit folder. +/* static */ void LLAppearanceManager::rebuildCOFFromOutfit(const LLUUID& category) +{ + lldebugs << "rebuildCOFFromOutfit()" << llendl; + + // Find all the wearables that are in the category's subtree. + LLInventoryModel::item_array_t items; + getCOFValidDescendents(category, items); + + if( items.count() == 0) + { + LLNotifications::instance().add("CouldNotPutOnOutfit"); + return; + } + + const LLUUID ¤t_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT); + // Processes that take time should show the busy cursor + //inc_busy_count(); + + LLInventoryModel::cat_array_t cof_cats; + LLInventoryModel::item_array_t cof_items; + gInventory.collectDescendents(current_outfit_id, cof_cats, cof_items, + LLInventoryModel::EXCLUDE_TRASH); + + if (items.count() > 0) + { + // Remove all current outfit folder links since we're now replacing the contents. + for (S32 i = 0; i < cof_items.count(); ++i) + { + gInventory.purgeObject(cof_items.get(i)->getUUID()); + } + } - // In the particular case that we're switching to a different outfit, - // create a link to the folder that we wore. + LLPointer link_waiter = new LLUpdateAppearanceOnDestroy; + LLAppearanceManager::shallowCopyCategory(category, current_outfit_id, link_waiter); + + // Create a link to the outfit that we wore. LLViewerInventoryCategory* catp = gInventory.getCategory(category); - if (!append && catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT) + if (catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT) { link_inventory_item(gAgent.getID(), category, current_outfit_id, catp->getName(), LLAssetType::AT_LINK_FOLDER, LLPointer(NULL)); @@ -621,7 +700,7 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, //If the folder doesn't contain only gestures, take off all attachments. if (!(wear_items.count() == 0 && obj_items.count() == 0 && gest_items.count() > 0) ) { - LLAgentWearables::userRemoveAllAttachments(NULL); + LLAgentWearables::userRemoveAllAttachments(); } if( obj_items.count() > 0 ) @@ -635,6 +714,21 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, } } +/* static */ +void LLAppearanceManager::getCOFValidDescendents(const LLUUID& category, + LLInventoryModel::item_array_t& items) +{ + LLInventoryModel::cat_array_t cats; + LLFindCOFValidItems is_cof_valid; + bool follow_folder_links = false; + gInventory.collectDescendentsIf(category, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_cof_valid, + follow_folder_links); +} + /* static */ void LLAppearanceManager::getUserDescendents(const LLUUID& category, LLInventoryModel::item_array_t& wear_items, LLInventoryModel::item_array_t& obj_items, @@ -708,14 +802,13 @@ void LLAppearanceManager::wearInventoryCategoryOnAvatar( LLInventoryCategory* ca lldebugs << "wearInventoryCategoryOnAvatar( " << category->getName() << " )" << llendl; - bool follow_folder_links = (category->getPreferredType() == LLAssetType::AT_CURRENT_OUTFIT || category->getPreferredType() == LLAssetType::AT_OUTFIT ); if( gFloaterCustomize ) { - gFloaterCustomize->askToSaveIfDirty(boost::bind(LLAppearanceManager::changeOutfit, _1, category->getUUID(), append, follow_folder_links)); + gFloaterCustomize->askToSaveIfDirty(boost::bind(LLAppearanceManager::changeOutfit, _1, category->getUUID(), append)); } else { - LLAppearanceManager::changeOutfit(TRUE, category->getUUID(), append, follow_folder_links ); + LLAppearanceManager::changeOutfit(TRUE, category->getUUID(), append); } } @@ -767,6 +860,7 @@ void LLAppearanceManager::wearOutfitByName(const std::string& name) //dec_busy_count(); } +/* static */ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update ) { // BAP add check for already in COF. @@ -779,6 +873,7 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update ) cb); } +/* static */ void LLAppearanceManager::wearEnsemble( LLInventoryCategory* cat, bool do_update ) { // BAP add check for already in COF. @@ -791,3 +886,25 @@ void LLAppearanceManager::wearEnsemble( LLInventoryCategory* cat, bool do_update cb); } +/* static */ +void LLAppearanceManager::removeItemLinks(LLUUID& item_id, bool do_update) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(LLAppearanceManager::getCOF(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i=0; igetLinkedUUID() == item_id) + { + gInventory.purgeObject(item_array.get(i)->getUUID()); + } + } + if (do_update) + { + LLAppearanceManager::updateAppearanceFromCOF(); + } +} diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 89b95833d7..2aa10e0bea 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -35,6 +35,7 @@ #include "llsingleton.h" #include "llinventorymodel.h" +#include "llviewerinventory.h" class LLWearable; struct LLWearableHoldingPattern; @@ -44,20 +45,29 @@ class LLAppearanceManager: public LLSingleton public: static void updateAppearanceFromCOF(); static bool needToSaveCOF(); - static void changeOutfit(bool proceed, const LLUUID& category, bool append, bool follow_folder_links); - static void updateCOFFromOutfit(const LLUUID& category, bool append, bool follow_folder_links); + static void changeOutfit(bool proceed, const LLUUID& category, bool append); + static void updateCOFFromCategory(const LLUUID& category, bool append); + static void rebuildCOFFromOutfit(const LLUUID& category); static void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append); static void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append); static void wearOutfitByName(const std::string& name); + static void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id, + LLPointer cb); // Add COF link to individual item. static void wearItem(LLInventoryItem* item, bool do_update = true); // Add COF link to ensemble folder. static void wearEnsemble(LLInventoryCategory* item, bool do_update = true); + static LLUUID getCOF(); + + // Remove COF entries + static void removeItemLinks(LLUUID& item_id, bool do_update = true); private: - static LLUUID getCOF(); + static void getCOFValidDescendents(const LLUUID& category, + LLInventoryModel::item_array_t& items); + static void getUserDescendents(const LLUUID& category, LLInventoryModel::item_array_t& wear_items, LLInventoryModel::item_array_t& obj_items, diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index 6a3a6c9514..27eb12b9cc 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -1229,7 +1229,11 @@ BOOL LLInventoryPanel::postBuild() // build everything. mInventoryObserver = new LLInventoryPanelObserver(this); mInventory->addObserver(mInventoryObserver); - rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD); + // build view of inventory if inventory ready, otherwise wait for modelChanged() callback + if (mInventory->isInventoryUsable()) + { + rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD); + } // bit of a hack to make sure the inventory is open. mFolders->openFolder(std::string("My Inventory")); @@ -1326,6 +1330,14 @@ void LLInventoryPanel::modelChanged(U32 mask) LLFastTimer t2(FTM_REFRESH); bool handled = false; + + // inventory just initialized, do complete build + if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty()) + { + rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD); + return; + } + if(mask & LLInventoryObserver::LABEL) { handled = true; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index eb07078402..40c5a243cc 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1481,8 +1481,8 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); if(!avatar) return FALSE; - // cannot drag categories into library or COF - if(!isAgentInventory() || isCOFFolder()) + // cannot drag categories into library + if(!isAgentInventory()) { return FALSE; } @@ -1729,6 +1729,34 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, return accept; } +bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + // Valid COF items are: + // - links to wearables (body parts or clothing) + // - links to attachments + // - links to gestures + // - links to ensemble folders + LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe? + if (linked_item) + { + LLAssetType::EType type = linked_item->getType(); + return (type == LLAssetType::AT_CLOTHING || + type == LLAssetType::AT_BODYPART || + type == LLAssetType::AT_GESTURE || + type == LLAssetType::AT_OBJECT); + } + else + { + LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe? + // BAP remove AT_NONE support after ensembles are fully working? + return (linked_category && + ((linked_category->getPreferredType() == LLAssetType::AT_NONE) || + (LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType())))); + } +} + + bool LLFindWearables::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { @@ -1743,6 +1771,8 @@ bool LLFindWearables::operator()(LLInventoryCategory* cat, return FALSE; } + + //Used by LLFolderBridge as callback for directory recursion. class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver { @@ -1948,6 +1978,15 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model modifyOutfit(FALSE); return; } + else if ("wearasensemble" == action) + { + LLInventoryModel* model = getInventoryModel(); + if(!model) return; + LLViewerInventoryCategory* cat = getCategory(); + if(!cat) return; + LLAppearanceManager::wearEnsemble(cat,true); + return; + } else if ("addtooutfit" == action) { modifyOutfit(TRUE); @@ -2277,8 +2316,11 @@ void LLFolderBridge::folderOptionsMenu() if(!model) return; const LLInventoryCategory* category = model->getCategory(mUUID); - const bool is_default_folder = category && - (LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType())); + LLAssetType::EType type = category->getPreferredType(); + const bool is_default_folder = category && LLAssetType::lookupIsProtectedCategoryType(type); + // BAP change once we're no longer treating regular categories as ensembles. + const bool is_ensemble = category && (type == LLAssetType::AT_NONE || + LLAssetType::lookupIsEnsembleCategoryType(type)); // calling card related functionality for folders. @@ -2313,6 +2355,10 @@ void LLFolderBridge::folderOptionsMenu() mItems.push_back(std::string("Add To Outfit")); mItems.push_back(std::string("Replace Outfit")); } + if (is_ensemble) + { + mItems.push_back(std::string("Wear As Ensemble")); + } mItems.push_back(std::string("Take Off Items")); } hideContextEntries(*mMenu, mItems, disabled_items); @@ -2370,8 +2416,10 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { LLViewerInventoryCategory *cat = getCategory(); - if (!isCOFFolder() && cat && - LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())) + // BAP removed protected check to re-enable standard ops in untyped folders. + // Not sure what the right thing is to do here. + if (!isCOFFolder() && cat /*&& + LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/) { // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) @@ -3983,6 +4031,16 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category ) } } +struct OnRemoveStruct +{ + LLUUID mUUID; + LLFolderView *mFolderToDeleteSelected; + OnRemoveStruct(const LLUUID& uuid, LLFolderView *fv = NULL): + mUUID(uuid), + mFolderToDeleteSelected(fv) + { + } +}; void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) { @@ -4030,10 +4088,10 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) ) { LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(), - item_array.get(i)->getName(), - item_array.get(i)->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new LLUUID(item_array.get(i)->getUUID())); + item_array.get(i)->getName(), + item_array.get(i)->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(item_array.get(i)->getUUID())); } } @@ -4134,12 +4192,25 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod { LLViewerInventoryItem* item = getItem(); if (item) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new LLUUID(mUUID)); + { + if (item->getIsLinkType() && + model->isObjectDescendentOf(mUUID,LLAppearanceManager::getCOF())) + { + // Delete link after item has been taken off. + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(mUUID, folder)); + } + else + { + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), + LLWearableBridge::onRemoveFromAvatarArrived, + new OnRemoveStruct(mUUID)); + } } } } @@ -4452,11 +4523,12 @@ void LLWearableBridge::onRemoveFromAvatar(void* user_data) LLViewerInventoryItem* item = self->getItem(); if (item) { + LLUUID parent_id = item->getParentUUID(); LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - onRemoveFromAvatarArrived, - new LLUUID(self->mUUID)); + item->getName(), + item->getType(), + onRemoveFromAvatarArrived, + new OnRemoveStruct(LLUUID(self->mUUID))); } } } @@ -4465,10 +4537,11 @@ void LLWearableBridge::onRemoveFromAvatar(void* user_data) void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, void* userdata) { - LLUUID* item_id = (LLUUID*) userdata; + OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; + LLUUID item_id = on_remove_struct->mUUID; if(wearable) { - if( gAgentWearables.isWearingItem( *item_id ) ) + if( gAgentWearables.isWearingItem( item_id ) ) { EWearableType type = wearable->getType(); @@ -4481,7 +4554,11 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, } } } - delete item_id; + if (on_remove_struct->mFolderToDeleteSelected) + { + on_remove_struct->mFolderToDeleteSelected->removeSelectedItems(); + } + delete on_remove_struct; } LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 4cbf3e169b..2f3171a868 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -474,7 +474,10 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, if (item->getActualType() == LLAssetType::AT_LINK_FOLDER) { LLViewerInventoryCategory *linked_cat = item->getLinkedCategory(); - if (linked_cat) + if (linked_cat && linked_cat->getPreferredType() != LLAssetType::AT_OUTFIT) + // BAP - was + // LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType())) + // Change back once ensemble typing is in place. { if(add(linked_cat,NULL)) { @@ -2492,6 +2495,10 @@ void LLInventoryModel::buildParentChildMap() // root of the agent's inv found. // The inv tree is built. mIsAgentInvUsable = true; + + llinfos << "Inventory initialized, notifying observers" << llendl; + addChangedMask(LLInventoryObserver::ALL, LLUUID::null); + notifyObservers(); } } } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index e3e4f6aca0..91a1906fab 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -730,6 +730,21 @@ protected: std::string mName; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFindCOFValidItems +// +// Collects items that can be legitimately linked to in the COF. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFindCOFValidItems : public LLInventoryCollectFunctor +{ +public: + LLFindCOFValidItems() {} + virtual ~LLFindCOFValidItems() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item); + +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFindWearables // diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index dbb3062323..6a55b571ae 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2158,10 +2158,6 @@ bool idle_startup() // lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" and fill it with buddies LLFriendCardsManager::instance().syncFriendsFolder(); - llinfos << "Setting Inventory changed mask and notifying observers" << llendl; - gInventory.addChangedMask(LLInventoryObserver::ALL, LLUUID::null); - gInventory.notifyObservers(); - // set up callbacks llinfos << "Registering Callbacks" << llendl; LLMessageSystem* msg = gMessageSystem; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 2ebf803e5e..9d278e6a6c 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2836,7 +2836,7 @@ class LLSelfRemoveAllAttachments : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLAgentWearables::userRemoveAllAttachments(NULL); + LLAgentWearables::userRemoveAllAttachments(); return true; } }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 1d9ca12af8..92dbb29d8e 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -80,6 +80,7 @@ #include "llsky.h" #include "llanimstatelabels.h" #include "lltrans.h" +#include "llappearancemgr.h" #include "llgesturemgr.h" //needed to trigger the voice gesticulations #include "llvoiceclient.h" @@ -5492,6 +5493,18 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) if (isSelf()) { // Then make sure the inventory is in sync with the avatar. + + // Update COF contents, don't trigger appearance update. + if (gAgent.getAvatarObject() == NULL) + { + llinfos << "removeItemLinks skipped, avatar is under destruction" << llendl; + } + else + { + LLAppearanceManager::removeItemLinks(item_id, false); + } + + // BAP - needs to change for label to track link. gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); gInventory.notifyObservers(); } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index dfc82ea8d5..20b8750fbf 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -82,6 +82,7 @@ #include "llgesturemgr.h" //needed to trigger the voice gesticulations #include "llvoiceclient.h" #include "llvoicevisualizer.h" // Ventrella +#include "llappearancemgr.h" #include "boost/lexical_cast.hpp" @@ -983,6 +984,11 @@ LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_obj updateAttachmentVisibility(gAgent.getCameraMode()); // Then make sure the inventory is in sync with the avatar. + LLViewerInventoryItem *item = gInventory.getItem(attachment->getItemID()); + if (item) + { + LLAppearanceManager::wearItem(item,false); // Add COF link for item. + } gInventory.addChangedMask(LLInventoryObserver::LABEL, attachment->getItemID()); gInventory.notifyObservers(); diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 7762a7f667..72cbd3bcd5 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -457,6 +457,14 @@ function="Inventory.DoToSelected" parameter="replaceoutfit" /> + + +