From f5b82a377256d5806ec101e8a9d90533ea1a3bf9 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 5 Feb 2010 18:44:35 -0500
Subject: For EXT-4919: Initial gesture setup is wrong for new users.  Added a
 template-y mechanism for roundtripping an inventory fetch - hopefully could
 replace some gratuitous classes elsewhere as well.

---
 indra/newview/llappearancemgr.cpp |  27 +++++++
 indra/newview/llappearancemgr.h   | 102 ++++++++++++++++++++++++
 indra/newview/llstartup.cpp       | 161 ++++++--------------------------------
 indra/newview/llvoavatar.cpp      |   3 +-
 4 files changed, 156 insertions(+), 137 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 6c4c59c4e7..6a0d5312ee 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -48,6 +48,31 @@
 #include "llviewerregion.h"
 #include "llwearablelist.h"
 
+LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name)
+{
+	LLInventoryModel::cat_array_t cat_array;
+	LLInventoryModel::item_array_t item_array;
+	LLNameCategoryCollector has_name(name);
+	gInventory.collectDescendentsIf(parent_id,
+									cat_array,
+									item_array,
+									LLInventoryModel::EXCLUDE_TRASH,
+									has_name);
+	if (0 == cat_array.count())
+		return LLUUID();
+	else
+	{
+		LLViewerInventoryCategory *cat = cat_array.get(0);
+		if (cat)
+			return cat->getUUID();
+		else
+		{
+			llwarns << "null cat" << llendl;
+			return LLUUID();
+		}
+	}
+}
+
 // support for secondlife:///app/appearance SLapps
 class LLAppearanceHandler : public LLCommandHandler
 {
@@ -538,6 +563,8 @@ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID
 														LLFolderType::FT_NONE,
 														src_cat->getName());
 	shallowCopyCategoryContents(src_id, subfolder_id, cb);
+
+	gInventory.notifyObservers();
 }
 
 // Copy contents of src_id to dst_id.
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 63ac4d5402..8ea52fb4af 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -35,6 +35,7 @@
 
 #include "llsingleton.h"
 #include "llinventorymodel.h"
+#include "llinventoryobserver.h"
 #include "llcallbacklist.h"
 
 class LLWearable;
@@ -148,6 +149,8 @@ public:
 
 #define SUPPORT_ENSEMBLES 0
 
+LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);
+
 // Shim class and template function to allow arbitrary boost::bind
 // expressions to be run as one-time idle callbacks.
 template <typename T>
@@ -216,4 +219,103 @@ void doOnIdleRepeating(T callable)
 	gIdleCallbacks.addFunction(&OnIdleCallbackRepeating<T>::onIdle,cb_functor);
 }
 
+template <class T>
+class CallAfterCategoryFetchStage2: public LLInventoryFetchObserver
+{
+public:
+	CallAfterCategoryFetchStage2(T callable):
+		mCallable(callable)
+	{
+	}
+	~CallAfterCategoryFetchStage2()
+	{
+	}
+	virtual void done()
+	{
+		gInventory.removeObserver(this);
+		doOnIdle(mCallable);
+		delete this;
+	}
+protected:
+	T mCallable;
+};
+
+template <class T>
+class CallAfterCategoryFetchStage1: public LLInventoryFetchDescendentsObserver
+{
+public:
+	CallAfterCategoryFetchStage1(T callable):
+		mCallable(callable)
+	{
+	}
+	~CallAfterCategoryFetchStage1()
+	{
+	}
+	virtual void done()
+	{
+		// What we do here is get the complete information on the items in
+		// the library, and set up an observer that will wait for that to
+		// happen.
+		LLInventoryModel::cat_array_t cat_array;
+		LLInventoryModel::item_array_t item_array;
+		gInventory.collectDescendents(mCompleteFolders.front(),
+									  cat_array,
+									  item_array,
+									  LLInventoryModel::EXCLUDE_TRASH);
+		S32 count = item_array.count();
+		if(!count)
+		{
+			llwarns << "Nothing fetched in category " << mCompleteFolders.front()
+					<< llendl;
+			//dec_busy_count();
+			gInventory.removeObserver(this);
+			delete this;
+			return;
+		}
+
+		CallAfterCategoryFetchStage2<T> *stage2 = new CallAfterCategoryFetchStage2<T>(mCallable);
+		LLInventoryFetchObserver::item_ref_t ids;
+		for(S32 i = 0; i < count; ++i)
+		{
+			ids.push_back(item_array.get(i)->getUUID());
+		}
+		
+		gInventory.removeObserver(this);
+		
+		// do the fetch
+		stage2->fetchItems(ids);
+		if(stage2->isEverythingComplete())
+		{
+			// everything is already here - call done.
+			stage2->done();
+		}
+		else
+		{
+			// it's all on it's way - add an observer, and the inventory
+			// will call done for us when everything is here.
+			gInventory.addObserver(stage2);
+		}
+		delete this;
+	}
+protected:
+	T mCallable;
+};
+
+template <class T> 
+void callAfterCategoryFetch(const LLUUID& cat_id, T callable)
+{
+	CallAfterCategoryFetchStage1<T> *stage1 = new CallAfterCategoryFetchStage1<T>(callable);
+	LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+	folders.push_back(cat_id);
+	stage1->fetchDescendents(folders);
+	if (stage1->isEverythingComplete())
+	{
+		stage1->done();
+	}
+	else
+	{
+		gInventory.addObserver(stage1);
+	}
+}
+
 #endif
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 7dd597a0df..6baaba907c 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2530,109 +2530,6 @@ bool callback_choose_gender(const LLSD& notification, const LLSD& response)
 	return false;
 }
 
