diff options
| -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);  | 
