From d2d192060993d938a2fd131f8872a60b678e4a04 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 4 Feb 2010 10:20:31 -0500 Subject: For EXT-4855: Crash on onWearableAssetFetch. Prevent late-arriving wearables from touching a deleted object. --- indra/newview/llappearancemgr.cpp | 47 +++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 585d42f66d..0fe236c056 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -321,7 +321,7 @@ public: ~LLWearableHoldingPattern(); bool pollCompletion(); - bool isDone(); + bool isFetchCompleted(); bool isTimedOut(); typedef std::list found_list_t; @@ -330,10 +330,12 @@ public: LLInventoryModel::item_array_t mGestItems; S32 mResolved; LLTimer mWaitTime; + bool mFired; }; LLWearableHoldingPattern::LLWearableHoldingPattern(): - mResolved(0) + mResolved(0), + mFired(false) { } @@ -341,31 +343,34 @@ LLWearableHoldingPattern::~LLWearableHoldingPattern() { } -bool LLWearableHoldingPattern::isDone() +bool LLWearableHoldingPattern::isFetchCompleted() { - if (mResolved >= (S32)mFoundList.size()) - return true; // have everything we were waiting for - else if (isTimedOut()) - { - llwarns << "Exceeded max wait time, updating appearance based on what has arrived" << llendl; - return true; - } - return false; - + return (mResolved >= (S32)mFoundList.size()); // have everything we were waiting for? } bool LLWearableHoldingPattern::isTimedOut() { - static F32 max_wait_time = 15.0; // give up if wearable fetches haven't completed in max_wait_time seconds. + static F32 max_wait_time = 20.0; // give up if wearable fetches haven't completed in max_wait_time seconds. return mWaitTime.getElapsedTimeF32() > max_wait_time; } bool LLWearableHoldingPattern::pollCompletion() { - bool done = isDone(); - llinfos << "polling, done status: " << done << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl; + bool completed = isFetchCompleted(); + bool timed_out = isTimedOut(); + bool done = completed || timed_out; + + llinfos << "polling, done status: " << completed << " timed out? " << timed_out << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl; + if (done) { + mFired = true; + + if (timed_out) + { + llwarns << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl; + } + // Activate all gestures in this folder if (mGestItems.count() > 0) { @@ -397,7 +402,11 @@ bool LLWearableHoldingPattern::pollCompletion() LLAgentWearables::userUpdateAttachments(mObjItems); } - delete this; + if (completed) + { + // Only safe to delete if all wearable callbacks completed. + delete this; + } } return done; } @@ -432,7 +441,11 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items) static void onWearableAssetFetch(LLWearable* wearable, void* data) { LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data; - + if (holder->mFired) + { + llwarns << "called after holder fired" << llendl; + } + if(wearable) { for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin(); -- cgit v1.2.3 From 14d77a36d4392cd51a0887d957905ce4c532ba38 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Thu, 4 Feb 2010 18:38:47 -0500 Subject: EXT-4993 : Deleting an item from the COF in Inventory Floater keeps it worn EXT-4997 : Centralize right-click menu options for delete/remove link EXT-4998 : Automatically reject double separators from right click menu Disabled/hid delete button from COF right-click menu, also means that trash icon is disabled. Added generalized function to remove consecutive separators from right-click menu. Made a minor cosmetic change to have all code duplication for adding "delete" menu item instead call a common function. --- indra/newview/llappearancemgr.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0fe236c056..326fc41c1e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1353,6 +1353,11 @@ BOOL LLAppearanceManager::getIsInCOF(const LLUUID& obj_id) const BOOL LLAppearanceManager::getIsProtectedCOFItem(const LLUUID& obj_id) const { if (!getIsInCOF(obj_id)) return FALSE; + + // For now, don't allow direct deletion from the COF. Instead, force users + // to choose "Detach" or "Take Off". + return TRUE; + /* const LLInventoryObject *obj = gInventory.getObject(obj_id); if (!obj) return FALSE; @@ -1363,4 +1368,5 @@ BOOL LLAppearanceManager::getIsProtectedCOFItem(const LLUUID& obj_id) const if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE; return FALSE; + */ } -- cgit v1.2.3 From d8f0bc021f3e7e18e3918178f3c81cdf444fb0d3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 5 Feb 2010 16:37:23 -0500 Subject: For EXT-4919: Initial gesture setup is wrong for new users. Checkpointing work in progress. --- indra/newview/llappearancemgr.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0fe236c056..6c4c59c4e7 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -519,8 +519,30 @@ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, boo LLAppearanceManager::instance().updateCOF(category,append); } +// Create a copy of src_id + contents as a subfolder of dst_id. void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id, LLPointer cb) +{ + LLInventoryCategory *src_cat = gInventory.getCategory(src_id); + if (!src_cat) + { + llwarns << "folder not found for src " << src_id.asString() << llendl; + return; + } + LLUUID parent_id = dst_id; + if(parent_id.isNull()) + { + parent_id = gInventory.getRootFolderID(); + } + LLUUID subfolder_id = gInventory.createNewCategory( parent_id, + LLFolderType::FT_NONE, + src_cat->getName()); + shallowCopyCategoryContents(src_id, subfolder_id, cb); +} + +// Copy contents of src_id to dst_id. +void LLAppearanceManager::shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, + LLPointer cb) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; -- cgit v1.2.3 From f5b82a377256d5806ec101e8a9d90533ea1a3bf9 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" 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 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') 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. -- cgit v1.2.3 From 8332550c6dc2a159c9c5812819e167578eda1269 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 8 Feb 2010 18:37:35 -0500 Subject: Temporary diagnostics --- indra/newview/llappearancemgr.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0cceba6cb0..aad39854e4 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -113,6 +113,8 @@ public: protected: ~LLWearInventoryCategoryCallback() { + llinfos << "BAP done all inventory callbacks" << llendl; + // Is the destructor called by ordinary dereference, or because the app's shutting down? // If the inventory callback manager goes away, we're shutting down, no longer want the callback. if( LLInventoryCallbackManager::is_instantiated() ) @@ -150,12 +152,15 @@ protected: void LLOutfitObserver::done() { + llinfos << "BAP done 2nd stage fetch" << llendl; gInventory.removeObserver(this); doOnIdle(boost::bind(&LLOutfitObserver::doWearCategory,this)); } void LLOutfitObserver::doWearCategory() { + llinfos << "BAP start" << llendl; + // We now have an outfit ready to be copied to agent inventory. Do // it, and wear that outfit normally. if(mCopyItems) @@ -244,6 +249,8 @@ 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 << "BAP done first stage fetch" << llendl; + LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; gInventory.collectDescendents(mCompleteFolders.front(), @@ -304,6 +311,8 @@ public: virtual ~LLUpdateAppearanceOnDestroy() { + llinfos << "BAP done update appearance on destroy" << llendl; + if (!LLApp::isExiting()) { LLAppearanceManager::instance().updateAppearanceFromCOF(); @@ -312,6 +321,7 @@ public: /* virtual */ void fire(const LLUUID& inv_item) { + llinfos << "BAP fire" << llendl; mFireCount++; } private: @@ -703,6 +713,8 @@ void LLAppearanceManager::linkAll(const LLUUID& category, void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) { + llinfos << "BAP updating cof" << llendl; + const LLUUID cof = getCOF(); // Deactivate currently active gestures in the COF, if replacing outfit @@ -760,18 +772,26 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) gInventory.notifyObservers(); // Create links to new COF contents. + llinfos << "BAP creating LLUpdateAppearanceOnDestroy" << llendl; LLPointer link_waiter = new LLUpdateAppearanceOnDestroy; linkAll(cof, body_items, link_waiter); + llinfos << "BAP submitted all body_items link requests" << llendl; linkAll(cof, wear_items, link_waiter); + llinfos << "BAP submitted all wear_items link requests" << llendl; linkAll(cof, obj_items, link_waiter); + llinfos << "BAP submitted all obj link requests" << llendl; linkAll(cof, gest_items, link_waiter); + llinfos << "BAP submitted all gest link requests" << llendl; + // Add link to outfit if category is an outfit. if (!append) { createBaseOutfitLink(category, link_waiter); } + llinfos << "BAP submitted all link requests" << llendl; + llinfos << "BAP waiting for LLUpdateAppearanceOnDestroy" << llendl; } void LLAppearanceManager::updatePanelOutfitName(const std::string& name) @@ -843,6 +863,8 @@ void LLAppearanceManager::updateAppearanceFromCOF() { // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link + llinfos << "BAP update appearance starts" << llendl; + updateIsDirty(); dumpCat(getCOF(),"COF, start"); @@ -973,8 +995,11 @@ void LLAppearanceManager::wearInventoryCategory(LLInventoryCategory* category, b { if(!category) return; + llinfos << "BAP wearInventoryCategory" << llendl; + lldebugs << "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. @@ -1003,6 +1028,8 @@ void LLAppearanceManager::wearInventoryCategoryOnAvatar( LLInventoryCategory* ca // this up front to avoid having to deal with the case of multiple // wearables being dirty. if(!category) return; + llinfos << "BAP wearInventoryCategoryOnAvatar( " << category->getName() + << " )" << llendl; lldebugs << "wearInventoryCategoryOnAvatar( " << category->getName() << " )" << llendl; -- cgit v1.2.3 From 71ae50c56b7e5e45df438bc450fead9424e70034 Mon Sep 17 00:00:00 2001 From: "Eric M. Tulla (BigPapi)" Date: Thu, 11 Feb 2010 11:06:42 -0500 Subject: EXT-4387 - Possible fix. No repro, but added an extra safety check and warning the only place in the function that it appears that something could go wrong if we have inventory corruption and InventoryType is wearable but the wearable type bitfield is in a broken state. -Reviewed by vir. --- indra/newview/llappearancemgr.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0cceba6cb0..a78dede344 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -666,6 +666,11 @@ void LLAppearanceManager::filterWearableItems( if (!item->isWearableType()) continue; EWearableType type = item->getWearableType(); + if(type < 0 || type >= WT_COUNT) + { + LL_WARNS("Appearance") << "Invalid wearable type. Type does not match wearable flag bitfield." << LL_ENDL; + continue; + } items_by_type[type].push_back(item); } -- cgit v1.2.3 From 39fe664b97b946daf7984b946fede6f04ae731c4 Mon Sep 17 00:00:00 2001 From: "Eric M. Tulla (BigPapi)" Date: Thu, 11 Feb 2010 11:09:08 -0500 Subject: Minor clarification edit to a warning comment. --- indra/newview/llappearancemgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a78dede344..018e9a92a0 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -668,7 +668,7 @@ void LLAppearanceManager::filterWearableItems( EWearableType type = item->getWearableType(); if(type < 0 || type >= WT_COUNT) { - LL_WARNS("Appearance") << "Invalid wearable type. Type does not match wearable flag bitfield." << LL_ENDL; + LL_WARNS("Appearance") << "Invalid wearable type. Inventory type does not match wearable flag bitfield." << LL_ENDL; continue; } items_by_type[type].push_back(item); -- cgit v1.2.3 From a3d8338cdcf73b17f6cec4f07916560477d933a6 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 12 Feb 2010 13:12:26 -0500 Subject: For EXT-5259: Major regression in load time for new users from 1.23 to 2.0. Moved autopopulate to after avatar appearance resolves --- indra/newview/llappearancemgr.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index aad39854e4..8a646bd626 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1307,6 +1307,20 @@ void LLAppearanceManager::updateIsDirty() } } +void LLAppearanceManager::onFirstFullyVisible() +{ + // 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. + static bool check_populate_my_outfits = true; + if (check_populate_my_outfits && + (LLInventoryModel::getIsFirstTimeInViewer2() + || gSavedSettings.getBOOL("MyOutfitsAutofill"))) + { + gAgentWearables.populateMyOutfitsFolder(); + } + check_populate_my_outfits = false; +} + //#define DUMP_CAT_VERBOSE void LLAppearanceManager::dumpCat(const LLUUID& cat_id, const std::string& msg) -- cgit v1.2.3 From 1e76fc2b1f4e735105f2d45d73ea5a92dbad4e05 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 12 Feb 2010 13:44:32 -0500 Subject: Log spam cleanup --- indra/newview/llappearancemgr.cpp | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 8a646bd626..062e291161 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -113,7 +113,7 @@ public: protected: ~LLWearInventoryCategoryCallback() { - llinfos << "BAP done all inventory callbacks" << llendl; + llinfos << "done all inventory callbacks" << llendl; // Is the destructor called by ordinary dereference, or because the app's shutting down? // If the inventory callback manager goes away, we're shutting down, no longer want the callback. @@ -152,14 +152,14 @@ protected: void LLOutfitObserver::done() { - llinfos << "BAP done 2nd stage fetch" << llendl; + llinfos << "done 2nd stage fetch" << llendl; gInventory.removeObserver(this); doOnIdle(boost::bind(&LLOutfitObserver::doWearCategory,this)); } void LLOutfitObserver::doWearCategory() { - llinfos << "BAP start" << llendl; + llinfos << "starting" << llendl; // We now have an outfit ready to be copied to agent inventory. Do // it, and wear that outfit normally. @@ -249,7 +249,7 @@ 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 << "BAP done first stage fetch" << llendl; + llinfos << "done first stage fetch" << llendl; LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; @@ -311,7 +311,7 @@ public: virtual ~LLUpdateAppearanceOnDestroy() { - llinfos << "BAP done update appearance on destroy" << llendl; + llinfos << "done update appearance on destroy" << llendl; if (!LLApp::isExiting()) { @@ -321,7 +321,7 @@ public: /* virtual */ void fire(const LLUUID& inv_item) { - llinfos << "BAP fire" << llendl; + llinfos << "callback fired" << llendl; mFireCount++; } private: @@ -713,7 +713,7 @@ void LLAppearanceManager::linkAll(const LLUUID& category, void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) { - llinfos << "BAP updating cof" << llendl; + llinfos << "starting" << llendl; const LLUUID cof = getCOF(); @@ -772,26 +772,20 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) gInventory.notifyObservers(); // Create links to new COF contents. - llinfos << "BAP creating LLUpdateAppearanceOnDestroy" << llendl; + llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl; LLPointer link_waiter = new LLUpdateAppearanceOnDestroy; linkAll(cof, body_items, link_waiter); - llinfos << "BAP submitted all body_items link requests" << llendl; linkAll(cof, wear_items, link_waiter); - llinfos << "BAP submitted all wear_items link requests" << llendl; linkAll(cof, obj_items, link_waiter); - llinfos << "BAP submitted all obj link requests" << llendl; linkAll(cof, gest_items, link_waiter); - llinfos << "BAP submitted all gest link requests" << llendl; - // Add link to outfit if category is an outfit. if (!append) { createBaseOutfitLink(category, link_waiter); } - llinfos << "BAP submitted all link requests" << llendl; - llinfos << "BAP waiting for LLUpdateAppearanceOnDestroy" << llendl; + llinfos << "waiting for LLUpdateAppearanceOnDestroy" << llendl; } void LLAppearanceManager::updatePanelOutfitName(const std::string& name) @@ -863,7 +857,7 @@ void LLAppearanceManager::updateAppearanceFromCOF() { // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link - llinfos << "BAP update appearance starts" << llendl; + llinfos << "starting" << llendl; updateIsDirty(); @@ -995,9 +989,7 @@ void LLAppearanceManager::wearInventoryCategory(LLInventoryCategory* category, b { if(!category) return; - llinfos << "BAP wearInventoryCategory" << llendl; - - lldebugs << "wearInventoryCategory( " << category->getName() + llinfos << "wearInventoryCategory( " << category->getName() << " )" << llendl; // What we do here is get the complete information on the items in @@ -1028,9 +1020,8 @@ void LLAppearanceManager::wearInventoryCategoryOnAvatar( LLInventoryCategory* ca // this up front to avoid having to deal with the case of multiple // wearables being dirty. if(!category) return; - llinfos << "BAP wearInventoryCategoryOnAvatar( " << category->getName() - << " )" << llendl; - lldebugs << "wearInventoryCategoryOnAvatar( " << category->getName() + + llinfos << "wearInventoryCategoryOnAvatar( " << category->getName() << " )" << llendl; if( gFloaterCustomize ) @@ -1311,6 +1302,9 @@ void LLAppearanceManager::onFirstFullyVisible() { // 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. + + llinfos << "avatar fully visible" << llendl; + static bool check_populate_my_outfits = true; if (check_populate_my_outfits && (LLInventoryModel::getIsFirstTimeInViewer2() -- cgit v1.2.3