diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 9f8aadeae7b0ce8151d897eb31e17129b64ee7bf..b76367324ce24550536f70b5bdc12dcd436d319b 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -174,7 +174,7 @@ class LLAgentWearables
 	
 	// 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(void);
+	void			populateMyOutfitsFolder();
 
 private:
 	void			makeNewOutfitDone(S32 type, U32 index); 
diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp
index 45274a8e2c0fd7b9c1b40e3f8bbc8cb94a5e2938..7a9ecd1c7fccbbbf63ba93a189a7a2a51abd2ff0 100644
--- a/indra/newview/llagentwearablesfetch.cpp
+++ b/indra/newview/llagentwearablesfetch.cpp
@@ -54,7 +54,7 @@ void LLInitialWearablesFetch::done()
 	// gInventory.notifyObservers.  The results will be handled in the next
 	// idle tick instead.
 	gInventory.removeObserver(this);
-	doOnIdle(boost::bind(&LLInitialWearablesFetch::processContents,this));
+	doOnIdleOneTime(boost::bind(&LLInitialWearablesFetch::processContents,this));
 }
 
 void LLInitialWearablesFetch::add(InitialWearableData &data)
@@ -210,8 +210,8 @@ void LLLibraryOutfitsFetch::done()
 {
 	// Delay this until idle() routine, since it's a heavy operation and
 	// we also can't have it run within notifyObservers.
-	doOnIdle(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this));
-	gInventory.removeObserver(this); // Prevent doOnIdle from being added twice.
+	doOnIdleOneTime(boost::bind(&LLLibraryOutfitsFetch::doneIdle,this));
+	gInventory.removeObserver(this); // Prevent doOnIdleOneTime from being added twice.
 }
 
 void LLLibraryOutfitsFetch::doneIdle()
@@ -254,7 +254,7 @@ void LLLibraryOutfitsFetch::doneIdle()
 	}
 }
 
-void LLLibraryOutfitsFetch::folderDone(void)
+void LLLibraryOutfitsFetch::folderDone()
 {
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t wearable_array;
@@ -295,7 +295,7 @@ void LLLibraryOutfitsFetch::folderDone(void)
 	}
 }
 
-void LLLibraryOutfitsFetch::outfitsDone(void)
+void LLLibraryOutfitsFetch::outfitsDone()
 {
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t wearable_array;
@@ -372,7 +372,7 @@ class LLLibraryOutfitsCopyDone: public LLInventoryCallback
 };
 
 // Copy the clothing folders from the library into the imported clothing folder
-void LLLibraryOutfitsFetch::libraryDone(void)
+void LLLibraryOutfitsFetch::libraryDone()
 {
 	if (mImportedClothingID != LLUUID::null)
 	{
@@ -427,7 +427,7 @@ void LLLibraryOutfitsFetch::libraryDone(void)
 	}
 }
 
-void LLLibraryOutfitsFetch::importedFolderFetch(void)
+void LLLibraryOutfitsFetch::importedFolderFetch()
 {
 	// Fetch the contents of the Imported Clothing Folder
 	uuid_vec_t folders;
@@ -442,7 +442,7 @@ void LLLibraryOutfitsFetch::importedFolderFetch(void)
 	}
 }
 
-void LLLibraryOutfitsFetch::importedFolderDone(void)
+void LLLibraryOutfitsFetch::importedFolderDone()
 {
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t wearable_array;
@@ -471,7 +471,7 @@ void LLLibraryOutfitsFetch::importedFolderDone(void)
 	}
 }
 
-void LLLibraryOutfitsFetch::contentsDone(void)
+void LLLibraryOutfitsFetch::contentsDone()
 {		
 	LLInventoryModel::cat_array_t cat_array;
 	LLInventoryModel::item_array_t wearable_array;
diff --git a/indra/newview/llagentwearablesfetch.h b/indra/newview/llagentwearablesfetch.h
index 72063114b8dd4ef4c6c0fc52b519f25e64315591..1d0c6739bab1861312c37bd25d62f98c5e894485 100644
--- a/indra/newview/llagentwearablesfetch.h
+++ b/indra/newview/llagentwearablesfetch.h
@@ -100,11 +100,11 @@ class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver
 	LLUUID mMyOutfitsID;
 	void importedFolderFetch();
 protected:
-	void folderDone(void);
-	void outfitsDone(void);
-	void libraryDone(void);
-	void importedFolderDone(void);
-	void contentsDone(void);
+	void folderDone();
+	void outfitsDone();
+	void libraryDone();
+	void importedFolderDone();
+	void contentsDone();
 	enum ELibraryOutfitFetchStep mCurrFetchStep;
 	uuid_vec_t mLibraryClothingFolders;
 	uuid_vec_t mImportedClothingFolders;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 8c5352ded71f71127e0e6d92d029211e3bd193f4..e0f1d5348dbf93e34dde52553a9d40d122e41ad4 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -74,23 +74,6 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string&
 	}
 }
 
