diff options
| author | leyla_linden <none@none> | 2011-01-19 11:39:25 -0800 | 
|---|---|---|
| committer | leyla_linden <none@none> | 2011-01-19 11:39:25 -0800 | 
| commit | 17068766b75fbe7dac968705f4f383fb61f73eb4 (patch) | |
| tree | 9a6923653b721311b61edac947b2e7682972cce3 /indra/newview | |
| parent | ca1c1eea78ff2ab83979a4308dd5a93ea0032fc8 (diff) | |
| parent | eec6071766e6fef7015610b002a9bcb09ce36836 (diff) | |
Merge
Diffstat (limited to 'indra/newview')
46 files changed, 1503 insertions, 892 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8ea0dd1089..437be15150 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -542,6 +542,7 @@ set(viewer_SOURCE_FILES      llviewerregion.cpp      llviewershadermgr.cpp      llviewerstats.cpp +    llviewerstatsrecorder.cpp      llviewertexteditor.cpp      llviewertexture.cpp      llviewertextureanim.cpp @@ -1081,6 +1082,7 @@ set(viewer_HEADER_FILES      llviewerregion.h      llviewershadermgr.h      llviewerstats.h +    llviewerstatsrecorder.h      llviewertexteditor.h      llviewertexture.h      llviewertextureanim.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3e0b4f9998..de7073be24 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -64,6 +64,7 @@  #include "lltool.h"  #include "lltoolmgr.h"  #include "lltrans.h" +#include "llurlentry.h"  #include "llviewercontrol.h"  #include "llviewerdisplay.h"  #include "llviewerjoystick.h" @@ -649,6 +650,10 @@ void LLAgent::setRegion(LLViewerRegion *regionp)  	}  	mRegionp = regionp; +	// Pass the region host to LLUrlEntryParcel to resolve parcel name +	// with a server request. +	LLUrlEntryParcel::setRegionHost(getRegionHost()); +  	// Must shift hole-covering water object locations because local  	// coordinate frame changed.  	LLWorld::getInstance()->updateWaterObjects(); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 0e080e713b..c45be8b05e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1300,8 +1300,16 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)  		return false;  	} -	// Check whether the outfit contains the full set of body parts (shape+skin+hair+eyes). -	return getCanMakeFolderIntoOutfit(outfit_cat_id); +	// Check whether the outfit contains any wearables we aren't wearing already (STORM-702). +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); +	gInventory.collectDescendentsIf(outfit_cat_id, +		cats, +		items, +		LLInventoryModel::EXCLUDE_TRASH, +		is_worn); +	return items.size() > 0;  }  void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0093279859..7e8c68632d 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -44,6 +44,7 @@  #include "llagentwearables.h"  #include "llwindow.h"  #include "llviewerstats.h" +#include "llviewerstatsrecorder.h"  #include "llmd5.h"  #include "llmeshrepository.h"  #include "llpumpio.h" @@ -96,6 +97,7 @@  #include "llmemory.h"  #include "llprimitive.h"  #include "llurlaction.h" +#include "llurlentry.h"  #include "llvfile.h"  #include "llvfsthread.h"  #include "llvolumemgr.h" @@ -670,6 +672,10 @@ bool LLAppViewer::init()      mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); +#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::initClass(); +#endif +      // *NOTE:Mani - LLCurl::initClass is not thread safe.       // Called before threads are created.      LLCurl::initClass(); @@ -993,6 +999,8 @@ bool LLAppViewer::init()  	LLAgentLanguage::init(); + +  	return true;  } @@ -1734,6 +1742,10 @@ bool LLAppViewer::cleanup()  	LLMetricPerformanceTesterBasic::cleanClass() ; +#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::cleanupClass(); +#endif +  	llinfos << "Cleaning up Media and Textures" << llendflush;  	//Note: @@ -4610,6 +4622,10 @@ void LLAppViewer::disconnectViewer()  	cleanup_xfer_manager();  	gDisconnected = TRUE; + +	// Pass the connection state to LLUrlEntryParcel not to attempt +	// parcel info requests while disconnected. +	LLUrlEntryParcel::setDisconnected(gDisconnected);  }  void LLAppViewer::forceErrorLLError() diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 8d5b3c648e..cc2a8c8aac 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -2833,21 +2833,6 @@ void LLModelPreview::clearMaterials()  	refresh();  } -bool LLModelPreview::containsRiggedAsset( void ) -{ -	//loop through the models and determine if any of them contained a rigged asset, and if so -	//return true. -	//This is used to cleanup the joint positions after a preview. -	for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) -	{ -		LLModel* pModel = *iter; -		if ( pModel->mAlternateBindMatrix.size() > 0 ) -		{ -			return true; -		} -	} -	return false; -}  void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)  {  	if (mBaseModel.empty()) diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 9ea1b5131a..8fc85cebb9 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -285,7 +285,6 @@ public:  	void rebuildUploadData();  	void clearIncompatible(S32 lod);  	void updateStatusMessages(); -	bool containsRiggedAsset( void );  	void clearGLODGroup();  	void onLODParamCommit(bool enforce_tri_limit); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1b07aa279b..342d15cf0f 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -686,6 +686,12 @@ bool LLFindWearablesEx::operator()(LLInventoryCategory* cat, LLInventoryItem* it  		return false;  	} +	// Skip broken links. +	if (vitem->getIsBrokenLink()) +	{ +		return false; +	} +  	return (bool) get_is_item_worn(item->getUUID()) == mIsWorn;  } diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index eab8f187a7..570e48d526 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -181,7 +181,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  	if (mBackgroundFetchActive && gAgent.getRegion())  	{  		// If we'll be using the capability, we'll be sending batches and the background thing isn't as important. -		std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");    +		std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");     		if (!url.empty())   		{  			bulkFetch(url); @@ -604,7 +604,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  		}  		if (body_lib["folders"].size())  		{ -			std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents"); +			std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");  			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);  			LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0); diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 91ff8c7867..0fd4b2bee5 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -203,8 +203,8 @@ void fetch_items_from_llsd(const LLSD& items_llsd)  {  	if (!items_llsd.size() || gDisconnected) return;  	LLSD body; -	body[0]["cap_name"] = "FetchInventory"; -	body[1]["cap_name"] = "FetchLib"; +	body[0]["cap_name"] = "FetchInventory2"; +	body[1]["cap_name"] = "FetchLib2";  	for (S32 i=0; i<items_llsd.size();i++)  	{  		if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString()) diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 1527f8f4c9..55164f6094 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -547,6 +547,10 @@ void LLLocationInputCtrl::onFocusLost()  {  	LLUICtrl::onFocusLost();  	refreshLocation(); + +	// Setting cursor to 0  to show the left edge of the text. See STORM-370. +	mTextEntry->setCursor(0); +  	if(mTextEntry->hasSelection()){  		mTextEntry->deselect();  	} diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index d2f76eceb0..b772999ee2 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -2299,7 +2299,7 @@ void LLMeshRepository::notifyLoadedMeshes()  	if (gAgent.getRegion())  	{ //update capability url  -		if (gAgent.getRegion()->getName() != region_name) +		if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())  		{  			region_name = gAgent.getRegion()->getName(); diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index 5ea94e0611..d3c9c3e131 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -76,17 +76,19 @@ void LLPanelMe::onOpen(const LLSD& key)  {  	LLPanelProfile::onOpen(key); -	// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) -	bool opened = gSavedSettings.getBOOL("MePanelOpened"); -	// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this -	// is the last time onOpen() is called -	if( !opened && !LLSideTray::getInstance()->getCollapsed() ) -	{ -		buildEditPanel(); -		openPanel(mEditPanel, getAvatarId()); - -		gSavedSettings.setBOOL("MePanelOpened", true); -	} +	// Removed this action as per SOCIAL-431 The first time a new resident opens the profile tab  +	//                                       in the sidebar, they see the old profile editing panel +	// +	//// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) +	//bool opened = gSavedSettings.getBOOL("MePanelOpened"); +	//// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this +	//// is the last time onOpen() is called +	//if( !opened && !LLSideTray::getInstance()->getCollapsed() ) +	//{ +	//	buildEditPanel(); +	//	openPanel(mEditPanel, getAvatarId()); +	//	gSavedSettings.setBOOL("MePanelOpened", true); +	//}  }  bool LLPanelMe::notifyChildren(const LLSD& info) diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index e5ef51bdd1..3862dac340 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -33,6 +33,7 @@  #include "llpanel.h"  #include "llhttpclient.h"  #include "llsdserialize.h" +#include "llurlentry.h"  #include "llviewerregion.h"  #include "llview.h" @@ -168,6 +169,18 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v  	{  		observers.erase(*i);  	} + +	LLUrlEntryParcel::LLParcelData url_data; +	url_data.parcel_id = parcel_data.parcel_id; +	url_data.name = parcel_data.name; +	url_data.sim_name = parcel_data.sim_name; +	url_data.global_x = parcel_data.global_x; +	url_data.global_y = parcel_data.global_y; +	url_data.global_z = parcel_data.global_z; + +	// Pass the parcel data to LLUrlEntryParcel to render +	// human readable parcel name. +	LLUrlEntryParcel::processParcelInfo(url_data);  }  void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index aef665a35c..19d1bdee86 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -498,8 +498,8 @@ private:  LLSideTray::Params::Params()  :	collapsed("collapsed",false), -	tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("sidebar_tab_left.tga")), -	tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("button_enabled_selected_32x128.tga")), +	tab_btn_image_normal("tab_btn_image",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Off.png")), +	tab_btn_image_selected("tab_btn_image_selected",LLUI::getUIImage("taskpanel/TaskPanel_Tab_Selected.png")),  	default_button_width("tab_btn_width",32),  	default_button_height("tab_btn_height",32),  	default_button_margin("tab_btn_margin",0) diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 1b5800b8a5..efda39c806 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2671,6 +2671,49 @@ void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)  	gGL.end();  } +void renderUpdateType(LLDrawable* drawablep) +{ +	LLViewerObject* vobj = drawablep->getVObj(); +	if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType()) +	{ +		return; +	} +	LLGLEnable blend(GL_BLEND); +	switch (vobj->getLastUpdateType()) +	{ +	case OUT_FULL: +		glColor4f(0,1,0,0.5f); +		break; +	case OUT_TERSE_IMPROVED: +		glColor4f(0,1,1,0.5f); +		break; +	case OUT_FULL_COMPRESSED: +		if (vobj->getLastUpdateCached()) +		{ +			glColor4f(1,0,0,0.5f); +		} +		else +		{ +			glColor4f(1,1,0,0.5f); +		} +		break; +	case OUT_FULL_CACHED: +		glColor4f(0,0,1,0.5f); +		break; +	default: +		llwarns << "Unknown update_type " << vobj->getLastUpdateType() << llendl; +		break; +	}; +	S32 num_faces = drawablep->getNumFaces(); +	if (num_faces) +	{ +		for (S32 i = 0; i < num_faces; ++i) +		{ +			pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); +		} +	} +} +  void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)  { @@ -3774,6 +3817,10 @@ public:  			{  				renderRaycast(drawable);  			} +			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_UPDATE_TYPE)) +			{ +				renderUpdateType(drawable); +			}  			LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); @@ -3990,6 +4037,7 @@ void LLSpatialPartition::renderDebug()  									  LLPipeline::RENDER_DEBUG_OCCLUSION |  									  LLPipeline::RENDER_DEBUG_LIGHTS |  									  LLPipeline::RENDER_DEBUG_BATCH_SIZE | +									  LLPipeline::RENDER_DEBUG_UPDATE_TYPE |  									  LLPipeline::RENDER_DEBUG_BBOXES |  									  LLPipeline::RENDER_DEBUG_NORMALS |  									  LLPipeline::RENDER_DEBUG_POINTS | diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 5dcbf079a4..029a48480f 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -139,6 +139,7 @@  #include "lltrans.h"  #include "llui.h"  #include "llurldispatcher.h" +#include "llurlentry.h"  #include "llslurl.h"  #include "llurlhistory.h"  #include "llurlwhitelist.h" @@ -2882,9 +2883,17 @@ bool process_login_success_response()  	if(!text.empty()) gAgentID.set(text);  	gDebugInfo["AgentID"] = text; +	// Agent id needed for parcel info request in LLUrlEntryParcel +	// to resolve parcel name. +	LLUrlEntryParcel::setAgentID(gAgentID); +  	text = response["session_id"].asString();  	if(!text.empty()) gAgentSessionID.set(text);  	gDebugInfo["SessionID"] = text; + +	// Session id needed for parcel info request in LLUrlEntryParcel +	// to resolve parcel name. +	LLUrlEntryParcel::setSessionID(gAgentSessionID);  	text = response["secure_session_id"].asString();  	if(!text.empty()) gAgent.mSecureSessionID.set(text); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index b3642a2c1e..cc851e676b 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -366,11 +366,11 @@ void LLViewerInventoryItem::fetchFromServer(void) const  		{  		  if(gAgent.getID() != mPermissions.getOwner())  		    { -		      url = region->getCapability("FetchLib"); +		      url = region->getCapability("FetchLib2");  		    }  		  else  		    {	 -		      url = region->getCapability("FetchInventory"); +		      url = region->getCapability("FetchInventory2");  		    }  		}  		else @@ -648,7 +648,7 @@ bool LLViewerInventoryCategory::fetch()  		std::string url;  		if (gAgent.getRegion())  		{ -			url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); +			url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");  		}  		else  		{ @@ -660,7 +660,7 @@ bool LLViewerInventoryCategory::fetch()  		}  		else  		{	//Deprecated, but if we don't have a capability, use the old system. -			llinfos << "WebFetchInventoryDescendents capability not found.  Using deprecated UDP message." << llendl; +			llinfos << "FetchInventoryDescendents2 capability not found.  Using deprecated UDP message." << llendl;  			LLMessageSystem* msg = gMessageSystem;  			msg->newMessage("FetchInventoryDescendents");  			msg->nextBlock("AgentData"); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 75531cef8d..a152ab4aa0 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -913,6 +913,10 @@ U32 info_display_from_string(std::string info_display)  	{  		return LLPipeline::RENDER_DEBUG_BATCH_SIZE;  	} +	else if ("update type" == info_display) +	{ +		return LLPipeline::RENDER_DEBUG_UPDATE_TYPE; +	}  	else if ("texture anim" == info_display)  	{  		return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM; @@ -4204,9 +4208,9 @@ class LLObjectEnableReturn : public view_listener_t  					{  						virtual bool apply(LLViewerObject* obj)  						{ -							return (obj->isOverAgentOwnedLand() || -									obj->isOverGroupOwnedLand() || -									obj->permModify()); +							return  +								obj->permModify() || +								obj->isReturnable();  						}  					} func;  					const bool firstonly = true; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1209183229..bf550e9c70 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -241,13 +241,12 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe  	mState(0),  	mMedia(NULL),  	mClickAction(0), -	mObjectCost(0.f), -	mLinksetCost(0.f), -	mPhysicsCost(0.f),  	mLinksetPhysicsCost(0.f),  	mCostStale(true),  	mPhysicsShapeUnknown(true), -	mAttachmentItemID(LLUUID::null) +	mAttachmentItemID(LLUUID::null), +	mLastUpdateType(OUT_UNKNOWN), +	mLastUpdateCached(FALSE)  {  	if (!is_global)  	{ @@ -529,20 +528,23 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list)  // This method returns true if the object is over land owned by the  // agent. -BOOL LLViewerObject::isOverAgentOwnedLand() const +bool LLViewerObject::isReturnable()  { -	return mRegionp -		&& mRegionp->getParcelOverlay() -		&& mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion()); -} +	if (isAttachment()) +	{ +		return false; +	} +	std::vector<LLBBox> boxes; +	boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); +	for (child_list_t::iterator iter = mChildList.begin(); +		 iter != mChildList.end(); iter++) +	{ +		LLViewerObject* child = *iter; +		boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); +	} -// This method returns true if the object is over land owned by the -// agent. -BOOL LLViewerObject::isOverGroupOwnedLand() const -{ -	return mRegionp  -		&& mRegionp->getParcelOverlay() -		&& mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion()); +	return mRegionp +		&& mRegionp->objectIsReturnable(getPositionRegion(), boxes);  }  BOOL LLViewerObject::setParent(LLViewerObject* parent) @@ -5598,6 +5600,26 @@ void LLViewerObject::setAttachmentItemID(const LLUUID &id)  	mAttachmentItemID = id;  } +EObjectUpdateType LLViewerObject::getLastUpdateType() const +{ +	return mLastUpdateType; +} + +void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type) +{ +	mLastUpdateType = last_update_type; +} + +BOOL LLViewerObject::getLastUpdateCached() const +{ +	return mLastUpdateCached; +} + +void LLViewerObject::setLastUpdateCached(BOOL last_update_cached) +{ +	mLastUpdateCached = last_update_cached; +} +  const LLUUID &LLViewerObject::extractAttachmentItemID()  {  	LLUUID item_id = LLUUID::null; @@ -5614,7 +5636,6 @@ const LLUUID &LLViewerObject::extractAttachmentItemID()  	return getAttachmentItemID();  } -  //virtual  LLVOAvatar* LLViewerObject::getAvatar() const  { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 3ba51a6448..8883272cde 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -77,6 +77,7 @@ typedef enum e_object_update_type  	OUT_TERSE_IMPROVED,  	OUT_FULL_COMPRESSED,  	OUT_FULL_CACHED, +	OUT_UNKNOWN,  } EObjectUpdateType; @@ -228,12 +229,9 @@ public:  	virtual BOOL hasLightTexture() const			{ return FALSE; }  	// This method returns true if the object is over land owned by -	// the agent. -	BOOL isOverAgentOwnedLand() const; - -	// True if over land owned by group of which the agent is -	// either officer or member. -	BOOL isOverGroupOwnedLand() const; +	// the agent, one of its groups, or it encroaches and  +	// anti-encroachment is enabled +	bool isReturnable();  	/*  	// This method will scan through this object, and then query the @@ -746,8 +744,15 @@ public:  	const LLUUID &getAttachmentItemID() const;  	void setAttachmentItemID(const LLUUID &id);  	const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object +	EObjectUpdateType getLastUpdateType() const; +	void setLastUpdateType(EObjectUpdateType last_update_type); +	BOOL getLastUpdateCached() const; +	void setLastUpdateCached(BOOL last_update_cached); +  private:  	LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory. +	EObjectUpdateType	mLastUpdateType; +	BOOL	mLastUpdateCached;  };  /////////////////// diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 7682d71e7f..e2dd4d075c 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -57,6 +57,7 @@  #include "llsdutil.h"  #include "llviewerregion.h"  #include "llviewerstats.h" +#include "llviewerstatsrecorder.h"  #include "llvoavatarself.h"  #include "lltoolmgr.h"  #include "lltoolpie.h" @@ -303,8 +304,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  	// have to transform to absolute coordinates.  	num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); +	// I don't think this case is ever hit.  TODO* Test this.  	if (!cached && !compressed && update_type != OUT_FULL)  	{ +		//llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl;  		gTerseObjectUpdates += num_objects;  		S32 size;  		if (mesgsys->getReceiveCompressedSize()) @@ -315,7 +318,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  		{  			size = mesgsys->getReceiveSize();  		} -		// llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl; +		//llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;  	}  	else  	{ @@ -346,9 +349,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  	U8 compressed_dpbuffer[2048];  	LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);  	LLDataPacker *cached_dpp = NULL; -	 + +#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(regionp); +#endif +  	for (i = 0; i < num_objects; i++)  	{ +		// timer is unused?  		LLTimer update_timer;  		BOOL justCreated = FALSE; @@ -360,9 +368,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);  			// Lookup data packer and add this id to cache miss lists if necessary. -			cached_dpp = regionp->getDP(id, crc); +			U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; +			cached_dpp = regionp->getDP(id, crc, cache_miss_type);  			if (cached_dpp)  			{ +				// Cache Hit.  				cached_dpp->reset();  				cached_dpp->unpackUUID(fullid, "ID");  				cached_dpp->unpackU32(local_id, "LocalID"); @@ -370,6 +380,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			}  			else  			{ +				// Cache Miss. +				#if LL_RECORD_VIEWER_STATS +				LLViewerStatsRecorder::instance()->recordCacheMissEvent(id, update_type, cache_miss_type); +				#endif +  				continue; // no data packer, skip this object  			}  		} @@ -381,13 +396,15 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			compressed_dp.reset();  			U32 flags = 0; -			if (update_type != OUT_TERSE_IMPROVED) +			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?  			{  				mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);  			} +			// I don't think we ever use this flag from the server.  DK 2010/12/09  			if (flags & FLAGS_ZLIB_COMPRESSED)  			{ +				//llinfos << "TEST: flags & FLAGS_ZLIB_COMPRESSED" << llendl;  				compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);  				mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i);  				uncompressed_length = 2048; @@ -403,7 +420,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			} -			if (update_type != OUT_TERSE_IMPROVED) +			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?  			{  				compressed_dp.unpackUUID(fullid, "ID");  				compressed_dp.unpackU32(local_id, "LocalID"); @@ -423,7 +440,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  				}  			}  		} -		else if (update_type != OUT_FULL) +		else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only?  		{  			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);  			getUUIDFromLocal(fullid, @@ -436,7 +453,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  				mNumUnknownUpdates++;  			}  		} -		else +		else // OUT_FULL only?  		{  			mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);  			mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); @@ -468,12 +485,12 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  							gMessageSystem->getSenderPort());  			if (objectp->mLocalID != local_id) -			{    // Update local ID in object with the one sent from the region +			{	// Update local ID in object with the one sent from the region  				objectp->mLocalID = local_id;  			}  			if (objectp->getRegion() != regionp) -			{    // Object changed region, so update it +			{	// Object changed region, so update it  				objectp->updateRegion(regionp); // for LLVOAvatar  			}  		} @@ -484,18 +501,24 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			{  				if (update_type == OUT_TERSE_IMPROVED)  				{ -					// llinfos << "terse update for an unknown object:" << fullid << llendl; +					// llinfos << "terse update for an unknown object (compressed):" << fullid << llendl; +					#if LL_RECORD_VIEWER_STATS +					LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); +					#endif  					continue;  				}  			} -			else if (cached) +			else if (cached) // Cache hit only?  			{  			}  			else  			{  				if (update_type != OUT_FULL)  				{ -					// llinfos << "terse update for an unknown object:" << fullid << llendl; +					//llinfos << "terse update for an unknown object:" << fullid << llendl; +					#if LL_RECORD_VIEWER_STATS +					LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); +					#endif  					continue;  				} @@ -505,7 +528,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			if (mDeadObjects.find(fullid) != mDeadObjects.end())  			{  				mNumDeadObjectUpdates++; -				// llinfos << "update for a dead object:" << fullid << llendl; +				//llinfos << "update for a dead object:" << fullid << llendl; +				#if LL_RECORD_VIEWER_STATS +				LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); +				#endif  				continue;  			}  #endif @@ -513,6 +539,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());  			if (!objectp)  			{ +				llinfos << "createObject failure for object: " << fullid << llendl; +				#if LL_RECORD_VIEWER_STATS +				LLViewerStatsRecorder::instance()->recordObjectUpdateFailure(local_id, update_type); +				#endif  				continue;  			}  			justCreated = TRUE; @@ -525,19 +555,26 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;  		} +		bool bCached = false;  		if (compressed)  		{ -			if (update_type != OUT_TERSE_IMPROVED) +			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?  			{  				objectp->mLocalID = local_id;  			}  			processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); -			if (update_type != OUT_TERSE_IMPROVED) +			if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?  			{ +				bCached = true; +				#if LL_RECORD_VIEWER_STATS +				LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); +				LLViewerStatsRecorder::instance()->recordCacheFullUpdate(local_id, update_type, result, objectp); +				#else  				objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); +				#endif  			}  		} -		else if (cached) +		else if (cached) // Cache hit only?  		{  			objectp->mLocalID = local_id;  			processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated); @@ -550,8 +587,17 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,  			}  			processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);  		} +		#if LL_RECORD_VIEWER_STATS +		LLViewerStatsRecorder::instance()->recordObjectUpdateEvent(local_id, update_type, objectp); +		#endif +		objectp->setLastUpdateType(update_type); +		objectp->setLastUpdateCached(bCached);  	} +#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); +#endif +  	LLVOAvatar::cullAvatarsByPixelArea();  } @@ -865,12 +911,12 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  	// update global timer  	F32 last_time = gFrameTimeSeconds; -	U64 time = totalTime();                 // this will become the new gFrameTime when the update is done +	U64 time = totalTime();				 // this will become the new gFrameTime when the update is done  	// Time _can_ go backwards, for example if the user changes the system clock.  	// It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here.  //	llassert(time > gFrameTime);  	F64 time_diff = U64_to_F64(time - gFrameTime)/(F64)SEC_TO_MICROSEC; -	gFrameTime    = time; +	gFrameTime	= time;  	F64 time_since_start = U64_to_F64(gFrameTime - gStartTime)/(F64)SEC_TO_MICROSEC;  	gFrameTimeSeconds = (F32)time_since_start; @@ -975,7 +1021,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  		{  			std::string id_str;  			objectp->mID.toString(id_str); -			std::string tmpstr = std::string("Par:    ") + id_str; +			std::string tmpstr = std::string("Par:	") + id_str;  			addDebugBeacon(objectp->getPositionAgent(),  							tmpstr,  							LLColor4(1.f,0.f,0.f,1.f), @@ -995,12 +1041,12 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)  			std::string tmpstr;  			if (objectp->getParent())  			{ -				tmpstr = std::string("ChP:    ") + id_str; +				tmpstr = std::string("ChP:	") + id_str;  				text_color = LLColor4(0.f, 1.f, 0.f, 1.f);  			}  			else  			{ -				tmpstr = std::string("ChNoP:    ") + id_str; +				tmpstr = std::string("ChNoP:	") + id_str;  				text_color = LLColor4(1.f, 0.f, 0.f, 1.f);  			}  			id = sIndexAndLocalIDToUUID[oi.mParentInfo]; @@ -1885,8 +1931,8 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)  			llinfos << "Agent: " << objectp->getPositionAgent() << llendl;  			addDebugBeacon(objectp->getPositionAgent(),"");  #endif -            gPipeline.markMoved(objectp->mDrawable);                 -            objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE); +			gPipeline.markMoved(objectp->mDrawable);				 +			objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE);  			// Flag the object as no longer orphaned  			childp->mOrphaned = FALSE; diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index eee653b0c1..d07e06f6a7 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -145,6 +145,35 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const  	return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay);  } +bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const +{ +	// boxes are expected to already be axis aligned +	for (U32 i = 0; i < boxes.size(); ++i) +	{ +		LLVector3 min = boxes[i].getMinAgent(); +		LLVector3 max = boxes[i].getMaxAgent(); +		 +		S32 left   = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 right  = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 top    = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +		S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); +	 +		for (S32 row = top; row <= bottom; row++) +		{ +			for (S32 column = left; column <= right; column++) +			{ +				U8 type = ownership(row, column); +				if ((PARCEL_SELF == type) +					|| (PARCEL_GROUP == type)) +				{ +					return true; +				} +			} +		} +	} +	return false; +} +  BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const  {  	S32 row =    S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 61be220312..c80baedda6 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -30,6 +30,7 @@  // The ownership data for land parcels.  // One of these structures per region. +#include "llbbox.h"  #include "lldarray.h"  #include "llframetimer.h"  #include "lluuid.h" @@ -54,6 +55,12 @@ public:  	BOOL			isOwnedSelf(const LLVector3& pos) const;  	BOOL			isOwnedGroup(const LLVector3& pos) const;  	BOOL			isOwnedOther(const LLVector3& pos) const; + +	// "encroaches" means the prim hangs over the parcel, but its center +	// might be in another parcel. for now, we simply test axis aligned  +	// bounding boxes which isn't perfect, but is close +	bool encroachesOwned(const std::vector<LLBBox>& boxes) const; +	  	BOOL			isSoundLocal(const LLVector3& pos) const;  	BOOL			isBuildCameraAllowed(const LLVector3& pos) const; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index a90c90a774..7fd6979702 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -59,6 +59,7 @@  #include "llurldispatcher.h"  #include "llviewerobjectlist.h"  #include "llviewerparceloverlay.h" +#include "llviewerstatsrecorder.h"  #include "llvlmanager.h"  #include "llvlcomposition.h"  #include "llvocache.h" @@ -1032,7 +1033,7 @@ void LLViewerRegion::getInfo(LLSD& info)  	info["Region"]["Handle"]["y"] = (LLSD::Integer)y;  } -void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) +LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)  {  	U32 local_id = objectp->getLocalID();  	U32 crc = objectp->getCRC(); @@ -1046,35 +1047,36 @@ void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinary  		{  			// Record a hit  			entry->recordDupe(); +			return CACHE_UPDATE_DUPE;  		} -		else -		{ -			// Update the cache entry -			mCacheMap.erase(local_id); -			delete entry; -			entry = new LLVOCacheEntry(local_id, crc, dp); -			mCacheMap[local_id] = entry; -		} -	} -	else -	{ -		// we haven't seen this object before -		// Create new entry and add to map -		if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) -		{ -			mCacheMap.erase(mCacheMap.begin()); -		} +		// Update the cache entry +		mCacheMap.erase(local_id); +		delete entry;  		entry = new LLVOCacheEntry(local_id, crc, dp); -  		mCacheMap[local_id] = entry; +		return CACHE_UPDATE_CHANGED; +	} + +	// we haven't seen this object before + +	// Create new entry and add to map +	eCacheUpdateResult result = CACHE_UPDATE_ADDED; +	if (mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) +	{ +		mCacheMap.erase(mCacheMap.begin()); +		result = CACHE_UPDATE_REPLACED; +		  	} -	return ; +	entry = new LLVOCacheEntry(local_id, crc, dp); + +	mCacheMap[local_id] = entry; +	return result;  }  // Get data packer for this object, if we have cached data  // AND the CRC matches. JC -LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc) +LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type)  {  	//llassert(mCacheLoaded);  This assert failes often, changing to early-out -- davep, 2010/10/18 @@ -1089,17 +1091,20 @@ LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc)  			{  				// Record a hit  				entry->recordHit(); +			cache_miss_type = CACHE_MISS_TYPE_NONE;  				return entry->getDP(crc);  			}  			else  			{  				// llinfos << "CRC miss for " << local_id << llendl; +			cache_miss_type = CACHE_MISS_TYPE_CRC;  				mCacheMissCRC.put(local_id);  			}  		}  		else  		{  			// llinfos << "Cache miss for " << local_id << llendl; +		cache_miss_type = CACHE_MISS_TYPE_FULL;  			mCacheMissFull.put(local_id);  		}  	} @@ -1122,9 +1127,6 @@ void LLViewerRegion::requestCacheMisses()  	S32 blocks = 0;  	S32 i; -	const U8 CACHE_MISS_TYPE_FULL = 0; -	const U8 CACHE_MISS_TYPE_CRC  = 1; -  	// Send full cache miss updates.  For these, we KNOW we don't  	// have a viewer object.  	for (i = 0; i < full_count; i++) @@ -1187,6 +1189,11 @@ void LLViewerRegion::requestCacheMisses()  	mCacheDirty = TRUE ;  	// llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; +	#if LL_RECORD_VIEWER_STATS +	LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this); +	LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count); +	LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); +	#endif  }  void LLViewerRegion::dumpCache() @@ -1375,11 +1382,12 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("DispatchRegionInfo");  	capabilityNames.append("EstateChangeInfo");  	capabilityNames.append("EventQueueGet"); -	capabilityNames.append("FetchInventory");  	capabilityNames.append("ObjectMedia");  	capabilityNames.append("ObjectMediaNavigate"); -	capabilityNames.append("FetchLib"); -	capabilityNames.append("FetchLibDescendents"); +	capabilityNames.append("FetchLib2"); +	capabilityNames.append("FetchLibDescendents2"); +	capabilityNames.append("FetchInventory2"); +	capabilityNames.append("FetchInventoryDescendents2");  	capabilityNames.append("GetDisplayNames");  	capabilityNames.append("GetTexture");  	capabilityNames.append("GetMesh"); @@ -1410,7 +1418,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("SimConsole");  	capabilityNames.append("SimulatorFeatures");  	capabilityNames.append("SetDisplayName"); -	capabilityNames.append("SimConsole");  	capabilityNames.append("SimConsoleAsync");  	capabilityNames.append("StartGroupProposal");  	capabilityNames.append("TextureStats"); @@ -1428,7 +1435,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("ViewerMetrics");  	capabilityNames.append("ViewerStartAuction");  	capabilityNames.append("ViewerStats"); -	capabilityNames.append("WebFetchInventoryDescendents");  	// Please add new capabilities alphabetically to reduce  	// merge conflicts. @@ -1509,6 +1515,20 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)  	return NULL;  } +// the viewer can not yet distinquish between normal- and estate-owned objects +// so we collapse these two bits and enable the UI if either are set +const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT +											| REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; + +bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const +{ +	return (mParcelOverlay != NULL) +		&& (mParcelOverlay->isOwnedSelf(pos) +			|| mParcelOverlay->isOwnedGroup(pos) +			|| ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) +				&& mParcelOverlay->encroachesOwned(boxes)) ); +} +  void LLViewerRegion::showReleaseNotes()  {  	std::string url = this->getCapability("ServerReleaseNotes"); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 8b71998f60..7c6559203e 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -33,6 +33,7 @@  #include "lldarray.h"  #include "llwind.h" +#include "llbbox.h"  #include "llcloud.h"  #include "llstat.h"  #include "v3dmath.h" @@ -50,7 +51,7 @@  // Surface id's  #define LAND  1  #define WATER 2 -const U32	MAX_OBJECT_CACHE_ENTRIES = 10000; +const U32	MAX_OBJECT_CACHE_ENTRIES = 50000;  class LLEventPoll; @@ -274,9 +275,24 @@ public:  	void getInfo(LLSD& info); +	typedef enum +	{ +		CACHE_MISS_TYPE_FULL = 0, +		CACHE_MISS_TYPE_CRC, +		CACHE_MISS_TYPE_NONE +	} eCacheMissType; + +	typedef enum +	{ +		CACHE_UPDATE_DUPE = 0, +		CACHE_UPDATE_CHANGED, +		CACHE_UPDATE_ADDED, +		CACHE_UPDATE_REPLACED +	} eCacheUpdateResult; +  	// handle a full update message -	void cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp); -	LLDataPacker *getDP(U32 local_id, U32 crc); +	eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp); +	LLDataPacker *getDP(U32 local_id, U32 crc, U8 &cache_miss_type);  	void requestCacheMisses();  	void addCacheMissFull(const U32 local_id); @@ -293,6 +309,8 @@ public:  	std::string getHttpUrl() const { return mHttpUrl ;}  	LLSpatialPartition* getSpatialPartition(U32 type); + +	bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;  public:  	struct CompareDistance  	{ diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp new file mode 100644 index 0000000000..e9d21b4848 --- /dev/null +++ b/indra/newview/llviewerstatsrecorder.cpp @@ -0,0 +1,258 @@ +/** + * @file llviewerstatsrecorder.cpp + * @brief record info about viewer events to a metrics log file + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llviewerstatsrecorder.h" + +#if LL_RECORD_VIEWER_STATS + +#include "llfile.h" +#include "llviewerregion.h" +#include "llviewerobject.h" + + +// To do - something using region name or global position +#if LL_WINDOWS +	static const std::string STATS_FILE_NAME("C:\\ViewerObjectCacheStats.csv"); +#else +	static const std::string STATS_FILE_NAME("/tmp/viewerstats.csv"); +#endif + +LLViewerStatsRecorder* LLViewerStatsRecorder::sInstance = NULL; +LLViewerStatsRecorder::LLViewerStatsRecorder() : +	mObjectCacheFile(NULL), +	mTimer(), +	mRegionp(NULL), +	mStartTime(0.f), +	mProcessingTime(0.f) +{ +	if (NULL != sInstance) +	{ +		llerrs << "Attempted to create multiple instances of LLViewerStatsRecorder!" << llendl; +	} +	sInstance = this; +	clearStats(); +} + +LLViewerStatsRecorder::~LLViewerStatsRecorder() +{ +	if (mObjectCacheFile != NULL) +	{ +		LLFile::close(mObjectCacheFile); +		mObjectCacheFile = NULL; +	} +} + +// static +void LLViewerStatsRecorder::initClass() +{ +	sInstance = new LLViewerStatsRecorder(); +} + +// static +void LLViewerStatsRecorder::cleanupClass() +{ +	delete sInstance; +	sInstance = NULL; +} + + +void LLViewerStatsRecorder::initStatsRecorder(LLViewerRegion *regionp) +{ +	if (mObjectCacheFile == NULL) +	{ +		mStartTime = LLTimer::getTotalTime(); +		mObjectCacheFile = LLFile::fopen(STATS_FILE_NAME, "wb"); +		if (mObjectCacheFile) +		{	// Write column headers +			std::ostringstream data_msg; +			data_msg << "EventTime, " +				<< "ProcessingTime, " +				<< "CacheHits, " +				<< "CacheFullMisses, " +				<< "CacheCrcMisses, " +				<< "FullUpdates, " +				<< "TerseUpdates, " +				<< "CacheMissRequests, " +				<< "CacheMissResponses, " +				<< "CacheUpdateDupes, " +				<< "CacheUpdateChanges, " +				<< "CacheUpdateAdds, " +				<< "CacheUpdateReplacements, " +				<< "UpdateFailures" +				<< "\n"; + +			fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); +		} +	} +} + +void LLViewerStatsRecorder::beginObjectUpdateEvents(LLViewerRegion *regionp) +{ +	initStatsRecorder(regionp); +	mRegionp = regionp; +	mProcessingTime = LLTimer::getTotalTime(); +	clearStats(); +} + +void LLViewerStatsRecorder::clearStats() +{ +	mObjectCacheHitCount = 0; +	mObjectCacheMissFullCount = 0; +	mObjectCacheMissCrcCount = 0; +	mObjectFullUpdates = 0; +	mObjectTerseUpdates = 0; +	mObjectCacheMissRequests = 0; +	mObjectCacheMissResponses = 0; +	mObjectCacheUpdateDupes = 0; +	mObjectCacheUpdateChanges = 0; +	mObjectCacheUpdateAdds = 0; +	mObjectCacheUpdateReplacements = 0; +	mObjectUpdateFailures = 0; +} + + +void LLViewerStatsRecorder::recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type) +{ +	mObjectUpdateFailures++; +} + +void LLViewerStatsRecorder::recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type) +{ +	if (LLViewerRegion::CACHE_MISS_TYPE_FULL == cache_miss_type) +	{ +		mObjectCacheMissFullCount++; +	} +	else +	{ +		mObjectCacheMissCrcCount++; +	} +} + +void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp) +{ +	switch (update_type) +	{ +	case OUT_FULL: +		mObjectFullUpdates++; +		break; +	case OUT_TERSE_IMPROVED: +		mObjectTerseUpdates++; +		break; +	case OUT_FULL_COMPRESSED: +		mObjectCacheMissResponses++; +		break; +	case OUT_FULL_CACHED: +		mObjectCacheHitCount++; +		break; +	default: +		llwarns << "Unknown update_type" << llendl; +		break; +	}; +} + +void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp) +{ +	switch (update_result) +	{ +		case LLViewerRegion::CACHE_UPDATE_DUPE: +			mObjectCacheUpdateDupes++; +			break; +		case LLViewerRegion::CACHE_UPDATE_CHANGED: +			mObjectCacheUpdateChanges++; +			break; +		case LLViewerRegion::CACHE_UPDATE_ADDED: +			mObjectCacheUpdateAdds++; +			break; +		case LLViewerRegion::CACHE_UPDATE_REPLACED: +			mObjectCacheUpdateReplacements++; +			break; +		default: +			llwarns << "Unknown update_result type" << llendl; +			break; +	}; +} + +void LLViewerStatsRecorder::recordRequestCacheMissesEvent(S32 count) +{ +	mObjectCacheMissRequests += count; +} + +void LLViewerStatsRecorder::endObjectUpdateEvents() +{ +	llinfos << "ILX: "  +		<< mObjectCacheHitCount << " hits, "  +		<< mObjectCacheMissFullCount << " full misses, " +		<< mObjectCacheMissCrcCount << " crc misses, " +		<< mObjectFullUpdates << " full updates, " +		<< mObjectTerseUpdates << " terse updates, " +		<< mObjectCacheMissRequests << " cache miss requests, " +		<< mObjectCacheMissResponses << " cache miss responses, " +		<< mObjectCacheUpdateDupes << " cache update dupes, " +		<< mObjectCacheUpdateChanges << " cache update changes, " +		<< mObjectCacheUpdateAdds << " cache update adds, " +		<< mObjectCacheUpdateReplacements << " cache update replacements, " +		<< mObjectUpdateFailures << " update failures" +		<< llendl; + +	S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures; +	if (mObjectCacheFile != NULL && +		total_objects > 0) +	{ +		std::ostringstream data_msg; +		F32 processing32 = (F32) ((LLTimer::getTotalTime() - mProcessingTime) / 1000.0); + +		data_msg << getTimeSinceStart() +			<< ", " << processing32 +			<< ", " << mObjectCacheHitCount +			<< ", " << mObjectCacheMissFullCount +			<< ", " << mObjectCacheMissCrcCount +			<< ", " << mObjectFullUpdates +			<< ", " << mObjectTerseUpdates +			<< ", " << mObjectCacheMissRequests +			<< ", " << mObjectCacheMissResponses +			<< ", " << mObjectCacheUpdateDupes +			<< ", " << mObjectCacheUpdateChanges +			<< ", " << mObjectCacheUpdateAdds +			<< ", " << mObjectCacheUpdateReplacements +			<< ", " << mObjectUpdateFailures +			<< "\n"; + +		fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); +	} + +	clearStats(); +} + +F32 LLViewerStatsRecorder::getTimeSinceStart() +{ +	return (F32) ((LLTimer::getTotalTime() - mStartTime) / 1000.0); +} + +#endif + + + diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h new file mode 100644 index 0000000000..612ac380f7 --- /dev/null +++ b/indra/newview/llviewerstatsrecorder.h @@ -0,0 +1,97 @@ +/** + * @file llviewerstatsrecorder.h + * @brief record info about viewer events to a metrics log file + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LLVIEWERSTATSRECORDER_H +#define LLVIEWERSTATSRECORDER_H + + +// This is a diagnostic class used to record information from the viewer +// for analysis. + +// This is normally 0.  Set to 1 to enable viewer stats recording +#define LL_RECORD_VIEWER_STATS	0 + + +#if LL_RECORD_VIEWER_STATS +#include "llframetimer.h" +#include "llviewerobject.h" +#include "llviewerregion.h" + +class LLMutex; +class LLViewerRegion; +class LLViewerObject; + +class LLViewerStatsRecorder +{ + public: +	LLViewerStatsRecorder(); +	~LLViewerStatsRecorder(); + +	static void initClass(); +	static void cleanupClass(); +	static LLViewerStatsRecorder* instance() {return sInstance; } + +	void initStatsRecorder(LLViewerRegion *regionp); + +	void beginObjectUpdateEvents(LLViewerRegion *regionp); +	void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type); +	void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type); +	void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp); +	void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp); +	void recordRequestCacheMissesEvent(S32 count); +	void endObjectUpdateEvents(); + +	F32 getTimeSinceStart(); + +private: +	static LLViewerStatsRecorder* sInstance; + +	LLFILE *	mObjectCacheFile;		// File to write data into +	LLFrameTimer	mTimer; +	LLViewerRegion*	mRegionp; +	F64			mStartTime; +	F64			mProcessingTime; + +	S32			mObjectCacheHitCount; +	S32			mObjectCacheMissFullCount; +	S32			mObjectCacheMissCrcCount; +	S32			mObjectFullUpdates; +	S32			mObjectTerseUpdates; +	S32			mObjectCacheMissRequests; +	S32			mObjectCacheMissResponses; +	S32			mObjectCacheUpdateDupes; +	S32			mObjectCacheUpdateChanges; +	S32			mObjectCacheUpdateAdds; +	S32			mObjectCacheUpdateReplacements; +	S32			mObjectUpdateFailures; + + +	void	clearStats(); +}; +#endif	// LL_RECORD_VIEWER_STATS + +#endif // LLVIEWERSTATSRECORDER_H + diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b667dc1af0..feb6db4700 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2128,31 +2128,6 @@ void LLVOAvatar::computeBodySize()  			gAgent.sendAgentSetAppearance();  		}  	} - -/* debug spam -	std::cout << "skull = " << skull << std::endl;				// adebug -	std::cout << "head = " << head << std::endl;				// adebug -	std::cout << "head_scale = " << head_scale << std::endl;	// adebug -	std::cout << "neck = " << neck << std::endl;				// adebug -	std::cout << "neck_scale = " << neck_scale << std::endl;	// adebug -	std::cout << "chest = " << chest << std::endl;				// adebug -	std::cout << "chest_scale = " << chest_scale << std::endl;	// adebug -	std::cout << "torso = " << torso << std::endl;				// adebug -	std::cout << "torso_scale = " << torso_scale << std::endl;	// adebug -	std::cout << std::endl;	// adebug - -	std::cout << "pelvis_scale = " << pelvis_scale << std::endl;// adebug -	std::cout << std::endl;	// adebug - -	std::cout << "hip = " << hip << std::endl;					// adebug -	std::cout << "hip_scale = " << hip_scale << std::endl;		// adebug -	std::cout << "ankle = " << ankle << std::endl;				// adebug -	std::cout << "ankle_scale = " << ankle_scale << std::endl;	// adebug -	std::cout << "foot = " << foot << std::endl;				// adebug -	std::cout << "mBodySize = " << mBodySize << std::endl;		// adebug -	std::cout << "mPelvisToFoot = " << mPelvisToFoot << std::endl;	// adebug -	std::cout << std::endl;		// adebug -*/  }  //------------------------------------------------------------------------ @@ -2446,9 +2421,19 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  		// here we get the approximate head position and set as sound source for the voice symbol  		// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing)  		//-------------------------------------------------------------------------------------------- -		LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); -		mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset ); +		if ( mIsSitting ) +		{ +			LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); +			mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset ); +		} +		else  +		{ +			LLVector3 tagPos = mRoot.getWorldPosition(); +			tagPos[VZ] -= mPelvisToFoot; +			tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); +			mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); +		}  	}//if ( voiceEnabled )  }		 diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 6ea88abab8..10d6b009ae 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1,707 +1,719 @@ -/**  - * @file llvocache.cpp - * @brief Cache of objects on the viewer. - * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llvocache.h" -#include "llerror.h" -#include "llregionhandle.h" -#include "llviewercontrol.h" - -BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes)  -{ -	return apr_file->read(src, n_bytes) == n_bytes ; -} - -BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)  -{ -	return apr_file->write(src, n_bytes) == n_bytes ; -} - - -//--------------------------------------------------------------------------- -// LLVOCacheEntry -//--------------------------------------------------------------------------- - -LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp) -	: -	mLocalID(local_id), -	mCRC(crc), -	mHitCount(0), -	mDupeCount(0), -	mCRCChangeCount(0) -{ -	mBuffer = new U8[dp.getBufferSize()]; -	mDP.assignBuffer(mBuffer, dp.getBufferSize()); -	mDP = dp; -} - -LLVOCacheEntry::LLVOCacheEntry() -	: -	mLocalID(0), -	mCRC(0), -	mHitCount(0), -	mDupeCount(0), -	mCRCChangeCount(0), -	mBuffer(NULL) -{ -	mDP.assignBuffer(mBuffer, 0); -} - -LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) -{ -	S32 size = -1; -	BOOL success; - -	success = check_read(apr_file, &mLocalID, sizeof(U32)); -	if(success) -	{ -		success = check_read(apr_file, &mCRC, sizeof(U32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mHitCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mDupeCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &mCRCChangeCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_read(apr_file, &size, sizeof(S32)); - -		// Corruption in the cache entries -		if ((size > 10000) || (size < 1)) -		{ -			// We've got a bogus size, skip reading it. -			// We won't bother seeking, because the rest of this file -			// is likely bogus, and will be tossed anyway. -			llwarns << "Bogus cache entry, size " << size << ", aborting!" << llendl; -			success = FALSE; -		} -	} -	if(success && size > 0) -	{ -		mBuffer = new U8[size]; -		success = check_read(apr_file, mBuffer, size); - -		if(success) -		{ -			mDP.assignBuffer(mBuffer, size); -		} -		else -		{ -			delete[] mBuffer ; -			mBuffer = NULL ; -		} -	} - -	if(!success) -	{ -		mLocalID = 0; -		mCRC = 0; -		mHitCount = 0; -		mDupeCount = 0; -		mCRCChangeCount = 0; -		mBuffer = NULL; -	} -} - -LLVOCacheEntry::~LLVOCacheEntry() -{ -	delete [] mBuffer; -} - - -// New CRC means the object has changed. -void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp) -{ -	if (  (mCRC != crc) -		||(mDP.getBufferSize() == 0)) -	{ -		mCRC = crc; -		mHitCount = 0; -		mCRCChangeCount++; - -		mDP.freeBuffer(); -		mBuffer = new U8[dp.getBufferSize()]; -		mDP.assignBuffer(mBuffer, dp.getBufferSize()); -		mDP = dp; -	} -} - -LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc) -{ -	if (  (mCRC != crc) -		||(mDP.getBufferSize() == 0)) -	{ -		//llinfos << "Not getting cache entry, invalid!" << llendl; -		return NULL; -	} -	mHitCount++; -	return &mDP; -} - - -void LLVOCacheEntry::recordHit() -{ -	mHitCount++; -} - - -void LLVOCacheEntry::dump() const -{ -	llinfos << "local " << mLocalID -		<< " crc " << mCRC -		<< " hits " << mHitCount -		<< " dupes " << mDupeCount -		<< " change " << mCRCChangeCount -		<< llendl; -} - -BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const -{ -	BOOL success; -	success = check_write(apr_file, (void*)&mLocalID, sizeof(U32)); -	if(success) -	{ -		success = check_write(apr_file, (void*)&mCRC, sizeof(U32)); -	} -	if(success) -	{ -		success = check_write(apr_file, (void*)&mHitCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32)); -	} -	if(success) -	{ -		success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32)); -	} -	if(success) -	{ -		S32 size = mDP.getBufferSize(); -		success = check_write(apr_file, (void*)&size, sizeof(S32)); -	 -		if(success) -		{ -			success = check_write(apr_file, (void*)mBuffer, size); -		} -	} - -	return success ; -} - -//------------------------------------------------------------------- -//LLVOCache -//------------------------------------------------------------------- -// Format string used to construct filename for the object cache -static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; - -const U32 NUM_ENTRIES_TO_PURGE = 50; -const char* object_cache_dirname = "objectcache"; -const char* header_filename = "object.cache"; - -LLVOCache* LLVOCache::sInstance = NULL; - -//static  -LLVOCache* LLVOCache::getInstance()  -{	 -	if(!sInstance) -	{ -		sInstance = new LLVOCache() ; -	} -	return sInstance ; -} - -//static  -BOOL LLVOCache::hasInstance()  -{ -	return sInstance != NULL ; -} - -//static  -void LLVOCache::destroyClass()  -{ -	if(sInstance) -	{ -		delete sInstance ; -		sInstance = NULL ; -	} -} - -LLVOCache::LLVOCache(): -	mInitialized(FALSE), -	mReadOnly(TRUE), -	mCacheSize(1) -{ -	mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); -	mLocalAPRFilePoolp = new LLVolatileAPRPool() ; -} - -LLVOCache::~LLVOCache() -{ -	if(mEnabled) -	{ -		writeCacheHeader(); -		clearCacheInMemory(); -	} -	delete mLocalAPRFilePoolp; -} - -void LLVOCache::setDirNames(ELLPath location) -{ -	std::string delem = gDirUtilp->getDirDelimiter(); - -	mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename); -	mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname); -} - -void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) -{ -	if(!mEnabled) -	{ -		llwarns << "Not initializing cache: Cache is currently disabled." << llendl; -		return ; -	} - -	if(mInitialized) -	{ -		llwarns << "Cache already initialized." << llendl; -		return ; -	} - -	setDirNames(location); -	if (!mReadOnly) -	{ -		LLFile::mkdir(mObjectCacheDirName); -	} - -	mCacheSize = size; - -	mMetaInfo.mVersion = cache_version; -	readCacheHeader(); -	mInitialized = TRUE ; - -	if(mMetaInfo.mVersion != cache_version)  -	{ -		mMetaInfo.mVersion = cache_version ; -		if(mReadOnly) //disable cache -		{ -			clearCacheInMemory(); -		} -		else //delete the current cache if the format does not match. -		{			 -			removeCache(); -		} -	}	 -} -	 -void LLVOCache::removeCache(ELLPath location)  -{ -	if(mReadOnly) -	{ -		llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl; -		return ; -	} - -	std::string delem = gDirUtilp->getDirDelimiter(); -	std::string mask = delem + "*"; -	std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname); -	gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files -	LLFile::rmdir(cache_dir); - -	clearCacheInMemory(); -	mInitialized = FALSE ; -} - -void LLVOCache::removeCache()  -{ -	llassert_always(mInitialized) ; -	if(mReadOnly) -	{ -		llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl; -		return ; -	} - -	std::string delem = gDirUtilp->getDirDelimiter(); -	std::string mask = delem + "*"; -	gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask);  - -	clearCacheInMemory() ; -	writeCacheHeader(); -} - -void LLVOCache::clearCacheInMemory() -{ -	std::for_each(mHandleEntryMap.begin(), mHandleEntryMap.end(), DeletePairedPointer()); -	mHandleEntryMap.clear(); -} - -void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename)  -{ -	U32 region_x, region_y; - -	grid_from_region_handle(handle, ®ion_x, ®ion_y); -	filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname, -			   llformat(OBJECT_CACHE_FILENAME, region_x, region_y)); - -	return ; -} - -void LLVOCache::removeFromCache(U64 handle) -{ -	if(mReadOnly) -	{ -		llwarns << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << llendl; -		return ; -	} - -	std::string filename; -	getObjectCacheFilename(handle, filename); -	LLAPRFile::remove(filename, mLocalAPRFilePoolp);	 -} - -BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes)  -{ -	if(!check_read(apr_file, src, n_bytes)) -	{ -		removeCache() ; -		return FALSE ; -	} - -	return TRUE ; -} - -BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes)  -{ -	if(!check_write(apr_file, src, n_bytes)) -	{ -		removeCache() ; -		return FALSE ; -	} - -	return TRUE ; -} - -void LLVOCache::readCacheHeader() -{ -	if(!mEnabled) -	{ -		llwarns << "Not reading cache header: Cache is currently disabled." << llendl; -		return; -	} - -	//clear stale info. -	clearCacheInMemory();	 - -	if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) -	{ -		LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp);		 -		 -		//read the meta element -		if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) -		{ -			llwarns << "Error reading meta information from cache header." << llendl; -			delete apr_file; -			return; -		} - -		HeaderEntryInfo* entry ; -		for(U32 entry_index = 0; entry_index < mCacheSize; ++entry_index) -		{ -			entry = new HeaderEntryInfo() ; -			if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo))) -			{ -				llwarns << "Error reading cache header entry. (entry_index=" << entry_index << ")" << llendl; -				delete entry ;			 -				break; -			} -			else if(!entry->mTime) //end of the cache. -			{ -				delete entry ; -				break; -			} - -			entry->mIndex = entry_index; -			mHandleEntryMap[entry->mHandle] = entry; -		} - -		delete apr_file ; -	} -	else -	{ -		writeCacheHeader() ; -	} -} - -void LLVOCache::writeCacheHeader() -{ -	if (!mEnabled) -	{ -		llwarns << "Not writing cache header: Cache is currently disabled." << llendl; -		return; -	} - -	if(mReadOnly) -	{ -		llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl; -		return; -	} - -	LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - -	//write the meta element -	if(!checkWrite(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo))) -	{ -		llwarns << "Error writing meta information to cache header." << llendl; -		delete apr_file; -		return; -	} - -	U32 entry_index = 0; -	handle_entry_map_t::iterator iter_end = mHandleEntryMap.end(); -	for(handle_entry_map_t::iterator iter = mHandleEntryMap.begin(); -		iter != iter_end; -		++iter) -	{ -		HeaderEntryInfo* entry = iter->second; -		entry->mIndex = entry_index++; -		if(!checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo))) -		{ -			llwarns << "Failed to write cache header for entry " << entry->mHandle << " (entry_index = " << entry_index << ")" << llendl; -			delete apr_file; -			return; -		} -	} - -	// Why do we need to fill the cache header with default entries?  DK 2010-12-14 -	// It looks like we currently rely on the file being pre-allocated so we can seek during updateEntry(). -	if(entry_index < mCacheSize) -	{ -		HeaderEntryInfo* entry = new HeaderEntryInfo() ; -		for(; entry_index < mCacheSize; ++entry_index) -		{ -			//fill the cache with the default entry. -			if(!checkWrite(apr_file, entry, sizeof(HeaderEntryInfo))) -			{ -				llwarns << "Failed to fill cache header with default entries (entry_index = " << entry_index << ").  Switching to read-only mode." << llendl; -				mReadOnly = TRUE ; //disable the cache. -				break; -			} -		} -		delete entry ; -	} -	delete apr_file ; -} - -BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) -{ -	LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); -	apr_file->seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; - -	BOOL result = checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; -	delete apr_file; -	return result; -} - -void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map)  -{ -	if(!mEnabled) -	{ -		llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl; -		return ; -	} -	llassert_always(mInitialized); - -	handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; -	if(iter == mHandleEntryMap.end()) //no cache -	{ -		llwarns << "No handle map entry for " << handle << llendl; -		return ; -	} - -	std::string filename; -	getObjectCacheFilename(handle, filename); -	LLAPRFile* apr_file = new LLAPRFile(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); - -	LLUUID cache_id ; -	if(!checkRead(apr_file, cache_id.mData, UUID_BYTES)) -	{ -		llwarns << "Error reading cache_id from " << filename << llendl; -		delete apr_file; -		return ; -	} -	if(cache_id != id) -	{ -		llwarns << "Cache ID (" << cache_id << ") doesn't match id for this region (" << id << "), discarding.  handle = " << handle << llendl; -		delete apr_file ; -		return ; -	} - -	S32 num_entries; -	if(!checkRead(apr_file, &num_entries, sizeof(S32))) -	{ -		llwarns << "Error reading num_entries from " << filename << llendl; -		delete apr_file; -		return ; -	} -	 -	for (S32 i = 0; i < num_entries; i++) -	{ -		LLVOCacheEntry* entry = new LLVOCacheEntry(apr_file); -		if (!entry->getLocalID()) -		{ -			llwarns << "Aborting cache file load for " << filename << ", cache file corruption! (entry number = " << i << ")" << llendl; -			delete entry ; -			break; -		} -		cache_entry_map[entry->getLocalID()] = entry; -	} - -	delete apr_file ; -	return ; -} -	 -void LLVOCache::purgeEntries() -{ -	U32 limit = mCacheSize - NUM_ENTRIES_TO_PURGE ; -	// Construct a vector of entries out of the map so we can sort by time. -	std::vector<HeaderEntryInfo*> header_vector; -	handle_entry_map_t::iterator iter_end = mHandleEntryMap.end(); -	for (handle_entry_map_t::iterator iter = mHandleEntryMap.begin(); -		iter != iter_end; -		++iter) -	{ -		header_vector.push_back(iter->second); -	} -	// Sort by time, oldest first. -	std::sort(header_vector.begin(), header_vector.end(), header_entry_less()); -	while(header_vector.size() > limit) -	{ -		HeaderEntryInfo* entry = header_vector.front(); -		 -		removeFromCache(entry->mHandle); -		mHandleEntryMap.erase(entry->mHandle); -		header_vector.erase(header_vector.begin()); -		delete entry; -	} - -	writeCacheHeader() ; -	// *TODO: Verify that we can avoid re-reading the cache header.  DK 2010-12-14 -	readCacheHeader() ; -} - -void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache)  -{ -	if(!mEnabled) -	{ -		llwarns << "Not writing cache for handle " << handle << "): Cache is currently disabled." << llendl; -		return ; -	} -	llassert_always(mInitialized); - -	if(mReadOnly) -	{ -		llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl; -		return ; -	} - -	HeaderEntryInfo* entry; -	handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; -	U32 num_handle_entries = mHandleEntryMap.size(); -	if(iter == mHandleEntryMap.end()) //new entry -	{ -		if(num_handle_entries >= mCacheSize) -		{ -			purgeEntries() ; -		} -		 -		entry = new HeaderEntryInfo(); -		entry->mHandle = handle ; -		entry->mTime = time(NULL) ; -		entry->mIndex = num_handle_entries++; -		mHandleEntryMap[handle] = entry ; -	} -	else -	{ -		// Update access time. -		entry = iter->second ; -		entry->mTime = time(NULL) ; -	} - -	//update cache header -	if(!updateEntry(entry)) -	{ -		llwarns << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << llendl; -		return ; //update failed. -	} - -	if(!dirty_cache) -	{ -		llwarns << "Skipping write to cache for handle " << handle << ": cache not dirty" << llendl; -		return ; //nothing changed, no need to update. -	} - -	//write to cache file -	std::string filename; -	getObjectCacheFilename(handle, filename); -	LLAPRFile* apr_file = new LLAPRFile(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); -	 -	if(!checkWrite(apr_file, (void*)id.mData, UUID_BYTES)) -	{ -		llwarns << "Error writing id to " << filename << llendl; -		delete apr_file; -		return ; -	} - -	S32 num_entries = cache_entry_map.size() ; -	if(!checkWrite(apr_file, &num_entries, sizeof(S32))) -	{ -		llwarns << "Error writing num_entries to " << filename << llendl; -		delete apr_file; -		return ; -	} - -	for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); iter != cache_entry_map.end(); ++iter) -	{ -		if(!iter->second->writeToFile(apr_file)) -		{ -			llwarns << "Aborting cache file write for " << filename << ", error writing to file!" << llendl; -			//failed -			removeCache() ; -			break; -		} -	} - -	delete apr_file ; -	return ; -} - +/** 
 + * @file llvocache.cpp
 + * @brief Cache of objects on the viewer.
 + *
 + * $LicenseInfo:firstyear=2003&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, Linden Research, Inc.
 + * 
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation;
 + * version 2.1 of the License only.
 + * 
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + * 
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 + * 
 + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 + * $/LicenseInfo$
 + */
 +
 +#include "llviewerprecompiledheaders.h"
 +#include "llvocache.h"
 +#include "llerror.h"
 +#include "llregionhandle.h"
 +#include "llviewercontrol.h"
 +
 +BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) 
 +{
 +	return apr_file->read(src, n_bytes) == n_bytes ;
 +}
 +
 +BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) 
 +{
 +	return apr_file->write(src, n_bytes) == n_bytes ;
 +}
 +
 +
 +//---------------------------------------------------------------------------
 +// LLVOCacheEntry
 +//---------------------------------------------------------------------------
 +
 +LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp)
 +	:
 +	mLocalID(local_id),
 +	mCRC(crc),
 +	mHitCount(0),
 +	mDupeCount(0),
 +	mCRCChangeCount(0)
 +{
 +	mBuffer = new U8[dp.getBufferSize()];
 +	mDP.assignBuffer(mBuffer, dp.getBufferSize());
 +	mDP = dp;
 +}
 +
 +LLVOCacheEntry::LLVOCacheEntry()
 +	:
 +	mLocalID(0),
 +	mCRC(0),
 +	mHitCount(0),
 +	mDupeCount(0),
 +	mCRCChangeCount(0),
 +	mBuffer(NULL)
 +{
 +	mDP.assignBuffer(mBuffer, 0);
 +}
 +
 +LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
 +{
 +	S32 size = -1;
 +	BOOL success;
 +
 +	success = check_read(apr_file, &mLocalID, sizeof(U32));
 +	if(success)
 +	{
 +		success = check_read(apr_file, &mCRC, sizeof(U32));
 +	}
 +	if(success)
 +	{
 +		success = check_read(apr_file, &mHitCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_read(apr_file, &mDupeCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_read(apr_file, &mCRCChangeCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_read(apr_file, &size, sizeof(S32));
 +
 +		// Corruption in the cache entries
 +		if ((size > 10000) || (size < 1))
 +		{
 +			// We've got a bogus size, skip reading it.
 +			// We won't bother seeking, because the rest of this file
 +			// is likely bogus, and will be tossed anyway.
 +			llwarns << "Bogus cache entry, size " << size << ", aborting!" << llendl;
 +			success = FALSE;
 +		}
 +	}
 +	if(success && size > 0)
 +	{
 +		mBuffer = new U8[size];
 +		success = check_read(apr_file, mBuffer, size);
 +
 +		if(success)
 +		{
 +			mDP.assignBuffer(mBuffer, size);
 +		}
 +		else
 +		{
 +			delete[] mBuffer ;
 +			mBuffer = NULL ;
 +		}
 +	}
 +
 +	if(!success)
 +	{
 +		mLocalID = 0;
 +		mCRC = 0;
 +		mHitCount = 0;
 +		mDupeCount = 0;
 +		mCRCChangeCount = 0;
 +		mBuffer = NULL;
 +	}
 +}
 +
 +LLVOCacheEntry::~LLVOCacheEntry()
 +{
 +	delete [] mBuffer;
 +}
 +
 +
 +// New CRC means the object has changed.
 +void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp)
 +{
 +	if (  (mCRC != crc)
 +		||(mDP.getBufferSize() == 0))
 +	{
 +		mCRC = crc;
 +		mHitCount = 0;
 +		mCRCChangeCount++;
 +
 +		mDP.freeBuffer();
 +		mBuffer = new U8[dp.getBufferSize()];
 +		mDP.assignBuffer(mBuffer, dp.getBufferSize());
 +		mDP = dp;
 +	}
 +}
 +
 +LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc)
 +{
 +	if (  (mCRC != crc)
 +		||(mDP.getBufferSize() == 0))
 +	{
 +		//llinfos << "Not getting cache entry, invalid!" << llendl;
 +		return NULL;
 +	}
 +	mHitCount++;
 +	return &mDP;
 +}
 +
 +
 +void LLVOCacheEntry::recordHit()
 +{
 +	mHitCount++;
 +}
 +
 +
 +void LLVOCacheEntry::dump() const
 +{
 +	llinfos << "local " << mLocalID
 +		<< " crc " << mCRC
 +		<< " hits " << mHitCount
 +		<< " dupes " << mDupeCount
 +		<< " change " << mCRCChangeCount
 +		<< llendl;
 +}
 +
 +BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
 +{
 +	BOOL success;
 +	success = check_write(apr_file, (void*)&mLocalID, sizeof(U32));
 +	if(success)
 +	{
 +		success = check_write(apr_file, (void*)&mCRC, sizeof(U32));
 +	}
 +	if(success)
 +	{
 +		success = check_write(apr_file, (void*)&mHitCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32));
 +	}
 +	if(success)
 +	{
 +		S32 size = mDP.getBufferSize();
 +		success = check_write(apr_file, (void*)&size, sizeof(S32));
 +	
 +		if(success)
 +		{
 +			success = check_write(apr_file, (void*)mBuffer, size);
 +		}
 +	}
 +
 +	return success ;
 +}
 +
 +//-------------------------------------------------------------------
 +//LLVOCache
 +//-------------------------------------------------------------------
 +// Format string used to construct filename for the object cache
 +static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc";
 +
 +// Throw out 1/20 (5%) of our cache entries if we run out of room.
 +const U32 ENTRIES_PURGE_FACTOR = 20;
 +const char* object_cache_dirname = "objectcache";
 +const char* header_filename = "object.cache";
 +
 +LLVOCache* LLVOCache::sInstance = NULL;
 +
 +//static 
 +LLVOCache* LLVOCache::getInstance() 
 +{	
 +	if(!sInstance)
 +	{
 +		sInstance = new LLVOCache() ;
 +	}
 +	return sInstance ;
 +}
 +
 +//static 
 +BOOL LLVOCache::hasInstance() 
 +{
 +	return sInstance != NULL ;
 +}
 +
 +//static 
 +void LLVOCache::destroyClass() 
 +{
 +	if(sInstance)
 +	{
 +		delete sInstance ;
 +		sInstance = NULL ;
 +	}
 +}
 +
 +LLVOCache::LLVOCache():
 +	mInitialized(FALSE),
 +	mReadOnly(TRUE),
 +	mCacheSize(1)
 +{
 +	mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled");
 +	mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
 +}
 +
 +LLVOCache::~LLVOCache()
 +{
 +	if(mEnabled)
 +	{
 +		writeCacheHeader();
 +		clearCacheInMemory();
 +	}
 +	delete mLocalAPRFilePoolp;
 +}
 +
 +void LLVOCache::setDirNames(ELLPath location)
 +{
 +	std::string delem = gDirUtilp->getDirDelimiter();
 +
 +	mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename);
 +	mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
 +}
 +
 +void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version)
 +{
 +	if(!mEnabled)
 +	{
 +		llwarns << "Not initializing cache: Cache is currently disabled." << llendl;
 +		return ;
 +	}
 +
 +	if(mInitialized)
 +	{
 +		llwarns << "Cache already initialized." << llendl;
 +		return ;
 +	}
 +
 +	setDirNames(location);
 +	if (!mReadOnly)
 +	{
 +		LLFile::mkdir(mObjectCacheDirName);
 +	}
 +
 +	mCacheSize = size;
 +
 +	readCacheHeader();
 +	mInitialized = TRUE ;
 +
 +	if(mMetaInfo.mVersion != cache_version) 
 +	{
 +		mMetaInfo.mVersion = cache_version ;
 +		if(mReadOnly) //disable cache
 +		{
 +			clearCacheInMemory();
 +		}
 +		else //delete the current cache if the format does not match.
 +		{			
 +			removeCache();
 +		}
 +	}	
 +}
 +	
 +void LLVOCache::removeCache(ELLPath location) 
 +{
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl;
 +		return ;
 +	}
 +
 +	std::string delem = gDirUtilp->getDirDelimiter();
 +	std::string mask = delem + "*";
 +	std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
 +	llinfos << "Removing cache at " << cache_dir << llendl;
 +	gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files
 +	LLFile::rmdir(cache_dir);
 +
 +	clearCacheInMemory();
 +	mInitialized = FALSE ;
 +}
 +
 +void LLVOCache::removeCache() 
 +{
 +	llassert_always(mInitialized) ;
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl;
 +		return ;
 +	}
 +
 +	std::string delem = gDirUtilp->getDirDelimiter();
 +	std::string mask = delem + "*";
 +	llinfos << "Removing cache at " << mObjectCacheDirName << llendl;
 +	gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); 
 +
 +	clearCacheInMemory() ;
 +	writeCacheHeader();
 +}
 +
 +void LLVOCache::clearCacheInMemory()
 +{
 +	std::for_each(mHandleEntryMap.begin(), mHandleEntryMap.end(), DeletePairedPointer());
 +	mHandleEntryMap.clear();
 +}
 +
 +void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename) 
 +{
 +	U32 region_x, region_y;
 +
 +	grid_from_region_handle(handle, ®ion_x, ®ion_y);
 +	filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname,
 +			   llformat(OBJECT_CACHE_FILENAME, region_x, region_y));
 +
 +	return ;
 +}
 +
 +void LLVOCache::removeFromCache(U64 handle)
 +{
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << llendl;
 +		return ;
 +	}
 +
 +	std::string filename;
 +	getObjectCacheFilename(handle, filename);
 +	LLAPRFile::remove(filename, mLocalAPRFilePoolp);	
 +}
 +
 +BOOL LLVOCache::checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error)
 +{
 +	if(!check_read(apr_file, src, n_bytes))
 +	{
 +		if (remove_cache_on_error)
 +		{
 +			removeCache() ;
 +		}
 +		return FALSE ;
 +	}
 +
 +	return TRUE ;
 +}
 +
 +BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error) 
 +{
 +	if(!check_write(apr_file, src, n_bytes))
 +	{
 +		if (remove_cache_on_error)
 +		{
 +			removeCache() ;
 +		}
 +		return FALSE ;
 +	}
 +
 +	return TRUE ;
 +}
 +
 +void LLVOCache::readCacheHeader()
 +{
 +	if(!mEnabled)
 +	{
 +		llwarns << "Not reading cache header: Cache is currently disabled." << llendl;
 +		return;
 +	}
 +
 +	//clear stale info.
 +	clearCacheInMemory();	
 +
 +	if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp))
 +	{
 +		LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_READ|APR_FOPEN_BINARY, mLocalAPRFilePoolp);		
 +		
 +		//read the meta element
 +		bool remove_cache_on_error = false;
 +		if(!checkRead(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo), remove_cache_on_error))
 +		{
 +			llwarns << "Error reading meta information from cache header." << llendl;
 +			delete apr_file;
 +			return;
 +		}
 +
 +		HeaderEntryInfo* entry ;
 +		for(U32 entry_index = 0; entry_index < mCacheSize; ++entry_index)
 +		{
 +			entry = new HeaderEntryInfo() ;
 +			if(!checkRead(apr_file, entry, sizeof(HeaderEntryInfo), remove_cache_on_error))
 +			{
 +				llwarns << "Error reading cache header entry. (entry_index=" << entry_index << ")" << llendl;
 +				delete entry ;			
 +				break;
 +			}
 +			else if(!entry->mTime) //end of the cache.
 +			{
 +				delete entry ;
 +				break;
 +			}
 +
 +			entry->mIndex = entry_index;
 +			mHandleEntryMap[entry->mHandle] = entry;
 +		}
 +
 +		delete apr_file ;
 +	}
 +	else
 +	{
 +		writeCacheHeader() ;
 +	}
 +}
 +
 +void LLVOCache::writeCacheHeader()
 +{
 +	if (!mEnabled)
 +	{
 +		llwarns << "Not writing cache header: Cache is currently disabled." << llendl;
 +		return;
 +	}
 +
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not writing cache header: Cache is currently in read-only mode." << llendl;
 +		return;
 +	}
 +
 +	LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BINARY|APR_FOPEN_TRUNCATE, mLocalAPRFilePoolp);
 +
 +	//write the meta element
 +	if(!checkWrite(apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)))
 +	{
 +		llwarns << "Error writing meta information to cache header." << llendl;
 +		delete apr_file;
 +		return;
 +	}
 +
 +	U32 entry_index = 0;
 +	handle_entry_map_t::iterator iter_end = mHandleEntryMap.end();
 +	for(handle_entry_map_t::iterator iter = mHandleEntryMap.begin();
 +		iter != iter_end;
 +		++iter)
 +	{
 +		HeaderEntryInfo* entry = iter->second;
 +		entry->mIndex = entry_index++;
 +		if(!checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)))
 +		{
 +			llwarns << "Failed to write cache header for entry " << entry->mHandle << " (entry_index = " << entry_index << ")" << llendl;
 +			delete apr_file;
 +			return;
 +		}
 +	}
 +
 +	// Why do we need to fill the cache header with default entries?  DK 2010-12-14
 +	// It looks like we currently rely on the file being pre-allocated so we can seek during updateEntry().
 +	if(entry_index < mCacheSize)
 +	{
 +		HeaderEntryInfo* entry = new HeaderEntryInfo() ;
 +		for(; entry_index < mCacheSize; ++entry_index)
 +		{
 +			//fill the cache with the default entry.
 +			if(!checkWrite(apr_file, entry, sizeof(HeaderEntryInfo)))
 +			{
 +				llwarns << "Failed to fill cache header with default entries (entry_index = " << entry_index << ").  Switching to read-only mode." << llendl;
 +				mReadOnly = TRUE ; //disable the cache.
 +				break;
 +			}
 +		}
 +		delete entry ;
 +	}
 +	delete apr_file ;
 +}
 +
 +BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry)
 +{
 +	LLAPRFile* apr_file = new LLAPRFile(mHeaderFileName, APR_FOPEN_WRITE|APR_FOPEN_BINARY, mLocalAPRFilePoolp);
 +	apr_file->seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ;
 +
 +	BOOL result = checkWrite(apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ;
 +	delete apr_file;
 +	return result;
 +}
 +
 +void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) 
 +{
 +	if(!mEnabled)
 +	{
 +		llwarns << "Not reading cache for handle " << handle << "): Cache is currently disabled." << llendl;
 +		return ;
 +	}
 +	llassert_always(mInitialized);
 +
 +	handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
 +	if(iter == mHandleEntryMap.end()) //no cache
 +	{
 +		llwarns << "No handle map entry for " << handle << llendl;
 +		return ;
 +	}
 +
 +	std::string filename;
 +	getObjectCacheFilename(handle, filename);
 +	LLAPRFile* apr_file = new LLAPRFile(filename, APR_FOPEN_READ|APR_FOPEN_BINARY, mLocalAPRFilePoolp);
 +
 +	LLUUID cache_id ;
 +	if(!checkRead(apr_file, cache_id.mData, UUID_BYTES))
 +	{
 +		llwarns << "Error reading cache_id from " << filename << llendl;
 +		delete apr_file;
 +		return ;
 +	}
 +	if(cache_id != id)
 +	{
 +		llwarns << "Cache ID (" << cache_id << ") doesn't match id for this region (" << id << "), discarding.  handle = " << handle << llendl;
 +		delete apr_file ;
 +		return ;
 +	}
 +
 +	S32 num_entries;
 +	if(!checkRead(apr_file, &num_entries, sizeof(S32)))
 +	{
 +		llwarns << "Error reading num_entries from " << filename << llendl;
 +		delete apr_file;
 +		return ;
 +	}
 +	
 +	for (S32 i = 0; i < num_entries; i++)
 +	{
 +		LLVOCacheEntry* entry = new LLVOCacheEntry(apr_file);
 +		if (!entry->getLocalID())
 +		{
 +			llwarns << "Aborting cache file load for " << filename << ", cache file corruption! (entry number = " << i << ")" << llendl;
 +			delete entry ;
 +			break;
 +		}
 +		cache_entry_map[entry->getLocalID()] = entry;
 +	}
 +
 +	delete apr_file ;
 +	return ;
 +}
 +	
 +void LLVOCache::purgeEntries()
 +{
 +	U32 limit = mCacheSize - (mCacheSize / ENTRIES_PURGE_FACTOR);
 +	limit = llclamp(limit, (U32)1, mCacheSize);
 +	// Construct a vector of entries out of the map so we can sort by time.
 +	std::vector<HeaderEntryInfo*> header_vector;
 +	handle_entry_map_t::iterator iter_end = mHandleEntryMap.end();
 +	for (handle_entry_map_t::iterator iter = mHandleEntryMap.begin();
 +		iter != iter_end;
 +		++iter)
 +	{
 +		header_vector.push_back(iter->second);
 +	}
 +	// Sort by time, oldest first.
 +	std::sort(header_vector.begin(), header_vector.end(), header_entry_less());
 +	while(header_vector.size() > limit)
 +	{
 +		HeaderEntryInfo* entry = header_vector.front();
 +		
 +		removeFromCache(entry->mHandle);
 +		mHandleEntryMap.erase(entry->mHandle);
 +		header_vector.erase(header_vector.begin());
 +		delete entry;
 +	}
 +
 +	writeCacheHeader() ;
 +	// *TODO: Verify that we can avoid re-reading the cache header.  DK 2010-12-14
 +	readCacheHeader() ;
 +}
 +
 +void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) 
 +{
 +	if(!mEnabled)
 +	{
 +		llwarns << "Not writing cache for handle " << handle << "): Cache is currently disabled." << llendl;
 +		return ;
 +	}
 +	llassert_always(mInitialized);
 +
 +	if(mReadOnly)
 +	{
 +		llwarns << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << llendl;
 +		return ;
 +	}
 +
 +	U32 num_handle_entries = mHandleEntryMap.size();
 +	
 +	HeaderEntryInfo* entry;
 +	handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ;
 +	if(iter == mHandleEntryMap.end()) //new entry
 +	{
 +		if(num_handle_entries >= mCacheSize)
 +		{
 +			purgeEntries() ;
 +			num_handle_entries = mHandleEntryMap.size();
 +		}
 +		
 +		entry = new HeaderEntryInfo();
 +		entry->mHandle = handle ;
 +		entry->mTime = time(NULL) ;
 +		entry->mIndex = num_handle_entries++;
 +		mHandleEntryMap[handle] = entry ;
 +	}
 +	else
 +	{
 +		// Update access time.
 +		entry = iter->second ;
 +		entry->mTime = time(NULL) ;
 +	}
 +
 +	//update cache header
 +	if(!updateEntry(entry))
 +	{
 +		llwarns << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << llendl;
 +		return ; //update failed.
 +	}
 +
 +	if(!dirty_cache)
 +	{
 +		llwarns << "Skipping write to cache for handle " << handle << ": cache not dirty" << llendl;
 +		return ; //nothing changed, no need to update.
 +	}
 +
 +	//write to cache file
 +	std::string filename;
 +	getObjectCacheFilename(handle, filename);
 +	LLAPRFile* apr_file = new LLAPRFile(filename, APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BINARY|APR_FOPEN_TRUNCATE, mLocalAPRFilePoolp);
 +	
 +	if(!checkWrite(apr_file, (void*)id.mData, UUID_BYTES))
 +	{
 +		llwarns << "Error writing id to " << filename << llendl;
 +		delete apr_file;
 +		return ;
 +	}
 +
 +	S32 num_entries = cache_entry_map.size() ;
 +	if(!checkWrite(apr_file, &num_entries, sizeof(S32)))
 +	{
 +		llwarns << "Error writing num_entries to " << filename << llendl;
 +		delete apr_file;
 +		return ;
 +	}
 +
 +	for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); iter != cache_entry_map.end(); ++iter)
 +	{
 +		if(!iter->second->writeToFile(apr_file))
 +		{
 +			llwarns << "Aborting cache file write for " << filename << ", error writing to file!" << llendl;
 +			//failed
 +			removeCache() ;
 +			break;
 +		}
 +	}
 +
 +	delete apr_file ;
 +	return ;
 +}
 +
 diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 014112718e..e103007979 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -128,8 +128,8 @@ private:  	void removeCache() ;  	void purgeEntries();  	BOOL updateEntry(const HeaderEntryInfo* entry); -	BOOL checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes) ; -	BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) ; +	BOOL checkRead(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error = true) ; +	BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes, bool remove_cache_on_error = true) ;  private:  	BOOL                 mEnabled; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 49269932f5..61264d380a 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -445,8 +445,9 @@ public:  		RENDER_DEBUG_AVATAR_VOLUME      = 0x0100000,  		RENDER_DEBUG_BUILD_QUEUE		= 0x0200000,  		RENDER_DEBUG_AGENT_TARGET       = 0x0400000, -		RENDER_DEBUG_PHYSICS_SHAPES     = 0x0800000, -		RENDER_DEBUG_NORMALS	        = 0x1000000, +		RENDER_DEBUG_UPDATE_TYPE		= 0x0800000, +		RENDER_DEBUG_PHYSICS_SHAPES     = 0x1000000, +		RENDER_DEBUG_NORMALS	        = 0x2000000,  	};  public: diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index feb6c1bb2a..7d767b9222 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -115,9 +115,6 @@       name="AlertCautionTextColor"       reference="LtYellow" />      <color -     name="AgentLinkColor" -     reference="EmphasisColor" /> -    <color       name="AlertTextColor"       value="0.58 0.66 0.84 1" />      <color @@ -349,9 +346,6 @@       name="GridlineShadowColor"       value="0 0 0 0.31" />      <color -     name="GroupLinkColor" -     reference="White" /> -    <color       name="GroupNotifyBoxColor"       value="0.3344 0.5456 0.5159 1" />      <color diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml index 70299c61b4..593e686d4c 100644 --- a/indra/newview/skins/default/xui/da/notifications.xml +++ b/indra/newview/skins/default/xui/da/notifications.xml @@ -1636,7 +1636,7 @@ Knappen vil blive vist når der er nok plads til den.  	<notification name="ShareItemsConfirmation">  		Er du sikker på at du vil dele følgende genstande: -[ITEMS] +<nolink>[ITEMS]</nolink>  Med følgende beboere: diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 06cc02cd84..a2d0b5a170 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -2747,7 +2747,7 @@ Die Schaltfläche wird angezeigt, wenn genügend Platz vorhanden ist.  	<notification name="ShareItemsConfirmation">  		Möchten Sie diese Objekte wirklich für andere freigeben: -[ITEMS] +<nolink>[ITEMS]</nolink>  Für folgende Einwohner: diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml index c751aa4e0c..719509301b 100644 --- a/indra/newview/skins/default/xui/en/menu_object.xml +++ b/indra/newview/skins/default/xui/en/menu_object.xml @@ -100,7 +100,7 @@           name="Object Attach HUD" />     </context_menu>     <context_menu -         label="Remove" +         label="Manage"           name="Remove">     <menu_item_call           enabled="false" @@ -129,15 +129,6 @@           <menu_item_call.on_enable            function="Object.EnableReturn" />       </menu_item_call> -     <menu_item_call -   enabled="false" -   label="Delete" -   name="Delete"> -      <menu_item_call.on_click -       function="Object.Delete" /> -      <menu_item_call.on_enable -       function="Object.EnableDelete" /> -    </menu_item_call>      </context_menu>     <menu_item_separator layout="topleft" />     <menu_item_call @@ -176,4 +167,13 @@        <menu_item_call.on_enable         function="Object.EnableBuy" />     </menu_item_call> +   <menu_item_call +     enabled="false" +     label="Delete" +     name="Delete"> +      <menu_item_call.on_click +       function="Object.Delete" /> +      <menu_item_call.on_enable +       function="Object.EnableDelete" /> +  </menu_item_call>  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b7816b8e25..6211561a5d 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -89,7 +89,7 @@           visibility_control="VoiceMorphingEnabled">              <menu_item_check.on_check               function="Floater.Visible" -             parameter="voice_effect" /> +             Parameter="voice_effect" />              <menu_item_check.on_click               function="Floater.Toggle"               parameter="voice_effect" /> @@ -2208,6 +2208,16 @@             parameter="render batches" />          </menu_item_check>          <menu_item_check +         label="Update Type" +         name="Update Type"> +          <menu_item_check.on_check +           function="Advanced.CheckInfoDisplay" +           parameter="update type" /> +          <menu_item_check.on_click +           function="Advanced.ToggleInfoDisplay" +           parameter="update type" /> +        </menu_item_check> +        <menu_item_check           label="Texture Anim"           name="Texture Anim">            <menu_item_check.on_check @@ -2771,7 +2781,7 @@                   function="Floater.Toggle"                   parameter="region_debug_console" />              </menu_item_check> -  +            <menu_item_check             <menu_item_separator />              <menu_item_check @@ -2790,6 +2800,10 @@              <menu_item_separator />              <menu_item_check + +            <menu_item_separator /> + +            <menu_item_check               label="Debug SelectMgr"               name="Debug SelectMgr">                  <menu_item_check.on_check diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e2fc173f7f..cac25b9312 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6450,7 +6450,7 @@ Select residents to share with.     type="alertmodal">  Are you sure you want to share the following items: -[ITEMS] +<nolink>[ITEMS]</nolink>  With the following Residents: diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index 61d6cbb2d0..eff674c628 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -67,23 +67,23 @@          <scroll_list.columns           label="Parcel"           name="name" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Region"           name="location" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Type"           name="type" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Area"           name="area" -         width="47" /> +         relative_width="0.2" />          <scroll_list.columns           label="Hidden"           name="hidden" -         width="47" /> +         relative_width="0.2" />      </scroll_list>      <text       type="string" diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index 85d0c633af..2e5ebafe46 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -21,4 +21,5 @@   tear_off_pressed_image="tearoff_pressed.tga"   dock_pressed_image="Icon_Dock_Press"   help_pressed_image="Icon_Help_Press" + focus_root="true"    /> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 2dd7a6b0f5..14ce39e8fc 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -2734,7 +2734,7 @@ Se mostrará cuando haya suficiente espacio.  	<notification name="ShareItemsConfirmation">  		¿Estás seguro de que quieres compartir los elementos siguientes? -[ITEMS] +<nolink>[ITEMS]</nolink>  Con los siguientes residentes: diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index ec362d7f22..f0b0e63af0 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -2730,7 +2730,7 @@ Le bouton sera affiché quand il y aura suffisamment de place.  	<notification name="ShareItemsConfirmation">  		Voulez-vous vraiment partager les articles suivants : -[ITEMS] +<nolink>[ITEMS]</nolink>  avec les résidents suivants : diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 32483881b2..5e53080c77 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -2679,7 +2679,7 @@ Il pulsante verrà visualizzato quando lo spazio sarà sufficiente.  	<notification name="ShareItemsConfirmation">  		Sei sicuro di volere condividere gli oggetti -[ITEMS] +<nolink>[ITEMS]</nolink>  Con i seguenti residenti? diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index c0af0e03ff..f133bb361a 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -2731,7 +2731,7 @@ M キーを押して変更します。  	<notification name="ShareItemsConfirmation">  		次のアイテムを共有しますか: -[ITEMS] +<nolink>[ITEMS]</nolink>  次の住人と共有しますか: diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index 8151c7eb93..57a6b8b8ef 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -2691,7 +2691,7 @@ Przycisk zostanie wyświetlony w przypadku dostatecznej ilości przestrzeni.  	<notification name="ShareItemsConfirmation">  		Jesteś pewien/pewna, że chcesz udostępnić następujące obiekty: -[ITEMS] +<nolink>[ITEMS]</nolink>  następującym Rezydentom: diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index dc38b740aa..a1855f2e89 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -477,7 +477,7 @@ Para aumentar a qualidade do vídeo, vá para Preferências > Vídeo.  	</notification>  	<notification name="CannotCopyWarning">  		Você não tem autorização para copiar os itens abaixo: -[ITENS] +[ITEMS]  ao dá-los, você ficará sem eles no seu inventário. Deseja realmente dar estes itens?  		<usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/>  	</notification> @@ -2714,7 +2714,7 @@ O botão será exibido quando houver espaço suficente.  	<notification name="ShareItemsConfirmation">  		Tem certeza de que quer compartilhar os items abaixo? -[ITENS] +<nolink>[ITEMS]</nolink>  Com os seguintes residentes: diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index dae22521bb..7862cce3a1 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -32,6 +32,7 @@  #include "../llagent.h"  #include "message.h" +#include "llurlentry.h"  namespace {  	LLControlGroup s_saved_settings("dummy_settings"); @@ -72,6 +73,7 @@ LLUIColor::LLUIColor(void) { }  LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { }  LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }  LLControlGroup::~LLControlGroup(void) { } +void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { }  namespace tut  { | 
