summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llagentwearables.cpp134
-rw-r--r--indra/newview/llappearancemgr.cpp100
-rw-r--r--indra/newview/llappearancemgr.h3
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);