diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llagentwearables.cpp | 134 | ||||
-rw-r--r-- | indra/newview/llappearancemgr.cpp | 100 | ||||
-rw-r--r-- | indra/newview/llappearancemgr.h | 3 |
3 files changed, 164 insertions, 73 deletions
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 11ac103b3a..7b55282ee5 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -119,9 +119,9 @@ protected: void importedFolderDone(void); void contentsDone(void); enum ELibraryOutfitFetchStep mCurrFetchStep; - typedef std::vector< std::pair< LLUUID, std::string > > cloth_folder_vec_t; - cloth_folder_vec_t mLibraryClothingFolders; - cloth_folder_vec_t mImportedClothingFolders; + typedef std::vector<LLUUID> clothing_folder_vec_t; + clothing_folder_vec_t mLibraryClothingFolders; + clothing_folder_vec_t mImportedClothingFolders; bool mOutfitsPopulated; LLUUID mClothingID; LLUUID mLibraryClothingID; @@ -2240,7 +2240,7 @@ void LLAgentWearables::updateServer() void LLAgentWearables::populateMyOutfitsFolder(void) { - llinfos << "starting outfit populate" << llendl; + llinfos << "starting outfit population" << llendl; LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(); @@ -2312,17 +2312,28 @@ void LLLibraryOutfitsFetch::folderDone(void) LLInventoryModel::item_array_t wearable_array; gInventory.collectDescendents(mMyOutfitsID, cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH); - // Early out if we already have items in My Outfits. if (cat_array.count() > 0 || wearable_array.count() > 0) { mOutfitsPopulated = true; return; } - + mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); mLibraryClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); - + + // If Library->Clothing->Initial Outfits exists, use that. + LLNameCategoryCollector matchFolderFunctor("Initial Outfits"); + gInventory.collectDescendentsIf(mLibraryClothingID, + cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH, + matchFolderFunctor); + if (cat_array.count() > 0) + { + const LLViewerInventoryCategory *cat = cat_array.get(0); + mLibraryClothingID = cat->getUUID(); + } + mCompleteFolders.clear(); // Get the complete information on the items in the inventory. @@ -2353,31 +2364,28 @@ void LLLibraryOutfitsFetch::outfitsDone(void) { const LLViewerInventoryCategory *cat = iter->get(); - // Get the names and id's of every outfit in the library, except for ruth and other "misc" outfits. - if (cat->getName() != "More Outfits" && cat->getName() != "Ruth") + // Get the names and id's of every outfit in the library, skip "Ruth" + // because it's a low quality legacy outfit + if (cat->getName() != "Ruth") { // Get the name of every outfit in the library folders.push_back(cat->getUUID()); - mLibraryClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); + mLibraryClothingFolders.push_back(cat->getUUID()); } } - - // Collect the contents of your Inventory Clothing folder cat_array.clear(); wearable_array.clear(); - gInventory.collectDescendents(mClothingID, cat_array, wearable_array, - LLInventoryModel::EXCLUDE_TRASH); // Check if you already have an "Imported Library Clothing" folder - for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); - iter != cat_array.end(); - ++iter) + LLNameCategoryCollector matchFolderFunctor(mImportedClothingName); + gInventory.collectDescendentsIf(mClothingID, + cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH, + matchFolderFunctor); + if (cat_array.size() > 0) { - const LLViewerInventoryCategory *cat = iter->get(); - if (cat->getName() == mImportedClothingName) - { - mImportedClothingID = cat->getUUID(); - } + const LLViewerInventoryCategory *cat = cat_array.get(0); + mImportedClothingID = cat->getUUID(); } mCompleteFolders.clear(); @@ -2415,31 +2423,59 @@ private: LLLibraryOutfitsFetch * mLibraryOutfitsFetcher; }; +// Copy the clothing folders from the library into the imported clothing folder void LLLibraryOutfitsFetch::libraryDone(void) { - // Copy the clothing folders from the library into the imported clothing folder if necessary. - if (mImportedClothingID == LLUUID::null) + if (mImportedClothingID != LLUUID::null) { - gInventory.removeObserver(this); - LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this); - mImportedClothingID = gInventory.createNewCategory(mClothingID, - LLFolderType::FT_NONE, - mImportedClothingName); + // Skip straight to fetching the contents of the imported folder + importedFolderFetch(); + return; + } + + // Remove observer; next autopopulation step will be triggered externally by LLLibraryOutfitsCopyDone. + gInventory.removeObserver(this); + + LLPointer<LLInventoryCallback> copy_waiter = new LLLibraryOutfitsCopyDone(this); + mImportedClothingID = gInventory.createNewCategory(mClothingID, + LLFolderType::FT_NONE, + mImportedClothingName); + // Copy each folder from library into clothing unless it already exists. + for (clothing_folder_vec_t::const_iterator iter = mLibraryClothingFolders.begin(); + iter != mLibraryClothingFolders.end(); + ++iter) + { + const LLUUID& src_folder_id = (*iter); // Library clothing folder ID + const LLViewerInventoryCategory *cat = gInventory.getCategory(src_folder_id); + if (!cat) + { + llwarns << "Library folder import for uuid:" << src_folder_id << " failed to find folder." << llendl; + continue; + } - for (cloth_folder_vec_t::const_iterator iter = mLibraryClothingFolders.begin(); - iter != mLibraryClothingFolders.end(); - ++iter) + if (!LLAppearanceManager::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id)) { - LLUUID folder_id = gInventory.createNewCategory(mImportedClothingID, - LLFolderType::FT_NONE, - iter->second); - LLAppearanceManager::getInstance()->shallowCopyCategoryContents(iter->first, folder_id, copy_waiter); + llinfos << "Skipping non-outfit folder name:" << cat->getName() << llendl; + continue; } - } - else - { - // Skip straight to fetching the contents of the imported folder - importedFolderFetch(); + + // Don't copy the category if it already exists. + LLNameCategoryCollector matchFolderFunctor(cat->getName()); + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + gInventory.collectDescendentsIf(mImportedClothingID, + cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH, + matchFolderFunctor); + if (cat_array.size() > 0) + { + continue; + } + + LLUUID dst_folder_id = gInventory.createNewCategory(mImportedClothingID, + LLFolderType::FT_NONE, + cat->getName()); + LLAppearanceManager::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter); } } @@ -2476,7 +2512,7 @@ void LLLibraryOutfitsFetch::importedFolderDone(void) // Get the name of every imported outfit folders.push_back(cat->getUUID()); - mImportedClothingFolders.push_back(std::make_pair(cat->getUUID(), cat->getName())); + mImportedClothingFolders.push_back(cat->getUUID()); } mCompleteFolders.clear(); @@ -2492,17 +2528,25 @@ void LLLibraryOutfitsFetch::contentsDone(void) LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; - for (cloth_folder_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); + for (clothing_folder_vec_t::const_iterator folder_iter = mImportedClothingFolders.begin(); folder_iter != mImportedClothingFolders.end(); ++folder_iter) { + const LLUUID &folder_id = (*folder_iter); + const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id); + if (!cat) + { + llwarns << "Library folder import for uuid:" << folder_id << " failed to find folder." << llendl; + continue; + } + // First, make a folder in the My Outfits directory. - LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, folder_iter->second); + LLUUID new_outfit_folder_id = gInventory.createNewCategory(mMyOutfitsID, LLFolderType::FT_OUTFIT, cat->getName()); cat_array.clear(); wearable_array.clear(); // Collect the contents of each imported clothing folder, so we can create new outfit links for it - gInventory.collectDescendents(folder_iter->first, cat_array, wearable_array, + gInventory.collectDescendents(folder_id, cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH); for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5c21be8c32..f08d8decfe 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -807,47 +807,91 @@ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID void LLAppearanceManager::shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, LLPointer<LLInventoryCallback> 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) + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(src_id, cats, items); + for (LLInventoryModel::item_array_t::const_iterator iter = items->begin(); + iter != items->end(); + ++iter) + { + const LLViewerInventoryItem* item = (*iter); + switch (item->getActualType()) { - LLViewerInventoryCategory *catp = item->getLinkedCategory(); - // Skip copying outfit links. - if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT) + case LLAssetType::AT_LINK: { link_inventory_item(gAgent.getID(), item->getLinkedUUID(), dst_id, item->getName(), - LLAssetType::AT_LINK_FOLDER, cb); + LLAssetType::AT_LINK, cb); + break; + } + case LLAssetType::AT_LINK_FOLDER: + { + LLViewerInventoryCategory *catp = item->getLinkedCategory(); + // Skip copying outfit links. + if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT) + { + link_inventory_item(gAgent.getID(), + item->getLinkedUUID(), + dst_id, + item->getName(), + LLAssetType::AT_LINK_FOLDER, cb); + } + break; } + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_OBJECT: + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_GESTURE: + { + copy_inventory_item(gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + dst_id, + item->getName(), + cb); + break; + } + default: + // Ignore non-outfit asset types + break; } - else + } +} + +BOOL LLAppearanceManager::getCanMakeFolderIntoOutfit(const LLUUID& folder_id) +{ + // These are the wearable items that are required for considering this + // folder as containing a complete outfit. + U32 required_wearables = 0; + required_wearables |= 1LL << WT_SHAPE; + required_wearables |= 1LL << WT_SKIN; + required_wearables |= 1LL << WT_HAIR; + required_wearables |= 1LL << WT_EYES; + + // These are the wearables that the folder actually contains. + U32 folder_wearables = 0; + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(folder_id, cats, items); + for (LLInventoryModel::item_array_t::const_iterator iter = items->begin(); + iter != items->end(); + ++iter) + { + const LLViewerInventoryItem* item = (*iter); + if (item->isWearableType()) { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - dst_id, - item->getName(), - cb); + const EWearableType wearable_type = item->getWearableType(); + folder_wearables |= 1LL << wearable_type; } } + + // If the folder contains the required wearables, return TRUE. + return ((required_wearables & folder_wearables) == required_wearables); } + void LLAppearanceManager::purgeBaseOutfitLink(const LLUUID& category) { LLInventoryModel::cat_array_t cats; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index e7e2f33520..9d6cd34ad7 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -60,6 +60,9 @@ public: void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id, LLPointer<LLInventoryCallback> cb); + // Return whether this folder contains minimal contents suitable for making a full outfit. + BOOL getCanMakeFolderIntoOutfit(const LLUUID& folder_id); + // Copy all items in a category. void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, LLPointer<LLInventoryCallback> cb); |