New inventory observer implementation.

This commit is contained in:
Shyotl
2012-01-21 04:54:39 -06:00
parent d7d65df9e0
commit 4a4b786a60
17 changed files with 781 additions and 539 deletions

View File

@@ -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);

View File

@@ -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()

View File

@@ -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();

View File

@@ -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(

View File

@@ -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;

View File

@@ -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<LLViewerInventoryCategory *>(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 <<llendl;
mIncompleteFolders.push_back(*fit);
}
else
{
mCompleteFolders.push_back(*fit);
lldebugs << "completing folder " << *fit <<llendl;
}
}
// Now for the items - we fetch everything which is not a direct
// descendent of an incomplete folder because the item will show
// up in an inventory descendents message soon enough so we do not
// have to fetch it individually.
LLSD items_llsd;
LLUUID owner_id;
for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
{
LLViewerInventoryItem* item = gInventory.getItem(*iit);
if(!item)
{
lldebugs << "uanble to find item " << *iit << llendl;
continue;
}
if(item->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<LLViewerInventoryItem> 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)
}
}
}
}
}
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();
}

View File

@@ -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<LLUUID> 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<LLUUID> folder_ref_t;
typedef std::vector<LLUUID> 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<LLUUID> 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<LLUUID> 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<LLViewerInventoryCategory*> 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<LLUUID> folder_ref_t;
typedef std::vector<LLUUID> 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<void()> 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<LLUUID, LLCategoryData> category_map_t;
typedef category_map_t::value_type category_map_value_t;
category_map_t mCategoryMap;
};
#endif // LL_LLINVENTORYOBSERVERS_H

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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<EDragAndDropType> types,
const std::vector<LLUUID>& 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<uuid_vec_t> 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;
// <edit>
//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;
// </edit>
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;
// <edit>
//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;
// <edit>
//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);
// <edit>
//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;
// </edit>
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

View File

@@ -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()
{
// <edit>
if((mUUID == gSystemFolderRoot) || (gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot))) return false;
// </edit>
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);
}

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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() {}
};

View File

@@ -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)