From 7e74e18548d9b508e3d4c3233044302742942eba Mon Sep 17 00:00:00 2001 From: "Eric M. Tulla (BigPapi)" Date: Wed, 11 Nov 2009 20:27:29 -0500 Subject: Fix for EXT-2244 - Auto fill the My Outfits folder from library/clothing if empty -Reviewed by Seraph --- indra/newview/llagentwearables.cpp | 150 ++++++++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 2 deletions(-) (limited to 'indra/newview/llagentwearables.cpp') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 3fc1055acd..1b1c65640f 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -84,6 +84,26 @@ protected: void processWearablesMessage(); }; +class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver +{ +public: + enum ELibraryOutfitFetchStep { + LOFS_FOLDER = 0, + LOFS_OUTFITS, + LOFS_CONTENTS + }; + LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) {} + ~LLLibraryOutfitsFetch() {} + virtual void done(); +protected: + void folderDone(void); + void outfitsDone(void); + void contentsDone(void); + enum ELibraryOutfitFetchStep mCurrFetchStep; + std::vector< std::pair< LLUUID, std::string > > mOutfits; + bool mOutfitsPopulated; +}; + LLAgentWearables gAgentWearables; BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; @@ -904,6 +924,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs // will call done for us when everything is here. gInventory.addObserver(outfit); } + + gAgentWearables.populateMyOutfitsFolder(); } } @@ -2003,18 +2025,142 @@ void LLAgentWearables::updateServer() gAgent.sendAgentSetAppearance(); } +void LLAgentWearables::populateMyOutfitsFolder(void) +{ + LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(); + + // 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. + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + const LLUUID my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + folders.push_back(my_outfits_id); + outfits->fetchDescendents(folders); + if(outfits->isEverythingComplete()) + { + // everything is already here - call done. + outfits->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(outfits); + } +} + +void LLLibraryOutfitsFetch::done() +{ + switch (mCurrFetchStep){ + case LOFS_FOLDER: + mCurrFetchStep = LOFS_OUTFITS; + folderDone(); + break; + case LOFS_OUTFITS: + mCurrFetchStep = LOFS_CONTENTS; + outfitsDone(); + break; + case LOFS_CONTENTS: + // No longer need this observer hanging around. + gInventory.removeObserver(this); + contentsDone(); + break; + default: + gInventory.removeObserver(this); + delete this; + return; + } + if (mOutfitsPopulated) + { + delete this; + } +} + +void LLLibraryOutfitsFetch::folderDone(void) +{ + // Early out if we already have items in My Outfits. + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + if (cat_array.count() > 0 || wearable_array.count() > 0) + { + mOutfitsPopulated = true; + gInventory.removeObserver(this); + return; + } + + // Get the UUID of the library's clothing folder + const LLUUID library_clothing_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); + + mCompleteFolders.clear(); + + // 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. + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + folders.push_back(library_clothing_id); + fetchDescendents(folders); + if(isEverythingComplete()) + { + // everything is already here - call done. + outfitsDone(); + } +} + +void LLLibraryOutfitsFetch::outfitsDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + for(S32 i = 0; i < cat_array.count(); ++i) + { + if (cat_array.get(i)->getName() != "More Outfits" && cat_array.get(i)->getName() != "Ruth"){ + folders.push_back(cat_array.get(i)->getUUID()); + mOutfits.push_back( std::make_pair(cat_array.get(i)->getUUID(), cat_array.get(i)->getName() )); + } + } + mCompleteFolders.clear(); + fetchDescendents(folders); + if(isEverythingComplete()) + { + // everything is already here - call done. + contentsDone(); + } +} + +void LLLibraryOutfitsFetch::contentsDone(void) +{ + for(S32 i = 0; i < mOutfits.size(); ++i) + { + // First, make a folder in the My Outfits directory. + const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + LLUUID folder_id = gInventory.createNewCategory(parent_id, + LLFolderType::FT_OUTFIT, + mOutfits[i].second); + + LLAppearanceManager::shallowCopyCategory(mOutfits[i].first, folder_id, NULL); + gInventory.notifyObservers(); + } + mOutfitsPopulated = true; +} + void LLInitialWearablesFetch::done() { // No longer need this observer hanging around. gInventory.removeObserver(this); - + // Fetch the wearable items from the Current Outfit Folder LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; LLFindWearables is_wearable; gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH, is_wearable); - + LLAppearanceManager::setAttachmentInvLinkEnable(true); if (wearable_array.count() > 0) { -- cgit v1.2.3 From 0b104e2a418dc794ce7230ab30f472d1787cd9c4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 12 Nov 2009 15:10:06 -0500 Subject: LLAppearanceManager cleanup - turning into proper singleton --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/llagentwearables.cpp') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 9b4986247f..94bf54de7e 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1261,7 +1261,7 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name) LLFolderType::FT_OUTFIT, new_folder_name); - LLAppearanceManager::shallowCopyCategory(LLAppearanceManager::getCOF(),folder_id, NULL); + LLAppearanceManager::instance().shallowCopyCategory(LLAppearanceManager::instance().getCOF(),folder_id, NULL); #if 0 // BAP - fix to go into rename state automatically after outfit is created. LLViewerInventoryCategory *parent_category = gInventory.getCategory(parent_id); @@ -1391,7 +1391,7 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem const LLUUID &item_id = getWearableItemID(type,i); popWearable(type,i); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - LLAppearanceManager::removeItemLinks(item_id,false); + LLAppearanceManager::instance().removeItemLinks(item_id,false); //queryWearableCache(); // moved below if (old_wearable) @@ -1408,7 +1408,7 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem const LLUUID &item_id = getWearableItemID(type,index); popWearable(type, index); gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); - LLAppearanceManager::removeItemLinks(item_id,false); + LLAppearanceManager::instance().removeItemLinks(item_id,false); //queryWearableCache(); // moved below @@ -2014,7 +2014,7 @@ void LLInitialWearablesFetch::done() gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH, is_wearable); - LLAppearanceManager::setAttachmentInvLinkEnable(true); + LLAppearanceManager::instance().setAttachmentInvLinkEnable(true); if (wearable_array.count() > 0) { LLAppearanceManager::instance().updateAppearanceFromCOF(); @@ -2023,7 +2023,7 @@ void LLInitialWearablesFetch::done() { processWearablesMessage(); // Create links for attachments that may have arrived before the COF existed. - LLAppearanceManager::linkRegisteredAttachments(); + LLAppearanceManager::instance().linkRegisteredAttachments(); } delete this; } -- cgit v1.2.3 From b685895dd09c4520027bbdcb48c749e5ea2e0485 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Thu, 12 Nov 2009 18:11:25 -0500 Subject: EXT-2426 : Remove COF processing that is causing recursive calls to gInventory.notifyObservers Changing COF processing to happen during idle(), versus within done(). Reviewed by: Vir --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'indra/newview/llagentwearables.cpp') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 9b4986247f..5bf1573a2c 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -35,6 +35,7 @@ #include "llagent.h" #include "llagentwearables.h" +#include "llcallbacklist.h" #include "llfloatercustomize.h" #include "llfloaterinventory.h" #include "llinventorybridge.h" @@ -82,6 +83,8 @@ public: protected: void processWearablesMessage(); + void processContents(); + static void onIdle(void *userdata); }; LLAgentWearables gAgentWearables; @@ -2002,11 +2005,34 @@ void LLAgentWearables::updateServer() gAgent.sendAgentSetAppearance(); } +//-------------------------------------------------------------------- +// InitialWearablesFetch +// +// This grabs contents from the COF and processes them. +// The processing is handled in idle(), i.e. outside of done(), +// to avoid gInventory.notifyObservers recursion. +//-------------------------------------------------------------------- + +// virtual void LLInitialWearablesFetch::done() { - // No longer need this observer hanging around. + // Delay processing the actual results of this so it's not handled within + // gInventory.notifyObservers. The results will be handled in the next + // idle tick instead. gInventory.removeObserver(this); + gIdleCallbacks.addFunction(onIdle, this); +} +// static +void LLInitialWearablesFetch::onIdle(void *data) +{ + gIdleCallbacks.deleteFunction(onIdle, data); + LLInitialWearablesFetch *self = reinterpret_cast(data); + self->processContents(); +} + +void LLInitialWearablesFetch::processContents() +{ // Fetch the wearable items from the Current Outfit Folder LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; -- cgit v1.2.3 From acdce232994fce7edf9a67a360db2368c5ad6594 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 13 Nov 2009 17:47:00 -0500 Subject: Header file cleanup Removed unnecessary "#include llinventorymodel.h" now that llinventoryobserver was split from llinventorymodel. --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llagentwearables.cpp') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 5dbbcd727c..17e7eea2f1 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -39,7 +39,7 @@ #include "llfloatercustomize.h" #include "llfloaterinventory.h" #include "llinventorybridge.h" -#include "llinventorymodel.h" +#include "llinventoryobserver.h" #include "llinventorypanel.h" #include "llnotify.h" #include "llviewerregion.h" -- cgit v1.2.3 From 68c6ff791ffdd01e98cf7fae61b868db4a6d1698 Mon Sep 17 00:00:00 2001 From: "Eric M. Tulla (BigPapi)" Date: Fri, 13 Nov 2009 22:22:30 -0500 Subject: Fix for post-merge compile error. --- indra/newview/llagentwearables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llagentwearables.cpp') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index a6664778fb..ab518adadd 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2145,7 +2145,7 @@ void LLLibraryOutfitsFetch::contentsDone(void) LLFolderType::FT_OUTFIT, mOutfits[i].second); - LLAppearanceManager::shallowCopyCategory(mOutfits[i].first, folder_id, NULL); + LLAppearanceManager::getInstance()->shallowCopyCategory(mOutfits[i].first, folder_id, NULL); gInventory.notifyObservers(); } mOutfitsPopulated = true; -- cgit v1.2.3 From f17399212edec08faf16fc844b2f9e5882f224f2 Mon Sep 17 00:00:00 2001 From: Steve Bennetts Date: Sat, 14 Nov 2009 11:09:07 -0800 Subject: Compile fix for Windows --- indra/newview/llagentwearables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llagentwearables.cpp') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index ab518adadd..6cb96d1336 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2137,7 +2137,7 @@ void LLLibraryOutfitsFetch::outfitsDone(void) void LLLibraryOutfitsFetch::contentsDone(void) { - for(S32 i = 0; i < mOutfits.size(); ++i) + for(S32 i = 0; i < (S32)mOutfits.size(); ++i) { // First, make a folder in the My Outfits directory. const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); -- cgit v1.2.3