-// support for secondlife:///app/appearance SLapps
-class LLAppearanceHandler : public LLCommandHandler
-{
-public:
-	// requests will be throttled from a non-trusted browser
-	LLAppearanceHandler() : LLCommandHandler("appearance", UNTRUSTED_THROTTLE) {}
-
-	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
-	{
-		// support secondlife:///app/appearance/show, but for now we just
-		// make all secondlife:///app/appearance SLapps behave this way
-		LLSideTray::getInstance()->showPanel("sidepanel_appearance", LLSD());
-		return true;
-	}
-};
-LLAppearanceHandler gAppearanceHandler;
-
 class LLWearInventoryCategoryCallback : public LLInventoryCallback
 {
 public:
@@ -133,175 +116,6 @@ class LLWearInventoryCategoryCallback : public LLInventoryCallback
 	bool mAppend;
 };
 
-class LLOutfitObserver : public LLInventoryFetchObserver
-{
-public:
-	LLOutfitObserver(const LLUUID& cat_id, bool copy_items, bool append) :
-		mCatID(cat_id),
-		mCopyItems(copy_items),
-		mAppend(append)
-	{}
-	~LLOutfitObserver() {}
-	virtual void done();
-	void doWearCategory();
-
-protected:
-	LLUUID mCatID;
-	bool mCopyItems;
-	bool mAppend;
-};
-
-void LLOutfitObserver::done()
-{
-	llinfos << "done 2nd stage fetch" << llendl;
-	gInventory.removeObserver(this);
-	doOnIdle(boost::bind(&LLOutfitObserver::doWearCategory,this));
-}
-
-void LLOutfitObserver::doWearCategory()
-{
-	llinfos << "starting" << llendl;
-	
-	// We now have an outfit ready to be copied to agent inventory. Do
-	// it, and wear that outfit normally.
-	if(mCopyItems)
-	{
-		LLInventoryCategory* cat = gInventory.getCategory(mCatID);
-		std::string name;
-		if(!cat)
-		{
-			// should never happen.
-			name = "New Outfit";
-		}
-		else
-		{
-			name = cat->getName();
-		}
-		LLViewerInventoryItem* item = NULL;
-		item_ref_t::iterator it = mComplete.begin();
-		item_ref_t::iterator end = mComplete.end();
-		LLUUID pid;
-		for(; it < end; ++it)
-		{
-			item = (LLViewerInventoryItem*)gInventory.getItem(*it);
-			if(item)
-			{
-				if(LLInventoryType::IT_GESTURE == item->getInventoryType())
-				{
-					pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
-				}
-				else
-				{
-					pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
-				}
-				break;
-			}
-		}
-		if(pid.isNull())
-		{
-			pid = gInventory.getRootFolderID();
-		}
-		
-		LLUUID cat_id = gInventory.createNewCategory(
-			pid,
-			LLFolderType::FT_NONE,
-			name);
-		mCatID = cat_id;
-		LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend);
-		it = mComplete.begin();
-		for(; it < end; ++it)
-		{
-			item = (LLViewerInventoryItem*)gInventory.getItem(*it);
-			if(item)
-			{
-				copy_inventory_item(
-					gAgent.getID(),
-					item->getPermissions().getOwner(),
-					item->getUUID(),
-					cat_id,
-					std::string(),
-					cb);
-			}
-		}
-		// BAP fixes a lag in display of created dir.
-		gInventory.notifyObservers();
-	}
-	else
-	{
-		// Wear the inventory category.
-		LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend);
-	}
-	delete this;
-}
-
-class LLOutfitFetch : public LLInventoryFetchDescendentsObserver
-{
-public:
-	LLOutfitFetch(bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {}
-	~LLOutfitFetch() {}
-	virtual void done();
-protected:
-	bool mCopyItems;
-	bool mAppend;
-};
-
-void LLOutfitFetch::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.
-	llinfos << "done first stage fetch" << llendl;
-	
-	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;
-	}
-
-	LLOutfitObserver* outfit_observer = new LLOutfitObserver(mCompleteFolders.front(), mCopyItems, mAppend);
-	LLInventoryFetchObserver::item_ref_t ids;
-	for(S32 i = 0; i < count; ++i)
-	{
-		ids.push_back(item_array.get(i)->getUUID());
-	}
-
-	// clean up, and remove this as an observer since the call to the
-	// outfit could notify observers and throw us into an infinite
-	// loop.
-	//dec_busy_count();
-	gInventory.removeObserver(this);
-
-	// increment busy count and either tell the inventory to check &
-	// call done, or add this object to the inventory for observation.
-	//inc_busy_count();
-
-	// do the fetch
-	outfit_observer->fetchItems(ids);
-	if(outfit_observer->isEverythingComplete())
-	{
-		// everything is already here - call done.
-		outfit_observer->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(outfit_observer);
-	}
-	delete this;
-}
-
 LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy():
 	mFireCount(0)
 {
@@ -1309,24 +1123,85 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
 	llinfos << "wearInventoryCategory( " << category->getName()
 			 << " )" << llendl;
 
-	// What we do here is get the complete information on the items in
-	// the inventory, and set up an observer that will wait for that to
-	// happen.
-	LLOutfitFetch* outfit_fetcher = new LLOutfitFetch(copy, append);
-	uuid_vec_t folders;
-	folders.push_back(category->getUUID());
-	outfit_fetcher->fetchDescendents(folders);
-	//inc_busy_count();
-	if(outfit_fetcher->isEverythingComplete())
+	callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
+														   &LLAppearanceMgr::instance(),
+														   category->getUUID(), copy, append));
+}
+
+void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
+{
+	llinfos << "starting" << llendl;
+	
+	// We now have an outfit ready to be copied to agent inventory. Do
+	// it, and wear that outfit normally.
+	LLInventoryCategory* cat = gInventory.getCategory(cat_id);
+	if(copy_items)
 	{
-		// everything is already here - call done.
-		outfit_fetcher->done();
+		LLInventoryModel::cat_array_t* cats;
+		LLInventoryModel::item_array_t* items;
+		gInventory.getDirectDescendentsOf(cat_id, cats, items);
+		std::string name;
+		if(!cat)
+		{
+			// should never happen.
+			name = "New Outfit";
+		}
+		else
+		{
+			name = cat->getName();
+		}
+		LLViewerInventoryItem* item = NULL;
+		LLInventoryModel::item_array_t::const_iterator it = items->begin();
+		LLInventoryModel::item_array_t::const_iterator end = items->end();
+		LLUUID pid;
+		for(; it < end; ++it)
+		{
+			item = *it;
+			if(item)
+			{
+				if(LLInventoryType::IT_GESTURE == item->getInventoryType())
+				{
+					pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
+				}
+				else
+				{
+					pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
+				}
+				break;
+			}
+		}
+		if(pid.isNull())
+		{
+			pid = gInventory.getRootFolderID();
+		}
+		
+		LLUUID new_cat_id = gInventory.createNewCategory(
+			pid,
+			LLFolderType::FT_NONE,
+			name);
+		LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(new_cat_id, append);
+		it = items->begin();
+		for(; it < end; ++it)
+		{
+			item = *it;
+			if(item)
+			{
+				copy_inventory_item(
+					gAgent.getID(),
+					item->getPermissions().getOwner(),
+					item->getUUID(),
+					new_cat_id,
+					std::string(),
+					cb);
+			}
+		}
+		// BAP fixes a lag in display of created dir.
+		gInventory.notifyObservers();
 	}
 	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(outfit_fetcher);
+		// Wear the inventory category.
+		LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(cat, append);
 	}
 }
 
