diff --git a/indra/newview/cofmgr.cpp b/indra/newview/cofmgr.cpp index 3820517ae..3f633f81b 100644 --- a/indra/newview/cofmgr.cpp +++ b/indra/newview/cofmgr.cpp @@ -56,7 +56,7 @@ public: class LLCOFFetcher : public LLInventoryFetchDescendentsObserver { public: - LLCOFFetcher() {} + LLCOFFetcher(const LLUUID& cat_id) : LLInventoryFetchDescendentsObserver(cat_id) {} /*virtual*/ ~LLCOFFetcher() {} /*virtual*/ void done() @@ -216,12 +216,9 @@ void LLCOFMgr::fetchCOF() return; } - LLInventoryFetchDescendentsObserver::folder_ref_t fetchFolders; - fetchFolders.push_back(idCOF); - - LLCOFFetcher* pFetcher = new LLCOFFetcher(); - pFetcher->fetchDescendents(fetchFolders); - if (pFetcher->isEverythingComplete()) + LLCOFFetcher* pFetcher = new LLCOFFetcher(idCOF); + pFetcher->startFetch(); + if (pFetcher->isFinished()) pFetcher->done(); else gInventory.addObserver(pFetcher); diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 9fdb2bea4..651185c0a 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -2775,10 +2775,10 @@ bool LLFloaterCustomize::onSaveDialog(const LLSD& notification, const LLSD& resp } // fetch observer -class LLCurrentlyWorn : public LLInventoryFetchObserver +class LLCurrentlyWorn : public LLInventoryFetchItemsObserver { public: - LLCurrentlyWorn() {} + LLCurrentlyWorn(const uuid_vec_t& item_ids) : LLInventoryFetchItemsObserver(item_ids){} ~LLCurrentlyWorn() {} virtual void done() { /* no operation necessary */} }; @@ -2799,8 +2799,8 @@ void LLFloaterCustomize::fetchInventory() // Fire & forget. The mInventoryObserver will catch inventory // updates and correct the UI as necessary. - LLCurrentlyWorn worn; - worn.fetchItems(ids); + LLCurrentlyWorn worn(ids); + worn.startFetch(); } void LLFloaterCustomize::updateInventoryUI() diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 7cff25975..e81d1d183 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1877,13 +1877,17 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id, } //Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver +class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver { public: - LLRightClickInventoryFetchObserver() : + LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : + LLInventoryFetchItemsObserver(ids), mCopyItems(false) { }; - LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) : + LLRightClickInventoryFetchObserver(const uuid_vec_t& ids, + const LLUUID& cat_id, + bool copy_items) : + LLInventoryFetchItemsObserver(ids), mCatID(cat_id), mCopyItems(copy_items) { }; @@ -1907,7 +1911,11 @@ protected: class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver { public: - LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {} + LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids, + bool copy_items) : + LLInventoryFetchDescendentsObserver(ids), + mCopyItems(copy_items) + {} ~LLRightClickInventoryFetchDescendentsObserver() {} virtual void done(); protected: @@ -1918,7 +1926,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done() { // Avoid passing a NULL-ref as mCompleteFolders.front() down to // gInventory.collectDescendents() - if( mCompleteFolders.empty() ) + if( mComplete.empty() ) { llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; dec_busy_count(); @@ -1932,7 +1940,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done() // happen. LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mCompleteFolders.front(), + gInventory.collectDescendents(mComplete.front(), cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH); @@ -1941,7 +1949,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done() // This early causes a giant menu to get produced, and doesn't seem to be needed. if(!count) { - llwarns << "Nothing fetched in category " << mCompleteFolders.front() + llwarns << "Nothing fetched in category " << mComplete.front() << llendl; dec_busy_count(); gInventory.removeObserver(this); @@ -1956,7 +1964,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done() ids.push_back(item_array.get(i)->getUUID()); } - LLRightClickInventoryFetchObserver* outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems); + LLRightClickInventoryFetchObserver* outfit = new LLRightClickInventoryFetchObserver(ids, mComplete.front(), mCopyItems); // clean up, and remove this as an observer since the call to the // outfit could notify observers and throw us into an infinite @@ -1970,7 +1978,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done() inc_busy_count(); // do the fetch - outfit->fetchItems(ids); + outfit->startFetch(); outfit->done(); //Not interested in waiting and this will be right 99% of the time. //Uncomment the following code for laggy Inventory UI. /* if(outfit->isEverythingComplete()) @@ -2549,10 +2557,10 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mMenu = menu.getHandle(); sSelf = getHandle(); - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); - fetch->fetchDescendents(folders); + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE); + fetch->startFetch(); inc_busy_count(); - if(fetch->isEverythingComplete()) + if(fetch->isFinished()) { // everything is already here - call done. fetch->done(); @@ -4358,10 +4366,11 @@ struct LLWearableHoldingPattern */ // [/RLVa:KB] -class LLOutfitObserver : public LLInventoryFetchObserver +class LLOutfitObserver : public LLInventoryFetchItemsObserver { public: - LLOutfitObserver(const LLUUID& cat_id, bool copy_items, bool append) : + LLOutfitObserver(const uuid_vec_t& ids, const LLUUID& cat_id, bool copy_items, bool append) : + LLInventoryFetchItemsObserver(ids), mCatID(cat_id), mCopyItems(copy_items), mAppend(append) @@ -4490,7 +4499,7 @@ void LLOutfitObserver::done() class LLOutfitFetch : public LLInventoryFetchDescendentsObserver { public: - LLOutfitFetch(bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {} + LLOutfitFetch(const LLUUID& id, bool copy_items, bool append) : mCopyItems(copy_items), mAppend(append) {} ~LLOutfitFetch() {} virtual void done(); protected: @@ -4505,14 +4514,14 @@ void LLOutfitFetch::done() // happen. LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mCompleteFolders.front(), + gInventory.collectDescendents(mComplete.front(), cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH); S32 count = item_array.count(); if(!count) { - llwarns << "Nothing fetched in category " << mCompleteFolders.front() + llwarns << "Nothing fetched in category " << mComplete.front() << llendl; dec_busy_count(); gInventory.removeObserver(this); @@ -4520,14 +4529,15 @@ void LLOutfitFetch::done() return; } - LLOutfitObserver* outfit; - outfit = new LLOutfitObserver(mCompleteFolders.front(), mCopyItems, mAppend); uuid_vec_t ids; for(S32 i = 0; i < count; ++i) { ids.push_back(item_array.get(i)->getUUID()); } + LLOutfitObserver* outfit = new LLOutfitObserver(ids, mComplete.front(), mCopyItems, mAppend); + + // clean up, and remove this as an observer since the call to the // outfit could notify observers and throw us into an infinite // loop. @@ -4540,8 +4550,8 @@ void LLOutfitFetch::done() inc_busy_count(); // do the fetch - outfit->fetchItems(ids); - if(outfit->isEverythingComplete()) + outfit->startFetch(); + if(outfit->isFinished()) { // everything is already here - call done. outfit->done(); @@ -4610,13 +4620,10 @@ void wear_inventory_category(LLInventoryCategory* category, bool copy, bool appe // 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; - outfit = new LLOutfitFetch(copy, append); - LLInventoryFetchDescendentsObserver::folder_ref_t folders; - folders.push_back(category->getUUID()); - outfit->fetchDescendents(folders); + LLOutfitFetch* outfit = new LLOutfitFetch(category->getUUID(), copy, append); + outfit->startFetch(); inc_busy_count(); - if(outfit->isEverythingComplete()) + if(outfit->isFinished()) { // everything is already here - call done. outfit->done(); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ecccc891e..5b4dab172 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1365,7 +1365,7 @@ bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id) const //{ // known_descendents += items->count(); //} - return cat->fetchDescendents(); + return cat->fetch(); } void LLInventoryModel::cache( diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index e361015c7..5c67d5017 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -246,7 +246,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() { // category exists but has no children yet, fetch the descendants // for now, just request every time and rely on retry timer to throttle - if (cat->fetchDescendents()) + if (cat->fetch()) { mFetchTimer.reset(); mTimelyFetchPending = TRUE; diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index e9f8207af..887f0a474 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -40,7 +40,7 @@ #include "llfloater.h" #include "llfocusmgr.h" #include "llinventorybridge.h" -//#include "llinventoryfunctions.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llviewermessage.h" #include "llviewerwindow.h" @@ -58,7 +58,45 @@ const F32 LLInventoryFetchItemsObserver::FETCH_TIMER_EXPIRY = 60.0f; -void fetch_items_from_llsd(const LLSD& items_llsd); + +LLInventoryObserver::LLInventoryObserver() +{ +} + +// virtual +LLInventoryObserver::~LLInventoryObserver() +{ +} + +LLInventoryFetchObserver::LLInventoryFetchObserver(const LLUUID& id) +{ + mIDs.clear(); + if (id != LLUUID::null) + { + setFetchID(id); + } +} + +LLInventoryFetchObserver::LLInventoryFetchObserver(const uuid_vec_t& ids) +{ + setFetchIDs(ids); +} + +BOOL LLInventoryFetchObserver::isFinished() const +{ + return mIncomplete.empty(); +} + +void LLInventoryFetchObserver::setFetchIDs(const uuid_vec_t& ids) +{ + mIDs = ids; +} +void LLInventoryFetchObserver::setFetchID(const LLUUID& id) +{ + mIDs.clear(); + mIDs.push_back(id); +} + void LLInventoryCompletionObserver::changed(U32 mask) { @@ -74,7 +112,7 @@ void LLInventoryCompletionObserver::changed(U32 mask) it = mIncomplete.erase(it); continue; } - if(item->isComplete()) + if (item->isFinished()) { mComplete.push_back(*it); it = mIncomplete.erase(it); @@ -97,25 +135,18 @@ void LLInventoryCompletionObserver::watchItem(const LLUUID& id) } } -LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const LLUUID& item_id) +LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const LLUUID& item_id) : + LLInventoryFetchObserver(item_id) { mIDs.clear(); - if (item_id != LLUUID::null) - { - mIDs.push_back(item_id); - } + mIDs.push_back(item_id); } -LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const uuid_vec_t& item_ids) - : mIDs(item_ids) +LLInventoryFetchItemsObserver::LLInventoryFetchItemsObserver(const uuid_vec_t& item_ids) : + LLInventoryFetchObserver(item_ids) { } -BOOL LLInventoryFetchItemsObserver::isFinished() const -{ - return mIncomplete.empty(); -} - void LLInventoryFetchItemsObserver::changed(U32 mask) { lldebugs << this << " remaining incomplete " << mIncomplete.size() @@ -134,7 +165,7 @@ void LLInventoryFetchItemsObserver::changed(U32 mask) { const LLUUID& item_id = (*it); LLViewerInventoryItem* item = gInventory.getItem(item_id); - if (item && item->isComplete()) + if (item && item->isFinished()) { mComplete.push_back(item_id); it = mIncomplete.erase(it); @@ -167,97 +198,6 @@ void LLInventoryFetchItemsObserver::changed(U32 mask) //llinfos << "LLInventoryFetchItemsObserver::changed() mIncomplete size " << mIncomplete.size() << llendl; } -void LLInventoryFetchItemsObserver::startFetch() -{ - LLUUID owner_id; - LLSD items_llsd; - for (uuid_vec_t::const_iterator it = mIDs.begin(); it < mIDs.end(); ++it) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if (item) - { - if (item->isComplete()) - { - // It's complete, so put it on the complete container. - mComplete.push_back(*it); - continue; - } - else - { - owner_id = item->getPermissions().getOwner(); - } - } - else - { - // assume it's agent inventory. - owner_id = gAgent.getID(); - } - - // Ignore categories since they're not items. We - // could also just add this to mComplete but not sure what the - // side-effects would be, so ignoring to be safe. - LLViewerInventoryCategory* cat = gInventory.getCategory(*it); - if (cat) - { - continue; - } - - // It's incomplete, so put it on the incomplete container, and - // pack this on the message. - mIncomplete.push_back(*it); - - // Prepare the data to fetch - LLSD item_entry; - item_entry["owner_id"] = owner_id; - item_entry["item_id"] = (*it); - items_llsd.append(item_entry); - } - - mFetchingPeriod.reset(); - mFetchingPeriod.setTimerExpirySec(FETCH_TIMER_EXPIRY); - - fetch_items_from_llsd(items_llsd); -} - -void LLInventoryFetchObserver::changed(U32 mask) -{ - // scan through the incomplete items and move or erase them as - // appropriate. - if(!mIncomplete.empty()) - { - for(uuid_vec_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); ) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(!item) - { - // BUG: This can cause done() to get called prematurely below. - // This happens with the LLGestureInventoryFetchObserver that - // loads gestures at startup. JC - it = mIncomplete.erase(it); - continue; - } - if(item->isComplete()) - { - mComplete.push_back(*it); - it = mIncomplete.erase(it); - continue; - } - ++it; - } - if(mIncomplete.empty()) - { - done(); - } - } - //llinfos << "LLInventoryFetchObserver::changed() mComplete size " << mComplete.size() << llendl; - //llinfos << "LLInventoryFetchObserver::changed() mIncomplete size " << mIncomplete.size() << llendl; -} - -bool LLInventoryFetchObserver::isEverythingComplete() const -{ - return mIncomplete.empty(); -} - void fetch_items_from_llsd(const LLSD& items_llsd) { if (!items_llsd.size() || gDisconnected) return; @@ -328,17 +268,16 @@ void fetch_items_from_llsd(const LLSD& items_llsd) } } -void LLInventoryFetchObserver::fetchItems( - const uuid_vec_t& ids) +void LLInventoryFetchItemsObserver::startFetch() { LLUUID owner_id; LLSD items_llsd; - for(uuid_vec_t::const_iterator it = ids.begin(); it < ids.end(); ++it) + for (uuid_vec_t::const_iterator it = mIDs.begin(); it < mIDs.end(); ++it) { LLViewerInventoryItem* item = gInventory.getItem(*it); - if(item) + if (item) { - if(item->isComplete()) + if (item->isFinished()) { // It's complete, so put it on the complete container. mComplete.push_back(*it); @@ -354,206 +293,174 @@ void LLInventoryFetchObserver::fetchItems( // assume it's agent inventory. owner_id = gAgent.getID(); } - + + // Ignore categories since they're not items. We + // could also just add this to mComplete but not sure what the + // side-effects would be, so ignoring to be safe. + LLViewerInventoryCategory* cat = gInventory.getCategory(*it); + if (cat) + { + continue; + } + // It's incomplete, so put it on the incomplete container, and // pack this on the message. mIncomplete.push_back(*it); - + // Prepare the data to fetch LLSD item_entry; item_entry["owner_id"] = owner_id; item_entry["item_id"] = (*it); items_llsd.append(item_entry); } + + mFetchingPeriod.reset(); + mFetchingPeriod.setTimerExpirySec(FETCH_TIMER_EXPIRY); + fetch_items_from_llsd(items_llsd); } + +LLInventoryFetchDescendentsObserver::LLInventoryFetchDescendentsObserver(const LLUUID& cat_id) : + LLInventoryFetchObserver(cat_id) +{ +} + +LLInventoryFetchDescendentsObserver::LLInventoryFetchDescendentsObserver(const uuid_vec_t& cat_ids) : + LLInventoryFetchObserver(cat_ids) +{ +} + // virtual void LLInventoryFetchDescendentsObserver::changed(U32 mask) { - for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();) + for (uuid_vec_t::iterator it = mIncomplete.begin(); it < mIncomplete.end();) { LLViewerInventoryCategory* cat = gInventory.getCategory(*it); if(!cat) { - it = mIncompleteFolders.erase(it); + it = mIncomplete.erase(it); continue; } - if(isComplete(cat)) + if (isCategoryComplete(cat)) { - mCompleteFolders.push_back(*it); - it = mIncompleteFolders.erase(it); + mComplete.push_back(*it); + it = mIncomplete.erase(it); continue; } ++it; } - if(mIncompleteFolders.empty()) + if (mIncomplete.empty()) { done(); } } -void LLInventoryFetchDescendentsObserver::fetchDescendents( - const folder_ref_t& ids) +void LLInventoryFetchDescendentsObserver::startFetch() { - for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + for (uuid_vec_t::const_iterator it = mIDs.begin(); it != mIDs.end(); ++it) { LLViewerInventoryCategory* cat = gInventory.getCategory(*it); - if(!cat) continue; - if(!isComplete(cat)) + if (!cat) continue; + if (!isCategoryComplete(cat)) { - cat->fetchDescendents(); //blindly fetch it without seeing if anything else is fetching it. - mIncompleteFolders.push_back(*it); //Add to list of things being downloaded for this observer. + cat->fetch(); //blindly fetch it without seeing if anything else is fetching it. + mIncomplete.push_back(*it); //Add to list of things being downloaded for this observer. } else { - mCompleteFolders.push_back(*it); + mComplete.push_back(*it); } } } -bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const +BOOL LLInventoryFetchDescendentsObserver::isCategoryComplete(const LLViewerInventoryCategory* cat) const { - return mIncompleteFolders.empty(); -} - -bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat) -{ - S32 version = cat->getVersion(); - S32 descendents = cat->getDescendentCount(); - if((LLViewerInventoryCategory::VERSION_UNKNOWN == version) - || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents)) + const S32 version = cat->getVersion(); + const S32 expected_num_descendents = cat->getDescendentCount(); + if ((version == LLViewerInventoryCategory::VERSION_UNKNOWN) || + (expected_num_descendents == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)) { - return false; + return FALSE; } // it might be complete - check known descendents against // currently available. LLInventoryModel::cat_array_t* cats; LLInventoryModel::item_array_t* items; gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items); - if(!cats || !items) + if (!cats || !items) { - // bit of a hack - pretend we're done if they are gone or - // incomplete. should never know, but it would suck if this - // kept tight looping because of a corrupt memory state. - return true; + llwarns << "Category '" << cat->getName() << "' descendents corrupted, fetch failed." << llendl; + // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean + // that the cat just doesn't have any items or subfolders). + // Unrecoverable, so just return done so that this observer can be cleared + // from memory. + return TRUE; } - S32 known = cats->count() + items->count(); - if(descendents == known) + const S32 current_num_known_descendents = cats->count() + items->count(); + + // Got the number of descendents that we were expecting, so we're done. + if (current_num_known_descendents == expected_num_descendents) { - // hey - we're done. - return true; + return TRUE; } - return false; + + // Error condition, but recoverable. This happens if something was added to the + // category before it was initialized, so accountForUpdate didn't update descendent + // count and thus the category thinks it has fewer descendents than it actually has. + if (current_num_known_descendents >= expected_num_descendents) + { + llwarns << "Category '" << cat->getName() << "' expected descendentcount:" << expected_num_descendents << " descendents but got descendentcount:" << current_num_known_descendents << llendl; + const_cast(cat)->setDescendentCount(current_num_known_descendents); + return TRUE; + } + return FALSE; +} + +LLInventoryFetchComboObserver::LLInventoryFetchComboObserver(const uuid_vec_t& folder_ids, + const uuid_vec_t& item_ids) +{ + mFetchDescendents = new LLInventoryFetchDescendentsObserver(folder_ids); + + uuid_vec_t pruned_item_ids; + for (uuid_vec_t::const_iterator item_iter = item_ids.begin(); + item_iter != item_ids.end(); + ++item_iter) + { + const LLUUID& item_id = (*item_iter); + const LLViewerInventoryItem* item = gInventory.getItem(item_id); + if (item && std::find(folder_ids.begin(), folder_ids.end(), item->getParentUUID()) == folder_ids.end()) + { + continue; + } + pruned_item_ids.push_back(item_id); + } + + mFetchItems = new LLInventoryFetchItemsObserver(pruned_item_ids); + mFetchDescendents = new LLInventoryFetchDescendentsObserver(folder_ids); +} + +LLInventoryFetchComboObserver::~LLInventoryFetchComboObserver() +{ + mFetchItems->done(); + mFetchDescendents->done(); + delete mFetchItems; + delete mFetchDescendents; } void LLInventoryFetchComboObserver::changed(U32 mask) { - if(!mIncompleteItems.empty()) + mFetchItems->changed(mask); + mFetchDescendents->changed(mask); + if (mFetchItems->isFinished() && mFetchDescendents->isFinished()) { - for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); ) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if(!item) - { - it = mIncompleteItems.erase(it); - continue; - } - if(item->isComplete()) - { - mCompleteItems.push_back(*it); - it = mIncompleteItems.erase(it); - continue; - } - ++it; - } - } - if(!mIncompleteFolders.empty()) - { - for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();) - { - LLViewerInventoryCategory* cat = gInventory.getCategory(*it); - if(!cat) - { - it = mIncompleteFolders.erase(it); - continue; - } - if(gInventory.isCategoryComplete(*it)) - { - mCompleteFolders.push_back(*it); - it = mIncompleteFolders.erase(it); - continue; - } - ++it; - } - } - if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty()) - { - mDone = true; done(); } } -void LLInventoryFetchComboObserver::fetch( - const folder_ref_t& folder_ids, - const item_ref_t& item_ids) +void LLInventoryFetchComboObserver::startFetch() { - lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl; - for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit) - { - LLViewerInventoryCategory* cat = gInventory.getCategory(*fit); - if(!cat) continue; - if(!gInventory.isCategoryComplete(*fit)) - { - cat->fetchDescendents(); - lldebugs << "fetching folder " << *fit <isComplete()) - { - // It's complete, so put it on the complete container. - mCompleteItems.push_back(*iit); - lldebugs << "completing item " << *iit << llendl; - continue; - } - else - { - mIncompleteItems.push_back(*iit); - owner_id = item->getPermissions().getOwner(); - } - if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end()) - { - LLSD item_entry; - item_entry["owner_id"] = owner_id; - item_entry["item_id"] = (*iit); - items_llsd.append(item_entry); - } - else - { - lldebugs << "not worrying about " << *iit << llendl; - } - } - fetch_items_from_llsd(items_llsd); + mFetchItems->startFetch(); + mFetchDescendents->startFetch(); } void LLInventoryExistenceObserver::watchItem(const LLUUID& id) @@ -587,13 +494,83 @@ void LLInventoryExistenceObserver::changed(U32 mask) } } } -void LLInventoryAddedObserver::changed(U32 mask) + +void LLInventoryAddItemByAssetObserver::changed(U32 mask) { if(!(mask & LLInventoryObserver::ADD)) { return; } + // nothing is watched + if (mWatchedAssets.size() == 0) + { + return; + } + + LLMessageSystem* msg = gMessageSystem; + if (!(msg->getMessageName() && (0 == strcmp(msg->getMessageName(), "UpdateCreateInventoryItem")))) + { + // this is not our message + return; // to prevent a crash. EXT-7921; + } + + LLPointer item = new LLViewerInventoryItem; + S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); + for(S32 i = 0; i < num_blocks; ++i) + { + item->unpackMessage(msg, _PREHASH_InventoryData, i); + const LLUUID& asset_uuid = item->getAssetUUID(); + if (item->getUUID().notNull() && asset_uuid.notNull()) + { + if (isAssetWatched(asset_uuid)) + { + LL_DEBUGS("Inventory_Move") << "Found asset UUID: " << asset_uuid << LL_ENDL; + mAddedItems.push_back(item->getUUID()); + } + } + } + + if (mAddedItems.size() == mWatchedAssets.size()) + { + done(); + LL_DEBUGS("Inventory_Move") << "All watched items are added & processed." << LL_ENDL; + mAddedItems.clear(); + + // Unable to clean watched items here due to somebody can require to check them in current frame. + // set dirty state to clean them while next watch cycle. + mIsDirty = true; + } +} + +void LLInventoryAddItemByAssetObserver::watchAsset(const LLUUID& asset_id) +{ + if(asset_id.notNull()) + { + if (mIsDirty) + { + LL_DEBUGS("Inventory_Move") << "Watched items are dirty. Clean them." << LL_ENDL; + mWatchedAssets.clear(); + mIsDirty = false; + } + + mWatchedAssets.push_back(asset_id); + onAssetAdded(asset_id); + } +} + +bool LLInventoryAddItemByAssetObserver::isAssetWatched( const LLUUID& asset_id ) +{ + return std::find(mWatchedAssets.begin(), mWatchedAssets.end(), asset_id) != mWatchedAssets.end(); +} + +void LLInventoryAddedObserver::changed(U32 mask) +{ + if (!(mask & LLInventoryObserver::ADD)) + { + return; + } + // *HACK: If this was in response to a packet off // the network, figure out which item was updated. LLMessageSystem* msg = gMessageSystem; @@ -627,6 +604,34 @@ void LLInventoryAddedObserver::changed(U32 mask) } } +void LLInventoryCategoryAddedObserver::changed(U32 mask) +{ + if (!(mask & LLInventoryObserver::ADD)) + { + return; + } + + const LLInventoryModel::changed_items_t& changed_ids = gInventory.getChangedIDs(); + + for (LLInventoryModel::changed_items_t::const_iterator cit = changed_ids.begin(); cit != changed_ids.end(); ++cit) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(*cit); + + if (cat) + { + mAddedCategories.push_back(cat); + } + } + + if (!mAddedCategories.empty()) + { + done(); + + mAddedCategories.clear(); + } +} + + LLInventoryTransactionObserver::LLInventoryTransactionObserver(const LLTransactionID& transaction_id) : mTransactionID(transaction_id) { @@ -676,4 +681,140 @@ void LLInventoryTransactionObserver::changed(U32 mask) } } } -} \ No newline at end of file +} + +void LLInventoryCategoriesObserver::changed(U32 mask) +{ + if (!mCategoryMap.size()) + return; + + for (category_map_t::iterator iter = mCategoryMap.begin(); + iter != mCategoryMap.end(); + ++iter) + { + const LLUUID& cat_id = (*iter).first; + + LLViewerInventoryCategory* category = gInventory.getCategory(cat_id); + if (!category) + continue; + + const S32 version = category->getVersion(); + const S32 expected_num_descendents = category->getDescendentCount(); + if ((version == LLViewerInventoryCategory::VERSION_UNKNOWN) || + (expected_num_descendents == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)) + { + continue; + } + + // Check number of known descendents to find out whether it has changed. + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat_id, cats, items); + if (!cats || !items) + { + llwarns << "Category '" << category->getName() << "' descendents corrupted, fetch failed." << llendl; + // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean + // that the cat just doesn't have any items or subfolders). + // Unrecoverable, so just skip this category. + + llassert(cats != NULL && items != NULL); + + continue; + } + + const S32 current_num_known_descendents = cats->count() + items->count(); + + LLCategoryData& cat_data = (*iter).second; + + bool cat_changed = false; + + // If category version or descendents count has changed + // update category data in mCategoryMap + if (version != cat_data.mVersion || current_num_known_descendents != cat_data.mDescendentsCount) + { + cat_data.mVersion = version; + cat_data.mDescendentsCount = current_num_known_descendents; + cat_changed = true; + } + + // If any item names have changed, update the name hash + // Only need to check if (a) name hash has not previously been + // computed, or (b) a name has changed. + if (!cat_data.mIsNameHashInitialized || (mask & LLInventoryObserver::LABEL)) + { + LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id); + if (cat_data.mItemNameHash != item_name_hash) + { + cat_data.mIsNameHashInitialized = true; + cat_data.mItemNameHash = item_name_hash; + cat_changed = true; + } + } + + // If anything has changed above, fire the callback. + if (cat_changed) + cat_data.mCallback(); + } +} + +bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb) +{ + S32 version = LLViewerInventoryCategory::VERSION_UNKNOWN; + S32 current_num_known_descendents = LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN; + bool can_be_added = true; + + LLViewerInventoryCategory* category = gInventory.getCategory(cat_id); + // If category could not be retrieved it might mean that + // inventory is unusable at the moment so the category is + // stored with VERSION_UNKNOWN and DESCENDENT_COUNT_UNKNOWN, + // it may be updated later. + if (category) + { + // Inventory category version is used to find out if some changes + // to a category have been made. + version = category->getVersion(); + + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat_id, cats, items); + if (!cats || !items) + { + llwarns << "Category '" << category->getName() << "' descendents corrupted, fetch failed." << llendl; + // NULL means the call failed -- cats/items map doesn't exist (note: this does NOT mean + // that the cat just doesn't have any items or subfolders). + // Unrecoverable, so just return "false" meaning that the category can't be observed. + can_be_added = false; + + llassert(cats != NULL && items != NULL); + } + else + { + current_num_known_descendents = cats->count() + items->count(); + } + } + + if (can_be_added) + { + mCategoryMap.insert(category_map_value_t( + cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents))); + } + + return can_be_added; +} + +void LLInventoryCategoriesObserver::removeCategory(const LLUUID& cat_id) +{ + mCategoryMap.erase(cat_id); +} + +LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData( + const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents) + + : mCatID(cat_id) + , mCallback(cb) + , mVersion(version) + , mDescendentsCount(num_descendents) + , mIsNameHashInitialized(false) +{ + mItemNameHash.finalize(); +} diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index e07beabd4..bf45db43d 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -58,49 +58,48 @@ public: GESTURE = 64, ALL = 0xffffffff }; - virtual ~LLInventoryObserver() {}; + LLInventoryObserver(); + virtual ~LLInventoryObserver(); virtual void changed(U32 mask) = 0; }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryFetchObserver // -// This class is much like the LLInventoryCompletionObserver, except -// that it handles all the the fetching necessary. Override the done() -// method to do the thing you want. +// Abstract class to handle fetching items, folders, etc. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - class LLInventoryFetchObserver : public LLInventoryObserver { public: - LLInventoryFetchObserver() {} - virtual void changed(U32 mask); - - bool isEverythingComplete() const; - void fetchItems(const uuid_vec_t& ids); - virtual void done() = 0; - -protected: - uuid_vec_t mComplete; - uuid_vec_t mIncomplete; -}; - -class LLInventoryFetchItemsObserver : public LLInventoryObserver -{ -public: - LLInventoryFetchItemsObserver(const LLUUID& item_id = LLUUID::null); - LLInventoryFetchItemsObserver(const uuid_vec_t& item_ids); + LLInventoryFetchObserver(const LLUUID& id = LLUUID::null); // single item + LLInventoryFetchObserver(const uuid_vec_t& ids); // multiple items + void setFetchID(const LLUUID& id); + void setFetchIDs(const uuid_vec_t& ids); BOOL isFinished() const; - virtual void startFetch(); - virtual void changed(U32 mask); + virtual void startFetch() = 0; + virtual void changed(U32 mask) = 0; virtual void done() {}; protected: uuid_vec_t mComplete; uuid_vec_t mIncomplete; uuid_vec_t mIDs; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryFetchItemsObserver +// +// Fetches inventory items, calls done() when all inventory has arrived. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryFetchItemsObserver : public LLInventoryFetchObserver +{ +public: + LLInventoryFetchItemsObserver(const LLUUID& item_id = LLUUID::null); + LLInventoryFetchItemsObserver(const uuid_vec_t& item_ids); + + /*virtual*/ void startFetch(); + /*virtual*/ void changed(U32 mask); private: LLTimer mFetchingPeriod; @@ -113,120 +112,147 @@ private: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryFetchDescendentsObserver // -// This class is much like the LLInventoryCompletionObserver, except -// that it handles fetching based on category. Override the done() -// method to do the thing you want. +// Fetches children of a category/folder, calls done() when all +// inventory has arrived. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryFetchDescendentsObserver : public LLInventoryObserver +class LLInventoryFetchDescendentsObserver : public LLInventoryFetchObserver { public: - LLInventoryFetchDescendentsObserver() {} - virtual void changed(U32 mask); - - typedef std::vector folder_ref_t; - void fetchDescendents(const folder_ref_t& ids); - bool isEverythingComplete() const; - virtual void done() = 0; + LLInventoryFetchDescendentsObserver(const LLUUID& cat_id = LLUUID::null); + LLInventoryFetchDescendentsObserver(const uuid_vec_t& cat_ids); + /*virtual*/ void startFetch(); + /*virtual*/ void changed(U32 mask); protected: - bool isComplete(LLViewerInventoryCategory* cat); - folder_ref_t mIncompleteFolders; - folder_ref_t mCompleteFolders; + BOOL isCategoryComplete(const LLViewerInventoryCategory* cat) const; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryFetchComboObserver // -// This class does an appropriate combination of fetch descendents and -// item fetches based on completion of categories and items. Much like -// the fetch and fetch descendents, this will call done() when everything -// has arrived. +// Does an appropriate combination of fetch descendents and +// item fetches based on completion of categories and items. This is optimized +// to not fetch item_ids that are descendents of any of the folder_ids. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLInventoryFetchComboObserver : public LLInventoryObserver { public: - LLInventoryFetchComboObserver() : mDone(false) {} - virtual void changed(U32 mask); - - typedef std::vector folder_ref_t; - typedef std::vector item_ref_t; - void fetch(const folder_ref_t& folder_ids, const item_ref_t& item_ids); + LLInventoryFetchComboObserver(const uuid_vec_t& folder_ids, + const uuid_vec_t& item_ids); + ~LLInventoryFetchComboObserver(); + /*virtual*/ void changed(U32 mask); + void startFetch(); virtual void done() = 0; - protected: - bool mDone; - folder_ref_t mCompleteFolders; - folder_ref_t mIncompleteFolders; - item_ref_t mCompleteItems; - item_ref_t mIncompleteItems; + LLInventoryFetchItemsObserver *mFetchItems; + LLInventoryFetchDescendentsObserver *mFetchDescendents; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryExistenceObserver // -// This class is used as a base class for doing somethign when all the -// observed item ids exist in the inventory somewhere. You can derive -// a class from this class and implement the done() method to do -// something useful. +// Used as a base class for doing something when all the +// observed item ids exist in the inventory somewhere. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - class LLInventoryExistenceObserver : public LLInventoryObserver { public: LLInventoryExistenceObserver() {} - virtual void changed(U32 mask); + /*virtual*/ void changed(U32 mask); void watchItem(const LLUUID& id); - protected: virtual void done() = 0; - uuid_vec_t mExist; uuid_vec_t mMIA; }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryMovedObserver +// +// This class is used as a base class for doing something when all the +// item for observed asset ids were added into the inventory. +// Derive a class from this class and implement the done() method to do +// something useful. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLInventoryAddItemByAssetObserver : public LLInventoryObserver +{ +public: + LLInventoryAddItemByAssetObserver() : mIsDirty(false) {} + virtual void changed(U32 mask); + + void watchAsset(const LLUUID& asset_id); + bool isAssetWatched(const LLUUID& asset_id); + +protected: + virtual void onAssetAdded(const LLUUID& asset_id) {} + virtual void done() = 0; + + typedef std::vector item_ref_t; + item_ref_t mAddedItems; + item_ref_t mWatchedAssets; + +private: + bool mIsDirty; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryAddedObserver // -// This class is used as a base class for doing something when -// a new item arrives in inventory. -// It does not watch for a certain UUID, rather it acts when anything is added -// Derive a class from this class and implement the done() method to do -// something useful. +// Base class for doing something when a new item arrives in inventory. +// It does not watch for a certain UUID, rather it acts when anything is added //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLInventoryAddedObserver : public LLInventoryObserver { public: LLInventoryAddedObserver() : mAdded() {} - virtual void changed(U32 mask); + /*virtual*/ void changed(U32 mask); protected: virtual void done() = 0; - typedef std::vector item_ref_t; - item_ref_t mAdded; + uuid_vec_t mAdded; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryCategoryAddedObserver +// +// Base class for doing something when a new category is created in the +// inventory. +// It does not watch for a certain UUID, rather it acts when anything is added +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryCategoryAddedObserver : public LLInventoryObserver +{ +public: + + typedef std::vector cat_vec_t; + + LLInventoryCategoryAddedObserver() : mAddedCategories() {} + /*virtual*/ void changed(U32 mask); + +protected: + virtual void done() = 0; + + cat_vec_t mAddedCategories; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryTransactionObserver // -// Class which can be used as a base class for doing something when an -// inventory transaction completes. -// -// *NOTE: This class is not quite complete. Avoid using unless you fix up it's -// functionality gaps. +// Base class for doing something when an inventory transaction completes. +// NOTE: This class is not quite complete. Avoid using unless you fix up its +// functionality gaps. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - class LLInventoryTransactionObserver : public LLInventoryObserver { public: LLInventoryTransactionObserver(const LLTransactionID& transaction_id); - virtual void changed(U32 mask); + /*virtual*/ void changed(U32 mask); protected: - typedef std::vector folder_ref_t; - typedef std::vector item_ref_t; - virtual void done(const folder_ref_t& folders, const item_ref_t& items) = 0; + virtual void done(const uuid_vec_t& folders, const uuid_vec_t& items) = 0; LLTransactionID mTransactionID; }; @@ -234,17 +260,16 @@ protected: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryCompletionObserver // -// Class which can be used as a base class for doing something when -// when all observed items are locally complete. This class implements -// the changed() method of LLInventoryObserver and declares a new -// method named done() which is called when all watched items have -// complete information in the inventory model. +// Base class for doing something when when all observed items are locally +// complete. Implements the changed() method of LLInventoryObserver +// and declares a new method named done() which is called when all watched items +// have complete information in the inventory model. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLInventoryCompletionObserver : public LLInventoryObserver { public: LLInventoryCompletionObserver() {} - virtual void changed(U32 mask); + /*virtual*/ void changed(U32 mask); void watchItem(const LLUUID& id); @@ -255,4 +280,47 @@ protected: uuid_vec_t mIncomplete; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryCategoriesObserver +// +// This class is used for monitoring a list of inventory categories +// and firing a callback when there are changes in any of them. +// Categories are identified by their UUIDs. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryCategoriesObserver : public LLInventoryObserver +{ +public: + typedef boost::function callback_t; + + LLInventoryCategoriesObserver() {}; + virtual void changed(U32 mask); + + /** + * Add cat_id to the list of observed categories with a + * callback fired on category being changed. + * + * @return "true" if category was added, "false" if it could + * not be found. + */ + bool addCategory(const LLUUID& cat_id, callback_t cb); + void removeCategory(const LLUUID& cat_id); + +protected: + struct LLCategoryData + { + LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents); + + callback_t mCallback; + S32 mVersion; + S32 mDescendentsCount; + LLMD5 mItemNameHash; + bool mIsNameHashInitialized; + LLUUID mCatID; + }; + + typedef std::map category_map_t; + typedef category_map_t::value_type category_map_value_t; + + category_map_t mCategoryMap; +}; #endif // LL_LLINVENTORYOBSERVERS_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index f940ca151..6a47c0dce 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -323,10 +323,10 @@ namespace }; } -class LLGestureInventoryFetchObserver : public LLInventoryFetchObserver +class LLGestureInventoryFetchObserver : public LLInventoryFetchItemsObserver { public: - LLGestureInventoryFetchObserver() {} + LLGestureInventoryFetchObserver(const uuid_vec_t& item_ids) : LLInventoryFetchItemsObserver(item_ids) {} virtual void done() { // we've downloaded all the items, so repaint the dialog @@ -2690,8 +2690,7 @@ bool idle_startup() } } - LLGestureInventoryFetchObserver* fetch = new LLGestureInventoryFetchObserver(); - fetch->fetchItems(item_ids); + LLGestureInventoryFetchObserver* fetch = new LLGestureInventoryFetchObserver(item_ids); // deletes itself when done gInventory.addObserver(fetch); } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 9826c9e78..267c838ec 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1337,20 +1337,6 @@ void LLTextureCtrl::closeFloater() } } -// Allow us to download textures quickly when floater is shown -class LLTextureFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver -{ -public: - virtual void done() - { - // We need to find textures in all folders, so get the main - // background download going. - LLInventoryModelBackgroundFetch::instance().start(); - gInventory.removeObserver(this); - delete this; - } -}; - BOOL LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask) { getWindow()->setCursor(UI_CURSOR_HAND); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 42ffd4a6b..c4967c2e9 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -190,10 +190,16 @@ bool LLDropCopyableItems::operator()( return allowed; } +// Starts a fetch on folders and items. This is really not used +// as an observer in the traditional sense; we're just using it to +// request a fetch and we don't care about when/if the response arrives. class LLCategoryFireAndForget : public LLInventoryFetchComboObserver { public: - LLCategoryFireAndForget() {} + LLCategoryFireAndForget(const uuid_vec_t& folder_ids, + const uuid_vec_t& item_ids) : + LLInventoryFetchComboObserver(folder_ids, item_ids) + {} ~LLCategoryFireAndForget() {} virtual void done() { @@ -202,11 +208,13 @@ public: } }; -class LLCategoryDropObserver : public LLInventoryFetchObserver +class LLCategoryDropObserver : public LLInventoryFetchItemsObserver { public: LLCategoryDropObserver( + const uuid_vec_t& ids, const LLUUID& obj_id, LLToolDragAndDrop::ESource src) : + LLInventoryFetchItemsObserver(ids), mObjectID(obj_id), mSource(src) {} @@ -243,7 +251,7 @@ void LLCategoryDropObserver::done() } delete this; } - +/* Doesn't seem to be used anymore. class LLCategoryDropDescendentsObserver : public LLInventoryFetchDescendentsObserver { public: @@ -264,8 +272,8 @@ void LLCategoryDropDescendentsObserver::done() { gInventory.removeObserver(this); - folder_ref_t::iterator it = mCompleteFolders.begin(); - folder_ref_t::iterator end = mCompleteFolders.end(); + uuid_vec_t::iterator it = mComplete.begin(); + uuid_vec_t::iterator end = mComplete.end(); LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; for(; it != end; ++it) @@ -302,6 +310,7 @@ void LLCategoryDropDescendentsObserver::done() } delete this; } +*/ // This array is used to more easily control what happens when a 3d // drag and drop event occurs. Since there's an array of drop target @@ -522,8 +531,9 @@ void LLToolDragAndDrop::beginDrag(EDragAndDropType type, } if(!folder_ids.empty() || !item_ids.empty()) { - LLCategoryFireAndForget fetcher; - fetcher.fetch(folder_ids, item_ids); + LLCategoryFireAndForget *fetcher = new LLCategoryFireAndForget(folder_ids, item_ids); + fetcher->startFetch(); + delete fetcher; } } } @@ -531,7 +541,7 @@ void LLToolDragAndDrop::beginDrag(EDragAndDropType type, void LLToolDragAndDrop::beginMultiDrag( const std::vector types, - const std::vector& cargo_ids, + const uuid_vec_t& cargo_ids, ESource source, const LLUUID& source_id) { @@ -592,8 +602,7 @@ void LLToolDragAndDrop::beginMultiDrag( uuid_vec_t item_ids; std::back_insert_iterator copier(folder_ids); std::copy(cat_ids.begin(), cat_ids.end(), copier); - LLCategoryFireAndForget fetcher; - fetcher.fetch(folder_ids, item_ids); + LLCategoryFireAndForget fetcher(folder_ids, item_ids); } } } @@ -1256,7 +1265,7 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return; + if (!item || !item->isFinished()) return; if (regionp && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)) @@ -1289,9 +1298,8 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, // Check if it's in the trash. bool is_in_trash = false; - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { is_in_trash = true; remove_from_inventory = TRUE; @@ -1509,8 +1517,8 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL // HACK: downcast LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item; // - //if(!vitem->isComplete()) return ACCEPT_NO; - if(!vitem->isComplete() && !(gInventory.isObjectDescendentOf(vitem->getUUID(), gSystemFolderRoot))) return ACCEPT_NO; + //if(!vitem->isFinished()) return ACCEPT_NO; + if(!vitem->isFinished() && !(gInventory.isObjectDescendentOf(vitem->getUUID(), gSystemFolderRoot))) return ACCEPT_NO; // if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links @@ -1527,7 +1535,7 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL // gAgent.getGroupID()) // && (obj->mPermModify || obj->mFlagAllowInventoryAdd)); BOOL worn = FALSE; - LLVOAvatar* my_avatar = NULL; + LLVOAvatarSelf* my_avatar = NULL; switch(item->getType()) { case LLAssetType::AT_OBJECT: @@ -1691,10 +1699,10 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; // must not be in the trash - LLUUID trash_id(gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) { return ACCEPT_NO; @@ -1768,7 +1776,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; // //LLVOAvatar* my_avatar = gAgentAvatarp; @@ -1804,8 +1812,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( } // Check if it's in the trash. - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { accept = ACCEPT_YES_SINGLE; @@ -1845,7 +1852,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if(!item || !item->isFinished()) return ACCEPT_NO; // //LLVOAvatar* my_avatar = gAgentAvatarp; //if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) @@ -1897,8 +1904,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( } // Check if it's in the trash. - LLUUID trash_id; - trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) { accept = ACCEPT_YES_SINGLE; @@ -1928,7 +1934,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezScript( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; EAcceptance rv = willObjectAcceptInventory(obj, item); if(drop && (ACCEPT_YES_SINGLE <= rv)) { @@ -1971,8 +1977,8 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject( LLViewerInventoryCategory* cat; locateInventory(item, cat); // - //if(!item || !item->isComplete()) return ACCEPT_NO; - if( !item || (!item->isComplete() && !(gInventory.isObjectDescendentOf(item->getUUID(), gSystemFolderRoot))) ) return ACCEPT_NO; + //if(!item || !item->isFinished()) return ACCEPT_NO; + if( !item || (!item->isFinished() && !(gInventory.isObjectDescendentOf(item->getUUID(), gSystemFolderRoot))) ) return ACCEPT_NO; // EAcceptance rv = willObjectAcceptInventory(obj, item); if((mask & MASK_CONTROL)) @@ -2003,6 +2009,7 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject( { dropTextureOneFace(obj, face, item, mSource, mSourceID); } + // VEFFECT: SetTexture LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); @@ -2038,7 +2045,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if(!item || !item->isFinished()) return ACCEPT_NO; if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) { @@ -2100,7 +2107,7 @@ EAcceptance LLToolDragAndDrop::dad3dActivateGesture( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) { @@ -2164,7 +2171,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory( if(mSource == SOURCE_AGENT) { - LLUUID trash_id(gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)); + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); if( gInventory.isObjectDescendentOf( category->getUUID(), trash_id ) ) { return ACCEPT_NO; @@ -2208,7 +2215,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventory( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; LLViewerObject* root_object = obj; if (obj && obj->getParent()) { @@ -2237,24 +2244,30 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { lldebugs << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << llendl; - if (NULL==obj) + if (obj == NULL) { llwarns << "obj is NULL; aborting func with ACCEPT_NO" << llendl; return ACCEPT_NO; } - if (mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY) + if ((mSource != SOURCE_AGENT) && (mSource != SOURCE_LIBRARY)) { return ACCEPT_NO; } - if(obj->isAttachment()) return ACCEPT_NO_LOCKED; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if(!cat) return ACCEPT_NO; - EAcceptance rv = ACCEPT_NO; + if (obj->isAttachment()) + { + return ACCEPT_NO_LOCKED; + } - // find all the items in the category + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; + locateInventory(item, cat); + if (!cat) + { + return ACCEPT_NO; + } + + // Find all the items in the category LLDroppableItem droppable(!obj->permYouOwner()); LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -2278,29 +2291,40 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( } } + EAcceptance rv = ACCEPT_NO; + // Check for accept - S32 i; - S32 count = cats.count(); - for(i = 0; i < count; ++i) + for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); + cat_iter != cats.end(); + ++cat_iter) { - rv = gInventory.isCategoryComplete(cats.get(i)->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO; + const LLViewerInventoryCategory *cat = (*cat_iter); + rv = gInventory.isCategoryComplete(cat->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO; if(rv < ACCEPT_YES_SINGLE) { - lldebugs << "Category " << cats.get(i)->getUUID() - << "is not complete." << llendl; + lldebugs << "Category " << cat->getUUID() << "is not complete." << llendl; break; } } - if(ACCEPT_YES_COPY_SINGLE <= rv) + if (ACCEPT_YES_COPY_SINGLE <= rv) { - count = items.count(); - for(i = 0; i < count; ++i) + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) { - rv = willObjectAcceptInventory(root_object, items.get(i)); - if(rv < ACCEPT_YES_COPY_SINGLE) + LLViewerInventoryItem *item = (*item_iter); + /* + // Pass the base objects, not the links. + if (item && item->getIsLinkType()) { - lldebugs << "Object will not accept " - << items.get(i)->getUUID() << llendl; + item = item->getLinkedItem(); + (*item_iter) = item; + } + */ + rv = willObjectAcceptInventory(root_object, item); + if (rv < ACCEPT_YES_COPY_SINGLE) + { + lldebugs << "Object will not accept " << item->getUUID() << llendl; break; } } @@ -2309,17 +2333,17 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( // if every item is accepted, go ahead and send it on. if(drop && (ACCEPT_YES_COPY_SINGLE <= rv)) { - S32 count = items.count(); uuid_vec_t ids; - for(i = 0; i < count; ++i) + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) { - //dropInventory(root_object, items.get(i), mSource, mSourceID); - ids.push_back(items.get(i)->getUUID()); + const LLViewerInventoryItem *item = (*item_iter); + ids.push_back(item->getUUID()); } - LLCategoryDropObserver* dropper; - dropper = new LLCategoryDropObserver(obj->getID(), mSource); - dropper->fetchItems(ids); - if(dropper->isEverythingComplete()) + LLCategoryDropObserver* dropper = new LLCategoryDropObserver(ids, obj->getID(), mSource); + dropper->startFetch(); + if (dropper->isFinished()) { dropper->done(); } @@ -2350,13 +2374,13 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) { // cannot give away no-transfer objects return ACCEPT_NO; } - LLVOAvatar* avatar = gAgentAvatarp; + LLVOAvatarSelf* avatar = gAgentAvatarp; if(avatar && avatar->isWearingAttachment( item->getUUID() ) ) { // You can't give objects that are attached to you @@ -2385,7 +2409,7 @@ EAcceptance LLToolDragAndDrop::dad3dGiveInventory( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; if(!LLGiveInventory::isInventoryGiveAcceptable(item)) { return ACCEPT_NO; @@ -2424,7 +2448,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand( LLViewerInventoryItem* item = NULL; LLViewerInventoryCategory* cat = NULL; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; if(!gAgent.allowOperation(PERM_COPY, item->getPermissions()) || !item->getPermissions().allowTransferTo(LLUUID::null)) @@ -2445,7 +2469,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject( LLViewerInventoryItem* item; LLViewerInventoryCategory* cat; locateInventory(item, cat); - if(!item || !item->isComplete()) return ACCEPT_NO; + if (!item || !item->isFinished()) return ACCEPT_NO; if((mask & MASK_CONTROL)) { // *HACK: In order to resolve SL-22177, we need to block drags diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b5ef89b8b..417bbb234 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -219,10 +219,23 @@ void LLViewerInventoryItem::fetchFromServer(void) const { std::string url; - if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString()) - url = gAgent.getRegion()->getCapability("FetchLib2"); - else - url = gAgent.getRegion()->getCapability("FetchInventory2"); + LLViewerRegion* region = gAgent.getRegion(); + // we have to check region. It can be null after region was destroyed. See EXT-245 + if (region) + { + if(gAgent.getID() != mPermissions.getOwner()) + { + url = region->getCapability("FetchLib2"); + } + else + { + url = region->getCapability("FetchInventory2"); + } + } + else + { + llwarns << "Agent Region is absent" << llendl; + } if (!url.empty()) { @@ -472,15 +485,16 @@ void LLViewerInventoryCategory::removeFromServer( void ) gAgent.sendReliableMessage(); } -bool LLViewerInventoryCategory::fetchDescendents() +bool LLViewerInventoryCategory::fetch() { // if((mUUID == gSystemFolderRoot) || (gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot))) return false; // - if (VERSION_UNKNOWN == mVersion && - (!mDescendentsRequested.getStarted() || - mDescendentsRequested.hasExpired())) // Expired check prevents multiple downloads. + if((VERSION_UNKNOWN == mVersion) && + (!mDescendentsRequested.getStarted() || + mDescendentsRequested.hasExpired())) //Expired check prevents multiple downloads. { + LL_DEBUGS("InventoryFetch") << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL; const F32 FETCH_TIMER_EXPIRY = 10.0f; mDescendentsRequested.start(FETCH_TIMER_EXPIRY); @@ -512,7 +526,7 @@ bool LLViewerInventoryCategory::fetchDescendents() } else { //Deprecated, but if we don't have a capability, use the old system. - //llinfos << "FetchInventoryDescendents capability not found. Using deprecated UDP message." << llendl; + llinfos << "FetchInventoryDescendents2 capability not found. Using deprecated UDP message." << llendl; LLMessageSystem* msg = gMessageSystem; msg->newMessage("FetchInventoryDescendents"); msg->nextBlock("AgentData"); @@ -711,6 +725,11 @@ void ActivateGestureCallback::fire(const LLUUID& inv_item) { if (inv_item.isNull()) return; + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (!item) + return; + if (item->getType() != LLAssetType::AT_GESTURE) + return; LLGestureMgr::instance().activateGesture(inv_item); } diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 31f6c6c3f..95b4d1519 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -199,7 +199,7 @@ public: void setVersion(S32 version) { mVersion = version; } // Returns true if a fetch was issued. - bool fetchDescendents(); + bool fetch(); // used to help make cacheing more robust - for example, if // someone is getting 4 packets but logs out after 3. the viewer diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4836e5323..37d589b2f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7122,10 +7122,12 @@ class LLAttachmentDetach : public view_listener_t //Adding an observer for a Jira 2422 and needs to be a fetch observer //for Jira 3119 -class LLWornItemFetchedObserver : public LLInventoryFetchObserver +class LLWornItemFetchedObserver : public LLInventoryFetchItemsObserver { public: - LLWornItemFetchedObserver() {} + LLWornItemFetchedObserver(const LLUUID& worn_item_id) : + LLInventoryFetchItemsObserver(worn_item_id) + {} virtual ~LLWornItemFetchedObserver() {} protected: @@ -7178,13 +7180,9 @@ class LLAttachmentEnableDrop : public view_listener_t // when the item finishes fetching worst case scenario // if a fetch is already out there (being sent from a slow sim) // we refetch and there are 2 fetches - LLWornItemFetchedObserver* wornItemFetched = new LLWornItemFetchedObserver(); - uuid_vec_t items; //add item to the inventory item to be fetched - - items.push_back((*attachment_iter)->getAttachmentItemID()); - - wornItemFetched->fetchItems(items); - gInventory.addObserver(wornItemFetched); + LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID()); + worn_item_fetched->startFetch(); + gInventory.addObserver(worn_item_fetched); } } } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 163f8a0f8..1bc82e6cc 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -814,10 +814,13 @@ static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_ //----------------------------------------------------------------------------- // Instant Message //----------------------------------------------------------------------------- -class LLOpenAgentOffer : public LLInventoryFetchObserver +class LLOpenAgentOffer : public LLInventoryFetchItemsObserver { public: - LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {} + LLOpenAgentOffer(const LLUUID& object_id, + const std::string& from_name) : + LLInventoryFetchItemsObserver(object_id), + mFromName(from_name) {} /*virtual*/ void done() { open_offer(mComplete, mFromName); @@ -856,13 +859,14 @@ void start_new_inventory_observer() } } -class LLDiscardAgentOffer : public LLInventoryFetchComboObserver +class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver { public: LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) : + LLInventoryFetchItemsObserver(object_id), mFolderID(folder_id), mObjectID(object_id) {} - virtual ~LLDiscardAgentOffer() {} + virtual void done() { LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL; @@ -875,6 +879,7 @@ public: gInventory.removeObserver(this); delete this; } + protected: LLUUID mFolderID; LLUUID mObjectID; @@ -1299,11 +1304,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& if ( (rlv_handler_t::isEnabled()) && (!RlvSettings::getForbidGiveToRLV()) && (LLAssetType::AT_CATEGORY == mType) && (RlvInventory::instance().getSharedRoot()) && (mDesc.find(RLV_PUTINV_PREFIX) == 0) ) { - RlvGiveToRLVAgentOffer* pOffer = new RlvGiveToRLVAgentOffer(); - LLInventoryFetchComboObserver::folder_ref_t folders; - folders.push_back(mObjectID); - pOffer->fetchDescendents(folders); - if (pOffer->isEverythingComplete()) + RlvGiveToRLVAgentOffer* pOffer = new RlvGiveToRLVAgentOffer(mObjectID); + pOffer->startFetch(); + if (pOffer->isFinished()) pOffer->done(); else gInventory.addObserver(pOffer); @@ -1311,11 +1314,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& #endif // RLV_EXTENSION_GIVETORLV_A2A // [/RLVa:KB] - uuid_vec_t items; - items.push_back(mObjectID); - LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string); - open_agent_offer->fetchItems(items); - if(catp || (itemp && itemp->isComplete())) + LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(mObjectID, from_string); + open_agent_offer->startFetch(); + if(catp || (itemp && itemp->isFinished())) { open_agent_offer->done(); } @@ -1382,13 +1383,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // request will suffice to discard the item. if(IM_INVENTORY_OFFERED == mIM) { - LLInventoryFetchComboObserver::folder_ref_t folders; - LLInventoryFetchComboObserver::item_ref_t items; - items.push_back(mObjectID); - LLDiscardAgentOffer* discard_agent_offer; - discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID); - discard_agent_offer->fetch(folders, items); - if(catp || (itemp && itemp->isComplete())) + LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID); + discard_agent_offer->startFetch(); + if (catp || (itemp && itemp->isFinished())) { discard_agent_offer->done(); } @@ -3623,7 +3620,9 @@ void process_teleport_progress(LLMessageSystem* msg, void**) class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver { public: - LLFetchInWelcomeArea() {} + LLFetchInWelcomeArea(const uuid_vec_t &ids) : + LLInventoryFetchDescendentsObserver(ids) + {} virtual void done() { LLIsType is_landmark(LLAssetType::AT_LANDMARK); @@ -3634,8 +3633,8 @@ public: LLInventoryModel::cat_array_t land_cats; LLInventoryModel::item_array_t land_items; - folder_ref_t::iterator it = mCompleteFolders.begin(); - folder_ref_t::iterator end = mCompleteFolders.end(); + uuid_vec_t::iterator it = mComplete.begin(); + uuid_vec_t::iterator end = mComplete.end(); for(; it != end; ++it) { gInventory.collectDescendentsIf( @@ -3696,19 +3695,18 @@ BOOL LLPostTeleportNotifiers::tick() if ( gAgent.getTeleportState() == LLAgent::TELEPORT_NONE ) { // get callingcards and landmarks available to the user arriving. - LLInventoryFetchDescendentsObserver::folder_ref_t folders; - LLUUID folder_id; - folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); - if(folder_id.notNull()) - folders.push_back(folder_id); - folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + uuid_vec_t folders; + const LLUUID callingcard_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); + if(callingcard_id.notNull()) + folders.push_back(callingcard_id); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); if(folder_id.notNull()) folders.push_back(folder_id); if(!folders.empty()) { - LLFetchInWelcomeArea* fetcher = new LLFetchInWelcomeArea; - fetcher->fetchDescendents(folders); - if(fetcher->isEverythingComplete()) + LLFetchInWelcomeArea* fetcher = new LLFetchInWelcomeArea(folders); + fetcher->startFetch(); + if(fetcher->isFinished()) { fetcher->done(); } diff --git a/indra/newview/rlvinventory.cpp b/indra/newview/rlvinventory.cpp index bd7771c46..39aab4293 100644 --- a/indra/newview/rlvinventory.cpp +++ b/indra/newview/rlvinventory.cpp @@ -44,7 +44,7 @@ const std::string RlvInventory::cstrSharedRoot = RLV_ROOT_FOLDER; class RlvSharedInventoryFetcher : public LLInventoryFetchDescendentsObserver { public: - RlvSharedInventoryFetcher() {} + RlvSharedInventoryFetcher(const uuid_vec_t& cat_ids) : LLInventoryFetchDescendentsObserver(cat_ids) {} virtual ~RlvSharedInventoryFetcher() {} virtual void done() @@ -75,19 +75,19 @@ void RlvInventory::fetchSharedInventory() gInventory.collectDescendents(pRlvRoot->getUUID(), folders, items, FALSE); // Add them to the "to fetch" list - LLInventoryFetchDescendentsObserver::folder_ref_t fetchFolders; + uuid_vec_t fetchFolders; fetchFolders.push_back(pRlvRoot->getUUID()); for (S32 idxFolder = 0, cntFolder = folders.count(); idxFolder < cntFolder; idxFolder++) fetchFolders.push_back(folders.get(idxFolder)->getUUID()); // Now fetch them all in one go - RlvSharedInventoryFetcher* pFetcher = new RlvSharedInventoryFetcher(); + RlvSharedInventoryFetcher* pFetcher = new RlvSharedInventoryFetcher(fetchFolders); RLV_INFOS << "Starting fetch of " << fetchFolders.size() << " shared folders" << RLV_ENDL; - pFetcher->fetchDescendents(fetchFolders); + pFetcher->startFetch(); m_fFetchStarted = true; - if (pFetcher->isEverythingComplete()) + if (pFetcher->isFinished()) pFetcher->done(); else gInventory.addObserver(pFetcher); @@ -126,8 +126,8 @@ void RlvInventory::fetchSharedLinks() RLV_INFOS << "Starting link target fetch of " << idItems.size() << " items and " << idFolders.size() << " folders" << RLV_ENDL; // Fetch all the link item targets - RlvItemFetcher itemFetcher; - itemFetcher.fetchItems(idItems); + RlvItemFetcher itemFetcher(idItems); + itemFetcher.startFetch(); // Fetch all the link folder targets // TODO! @@ -167,8 +167,8 @@ void RlvInventory::fetchWornItems() } } - RlvItemFetcher itemFetcher; - itemFetcher.fetchItems(idItems); + RlvItemFetcher itemFetcher(idItems); + itemFetcher.startFetch(); } // Checked: 2010-09-27 (RLVa-1.1.3a) | Added: RLVa-1.1.3a @@ -176,10 +176,8 @@ void RlvInventory::fetchWornItem(const LLUUID& idItem) { if (idItem.notNull()) { - uuid_vec_t idItems; - idItems.push_back(idItem); - RlvItemFetcher itemFetcher; - itemFetcher.fetchItems(idItems); + RlvItemFetcher itemFetcher(idItem); + itemFetcher.startFetch(); } } @@ -532,7 +530,7 @@ void RlvGiveToRLVAgentOffer::done() void RlvGiveToRLVAgentOffer::doneIdle() { const LLViewerInventoryCategory* pRlvRoot = RlvInventory::instance().getSharedRoot(); - const LLViewerInventoryCategory* pFolder = (mCompleteFolders.size()) ? gInventory.getCategory(mCompleteFolders[0]) : NULL; + const LLViewerInventoryCategory* pFolder = (mComplete.size()) ? gInventory.getCategory(mComplete[0]) : NULL; if ( (pRlvRoot) && (pFolder) ) { std::string strName = pFolder->getName(); diff --git a/indra/newview/rlvinventory.h b/indra/newview/rlvinventory.h index 87dabd87c..b8dca27b9 100644 --- a/indra/newview/rlvinventory.h +++ b/indra/newview/rlvinventory.h @@ -123,7 +123,7 @@ protected: class RlvGiveToRLVAgentOffer : public LLInventoryFetchDescendentsObserver { public: - RlvGiveToRLVAgentOffer() {} + RlvGiveToRLVAgentOffer(const LLUUID& cat_id) : LLInventoryFetchDescendentsObserver(cat_id) {} virtual void done(); protected: void doneIdle(); @@ -223,10 +223,11 @@ public: virtual bool operator()(LLInventoryCategory* pFolder, LLInventoryItem* pItem) { return (pItem) && (pItem->getIsLinkType()); } }; -class RlvItemFetcher : public LLInventoryFetchObserver +class RlvItemFetcher : public LLInventoryFetchItemsObserver { public: - RlvItemFetcher() {} + RlvItemFetcher(const uuid_vec_t& cat_ids) : LLInventoryFetchItemsObserver(cat_ids) {} + RlvItemFetcher(const LLUUID& cat_id) : LLInventoryFetchItemsObserver(cat_id) {} virtual ~RlvItemFetcher() {} virtual void done() {} }; diff --git a/indra/newview/statemachine/aifetchinventoryfolder.cpp b/indra/newview/statemachine/aifetchinventoryfolder.cpp index 03ea78ed5..1302c1a3a 100644 --- a/indra/newview/statemachine/aifetchinventoryfolder.cpp +++ b/indra/newview/statemachine/aifetchinventoryfolder.cpp @@ -57,14 +57,20 @@ class AIInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsOb AIStateMachine* mStateMachine; }; -AIInventoryFetchDescendentsObserver::AIInventoryFetchDescendentsObserver(AIStateMachine* statemachine, LLUUID const& folder) : mStateMachine(statemachine) +AIInventoryFetchDescendentsObserver::AIInventoryFetchDescendentsObserver(AIStateMachine* statemachine, LLUUID const& folder) : + mStateMachine(statemachine), + LLInventoryFetchDescendentsObserver(folder) { - mStateMachine->idle(); - folder_ref_t folders(1, folder); - fetchDescendents(folders); - gInventory.addObserver(this); - if (isEverythingComplete()) - done(); + mStateMachine->idle(); + startFetch(); + if(isFinished()) + { + done(); + } + else + { + gInventory.addObserver(this); + } } void AIFetchInventoryFolder::fetch(std::string const& foldername, bool create, bool fetch_contents)