diff options
-rw-r--r-- | indra/newview/llagentwearables.h | 2 | ||||
-rw-r--r-- | indra/newview/llagentwearablesfetch.cpp | 18 | ||||
-rw-r--r-- | indra/newview/llagentwearablesfetch.h | 10 | ||||
-rw-r--r-- | indra/newview/llappearancemgr.cpp | 290 | ||||
-rw-r--r-- | indra/newview/llappearancemgr.h | 21 |
5 files changed, 113 insertions, 228 deletions
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 9f8aadeae7..b76367324c 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -174,7 +174,7 @@ 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(void); + void populateMyOutfitsFolder(); private: void makeNewOutfitDone(S32 type, U32 index); diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index 45274a8e2c..7a9ecd1c7f 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 @@ private: }; // 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 72063114b8..1d0c6739ba 100644 --- a/indra/newview/llagentwearablesfetch.h +++ b/indra/newview/llagentwearablesfetch.h @@ -100,11 +100,11 @@ public: 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 8c5352ded7..e0f1d5348d 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 @@ private: 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 @@ private: }; +// 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 2d6a0a10ed..5a499026e8 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -53,6 +53,7 @@ public: 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 @@ public: // 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 @@ private: }; 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 @@ public: 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 @@ public: virtual void done() { gInventory.removeObserver(this); - doOnIdle(mCallable); + doOnIdleOneTime(mCallable); delete this; } protected: |