@@ -1436,6 +1311,8 @@ class LLDeferredCOFLinkObserver: public LLInventoryObserver
 };
 
 
+// BAP - note that this runs asynchronously if the item is not already loaded from inventory.
+// Dangerous if caller assumes link will exist after calling the function.
 void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update )
 {
 	const LLInventoryItem *item = gInventory.getItem(item_id);
@@ -1616,7 +1493,7 @@ void LLAppearanceMgr::updateIsDirty()
 	}
 }
 
-void LLAppearanceMgr::onFirstFullyVisible()
+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.
@@ -1633,6 +1510,12 @@ void LLAppearanceMgr::onFirstFullyVisible()
 	check_populate_my_outfits = false;
 }
 
+// Handler for anything that's deferred until avatar de-clouds.
+void LLAppearanceMgr::onFirstFullyVisible()
+{
+	autopopulateOutfits();
+}
+
 //#define DUMP_CAT_VERBOSE
 
 void LLAppearanceMgr::dumpCat(const LLUUID& cat_id, const std::string& msg)
@@ -1684,6 +1567,7 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val)
 	mAttachmentInvLinkEnabled = val;
 }
 
+// BAP TODO - mRegisteredAttachments is currently maintained but not used for anything.  Consider yanking.
 void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg)
 {
        llinfos << msg << llendl;
@@ -1705,7 +1589,6 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id)
 {
        mRegisteredAttachments.insert(item_id);
 	   gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
-       //dumpAttachmentSet(mRegisteredAttachments,"after register:");
 
 	   if (mAttachmentInvLinkEnabled)
 	   {
@@ -1722,11 +1605,8 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id)
        mRegisteredAttachments.erase(item_id);
 	   gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
 
-       //dumpAttachmentSet(mRegisteredAttachments,"after unregister:");
-
 	   if (mAttachmentInvLinkEnabled)
 	   {
-		   //LLAppearanceMgr::dumpCat(LLAppearanceMgr::getCOF(),"Removing attachment link:");
 		   LLAppearanceMgr::removeCOFItemLinks(item_id, false);
 	   }
 	   else
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 2d6a0a10edb389179185d5935288bc00e5d7713e..5a499026e870a6bf394bd9aa10f2064230d59dde 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -53,6 +53,7 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	void updateCOF(const LLUUID& category, bool append = false);
 	void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
 	void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
+	void wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append);
 	void wearOutfitByName(const std::string& name);
 	void changeOutfit(bool proceed, const LLUUID& category, bool append);
 
