diff options
| -rwxr-xr-x[-rw-r--r--] | indra/newview/llagentwearables.cpp | 18 | ||||
| -rwxr-xr-x | indra/newview/llagentwearables.h | 6 | ||||
| -rwxr-xr-x | indra/newview/llagentwearablesfetch.cpp | 394 | ||||
| -rwxr-xr-x | indra/newview/llagentwearablesfetch.h | 41 | ||||
| -rwxr-xr-x | indra/newview/llappearancemgr.cpp | 226 | ||||
| -rwxr-xr-x | indra/newview/llappearancemgr.h | 31 | ||||
| -rwxr-xr-x | indra/newview/llinventorybridge.cpp | 69 | ||||
| -rwxr-xr-x | indra/newview/llviewerfoldertype.cpp | 6 | 
8 files changed, 144 insertions, 647 deletions
| diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 80c8364223..8e60bf1c6d 100644..100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1861,24 +1861,6 @@ void LLAgentWearables::updateServer()  	gAgent.sendAgentSetAppearance();  } -void LLAgentWearables::populateMyOutfitsFolder(void) -{	 -	llinfos << "starting outfit population" << llendl; - -	const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); -	LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(my_outfits_id); -	outfits->mMyOutfitsID = my_outfits_id; -	 -	// Get the complete information on the items in the inventory and  -	// setup an observer that will wait for that to happen. -	gInventory.addObserver(outfits); -	outfits->startFetch(); -	if (outfits->isFinished()) -	{ -		outfits->done(); -	} -} -  boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb)  {  	return mLoadingStartedSignal.connect(cb); diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 0adf545aab..b0ac988341 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -171,12 +171,6 @@ protected:  	//--------------------------------------------------------------------  	// Outfits  	//-------------------------------------------------------------------- -public: -	 -	// Should only be called if we *know* we've never done so before, since users may -	// not want the Library outfits to stay in their quick outfit selector and can delete them. -	void			populateMyOutfitsFolder(); -  private:  	void			makeNewOutfitDone(S32 type, U32 index);  diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index 2d2d730396..014c610a5c 100755 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -35,46 +35,6 @@  #include "llvoavatarself.h" -void order_my_outfits_cb() -{ -	if (!LLApp::isRunning()) -	{ -		llwarns << "called during shutdown, skipping" << llendl; -		return; -	} -		 -	const LLUUID& my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); -	if (my_outfits_id.isNull()) return; - -	LLInventoryModel::cat_array_t* cats; -	LLInventoryModel::item_array_t* items; -	gInventory.getDirectDescendentsOf(my_outfits_id, cats, items); -	if (!cats) return; - -	//My Outfits should at least contain saved initial outfit and one another outfit -	if (cats->size() < 2) -	{ -		llwarning("My Outfits category was not populated properly", 0); -		return; -	} - -	llinfos << "Starting updating My Outfits with wearables ordering information" << llendl; - -	for (LLInventoryModel::cat_array_t::iterator outfit_iter = cats->begin(); -		 outfit_iter != cats->end(); ++outfit_iter) -	{ -		const LLUUID& cat_id = (*outfit_iter)->getUUID(); -		if (cat_id.isNull()) continue; - -		// saved initial outfit already contains wearables ordering information -		if (cat_id == LLAppearanceMgr::getInstance()->getBaseOutfitUUID()) continue; - -		LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(cat_id); -	} - -	llinfos << "Finished updating My Outfits with wearables ordering information" << llendl; -} -  LLInitialWearablesFetch::LLInitialWearablesFetch(const LLUUID& cof_id) :  	LLInventoryFetchDescendentsObserver(cof_id)  { @@ -244,357 +204,3 @@ void LLInitialWearablesFetch::processWearablesMessage()  	}  } -LLLibraryOutfitsFetch::LLLibraryOutfitsFetch(const LLUUID& my_outfits_id) :  -	LLInventoryFetchDescendentsObserver(my_outfits_id), -	mCurrFetchStep(LOFS_FOLDER),  -	mOutfitsPopulated(false)  -{ -	llinfos << "created" << llendl; - -	mMyOutfitsID = LLUUID::null; -	mClothingID = LLUUID::null; -	mLibraryClothingID = LLUUID::null; -	mImportedClothingID = LLUUID::null; -	mImportedClothingName = "Imported Library Clothing"; -} - -LLLibraryOutfitsFetch::~LLLibraryOutfitsFetch() -{ -	llinfos << "destroyed" << llendl; -} - -void LLLibraryOutfitsFetch::done() -{ -	llinfos << "start" << llendl; - -	// Delay this until idle() routine, since it's a heavy operation and -	// we also can't have it run within notifyObservers. -	doOnIdleOneTime(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this)); -	gInventory.removeObserver(this); // Prevent doOnIdleOneTime from being added twice. -} - -void LLLibraryOutfitsFetch::doneIdle() -{ -	llinfos << "start" << llendl; - -	gInventory.addObserver(this); // Add this back in since it was taken out during ::done() -	 -	switch (mCurrFetchStep) -	{ -		case LOFS_FOLDER: -			folderDone(); -			mCurrFetchStep = LOFS_OUTFITS; -			break; -		case LOFS_OUTFITS: -			outfitsDone(); -			mCurrFetchStep = LOFS_LIBRARY; -			break; -		case LOFS_LIBRARY: -			libraryDone(); -			mCurrFetchStep = LOFS_IMPORTED; -			break; -		case LOFS_IMPORTED: -			importedFolderDone(); -			mCurrFetchStep = LOFS_CONTENTS; -			break; -		case LOFS_CONTENTS: -			contentsDone(); -			break; -		default: -			llwarns << "Got invalid state for outfit fetch: " << mCurrFetchStep << llendl; -			mOutfitsPopulated = TRUE; -			break; -	} - -	// We're completely done.  Cleanup. -	if (mOutfitsPopulated) -	{ -		gInventory.removeObserver(this); -		delete this; -		return; -	} -} - -void LLLibraryOutfitsFetch::folderDone() -{ -	llinfos << "start" << llendl; - -	LLInventoryModel::cat_array_t cat_array; -	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 -	// except the case when My Outfits contains just initial outfit -	if (cat_array.count() > 1) -	{ -		mOutfitsPopulated = true; -		return; -	} - -	mClothingID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING); -	mLibraryClothingID = gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_CLOTHING, false); - -	// If Library->Clothing->Initial Outfits exists, use that. -	LLNameCategoryCollector matchFolderFunctor("Initial Outfits"); -	cat_array.clear(); -	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(); -	} - -	mComplete.clear(); -	 -	// Get the complete information on the items in the inventory. -	uuid_vec_t folders; -	folders.push_back(mClothingID); -	folders.push_back(mLibraryClothingID); -	setFetchIDs(folders); -	startFetch(); -	if (isFinished()) -	{ -		done(); -	} -} - -void LLLibraryOutfitsFetch::outfitsDone() -{ -	llinfos << "start" << llendl; - -	LLInventoryModel::cat_array_t cat_array; -	LLInventoryModel::item_array_t wearable_array; -	uuid_vec_t folders; -	 -	// Collect the contents of the Library's Clothing folder -	gInventory.collectDescendents(mLibraryClothingID, cat_array, wearable_array,  -								  LLInventoryModel::EXCLUDE_TRASH); -	 -	llassert(cat_array.count() > 0); -	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); -		 iter != cat_array.end(); -		 ++iter) -	{ -		const LLViewerInventoryCategory *cat = iter->get(); -		 -		// 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(cat->getUUID()); -		} -	} -	cat_array.clear(); -	wearable_array.clear(); - -	// Check if you already have an "Imported Library Clothing" folder -	LLNameCategoryCollector matchFolderFunctor(mImportedClothingName); -	gInventory.collectDescendentsIf(mClothingID,  -									cat_array, wearable_array,  -									LLInventoryModel::EXCLUDE_TRASH, -									matchFolderFunctor); -	if (cat_array.size() > 0) -	{ -		const LLViewerInventoryCategory *cat = cat_array.get(0); -		mImportedClothingID = cat->getUUID(); -	} -	 -	mComplete.clear(); -	setFetchIDs(folders); -	startFetch(); -	if (isFinished()) -	{ -		done(); -	} -} - -class LLLibraryOutfitsCopyDone: public LLInventoryCallback -{ -public: -	LLLibraryOutfitsCopyDone(LLLibraryOutfitsFetch * fetcher): -	mFireCount(0), mLibraryOutfitsFetcher(fetcher) -	{ -	} -	 -	virtual ~LLLibraryOutfitsCopyDone() -	{ -		if (!LLApp::isExiting() && mLibraryOutfitsFetcher) -		{ -			gInventory.addObserver(mLibraryOutfitsFetcher); -			mLibraryOutfitsFetcher->done(); -		} -	} -	 -	/* virtual */ void fire(const LLUUID& inv_item) -	{ -		mFireCount++; -	} -private: -	U32 mFireCount; -	LLLibraryOutfitsFetch * mLibraryOutfitsFetcher; -}; - -// Copy the clothing folders from the library into the imported clothing folder -void LLLibraryOutfitsFetch::libraryDone() -{ -	llinfos << "start" << llendl; - -	if (mImportedClothingID != LLUUID::null) -	{ -		// 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 (uuid_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; -		} -		 -		if (!LLAppearanceMgr::getInstance()->getCanMakeFolderIntoOutfit(src_folder_id)) -		{ -			llinfos << "Skipping non-outfit folder name:" << cat->getName() << llendl; -			continue; -		} -		 -		// 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()); -		LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_folder_id, dst_folder_id, copy_waiter); -	} -} - -void LLLibraryOutfitsFetch::importedFolderFetch() -{ -	llinfos << "start" << llendl; - -	// Fetch the contents of the Imported Clothing Folder -	uuid_vec_t folders; -	folders.push_back(mImportedClothingID); -	 -	mComplete.clear(); -	setFetchIDs(folders); -	startFetch(); -	if (isFinished()) -	{ -		done(); -	} -} - -void LLLibraryOutfitsFetch::importedFolderDone() -{ -	llinfos << "start" << llendl; - -	LLInventoryModel::cat_array_t cat_array; -	LLInventoryModel::item_array_t wearable_array; -	uuid_vec_t folders; -	 -	// Collect the contents of the Imported Clothing folder -	gInventory.collectDescendents(mImportedClothingID, cat_array, wearable_array,  -								  LLInventoryModel::EXCLUDE_TRASH); -	 -	for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array.begin(); -		 iter != cat_array.end(); -		 ++iter) -	{ -		const LLViewerInventoryCategory *cat = iter->get(); -		 -		// Get the name of every imported outfit -		folders.push_back(cat->getUUID()); -		mImportedClothingFolders.push_back(cat->getUUID()); -	} -	 -	mComplete.clear(); -	setFetchIDs(folders); -	startFetch(); -	if (isFinished()) -	{ -		done(); -	} -} - -void LLLibraryOutfitsFetch::contentsDone() -{		 -	llinfos << "start" << llendl; - -	LLInventoryModel::cat_array_t cat_array; -	LLInventoryModel::item_array_t wearable_array; -	 -	LLPointer<LLInventoryCallback> order_myoutfits_on_destroy = new LLBoostFuncInventoryCallback(no_op_inventory_func, order_my_outfits_cb); - -	for (uuid_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; -		} - -		//initial outfit should be already in My Outfits -		if (cat->getName() == LLStartUp::getInitialOutfitName()) continue; -		 -		// First, make a folder in the My Outfits directory. -		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_id, cat_array, wearable_array,  -									  LLInventoryModel::EXCLUDE_TRASH); -		 -		for (LLInventoryModel::item_array_t::const_iterator wearable_iter = wearable_array.begin(); -			 wearable_iter != wearable_array.end(); -			 ++wearable_iter) -		{ -			const LLViewerInventoryItem *item = wearable_iter->get(); -			link_inventory_item(gAgent.getID(), -								item->getLinkedUUID(), -								new_outfit_folder_id, -								item->getName(), -								item->getDescription(), -								LLAssetType::AT_LINK, -								order_myoutfits_on_destroy); -		} -	} - -	mOutfitsPopulated = true; -} - diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h index bedc445c0e..81b03110ae 100755 --- a/indra/newview/llagentwearablesfetch.h +++ b/indra/newview/llagentwearablesfetch.h @@ -70,45 +70,4 @@ private:  	initial_wearable_data_vec_t mAgentInitialWearables; // Wearables from the old agent wearables msg  }; -//-------------------------------------------------------------------- -// InitialWearablesFetch -//  -// This grabs outfits from the Library and copies those over to the user's -// outfits folder, typically during first-ever login. -//-------------------------------------------------------------------- -class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver -{ -public: -	enum ELibraryOutfitFetchStep -	{ -		LOFS_FOLDER = 0, -		LOFS_OUTFITS, -		LOFS_LIBRARY, -		LOFS_IMPORTED, -		LOFS_CONTENTS -	}; - -	LLLibraryOutfitsFetch(const LLUUID& my_outfits_id); -	~LLLibraryOutfitsFetch(); - -	virtual void done(); -	void doneIdle(); -	LLUUID mMyOutfitsID; -	void importedFolderFetch(); -protected: -	void folderDone(); -	void outfitsDone(); -	void libraryDone(); -	void importedFolderDone(); -	void contentsDone(); -	enum ELibraryOutfitFetchStep mCurrFetchStep; -	uuid_vec_t mLibraryClothingFolders; -	uuid_vec_t mImportedClothingFolders; -	bool mOutfitsPopulated; -	LLUUID mClothingID; -	LLUUID mLibraryClothingID; -	LLUUID mImportedClothingID; -	std::string mImportedClothingName; -}; -  #endif // LL_AGENTWEARABLESINITIALFETCH_H diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 118f557c97..12c8c82af4 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -435,13 +435,11 @@ private:  S32 LLCallAfterInventoryCopyMgr::sInstanceCount = 0; -LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering, -														 bool enforce_item_restrictions, +LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions,  														 bool enforce_ordering,  														 nullary_func_t post_update_func   	):  	mFireCount(0), -	mUpdateBaseOrder(update_base_outfit_ordering),  	mEnforceItemRestrictions(enforce_item_restrictions),  	mEnforceOrdering(enforce_ordering),  	mPostUpdateFunc(post_update_func) @@ -468,8 +466,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()  		selfStopPhase("update_appearance_on_destroy"); -		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, -															mEnforceItemRestrictions, +		LLAppearanceMgr::instance().updateAppearanceFromCOF(mEnforceItemRestrictions,  															mEnforceOrdering,  															mPostUpdateFunc);  	} @@ -503,7 +500,7 @@ LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOn  	if (!LLApp::isExiting())  	{  		LLAppearanceMgr::instance().updateAppearanceFromCOF( -			false,true,true, +			true,true,  			boost::bind(edit_wearable_and_customize_avatar, mItemID));  	}  } @@ -1450,7 +1447,7 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds  	gInventory.notifyObservers();  } -void LLAppearanceMgr::copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id, +void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,  										bool include_folder_links, LLPointer<LLInventoryCallback> cb)  {  	LLInventoryModel::cat_array_t* cats; @@ -1819,35 +1816,36 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)  	all_items += obj_items;  	all_items += gest_items; -	// Will link all the above items. -	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy; -#if 0 -	linkAll(cof,all_items,link_waiter); +	// Find any wearables that need description set to enforce ordering. +	desc_map_t desc_map; +	getWearableOrderingDescUpdates(wear_items, desc_map); -	// Add link to outfit if category is an outfit.  -	if (!append) -	{ -		createBaseOutfitLink(category, link_waiter); -	} - -	// Remove current COF contents.  Have to do this after creating -	// the link_waiter so links can be followed for any items that get -	// carried over (e.g. keeping old shape if the new outfit does not -	// contain one) - -	// even in the non-append case, createBaseOutfitLink() already -	// deletes the existing link, don't need to do it again here. -	bool keep_outfit_links = true; -	remove_folder_contents(cof, keep_outfit_links, link_waiter); -#else +	// Will link all the above items. +	// link_waiter enforce flags are false because we've already fixed everything up in updateCOF(). +	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(false,false);  	LLSD contents = LLSD::emptyArray(); +  	for (LLInventoryModel::item_array_t::const_iterator it = all_items.begin();  		 it != all_items.end(); ++it)  	{  		LLSD item_contents;  		LLInventoryItem *item = *it; + +		std::string desc; +		desc_map_t::const_iterator desc_iter = desc_map.find(item->getUUID()); +		if (desc_iter != desc_map.end()) +		{ +			desc = desc_iter->second; +			LL_DEBUGS("Avatar") << item->getName() << " overriding desc to: " << desc +								<< " (was: " << item->getActualDescription() << ")" << llendl; +		} +		else +		{ +			desc = item->getActualDescription(); +		} +  		item_contents["name"] = item->getName(); -		item_contents["desc"] = item->getActualDescription(); +		item_contents["desc"] = desc;  		item_contents["linked_id"] = item->getLinkedUUID();  		item_contents["type"] = LLAssetType::AT_LINK;   		contents.append(item_contents); @@ -1868,7 +1866,6 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)  		dump_sequential_xml(gAgentAvatarp->getFullname() + "_slam_request", contents);  	}  	slam_inventory_folder(getCOF(), contents, link_waiter); -#endif  	LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;  } @@ -2035,8 +2032,7 @@ void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback>  	}  } -void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering, -											  bool enforce_item_restrictions, +void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,  											  bool enforce_ordering,  											  nullary_func_t post_update_func)  { @@ -2056,7 +2052,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,  		// enforce_item_restrictions to false so we don't get  		// caught in a perpetual loop.  		LLPointer<LLInventoryCallback> cb( -			new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false, enforce_ordering, post_update_func)); +			new LLUpdateAppearanceOnDestroy(false, enforce_ordering, post_update_func));  		enforceCOFItemRestrictions(cb);  		return;  	} @@ -2070,11 +2066,13 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,  		// to wait for the update callbacks, then (finally!) call  		// updateAppearanceFromCOF() with no additional COF munging needed.  		LLPointer<LLInventoryCallback> cb( -			new LLUpdateAppearanceOnDestroy(false, false, false, post_update_func)); -		updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering, cb); +			new LLUpdateAppearanceOnDestroy(false, false, post_update_func)); +		updateClothingOrderingInfo(LLUUID::null, cb);  		return;  	} +	llassert(validateClothingOrderingInfo()); +  	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);  	selfStartPhase("update_appearance_from_cof"); @@ -2817,23 +2815,6 @@ void LLAppearanceMgr::copyLibraryGestures()  	}  } -void LLAppearanceMgr::autopopulateOutfits() -{ -	// If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account) -	// then auto-populate outfits from the library into the My Outfits folder. - -	LL_INFOS("Avatar") << self_av_string() << "avatar fully visible" << LL_ENDL; - -	static bool check_populate_my_outfits = true; -	if (check_populate_my_outfits &&  -		(LLInventoryModel::getIsFirstTimeInViewer2()  -		 || gSavedSettings.getBOOL("MyOutfitsAutofill"))) -	{ -		gAgentWearables.populateMyOutfitsFolder(); -	} -	check_populate_my_outfits = false; -} -  // Handler for anything that's deferred until avatar de-clouds.  void LLAppearanceMgr::onFirstFullyVisible()  { @@ -2841,10 +2822,6 @@ void LLAppearanceMgr::onFirstFullyVisible()  	gAgentAvatarp->reportAvatarRezTime();  	gAgentAvatarp->debugAvatarVisible(); -	// The auto-populate is failing at the point of generating outfits -	// folders, so don't do the library copy until that is resolved. -	// autopopulateOutfits(); -  	// If this is the first time we've ever logged in,  	// then copy default gestures from the library.  	if (gAgent.isFirstLogin()) { @@ -2862,6 +2839,22 @@ void appearance_mgr_update_dirty_state()  	}  } +void update_base_outfit_after_ordering() +{ +	LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance(); +	 +	LLPointer<LLInventoryCallback> dirty_state_updater = +		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state); + +	//COF contains only links so we copy to the Base Outfit only links +	const LLUUID base_outfit_id = app_mgr.getBaseOutfitUUID(); +	bool copy_folder_links = false; +	app_mgr.slamCategoryLinks(app_mgr.getCOF(), base_outfit_id, copy_folder_links, dirty_state_updater); + +} + +// Save COF changes - update the contents of the current base outfit +// to match the current COF. Fails if no current base outfit is set.  bool LLAppearanceMgr::updateBaseOutfit()  {  	if (isOutfitLocked()) @@ -2871,25 +2864,19 @@ bool LLAppearanceMgr::updateBaseOutfit()  		return false;  	} -  	setOutfitLocked(true);  	gAgentWearables.notifyLoadingStarted();  	const LLUUID base_outfit_id = getBaseOutfitUUID(); -	LL_DEBUGS("Avatar") << "updating base outfit to " << base_outfit_id << llendl;  	if (base_outfit_id.isNull()) return false; +	LL_DEBUGS("Avatar") << "saving cof to base outfit " << base_outfit_id << llendl; -	updateClothingOrderingInfo(); - -	// in a Base Outfit we do not remove items, only links -	remove_folder_contents(base_outfit_id, false, NULL); - -	LLPointer<LLInventoryCallback> dirty_state_updater = -		new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state); - -	//COF contains only links so we copy to the Base Outfit only links -	shallowCopyCategoryContents(getCOF(), base_outfit_id, dirty_state_updater); +	LLPointer<LLInventoryCallback> cb = +		new LLBoostFuncInventoryCallback(no_op_inventory_func, update_base_outfit_after_ordering); +	// Really shouldn't be needed unless there's a race condition - +	// updateAppearanceFromCOF() already calls updateClothingOrderingInfo. +	updateClothingOrderingInfo(LLUUID::null, cb);  	return true;  } @@ -2937,12 +2924,6 @@ struct WearablesOrderComparator  	bool operator()(const LLInventoryItem* item1, const LLInventoryItem* item2)  	{ -		if (!item1 || !item2) -		{ -			llwarning("either item1 or item2 is NULL", 0); -			return true; -		} -		  		const std::string& desc1 = item1->getActualDescription();  		const std::string& desc2 = item2->getActualDescription(); @@ -2965,55 +2946,94 @@ struct WearablesOrderComparator  	U32 mControlSize;  }; -void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, -												 bool update_base_outfit_ordering, -												 LLPointer<LLInventoryCallback> cb) +void LLAppearanceMgr::getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items, +													 desc_map_t& desc_map)  { -	if (cat_id.isNull()) -	{ -		cat_id = getCOF(); -		if (update_base_outfit_ordering) -		{ -			const LLUUID base_outfit_id = getBaseOutfitUUID(); -			if (base_outfit_id.notNull()) -			{ -				updateClothingOrderingInfo(base_outfit_id,false,cb); -			} -		} -	} - -	// COF is processed if cat_id is not specified -	LLInventoryModel::item_array_t wear_items; -	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING); -  	wearables_by_type_t items_by_type(LLWearableType::WT_COUNT);  	divvyWearablesByType(wear_items, items_by_type);  	for (U32 type = LLWearableType::WT_SHIRT; type < LLWearableType::WT_COUNT; type++)  	{ -		  		U32 size = items_by_type[type].size();  		if (!size) continue; - +		  		//sinking down invalid items which need reordering  		std::sort(items_by_type[type].begin(), items_by_type[type].end(), WearablesOrderComparator((LLWearableType::EType) type)); - +		  		//requesting updates only for those links which don't have "valid" descriptions  		for (U32 i = 0; i < size; i++)  		{  			LLViewerInventoryItem* item = items_by_type[type][i];  			if (!item) continue; - +			  			std::string new_order_str = build_order_string((LLWearableType::EType)type, i);  			if (new_order_str == item->getActualDescription()) continue; - -			LLSD updates; -			updates["desc"] = new_order_str; -			update_inventory_item(item->getUUID(),updates,cb); +			 +			desc_map[item->getUUID()] = new_order_str;  		}  	}  } +bool LLAppearanceMgr::validateClothingOrderingInfo(LLUUID cat_id) +{ +	// COF is processed if cat_id is not specified +	if (cat_id.isNull()) +	{ +		cat_id = getCOF(); +	} + +	LLInventoryModel::item_array_t wear_items; +	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING); + +	// Identify items for which desc needs to change. +	desc_map_t desc_map; +	getWearableOrderingDescUpdates(wear_items, desc_map); + +	for (desc_map_t::const_iterator it = desc_map.begin(); +		 it != desc_map.end(); ++it) +	{ +		const LLUUID& item_id = it->first; +		const std::string& new_order_str = it->second; +		LLViewerInventoryItem *item = gInventory.getItem(item_id); +		llwarns << "Order validation fails: " << item->getName() +				<< " needs to update desc to: " << new_order_str +				<< " (from: " << item->getActualDescription() << ")" << llendl; +	} +	 +	return desc_map.size() == 0; +} + +void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, +												 LLPointer<LLInventoryCallback> cb) +{ +	// COF is processed if cat_id is not specified +	if (cat_id.isNull()) +	{ +		cat_id = getCOF(); +	} + +	LLInventoryModel::item_array_t wear_items; +	getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING); + +	// Identify items for which desc needs to change. +	desc_map_t desc_map; +	getWearableOrderingDescUpdates(wear_items, desc_map); + +	for (desc_map_t::const_iterator it = desc_map.begin(); +		 it != desc_map.end(); ++it) +	{ +		LLSD updates; +		const LLUUID& item_id = it->first; +		const std::string& new_order_str = it->second; +		LLViewerInventoryItem *item = gInventory.getItem(item_id); +		LL_DEBUGS("Avatar") << item->getName() << " updating desc to: " << new_order_str +			<< " (was: " << item->getActualDescription() << ")" << llendl; +		updates["desc"] = new_order_str; +		update_inventory_item(item_id,updates,cb); +	} +		 +} +  class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder  {  	LOG_CLASS(RequestAgentUpdateAppearanceResponder); @@ -3428,7 +3448,7 @@ void LLAppearanceMgr::onOutfitFolderCreated(const LLUUID& folder_id, bool show_p  	LLPointer<LLInventoryCallback> cb =  		new LLBoostFuncInventoryCallback(no_op_inventory_func,  										 boost::bind(&LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered,this,folder_id,show_panel)); -	updateClothingOrderingInfo(LLUUID::null, false, cb); +	updateClothingOrderingInfo(LLUUID::null, cb);  }  void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel) @@ -3437,7 +3457,7 @@ void LLAppearanceMgr::onOutfitFolderCreatedAndClothingOrdered(const LLUUID& fold  		new LLBoostFuncInventoryCallback(no_op_inventory_func,  										 boost::bind(show_created_outfit,folder_id,show_panel));  	bool copy_folder_links = false; -	copyCategoryLinks(getCOF(), folder_id, copy_folder_links, cb); +	slamCategoryLinks(getCOF(), folder_id, copy_folder_links, cb);  }  void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel) diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 4d7c536b3d..b2917cced4 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -49,8 +49,7 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>  public:  	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t; -	void updateAppearanceFromCOF(bool update_base_outfit_ordering = false, -								 bool enforce_item_restrictions = true, +	void updateAppearanceFromCOF(bool enforce_item_restrictions = true,  								 bool enforce_ordering = true,  								 nullary_func_t post_update_func = no_op);  	bool needToSaveCOF(); @@ -74,10 +73,11 @@ public:  	S32 getActiveCopyOperations() const; -	// Copy all links via the slam command (single inventory operation where supported) -	void copyCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id, +	// Replace category contents with copied links via the slam_inventory_folder +	// command (single inventory operation where supported) +	void slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id,  						   bool include_folder_links, LLPointer<LLInventoryCallback> cb); -	 +   	// Copy all items and the src category itself.  	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,  							 LLPointer<LLInventoryCallback> cb); @@ -173,9 +173,6 @@ public:  	// Called when self avatar is first fully visible.  	void onFirstFullyVisible(); -	// Create initial outfits from library. -	void autopopulateOutfits(); -  	// Copy initial gestures from library.  	void copyLibraryGestures(); @@ -192,7 +189,8 @@ public:  	void onOutfitFolderCreated(const LLUUID& folder_id, bool show_panel);  	void onOutfitFolderCreatedAndClothingOrdered(const LLUUID& folder_id, bool show_panel); -	void makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel = true); + +	void makeNewOutfitLinks(const std::string& new_folder_name,bool show_panel = true);  	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body); @@ -201,10 +199,15 @@ public:  	//Divvy items into arrays by wearable type  	static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type); +	typedef std::map<LLUUID,std::string> desc_map_t; + +	void getWearableOrderingDescUpdates(LLInventoryModel::item_array_t& wear_items, desc_map_t& desc_map); +  	//Check ordering information on wearables stored in links' descriptions and update if it is invalid  	// COF is processed if cat_id is not specified +	bool validateClothingOrderingInfo(LLUUID cat_id = LLUUID::null); +	  	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null, -									bool update_base_outfit_ordering = false,  									LLPointer<LLInventoryCallback> cb = NULL);  	bool isOutfitLocked() { return mOutfitLocked; } @@ -277,8 +280,7 @@ public:  class LLUpdateAppearanceOnDestroy: public LLInventoryCallback  {  public: -	LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false, -								bool enforce_item_restrictions = true, +	LLUpdateAppearanceOnDestroy(bool enforce_item_restrictions = true,  								bool enforce_ordering = true,  								nullary_func_t post_update_func = no_op);  	virtual ~LLUpdateAppearanceOnDestroy(); @@ -286,7 +288,6 @@ public:  private:  	U32 mFireCount; -	bool mUpdateBaseOrder;  	bool mEnforceItemRestrictions;  	bool mEnforceOrdering;  	nullary_func_t mPostUpdateFunc; @@ -305,10 +306,6 @@ private:  	LLUUID mItemID;  }; -class  - -#define SUPPORT_ENSEMBLES 0 -  LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);  // Invoke a given callable after category contents are fully fetched. diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 89c56ab82c..cb3f40a5bb 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2416,49 +2416,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  					}  				}  			} -			// if target is an outfit or current outfit folder we use link -			if (move_is_into_current_outfit || move_is_into_outfit) +			// if target is current outfit folder we use link +			if (move_is_into_current_outfit && +				inv_cat->getPreferredType() == LLFolderType::FT_NONE)  			{ -				if (inv_cat->getPreferredType() == LLFolderType::FT_NONE) -				{ -					if (move_is_into_current_outfit) -					{ -						// traverse category and add all contents to currently worn. -						BOOL append = true; -						LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append); -					} -					else -					{ -						// Recursively create links in target outfit. -						LLInventoryModel::cat_array_t cats; -						LLInventoryModel::item_array_t items; -						model->collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); -						LLAppearanceMgr::instance().linkAll(mUUID,items,NULL); -					} -				} -				else -				{ -#if SUPPORT_ENSEMBLES -					// BAP - should skip if dup. -					if (move_is_into_current_outfit) -					{ -						LLAppearanceMgr::instance().addEnsembleLink(inv_cat); -					} -					else -					{ -						LLPointer<LLInventoryCallback> cb = NULL; -						const std::string empty_description = ""; -						link_inventory_item( -							gAgent.getID(), -							cat_id, -							mUUID, -							inv_cat->getName(), -							empty_description, -							LLAssetType::AT_LINK_FOLDER, -							cb); -					} -#endif -				} +				// traverse category and add all contents to currently worn. +				BOOL append = true; +				LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append);  			}  			else if (move_is_into_outbox && !move_is_from_outbox)  			{ @@ -2850,17 +2814,6 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)  		modifyOutfit(FALSE);  		return;  	} -#if SUPPORT_ENSEMBLES -	else if ("wearasensemble" == action) -	{ -		LLInventoryModel* model = getInventoryModel(); -		if(!model) return; -		LLViewerInventoryCategory* cat = getCategory(); -		if(!cat) return; -		LLAppearanceMgr::instance().addEnsembleLink(cat,true); -		return; -	} -#endif  	else if ("addtooutfit" == action)  	{  		modifyOutfit(TRUE); @@ -3382,16 +3335,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items  				items.push_back(std::string("New Clothes"));  				items.push_back(std::string("New Body Parts"));  			} -#if SUPPORT_ENSEMBLES -			// Changing folder types is an unfinished unsupported feature -			// and can lead to unexpected behavior if enabled. -			items.push_back(std::string("Change Type")); -			const LLViewerInventoryCategory *cat = getCategory(); -			if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) -			{ -				disabled_items.push_back(std::string("Change Type")); -			} -#endif  			getClipboardEntries(false, items, disabled_items, flags);  		}  		else diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index a179b61cff..4e028d2163 100755 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -139,14 +139,10 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()  	addEntry(LLFolderType::FT_NONE, 				new ViewerFolderEntry("New Folder",				"Inv_FolderOpen",		"Inv_FolderClosed",		FALSE,     false, "default")); -#if SUPPORT_ENSEMBLES -	initEnsemblesFromFile(); -#else  	for (U32 type = (U32)LLFolderType::FT_ENSEMBLE_START; type <= (U32)LLFolderType::FT_ENSEMBLE_END; ++type)  	{  		addEntry((LLFolderType::EType)type, 		new ViewerFolderEntry("New Folder",				"Inv_FolderOpen",		"Inv_FolderClosed",		FALSE,     false)); -	}	 -#endif +	}  }  bool LLViewerFolderDictionary::initEnsemblesFromFile() | 