-LLViewerInventoryCategory* findDescendentCategoryByName(const LLUUID& parent_id,const std::string& name)
-{
-	LLInventoryModel::cat_array_t cat_array;
-	LLInventoryModel::item_array_t item_array;
-	LLNameCategoryCollector has_name(name);
-	gInventory.collectDescendentsIf(parent_id,
-									cat_array,
-									item_array,
-									LLInventoryModel::EXCLUDE_TRASH,
-									has_name);
-	if (0 == cat_array.count())
-		return NULL;
-	else
-		return cat_array.get(0);
-}
-
-class CopyAfterFetchStage2: public LLInventoryFetchObserver
-{
-public:
-	CopyAfterFetchStage2(LLViewerInventoryCategory *cat, const LLUUID& dst_id):
-		mCat(cat),
-		mDstID(dst_id)
-	{
-	}
-	~CopyAfterFetchStage2()
-	{
-	}
-	virtual void done()
-	{
-//		LLAppearanceManager::instance().shallowCopyCategory(cat,dst_id,NULL);
-		gInventory.removeObserver(this);
-		LLPointer<LLInventoryCallback> cb(NULL);
-		LLAppearanceManager *app_mgr = &(LLAppearanceManager::instance());
-		doOnIdle(boost::bind(&LLAppearanceManager::shallowCopyCategory,app_mgr,mCat->getUUID(),mDstID,cb));
-		delete this;
-	}
-protected:
-	LLViewerInventoryCategory *mCat;
-	LLUUID mDstID;
-};
-
-class CopyAfterFetchStage1: public LLInventoryFetchDescendentsObserver
-{
-public:
-	CopyAfterFetchStage1(LLViewerInventoryCategory *cat, const LLUUID& dst_id):
-		mCat(cat),
-		mDstID(dst_id)
-	{
-	}
-	~CopyAfterFetchStage1()
-	{
-	}
-	virtual void done()
-	{
-		// What we do here is get the complete information on the items in
-		// the library, and set up an observer that will wait for that to
-		// happen.
-		LLInventoryModel::cat_array_t cat_array;
-		LLInventoryModel::item_array_t item_array;
-		gInventory.collectDescendents(mCompleteFolders.front(),
-									  cat_array,
-									  item_array,
-									  LLInventoryModel::EXCLUDE_TRASH);
-		S32 count = item_array.count();
-		if(!count)
-		{
-			llwarns << "Nothing fetched in category " << mCompleteFolders.front()
-					<< llendl;
-			//dec_busy_count();
-			gInventory.removeObserver(this);
-			delete this;
-			return;
-		}
-
-		CopyAfterFetchStage2 *stage2 = new CopyAfterFetchStage2(mCat,mDstID);
-		LLInventoryFetchObserver::item_ref_t ids;
-		for(S32 i = 0; i < count; ++i)
-		{
-			ids.push_back(item_array.get(i)->getUUID());
-		}
-		
-		gInventory.removeObserver(this);
-		
-		// do the fetch
-		stage2->fetchItems(ids);
-		if(stage2->isEverythingComplete())
-		{
-			// everything is already here - call done.
-			stage2->done();
-		}
-		else
-		{
-			// it's all on it's way - add an observer, and the inventory
-			// will call done for us when everything is here.
-			gInventory.addObserver(stage2);
-		}
-		delete this;
-	}
-protected:
-	LLViewerInventoryCategory *mCat;
-	LLUUID mDstID;
-};
-
 void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 								   const std::string& gender_name )
 {
@@ -2656,10 +2553,10 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 
 	// try to find the outfit - if not there, create some default
 	// wearables.
-	LLViewerInventoryCategory *cat = findDescendentCategoryByName(
+	LLUUID cat_id = findDescendentCategoryIDByName(
 		gInventory.getLibraryRootFolderID(),
 		outfit_folder_name);
-	if (!cat)
+	if (cat_id.isNull())
 	{
 		gAgentWearables.createStandardWearables(gender);
 	}
@@ -2667,48 +2564,42 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 	{
 		bool do_copy = true;
 		bool do_append = false;
+		LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
 		LLAppearanceManager::instance().wearInventoryCategory(cat, do_copy, do_append);
 	}
 
-	// Copy gender-specific gestures.
-	LLViewerInventoryCategory *gestures_cat = findDescendentCategoryByName( 
+	// Copy gestures
+	LLUUID dst_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
+	LLPointer<LLInventoryCallback> cb(NULL);
+	LLAppearanceManager *app_mgr = &(LLAppearanceManager::instance());
+
+	// - Copy gender-specific gestures.
+	LLUUID gestures_cat_id = findDescendentCategoryIDByName( 
 		gInventory.getLibraryRootFolderID(),
 		gestures);
-	if (gestures_cat)
+	if (gestures_cat_id.notNull())
 	{
-		CopyAfterFetchStage1 *stage1 = new CopyAfterFetchStage1(
-			gestures_cat, gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE));
-		LLInventoryFetchDescendentsObserver::folder_ref_t folders;
-		folders.push_back(gestures_cat->getUUID());
-		stage1->fetchDescendents(folders);
-		if (stage1->isEverythingComplete())
-		{
-			stage1->done();
-		}
-		else
-		{
-			gInventory.addObserver(stage1);
-		}
-
-//		LLAppearanceManager::instance().shallowCopyCategory(
-//			gestures_cat->getUUID(),
-//			gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE),
-//			NULL);
+		callAfterCategoryFetch(gestures_cat_id,
+							   boost::bind(&LLAppearanceManager::shallowCopyCategory,
+										   app_mgr,
+										   gestures_cat_id,
+										   dst_id,
+										   cb));
 	}
 
-	// Copy common gestures.
-#if 0
-	LLViewerInventoryCategory *common_gestures_cat = findDescendentCategoryByName( 
+	// - Copy common gestures.
+	LLUUID common_gestures_cat_id = findDescendentCategoryIDByName( 
 		gInventory.getLibraryRootFolderID(),
 		COMMON_GESTURES_FOLDER);
-	if (common_gestures_cat)
+	if (common_gestures_cat_id.notNull())
 	{
-		LLAppearanceManager::instance().shallowCopyCategory(
-			common_gestures_cat->getUUID(),
-			gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE),
-			NULL);
+		callAfterCategoryFetch(common_gestures_cat_id,
+							   boost::bind(&LLAppearanceManager::shallowCopyCategory,
+										   app_mgr,
+										   common_gestures_cat_id,
+										   dst_id,
+										   cb));
 	}
-#endif
 
 	// This is really misnamed -- it means we have started loading
 	// an outfit/shape that will give the avatar a gender eventually. JC
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index bafdd9474e..4235f97eab 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1869,8 +1869,7 @@ void LLVOAvatar::releaseMeshData()
 // virtual
 void LLVOAvatar::restoreMeshData()
 {
-	// BAP restore
-	//llassert(!isSelf());
+	llassert(!isSelf());
 	LLMemType mt(LLMemType::MTYPE_AVATAR);
 	
 	//llinfos << "Restoring" << llendl;
-- 
cgit v1.2.3