* HTTP inventory fetching from V3, backported by Henri Beauchamp (Cool VL)

Sat, 07 Jan 2012 17:05:31 +0100

author
Ansariel
date
Sat, 07 Jan 2012 17:05:31 +0100
changeset 1616
d5a1e93aefb9
parent 1615
2388998e3bb6
child 1617
afcaf62a83c8

* HTTP inventory fetching from V3, backported by Henri Beauchamp (Cool VL)
* Qarl's Mesh Deformer alpha version, backported by Henri Beauchamp (Cool VL)

indra/llcommon/llfasttimer.h file | annotate | diff | revisions
indra/llmath/m4math.cpp file | annotate | diff | revisions
indra/llmath/m4math.h file | annotate | diff | revisions
indra/newview/CMakeLists.txt file | annotate | diff | revisions
indra/newview/app_settings/settings.xml file | annotate | diff | revisions
indra/newview/chatbar_as_cmdline.cpp file | annotate | diff | revisions
indra/newview/floaterao.cpp file | annotate | diff | revisions
indra/newview/jc_lslviewerbridge.cpp file | annotate | diff | revisions
indra/newview/jclslpreproc.cpp file | annotate | diff | revisions
indra/newview/llagent.h file | annotate | diff | revisions
indra/newview/llappviewer.cpp file | annotate | diff | revisions
indra/newview/llappviewer.h file | annotate | diff | revisions
indra/newview/lldrawpoolavatar.cpp file | annotate | diff | revisions
indra/newview/lldrawpoolavatar.h file | annotate | diff | revisions
indra/newview/llfasttimerview.cpp file | annotate | diff | revisions
indra/newview/llfloaterlandmark.cpp file | annotate | diff | revisions
indra/newview/llfloateropenobject.cpp file | annotate | diff | revisions
indra/newview/llfloaterwater.cpp file | annotate | diff | revisions
indra/newview/llfloaterwindlight.cpp file | annotate | diff | revisions
indra/newview/llfloaterworldmap.cpp file | annotate | diff | revisions
indra/newview/llfolderview.cpp file | annotate | diff | revisions
indra/newview/llinventoryactions.cpp file | annotate | diff | revisions
indra/newview/llinventorybridge.cpp file | annotate | diff | revisions
indra/newview/llinventorymodel.cpp file | annotate | diff | revisions
indra/newview/llinventorymodel.h file | annotate | diff | revisions
indra/newview/llinventorymodelbackgroundfetch.cpp file | annotate | diff | revisions
indra/newview/llinventorymodelbackgroundfetch.h file | annotate | diff | revisions
indra/newview/llinventoryview.cpp file | annotate | diff | revisions
indra/newview/llpanelface.cpp file | annotate | diff | revisions
indra/newview/llpanelobject.cpp file | annotate | diff | revisions
indra/newview/llpolymesh.h file | annotate | diff | revisions
indra/newview/llpreviewgesture.cpp file | annotate | diff | revisions
indra/newview/llpreviewscript.cpp file | annotate | diff | revisions
indra/newview/llstartup.cpp file | annotate | diff | revisions
indra/newview/lltexturectrl.cpp file | annotate | diff | revisions
indra/newview/llviewerinventory.cpp file | annotate | diff | revisions
indra/newview/llviewerinventory.h file | annotate | diff | revisions
indra/newview/llviewermenu.cpp file | annotate | diff | revisions
indra/newview/llviewermessage.cpp file | annotate | diff | revisions
indra/newview/llviewerregion.cpp file | annotate | diff | revisions
indra/newview/llvoavatar.cpp file | annotate | diff | revisions
indra/newview/llvoavatar.h file | annotate | diff | revisions
indra/newview/llvovolume.cpp file | annotate | diff | revisions
indra/newview/llvovolume.h file | annotate | diff | revisions
indra/newview/rlvhelper.cpp file | annotate | diff | revisions
indra/newview/rlvinventory.cpp file | annotate | diff | revisions
indra/newview/rlvlocks.cpp file | annotate | diff | revisions
     1.1 --- a/indra/llcommon/llfasttimer.h	Tue Dec 27 12:40:48 2011 +0100
     1.2 +++ b/indra/llcommon/llfasttimer.h	Sat Jan 07 17:05:31 2012 +0100
     1.3 @@ -173,6 +173,7 @@
     1.4  		FTM_LOD_UPDATE,
     1.5  		FTM_UPDATE_RIGGED_VOLUME,
     1.6  		FTM_SKIN_RIGGED,
     1.7 +		FTM_SKIN_RIGGED_DEFORM,
     1.8  		FTM_RIGGED_OCTREE,
     1.9  		FTM_REGION_UPDATE,
    1.10  		FTM_CLEANUP,
     2.1 --- a/indra/llmath/m4math.cpp	Tue Dec 27 12:40:48 2011 +0100
     2.2 +++ b/indra/llmath/m4math.cpp	Sat Jan 07 17:05:31 2012 +0100
     2.3 @@ -280,6 +280,64 @@
     2.4  	return *this;
     2.5  }
     2.6  
     2.7 +// does an actual inversion
     2.8 +const LLMatrix4& LLMatrix4::invert_real()
     2.9 +{
    2.10 +	F32* m = &mMatrix[0][0];
    2.11 +
    2.12 +	F32 inv[16];
    2.13 +	F32 det;
    2.14 +
    2.15 +	inv[0] =   m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
    2.16 +	+ m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
    2.17 +	inv[4] =  -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
    2.18 +	- m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
    2.19 +	inv[8] =   m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
    2.20 +	+ m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
    2.21 +	inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
    2.22 +	- m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
    2.23 +	inv[1] =  -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
    2.24 +	- m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
    2.25 +	inv[5] =   m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
    2.26 +	+ m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
    2.27 +	inv[9] =  -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
    2.28 +	- m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
    2.29 +	inv[13] =  m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
    2.30 +	+ m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
    2.31 +	inv[2] =   m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
    2.32 +	+ m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
    2.33 +	inv[6] =  -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
    2.34 +	- m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
    2.35 +	inv[10] =  m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
    2.36 +	+ m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
    2.37 +	inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
    2.38 +	- m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
    2.39 +	inv[3] =  -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
    2.40 +	- m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
    2.41 +	inv[7] =   m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
    2.42 +	+ m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
    2.43 +	inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
    2.44 +	- m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
    2.45 +	inv[15] =  m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
    2.46 +	+ m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
    2.47 +
    2.48 +	det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
    2.49 +
    2.50 +	if (det == 0)
    2.51 +	{
    2.52 +		setZero();
    2.53 +	}
    2.54 +	else 
    2.55 +	{
    2.56 +		det = 1.0 / det;
    2.57 +
    2.58 +		for (int i = 0; i < 16; i++)
    2.59 +			m[i] = inv[i] * det;
    2.60 +	}
    2.61 +
    2.62 +	return *this;
    2.63 +}
    2.64 +
    2.65  LLVector4 LLMatrix4::getFwdRow4() const
    2.66  {
    2.67  	return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ], mMatrix[VX][VW]);
     3.1 --- a/indra/llmath/m4math.h	Tue Dec 27 12:40:48 2011 +0100
     3.2 +++ b/indra/llmath/m4math.h	Sat Jan 07 17:05:31 2012 +0100
     3.3 @@ -208,7 +208,8 @@
     3.4  	//
     3.5  
     3.6  	const LLMatrix4& transpose();						// Transpose LLMatrix4
     3.7 -	const LLMatrix4& invert();						// Invert LLMatrix4
     3.8 +	const LLMatrix4& invert();						// Invert LLMatrix4 
     3.9 +	const LLMatrix4& invert_real();					// Invert LLMatrix4 - works for all matrices
    3.10  
    3.11  	// Rotate existing matrix
    3.12  	// These are really, really, inefficient as implemented! - djs
     4.1 --- a/indra/newview/CMakeLists.txt	Tue Dec 27 12:40:48 2011 +0100
     4.2 +++ b/indra/newview/CMakeLists.txt	Sat Jan 07 17:05:31 2012 +0100
     4.3 @@ -306,6 +306,7 @@
     4.4      llinventoryclipboard.cpp
     4.5      llinventoryicon.cpp
     4.6      llinventorymodel.cpp
     4.7 +    llinventorymodelbackgroundfetch.cpp
     4.8      llinventoryview.cpp
     4.9      lljoystickbutton.cpp
    4.10      lllandmarklist.cpp
    4.11 @@ -784,6 +785,7 @@
    4.12      llinventoryclipboard.h
    4.13      llinventoryicon.h
    4.14      llinventorymodel.h
    4.15 +    llinventorymodelbackgroundfetch.h
    4.16      llinventoryview.h
    4.17      lljoystickbutton.h
    4.18      lllandmarklist.h
     5.1 --- a/indra/newview/app_settings/settings.xml	Tue Dec 27 12:40:48 2011 +0100
     5.2 +++ b/indra/newview/app_settings/settings.xml	Sat Jan 07 17:05:31 2012 +0100
     5.3 @@ -6364,6 +6364,17 @@
     5.4  			<key>Value</key>
     5.5  			<integer>16</integer>
     5.6  		</map>
     5.7 +		<key>MeshEnableDeformer</key>
     5.8 +		<map>
     5.9 +			<key>Comment</key>
    5.10 +			<string>Enable mesh deformer (tailoring): this is alpha code</string>
    5.11 +			<key>Persist</key>
    5.12 +			<integer>1</integer>
    5.13 +			<key>Type</key>
    5.14 +			<string>Boolean</string>
    5.15 +			<key>Value</key>
    5.16 +			<real>0</real>
    5.17 +		</map>
    5.18  		<key>MeshImportUseSLM</key>
    5.19  		<map>
    5.20  			<key>Comment</key>
    5.21 @@ -16341,6 +16352,17 @@
    5.22  			<key>Value</key>
    5.23  			<integer>0</integer>
    5.24  		</map>
    5.25 +		<key>UseHTTPInventory</key>
    5.26 +		<map>
    5.27 +			<key>Comment</key>
    5.28 +			<string>Allow use of http inventory transfers instead of UDP</string>
    5.29 +			<key>Persist</key>
    5.30 +			<integer>1</integer>
    5.31 +			<key>Type</key>
    5.32 +			<string>Boolean</string>
    5.33 +			<key>Value</key>
    5.34 +			<integer>1</integer>
    5.35 +		</map>
    5.36  		<key>UseInventoryLinks</key>
    5.37  		<map>
    5.38  			<key>Comment</key>
     6.1 --- a/indra/newview/chatbar_as_cmdline.cpp	Tue Dec 27 12:40:48 2011 +0100
     6.2 +++ b/indra/newview/chatbar_as_cmdline.cpp	Sat Jan 07 17:05:31 2012 +0100
     6.3 @@ -447,7 +447,7 @@
     6.4  	LLViewerInventoryCategory::cat_array_t cats;
     6.5  	LLViewerInventoryItem::item_array_t items;
     6.6  	//ObjectContentNameMatches objectnamematches(ifolder);
     6.7 -	gInventory.collectDescendents(gAgent.getInventoryRootID(),cats,items,FALSE);//,objectnamematches);
     6.8 +	gInventory.collectDescendents(gInventory.getRootFolderID(),cats,items,FALSE);//,objectnamematches);
     6.9  }
    6.10  
    6.11  /*static BOOL *sPhoenixCmdLine;
     7.1 --- a/indra/newview/floaterao.cpp	Tue Dec 27 12:40:48 2011 +0100
     7.2 +++ b/indra/newview/floaterao.cpp	Sat Jan 07 17:05:31 2012 +0100
     7.3 @@ -14,6 +14,7 @@
     7.4  #include "llvoavatar.h"
     7.5  #include "llanimationstates.h"
     7.6  #include "lluictrlfactory.h"
     7.7 +#include "llinventorymodelbackgroundfetch.h"
     7.8  #include "llinventoryview.h"
     7.9  #include "llstartup.h"
    7.10  #include "llpreviewnotecard.h"
    7.11 @@ -586,7 +587,7 @@
    7.12  					{
    7.13  						fullfetch = TRUE;
    7.14  						//no choice, can't move the AO till we find it, should only have to happen once
    7.15 -						gInventory.startBackgroundFetch();
    7.16 +						LLInventoryModelBackgroundFetch::instance().start();
    7.17  						return FALSE;
    7.18  					}
    7.19  				}
     8.1 --- a/indra/newview/jc_lslviewerbridge.cpp	Tue Dec 27 12:40:48 2011 +0100
     8.2 +++ b/indra/newview/jc_lslviewerbridge.cpp	Sat Jan 07 17:05:31 2012 +0100
     8.3 @@ -48,6 +48,7 @@
     8.4  #include "llviewerobject.h"
     8.5  #include "llvoavatar.h"
     8.6  #include "llinventorymodel.h"
     8.7 +#include "llinventorymodelbackgroundfetch.h"
     8.8  #include "lltooldraganddrop.h"
     8.9  #include "llmd5.h"
    8.10  #include "llstartup.h"
    8.11 @@ -365,7 +366,7 @@
    8.12  	phoenix_category = gInventory.findCategoryByName(phoenix_category_name);
    8.13  	if(phoenix_category.isNull())
    8.14  	{
    8.15 -		phoenix_category = gInventory.createNewCategory(gAgent.getInventoryRootID(), LLFolderType::FT_NONE, phoenix_category_name);
    8.16 +		phoenix_category = gInventory.createNewCategory(gInventory.getRootFolderID(), LLFolderType::FT_NONE, phoenix_category_name);
    8.17  	}
    8.18  	return phoenix_category;
    8.19  }
    8.20 @@ -382,7 +383,7 @@
    8.21  		category = findCategoryByNameOrCreate(catname);
    8.22  	}else
    8.23  	{
    8.24 -		category = gAgent.getInventoryRootID();
    8.25 +		category = gInventory.getRootFolderID();
    8.26  	}
    8.27  
    8.28  	gInventory.collectDescendentsIf(category,cats,items,FALSE,objectnamematches);
    8.29 @@ -658,7 +659,7 @@
    8.30  		LLViewerInventoryCategory::cat_array_t cats;
    8.31  		LLViewerInventoryItem::item_array_t items;
    8.32  
    8.33 -		gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),cats,items,FALSE,prefixmatcher);
    8.34 +		gInventory.collectDescendentsIf(gInventory.getRootFolderID(),cats,items,FALSE,prefixmatcher);
    8.35  
    8.36  		LLViewerInventoryItem::item_array_t delete_queue;
    8.37  
    8.38 @@ -704,7 +705,7 @@
    8.39  		}
    8.40  		
    8.41  		static BOOL first_full_load = TRUE;
    8.42 -		if (first_full_load && gInventory.isEverythingFetched()) // when the inv is done fetching, check for old bridges
    8.43 +		if (first_full_load && LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) // when the inv is done fetching, check for old bridges
    8.44  		{
    8.45  			//cmdline_printchat("--first full inv load");
    8.46  			first_full_load = FALSE;
     9.1 --- a/indra/newview/jclslpreproc.cpp	Tue Dec 27 12:40:48 2011 +0100
     9.2 +++ b/indra/newview/jclslpreproc.cpp	Sat Jan 07 17:05:31 2012 +0100
     9.3 @@ -77,7 +77,7 @@
     9.4  	LLViewerInventoryCategory::cat_array_t cats;
     9.5  	LLViewerInventoryItem::item_array_t items;
     9.6  	ScriptMatches namematches(name);
     9.7 -	gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),cats,items,FALSE,namematches);
     9.8 +	gInventory.collectDescendentsIf(gInventory.getRootFolderID(),cats,items,FALSE,namematches);
     9.9  
    9.10  	if (items.count())
    9.11  	{
    10.1 --- a/indra/newview/llagent.h	Tue Dec 27 12:40:48 2011 +0100
    10.2 +++ b/indra/newview/llagent.h	Sat Jan 07 17:05:31 2012 +0100
    10.3 @@ -190,7 +190,7 @@
    10.4  
    10.5  	// Set the home data
    10.6  	void			setRegion(LLViewerRegion *regionp);
    10.7 -	LLViewerRegion	*getRegion() const;
    10.8 +	LLViewerRegion*	getRegion() const;
    10.9  	const LLHost&	getRegionHost() const;
   10.10  	std::string		getSLURL() const;
   10.11  	
   10.12 @@ -307,8 +307,6 @@
   10.13  	bool			getAlwaysRun() const { return mbAlwaysRun; }
   10.14  	bool			getRunning() const { return mbRunning; }
   10.15  
   10.16 -	const LLUUID&	getInventoryRootID() const 	{ return mInventoryRootID; }
   10.17 -
   10.18  	void			buildFullname(std::string &name) const;
   10.19  	void			buildFullnameAndTitle(std::string &name) const;
   10.20  
   10.21 @@ -777,8 +775,7 @@
   10.22  	std::string		mGroupTitle; // honorific, like "Sir"
   10.23  	std::string		mGroupName;
   10.24  	LLUUID			mGroupID;
   10.25 -	//LLUUID			mGroupInsigniaID;
   10.26 -	LLUUID			mInventoryRootID;
   10.27 +	//LLUUID		mGroupInsigniaID;
   10.28  	LLUUID			mMapID;
   10.29  	F64				mMapOriginX;	// Global x coord of mMapID's bottom left corner.
   10.30  	F64				mMapOriginY;	// Global y coord of mMapID's bottom left corner.
    11.1 --- a/indra/newview/llappviewer.cpp	Tue Dec 27 12:40:48 2011 +0100
    11.2 +++ b/indra/newview/llappviewer.cpp	Sat Jan 07 17:05:31 2012 +0100
    11.3 @@ -255,17 +255,14 @@
    11.4  static const F32 LOGOUT_REQUEST_TIME = 6.f;  // this will be cut short by the LogoutReply msg.
    11.5  F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME;
    11.6  
    11.7 -LLUUID gInventoryLibraryOwner;
    11.8 -LLUUID gInventoryLibraryRoot;
    11.9 -
   11.10 -BOOL				gDisconnected = FALSE;
   11.11 +BOOL gDisconnected = FALSE;
   11.12  
   11.13  // Minimap scale in pixels per region
   11.14  
   11.15  // used to restore texture state after a mode switch
   11.16  LLFrameTimer	gRestoreGLTimer;
   11.17  BOOL			gRestoreGL = FALSE;
   11.18 -BOOL				gUseWireframe = FALSE;
   11.19 +BOOL			gUseWireframe = FALSE;
   11.20  
   11.21  // VFS globals - see llappviewer.h
   11.22  LLVFS* gStaticVFS = NULL;
   11.23 @@ -1484,7 +1481,8 @@
   11.24  		llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
   11.25  		ms_sleep(100);
   11.26  	}
   11.27 -	llinfos << "Shutting down." << llendflush;
   11.28 +
   11.29 +	llinfos << "Shutting down Views" << llendflush;
   11.30  
   11.31  	// Destroy the UI
   11.32  	if (gViewerWindow)
   11.33 @@ -1492,6 +1490,12 @@
   11.34  		gViewerWindow->shutdownViews();
   11.35  	}
   11.36  
   11.37 +	llinfos << "Cleaning up Inventory" << llendflush;
   11.38 +	
   11.39 +	// Cleanup Inventory after the UI since it will delete any remaining observers
   11.40 +	// (Deleted observers should have already removed themselves)
   11.41 +	gInventory.cleanupInventory();
   11.42 +
   11.43  	// Clean up selection managers after UI is destroyed, as UI may be observing them.
   11.44  	// Clean up before GL is shut down because we might be holding on to objects with texture references
   11.45  	LLSelectMgr::cleanupGlobals();
   11.46 @@ -3812,6 +3816,7 @@
   11.47  		gEventNotifier.update();
   11.48  
   11.49  		gIdleCallbacks.callFunctions();
   11.50 +		gInventory.idleNotifyObservers();
   11.51  	}
   11.52  
   11.53  	gViewerWindow->handlePerFrameHover();
   11.54 @@ -4358,10 +4363,12 @@
   11.55  	if (!gNoRender)
   11.56  	{
   11.57  		// save inventory if appropriate
   11.58 -		gInventory.cache(gAgent.getInventoryRootID(), gAgent.getID());
   11.59 -		if(gInventoryLibraryRoot.notNull() && gInventoryLibraryOwner.notNull())
   11.60 +		gInventory.cache(gInventory.getRootFolderID(), gAgent.getID());
   11.61 +		if (gInventory.getLibraryRootFolderID().notNull() &&
   11.62 +			gInventory.getLibraryOwnerID().notNull())
   11.63  		{
   11.64 -			gInventory.cache(gInventoryLibraryRoot, gInventoryLibraryOwner);
   11.65 +			gInventory.cache(gInventory.getLibraryRootFolderID(),
   11.66 +							 gInventory.getLibraryOwnerID());
   11.67  		}
   11.68  	}
   11.69  
    12.1 --- a/indra/newview/llappviewer.h	Tue Dec 27 12:40:48 2011 +0100
    12.2 +++ b/indra/newview/llappviewer.h	Sat Jan 07 17:05:31 2012 +0100
    12.3 @@ -305,13 +305,13 @@
    12.4  // currently in daylight savings time?
    12.5  extern BOOL gPacificDaylightTime;
    12.6  
    12.7 -extern U64      gFrameTime;					// The timestamp of the most-recently-processed frame
    12.8 -extern F32		gFrameTimeSeconds;			// Loses msec precision after ~4.5 hours...
    12.9 -extern F32		gFrameIntervalSeconds;		// Elapsed time between current and previous gFrameTimeSeconds
   12.10 -extern F32		gFPSClamped;				// Frames per second, smoothed, weighted toward last frame
   12.11 -extern F32		gFrameDTClamped;
   12.12 -extern U64		gStartTime;
   12.13 -extern U32 		gFrameStalls;
   12.14 +extern U64 gFrameTime;                 // The timestamp of the most-recently-processed frame
   12.15 +extern F32 gFrameTimeSeconds;          // Loses msec precision after ~4.5 hours...
   12.16 +extern F32 gFrameIntervalSeconds;      // Elapsed time between current and previous gFrameTimeSeconds
   12.17 +extern F32 gFPSClamped;                // Frames per second, smoothed, weighted toward last frame
   12.18 +extern F32 gFrameDTClamped;
   12.19 +extern U64 gStartTime;
   12.20 +extern U32 gFrameStalls;
   12.21  
   12.22  extern LLTimer gRenderStartTime;
   12.23  extern LLFrameTimer gForegroundTime;
   12.24 @@ -322,21 +322,18 @@
   12.25  extern F32 gSimLastTime; 
   12.26  extern F32 gSimFrames;
   12.27  
   12.28 -extern LLUUID gInventoryLibraryOwner;
   12.29 -extern LLUUID gInventoryLibraryRoot;
   12.30 -
   12.31 -extern BOOL		gDisconnected;
   12.32 +extern BOOL gDisconnected;
   12.33  
   12.34  // Minimap scale in pixels per region
   12.35  
   12.36  extern LLFrameTimer	gRestoreGLTimer;
   12.37  extern BOOL			gRestoreGL;
   12.38 -extern BOOL		gUseWireframe;
   12.39 +extern BOOL			gUseWireframe;
   12.40  
   12.41  // VFS globals - gVFS is for general use
   12.42  // gStaticVFS is read-only and is shipped w/ the viewer
   12.43  // it has pre-cache data like the UI .TGAs
   12.44 -extern LLVFS	*gStaticVFS;
   12.45 +extern LLVFS* gStaticVFS;
   12.46  
   12.47  extern LLMemoryInfo gSysMemory;
   12.48  extern U64 gMemoryAllocated;
    13.1 --- a/indra/newview/lldrawpoolavatar.cpp	Tue Dec 27 12:40:48 2011 +0100
    13.2 +++ b/indra/newview/lldrawpoolavatar.cpp	Sat Jan 07 17:05:31 2012 +0100
    13.3 @@ -46,6 +46,7 @@
    13.4  #include "llmeshrepository.h"
    13.5  #include "llsky.h"
    13.6  #include "llviewercamera.h"
    13.7 +#include "llviewercontrol.h"
    13.8  #include "llviewerregion.h"
    13.9  #include "noise.h"
   13.10  #include "pipeline.h"
   13.11 @@ -1271,7 +1272,9 @@
   13.12  	}
   13.13  }
   13.14  
   13.15 -void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
   13.16 +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, 
   13.17 +													const LLMeshSkinInfo* skin, LLVolume* volume, 
   13.18 +													const LLVolumeFace& vol_face, LLVOVolume* vobj)
   13.19  {
   13.20  	LLVector4a* weight = vol_face.mWeights;
   13.21  	if (!weight)
   13.22 @@ -1323,10 +1326,21 @@
   13.23  						m.m[4], m.m[5], m.m[6],
   13.24  						m.m[8], m.m[9], m.m[10] };
   13.25  
   13.26 -		LLMatrix3 mat_normal(mat3);				
   13.27 +		LLMatrix3 mat_normal(mat3);
   13.28  
   13.29 -		face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert,
   13.30 -								mat_normal, offset, true);
   13.31 +		static LLCachedControl<bool> mesh_enable_deformer(gSavedSettings, "MeshEnableDeformer");
   13.32 +		if (mesh_enable_deformer)
   13.33 +		{
   13.34 +			LLDeformedVolume* deformed_volume = vobj->getDeformedVolume();
   13.35 +			deformed_volume->deform(volume, avatar, skin, face->getTEOffset());
   13.36 +			face->getGeometryVolume(*deformed_volume, face->getTEOffset(), mat_vert,
   13.37 +									mat_normal, offset, true);
   13.38 +		}
   13.39 +		else
   13.40 +		{
   13.41 +			face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert,
   13.42 + 									mat_normal, offset, true);
   13.43 +		}
   13.44  	}
   13.45  
   13.46  	if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
   13.47 @@ -1463,7 +1477,7 @@
   13.48  		stop_glerror();
   13.49  
   13.50  		const LLVolumeFace& vol_face = volume->getVolumeFace(te);
   13.51 -		updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face);
   13.52 +		updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face, vobj);
   13.53  
   13.54  		stop_glerror();
   13.55  
    14.1 --- a/indra/newview/lldrawpoolavatar.h	Tue Dec 27 12:40:48 2011 +0100
    14.2 +++ b/indra/newview/lldrawpoolavatar.h	Sat Jan 07 17:05:31 2012 +0100
    14.3 @@ -41,6 +41,7 @@
    14.4  class LLMeshSkinInfo;
    14.5  class LLVolume;
    14.6  class LLVolumeFace;
    14.7 +class LLVOVolume;
    14.8  
    14.9  class LLDrawPoolAvatar : public LLFacePool
   14.10  {
   14.11 @@ -138,7 +139,8 @@
   14.12  									  LLFace* facep, 
   14.13  									  const LLMeshSkinInfo* skin, 
   14.14  									  LLVolume* volume,
   14.15 -									  const LLVolumeFace& vol_face);
   14.16 +									  const LLVolumeFace& vol_face,
   14.17 +									  LLVOVolume* vobj);
   14.18  
   14.19  	void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false);
   14.20  	void renderRiggedSimple(LLVOAvatar* avatar);
    15.1 --- a/indra/newview/llfasttimerview.cpp	Tue Dec 27 12:40:48 2011 +0100
    15.2 +++ b/indra/newview/llfasttimerview.cpp	Sat Jan 07 17:05:31 2012 +0100
    15.3 @@ -213,6 +213,7 @@
    15.4  	{ LLFastTimer::FTM_RENDER_TERRAIN,		"     Terrain",			&LLColor4::green6, 0 },
    15.5  	{ LLFastTimer::FTM_AVATAR_FACE,			"     Avatar Face",		&LLColor4::yellow1, 0 },
    15.6  	{ LLFastTimer::FTM_RENDER_CHARACTERS,	"     Avatars",			&LLColor4::yellow2, 0 },
    15.7 +	{ LLFastTimer::FTM_SKIN_RIGGED_DEFORM,	"      Rigged Deform",	&LLColor4::yellow3, 0 },
    15.8  	{ LLFastTimer::FTM_RENDER_SIMPLE,		"     Simple",			&LLColor4::yellow4, 0 },
    15.9  	{ LLFastTimer::FTM_RENDER_FULLBRIGHT,	"     Fullbright",		&LLColor4::yellow5, 0 },
   15.10  	{ LLFastTimer::FTM_RENDER_GLOW,			"     Glow",			&LLColor4::orange1, 0 },
    16.1 --- a/indra/newview/llfloaterlandmark.cpp	Tue Dec 27 12:40:48 2011 +0100
    16.2 +++ b/indra/newview/llfloaterlandmark.cpp	Sat Jan 07 17:05:31 2012 +0100
    16.3 @@ -190,7 +190,7 @@
    16.4  		{
    16.5  			if (!root_folder->getCurSelectedItem())
    16.6  			{
    16.7 -				LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID());
    16.8 +				LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID());
    16.9  				if (itemp)
   16.10  				{
   16.11  					root_folder->setSelection(itemp, FALSE, FALSE);
    17.1 --- a/indra/newview/llfloateropenobject.cpp	Tue Dec 27 12:40:48 2011 +0100
    17.2 +++ b/indra/newview/llfloateropenobject.cpp	Sat Jan 07 17:05:31 2012 +0100
    17.3 @@ -153,7 +153,7 @@
    17.4  	}
    17.5  	else
    17.6  	{
    17.7 -		parent_category_id = gAgent.getInventoryRootID();
    17.8 +		parent_category_id = gInventory.getRootFolderID();
    17.9  	}
   17.10  	LLUUID category_id = gInventory.createNewCategory(parent_category_id, 
   17.11  		LLFolderType::FT_NONE, 
    18.1 --- a/indra/newview/llfloaterwater.cpp	Tue Dec 27 12:40:48 2011 +0100
    18.2 +++ b/indra/newview/llfloaterwater.cpp	Sat Jan 07 17:05:31 2012 +0100
    18.3 @@ -639,7 +639,7 @@
    18.4  		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
    18.5  		if(LLWaterParamManager::instance()->mCurParams.mInventoryID.notNull() 
    18.6  			&& !gInventory.isObjectDescendentOf(LLWaterParamManager::instance()->mCurParams.mInventoryID, trash_id)
    18.7 -			&& gInventory.isObjectDescendentOf(LLWaterParamManager::instance()->mCurParams.mInventoryID, gAgent.getInventoryRootID())
    18.8 +			&& gInventory.isObjectDescendentOf(LLWaterParamManager::instance()->mCurParams.mInventoryID, gInventory.getRootFolderID())
    18.9  		)
   18.10  		{
   18.11  			LLNotifications::instance().add("KittyWLSaveNotecardAlert", LLSD(), LLSD(), saveNotecardCallback);
    19.1 --- a/indra/newview/llfloaterwindlight.cpp	Tue Dec 27 12:40:48 2011 +0100
    19.2 +++ b/indra/newview/llfloaterwindlight.cpp	Sat Jan 07 17:05:31 2012 +0100
    19.3 @@ -832,7 +832,7 @@
    19.4  		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
    19.5  		if(LLWLParamManager::instance()->mCurParams.mInventoryID.notNull() 
    19.6  			&& !gInventory.isObjectDescendentOf(LLWLParamManager::instance()->mCurParams.mInventoryID, trash_id)
    19.7 -			&& gInventory.isObjectDescendentOf(LLWLParamManager::instance()->mCurParams.mInventoryID, gAgent.getInventoryRootID())
    19.8 +			&& gInventory.isObjectDescendentOf(LLWLParamManager::instance()->mCurParams.mInventoryID, gInventory.getRootFolderID())
    19.9  		)
   19.10   		{
   19.11  			LLNotifications::instance().add("KittyWLSaveNotecardAlert", LLSD(), LLSD(), saveNotecardCallback);
    20.1 --- a/indra/newview/llfloaterworldmap.cpp	Tue Dec 27 12:40:48 2011 +0100
    20.2 +++ b/indra/newview/llfloaterworldmap.cpp	Sat Jan 07 17:05:31 2012 +0100
    20.3 @@ -50,6 +50,7 @@
    20.4  #include "llviewercontrol.h"
    20.5  #include "lldraghandle.h"
    20.6  #include "llfirstuse.h"
    20.7 +#include "llinventorymodelbackgroundfetch.h"
    20.8  #include "llfocusmgr.h"
    20.9  #include "lllandmarklist.h"
   20.10  #include "lllineeditor.h"
   20.11 @@ -374,7 +375,7 @@
   20.12  
   20.13  		// Start speculative download of landmarks
   20.14  		LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
   20.15 -		gInventory.startBackgroundFetch(landmark_folder_id);
   20.16 +		LLInventoryModelBackgroundFetch::instance().start(landmark_folder_id);
   20.17  
   20.18  		gFloaterWorldMap->childSetFocus("location", TRUE);
   20.19  		gFocusMgr.triggerFocusFlash();
   20.20 @@ -969,7 +970,7 @@
   20.21  	LLInventoryModel::cat_array_t cats;
   20.22  	LLInventoryModel::item_array_t items;
   20.23  	LLIsType is_landmark(LLAssetType::AT_LANDMARK);
   20.24 -	gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
   20.25 +	gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
   20.26  									cats,
   20.27  									items,
   20.28  									LLInventoryModel::EXCLUDE_TRASH,
    21.1 --- a/indra/newview/llfolderview.cpp	Tue Dec 27 12:40:48 2011 +0100
    21.2 +++ b/indra/newview/llfolderview.cpp	Sat Jan 07 17:05:31 2012 +0100
    21.3 @@ -46,14 +46,15 @@
    21.4  #include "llinventory.h"
    21.5  
    21.6  #include "llcallbacklist.h"
    21.7 -#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
    21.8 -#include "llinventoryview.h"// hacked in for the bonus context menu items.
    21.9 +#include "llinventoryclipboard.h"	// *TODO: remove this once hack below gone.
   21.10 +#include "llinventorymodelbackgroundfetch.h"
   21.11 +#include "llinventoryview.h"		// hacked in for the bonus context menu items.
   21.12  #include "llkeyboard.h"
   21.13  #include "lllineeditor.h"
   21.14  #include "llmenugl.h"
   21.15  #include "llresmgr.h"
   21.16  #include "llpreview.h"
   21.17 -#include "llscrollcontainer.h" // hack to allow scrolling
   21.18 +#include "llscrollcontainer.h"		// hack to allow scrolling
   21.19  #include "lltooldraganddrop.h"
   21.20  #include "llui.h"
   21.21  #include "llviewertexturelist.h"
   21.22 @@ -785,11 +786,11 @@
   21.23  
   21.24  				// *TODO: push this into listener and remove
   21.25  				// dependency on llagent
   21.26 -				if(mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gAgent.getInventoryRootID()))
   21.27 +				if (mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getRootFolderID()))
   21.28  				{
   21.29  					src = LLToolDragAndDrop::SOURCE_AGENT;
   21.30  				}
   21.31 -				else if (mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventoryLibraryRoot))
   21.32 +				else if (mListener && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getLibraryRootFolderID()))
   21.33  				{
   21.34  					src = LLToolDragAndDrop::SOURCE_LIBRARY;
   21.35  				}
   21.36 @@ -1362,7 +1363,7 @@
   21.37  	// when applying a filter, matching folders get their contents downloaded first
   21.38  	if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID())))
   21.39  	{
   21.40 -		gInventory.startBackgroundFetch(mListener->getUUID());
   21.41 +		LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID());
   21.42  	}
   21.43  
   21.44  	// now query children
   21.45 @@ -2794,10 +2795,10 @@
   21.46  	return mSortOrder;
   21.47  }
   21.48  
   21.49 -BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)
   21.50 +BOOL LLFolderView::addFolder(LLFolderViewFolder* folder)
   21.51  {
   21.52  	// enforce sort order of My Inventory followed by Library
   21.53 -	if (folder->getListener()->getUUID() == gInventoryLibraryRoot)
   21.54 +	if (folder->getListener()->getUUID() == gInventory.getLibraryRootFolderID())
   21.55  	{
   21.56  		mFolders.push_back(folder);
   21.57  	}
   21.58 @@ -3209,7 +3210,7 @@
   21.59  		else
   21.60  		{
   21.61  			// nothing selected to start with, so pick "My Inventory" as best guess
   21.62 -			new_selection = getItemByID(gAgent.getInventoryRootID());
   21.63 +			new_selection = getItemByID(gInventory.getRootFolderID());
   21.64  		}
   21.65  
   21.66  		if (new_selection)
   21.67 @@ -3324,7 +3325,8 @@
   21.68  	}
   21.69  	else
   21.70  	{
   21.71 -		if (gInventory.backgroundFetchActive() || mCompletedFilterGeneration < mFilter.getMinRequiredGeneration())
   21.72 +		if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() ||
   21.73 +			mCompletedFilterGeneration < mFilter.getMinRequiredGeneration())
   21.74  		{
   21.75  			mStatusText = std::string("Searching..."); // *TODO:translate
   21.76  			sFont->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE );
   21.77 @@ -5186,7 +5188,8 @@
   21.78  		filtered_by_all_types = FALSE;
   21.79  	}
   21.80  
   21.81 -	if (!gInventory.backgroundFetchActive() && filtered_by_type && !filtered_by_all_types)
   21.82 +	if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() &&
   21.83 +		filtered_by_type && !filtered_by_all_types)
   21.84  	{
   21.85  		mFilterText += " - ";
   21.86  		if (num_filter_types < 5)
    22.1 --- a/indra/newview/llinventoryactions.cpp	Tue Dec 27 12:40:48 2011 +0100
    22.2 +++ b/indra/newview/llinventoryactions.cpp	Sat Jan 07 17:05:31 2012 +0100
    22.3 @@ -341,7 +341,7 @@
    22.4  		}
    22.5  		else
    22.6  		{
    22.7 -			category = model->createNewCategory(gAgent.getInventoryRootID(),
    22.8 +			category = model->createNewCategory(gInventory.getRootFolderID(),
    22.9  												LLFolderType::FT_NONE, LLStringUtil::null);
   22.10  		}
   22.11  		model->notifyObservers();
   22.12 @@ -787,7 +787,7 @@
   22.13  		}
   22.14  		LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id);
   22.15  
   22.16 -		if(item && gInventory.isObjectDescendentOf(id, gAgent.getInventoryRootID()))
   22.17 +		if (item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()))
   22.18  		{
   22.19  			rez_attachment(item, attachmentp);
   22.20  		}
    23.1 --- a/indra/newview/llinventorybridge.cpp	Tue Dec 27 12:40:48 2011 +0100
    23.2 +++ b/indra/newview/llinventorybridge.cpp	Sat Jan 07 17:05:31 2012 +0100
    23.3 @@ -62,6 +62,7 @@
    23.4  #include "lliconctrl.h"
    23.5  #include "llinventoryicon.h"
    23.6  #include "llinventorymodel.h"
    23.7 +#include "llinventorymodelbackgroundfetch.h"
    23.8  #include "llinventoryclipboard.h"
    23.9  #include "lllineeditor.h"
   23.10  #include "llmenugl.h"
   23.11 @@ -199,7 +200,7 @@
   23.12  	{
   23.13  		return TRUE;
   23.14  	}
   23.15 -	if (model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()))
   23.16 +	if (model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
   23.17  	{
   23.18  		return TRUE;
   23.19  	}
   23.20 @@ -380,7 +381,7 @@
   23.21  		return FALSE;
   23.22  	}
   23.23  
   23.24 -	BOOL is_agent_inventory = model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID());
   23.25 +	BOOL is_agent_inventory = model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
   23.26  	if (!LLInventoryClipboard::instance().hasContents() || !is_agent_inventory)
   23.27  	{
   23.28  		return FALSE;
   23.29 @@ -641,7 +642,7 @@
   23.30  
   23.31  		if (*type == DAD_CATEGORY)
   23.32  		{
   23.33 -			gInventory.startBackgroundFetch(obj->getUUID());
   23.34 +			LLInventoryModelBackgroundFetch::instance().start(obj->getUUID());
   23.35  		}
   23.36  
   23.37  		rv = TRUE;
   23.38 @@ -702,8 +703,8 @@
   23.39  {
   23.40  	LLInventoryModel* model = mInventoryPanel->getModel();
   23.41  	if(!model) return FALSE;
   23.42 -	if(gAgent.getInventoryRootID() == mUUID) return TRUE;
   23.43 -	return model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID());
   23.44 +	if(gInventory.getRootFolderID() == mUUID) return TRUE;
   23.45 +	return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
   23.46  }
   23.47  
   23.48  BOOL LLInvFVBridge::isItemPermissive() const
   23.49 @@ -1360,8 +1361,7 @@
   23.50  BOOL LLFolderBridge::isItemRemovable()
   23.51  {
   23.52  	LLInventoryModel* model = mInventoryPanel->getModel();
   23.53 -
   23.54 -	if(!model->isObjectDescendentOf(mUUID, gAgent.getInventoryRootID()))
   23.55 +	if (!model || !model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
   23.56  	{
   23.57  		return FALSE;
   23.58  	}
   23.59 @@ -3878,7 +3878,7 @@
   23.60  		LLUUID object_id = mUUID;
   23.61  		LLViewerInventoryItem* item;
   23.62  		item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
   23.63 -		if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID()))
   23.64 +		if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
   23.65  		{
   23.66  			rez_attachment(item, NULL, replace);
   23.67  		}
   23.68 @@ -3967,7 +3967,7 @@
   23.69  	item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
   23.70  	if (gSavedSettings.getBOOL("PhoenixDoubleClickWearInventoryObjects"))
   23.71  	{
   23.72 -		if(item && gInventory.isObjectDescendentOf(object_id, gAgent.getInventoryRootID()))
   23.73 +		if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
   23.74  		{
   23.75  			rez_attachment(item, NULL);
   23.76  		}
   23.77 @@ -4495,7 +4495,7 @@
   23.78  		}
   23.79  		if (pid.isNull())
   23.80  		{
   23.81 -			pid = gAgent.getInventoryRootID();
   23.82 +			pid = gInventory.getRootFolderID();
   23.83  		}
   23.84  		
   23.85  		LLUUID cat_id = gInventory.createNewCategory(pid, LLFolderType::FT_NONE, name);
   23.86 @@ -4594,7 +4594,7 @@
   23.87  	LLInventoryModel::cat_array_t cat_array;
   23.88  	LLInventoryModel::item_array_t item_array;
   23.89  	LLNameCategoryCollector has_name(name);
   23.90 -	gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
   23.91 +	gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
   23.92  									cat_array,
   23.93  									item_array,
   23.94  									LLInventoryModel::EXCLUDE_TRASH,
    24.1 --- a/indra/newview/llinventorymodel.cpp	Tue Dec 27 12:40:48 2011 +0100
    24.2 +++ b/indra/newview/llinventorymodel.cpp	Sat Jan 07 17:05:31 2012 +0100
    24.3 @@ -32,54 +32,33 @@
    24.4  
    24.5  #include "llviewerprecompiledheaders.h"
    24.6  
    24.7 +#include <deque>
    24.8 +
    24.9  #include "llinventorymodel.h"
   24.10  
   24.11 -#include "llassetstorage.h"
   24.12 -#include "llcrc.h"
   24.13  #include "lldir.h"
   24.14 -#include "llsys.h"
   24.15 -#include "llxfermanager.h"
   24.16 -#include "message.h"
   24.17 +#include "llsdutil.h"
   24.18  
   24.19  #include "llagent.h"
   24.20 +#include "llappviewer.h"
   24.21 +#include "llcallbacklist.h"
   24.22  #include "llfloater.h"
   24.23 -#include "llfocusmgr.h"
   24.24  #include "llinventoryview.h"
   24.25 -#include "llviewerinventory.h"
   24.26 -#include "llviewermessage.h"
   24.27 -#include "llviewerwindow.h"
   24.28 -#include "llviewerregion.h"
   24.29 -#include "llappviewer.h"
   24.30 -#include "lldbstrings.h"
   24.31 -#include "llviewerstats.h"
   24.32  #include "llmutelist.h"
   24.33 -#include "llcallbacklist.h"
   24.34  #include "llpreview.h"
   24.35  #include "llviewercontrol.h"
   24.36  #include "llviewerfoldertype.h"
   24.37 +#include "llviewerinventory.h"
   24.38 +#include "llviewermessage.h"
   24.39 +#include "llviewerregion.h"
   24.40 +#include "llviewerstats.h"
   24.41 +#include "llviewerwindow.h"
   24.42  #include "llvoavatar.h"
   24.43 -#include "llsdutil.h"
   24.44 -#include <deque>
   24.45  
   24.46  // [RLVa:KB]
   24.47  #include "rlvhandler.h"
   24.48  // [/RLVa:KB]
   24.49  
   24.50 -//#define DIFF_INVENTORY_FILES
   24.51 -#ifdef DIFF_INVENTORY_FILES
   24.52 -#include "process.h"
   24.53 -#endif
   24.54 -
   24.55 -BOOL LLInventoryModel::sBackgroundFetchActive = FALSE;
   24.56 -BOOL LLInventoryModel::sAllFoldersFetched = FALSE;
   24.57 -BOOL LLInventoryModel::sFullFetchStarted = FALSE;
   24.58 -S32  LLInventoryModel::sNumFetchRetries = 0;
   24.59 -F32  LLInventoryModel::sMinTimeBetweenFetches = 0.3f;
   24.60 -F32  LLInventoryModel::sMaxTimeBetweenFetches = 10.f;
   24.61 -BOOL LLInventoryModel::sTimelyFetchPending = FALSE;
   24.62 -LLFrameTimer LLInventoryModel::sFetchTimer;
   24.63 -S16 LLInventoryModel::sBulkFetchCount = 0;
   24.64 -
   24.65  // RN: for some reason, using std::queue in the header file confuses the compiler which thinks it's an xmlrpc_queue
   24.66  static std::deque<LLUUID> sFetchQueue;
   24.67  
   24.68 @@ -92,8 +71,6 @@
   24.69  ///----------------------------------------------------------------------------
   24.70  
   24.71  //BOOL decompress_file(const char* src_filename, const char* dst_filename);
   24.72 -const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
   24.73 -const S32 MAX_FETCH_RETRIES = 10;
   24.74  const char CACHE_FORMAT_STRING[] = "%s.inv"; 
   24.75  
   24.76  struct InventoryIDPtrLess
   24.77 @@ -161,8 +138,8 @@
   24.78  LLInventoryModel gInventory;
   24.79  
   24.80  // Default constructor
   24.81 -LLInventoryModel::LLInventoryModel() :
   24.82 -	mModifyMask(LLInventoryObserver::ALL),
   24.83 +LLInventoryModel::LLInventoryModel()
   24.84 +:	mModifyMask(LLInventoryObserver::ALL),
   24.85  	mChangedItemIDs(),
   24.86  	mCategoryMap(),
   24.87  	mItemMap(),
   24.88 @@ -172,6 +149,10 @@
   24.89  	mParentChildCategoryTree(),
   24.90  	mParentChildItemTree(),
   24.91  	mObservers(),
   24.92 +	mRootFolderID(),
   24.93 +	mLibraryRootFolderID(),
   24.94 +	mLibraryOwnerID(),
   24.95 +	mIsNotifyObservers(false),
   24.96  	mIsAgentInvUsable(false)
   24.97  {
   24.98  }
   24.99 @@ -179,6 +160,11 @@
  24.100  // Destroys the object
  24.101  LLInventoryModel::~LLInventoryModel()
  24.102  {
  24.103 +	cleanupInventory();
  24.104 +}
  24.105 +
  24.106 +void LLInventoryModel::cleanupInventory()
  24.107 +{
  24.108  	empty();
  24.109  	// Deleting one observer might erase others from the list, so always pop off the front
  24.110  	while (!mObservers.empty())
  24.111 @@ -257,10 +243,13 @@
  24.112  LLViewerInventoryCategory* LLInventoryModel::getCategory(const LLUUID& id) const
  24.113  {
  24.114  	LLViewerInventoryCategory* category = NULL;
  24.115 -	cat_map_t::const_iterator iter = mCategoryMap.find(id);
  24.116 -	if (iter != mCategoryMap.end())
  24.117 +	if (mCategoryMap.size() > 0)
  24.118  	{
  24.119 -		category = iter->second;
  24.120 +		cat_map_t::const_iterator iter = mCategoryMap.find(id);
  24.121 +		if (iter != mCategoryMap.end())
  24.122 +		{
  24.123 +			category = iter->second;
  24.124 +		}
  24.125  	}
  24.126  	return category;
  24.127  }
  24.128 @@ -319,7 +308,7 @@
  24.129  	LLUUID rv = findCatUUID(t);
  24.130  	if (rv.isNull() && isInventoryUsable() && create_folder)
  24.131  	{
  24.132 -		LLUUID root_id = gAgent.getInventoryRootID();
  24.133 +		LLUUID root_id = gInventory.getRootFolderID();
  24.134  		if (root_id.notNull())
  24.135  		{
  24.136  			rv = createNewCategory(root_id, t, LLStringUtil::null);
  24.137 @@ -339,9 +328,6 @@
  24.138  	{
  24.139  		const LLViewerInventoryCategory *cat = getCategory(parent_id);
  24.140  		if (!cat) break;
  24.141 -		// Ansariel: Original version
  24.142 -		//const LLAssetType::EType folder_type = cat->getPreferredType();
  24.143 -		//if (folder_type != LLAssetType::AT_NONE && folder_type != LLAssetType::AT_ROOT_CATEGORY)
  24.144  		const LLFolderType::EType folder_type = cat->getPreferredType();
  24.145  		if (folder_type != LLFolderType::FT_NONE && folder_type != LLFolderType::FT_ROOT_INVENTORY)
  24.146  		{
  24.147 @@ -356,7 +342,7 @@
  24.148  // preferred type. Returns LLUUID::null if not found.
  24.149  LLUUID LLInventoryModel::findCatUUID(LLFolderType::EType preferred_type)
  24.150  {
  24.151 -	LLUUID root_id = gAgent.getInventoryRootID();
  24.152 +	LLUUID root_id = gInventory.getRootFolderID();
  24.153  	if (preferred_type == LLFolderType::FT_ROOT_INVENTORY)
  24.154  	{
  24.155  		return root_id;
  24.156 @@ -382,7 +368,7 @@
  24.157  
  24.158  LLUUID LLInventoryModel::findCategoryByName(std::string name)
  24.159  {
  24.160 -	LLUUID root_id = gAgent.getInventoryRootID();
  24.161 +	LLUUID root_id = gInventory.getRootFolderID();
  24.162  	if(root_id.notNull())
  24.163  	{
  24.164  		cat_array_t* cats = NULL;
  24.165 @@ -579,7 +565,7 @@
  24.166  	LLInventoryModel::cat_array_t cat_array;
  24.167  	LLInventoryModel::item_array_t item_array;
  24.168  	LLLinkedItemIDMatches is_linked_item_match(object_id);
  24.169 -	collectDescendentsIf(gAgent.getInventoryRootID(),
  24.170 +	collectDescendentsIf(gInventory.getRootFolderID(),
  24.171  						 cat_array,
  24.172  						 item_array,
  24.173  						 LLInventoryModel::INCLUDE_TRASH,
  24.174 @@ -629,7 +615,7 @@
  24.175  	item_array_t items;
  24.176  	LLInventoryModel::cat_array_t cat_array;
  24.177  	LLLinkedItemIDMatches is_linked_item_match(id);
  24.178 -	collectDescendentsIf((start_folder_id == LLUUID::null ? gAgent.getInventoryRootID() : start_folder_id),
  24.179 +	collectDescendentsIf((start_folder_id == LLUUID::null ? gInventory.getRootFolderID() : start_folder_id),
  24.180  						 cat_array,
  24.181  						 items,
  24.182  						 LLInventoryModel::INCLUDE_TRASH,
  24.183 @@ -658,14 +644,9 @@
  24.184  	path.append(temp);
  24.185  }
  24.186  
  24.187 -bool LLInventoryModel::isInventoryUsable()
  24.188 +bool LLInventoryModel::isInventoryUsable() const
  24.189  {
  24.190 -	bool result = false;
  24.191 -	if(gAgent.getInventoryRootID().notNull() && mIsAgentInvUsable)
  24.192 -	{
  24.193 -		result = true;
  24.194 -	}
  24.195 -	return result;	
  24.196 +	return gInventory.getRootFolderID().notNull() && mIsAgentInvUsable;
  24.197  }
  24.198  
  24.199  // Calling this method with an inventory item will either change an
  24.200 @@ -1147,11 +1128,17 @@
  24.201  	return mObservers.find(observer) != mObservers.end();
  24.202  }
  24.203  
  24.204 -// Call this method when it's time to update everyone on a new state,
  24.205 -// by default, the inventory model will not update observers
  24.206 -// automatically.
  24.207 -// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
  24.208 -void LLInventoryModel::notifyObservers(const std::string service_name)
  24.209 +void LLInventoryModel::idleNotifyObservers()
  24.210 +{
  24.211 +	if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0))
  24.212 +	{
  24.213 +		return;
  24.214 +	}
  24.215 +	notifyObservers();
  24.216 +}
  24.217 +
  24.218 +// Call this method when it's time to update everyone on a new state.
  24.219 +void LLInventoryModel::notifyObservers()
  24.220  {
  24.221  	if (mIsNotifyObservers)
  24.222  	{
  24.223 @@ -1162,29 +1149,21 @@
  24.224  		return;
  24.225  	}
  24.226  
  24.227 -	mIsNotifyObservers = TRUE;
  24.228 +	mIsNotifyObservers = true;
  24.229  	for (observer_list_t::iterator iter = mObservers.begin();
  24.230  		 iter != mObservers.end(); )
  24.231  	{
  24.232  		LLInventoryObserver* observer = *iter;
  24.233  		
  24.234 -		if (service_name.empty())
  24.235 -		{
  24.236 -			observer->changed(mModifyMask);
  24.237 -		}
  24.238 -		else
  24.239 -		{
  24.240 -			observer->mMessageName = service_name;
  24.241 -			observer->changed(mModifyMask);
  24.242 -		}
  24.243 +		observer->changed(mModifyMask);
  24.244  
  24.245 -		// safe way to incrament since changed may delete entries! (@!##%@!@&*!)
  24.246 +		// safe way to increment since changed may delete entries! (@!##%@!@&*!)
  24.247  		iter = mObservers.upper_bound(observer); 
  24.248  	}
  24.249  
  24.250  	mModifyMask = LLInventoryObserver::NONE;
  24.251  	mChangedItemIDs.clear();
  24.252 -	mIsNotifyObservers = FALSE;
  24.253 +	mIsNotifyObservers = false;
  24.254  }
  24.255  
  24.256  // store flag for change
  24.257 @@ -1277,16 +1256,15 @@
  24.258  	{
  24.259  		changes |= gInventory.updateItem(*it);
  24.260  	}
  24.261 -	gInventory.notifyObservers("fetchinventory");
  24.262 +	gInventory.notifyObservers();
  24.263  	gViewerWindow->getWindow()->decBusyCount();
  24.264  }
  24.265  
  24.266  //If we get back an error (not found, etc...), handle it here
  24.267  void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::string& reason)
  24.268  {
  24.269 -	LL_INFOS("Inventory") << "fetchInventory::error "
  24.270 -		<< status << ": " << reason << LL_ENDL;
  24.271 -	gInventory.notifyObservers("fetchinventory");
  24.272 +	llinfos << "fetchInventory::error " << status << ": " << reason << llendl;
  24.273 +	gInventory.notifyObservers();
  24.274  }
  24.275  
  24.276  void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
  24.277 @@ -1314,508 +1292,14 @@
  24.278  	//{
  24.279  	//	known_descendents += items->count();
  24.280  	//}
  24.281 -	if(!cat->fetchDescendents())
  24.282 +	if (!cat->fetch())
  24.283  	{
  24.284  		LL_DEBUGS("Inventory") << "Not fetching descendents" <<  LL_ENDL;
  24.285  	}
  24.286  }
  24.287  
  24.288 -//Initialize statics.
  24.289 -bool LLInventoryModel::isBulkFetchProcessingComplete()
  24.290 -{
  24.291 -	return ( (sFetchQueue.empty() 
  24.292 -			&& sBulkFetchCount<=0)  ?  TRUE : FALSE ) ;
  24.293 -}
  24.294 -
  24.295 -class fetchDescendentsResponder: public LLHTTPClient::Responder
  24.296 -{
  24.297 -	public:
  24.298 -		fetchDescendentsResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
  24.299 -		//fetchDescendentsResponder() {};
  24.300 -		void result(const LLSD& content);
  24.301 -		void error(U32 status, const std::string& reason);
  24.302 -	public:
  24.303 -		typedef std::vector<LLViewerInventoryCategory*> folder_ref_t;
  24.304 -	protected:
  24.305 -		LLSD mRequestSD;
  24.306 -};
  24.307 -
  24.308 -//If we get back a normal response, handle it here
  24.309 -// Note: this is the handler for WebFetchInventoryDescendents and agent/inventory caps
  24.310 -void  fetchDescendentsResponder::result(const LLSD& content)
  24.311 -{
  24.312 -	LL_DEBUGS("Inventory") << " fetch descendents got " << ll_pretty_print_sd(content) << LL_ENDL; // OGPX
  24.313 -	if (content.has("folders"))	
  24.314 -	{
  24.315 -		for (LLSD::array_const_iterator folder_it = content["folders"].beginArray();
  24.316 -			 folder_it != content["folders"].endArray(); ++folder_it)
  24.317 -		{	
  24.318 -			LLSD folder_sd = *folder_it;		
  24.319 -
  24.320 -			//LLUUID agent_id = folder_sd["agent_id"];
  24.321 -			//if(agent_id != gAgent.getID())	//This should never happen.
  24.322 -			//{
  24.323 -			//	llwarns << "Got a UpdateInventoryItem for the wrong agent."
  24.324 -			//			<< llendl;
  24.325 -			//	break;
  24.326 -			//}
  24.327 -
  24.328 -			LLUUID parent_id = folder_sd["folder_id"];
  24.329 -			LLUUID owner_id = folder_sd["owner_id"];
  24.330 -			S32    version  = (S32)folder_sd["version"].asInteger();
  24.331 -			S32    descendents = (S32)folder_sd["descendents"].asInteger();
  24.332 -			LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
  24.333 -
  24.334 -            if (parent_id.isNull())
  24.335 -            {
  24.336 -			    LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
  24.337 -			    for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
  24.338 -				    item_it != folder_sd["items"].endArray();
  24.339 -				    ++item_it)
  24.340 -			    {	
  24.341 -                    const LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
  24.342 -                    if (lost_uuid.notNull())
  24.343 -                    {
  24.344 -				        LLSD item = *item_it;
  24.345 -				        titem->unpackMessage(item);
  24.346 -
  24.347 -                        LLInventoryModel::update_list_t update;
  24.348 -                        LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1);
  24.349 -                        update.push_back(new_folder);
  24.350 -                        gInventory.accountForUpdate(update);
  24.351 -
  24.352 -                        titem->setParent(lost_uuid);
  24.353 -                        titem->updateParentOnServer(FALSE);
  24.354 -                        gInventory.updateItem(titem);
  24.355 -                        gInventory.notifyObservers("fetchDescendents");
  24.356 -                        
  24.357 -                    }
  24.358 -                }
  24.359 -            }
  24.360 -
  24.361 -	        LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id);
  24.362 -			if (!pcat)
  24.363 -			{
  24.364 -				continue;
  24.365 -			}
  24.366 -
  24.367 -			for (LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray();
  24.368 -				 category_it != folder_sd["categories"].endArray(); ++category_it)
  24.369 -			{
  24.370 -				LLSD category = *category_it;
  24.371 -				tcategory->fromLLSD(category); 
  24.372 -
  24.373 -				if (LLInventoryModel::sFullFetchStarted)
  24.374 -				{
  24.375 -					sFetchQueue.push_back(tcategory->getUUID());
  24.376 -				}
  24.377 -				else if ( !gInventory.isCategoryComplete(tcategory->getUUID()))
  24.378 -				{
  24.379 -					gInventory.updateCategory(tcategory);
  24.380 -				}
  24.381 -			}
  24.382 -
  24.383 -			LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
  24.384 -			for (LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
  24.385 -				item_it != folder_sd["items"].endArray();
  24.386 -				++item_it)
  24.387 -			{	
  24.388 -				LLSD item = *item_it;
  24.389 -				titem->unpackMessage(item);
  24.390 -				gInventory.updateItem(titem);
  24.391 -			}
  24.392 -
  24.393 -			// set version and descendentcount according to message.
  24.394 -			LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);
  24.395 -			if (cat)
  24.396 -			{
  24.397 -				cat->setVersion(version);
  24.398 -				cat->setDescendentCount(descendents);
  24.399 -			}
  24.400 -		}
  24.401 -	}
  24.402 -
  24.403 -	if (content.has("bad_folders"))
  24.404 -	{
  24.405 -		for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray();
  24.406 -			folder_it != content["bad_folders"].endArray();
  24.407 -			++folder_it)
  24.408 -		{	
  24.409 -			LLSD folder_sd = *folder_it;
  24.410 -
  24.411 -			//These folders failed on the dataserver.  We probably don't want to retry them.
  24.412 -			LL_INFOS("Inventory") << "Folder " << folder_sd["folder_id"].asString() 
  24.413 -					<< "Error: " << folder_sd["error"].asString() << LL_ENDL;
  24.414 -		}
  24.415 -	}
  24.416 -
  24.417 -	LLInventoryModel::incrBulkFetch(-1);
  24.418 -
  24.419 -	if (LLInventoryModel::isBulkFetchProcessingComplete())
  24.420 -	{
  24.421 -		LL_DEBUGS("Inventory") << "Inventory fetch completed" << LL_ENDL;
  24.422 -		if (LLInventoryModel::sFullFetchStarted)
  24.423 -		{
  24.424 -			LLInventoryModel::sAllFoldersFetched = TRUE;
  24.425 -		}
  24.426 -		LLInventoryModel::stopBackgroundFetch();
  24.427 -	}
  24.428 -
  24.429 -	gInventory.notifyObservers("fetchDescendents");
  24.430 -}
  24.431 -
  24.432 -//If we get back an error (not found, etc...), handle it here
  24.433 -void fetchDescendentsResponder::error(U32 status, const std::string& reason)
  24.434 -{
  24.435 -	LL_INFOS("Inventory") << "fetchDescendentsResponder::error " << status << ": " << reason << LL_ENDL;
  24.436 -
  24.437 -	LLInventoryModel::incrBulkFetch(-1);
  24.438 -
  24.439 -	if (status==499)		//timed out.  Let's be awesome!
  24.440 -	{
  24.441 -		for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
  24.442 -			folder_it != mRequestSD["folders"].endArray();
  24.443 -			++folder_it)
  24.444 -		{	
  24.445 -			LLSD folder_sd = *folder_it;
  24.446 -			LLUUID folder_id = folder_sd["folder_id"];
  24.447 -			sFetchQueue.push_front(folder_id);
  24.448 -		}
  24.449 -	}
  24.450 -	else
  24.451 -	{
  24.452 -		if (LLInventoryModel::isBulkFetchProcessingComplete())
  24.453 -		{
  24.454 -			if (LLInventoryModel::sFullFetchStarted)
  24.455 -			{
  24.456 -				LLInventoryModel::sAllFoldersFetched = TRUE;
  24.457 -			}
  24.458 -			LLInventoryModel::stopBackgroundFetch();
  24.459 -		}
  24.460 -	}
  24.461 -	gInventory.notifyObservers("fetchDescendents");
  24.462 -}
  24.463 -
  24.464 -//static   Bundle up a bunch of requests to send all at once.
  24.465 -void LLInventoryModel::bulkFetch(std::string url)
  24.466 -{
  24.467 -	//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.
  24.468 -	//If there are items in sFetchQueue, we want to check the time since the last bulkFetch was 
  24.469 -	//sent.  If it exceeds our retry time, go ahead and fire off another batch.  
  24.470 -	//Stopbackgroundfetch will be run from the Responder instead of here.  
  24.471 -
  24.472 -	S16 max_concurrent_fetches=8;
  24.473 -	F32 new_min_time = 0.5f;			//HACK!  Clean this up when old code goes away entirely.
  24.474 -	if (sMinTimeBetweenFetches < new_min_time) sMinTimeBetweenFetches=new_min_time;  //HACK!  See above.
  24.475 -	
  24.476 -	if (gDisconnected || sBulkFetchCount > max_concurrent_fetches ||
  24.477 -		sFetchTimer.getElapsedTimeF32() < sMinTimeBetweenFetches)
  24.478 -	{
  24.479 -		return; // just bail if we are disconnected.
  24.480 -	}	
  24.481 -
  24.482 -	U32 folder_count=0;
  24.483 -	U32 max_batch_size=5;
  24.484 -
  24.485 -	U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
  24.486 -
  24.487 -	LLSD body;
  24.488 -	LLSD body_lib;
  24.489 -	while( !(sFetchQueue.empty() ) && (folder_count < max_batch_size) )
  24.490 -	{
  24.491 -        if (sFetchQueue.front().isNull()) //DEV-17797
  24.492 -        {
  24.493 -			LLSD folder_sd;
  24.494 -			folder_sd["folder_id"]		= LLUUID::null.asString();
  24.495 -			folder_sd["owner_id"]		= gAgent.getID();
  24.496 -			folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
  24.497 -			folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE;
  24.498 -			folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
  24.499 -			body["folders"].append(folder_sd);
  24.500 -            folder_count++;
  24.501 -        }
  24.502 -        else
  24.503 -        {
  24.504 -		    LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
  24.505 -		    if (cat)
  24.506 -		    {
  24.507 -			    if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
  24.508 -			    {
  24.509 -				    LLSD folder_sd;
  24.510 -				    folder_sd["folder_id"]		= cat->getUUID();
  24.511 -				    folder_sd["owner_id"]		= cat->getOwnerID();
  24.512 -				    folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
  24.513 -				    folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted;
  24.514 -				    folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
  24.515 -
  24.516 -					LL_DEBUGS("Inventory") << " fetching "<<cat->getUUID()<<" with cat owner "<<cat->getOwnerID()<<" and agent" << gAgent.getID() << LL_ENDL;
  24.517 -				    //OGPX if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
  24.518 -					// for OGP it really doesnt make sense to have the decision about whether to fetch
  24.519 -					// from the library or user cap be determined by a hard coded UUID. 
  24.520 -					// if it isnt an item that belongs to the agent, then fetch from the library
  24.521 -					if (gAgent.getID() != cat->getOwnerID()) //if i am not the owner, it must be in the library
  24.522 -					    body_lib["folders"].append(folder_sd);
  24.523 -				    else
  24.524 -					    body["folders"].append(folder_sd);
  24.525 -				    folder_count++;
  24.526 -			    }
  24.527 -			    if (sFullFetchStarted)
  24.528 -			    {	//Already have this folder but append child folders to list.
  24.529 -				    // add all children to queue
  24.530 -				    parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
  24.531 -				    if (cat_it != gInventory.mParentChildCategoryTree.end())
  24.532 -				    {
  24.533 -					    cat_array_t* child_categories = cat_it->second;
  24.534 -
  24.535 -					    for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
  24.536 -					    {
  24.537 -						    sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
  24.538 -					    }
  24.539 -				    }
  24.540 -    
  24.541 -			    }
  24.542 -		    }
  24.543 -        }
  24.544 -		sFetchQueue.pop_front();
  24.545 -	}
  24.546 -
  24.547 -	if (folder_count > 0)
  24.548 -	{
  24.549 -		sBulkFetchCount++;
  24.550 -		if (body["folders"].size())
  24.551 -		{
  24.552 -			LL_DEBUGS("Inventory") << " fetch descendents post to " << url << ": " << ll_pretty_print_sd(body) << LL_ENDL; // OGPX
  24.553 -			LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0);
  24.554 -		}
  24.555 -		if (body_lib["folders"].size())
  24.556 -		{
  24.557 -			std::string url_lib;
  24.558 -			if (!gSavedSettings.getBOOL("OpenGridProtocol"))
  24.559 -			{
  24.560 -				url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
  24.561 -			}
  24.562 -			else
  24.563 -			{
  24.564 -				url_lib = gAgent.getCapability("agent/inventory_library");
  24.565 -			}
  24.566 -			LL_DEBUGS("Inventory") << " fetch descendents lib post: " << ll_pretty_print_sd(body_lib) << LL_ENDL; // OGPX
  24.567 -			LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0);
  24.568 -		}
  24.569 -		sFetchTimer.reset();
  24.570 -	}
  24.571 -	else if (isBulkFetchProcessingComplete())
  24.572 -	{
  24.573 -		if (sFullFetchStarted)
  24.574 -		{
  24.575 -			sAllFoldersFetched = TRUE;
  24.576 -		}
  24.577 -		stopBackgroundFetch();
  24.578 -	}	
  24.579 -}
  24.580 -
  24.581 -// static
  24.582 -bool LLInventoryModel::isEverythingFetched()
  24.583 -{
  24.584 -	return (sAllFoldersFetched ? true : false);
  24.585 -}
  24.586 -
  24.587 -//static
  24.588 -BOOL LLInventoryModel::backgroundFetchActive()
  24.589 -{
  24.590 -	return sBackgroundFetchActive;
  24.591 -}
  24.592 -
  24.593 -//static 
  24.594 -void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
  24.595 -{
  24.596 -	if (!sAllFoldersFetched)
  24.597 -	{
  24.598 -		sBackgroundFetchActive = TRUE;
  24.599 -		if (cat_id.isNull())
  24.600 -		{
  24.601 -			if (!sFullFetchStarted)
  24.602 -			{
  24.603 -				sFullFetchStarted = TRUE;
  24.604 -				sFetchQueue.push_back(gInventoryLibraryRoot);
  24.605 -				sFetchQueue.push_back(gAgent.getInventoryRootID());
  24.606 -				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
  24.607 -			}
  24.608 -		}
  24.609 -		else
  24.610 -		{
  24.611 -			// specific folder requests go to front of queue
  24.612 -			if (sFetchQueue.empty() || sFetchQueue.front() != cat_id)
  24.613 -			{
  24.614 -				sFetchQueue.push_front(cat_id);
  24.615 -				gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
  24.616 -			}
  24.617 -		}
  24.618 -	}
  24.619 -}
  24.620 -
  24.621 -//static
  24.622 -void LLInventoryModel::findLostItems()
  24.623 -{
  24.624 -	sBackgroundFetchActive = TRUE;
  24.625 -    sFetchQueue.push_back(LLUUID::null);
  24.626 -    gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
  24.627 -}
  24.628 -
  24.629 -//static
  24.630 -void LLInventoryModel::stopBackgroundFetch()
  24.631 -{
  24.632 -	if (sBackgroundFetchActive)
  24.633 -	{
  24.634 -		sBackgroundFetchActive = FALSE;
  24.635 -		gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL);
  24.636 -		sBulkFetchCount=0;
  24.637 -		sMinTimeBetweenFetches=0.0f;
  24.638 -//		sFullFetchStarted=FALSE;
  24.639 -	}
  24.640 -}
  24.641 -
  24.642 -//static 
  24.643 -void LLInventoryModel::backgroundFetch(void*)
  24.644 -{
  24.645 -	if (sBackgroundFetchActive && gAgent.getRegion())
  24.646 -	{
  24.647 -	    // OGPX : agent/inventory is on gAgent for OGPX. I check both, and give
  24.648 -		// ...preference to the one on gAgent. That way the existing non OGP path will remain the same. 
  24.649 -        // Q: How *should* I handle deciding which cap to use? Maybe I don't want to trust fetching inventory from the region
  24.650 -		// OGPX TODO: manage getting caps from more than one service securely. 
  24.651 -		std::string url = gAgent.getCapability("agent/inventory"); // was WebFetchInventoryDescendents
  24.652 -		if (url.empty()) 
  24.653 -		{
  24.654 -			// OGPX : if we didn't get an agent/inventory cap from the Agent Domain, check to see if there was one on the region
  24.655 -			// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
  24.656 -			// OGPX TODO: this should change when Capabilities are refactored. 
  24.657 -			// ... this is a trust/security issue. if we have an agent/inventory from the Agent Domain, 
  24.658 -			// maybe we shouldn't trust WFID from region.
  24.659 -			LL_DEBUGS("Inventory") << " no agent/inventory not on AD, checking fallback to region " << LL_ENDL; 
  24.660 -			url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); 
  24.661 -		}
  24.662 -		if (!url.empty()) 
  24.663 -		{
  24.664 -			bulkFetch(url);
  24.665 -			return;
  24.666 -		}
  24.667 -
  24.668 -		// If there was no HTTP cap to fetch with, then do the UDP fetch
  24.669 -		//DEPRECATED OLD CODE FOLLOWS.
  24.670 -		// no more categories to fetch, stop fetch process
  24.671 -		if (sFetchQueue.empty())
  24.672 -		{
  24.673 -			LL_DEBUGS("Inventory") << "Inventory fetch completed" << LL_ENDL;
  24.674 -			if (sFullFetchStarted)
  24.675 -			{
  24.676 -				sAllFoldersFetched = TRUE;
  24.677 -			}
  24.678 -			stopBackgroundFetch();
  24.679 -			return;
  24.680 -		}
  24.681 -
  24.682 -		F32 fast_fetch_time = lerp(sMinTimeBetweenFetches, sMaxTimeBetweenFetches, 0.1f);
  24.683 -		F32 slow_fetch_time = lerp(sMinTimeBetweenFetches, sMaxTimeBetweenFetches, 0.5f);
  24.684 -		if (sTimelyFetchPending && sFetchTimer.getElapsedTimeF32() > slow_fetch_time)
  24.685 -		{
  24.686 -			// double timeouts on failure
  24.687 -			sMinTimeBetweenFetches = llmin(sMinTimeBetweenFetches * 2.f, 10.f);
  24.688 -			sMaxTimeBetweenFetches = llmin(sMaxTimeBetweenFetches * 2.f, 120.f);
  24.689 -			LL_DEBUGS("Inventory") << "Inventory fetch times grown to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << LL_ENDL;
  24.690 -			// fetch is no longer considered "timely" although we will wait for full time-out
  24.691 -			sTimelyFetchPending = FALSE;
  24.692 -		}
  24.693 -
  24.694 -		while(1)
  24.695 -		{
  24.696 -			if (gDisconnected || sFetchQueue.empty())
  24.697 -			{
  24.698 -				break;
  24.699 -			}
  24.700 -
  24.701 -			LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
  24.702 -
  24.703 -			// category has been deleted, remove from queue.
  24.704 -			if (!cat)
  24.705 -			{
  24.706 -				sFetchQueue.pop_front();
  24.707 -				continue;
  24.708 -			}
  24.709 -
  24.710 -			if (sFetchTimer.getElapsedTimeF32() > sMinTimeBetweenFetches && 
  24.711 -				LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
  24.712 -			{
  24.713 -				// category exists but has no children yet, fetch the descendants
  24.714 -				// for now, just request every time and rely on retry timer to throttle
  24.715 -				if (cat->fetchDescendents())
  24.716 -				{
  24.717 -					sFetchTimer.reset();
  24.718 -					sTimelyFetchPending = TRUE;
  24.719 -				}
  24.720 -				else
  24.721 -				{
  24.722 -					//  The catagory also tracks if it has expired and here it says it hasn't
  24.723 -					//  yet.  Get out of here because nothing is going to happen until we
  24.724 -					//  update the timers.
  24.725 -					break;
  24.726 -				}
  24.727 -			}
  24.728 -			// do I have all my children?
  24.729 -			else if (gInventory.isCategoryComplete(sFetchQueue.front()))
  24.730 -			{
  24.731 -				// finished with this category, remove from queue
  24.732 -				sFetchQueue.pop_front();
  24.733 -
  24.734 -				// add all children to queue
  24.735 -				parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
  24.736 -				if (cat_it != gInventory.mParentChildCategoryTree.end())
  24.737 -				{
  24.738 -					cat_array_t* child_categories = cat_it->second;
  24.739 -
  24.740 -					for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
  24.741 -					{
  24.742 -						sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
  24.743 -					}
  24.744 -				}
  24.745 -
  24.746 -				// we received a response in less than the fast time
  24.747 -				if (sTimelyFetchPending && sFetchTimer.getElapsedTimeF32() < fast_fetch_time)
  24.748 -				{
  24.749 -					// shrink timeouts based on success
  24.750 -					sMinTimeBetweenFetches = llmax(sMinTimeBetweenFetches * 0.8f, 0.3f);
  24.751 -					sMaxTimeBetweenFetches = llmax(sMaxTimeBetweenFetches * 0.8f, 10.f);
  24.752 -					//llinfos << "Inventory fetch times shrunk to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << llendl;
  24.753 -				}
  24.754 -
  24.755 -				sTimelyFetchPending = FALSE;
  24.756 -				continue;
  24.757 -			}
  24.758 -			else if (sFetchTimer.getElapsedTimeF32() > sMaxTimeBetweenFetches)
  24.759 -			{
  24.760 -				// received first packet, but our num descendants does not match db's num descendants
  24.761 -				// so try again later
  24.762 -				LLUUID fetch_id = sFetchQueue.front();
  24.763 -				sFetchQueue.pop_front();
  24.764 -
  24.765 -				if (sNumFetchRetries++ < MAX_FETCH_RETRIES)
  24.766 -				{
  24.767 -					// push on back of queue
  24.768 -					sFetchQueue.push_back(fetch_id);
  24.769 -				}
  24.770 -				sTimelyFetchPending = FALSE;
  24.771 -				sFetchTimer.reset();
  24.772 -				break;
  24.773 -			}
  24.774 -
  24.775 -			// not enough time has elapsed to do a new fetch
  24.776 -			break;
  24.777 -		}
  24.778 -	}
  24.779 -}
  24.780 -
  24.781 -void LLInventoryModel::cache(
  24.782 -	const LLUUID& parent_folder_id,
  24.783 -	const LLUUID& agent_id)
  24.784 +void LLInventoryModel::cache(const LLUUID& parent_folder_id,
  24.785 +							 const LLUUID& agent_id)
  24.786  {
  24.787  	lldebugs << "Caching " << parent_folder_id << " for " << agent_id
  24.788  			 << llendl;
  24.789 @@ -1827,12 +1311,8 @@
  24.790  
  24.791  	LLCanCache can_cache(this);
  24.792  	can_cache(root_cat, NULL);
  24.793 -	collectDescendentsIf(
  24.794 -		parent_folder_id,
  24.795 -		categories,
  24.796 -		items,
  24.797 -		INCLUDE_TRASH,
  24.798 -		can_cache);
  24.799 +	collectDescendentsIf(parent_folder_id, categories, items, INCLUDE_TRASH,
  24.800 +						 can_cache);
  24.801  	std::string agent_id_str;
  24.802  	std::string inventory_filename;
  24.803  	agent_id.toString(agent_id_str);
  24.804 @@ -2456,7 +1936,7 @@
  24.805  			else
  24.806  			{
  24.807  				// it's a protected folder.
  24.808 -				cat->setParent(gAgent.getInventoryRootID());
  24.809 +				cat->setParent(gInventory.getRootFolderID());
  24.810  			}
  24.811  			cat->updateServer(TRUE);
  24.812  			catsp = getUnlockedCatArray(cat->getParentUUID());
  24.813 @@ -2556,7 +2036,7 @@
  24.814  		}
  24.815  	}
  24.816  
  24.817 -	const LLUUID& agent_inv_root_id = gAgent.getInventoryRootID();
  24.818 +	const LLUUID& agent_inv_root_id = gInventory.getRootFolderID();
  24.819  	if (agent_inv_root_id.notNull())
  24.820  	{
  24.821  		cat_array_t* catsp = get_ptr_in_map(mParentChildCategoryTree, agent_inv_root_id);
  24.822 @@ -2749,12 +2229,6 @@
  24.823  // static
  24.824  void LLInventoryModel::registerCallbacks(LLMessageSystem* msg)
  24.825  {
  24.826 -	//msg->setHandlerFuncFast(_PREHASH_InventoryUpdate,
  24.827 -	//					processInventoryUpdate,
  24.828 -	//					NULL);
  24.829 -	//msg->setHandlerFuncFast(_PREHASH_UseCachedInventory,
  24.830 -	//					processUseCachedInventory,
  24.831 -	//					NULL);
  24.832  	msg->setHandlerFuncFast(_PREHASH_UpdateCreateInventoryItem,
  24.833  						processUpdateCreateInventoryItem,
  24.834  						NULL);
  24.835 @@ -2767,15 +2241,6 @@
  24.836  	msg->setHandlerFuncFast(_PREHASH_RemoveInventoryFolder,
  24.837  						processRemoveInventoryFolder,
  24.838  						NULL);
  24.839 -	//msg->setHandlerFuncFast(_PREHASH_ExchangeCallingCard,
  24.840 -	//						processExchangeCallingcard,
  24.841 -	//						NULL);
  24.842 -	//msg->setHandlerFuncFast(_PREHASH_AddCallingCard,
  24.843 -	//					processAddCallingcard,
  24.844 -	//					NULL);
  24.845 -	//msg->setHandlerFuncFast(_PREHASH_DeclineCallingCard,
  24.846 -	//					processDeclineCallingcard,
  24.847 -	//					NULL);
  24.848  	msg->setHandlerFuncFast(_PREHASH_SaveAssetIntoInventory,
  24.849  						processSaveAssetIntoInventory,
  24.850  						NULL);
  24.851 @@ -3417,6 +2882,36 @@
  24.852  	}
  24.853  }
  24.854  
  24.855 +const LLUUID &LLInventoryModel::getRootFolderID() const
  24.856 +{
  24.857 +	return mRootFolderID;
  24.858 +}
  24.859 +
  24.860 +void LLInventoryModel::setRootFolderID(const LLUUID& val)
  24.861 +{
  24.862 +	mRootFolderID = val;
  24.863 +}
  24.864 +
  24.865 +const LLUUID &LLInventoryModel::getLibraryRootFolderID() const
  24.866 +{
  24.867 +	return mLibraryRootFolderID;
  24.868 +}
  24.869 +
  24.870 +void LLInventoryModel::setLibraryRootFolderID(const LLUUID& val)
  24.871 +{
  24.872 +	mLibraryRootFolderID = val;
  24.873 +}
  24.874 +
  24.875 +const LLUUID &LLInventoryModel::getLibraryOwnerID() const
  24.876 +{
  24.877 +	return mLibraryOwnerID;
  24.878 +}
  24.879 +
  24.880 +void LLInventoryModel::setLibraryOwnerID(const LLUUID& val)
  24.881 +{
  24.882 +	mLibraryOwnerID = val;
  24.883 +}
  24.884 +
  24.885  ///----------------------------------------------------------------------------
  24.886  /// LLInventoryCollectFunctor implementations
  24.887  ///----------------------------------------------------------------------------
  24.888 @@ -3783,7 +3278,7 @@
  24.889  		if(!cat) continue;
  24.890  		if(!isComplete(cat))
  24.891  		{
  24.892 -			cat->fetchDescendents();		//blindly fetch it without seeing if anything else is fetching it.
  24.893 +			cat->fetch();	// blindly fetch it without seeing if anything else is fetching it.
  24.894  			mIncompleteFolders.push_back(*it);	//Add to list of things being downloaded for this observer.
  24.895  		}
  24.896  		else
  24.897 @@ -3886,7 +3381,7 @@
  24.898  		if(!cat) continue;
  24.899  		if(!gInventory.isCategoryComplete(*fit))
  24.900  		{
  24.901 -			cat->fetchDescendents();
  24.902 +			cat->fetch();
  24.903  			lldebugs << "fetching folder " << *fit <<llendl;
  24.904  			mIncompleteFolders.push_back(*fit);
  24.905  		}
    25.1 --- a/indra/newview/llinventorymodel.h	Tue Dec 27 12:40:48 2011 +0100
    25.2 +++ b/indra/newview/llinventorymodel.h	Sat Jan 07 17:05:31 2012 +0100
    25.3 @@ -95,22 +95,30 @@
    25.4  class LLMessageSystem;
    25.5  class LLInventoryCollectFunctor;
    25.6  
    25.7 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    25.8 +// LLInventoryModel
    25.9 +//
   25.10 +// Represents a collection of inventory, and provides efficient ways to access 
   25.11 +// that information.
   25.12 +//   NOTE: This class could in theory be used for any place where you need 
   25.13 +//   inventory, though it optimizes for time efficiency - not space efficiency, 
   25.14 +//   probably making it inappropriate for use on tasks.
   25.15 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   25.16  class LLInventoryModel
   25.17  {
   25.18  public:
   25.19 -	typedef enum e_has_children
   25.20 +	friend class LLInventoryModelFetchDescendentsResponder;
   25.21 +
   25.22 +	enum EHasChildren
   25.23  	{
   25.24  		CHILDREN_NO,
   25.25  		CHILDREN_YES,
   25.26  		CHILDREN_MAYBE
   25.27 -	}EHasChildren;
   25.28 +	};
   25.29  
   25.30 -	// These are used a lot...
   25.31  	typedef LLDynamicArray<LLPointer<LLViewerInventoryCategory> > cat_array_t;
   25.32  	typedef LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array_t;
   25.33 -	// construction & destruction
   25.34 -	LLInventoryModel();
   25.35 -	~LLInventoryModel();
   25.36 +	typedef std::set<LLUUID> changed_items_t;
   25.37  
   25.38  	class fetchInventoryResponder: public LLHTTPClient::Responder
   25.39  	{
   25.40 @@ -119,61 +127,119 @@
   25.41  		void result(const LLSD& content);			
   25.42  		void error(U32 status, const std::string& reason);
   25.43  
   25.44 -	public:
   25.45  		typedef std::vector<LLViewerInventoryCategory*> folder_ref_t;
   25.46 +
   25.47  	protected:
   25.48  		LLSD mRequestSD;
   25.49  	};
   25.50  
   25.51 +	//--------------------------------------------------------------------
   25.52 +	// Constructors / Destructors
   25.53 +	//--------------------------------------------------------------------
   25.54 +public:
   25.55 +	LLInventoryModel();
   25.56 +	~LLInventoryModel();
   25.57 +	void cleanupInventory();
   25.58 +
   25.59 +protected:
   25.60 +	// Empty the entire contents
   25.61 +	void empty();
   25.62 +
   25.63 +	//--------------------------------------------------------------------
   25.64 +	// Initialization
   25.65 +	//--------------------------------------------------------------------
   25.66 +public:
   25.67 +	// The inventory model usage is sensitive to the initial construction of the model
   25.68 +	bool isInventoryUsable() const;
   25.69 +
   25.70 +private:
   25.71 +	bool mIsAgentInvUsable; // used to handle an invalid inventory state
   25.72 +
   25.73 +	//--------------------------------------------------------------------
   25.74 +	// Root Folders
   25.75 +	//--------------------------------------------------------------------
   25.76 +public:
   25.77 +	// The following are set during login with data from the server
   25.78 +	void setRootFolderID(const LLUUID& id);
   25.79 +	void setLibraryOwnerID(const LLUUID& id);
   25.80 +	void setLibraryRootFolderID(const LLUUID& id);
   25.81 +
   25.82 +	const LLUUID &getRootFolderID() const;
   25.83 +	const LLUUID &getLibraryOwnerID() const;
   25.84 +	const LLUUID &getLibraryRootFolderID() const;
   25.85 +
   25.86 +private:
   25.87 +	LLUUID mRootFolderID;
   25.88 +	LLUUID mLibraryRootFolderID;
   25.89 +	LLUUID mLibraryOwnerID;
   25.90 +
   25.91 +	//--------------------------------------------------------------------
   25.92 +	// Structure
   25.93 +	//--------------------------------------------------------------------
   25.94 +public:
   25.95 +	// Methods to load up inventory skeleton & meat. These are used
   25.96 +	// during authentication. Returns true if everything parsed.
   25.97 +	bool loadSkeleton(const LLSD& options, const LLUUID& owner_id);
   25.98 +	// Legacy method for old XML-RPC login (to remove once llstartup.cpp is
   25.99 +	// updated to v2/3 viewer code).
  25.100 +	typedef std::map<std::string, std::string> response_t;
  25.101 +	typedef std::vector<response_t> options_t;
  25.102 +	bool loadSkeleton(const options_t& options, const LLUUID& owner_id);
  25.103 +
  25.104 +	// Brute force method to rebuild the entire parent-child relations.
  25.105 +	void buildParentChildMap();
  25.106 +
  25.107 +	// Call on logout to save a terse representation.
  25.108 +	void cache(const LLUUID& parent_folder_id, const LLUUID& agent_id);
  25.109 +
  25.110 +private:
  25.111 +	// Information for tracking the actual inventory. We index this
  25.112 +	// information in a lot of different ways so we can access
  25.113 +	// the inventory using several different identifiers.
  25.114 +	// mCategoryMap and mItemMap store uuid->object mappings. 
  25.115 +	typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
  25.116 +	typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
  25.117 +	cat_map_t mCategoryMap;
  25.118 +	item_map_t mItemMap;
  25.119 +	// This last set of indices is used to map parents to children.
  25.120 +	typedef std::map<LLUUID, cat_array_t*> parent_cat_map_t;
  25.121 +	typedef std::map<LLUUID, item_array_t*> parent_item_map_t;
  25.122 +	parent_cat_map_t mParentChildCategoryTree;
  25.123 +	parent_item_map_t mParentChildItemTree;
  25.124 +
  25.125 +
  25.126 +	//--------------------------------------------------------------------
  25.127 +	// Login
  25.128 +	//--------------------------------------------------------------------
  25.129 +private:
  25.130 +	const static S32 sCurrentInvCacheVersion; // expected inventory cache version
  25.131 +
  25.132  	//
  25.133  	// Accessors
  25.134  	//
  25.135  
  25.136 -	// This is a convenience function to check if one object has a
  25.137 -	// parent chain up to the category specified by UUID.
  25.138 -	BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id);
  25.139 -
  25.140 -	// Get the object by id. Returns NULL if not found.
  25.141 -	// * WARNING: use the pointer returned for read operations - do
  25.142 -	// not modify the object values in place or you will break stuff.
  25.143 -	LLInventoryObject* getObject(const LLUUID& id) const;
  25.144 -
  25.145 -	// Get the item by id. Returns NULL if not found.
  25.146 -	// * WARNING: use the pointer for read operations - use the
  25.147 -	// updateItem() method to actually modify values.
  25.148 -	LLViewerInventoryItem* getItem(const LLUUID& id) const;
  25.149 -
  25.150 -	// Get the category by id. Returns NULL if not found.
  25.151 -	// * WARNING: use the pointer for read operations - use the
  25.152 -	// updateCategory() method to actually modify values.
  25.153 -	LLViewerInventoryCategory* getCategory(const LLUUID& id) const;
  25.154 -
  25.155 -	// Return the number of items or categories
  25.156 -	S32 getItemCount() const;
  25.157 -	S32 getCategoryCount() const;
  25.158 +	//--------------------------------------------------------------------
  25.159 +	// Descendents
  25.160 +	//--------------------------------------------------------------------
  25.161 +public:
  25.162 +	// Make sure we have the descendents in the structure.
  25.163 +	void fetchDescendentsOf(const LLUUID& folder_id);
  25.164  
  25.165  	// Return the direct descendents of the id provided.Set passed
  25.166  	// in values to NULL if the call fails.
  25.167 -	// *WARNING: The array provided points straight into the guts of
  25.168 -	// this object, and should only be used for read operations, since
  25.169 -	// modifications may invalidate the internal state of the
  25.170 -	// inventory.
  25.171 +	//    NOTE: The array provided points straight into the guts of
  25.172 +	//    this object, and should only be used for read operations, since
  25.173 +	//    modifications may invalidate the internal state of the inventory.
  25.174  	void getDirectDescendentsOf(const LLUUID& cat_id,
  25.175  								cat_array_t*& categories,
  25.176  								item_array_t*& items) const;
  25.177  	
  25.178 -	// SJB: Added version to lock the arrays to catch potential logic bugs
  25.179 -	void lockDirectDescendentArrays(const LLUUID& cat_id,
  25.180 -									cat_array_t*& categories,
  25.181 -									item_array_t*& items);
  25.182 -	void unlockDirectDescendentArrays(const LLUUID& cat_id);
  25.183 -	
  25.184 -	// Starting with the object specified, add it's descendents to the
  25.185 +	// Starting with the object specified, add its descendents to the
  25.186  	// array provided, but do not add the inventory object specified
  25.187 -	// by id. There is no guaranteed order. Neither array will be
  25.188 -	// erased before adding objects to it. Do not store a copy of the
  25.189 -	// pointers collected - use them, and collect them again later if
  25.190 -	// you need to reference the same objects.
  25.191 +	// by id. There is no guaranteed order. 
  25.192 +	//    NOTE: Neither array will be erased before adding objects to it. 
  25.193 +	//    Do not store a copy of the pointers collected - use them, and 
  25.194 +	//    collect them again later if you need to reference the same objects.
  25.195  	enum {
  25.196  		EXCLUDE_TRASH = FALSE,
  25.197  		INCLUDE_TRASH = TRUE
  25.198 @@ -194,50 +260,91 @@
  25.199  	item_array_t collectLinkedItems(const LLUUID& item_id,
  25.200  									const LLUUID& start_folder_id = LLUUID::null);
  25.201  
  25.202 +	// Check if one object has a parent chain up to the category specified by UUID.
  25.203 +	BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id);
  25.204 +
  25.205 +	//--------------------------------------------------------------------
  25.206 +	// Find
  25.207 +	//--------------------------------------------------------------------
  25.208 +public:
  25.209 +	// Returns the uuid of the category that specifies 'type' as what it
  25.210 +	// defaults to containing. The category is not necessarily only for that type.
  25.211 +	// NOTE: If create_folder is true, this will create a new inventory category
  25.212 +	// on the fly if one does not exist.
  25.213 +	LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type,
  25.214 +								   bool create_folder = true);
  25.215 +
  25.216 +	// Get the object by id. Returns NULL if not found.
  25.217 +	//   NOTE: Use the pointer returned for read operations - do
  25.218 +	//   not modify the object values in place or you will break stuff.
  25.219 +	LLInventoryObject* getObject(const LLUUID& id) const;
  25.220 +
  25.221 +	// Get the item by id. Returns NULL if not found.
  25.222 +	//    NOTE: Use the pointer for read operations - use the
  25.223 +	//    updateItem() method to actually modify values.
  25.224 +	LLViewerInventoryItem* getItem(const LLUUID& id) const;
  25.225 +
  25.226 +	// Get the category by id. Returns NULL if not found.
  25.227 +	//    NOTE: Use the pointer for read operations - use the
  25.228 +	//    updateCategory() method to actually modify values.
  25.229 +	LLViewerInventoryCategory* getCategory(const LLUUID& id) const;
  25.230 +
  25.231  	// Get the inventoryID that this item points to, else just return item_id
  25.232  	const LLUUID& getLinkedItemID(const LLUUID& object_id) const;
  25.233  	LLViewerInventoryItem* getLinkedItem(const LLUUID& object_id) const;
  25.234  
  25.235 -	// This method will return false if this inventory model is in an usabel state.
  25.236 -	// The inventory model usage is sensitive to the initial construction of the 
  25.237 -	// model. 
  25.238 -	bool isInventoryUsable();
  25.239 +protected:
  25.240 +	// Internal method which looks for a category with the specified
  25.241 +	// preferred type. Returns LLUUID::null if not found
  25.242 + 	LLUUID findCatUUID(LLFolderType::EType preferred_type);
  25.243 +
  25.244 +private:
  25.245 +	mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups
  25.246 +
  25.247 +	//--------------------------------------------------------------------
  25.248 +	// Count
  25.249 +	//--------------------------------------------------------------------
  25.250 +public:
  25.251 +	// Return the number of items or categories
  25.252 +	S32 getItemCount() const;
  25.253 +	S32 getCategoryCount() const;
  25.254  
  25.255  	//
  25.256  	// Mutators
  25.257  	//
  25.258  
  25.259 -	// Calling this method with an inventory item will either change
  25.260 -	// an existing item with a matching item_id, or will add the item
  25.261 +public:
  25.262 +	// Change an existing item with a matching item_id or add the item
  25.263  	// to the current inventory. Returns the change mask generated by
  25.264 -	// the update. No notifcation will be sent to observers. This
  25.265 +	// the update. No notification will be sent to observers. This
  25.266  	// method will only generate network traffic if the item had to be
  25.267  	// reparented.
  25.268 -	// *NOTE: In usage, you will want to perform cache accounting
  25.269 -	// operations in LLInventoryModel::accountForUpdate() or
  25.270 -	// LLViewerInventoryItem::updateServer() before calling this
  25.271 -	// method.
  25.272 +	//    NOTE: In usage, you will want to perform cache accounting
  25.273 +	//    operations in LLInventoryModel::accountForUpdate() or
  25.274 +	//    LLViewerInventoryItem::updateServer() before calling this method.
  25.275  	U32 updateItem(const LLViewerInventoryItem* item);
  25.276  
  25.277 -	// Calling this method with an inventory category will either
  25.278 -	// change an existing item with the matching id, or it will add
  25.279 +	// Change an existing item with the matching id or add
  25.280  	// the category. No notifcation will be sent to observers. This
  25.281  	// method will only generate network traffic if the item had to be
  25.282  	// reparented.
  25.283 -	// *NOTE: In usage, you will want to perform cache accounting
  25.284 -	// operations in LLInventoryModel::accountForUpdate() or
  25.285 -	// LLViewerInventoryCategory::updateServer() before calling this
  25.286 -	// method.
  25.287 +	//    NOTE: In usage, you will want to perform cache accounting
  25.288 +	//    operations in accountForUpdate() or LLViewerInventoryCategory::
  25.289 +	//    updateServer() before calling this method.
  25.290  	void updateCategory(const LLViewerInventoryCategory* cat);
  25.291  
  25.292 -	// This method will move the specified object id to the specified
  25.293 -	// category, update the internal structures. No cache accounting,
  25.294 +	// Move the specified object id to the specified category and
  25.295 +	// update the internal structures. No cache accounting,
  25.296  	// observer notification, or server update is performed.
  25.297  	void moveObject(const LLUUID& object_id, const LLUUID& cat_id);
  25.298  
  25.299 -	// delete a particular inventory object by ID. This will purge one
  25.300 -	// object from the internal data structures maintaining a
  25.301 -	// cosistent internal state. No cache accounting, observer
  25.302 +	//--------------------------------------------------------------------
  25.303 +	// Delete
  25.304 +	//--------------------------------------------------------------------
  25.305 +public:
  25.306 +	// Delete a particular inventory object by ID. Will purge one
  25.307 +	// object from the internal data structures, maintaining a
  25.308 +	// consistent internal state. No cache accounting, observer
  25.309  	// notification, or server update is performed.
  25.310  	void deleteObject(const LLUUID& id);
  25.311  	void removeItem(const LLUUID& item_id);
  25.312 @@ -246,12 +353,12 @@
  25.313  	// the server. Also updates linked items.
  25.314  	void purgeObject(const LLUUID& id);
  25.315  
  25.316 -	// This is a method which collects the descendents of the id
  25.317 +	// Collects and purges the descendants of the id
  25.318  	// provided. If the category is not found, no action is
  25.319  	// taken. This method goes through the long winded process of
  25.320  	// removing server representation of folders and items while doing
  25.321  	// cache accounting in a fairly efficient manner. This method does
  25.322 -	// not notify observers (though maybe it shouldd...)
  25.323 +	// not notify observers (though maybe it should...)
  25.324  	void purgeDescendentsOf(const LLUUID& id);
  25.325  
  25.326  	// This method optimally removes the referenced categories and
  25.327 @@ -261,101 +368,36 @@
  25.328  	void deleteFromServer(LLDynamicArray<LLUUID>& category_ids,
  25.329  						  LLDynamicArray<LLUUID>& item_ids);
  25.330  
  25.331 -	// Add/remove an observer. If the observer is destroyed, be sure
  25.332 -	// to remove it.
  25.333 -	void addObserver(LLInventoryObserver* observer);
  25.334 -	void removeObserver(LLInventoryObserver* observer);
  25.335 -	BOOL containsObserver(LLInventoryObserver* observer);
  25.336 -
  25.337 -	//
  25.338 -	// Misc Methods 
  25.339 -	//
  25.340 -
  25.341 -	// findCategoryUUIDForType() returns the uuid of the category that
  25.342 -	// specifies 'type' as what it defaults to containing. The
  25.343 -	// category is not necessarily only for that type. *NOTE: This
  25.344 -	// will create a new inventory category on the fly if one does not
  25.345 -	// exist.
  25.346 -
  25.347 -	// SDK: Added flag to specify whether the folder should be created if not found.  This fixes the horrible
  25.348 -	// multiple trash can bug.
  25.349 -	LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder = true);
  25.350 -
  25.351  	// Get whatever special folder this object is a child of, if any.
  25.352  	const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const;
  25.353  
  25.354 -	// Call this method when it's time to update everyone on a new
  25.355 -	// state, by default, the inventory model will not update
  25.356 -	// observers automatically.
  25.357 -	// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
  25.358 -	void notifyObservers(const std::string service_name="");
  25.359  
  25.360 -	// This allows outsiders to tell the inventory if something has
  25.361 -	// been changed 'under the hood', but outside the control of the
  25.362 -	// inventory. For example, if we grant someone modify permissions,
  25.363 -	// then that changes the data structures for LLAvatarTracker, but
  25.364 -	// potentially affects inventory observers. This API makes sure
  25.365 -	// that the next notify will include that notification.
  25.366 -	void addChangedMask(U32 mask, const LLUUID& referent);
  25.367 -
  25.368 -	const std::set<LLUUID>& getChangedIDs() { return mChangedItemIDs; }
  25.369 -
  25.370 -	// This method to prepares a set of mock inventory which provides
  25.371 -	// minimal functionality before the actual arrival of inventory.
  25.372 -	//void mock(const LLUUID& root_id);
  25.373 -
  25.374 -	// make sure we have the descendents in the structure.
  25.375 -	void fetchDescendentsOf(const LLUUID& folder_id);
  25.376 -	
  25.377 -	// Add categories to a list to be fetched in bulk.
  25.378 -	static void bulkFetch(std::string url);
  25.379 -
  25.380 -	// call this method to request the inventory.
  25.381 -	//void requestFromServer(const LLUUID& agent_id);
  25.382 -
  25.383 -	// call this method on logout to save a terse representation
  25.384 -	void cache(const LLUUID& parent_folder_id, const LLUUID& agent_id);
  25.385 -
  25.386 -	// Generates a string containing the path to the item specified by
  25.387 -	// item_id.
  25.388 -	void appendPath(const LLUUID& id, std::string& path);
  25.389 -
  25.390 -	// message handling functionality
  25.391 -	static void registerCallbacks(LLMessageSystem* msg);
  25.392 -
  25.393 -	// Convenience function to create a new category. You could call
  25.394 -	// updateCatgory() with a newly generated UUID category, but this
  25.395 -	// version will take care of details like what the name should be
  25.396 -	// based on preferred type. Returns the UUID of the new
  25.397 -	// category. If you want to use the default name based on type,
  25.398 -	// pass in a NULL to the 'name parameter.
  25.399 +	//--------------------------------------------------------------------
  25.400 +	// Creation
  25.401 +	//--------------------------------------------------------------------
  25.402 +public:
  25.403 +	// Returns the UUID of the new category. If you want to use the default 
  25.404 +	// name based on type, pass in a NULL to the 'name' parameter.
  25.405  	LLUUID createNewCategory(const LLUUID& parent_id,
  25.406  							 LLFolderType::EType preferred_type,
  25.407  							 const std::string& name);
  25.408  
  25.409  	LLUUID findCategoryByName(std::string name);
  25.410  
  25.411 -	// methods to load up inventory skeleton & meat. These are used
  25.412 -	// during authentication. return true if everything parsed.
  25.413 -	typedef std::map<std::string, std::string> response_t;
  25.414 -	typedef std::vector<response_t> options_t;
  25.415 -	// OGPX : Two loadSkeleton(), one for the XML-RPC logins, one for LLSD
  25.416 -	//... The concept of a skeleton being different from the cap that 
  25.417 -	//... we do inventory queries on should be examined, and the usage of
  25.418 -	//... the skeleton in querying the wearables needs to be examined as well.
  25.419 -	bool loadSkeleton(const options_t& options, const LLUUID& owner_id);
  25.420 -	bool loadSkeleton(const LLSD& options, const LLUUID& owner_id); 
  25.421 -
  25.422 -	// This is a brute force method to rebuild the entire parent-child
  25.423 -	// relations.
  25.424 -	void buildParentChildMap();
  25.425 +protected:
  25.426 +	// Internal methods that add inventory and make sure that all of
  25.427 +	// the internal data structures are consistent. These methods
  25.428 +	// should be passed pointers of newly created objects, and the
  25.429 +	// instance will take over the memory management from there.
  25.430 +	void addCategory(LLViewerInventoryCategory* category);
  25.431 +	void addItem(LLViewerInventoryItem* item);
  25.432  
  25.433  	//
  25.434  	// Category accounting.
  25.435  	//
  25.436  
  25.437 -	// This structure represents the number of items added or removed
  25.438 -	// from a category.
  25.439 +public:
  25.440 +	// Represents the number of items added or removed from a category.
  25.441  	struct LLCategoryUpdate
  25.442  	{
  25.443  		LLCategoryUpdate() : mDescendentDelta(0) {}
  25.444 @@ -367,8 +409,7 @@
  25.445  	};
  25.446  	typedef std::vector<LLCategoryUpdate> update_list_t;
  25.447  
  25.448 -	// This structure eixts to make it easier to account for deltas in
  25.449 -	// a map.
  25.450 +	// This exists to make it easier to account for deltas in a map.
  25.451  	struct LLInitializedS32
  25.452  	{
  25.453  		LLInitializedS32() : mValue(0) {}
  25.454 @@ -386,38 +427,72 @@
  25.455  	void accountForUpdate(const update_list_t& updates);
  25.456  	void accountForUpdate(const update_map_t& updates);
  25.457  
  25.458 -	// Return child status of category children. yes/no/maybe
  25.459 +	// Return (yes/no/maybe) child status of category children.
  25.460  	EHasChildren categoryHasChildren(const LLUUID& cat_id) const;
  25.461  
  25.462 -	// returns true iff category version is known and theoretical
  25.463 +	// Returns true if category version is known and theoretical
  25.464  	// descendents == actual descendents.
  25.465  	bool isCategoryComplete(const LLUUID& cat_id) const;
  25.466  
  25.467 -	// start and stop background breadth-first fetching of inventory contents
  25.468 -	// this gets triggered when performing a filter-search
  25.469 -	static void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null); // start fetch process
  25.470 -    static void findLostItems();
  25.471 -	static BOOL backgroundFetchActive();
  25.472 -	static bool isEverythingFetched();
  25.473 -	static void backgroundFetch(void*); // background fetch idle function
  25.474 -	static void incrBulkFetch(S16 fetching) {  sBulkFetchCount+=fetching; if (sBulkFetchCount<0) sBulkFetchCount=0; }
  25.475 +	//
  25.476 +	// Notifications
  25.477 +	//
  25.478 +public:
  25.479 +	// Called by the idle loop.  Only updates if new state is detected.  Call 
  25.480 +	// notifyObservers() manually to update regardless of whether state change 
  25.481 +	// has been indicated.
  25.482 +	void idleNotifyObservers();
  25.483 +
  25.484 +	// Call to explicitly update everyone on a new state.
  25.485 +	void notifyObservers();
  25.486 +
  25.487 +	// Allows outsiders to tell the inventory if something has
  25.488 +	// been changed 'under the hood', but outside the control of the
  25.489 +	// inventory. The next notify will include that notification.
  25.490 +	void addChangedMask(U32 mask, const LLUUID& referent);
  25.491 +	const changed_items_t& getChangedIDs() { return mChangedItemIDs; }
  25.492 +
  25.493  protected:
  25.494 +	// Updates all linked items pointing to this id.
  25.495 +	void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
  25.496  
  25.497 -	// Internal methods which add inventory and make sure that all of
  25.498 -	// the internal data structures are consistent. These methods
  25.499 -	// should be passed pointers of newly created objects, and the
  25.500 -	// instance will take over the memory management from there.
  25.501 -	void addCategory(LLViewerInventoryCategory* category);
  25.502 -	void addItem(LLViewerInventoryItem* item);
  25.503 +private:
  25.504 +	// Flag set when notifyObservers is being called, to look for bugs
  25.505 +	// where it's called recursively.
  25.506 +	bool mIsNotifyObservers;
  25.507 +	// Variables used to track what has changed since the last notify.
  25.508 +	U32 mModifyMask;
  25.509 +	changed_items_t mChangedItemIDs;
  25.510  
  25.511 -	// Internal method which looks for a category with the specified
  25.512 -	// preferred type. Returns LLUUID::null if not found
  25.513 - 	LLUUID findCatUUID(LLFolderType::EType preferred_type);
  25.514  
  25.515 -	// Empty the entire contents
  25.516 -	void empty();
  25.517 +	//--------------------------------------------------------------------
  25.518 +	// Observers
  25.519 +	//--------------------------------------------------------------------
  25.520 +public:
  25.521 +	// If the observer is destroyed, be sure to remove it.
  25.522 +	void addObserver(LLInventoryObserver* observer);
  25.523 +	void removeObserver(LLInventoryObserver* observer);
  25.524 +	BOOL containsObserver(LLInventoryObserver* observer);
  25.525  
  25.526 -	// file import/export.
  25.527 +private:
  25.528 +	typedef std::set<LLInventoryObserver*> observer_list_t;
  25.529 +	observer_list_t mObservers;
  25.530 +
  25.531 +	//
  25.532 +	// Misc Methods 
  25.533 +	//
  25.534 +
  25.535 +	//--------------------------------------------------------------------
  25.536 +	// Callbacks
  25.537 +	//--------------------------------------------------------------------
  25.538 +public:
  25.539 +	// message handling functionality
  25.540 +	static void registerCallbacks(LLMessageSystem* msg);
  25.541 +
  25.542 +	//--------------------------------------------------------------------
  25.543 +	// File I/O
  25.544 +	//--------------------------------------------------------------------
  25.545 +protected:
  25.546  	static bool loadFromFile(const std::string& filename,
  25.547  							 cat_array_t& categories,
  25.548  							 item_array_t& items,
  25.549 @@ -426,88 +501,53 @@
  25.550  						   const cat_array_t& categories,
  25.551  						   const item_array_t& items); 
  25.552  
  25.553 -	// message handling functionality
  25.554 -	//static void processUseCachedInventory(LLMessageSystem* msg, void**);
  25.555 +	//--------------------------------------------------------------------
  25.556 +	// Message handling functionality
  25.557 +	//--------------------------------------------------------------------
  25.558 +public:
  25.559  	static void processUpdateCreateInventoryItem(LLMessageSystem* msg, void**);
  25.560  	static void processRemoveInventoryItem(LLMessageSystem* msg, void**);
  25.561  	static void processUpdateInventoryFolder(LLMessageSystem* msg, void**);
  25.562  	static void processRemoveInventoryFolder(LLMessageSystem* msg, void**);
  25.563 -	//static void processExchangeCallingcard(LLMessageSystem* msg, void**);
  25.564 -	//static void processAddCallingcard(LLMessageSystem* msg, void**);
  25.565 -	//static void processDeclineCallingcard(LLMessageSystem* msg, void**);
  25.566  	static void processSaveAssetIntoInventory(LLMessageSystem* msg, void**);
  25.567  	static void processBulkUpdateInventory(LLMessageSystem* msg, void**);
  25.568  	static void processInventoryDescendents(LLMessageSystem* msg, void**);
  25.569  	static void processMoveInventoryItem(LLMessageSystem* msg, void**);
  25.570  	static void processFetchInventoryReply(LLMessageSystem* msg, void**);
  25.571  	
  25.572 +protected:
  25.573  	bool messageUpdateCore(LLMessageSystem* msg, bool do_accounting);
  25.574  
  25.575 -	// Updates all linked items pointing to this id.
  25.576 -	void addChangedMaskForLinks(const LLUUID& object_id, U32 mask);
  25.577 +	//--------------------------------------------------------------------
  25.578 +	// Locking
  25.579 +	//--------------------------------------------------------------------
  25.580 +public:
  25.581 +	void lockDirectDescendentArrays(const LLUUID& cat_id,
  25.582 +									cat_array_t*& categories,
  25.583 +									item_array_t*& items);
  25.584 +	void unlockDirectDescendentArrays(const LLUUID& cat_id);
  25.585  
  25.586  protected:
  25.587  	cat_array_t* getUnlockedCatArray(const LLUUID& id);
  25.588  	item_array_t* getUnlockedItemArray(const LLUUID& id);
  25.589  	
  25.590 -protected:
  25.591 -	// Varaibles used to track what has changed since the last notify.
  25.592 -	U32 mModifyMask;
  25.593 -	typedef std::set<LLUUID> changed_items_t;
  25.594 -	changed_items_t mChangedItemIDs;
  25.595 -
  25.596 -	// Information for tracking the actual inventory. We index this
  25.597 -	// information in a lot of different ways so we can access
  25.598 -	// the inventory using several different identifiers.
  25.599 -	// mInventory member data is the 'master' list of inventory, and
  25.600 -	// mCategoryMap and mItemMap store uuid->object mappings. 
  25.601 -	typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
  25.602 -	typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
  25.603 -	//inv_map_t mInventory;
  25.604 -	cat_map_t mCategoryMap;
  25.605 -	item_map_t mItemMap;
  25.606 -
  25.607 +private:
  25.608  	std::map<LLUUID, bool> mCategoryLock;
  25.609  	std::map<LLUUID, bool> mItemLock;
  25.610  	
  25.611 -	// cache recent lookups
  25.612 -	mutable LLPointer<LLViewerInventoryItem> mLastItem;
  25.613 -
  25.614 -	// This last set of indices is used to map parents to children.
  25.615 -	typedef std::map<LLUUID, cat_array_t*> parent_cat_map_t;
  25.616 -	typedef std::map<LLUUID, item_array_t*> parent_item_map_t;
  25.617 -	parent_cat_map_t mParentChildCategoryTree;
  25.618 -	parent_item_map_t mParentChildItemTree;
  25.619 -
  25.620 -	typedef std::set<LLInventoryObserver*> observer_list_t;
  25.621 -	observer_list_t mObservers;
  25.622 -
  25.623 -	// completing the fetch once per session should be sufficient
  25.624 -	static BOOL sBackgroundFetchActive;
  25.625 -	static BOOL sTimelyFetchPending;
  25.626 -	static S32  sNumFetchRetries;
  25.627 -	static LLFrameTimer sFetchTimer;
  25.628 -	static F32 sMinTimeBetweenFetches;
  25.629 -	static F32 sMaxTimeBetweenFetches;
  25.630 -	static S16 sBulkFetchCount;
  25.631 -
  25.632 -	// This flag is used to handle an invalid inventory state.
  25.633 -	bool mIsAgentInvUsable;
  25.634 -
  25.635 -private:
  25.636 -	const static S32 sCurrentInvCacheVersion; // expected inventory cache version
  25.637 -	// Flag set when notifyObservers is being called, to look for bugs
  25.638 -	// where it's called recursively.
  25.639 -	BOOL mIsNotifyObservers;
  25.640 +	//--------------------------------------------------------------------
  25.641 +	// Debugging
  25.642 +	//--------------------------------------------------------------------
  25.643  
  25.644  public:
  25.645 -	// *NOTE: DEBUG functionality
  25.646  	void dumpInventory();
  25.647 -	static bool isBulkFetchProcessingComplete();
  25.648 -	static void stopBackgroundFetch(); // stop fetch process
  25.649 -
  25.650 -	static BOOL sFullFetchStarted;
  25.651 -	static BOOL sAllFoldersFetched; 
  25.652 +	//--------------------------------------------------------------------
  25.653 +	// Other
  25.654 +	//--------------------------------------------------------------------
  25.655 +public:
  25.656 +	// Generates a string containing the path to the item specified by
  25.657 +	// item_id.
  25.658 +	void appendPath(const LLUUID& id, std::string& path);
  25.659  };
  25.660  
  25.661  // a special inventory model for the agent
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp	Sat Jan 07 17:05:31 2012 +0100
    26.3 @@ -0,0 +1,648 @@
    26.4 +/** 
    26.5 + * @file llinventorymodelbackgroundfetch.cpp
    26.6 + * @brief Implementation of the inventory fetcher.
    26.7 + *
    26.8 + * $LicenseInfo:firstyear=2002&license=viewergpl$
    26.9 + * 
   26.10 + * Copyright (c) 2010, Linden Research, Inc.
   26.11 + * 
   26.12 + * Second Life Viewer Source Code
   26.13 + * The source code in this file ("Source Code") is provided by Linden Lab
   26.14 + * to you under the terms of the GNU General Public License, version 2.0
   26.15 + * ("GPL"), unless you have obtained a separate licensing agreement
   26.16 + * ("Other License"), formally executed by you and Linden Lab.  Terms of
   26.17 + * the GPL can be found in doc/GPL-license.txt in this distribution, or
   26.18 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
   26.19 + * 
   26.20 + * There are special exceptions to the terms and conditions of the GPL as
   26.21 + * it is applied to this Source Code. View the full text of the exception
   26.22 + * in the file doc/FLOSS-exception.txt in this software distribution, or
   26.23 + * online at
   26.24 + * http://secondlifegrid.net/programs/open_source/licensing/flossexception
   26.25 + * 
   26.26 + * By copying, modifying or distributing this software, you acknowledge
   26.27 + * that you have read and understood your obligations described above,
   26.28 + * and agree to abide by those obligations.
   26.29 + * 
   26.30 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
   26.31 + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
   26.32 + * COMPLETENESS OR PERFORMANCE.
   26.33 + * $/LicenseInfo$
   26.34 + */
   26.35 +
   26.36 +#include "llviewerprecompiledheaders.h"
   26.37 +
   26.38 +#include "llinventorymodelbackgroundfetch.h"
   26.39 +
   26.40 +#include "llagent.h"
   26.41 +#include "llappviewer.h"
   26.42 +#include "llcallbacklist.h"
   26.43 +#include "llinventorymodel.h"
   26.44 +#include "llinventoryview.h"
   26.45 +#include "llviewercontrol.h"
   26.46 +#include "llviewerinventory.h"
   26.47 +#include "llviewermessage.h"
   26.48 +#include "llviewerregion.h"
   26.49 +#include "llviewerwindow.h"
   26.50 +
   26.51 +const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
   26.52 +const S32 MAX_FETCH_RETRIES = 10;
   26.53 +
   26.54 +LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch()
   26.55 +:	mBackgroundFetchActive(FALSE),
   26.56 +	mAllFoldersFetched(FALSE),
   26.57 +	mRecursiveInventoryFetchStarted(FALSE),
   26.58 +	mRecursiveLibraryFetchStarted(FALSE),
   26.59 +	mNumFetchRetries(0),
   26.60 +	mMinTimeBetweenFetches(0.3f),
   26.61 +	mMaxTimeBetweenFetches(10.f),
   26.62 +	mTimelyFetchPending(FALSE),
   26.63 +	mBulkFetchCount(0)
   26.64 +{
   26.65 +}
   26.66 +
   26.67 +LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()
   26.68 +{
   26.69 +}
   26.70 +
   26.71 +bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const
   26.72 +{
   26.73 +	return mFetchQueue.empty() && mBulkFetchCount <= 0;
   26.74 +}
   26.75 +
   26.76 +bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const
   26.77 +{
   26.78 +	return mRecursiveLibraryFetchStarted;
   26.79 +}
   26.80 +
   26.81 +bool LLInventoryModelBackgroundFetch::libraryFetchCompleted() const
   26.82 +{
   26.83 +	return libraryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getLibraryRootFolderID());
   26.84 +}
   26.85 +
   26.86 +bool LLInventoryModelBackgroundFetch::libraryFetchInProgress() const
   26.87 +{
   26.88 +	return libraryFetchStarted() && !libraryFetchCompleted();
   26.89 +}
   26.90 +
   26.91 +bool LLInventoryModelBackgroundFetch::inventoryFetchStarted() const
   26.92 +{
   26.93 +	return mRecursiveInventoryFetchStarted;
   26.94 +}
   26.95 +
   26.96 +bool LLInventoryModelBackgroundFetch::inventoryFetchCompleted() const
   26.97 +{
   26.98 +	return inventoryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getRootFolderID());
   26.99 +}
  26.100 +
  26.101 +bool LLInventoryModelBackgroundFetch::inventoryFetchInProgress() const
  26.102 +{
  26.103 +	return inventoryFetchStarted() && !inventoryFetchCompleted();
  26.104 +}
  26.105 +
  26.106 +bool LLInventoryModelBackgroundFetch::isEverythingFetched() const
  26.107 +{
  26.108 +	return mAllFoldersFetched;
  26.109 +}
  26.110 +
  26.111 +BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const
  26.112 +{
  26.113 +	return mBackgroundFetchActive;
  26.114 +}
  26.115 +
  26.116 +void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive)
  26.117 +{
  26.118 +	if (!mAllFoldersFetched || cat_id.notNull())
  26.119 +	{
  26.120 +		LL_DEBUGS("InventoryFetch") << "Start fetching category: " << cat_id
  26.121 +									<< ", recursive: " << recursive << LL_ENDL;
  26.122 +
  26.123 +		mBackgroundFetchActive = TRUE;
  26.124 +		if (cat_id.isNull())
  26.125 +		{
  26.126 +			if (!mRecursiveInventoryFetchStarted)
  26.127 +			{
  26.128 +				mRecursiveInventoryFetchStarted |= recursive;
  26.129 +				mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive));
  26.130 +				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
  26.131 +			}
  26.132 +			if (!mRecursiveLibraryFetchStarted)
  26.133 +			{
  26.134 +				mRecursiveLibraryFetchStarted |= recursive;
  26.135 +				mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive));
  26.136 +				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
  26.137 +			}
  26.138 +		}
  26.139 +		else
  26.140 +		{
  26.141 +			// Specific folder requests go to front of queue.
  26.142 +			if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id)
  26.143 +			{
  26.144 +				mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive));
  26.145 +				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
  26.146 +			}
  26.147 +			if (cat_id == gInventory.getLibraryRootFolderID())
  26.148 +			{
  26.149 +				mRecursiveLibraryFetchStarted |= recursive;
  26.150 +			}
  26.151 +			if (cat_id == gInventory.getRootFolderID())
  26.152 +			{
  26.153 +				mRecursiveInventoryFetchStarted |= recursive;
  26.154 +			}
  26.155 +		}
  26.156 +	}
  26.157 +}
  26.158 +
  26.159 +void LLInventoryModelBackgroundFetch::findLostItems()
  26.160 +{
  26.161 +	mBackgroundFetchActive = TRUE;
  26.162 +    mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE));
  26.163 +    gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
  26.164 +}
  26.165 +
  26.166 +void LLInventoryModelBackgroundFetch::stopBackgroundFetch()
  26.167 +{
  26.168 +	if (mBackgroundFetchActive)
  26.169 +	{
  26.170 +		mBackgroundFetchActive = FALSE;
  26.171 +		gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
  26.172 +		mBulkFetchCount = 0;
  26.173 +		mMinTimeBetweenFetches = 0.0f;
  26.174 +	}
  26.175 +}
  26.176 +
  26.177 +void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
  26.178 +{
  26.179 +	if (mRecursiveInventoryFetchStarted &&
  26.180 +		mRecursiveLibraryFetchStarted)
  26.181 +	{
  26.182 +		mAllFoldersFetched = TRUE;
  26.183 +	}
  26.184 +	stopBackgroundFetch();
  26.185 +}
  26.186 +
  26.187 +void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *)
  26.188 +{
  26.189 +	LLInventoryModelBackgroundFetch::instance().backgroundFetch();
  26.190 +}
  26.191 +
  26.192 +void LLInventoryModelBackgroundFetch::backgroundFetch()
  26.193 +{
  26.194 +	if (mBackgroundFetchActive && gAgent.getRegion())
  26.195 +	{
  26.196 +		// If we'll be using the capability, we'll be sending batches and the
  26.197 +		// background thing isn't as important.
  26.198 +		std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");   
  26.199 +		if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty()) 
  26.200 +		{
  26.201 +			bulkFetch(url);
  26.202 +			return;
  26.203 +		}
  26.204 +
  26.205 +		// No more categories to fetch, stop fetch process.
  26.206 +		if (mFetchQueue.empty())
  26.207 +		{
  26.208 +			llinfos << "Inventory fetch completed" << llendl;
  26.209 +
  26.210 +			setAllFoldersFetched();
  26.211 +			return;
  26.212 +		}
  26.213 +
  26.214 +		F32 fast_fetch_time = lerp(mMinTimeBetweenFetches, mMaxTimeBetweenFetches, 0.1f);
  26.215 +		F32 slow_fetch_time = lerp(mMinTimeBetweenFetches, mMaxTimeBetweenFetches, 0.5f);
  26.216 +		if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() > slow_fetch_time)
  26.217 +		{
  26.218 +			// Double timeouts on failure.
  26.219 +			mMinTimeBetweenFetches = llmin(mMinTimeBetweenFetches * 2.f, 10.f);
  26.220 +			mMaxTimeBetweenFetches = llmin(mMaxTimeBetweenFetches * 2.f, 120.f);
  26.221 +			LL_DEBUGS("InventoryFetch") << "Inventory fetch times grown to ("
  26.222 +										<< mMinTimeBetweenFetches << ", "
  26.223 +										<< mMaxTimeBetweenFetches << ")"
  26.224 +										<< LL_ENDL;
  26.225 +			// fetch is no longer considered "timely" although we will wait for full time-out.
  26.226 +			mTimelyFetchPending = FALSE;
  26.227 +		}
  26.228 +
  26.229 +		while (1)
  26.230 +		{
  26.231 +			if (mFetchQueue.empty())
  26.232 +			{
  26.233 +				break;
  26.234 +			}
  26.235 +
  26.236 +			if (gDisconnected)
  26.237 +			{
  26.238 +				// Just bail if we are disconnected.
  26.239 +				break;
  26.240 +			}
  26.241 +
  26.242 +			const FetchQueueInfo info = mFetchQueue.front();
  26.243 +			LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID);
  26.244 +
  26.245 +			// Category has been deleted, remove from queue.
  26.246 +			if (!cat)
  26.247 +			{
  26.248 +				mFetchQueue.pop_front();
  26.249 +				continue;
  26.250 +			}
  26.251 +
  26.252 +			if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches && 
  26.253 +				LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
  26.254 +			{
  26.255 +				// Category exists but has no children yet, fetch the descendants
  26.256 +				// for now, just request every time and rely on retry timer to throttle.
  26.257 +				if (cat->fetch())
  26.258 +				{
  26.259 +					mFetchTimer.reset();
  26.260 +					mTimelyFetchPending = TRUE;
  26.261 +				}
  26.262 +				else
  26.263 +				{
  26.264 +					//  The catagory also tracks if it has expired and here it says it hasn't
  26.265 +					//  yet.  Get out of here because nothing is going to happen until we
  26.266 +					//  update the timers.
  26.267 +					break;
  26.268 +				}
  26.269 +			}
  26.270 +			// Do I have all my children?
  26.271 +			else if (gInventory.isCategoryComplete(info.mCatUUID))
  26.272 +			{
  26.273 +				// Finished with this category, remove from queue.
  26.274 +				mFetchQueue.pop_front();
  26.275 +
  26.276 +				// Add all children to queue.
  26.277 +				LLInventoryModel::cat_array_t* categories;
  26.278 +				LLInventoryModel::item_array_t* items;
  26.279 +				gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
  26.280 +				for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
  26.281 +					 it != categories->end(); ++it)
  26.282 +				{
  26.283 +					mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive));
  26.284 +				}
  26.285 +
  26.286 +				// We received a response in less than the fast time.
  26.287 +				if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time)
  26.288 +				{
  26.289 +					// Shrink timeouts based on success.
  26.290 +					mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f);
  26.291 +					mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f);
  26.292 +					LL_DEBUGS("InventoryFetch") << "Inventory fetch times shrunk to ("
  26.293 +												<< mMinTimeBetweenFetches << ", "
  26.294 +												<< mMaxTimeBetweenFetches << ")"
  26.295 +												<< LL_ENDL;
  26.296 +				}
  26.297 +
  26.298 +				mTimelyFetchPending = FALSE;
  26.299 +				continue;
  26.300 +			}
  26.301 +			else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
  26.302 +			{
  26.303 +				// Received first packet, but our num descendants does not match db's num descendants
  26.304 +				// so try again later.
  26.305 +				mFetchQueue.pop_front();
  26.306 +
  26.307 +				if (mNumFetchRetries++ < MAX_FETCH_RETRIES)
  26.308 +				{
  26.309 +					// push on back of queue
  26.310 +					mFetchQueue.push_back(info);
  26.311 +				}
  26.312 +				mTimelyFetchPending = FALSE;
  26.313 +				mFetchTimer.reset();
  26.314 +				break;
  26.315 +			}
  26.316 +
  26.317 +			// Not enough time has elapsed to do a new fetch
  26.318 +			break;
  26.319 +		}
  26.320 +	}
  26.321 +}
  26.322 +
  26.323 +void LLInventoryModelBackgroundFetch::incrBulkFetch(S16 fetching) 
  26.324 +{  
  26.325 +	mBulkFetchCount += fetching; 
  26.326 +	if (mBulkFetchCount < 0)
  26.327 +	{
  26.328 +		mBulkFetchCount = 0; 
  26.329 +	}
  26.330 +}
  26.331 +
  26.332 +class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
  26.333 +{
  26.334 +public:
  26.335 +	LLInventoryModelFetchDescendentsResponder(const LLSD& request_sd, uuid_vec_t recursive_cats)
  26.336 +	:	mRequestSD(request_sd),
  26.337 +		mRecursiveCatUUIDs(recursive_cats)
  26.338 +	{
  26.339 +	}
  26.340 +	//LLInventoryModelFetchDescendentsResponder() {};
  26.341 +	void result(const LLSD& content);
  26.342 +	void error(U32 status, const std::string& reason);
  26.343 +
  26.344 +protected:
  26.345 +	BOOL getIsRecursive(const LLUUID& cat_id) const;
  26.346 +
  26.347 +private:
  26.348 +	LLSD mRequestSD;
  26.349 +	uuid_vec_t mRecursiveCatUUIDs; // hack for storing away which cat fetches are recursive
  26.350 +};
  26.351 +
  26.352 +// If we get back a normal response, handle it here.
  26.353 +void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
  26.354 +{
  26.355 +	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
  26.356 +	if (content.has("folders"))
  26.357 +	{
  26.358 +		for (LLSD::array_const_iterator folder_it = content["folders"].beginArray();
  26.359 +			folder_it != content["folders"].endArray(); ++folder_it)
  26.360 +		{
  26.361 +			LLSD folder_sd = *folder_it;
  26.362 +
  26.363 +			//LLUUID agent_id = folder_sd["agent_id"];
  26.364 +
  26.365 +			//if (agent_id != gAgent.getID())	//This should never happen.
  26.366 +			//{
  26.367 +			//	llwarns << "Got a UpdateInventoryItem for the wrong agent."
  26.368 +			//			<< llendl;
  26.369 +			//	break;
  26.370 +			//}
  26.371 +
  26.372 +			LLUUID parent_id = folder_sd["folder_id"];
  26.373 +			LLUUID owner_id = folder_sd["owner_id"];
  26.374 +			S32    version  = (S32)folder_sd["version"].asInteger();
  26.375 +			S32    descendents = (S32)folder_sd["descendents"].asInteger();
  26.376 +			LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
  26.377 +
  26.378 +            if (parent_id.isNull())
  26.379 +            {
  26.380 +			    LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
  26.381 +			    for (LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
  26.382 +				    item_it != folder_sd["items"].endArray(); ++item_it)
  26.383 +			    {
  26.384 +                    const LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
  26.385 +                    if (lost_uuid.notNull())
  26.386 +                    {
  26.387 +				        LLSD item = *item_it;
  26.388 +				        titem->unpackMessage(item);
  26.389 +
  26.390 +                        LLInventoryModel::update_list_t update;
  26.391 +                        LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1);
  26.392 +                        update.push_back(new_folder);
  26.393 +                        gInventory.accountForUpdate(update);
  26.394 +
  26.395 +                        titem->setParent(lost_uuid);
  26.396 +                        titem->updateParentOnServer(FALSE);
  26.397 +                        gInventory.updateItem(titem);
  26.398 +                        gInventory.notifyObservers();
  26.399 +                    }
  26.400 +                }
  26.401 +            }
  26.402 +
  26.403 +	        LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id);
  26.404 +			if (!pcat)
  26.405 +			{
  26.406 +				continue;
  26.407 +			}
  26.408 +
  26.409 +			for (LLSD::array_const_iterator category_it = folder_sd["categories"].beginArray();
  26.410 +				category_it != folder_sd["categories"].endArray();
  26.411 +				++category_it)
  26.412 +			{
  26.413 +				LLSD category = *category_it;
  26.414 +				tcategory->fromLLSD(category); 
  26.415 +
  26.416 +				const BOOL recursive = getIsRecursive(tcategory->getUUID());
  26.417 +
  26.418 +				if (recursive)
  26.419 +				{
  26.420 +					fetcher->mFetchQueue.push_back(LLInventoryModelBackgroundFetch::FetchQueueInfo(tcategory->getUUID(), recursive));
  26.421 +				}
  26.422 +				else if (!gInventory.isCategoryComplete(tcategory->getUUID()))
  26.423 +				{
  26.424 +					gInventory.updateCategory(tcategory);
  26.425 +				}
  26.426 +			}
  26.427 +			LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
  26.428 +			for (LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
  26.429 +				item_it != folder_sd["items"].endArray(); ++item_it)
  26.430 +			{
  26.431 +				LLSD item = *item_it;
  26.432 +				titem->unpackMessage(item);
  26.433 +
  26.434 +				gInventory.updateItem(titem);
  26.435 +			}
  26.436 +
  26.437 +			// Set version and descendentcount according to message.
  26.438 +			LLViewerInventoryCategory* cat = gInventory.getCategory(parent_id);
  26.439 +			if (cat)
  26.440 +			{
  26.441 +				cat->setVersion(version);
  26.442 +				cat->setDescendentCount(descendents);
  26.443 +			}
  26.444 +		}
  26.445 +	}
  26.446 +
  26.447 +	if (content.has("bad_folders"))
  26.448 +	{
  26.449 +		for (LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray();
  26.450 +			folder_it != content["bad_folders"].endArray(); ++folder_it)
  26.451 +		{
  26.452 +			LLSD folder_sd = *folder_it;
  26.453 +
  26.454 +			// These folders failed on the dataserver.  We probably don't want to retry them.
  26.455 +			llinfos << "Folder " << folder_sd["folder_id"].asString() 
  26.456 +					<< "Error: " << folder_sd["error"].asString() << llendl;
  26.457 +		}
  26.458 +	}
  26.459 +
  26.460 +	fetcher->incrBulkFetch(-1);
  26.461 +
  26.462 +	if (fetcher->isBulkFetchProcessingComplete())
  26.463 +	{
  26.464 +		llinfos << "Inventory fetch completed" << llendl;
  26.465 +		fetcher->setAllFoldersFetched();
  26.466 +	}
  26.467 +
  26.468 +	gInventory.notifyObservers();
  26.469 +}
  26.470 +
  26.471 +// If we get back an error (not found, etc...), handle it here.
  26.472 +void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::string& reason)
  26.473 +{
  26.474 +	LLInventoryModelBackgroundFetch *fetcher = LLInventoryModelBackgroundFetch::getInstance();
  26.475 +
  26.476 +	llinfos << "LLInventoryModelFetchDescendentsResponder::error " << status
  26.477 +			<< ": " << reason << llendl;
  26.478 +
  26.479 +	fetcher->incrBulkFetch(-1);
  26.480 +
  26.481 +	if (status == 499) // timed out
  26.482 +	{
  26.483 +		for (LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
  26.484 +			folder_it != mRequestSD["folders"].endArray(); ++folder_it)
  26.485 +		{
  26.486 +			LLSD folder_sd = *folder_it;
  26.487 +			LLUUID folder_id = folder_sd["folder_id"];
  26.488 +			const BOOL recursive = getIsRecursive(folder_id);
  26.489 +			fetcher->mFetchQueue.push_front(LLInventoryModelBackgroundFetch::FetchQueueInfo(folder_id, recursive));
  26.490 +		}
  26.491 +	}
  26.492 +	else
  26.493 +	{
  26.494 +		if (fetcher->isBulkFetchProcessingComplete())
  26.495 +		{
  26.496 +			fetcher->setAllFoldersFetched();
  26.497 +		}
  26.498 +	}
  26.499 +	gInventory.notifyObservers();
  26.500 +}
  26.501 +
  26.502 +BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat_id) const
  26.503 +{
  26.504 +	return (std::find(mRecursiveCatUUIDs.begin(),mRecursiveCatUUIDs.end(), cat_id) != mRecursiveCatUUIDs.end());
  26.505 +}
  26.506 +
  26.507 +// Bundle up a bunch of requests to send all at once.
  26.508 +// static   
  26.509 +void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
  26.510 +{
  26.511 +	// Background fetch is called from gIdleCallbacks in a loop until background
  26.512 +	// fetch is stopped.
  26.513 +	// If there are items in mFetchQueue, we want to check the time since the
  26.514 +	// last bulkFetch was sent.
  26.515 +	// If it exceeds our retry time, go ahead and fire off another batch.  
  26.516 +	// Stopbackgroundfetch will be run from the Responder instead of here.  
  26.517 +
  26.518 +	S16 max_concurrent_fetches = 8;
  26.519 +	F32 new_min_time = 0.5f;			//HACK!  Clean this up when old code goes away entirely.
  26.520 +	if (mMinTimeBetweenFetches < new_min_time) 
  26.521 +	{
  26.522 +		mMinTimeBetweenFetches=new_min_time;  //HACK!  See above.
  26.523 +	}
  26.524 +
  26.525 +	if (gDisconnected || mBulkFetchCount > max_concurrent_fetches ||
  26.526 +		mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)
  26.527 +	{
  26.528 +		return; // just bail if we are disconnected
  26.529 +	}
  26.530 +
  26.531 +	U32 folder_count = 0;
  26.532 +	U32 max_batch_size = 5;
  26.533 +
  26.534 +	U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1;
  26.535 +
  26.536 +	uuid_vec_t recursive_cats;
  26.537 +
  26.538 +	LLSD body;
  26.539 +	LLSD body_lib;
  26.540 +
  26.541 +	while (!mFetchQueue.empty() && folder_count < max_batch_size)
  26.542 +	{
  26.543 +		const FetchQueueInfo& fetch_info = mFetchQueue.front();
  26.544 +		const LLUUID &cat_id = fetch_info.mCatUUID;
  26.545 +        if (cat_id.isNull()) //DEV-17797
  26.546 +        {
  26.547 +			LLSD folder_sd;
  26.548 +			folder_sd["folder_id"]		= LLUUID::null.asString();
  26.549 +			folder_sd["owner_id"]		= gAgent.getID();
  26.550 +			folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
  26.551 +			folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE;
  26.552 +			folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
  26.553 +			body["folders"].append(folder_sd);
  26.554 +            folder_count++;
  26.555 +        }
  26.556 +        else
  26.557 +        {
  26.558 +		    const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
  26.559 +
  26.560 +		    if (cat)
  26.561 +		    {
  26.562 +			    if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
  26.563 +			    {
  26.564 +				    LLSD folder_sd;
  26.565 +				    folder_sd["folder_id"]		= cat->getUUID();
  26.566 +				    folder_sd["owner_id"]		= cat->getOwnerID();
  26.567 +				    folder_sd["sort_order"]		= (LLSD::Integer)sort_order;
  26.568 +				    folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted;
  26.569 +				    folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE;
  26.570 +				    
  26.571 +				    if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
  26.572 +					    body_lib["folders"].append(folder_sd);
  26.573 +				    else
  26.574 +					    body["folders"].append(folder_sd);
  26.575 +				    folder_count++;
  26.576 +			    }
  26.577 +				// May already have this folder, but append child folders to list.
  26.578 +			    if (fetch_info.mRecursive)
  26.579 +			    {
  26.580 +					LLInventoryModel::cat_array_t* categories;
  26.581 +					LLInventoryModel::item_array_t* items;
  26.582 +					gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
  26.583 +					for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
  26.584 +						 it != categories->end(); ++it)
  26.585 +					{
  26.586 +						mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
  26.587 +				    }
  26.588 +			    }
  26.589 +		    }
  26.590 +        }
  26.591 +		if (fetch_info.mRecursive)
  26.592 +			recursive_cats.push_back(cat_id);
  26.593 +
  26.594 +		mFetchQueue.pop_front();
  26.595 +	}
  26.596 +
  26.597 +	if (folder_count > 0)
  26.598 +	{
  26.599 +		mBulkFetchCount++;
  26.600 +		if (body["folders"].size())
  26.601 +		{
  26.602 +			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body, recursive_cats);
  26.603 +			LLHTTPClient::post(url, body, fetcher, 300.0);
  26.604 +		}
  26.605 +		if (body_lib["folders"].size())
  26.606 +		{
  26.607 +			std::string url_lib;
  26.608 +			if (!gSavedSettings.getBOOL("OpenGridProtocol"))
  26.609 +			{
  26.610 +				url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
  26.611 +				if (url_lib.empty())
  26.612 +				{
  26.613 +					url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
  26.614 +					LL_DEBUGS("InventoryFetch") << "Using capability FetchLibDescendents for fetch"
  26.615 +												<< LL_ENDL;
  26.616 +				}
  26.617 +				else
  26.618 +				{
  26.619 +					LL_DEBUGS("InventoryFetch") << "Using capability FetchLibDescendents2 for fetch"
  26.620 +												<< LL_ENDL;
  26.621 +				}
  26.622 +			}
  26.623 +			else
  26.624 +			{
  26.625 +				url_lib = gAgent.getCapability("agent/inventory_library");
  26.626 +				LL_DEBUGS("InventoryFetch") << "Using capability agent/inventory_library for fetch"
  26.627 +											<< LL_ENDL;
  26.628 +			}
  26.629 +
  26.630 +			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);
  26.631 +			LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0);
  26.632 +		}
  26.633 +		mFetchTimer.reset();
  26.634 +	}
  26.635 +	else if (isBulkFetchProcessingComplete())
  26.636 +	{
  26.637 +		setAllFoldersFetched();
  26.638 +	}
  26.639 +}
  26.640 +
  26.641 +bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const
  26.642 +{
  26.643 +	for (fetch_queue_t::const_iterator it = mFetchQueue.begin();
  26.644 +		 it != mFetchQueue.end(); ++it)
  26.645 +	{
  26.646 +		const LLUUID& fetch_id = (*it).mCatUUID;
  26.647 +		if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
  26.648 +			return false;
  26.649 +	}
  26.650 +	return true;
  26.651 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/indra/newview/llinventorymodelbackgroundfetch.h	Sat Jan 07 17:05:31 2012 +0100
    27.3 @@ -0,0 +1,107 @@
    27.4 +/** 
    27.5 + * @file llinventorymodelbackgroundfetch.h
    27.6 + * @brief LLInventoryModelBackgroundFetch class header file
    27.7 + *
    27.8 + * $LicenseInfo:firstyear=2002&license=viewergpl$
    27.9 + * 
   27.10 + * Copyright (c) 2010, Linden Research, Inc.
   27.11 + * 
   27.12 + * Second Life Viewer Source Code
   27.13 + * The source code in this file ("Source Code") is provided by Linden Lab
   27.14 + * to you under the terms of the GNU General Public License, version 2.0
   27.15 + * ("GPL"), unless you have obtained a separate licensing agreement
   27.16 + * ("Other License"), formally executed by you and Linden Lab.  Terms of
   27.17 + * the GPL can be found in doc/GPL-license.txt in this distribution, or
   27.18 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
   27.19 + * 
   27.20 + * There are special exceptions to the terms and conditions of the GPL as
   27.21 + * it is applied to this Source Code. View the full text of the exception
   27.22 + * in the file doc/FLOSS-exception.txt in this software distribution, or
   27.23 + * online at
   27.24 + * http://secondlifegrid.net/programs/open_source/licensing/flossexception
   27.25 + * 
   27.26 + * By copying, modifying or distributing this software, you acknowledge
   27.27 + * that you have read and understood your obligations described above,
   27.28 + * and agree to abide by those obligations.
   27.29 + * 
   27.30 + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
   27.31 + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
   27.32 + * COMPLETENESS OR PERFORMANCE.
   27.33 + * $/LicenseInfo$
   27.34 + */
   27.35 +
   27.36 +#ifndef LL_LLINVENTORYMODELBACKGROUNDFETCH_H
   27.37 +#define LL_LLINVENTORYMODELBACKGROUNDFETCH_H
   27.38 +
   27.39 +#include "llsingleton.h"
   27.40 +#include "lluuid.h"
   27.41 +
   27.42 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   27.43 +// Class LLInventoryModelBackgroundFetch
   27.44 +//
   27.45 +// This class handles background fetches, which are fetches of
   27.46 +// inventory folder.  Fetches can be recursive or not.
   27.47 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   27.48 +class LLInventoryModelBackgroundFetch : public LLSingleton<LLInventoryModelBackgroundFetch>
   27.49 +{
   27.50 +	friend class LLInventoryModelFetchDescendentsResponder;
   27.51 +
   27.52 +public:
   27.53 +	LLInventoryModelBackgroundFetch();
   27.54 +	~LLInventoryModelBackgroundFetch();
   27.55 +
   27.56 +	// Start and stop background breadth-first fetching of inventory contents.
   27.57 +	// This gets triggered when performing a filter-search.
   27.58 +	void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE);
   27.59 +
   27.60 +	BOOL backgroundFetchActive() const;
   27.61 +	bool isEverythingFetched() const; // completing the fetch once per session should be sufficient
   27.62 +
   27.63 +	bool libraryFetchStarted() const;
   27.64 +	bool libraryFetchCompleted() const;
   27.65 +	bool libraryFetchInProgress() const;
   27.66 +
   27.67 +	bool inventoryFetchStarted() const;
   27.68 +	bool inventoryFetchCompleted() const;
   27.69 +	bool inventoryFetchInProgress() const;
   27.70 +
   27.71 +    void findLostItems();
   27.72 +protected:
   27.73 +	void incrBulkFetch(S16 fetching);
   27.74 +	bool isBulkFetchProcessingComplete() const;
   27.75 +	void bulkFetch(std::string url);
   27.76 +
   27.77 +	void backgroundFetch();
   27.78 +	static void backgroundFetchCB(void*); // background fetch idle function
   27.79 +	void stopBackgroundFetch(); // stop fetch process
   27.80 +
   27.81 +	void setAllFoldersFetched();
   27.82 +	bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const;
   27.83 +private:
   27.84 + 	BOOL mRecursiveInventoryFetchStarted;
   27.85 +	BOOL mRecursiveLibraryFetchStarted;
   27.86 +	BOOL mAllFoldersFetched;
   27.87 +
   27.88 +	BOOL mBackgroundFetchActive;
   27.89 +	S16 mBulkFetchCount;
   27.90 +	BOOL mTimelyFetchPending;
   27.91 +	S32 mNumFetchRetries;
   27.92 +
   27.93 +	LLFrameTimer mFetchTimer;
   27.94 +	F32 mMinTimeBetweenFetches;
   27.95 +	F32 mMaxTimeBetweenFetches;
   27.96 +
   27.97 +	struct FetchQueueInfo
   27.98 +	{
   27.99 +		FetchQueueInfo(const LLUUID& id, BOOL recursive) :
  27.100 +			mCatUUID(id), mRecursive(recursive)
  27.101 +		{
  27.102 +		}
  27.103 +		LLUUID mCatUUID;
  27.104 +		BOOL mRecursive;
  27.105 +	};
  27.106 +	typedef std::deque<FetchQueueInfo> fetch_queue_t;
  27.107 +	fetch_queue_t mFetchQueue;
  27.108 +};
  27.109 +
  27.110 +#endif // LL_LLINVENTORYMODELBACKGROUNDFETCH_H
    28.1 --- a/indra/newview/llinventoryview.cpp	Tue Dec 27 12:40:48 2011 +0100
    28.2 +++ b/indra/newview/llinventoryview.cpp	Sat Jan 07 17:05:31 2012 +0100
    28.3 @@ -57,6 +57,7 @@
    28.4  #include "llgesturemgr.h"
    28.5  #include "lliconctrl.h"
    28.6  #include "llinventorymodel.h"
    28.7 +#include "llinventorymodelbackgroundfetch.h"
    28.8  #include "llinventoryclipboard.h"
    28.9  #include "lllineeditor.h"
   28.10  #include "llmenugl.h"
   28.11 @@ -674,7 +675,7 @@
   28.12  
   28.13  void LLInventoryView::draw()
   28.14  {
   28.15 - 	if (LLInventoryModel::isEverythingFetched())
   28.16 + 	if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched())
   28.17  	{
   28.18  		LLLocale locale(LLLocale::USER_LOCALE);
   28.19  		std::ostringstream title;
   28.20 @@ -849,7 +850,7 @@
   28.21  {
   28.22  	std::ostringstream title;
   28.23  	title << "Inventory";
   28.24 - 	if (LLInventoryModel::backgroundFetchActive())
   28.25 + 	if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive())
   28.26  	{
   28.27  		LLLocale locale(LLLocale::USER_LOCALE);
   28.28  		std::string item_count_string;
   28.29 @@ -1006,7 +1007,7 @@
   28.30  		addDependentFloater(mFinderHandle);
   28.31  
   28.32  		// start background fetch of folders
   28.33 -		gInventory.startBackgroundFetch();
   28.34 +		LLInventoryModelBackgroundFetch::instance().start();
   28.35  
   28.36  		mFloaterControls[std::string("Inventory.ShowFilters")]->setValue(TRUE);
   28.37  	}
   28.38 @@ -1082,7 +1083,7 @@
   28.39  		return;
   28.40  	}
   28.41  
   28.42 -	gInventory.startBackgroundFetch();
   28.43 +	LLInventoryModelBackgroundFetch::instance().start();
   28.44  
   28.45  	std::string filter_text = search_string;
   28.46  	std::string uppercase_search_string = filter_text;
   28.47 @@ -1435,7 +1436,7 @@
   28.48  	if (filter->isActive())
   28.49  	{
   28.50  		// If our filter is active we may be the first thing requiring a fetch so we better start it here.
   28.51 -		gInventory.startBackgroundFetch();
   28.52 +		LLInventoryModelBackgroundFetch::instance().start();
   28.53  	}
   28.54  	self->setFilterTextFromFilter();
   28.55  	self->updateSortControls();
   28.56 @@ -1960,7 +1961,8 @@
   28.57  	if(handled)
   28.58  	{
   28.59  		ECursorType cursor = getWindow()->getCursor();
   28.60 -		if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
   28.61 +		if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
   28.62 +			&& cursor == UI_CURSOR_ARROW)
   28.63  		{
   28.64  			// replace arrow cursor with arrow and hourglass cursor
   28.65  			getWindow()->setCursor(UI_CURSOR_WORKING);
    29.1 --- a/indra/newview/llpanelface.cpp	Tue Dec 27 12:40:48 2011 +0100
    29.2 +++ b/indra/newview/llpanelface.cpp	Sat Jan 07 17:05:31 2012 +0100
    29.3 @@ -1228,7 +1228,7 @@
    29.4  		LLSD face = objectp->getTE(i)->asLLSD();
    29.5  		LLUUID image_id = objectp->getTE(i)->getID();
    29.6  		BOOL allow_texture = FALSE;
    29.7 -		if (gInventory.isObjectDescendentOf(face["imageid"], gInventoryLibraryRoot)
    29.8 +		if (gInventory.isObjectDescendentOf(face["imageid"], gInventory.getLibraryRootFolderID())
    29.9  			|| image_id == LLUUID(gSavedSettings.getString( "DefaultObjectTexture" ))
   29.10  			|| image_id == LLUUID(gSavedSettings.getString( "UIImgWhiteUUID" ))
   29.11  			|| image_id == LLUUID(gSavedSettings.getString( "UIImgInvisibleUUID" ))
    30.1 --- a/indra/newview/llpanelobject.cpp	Tue Dec 27 12:40:48 2011 +0100
    30.2 +++ b/indra/newview/llpanelobject.cpp	Sat Jan 07 17:05:31 2012 +0100
    30.3 @@ -2619,7 +2619,7 @@
    30.4  
    30.5  		LLUUID image_id = sculpt_params->getSculptTexture();
    30.6  		BOOL allow_texture = FALSE;
    30.7 -		if (gInventory.isObjectDescendentOf(image_id, gInventoryLibraryRoot)
    30.8 +		if (gInventory.isObjectDescendentOf(image_id, gInventory.getLibraryRootFolderID())
    30.9  			|| image_id == LLUUID(gSavedSettings.getString( "DefaultObjectTexture" ))
   30.10  			|| image_id == LLUUID(gSavedSettings.getString( "UIImgWhiteUUID" ))
   30.11  			|| image_id == LLUUID(gSavedSettings.getString( "UIImgInvisibleUUID" ))
    31.1 --- a/indra/newview/llpolymesh.h	Tue Dec 27 12:40:48 2011 +0100
    31.2 +++ b/indra/newview/llpolymesh.h	Sat Jan 07 17:05:31 2012 +0100
    31.3 @@ -259,6 +259,12 @@
    31.4  		return mBinormals; 
    31.5  	}
    31.6  
    31.7 +	// Get base mesh coords
    31.8 +	const LLVector3 *getBaseCoords() const{
    31.9 +		llassert(mSharedData);
   31.10 +		return mSharedData->mBaseCoords;
   31.11 +	}
   31.12 +
   31.13  	// Get base mesh normals
   31.14  	const LLVector3 *getBaseNormals() const{
   31.15  		llassert(mSharedData);
    32.1 --- a/indra/newview/llpreviewgesture.cpp	Tue Dec 27 12:40:48 2011 +0100
    32.2 +++ b/indra/newview/llpreviewgesture.cpp	Sat Jan 07 17:05:31 2012 +0100
    32.3 @@ -63,6 +63,7 @@
    32.4  #include "llfloatergesture.h"			// for some label constants
    32.5  #include "llgesturemgr.h"
    32.6  #include "llinventorymodel.h"
    32.7 +#include "llinventorymodelbackgroundfetch.h"
    32.8  #include "llviewerinventory.h"
    32.9  #include "llviewerobjectlist.h"
   32.10  #include "llviewerregion.h"
   32.11 @@ -153,10 +154,10 @@
   32.12  
   32.13  	// Start speculative download of sounds and animations
   32.14  	const LLUUID animation_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ANIMATION);
   32.15 -	gInventory.startBackgroundFetch(animation_folder_id);
   32.16 +	LLInventoryModelBackgroundFetch::instance().start(animation_folder_id);
   32.17  
   32.18  	const LLUUID sound_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SOUND);
   32.19 -	gInventory.startBackgroundFetch(sound_folder_id);
   32.20 +	LLInventoryModelBackgroundFetch::instance().start(sound_folder_id);
   32.21  
   32.22  	// this will call refresh when we have everything.
   32.23  	LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
   32.24 @@ -622,7 +623,7 @@
   32.25  													PERM_ITEM_UNRESTRICTED,
   32.26  													gAgent.getID(),
   32.27  													gAgent.getGroupID());
   32.28 -	gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
   32.29 +	gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
   32.30  									cats,
   32.31  									items,
   32.32  									LLInventoryModel::EXCLUDE_TRASH,
   32.33 @@ -667,7 +668,7 @@
   32.34  													PERM_ITEM_UNRESTRICTED,
   32.35  													gAgent.getID(),
   32.36  													gAgent.getGroupID());
   32.37 -	gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
   32.38 +	gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
   32.39  									cats,
   32.40  									items,
   32.41  									LLInventoryModel::EXCLUDE_TRASH,
    33.1 --- a/indra/newview/llpreviewscript.cpp	Tue Dec 27 12:40:48 2011 +0100
    33.2 +++ b/indra/newview/llpreviewscript.cpp	Sat Jan 07 17:05:31 2012 +0100
    33.3 @@ -1649,7 +1649,7 @@
    33.4  	const LLInventoryItem* item = gInventory.getItem(mItemUUID);
    33.5  	BOOL is_library = item
    33.6  		&& !gInventory.isObjectDescendentOf(mItemUUID,
    33.7 -											gAgent.getInventoryRootID());
    33.8 +											gInventory.getRootFolderID());
    33.9  	if(!item)
   33.10  	{
   33.11  		// do the more generic search.
    34.1 --- a/indra/newview/llstartup.cpp	Tue Dec 27 12:40:48 2011 +0100
    34.2 +++ b/indra/newview/llstartup.cpp	Sat Jan 07 17:05:31 2012 +0100
    34.3 @@ -124,6 +124,7 @@
    34.4  #include "llhudmanager.h"
    34.5  #include "llimagebmp.h"
    34.6  #include "llinventorymodel.h"
    34.7 +#include "llinventorymodelbackgroundfetch.h"
    34.8  #include "llinventoryview.h"
    34.9  #include "llkeyboard.h"
   34.10  #include "llloginhandler.h"			// gLoginHandler, SLURL support
   34.11 @@ -1705,7 +1706,9 @@
   34.12  				it = options[0].find("folder_id");
   34.13  				if(it != options[0].end())
   34.14  				{
   34.15 -					gAgent.mInventoryRootID.set((*it).second);
   34.16 +					LLUUID inv_root_folder_id;
   34.17 +					inv_root_folder_id.set((*it).second);
   34.18 +					gInventory.setRootFolderID(inv_root_folder_id);
   34.19  					//gInventory.mock(gAgent.getInventoryRootID());
   34.20  				}
   34.21  			}
   34.22 @@ -1848,7 +1851,7 @@
   34.23  			   && gAgentSessionID.notNull()
   34.24  			   && gMessageSystem->mOurCircuitCode
   34.25  			   && first_sim.isOk()
   34.26 -			   && gAgent.mInventoryRootID.notNull())
   34.27 +			   && gInventory.getRootFolderID().notNull())
   34.28  			{
   34.29  				LLStartUp::setStartupState( STATE_WORLD_INIT );
   34.30  			}
   34.31 @@ -2316,7 +2319,9 @@
   34.32  			it = options[0].find("folder_id");
   34.33  			if(it != options[0].end())
   34.34  			{
   34.35 -				gInventoryLibraryRoot.set((*it).second);
   34.36 +				LLUUID lib_root_folder_id;
   34.37 +				lib_root_folder_id.set((*it).second);
   34.38 +				gInventory.setLibraryRootFolderID(lib_root_folder_id);
   34.39  			}
   34.40  		}
   34.41   		options.clear();
   34.42 @@ -2328,14 +2333,16 @@
   34.43  			it = options[0].find("agent_id");
   34.44  			if(it != options[0].end())
   34.45  			{
   34.46 -				gInventoryLibraryOwner.set((*it).second);
   34.47 +				LLUUID lib_owner_id;
   34.48 +				lib_owner_id.set((*it).second);
   34.49 +				gInventory.setLibraryOwnerID(lib_owner_id);
   34.50  			}
   34.51  		}
   34.52   		options.clear();
   34.53   		if(LLUserAuth::getInstance()->getOptions("inventory-skel-lib", options)
   34.54 -			&& gInventoryLibraryOwner.notNull())
   34.55 +			&& gInventory.getLibraryOwnerID().notNull())
   34.56   		{
   34.57 - 			if(!gInventory.loadSkeleton(options, gInventoryLibraryOwner))
   34.58 + 			if(!gInventory.loadSkeleton(options, gInventory.getLibraryOwnerID()))
   34.59   			{
   34.60   				LL_WARNS("AppInit") << "Problem loading inventory-skel-lib" << LL_ENDL;
   34.61   			}
   34.62 @@ -2632,7 +2639,7 @@
   34.63  		if (gSavedSettings.getBOOL("FetchInventoryOnLogin"))
   34.64  		{
   34.65  			// Fetch inventory in the background
   34.66 -			gInventory.startBackgroundFetch();
   34.67 +			LLInventoryModelBackgroundFetch::instance().start();
   34.68  		}
   34.69  
   34.70  		// HACK: Inform simulator of window size.
   34.71 @@ -2697,7 +2704,7 @@
   34.72  		}
   34.73  
   34.74          //DEV-17797.  get null folder.  Any items found here moved to Lost and Found
   34.75 -        LLInventoryModel::findLostItems();
   34.76 +        LLInventoryModelBackgroundFetch::instance().findLostItems();
   34.77  
   34.78  		LLStartUp::setStartupState( STATE_PRECACHE );
   34.79  		timeout.reset();
    35.1 --- a/indra/newview/lltexturectrl.cpp	Tue Dec 27 12:40:48 2011 +0100
    35.2 +++ b/indra/newview/lltexturectrl.cpp	Sat Jan 07 17:05:31 2012 +0100
    35.3 @@ -45,6 +45,7 @@
    35.4  #include "llfolderview.h"
    35.5  #include "llinventory.h"
    35.6  #include "llinventorymodel.h"
    35.7 +#include "llinventorymodelbackgroundfetch.h"
    35.8  #include "llinventoryview.h"
    35.9  #include "lllineeditor.h"
   35.10  #include "llui.h"
   35.11 @@ -466,7 +467,7 @@
   35.12  		{
   35.13  			if (!root_folder->getCurSelectedItem())
   35.14  			{
   35.15 -				LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID());
   35.16 +				LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID());
   35.17  				if (itemp)
   35.18  				{
   35.19  					root_folder->setSelection(itemp, FALSE, FALSE);
   35.20 @@ -1309,7 +1310,7 @@
   35.21  	{
   35.22  		// We need to find textures in all folders, so get the main
   35.23  		// background download going.
   35.24 -		gInventory.startBackgroundFetch();
   35.25 +		LLInventoryModelBackgroundFetch::instance().start();
   35.26  		gInventory.removeObserver(this);
   35.27  		delete this;
   35.28  	}
   35.29 @@ -1330,9 +1331,9 @@
   35.30  		showPicker(FALSE);
   35.31  
   35.32  		//grab textures first...
   35.33 -		gInventory.startBackgroundFetch(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
   35.34 +		LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE));
   35.35  		//...then start full inventory fetch.
   35.36 -		gInventory.startBackgroundFetch();
   35.37 +		LLInventoryModelBackgroundFetch::instance().start();
   35.38  	}
   35.39  	return handled;
   35.40  }
    36.1 --- a/indra/newview/llviewerinventory.cpp	Tue Dec 27 12:40:48 2011 +0100
    36.2 +++ b/indra/newview/llviewerinventory.cpp	Sat Jan 07 17:05:31 2012 +0100
    36.3 @@ -40,11 +40,12 @@
    36.4  
    36.5  #include "llagent.h"
    36.6  #include "llconsole.h"
    36.7 -#include "llinventorymodel.h"
    36.8  #include "llimview.h"
    36.9  #include "llgesturemgr.h"
   36.10  
   36.11  #include "llinventorybridge.h"
   36.12 +#include "llinventorymodel.h"
   36.13 +#include "llinventorymodelbackgroundfetch.h"
   36.14  #include "llinventoryview.h"
   36.15  
   36.16  #include "llviewercontrol.h"
   36.17 @@ -469,12 +470,14 @@
   36.18  	gAgent.sendReliableMessage();
   36.19  }
   36.20  
   36.21 -bool LLViewerInventoryCategory::fetchDescendents()
   36.22 +bool LLViewerInventoryCategory::fetch()
   36.23  {
   36.24 -	if((VERSION_UNKNOWN == mVersion)
   36.25 -	   && mDescendentsRequested.hasExpired())	//Expired check prevents multiple downloads.
   36.26 +	static LLViewerRegion *last_region = NULL;
   36.27 +
   36.28 +	if (VERSION_UNKNOWN == mVersion && mDescendentsRequested.hasExpired())	//Expired check prevents multiple downloads.
   36.29  	{
   36.30 -		LL_DEBUGS("InventoryFetch") << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL;
   36.31 +		LL_DEBUGS("InventoryFetch") << "Fetching category children: " << mName
   36.32 +									<< ", UUID: " << mUUID << LL_ENDL;
   36.33  		const F32 FETCH_TIMER_EXPIRY = 10.0f;
   36.34  		mDescendentsRequested.reset();
   36.35  		mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY);
   36.36 @@ -484,29 +487,50 @@
   36.37  		// 2 = folders by date
   36.38  		// Need to mask off anything but the first bit.
   36.39  		// This comes from LLInventoryFilter from llfolderview.h
   36.40 -		U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
   36.41 +		U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER) & 0x1;
   36.42  
   36.43 -		std::string url = gAgent.getCapability("agent/inventory"); // OGPX : was WebFetchInventoryDescendents
   36.44 -		if (url.empty()) //OGPX : agent/inventory Capability not found on agent domain.  See if the region has one.
   36.45 +		std::string capability, url;
   36.46 +		if (gSavedSettings.getBOOL("OpenGridProtocol"))
   36.47  		{
   36.48 -			//llinfos << " agent/inventory not on AD, checking fallback to region " << llendl; //OGPX
   36.49 -			if (gAgent.getRegion())
   36.50 +			capability = "agent/inventory";
   36.51 +			url = gAgent.getCapability(capability); // OGPX
   36.52 +		}
   36.53 +		LLViewerRegion* region = gAgent.getRegion();
   36.54 +		if (url.empty())
   36.55 +		{
   36.56 +			if (region)
   36.57  			{
   36.58 -				url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
   36.59 +				capability = "FetchInventoryDescendents2";
   36.60 +				url = region->getCapability(capability);
   36.61 +				if (url.empty() && gSavedSettings.getBOOL("OpenGridProtocol"))
   36.62 +				{
   36.63 +					capability = "WebFetchInventoryDescendents";
   36.64 +					url = region->getCapability(capability);
   36.65 +				}
   36.66  			}
   36.67  			else
   36.68  			{
   36.69 -				llwarns << "agent region is null" << llendl;
   36.70 +				llwarns << "Agent region is null" << llendl;
   36.71  			}
   36.72  		}
   36.73  		if (!url.empty()) //Capability found.  Build up LLSD and use it.
   36.74  		{
   36.75 -			LLInventoryModel::startBackgroundFetch(mUUID);			
   36.76 +			if (region != last_region)	// Do not spam the log file.
   36.77 +			{
   36.78 +				llinfos << "Using capability \"" << capability
   36.79 +						<< "\" for inventory fetch." << llendl;
   36.80 +				last_region = region;
   36.81 +			}
   36.82 +			LLInventoryModelBackgroundFetch::instance().start(mUUID);			
   36.83  		}
   36.84  		else
   36.85 -		{	//Deprecated, but if we don't have a capability, use the old system.
   36.86 -			//Great, but we don't need to know about it, removed this info message.
   36.87 -			//llinfos << "WebFetchInventoryDescendents or agent/inventory capability not found.  Using deprecated UDP message." << llendl;
   36.88 +		{	// Deprecated, but if we don't have a capability, use the old system.
   36.89 +			if (region != last_region)	// Do not spam the log file.
   36.90 +			{
   36.91 +				llinfos << "Inventory fetch capabilities not found. Using deprecated UDP message."
   36.92 +						<< llendl;
   36.93 +				last_region = region;
   36.94 +			}
   36.95  			LLMessageSystem* msg = gMessageSystem;
   36.96  			msg->newMessage("FetchInventoryDescendents");
   36.97  			msg->nextBlock("AgentData");
    37.1 --- a/indra/newview/llviewerinventory.h	Tue Dec 27 12:40:48 2011 +0100
    37.2 +++ b/indra/newview/llviewerinventory.h	Sat Jan 07 17:05:31 2012 +0100
    37.3 @@ -191,7 +191,7 @@
    37.4  	void setVersion(S32 version) { mVersion = version; }
    37.5  
    37.6  	// Returns true if a fetch was issued.
    37.7 -	bool fetchDescendents();
    37.8 +	bool fetch();
    37.9  
   37.10  	// used to help make cacheing more robust - for example, if
   37.11  	// someone is getting 4 packets but logs out after 3. the viewer
    38.1 --- a/indra/newview/llviewermenu.cpp	Tue Dec 27 12:40:48 2011 +0100
    38.2 +++ b/indra/newview/llviewermenu.cpp	Sat Jan 07 17:05:31 2012 +0100
    38.3 @@ -259,8 +259,6 @@
    38.4  LLVOAvatar* find_avatar_from_object( LLViewerObject* object );
    38.5  LLVOAvatar* find_avatar_from_object( const LLUUID& object_id );
    38.6  
    38.7 -void handle_test_load_url(void*);
    38.8 -
    38.9  //
   38.10  // Evil hackish imported globals
   38.11  //
   38.12 @@ -1012,6 +1010,12 @@
   38.13  										(void*) "MouseSmooth"));
   38.14  	menu->appendSeparator();
   38.15  
   38.16 +	menu->append(new LLMenuItemCheckGL("HTTP Inventory Fetches",
   38.17 +										&menu_toggle_control,
   38.18 +										NULL,
   38.19 +										&menu_check_control,
   38.20 +										(void*) "UseHTTPInventory"));
   38.21 +
   38.22  	menu->append(new LLMenuItemCheckGL( "Console Window", 
   38.23  										&menu_toggle_control,
   38.24  										NULL, 
   38.25 @@ -1438,7 +1442,7 @@
   38.26  	item = new LLMenuItemCheckGL("HTTP Get Textures", toggle_HTTPGetTextures, NULL, menu_check_control, (void*)"ImagePipelineUseHTTPFetch3");
   38.27  	menu->append(item);
   38.28  #endif
   38.29 -	
   38.30 +
   38.31  	item = new LLMenuItemCheckGL("Run Multiple Threads", menu_toggle_control, NULL, menu_check_control, (void*)"RunMultipleThreads");
   38.32  	menu->append(item);
   38.33  
   38.34 @@ -4580,7 +4584,7 @@
   38.35  			}
   38.36  
   38.37  			// check library
   38.38 -			if(gInventory.isObjectDescendentOf(category_id, gInventoryLibraryRoot))
   38.39 +			if (gInventory.isObjectDescendentOf(category_id, gInventory.getRootFolderID()))
   38.40  			{
   38.41  				category_id.setNull();
   38.42  			}
   38.43 @@ -8614,14 +8618,6 @@
   38.44  	}
   38.45  };
   38.46  
   38.47 -void handle_test_load_url(void*)
   38.48 -{
   38.49 -	LLWeb::loadURL("");
   38.50 -	LLWeb::loadURL("hacker://www.google.com/");
   38.51 -	LLWeb::loadURL("http");
   38.52 -	LLWeb::loadURL("http://www.google.com/");
   38.53 -}
   38.54 -
   38.55  //
   38.56  // LLViewerMenuHolderGL
   38.57  //
    39.1 --- a/indra/newview/llviewermessage.cpp	Tue Dec 27 12:40:48 2011 +0100
    39.2 +++ b/indra/newview/llviewermessage.cpp	Sat Jan 07 17:05:31 2012 +0100
    39.3 @@ -6115,7 +6115,7 @@
    39.4  	{
    39.5  		// create a new inventory category to put this in
    39.6  		LLUUID cat_id;
    39.7 -		cat_id = gInventory.createNewCategory(gAgent.getInventoryRootID(),
    39.8 +		cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(),
    39.9  											  LLFolderType::FT_NONE,
   39.10  											  std::string("Acquired Items")); //TODO: Translate
   39.11  
    40.1 --- a/indra/newview/llviewerregion.cpp	Tue Dec 27 12:40:48 2011 +0100
    40.2 +++ b/indra/newview/llviewerregion.cpp	Sat Jan 07 17:05:31 2012 +0100
    40.3 @@ -59,6 +59,7 @@
    40.4  #include "llsdutil.h"
    40.5  #include "llstartup.h"
    40.6  #include "lltrans.h"
    40.7 +#include "llviewercontrol.h"
    40.8  #include "llviewerobjectlist.h"
    40.9  #include "llviewerparceloverlay.h"
   40.10  #include "llvlmanager.h"
   40.11 @@ -1433,6 +1434,13 @@
   40.12  	capabilityNames.append("FetchInventory");
   40.13  	capabilityNames.append("FetchLib");
   40.14  	capabilityNames.append("FetchLibDescendents");
   40.15 +	if (gSavedSettings.getBOOL("UseHTTPInventory"))
   40.16 +	{
   40.17 +		capabilityNames.append("FetchLib2");
   40.18 +		capabilityNames.append("FetchLibDescendents2");
   40.19 +		capabilityNames.append("FetchInventory2");
   40.20 +		capabilityNames.append("FetchInventoryDescendents2");
   40.21 +	}
   40.22  	capabilityNames.append("GetMesh");
   40.23  	capabilityNames.append("GetObjectCost");
   40.24  	capabilityNames.append("GetObjectPhysicsData");
    41.1 --- a/indra/newview/llvoavatar.cpp	Tue Dec 27 12:40:48 2011 +0100
    41.2 +++ b/indra/newview/llvoavatar.cpp	Sat Jan 07 17:05:31 2012 +0100
    41.3 @@ -6801,6 +6801,7 @@
    41.4  
    41.5  	dirtyMesh();
    41.6  	updateHeadOffset();
    41.7 +	rebuildRiggedAttachments();
    41.8  }
    41.9  
   41.10  //-----------------------------------------------------------------------------
   41.11 @@ -9880,6 +9881,11 @@
   41.12  	dirtyMesh();
   41.13  }
   41.14  
   41.15 +LLPolyMesh* LLVOAvatar::getMesh(S32 which)
   41.16 +{
   41.17 +	return mMeshLOD[which]->mMeshParts[0]->getMesh();
   41.18 +}
   41.19 +
   41.20  // static
   41.21  void LLVOAvatar::dumpArchetypeXML( void* )
   41.22  {
    42.1 --- a/indra/newview/llvoavatar.h	Tue Dec 27 12:40:48 2011 +0100
    42.2 +++ b/indra/newview/llvoavatar.h	Sat Jan 07 17:05:31 2012 +0100
    42.3 @@ -222,6 +222,7 @@
    42.4  	virtual F32 getPixelArea() const;
    42.5  	virtual LLPolyMesh*	getHeadMesh();
    42.6  	virtual LLPolyMesh*	getUpperBodyMesh();
    42.7 +	virtual LLPolyMesh* getMesh(S32 which);
    42.8  	virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position);
    42.9  	virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position);
   42.10  	virtual void updateVisualParams();
    43.1 --- a/indra/newview/llvovolume.cpp	Tue Dec 27 12:40:48 2011 +0100
    43.2 +++ b/indra/newview/llvovolume.cpp	Sat Jan 07 17:05:31 2012 +0100
    43.3 @@ -3798,6 +3798,206 @@
    43.4  	}
    43.5  }
    43.6  
    43.7 +LLDeformedVolume* LLVOVolume::getDeformedVolume()
    43.8 +{
    43.9 +	if (!mDeformedVolume)
   43.10 +	{
   43.11 +		// doesn't exist yet - make it
   43.12 +		mDeformedVolume = new LLDeformedVolume;
   43.13 +	}
   43.14 +
   43.15 +	return mDeformedVolume;
   43.16 +}
   43.17 +
   43.18 +LLDeformedVolume::deform_table_t& LLDeformedVolume::getDeformTable(LLVolume* source, LLVOAvatar* avatar, const LLMeshSkinInfo* skin, S32 face)
   43.19 +{
   43.20 +	LLDeformTableCacheIndex cache_index(source->getParams().getSculptID(), face, source->getVolumeFace(face).mNumVertices);
   43.21 +
   43.22 +	deform_cache_t::iterator i = mDeformCache.find(cache_index);
   43.23 +
   43.24 +	if (i != mDeformCache.end())
   43.25 +	{
   43.26 +		return i->second;
   43.27 +	}
   43.28 +
   43.29 +	// doesn't exist in cache, must create
   43.30 +
   43.31 +	// tables are fairly small, we keep them around in case the user is switching between meshes for poorman's animation
   43.32 +	U32 MAX_CACHE_SIZE = 20;  
   43.33 +
   43.34 +	if (mDeformCache.size() > MAX_CACHE_SIZE)
   43.35 +	{
   43.36 +		// delete element at random
   43.37 +		U32 random = ll_rand(MAX_CACHE_SIZE-1);
   43.38 +
   43.39 +		deform_cache_t::iterator iterator = mDeformCache.begin();
   43.40 +
   43.41 +		for (int i = 0; i < random; i++)
   43.42 +		{
   43.43 +			iterator++;
   43.44 +		}
   43.45 +		
   43.46 +		mDeformCache.erase(iterator);
   43.47 +	}
   43.48 +
   43.49 +	deform_table_t& deform_table = mDeformCache[cache_index];
   43.50 +
   43.51 +	// table is a mapping from verts on the volume to verts on the avatar mesh.
   43.52 +	// currently we take closest point - but may want to modify this is favor
   43.53 +	// verts with similar skin weights and/or normals (so verts on the left leg
   43.54 +	// don't move with the right leg by accident.)
   43.55 +
   43.56 +	const LLVolumeFace& source_face = source->getVolumeFace(face);
   43.57 +
   43.58 +	// build mapping
   43.59 +	deform_table.resize(source_face.mNumVertices);
   43.60 +
   43.61 +	// maps volume space to object (avatar) space
   43.62 +	LLMatrix4a bind_shape_matrix_a;
   43.63 +	bind_shape_matrix_a.loadu(skin->mBindShapeMatrix);  
   43.64 +	// skeleton scaling factor - lots of assumptions in this, but necessary for efficiency
   43.65 +	F32 scale = powf(skin->mInvBindMatrix[0].determinant(), 1.0f / 3.0f);
   43.66 +
   43.67 +	// these are the meshes we follow
   43.68 +	S32 MORPH_MESHES[] = { LLVOAvatarDefines::MESH_ID_HEAD,
   43.69 +						   LLVOAvatarDefines::MESH_ID_UPPER_BODY,
   43.70 +						   LLVOAvatarDefines::MESH_ID_LOWER_BODY };
   43.71 +
   43.72 +	// for each vertex in the volume, find the closest vertex on the avatar mesh(es)	
   43.73 +	for (S32 i = 0; i < source_face.mNumVertices; i++)
   43.74 +	{
   43.75 +		LLVector4a source_position = source_face.mPositions[i];
   43.76 +		LLVector4a source_position_transformed;
   43.77 +		bind_shape_matrix_a.affineTransform(source_position, source_position_transformed);
   43.78 +		source_position_transformed.mul(scale);
   43.79 +
   43.80 +		F32 closest_distance = 0.0f;
   43.81 +		S32 closest_vertex = 0;
   43.82 +		S32 closest_mesh = 0;
   43.83 +
   43.84 +		BOOL first_time = TRUE;
   43.85 +
   43.86 +		for (S32 k = 0; k < sizeof(MORPH_MESHES)/sizeof(S32); k++)
   43.87 +		{
   43.88 +			S32 mesh_id = MORPH_MESHES[k];
   43.89 +
   43.90 +			LLPolyMesh* avatar_mesh = avatar->getMesh(mesh_id);
   43.91 +
   43.92 +			const LLVector3* base_positions = avatar_mesh->getBaseCoords();
   43.93 +
   43.94 +			for (S32 j = 0; j < avatar_mesh->getNumVertices(); j++)
   43.95 +			{
   43.96 +				LLVector4a base_position;
   43.97 +				base_position.load3(base_positions[j].mV);
   43.98 +
   43.99 +				LLVector4a delta;
  43.100 +				delta.setSub(source_position_transformed, base_position);
  43.101 +
  43.102 +				F32 distance = delta.getLength3().getF32();
  43.103 +				
  43.104 +				if (first_time ||  // first time through loop is always closest
  43.105 +					(distance < closest_distance))
  43.106 +				{
  43.107 +					closest_distance = distance;
  43.108 +					closest_vertex = j;
  43.109 +					closest_mesh = mesh_id;
  43.110 +					first_time = FALSE;
  43.111 +				}
  43.112 +			}
  43.113 +		}
  43.114 +		// create entry for found vertex
  43.115 +		deform_table[i].mVertex = closest_vertex;
  43.116 +		deform_table[i].mMesh = (U8)closest_mesh;	
  43.117 +	}
  43.118 +
  43.119 +	return deform_table;
  43.120 +}
  43.121 +
  43.122 +void LLDeformedVolume::deform(LLVolume* source, LLVOAvatar* avatar, const LLMeshSkinInfo* skin, S32 face)
  43.123 +{
  43.124 +	LLFastTimer t(LLFastTimer::FTM_SKIN_RIGGED_DEFORM);
  43.125 +
  43.126 +	bool copy = false;
  43.127 +	if (source->getNumVolumeFaces() != getNumVolumeFaces())
  43.128 +	{ 
  43.129 +		copy = true;
  43.130 +	}
  43.131 +
  43.132 +	for (S32 i = 0; i < source->getNumVolumeFaces() && !copy; ++i)
  43.133 +	{
  43.134 +		const LLVolumeFace& src_face = source->getVolumeFace(i);
  43.135 +		const LLVolumeFace& dst_face = getVolumeFace(i);
  43.136 +		
  43.137 +		if (src_face.mNumIndices != dst_face.mNumIndices ||
  43.138 +			src_face.mNumVertices != dst_face.mNumVertices)
  43.139 +		{
  43.140 +			copy = true;
  43.141 +		}
  43.142 +	}
  43.143 +
  43.144 +	if (copy)
  43.145 +	{
  43.146 +		copyVolumeFaces(source);	
  43.147 +	}
  43.148 +
  43.149 +	const LLVolumeFace& source_face = source->getVolumeFace(face);
  43.150 +	const LLVolumeFace& destination_face = getVolumeFace(face);
  43.151 +
  43.152 +	// transforms volume space to avatar space
  43.153 +	LLMatrix4a bind_shape_matrix_a;
  43.154 +	bind_shape_matrix_a.loadu(skin->mBindShapeMatrix);
  43.155 +
  43.156 +	// transforms back again
  43.157 +	LLMatrix4 bind_shape_matrix_inverse = skin->mBindShapeMatrix;
  43.158 +	bind_shape_matrix_inverse.invert_real();
  43.159 +	LLMatrix4a bind_shape_matrix_inverse_a;
  43.160 +	bind_shape_matrix_inverse_a.loadu(bind_shape_matrix_inverse);
  43.161 +
  43.162 +	// skeleton scaling factor - lots of assumptions in this, but necessary for efficiency
  43.163 +	F32 scale = powf(skin->mInvBindMatrix[0].determinant(), 1.0f / 3.0f);
  43.164 +
  43.165 +	// get the deform table
  43.166 +	LLDeformTableCacheIndex cache_index(source->getParams().getSculptID(), face, source->getVolumeFace(face).mNumVertices);
  43.167 +	deform_table_t& deform_table = getDeformTable(source, avatar, skin, face);
  43.168 +
  43.169 +	for (S32 i = 0; i < source_face.mNumVertices; i++)
  43.170 +	{
  43.171 +		U16 closest_vertex = deform_table[i].mVertex;
  43.172 +		S32 closest_mesh = deform_table[i].mMesh;
  43.173 +		
  43.174 +		// find the current mesh
  43.175 +		LLPolyMesh* avatar_mesh = avatar->getMesh(closest_mesh);
  43.176 +		// and get positions for both original and morphed vertices
  43.177 +		const LLVector3* base_positions = avatar_mesh->getBaseCoords();
  43.178 +		const LLVector4* morph_positions = avatar_mesh->getCoords();
  43.179 +
  43.180 +		// find the movement of this vertex due to morphing
  43.181 +		LLVector4a base_position;
  43.182 +		base_position.load3(base_positions[closest_vertex].mV);
  43.183 +		LLVector4a morph_position;
  43.184 +		morph_position.load3(morph_positions[closest_vertex].mV);
  43.185 +		LLVector4a morph_delta;
  43.186 +		morph_delta.setSub(morph_position, base_position);
  43.187 +
  43.188 +		// source position mapped to avatar space
  43.189 +		LLVector4a source_position = source_face.mPositions[i];
  43.190 +		LLVector4a source_position_transformed;
  43.191 +		bind_shape_matrix_a.affineTransform(source_position, source_position_transformed);
  43.192 +		source_position_transformed.mul(scale);
  43.193 +
  43.194 +		// modify by movement delta
  43.195 +		LLVector4a destination_position_transformed;
  43.196 +		destination_position_transformed.setAdd(source_position_transformed, morph_delta);
  43.197 +		
  43.198 +		// map back to volume space
  43.199 +		destination_position_transformed.mul(1.0f / scale);
  43.200 +		LLVector4a destination_position;
  43.201 +		bind_shape_matrix_inverse_a.affineTransform(destination_position_transformed, destination_position);
  43.202 +		
  43.203 +		destination_face.mPositions[i] = destination_position;
  43.204 +	}
  43.205 +}
  43.206 +
  43.207  U32 LLVOVolume::getPartitionType() const
  43.208  {
  43.209  	if (isHUDAttachment())
    44.1 --- a/indra/newview/llvovolume.h	Tue Dec 27 12:40:48 2011 +0100
    44.2 +++ b/indra/newview/llvovolume.h	Sat Jan 07 17:05:31 2012 +0100
    44.3 @@ -74,6 +74,61 @@
    44.4  	void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume);
    44.5  };
    44.6  
    44.7 +class LLDeformedVolume : public LLVolume
    44.8 +{
    44.9 +public:
   44.10 +	LLDeformedVolume()
   44.11 +	:	LLVolume(LLVolumeParams(), 0.f)
   44.12 +	{
   44.13 +	}
   44.14 +
   44.15 +	// used as a key for the deform table cache
   44.16 +	class LLDeformTableCacheIndex
   44.17 +	{
   44.18 +	public:
   44.19 +		LLDeformTableCacheIndex(const LLUUID& id, S32 face, S32 vertex_count) :
   44.20 +		mID(id), mFace(face), mVertexCount(vertex_count) {}
   44.21 +
   44.22 +		LLUUID mID;
   44.23 +		S32 mFace;
   44.24 +		S32 mVertexCount;
   44.25 +
   44.26 +		bool operator<(const LLDeformTableCacheIndex& lhs) const
   44.27 +		{
   44.28 +			if (mID < lhs.mID)
   44.29 +				return TRUE;
   44.30 +			if (mID > lhs.mID)
   44.31 +				return FALSE;
   44.32 +			if (mFace < lhs.mFace)
   44.33 +				return TRUE;
   44.34 +			if (mFace > lhs.mFace)
   44.35 +				return FALSE;
   44.36 +			if (mVertexCount < lhs.mVertexCount)
   44.37 +				return TRUE;
   44.38 +			
   44.39 +			return FALSE;
   44.40 +		}
   44.41 +	};
   44.42 +
   44.43 +	// these are entries in the deformer table.
   44.44 +	// they map vertices on the volume mesh to
   44.45 +	// vertices on the avatar mesh(es).
   44.46 +	struct LLDeformMap
   44.47 +	{
   44.48 +		U8 mMesh;
   44.49 +		U16 mVertex;
   44.50 +	};
   44.51 +
   44.52 +	typedef std::vector<struct LLDeformMap> deform_table_t;
   44.53 +	typedef std::map<LLDeformTableCacheIndex, deform_table_t > deform_cache_t;
   44.54 +	deform_cache_t mDeformCache;
   44.55 +
   44.56 +	void deform(LLVolume* source, LLVOAvatar* avatar, const LLMeshSkinInfo* skin, S32 face);
   44.57 +
   44.58 +private:
   44.59 +	deform_table_t& getDeformTable(LLVolume* source, LLVOAvatar* avatar, const LLMeshSkinInfo* skin, S32 face);
   44.60 +};
   44.61 +
   44.62  // Base class for implementations of the volume - Primitive, Flexible Object, etc.
   44.63  class LLVolumeInterface
   44.64  {
   44.65 @@ -334,6 +389,9 @@
   44.66  	//clear out rigged volume and revert back to non-rigged state for picking/LOD/distance updates
   44.67  	void clearRiggedVolume();
   44.68  
   44.69 +	// deformed volume (rigged attachments follow avatar morph shape changes
   44.70 +	LLDeformedVolume* getDeformedVolume();
   44.71 +
   44.72  protected:
   44.73  	S32	computeLODDetail(F32	distance, F32 radius);
   44.74  	BOOL calcLOD();
   44.75 @@ -374,6 +432,7 @@
   44.76  #endif
   44.77  
   44.78  	LLPointer<LLRiggedVolume> mRiggedVolume;
   44.79 +	LLPointer<LLDeformedVolume> mDeformedVolume;
   44.80  
   44.81  	// statics
   44.82  public:
    45.1 --- a/indra/newview/rlvhelper.cpp	Tue Dec 27 12:40:48 2011 +0100
    45.2 +++ b/indra/newview/rlvhelper.cpp	Sat Jan 07 17:05:31 2012 +0100
    45.3 @@ -683,7 +683,7 @@
    45.4  		}
    45.5  
    45.6  		LLViewerInventoryCategory* pFolder = gInventory.getCategory(pItem->getParentUUID());
    45.7 -		while ( (pFolder) && (gAgent.getInventoryRootID() != pFolder->getParentUUID()) )
    45.8 +		while ( (pFolder) && (gInventory.getRootFolderID() != pFolder->getParentUUID()) )
    45.9  		{
   45.10  			if (std::string::npos != pFolder->getName().find(RLV_FOLDER_FLAG_NOSTRIP))
   45.11  				return false;
    46.1 --- a/indra/newview/rlvinventory.cpp	Tue Dec 27 12:40:48 2011 +0100
    46.2 +++ b/indra/newview/rlvinventory.cpp	Sat Jan 07 17:05:31 2012 +0100
    46.3 @@ -261,7 +261,7 @@
    46.4  	if ( (m_idRlvRoot.isNull()) && (gInventory.isInventoryUsable()) )
    46.5  	{
    46.6  		LLInventoryModel::cat_array_t* pFolders; LLInventoryModel::item_array_t* pItems;
    46.7 -		gInventory.getDirectDescendentsOf(gAgent.getInventoryRootID(), pFolders, pItems);
    46.8 +		gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), pFolders, pItems);
    46.9  		if (pFolders)
   46.10  		{
   46.11  			// NOTE: we might have multiple #RLV folders so we'll just go with the first one we come across
   46.12 @@ -341,7 +341,7 @@
   46.13  		return std::string();
   46.14  
   46.15  	const LLUUID& idRLV  = pRlvRoot->getUUID();
   46.16 -	const LLUUID& idRoot = gAgent.getInventoryRootID();
   46.17 +	const LLUUID& idRoot = gInventory.getRootFolderID();
   46.18  	std::string strPath;
   46.19  
   46.20  	// Walk up the tree until we reach the top
   46.21 @@ -652,7 +652,7 @@
   46.22  	while ((itCurFolder = m_WearActionMap.find(idCurFolder)) == m_WearActionMap.end())
   46.23  	{
   46.24  		const LLViewerInventoryCategory* pFolder = gInventory.getCategory(idCurFolder);
   46.25 -		if ((!pFolder) || (gAgent.getInventoryRootID() == pFolder->getParentUUID()))
   46.26 +		if ((!pFolder) || (gInventory.getRootFolderID() == pFolder->getParentUUID()))
   46.27  			break;
   46.28  		idCurFolder = pFolder->getParentUUID();
   46.29  	}
    47.1 --- a/indra/newview/rlvlocks.cpp	Tue Dec 27 12:40:48 2011 +0100
    47.2 +++ b/indra/newview/rlvlocks.cpp	Sat Jan 07 17:05:31 2012 +0100
    47.3 @@ -996,7 +996,7 @@
    47.4  			break;
    47.5  		case ST_ROOTFOLDER:
    47.6  			{
    47.7 -				LLViewerInventoryCategory* pFolder = gInventory.getCategory(gAgent.getInventoryRootID());
    47.8 +				LLViewerInventoryCategory* pFolder = gInventory.getCategory(gInventory.getRootFolderID());
    47.9  				if (pFolder)
   47.10  					lockFolders.push_back(pFolder);
   47.11  			}
   47.12 @@ -1105,7 +1105,7 @@
   47.13  		refreshLockedLookups();
   47.14  
   47.15  	// Walk up the folder tree and check if anything has 'idFolder' locked
   47.16 -	std::list<LLUUID> idsRlvObjRem, idsRlvObjAdd; const LLUUID& idFolderRoot = gAgent.getInventoryRootID(); LLUUID idFolderCur = idFolder;
   47.17 +	std::list<LLUUID> idsRlvObjRem, idsRlvObjAdd; const LLUUID& idFolderRoot = gInventory.getRootFolderID(); LLUUID idFolderCur = idFolder;
   47.18  	while (idFolderRoot != idFolderCur)
   47.19  	{
   47.20  		// Iterate over any folder locks for 'idFolderCur'
   47.21 @@ -1167,7 +1167,7 @@
   47.22  	{
   47.23  		const folderlock_descr_t* pLockDescr = *itFolderLock;
   47.24  
   47.25 -		LLInventoryModel::cat_array_t lockedFolders; const LLUUID& idFolderRoot = gAgent.getInventoryRootID();
   47.26 +		LLInventoryModel::cat_array_t lockedFolders; const LLUUID& idFolderRoot = gInventory.getRootFolderID();
   47.27  		if (getLockedFolders(pLockDescr->lockSource, lockedFolders))
   47.28  		{
   47.29  			for (S32 idxFolder = 0, cntFolder = lockedFolders.count(); idxFolder < cntFolder; idxFolder++)

mercurial