@@ -118,6 +119,9 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 
 	// Called when self avatar is first fully visible.
 	void onFirstFullyVisible();
+
+	// Create initial outfits from library.
+	void autopopulateOutfits();
 	
 protected:
 	LLAppearanceMgr();
@@ -173,17 +177,17 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string&
 // Shim class and template function to allow arbitrary boost::bind
 // expressions to be run as one-time idle callbacks.
 template <typename T>
-class OnIdleCallback
+class OnIdleCallbackOneTime
 {
 public:
-	OnIdleCallback(T callable):
+	OnIdleCallbackOneTime(T callable):
 		mCallable(callable)
 	{
 	}
 	static void onIdle(void *data)
 	{
 		gIdleCallbacks.deleteFunction(onIdle, data);
-		OnIdleCallback<T>* self = reinterpret_cast<OnIdleCallback<T>*>(data);
+		OnIdleCallbackOneTime<T>* self = reinterpret_cast<OnIdleCallbackOneTime<T>*>(data);
 		self->call();
 		delete self;
 	}
@@ -196,14 +200,15 @@ class OnIdleCallback
 };
 
 template <typename T>
-void doOnIdle(T callable)
+void doOnIdleOneTime(T callable)
 {
-	OnIdleCallback<T>* cb_functor = new OnIdleCallback<T>(callable);
-	gIdleCallbacks.addFunction(&OnIdleCallback<T>::onIdle,cb_functor);
+	OnIdleCallbackOneTime<T>* cb_functor = new OnIdleCallbackOneTime<T>(callable);
+	gIdleCallbacks.addFunction(&OnIdleCallbackOneTime<T>::onIdle,cb_functor);
 }
 
 // Shim class and template function to allow arbitrary boost::bind
 // expressions to be run as recurring idle callbacks.
+// Callable should return true when done, false to continue getting called.
 template <typename T>
 class OnIdleCallbackRepeating
 {
@@ -212,7 +217,7 @@ class OnIdleCallbackRepeating
 		mCallable(callable)
 	{
 	}
-	// Will keep getting called until the callable returns false.
+	// Will keep getting called until the callable returns true.
 	static void onIdle(void *data)
 	{
 		OnIdleCallbackRepeating<T>* self = reinterpret_cast<OnIdleCallbackRepeating<T>*>(data);
@@ -252,7 +257,7 @@ class CallAfterCategoryFetchStage2: public LLInventoryFetchObserver
 	virtual void done()
 	{
 		gInventory.removeObserver(this);
-		doOnIdle(mCallable);
+		doOnIdleOneTime(mCallable);
 		delete this;
 	}
 protected: