PageRenderTime 187ms CodeModel.GetById 42ms app.highlight 132ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llviewerobject.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2282 lines | 1728 code | 247 blank | 307 comment | 282 complexity | 0138c1b0fc42dc89e785b38421c470fd MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llviewerobject.cpp
   3 * @brief Base class for viewer objects
   4 *
   5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29#include "llviewerobject.h"
  30
  31#include "llaudioengine.h"
  32#include "imageids.h"
  33#include "indra_constants.h"
  34#include "llmath.h"
  35#include "llflexibleobject.h"
  36#include "llviewercontrol.h"
  37#include "lldatapacker.h"
  38#include "llfasttimer.h"
  39#include "llfloaterreg.h"
  40#include "llfontgl.h"
  41#include "llframetimer.h"
  42#include "llinventory.h"
  43#include "llinventorydefines.h"
  44#include "llmaterialtable.h"
  45#include "llmutelist.h"
  46#include "llnamevalue.h"
  47#include "llprimitive.h"
  48#include "llquantize.h"
  49#include "llregionhandle.h"
  50#include "llsdserialize.h"
  51#include "lltree_common.h"
  52#include "llxfermanager.h"
  53#include "message.h"
  54#include "object_flags.h"
  55#include "timing.h"
  56
  57#include "llaudiosourcevo.h"
  58#include "llagent.h"
  59#include "llagentcamera.h"
  60#include "llbbox.h"
  61#include "llbox.h"
  62#include "llcylinder.h"
  63#include "lldrawable.h"
  64#include "llface.h"
  65#include "llfloaterproperties.h"
  66#include "llfloatertools.h"
  67#include "llfollowcam.h"
  68#include "llhudtext.h"
  69#include "llselectmgr.h"
  70#include "llrendersphere.h"
  71#include "lltooldraganddrop.h"
  72#include "llviewercamera.h"
  73#include "llviewertexturelist.h"
  74#include "llviewerinventory.h"
  75#include "llviewerobjectlist.h"
  76#include "llviewerparceloverlay.h"
  77#include "llviewerpartsource.h"
  78#include "llviewerregion.h"
  79#include "llviewerstats.h"
  80#include "llviewertextureanim.h"
  81#include "llviewerwindow.h" // For getSpinAxis
  82#include "llvoavatar.h"
  83#include "llvoavatarself.h"
  84#include "llvograss.h"
  85#include "llvoground.h"
  86#include "llvolume.h"
  87#include "llvolumemessage.h"
  88#include "llvopartgroup.h"
  89#include "llvosky.h"
  90#include "llvosurfacepatch.h"
  91#include "llvotree.h"
  92#include "llvovolume.h"
  93#include "llvowater.h"
  94#include "llworld.h"
  95#include "llui.h"
  96#include "pipeline.h"
  97#include "llviewernetwork.h"
  98#include "llvowlsky.h"
  99#include "llmanip.h"
 100#include "lltrans.h"
 101#include "llsdutil.h"
 102#include "llmediaentry.h"
 103
 104//#define DEBUG_UPDATE_TYPE
 105
 106BOOL		LLViewerObject::sVelocityInterpolate = TRUE;
 107BOOL		LLViewerObject::sPingInterpolate = TRUE; 
 108
 109U32			LLViewerObject::sNumZombieObjects = 0;
 110S32			LLViewerObject::sNumObjects = 0;
 111BOOL		LLViewerObject::sMapDebug = TRUE;
 112LLColor4	LLViewerObject::sEditSelectColor(	1.0f, 1.f, 0.f, 0.3f);	// Edit OK
 113LLColor4	LLViewerObject::sNoEditSelectColor(	1.0f, 0.f, 0.f, 0.3f);	// Can't edit
 114S32			LLViewerObject::sAxisArrowLength(50);
 115BOOL		LLViewerObject::sPulseEnabled(FALSE);
 116BOOL		LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
 117
 118// sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime
 119F64			LLViewerObject::sMaxUpdateInterpolationTime = 3.0;		// For motion interpolation: after X seconds with no updates, don't predict object motion
 120F64			LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0;	// For motion interpolation: after Y seconds with no updates, taper off motion prediction
 121
 122
 123static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object");
 124
 125// static
 126LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
 127{
 128	LLViewerObject *res = NULL;
 129	LLFastTimer t1(FTM_CREATE_OBJECT);
 130	
 131	switch (pcode)
 132	{
 133	case LL_PCODE_VOLUME:
 134	  res = new LLVOVolume(id, pcode, regionp); break;
 135	case LL_PCODE_LEGACY_AVATAR:
 136	{
 137		if (id == gAgentID)
 138		{
 139			if (!gAgentAvatarp)
 140			{
 141				gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp);
 142				gAgentAvatarp->initInstance();
 143			}
 144			else 
 145			{
 146				gAgentAvatarp->updateRegion(regionp);
 147			}
 148			res = gAgentAvatarp;
 149		}
 150		else
 151		{
 152			LLVOAvatar *avatar = new LLVOAvatar(id, pcode, regionp); 
 153			avatar->initInstance();
 154			res = avatar;
 155		}
 156		break;
 157	}
 158	case LL_PCODE_LEGACY_GRASS:
 159	  res = new LLVOGrass(id, pcode, regionp); break;
 160	case LL_PCODE_LEGACY_PART_SYS:
 161// 	  llwarns << "Creating old part sys!" << llendl;
 162// 	  res = new LLVOPart(id, pcode, regionp); break;
 163	  res = NULL; break;
 164	case LL_PCODE_LEGACY_TREE:
 165	  res = new LLVOTree(id, pcode, regionp); break;
 166	case LL_PCODE_TREE_NEW:
 167// 	  llwarns << "Creating new tree!" << llendl;
 168// 	  res = new LLVOTree(id, pcode, regionp); break;
 169	  res = NULL; break;
 170	case LL_VO_SURFACE_PATCH:
 171	  res = new LLVOSurfacePatch(id, pcode, regionp); break;
 172	case LL_VO_SKY:
 173	  res = new LLVOSky(id, pcode, regionp); break;
 174	case LL_VO_VOID_WATER:
 175		res = new LLVOVoidWater(id, pcode, regionp); break;
 176	case LL_VO_WATER:
 177		res = new LLVOWater(id, pcode, regionp); break;
 178	case LL_VO_GROUND:
 179	  res = new LLVOGround(id, pcode, regionp); break;
 180	case LL_VO_PART_GROUP:
 181	  res = new LLVOPartGroup(id, pcode, regionp); break;
 182	case LL_VO_HUD_PART_GROUP:
 183	  res = new LLVOHUDPartGroup(id, pcode, regionp); break;
 184	case LL_VO_WL_SKY:
 185	  res = new LLVOWLSky(id, pcode, regionp); break;
 186	default:
 187	  llwarns << "Unknown object pcode " << (S32)pcode << llendl;
 188	  res = NULL; break;
 189	}
 190	return res;
 191}
 192
 193LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global)
 194:	LLPrimitive(),
 195	mChildList(),
 196	mID(id),
 197	mLocalID(0),
 198	mTotalCRC(0),
 199	mTEImages(NULL),
 200	mGLName(0),
 201	mbCanSelect(TRUE),
 202	mFlags(0),
 203	mPhysicsShapeType(0),
 204	mPhysicsGravity(0),
 205	mPhysicsFriction(0),
 206	mPhysicsDensity(0),
 207	mPhysicsRestitution(0),
 208	mDrawable(),
 209	mCreateSelected(FALSE),
 210	mRenderMedia(FALSE),
 211	mBestUpdatePrecision(0),
 212	mText(),
 213	mLastInterpUpdateSecs(0.f),
 214	mLastMessageUpdateSecs(0.f),
 215	mLatestRecvPacketID(0),
 216	mData(NULL),
 217	mAudioSourcep(NULL),
 218	mAudioGain(1.f),
 219	mAppAngle(0.f),
 220	mPixelArea(1024.f),
 221	mInventory(NULL),
 222	mInventorySerialNum(0),
 223	mRegionp( regionp ),
 224	mInventoryPending(FALSE),
 225	mInventoryDirty(FALSE),
 226	mDead(FALSE),
 227	mOrphaned(FALSE),
 228	mUserSelected(FALSE),
 229	mOnActiveList(FALSE),
 230	mOnMap(FALSE),
 231	mStatic(FALSE),
 232	mNumFaces(0),
 233	mTimeDilation(1.f),
 234	mRotTime(0.f),
 235	mJointInfo(NULL),
 236	mState(0),
 237	mMedia(NULL),
 238	mClickAction(0),
 239	mObjectCost(0),
 240	mLinksetCost(0),
 241	mPhysicsCost(0),
 242	mLinksetPhysicsCost(0.f),
 243	mCostStale(true),
 244	mPhysicsShapeUnknown(true),
 245	mAttachmentItemID(LLUUID::null),
 246	mLastUpdateType(OUT_UNKNOWN),
 247	mLastUpdateCached(FALSE)
 248{
 249	if (!is_global)
 250	{
 251		llassert(mRegionp);
 252	}
 253
 254	LLPrimitive::init_primitive(pcode);
 255
 256	// CP: added 12/2/2005 - this was being initialised to 0, not the current frame time
 257	mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
 258
 259	mPositionRegion = LLVector3(0.f, 0.f, 0.f);
 260
 261	if (!is_global && mRegionp)
 262	{
 263		mPositionAgent = mRegionp->getOriginAgent();
 264	}
 265
 266	LLViewerObject::sNumObjects++;
 267}
 268
 269LLViewerObject::~LLViewerObject()
 270{
 271	deleteTEImages();
 272
 273	if(mInventory)
 274	{
 275		mInventory->clear();  // will deref and delete entries
 276		delete mInventory;
 277		mInventory = NULL;
 278	}
 279
 280	if (mJointInfo)
 281	{
 282		delete mJointInfo;
 283		mJointInfo = NULL;
 284	}
 285
 286	if (mPartSourcep)
 287	{
 288		mPartSourcep->setDead();
 289		mPartSourcep = NULL;
 290	}
 291
 292	// Delete memory associated with extra parameters.
 293	std::map<U16, ExtraParameter*>::iterator iter;
 294	for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
 295	{
 296		if(iter->second != NULL)
 297		{
 298			delete iter->second->data;
 299			delete iter->second;
 300		}
 301	}
 302	mExtraParameterList.clear();
 303
 304	for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
 305	mNameValuePairs.clear();
 306	
 307	delete[] mData;
 308	mData = NULL;
 309
 310	delete mMedia;
 311	mMedia = NULL;
 312
 313	sNumObjects--;
 314	sNumZombieObjects--;
 315	llassert(mChildList.size() == 0);
 316
 317	clearInventoryListeners();
 318}
 319
 320void LLViewerObject::deleteTEImages()
 321{
 322	delete[] mTEImages;
 323	mTEImages = NULL;
 324}
 325
 326void LLViewerObject::markDead()
 327{
 328	if (!mDead)
 329	{
 330		//llinfos << "Marking self " << mLocalID << " as dead." << llendl;
 331		
 332		// Root object of this hierarchy unlinks itself.
 333		if (getParent())
 334		{
 335			((LLViewerObject *)getParent())->removeChild(this);
 336			// go ahead and delete any jointinfo's that we find
 337			delete mJointInfo;
 338			mJointInfo = NULL;
 339		}
 340
 341		// Mark itself as dead
 342		mDead = TRUE;
 343		gObjectList.cleanupReferences(this);
 344
 345		LLViewerObject *childp;
 346		while (mChildList.size() > 0)
 347		{
 348			childp = mChildList.back();
 349			if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR)
 350			{
 351				//llinfos << "Marking child " << childp->getLocalID() << " as dead." << llendl;
 352				childp->setParent(NULL); // LLViewerObject::markDead 1
 353				childp->markDead();
 354			}
 355			else
 356			{
 357				// make sure avatar is no longer parented, 
 358				// so we can properly set it's position
 359				childp->setDrawableParent(NULL);
 360				((LLVOAvatar*)childp)->getOffObject();
 361				childp->setParent(NULL); // LLViewerObject::markDead 2
 362			}
 363			mChildList.pop_back();
 364		}
 365
 366		if (mDrawable.notNull())
 367		{
 368			// Drawables are reference counted, mark as dead, then nuke the pointer.
 369			mDrawable->markDead();
 370			mDrawable = NULL;
 371		}
 372
 373		if (mText)
 374		{
 375			mText->markDead();
 376			mText = NULL;
 377		}
 378
 379		if (mIcon)
 380		{
 381			mIcon->markDead();
 382			mIcon = NULL;
 383		}
 384
 385		if (mPartSourcep)
 386		{
 387			mPartSourcep->setDead();
 388			mPartSourcep = NULL;
 389		}
 390
 391		if (mAudioSourcep)
 392		{
 393			// Do some cleanup
 394			if (gAudiop)
 395			{
 396				gAudiop->cleanupAudioSource(mAudioSourcep);
 397			}
 398			mAudioSourcep = NULL;
 399		}
 400
 401		if (flagAnimSource())
 402		{
 403			if (isAgentAvatarValid())
 404			{
 405				// stop motions associated with this object
 406				gAgentAvatarp->stopMotionFromSource(mID);
 407			}
 408		}
 409
 410		if (flagCameraSource())
 411		{
 412			LLFollowCamMgr::removeFollowCamParams(mID);
 413		}
 414
 415		sNumZombieObjects++;
 416	}
 417}
 418
 419void LLViewerObject::dump() const
 420{
 421	llinfos << "Type: " << pCodeToString(mPrimitiveCode) << llendl;
 422	llinfos << "Drawable: " << (LLDrawable *)mDrawable << llendl;
 423	llinfos << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << llendl;
 424
 425	llinfos << "Parent: " << getParent() << llendl;
 426	llinfos << "ID: " << mID << llendl;
 427	llinfos << "LocalID: " << mLocalID << llendl;
 428	llinfos << "PositionRegion: " << getPositionRegion() << llendl;
 429	llinfos << "PositionAgent: " << getPositionAgent() << llendl;
 430	llinfos << "PositionGlobal: " << getPositionGlobal() << llendl;
 431	llinfos << "Velocity: " << getVelocity() << llendl;
 432	if (mDrawable.notNull() && mDrawable->getNumFaces())
 433	{
 434		LLFacePool *poolp = mDrawable->getFace(0)->getPool();
 435		if (poolp)
 436		{
 437			llinfos << "Pool: " << poolp << llendl;
 438			llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl;
 439		}
 440	}
 441	//llinfos << "BoxTree Min: " << mDrawable->getBox()->getMin() << llendl;
 442	//llinfos << "BoxTree Max: " << mDrawable->getBox()->getMin() << llendl;
 443	/*
 444	llinfos << "Velocity: " << getVelocity() << llendl;
 445	llinfos << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << llendl;
 446	llinfos << "UsePhysics: " << usePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << llendl;
 447	llinfos << "AppAngle: " << mAppAngle << llendl;
 448	llinfos << "PixelArea: " << mPixelArea << llendl;
 449
 450	char buffer[1000];
 451	char *key;
 452	for (key = mNameValuePairs.getFirstKey(); key; key = mNameValuePairs.getNextKey() )
 453	{
 454		mNameValuePairs[key]->printNameValue(buffer);
 455		llinfos << buffer << llendl;
 456	}
 457	for (child_list_t::iterator iter = mChildList.begin();
 458		 iter != mChildList.end(); iter++)
 459	{
 460		LLViewerObject* child = *iter;
 461		llinfos << "  child " << child->getID() << llendl;
 462	}
 463	*/
 464}
 465
 466void LLViewerObject::printNameValuePairs() const
 467{
 468	for (name_value_map_t::const_iterator iter = mNameValuePairs.begin();
 469		 iter != mNameValuePairs.end(); iter++)
 470	{
 471		LLNameValue* nv = iter->second;
 472		llinfos << nv->printNameValue() << llendl;
 473	}
 474}
 475
 476void LLViewerObject::initVOClasses()
 477{
 478	// Initialized shared class stuff first.
 479	LLVOAvatar::initClass();
 480	LLVOTree::initClass();
 481	llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl;
 482	LLVOGrass::initClass();
 483	LLVOWater::initClass();
 484	LLVOVolume::initClass();
 485}
 486
 487void LLViewerObject::cleanupVOClasses()
 488{
 489	LLVOGrass::cleanupClass();
 490	LLVOWater::cleanupClass();
 491	LLVOTree::cleanupClass();
 492	LLVOAvatar::cleanupClass();
 493	LLVOVolume::cleanupClass();
 494}
 495
 496// Replaces all name value pairs with data from \n delimited list
 497// Does not update server
 498void LLViewerObject::setNameValueList(const std::string& name_value_list)
 499{
 500	// Clear out the old
 501	for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
 502	mNameValuePairs.clear();
 503
 504	// Bring in the new
 505	std::string::size_type length = name_value_list.length();
 506	std::string::size_type start = 0;
 507	while (start < length)
 508	{
 509		std::string::size_type end = name_value_list.find_first_of("\n", start);
 510		if (end == std::string::npos) end = length;
 511		if (end > start)
 512		{
 513			std::string tok = name_value_list.substr(start, end - start);
 514			addNVPair(tok);
 515		}
 516		start = end+1;
 517	}
 518}
 519
 520// This method returns true if the object is over land owned by the
 521// agent.
 522bool LLViewerObject::isReturnable()
 523{
 524	if (isAttachment())
 525	{
 526		return false;
 527	}
 528		
 529	std::vector<LLBBox> boxes;
 530	boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned());
 531	for (child_list_t::iterator iter = mChildList.begin();
 532		 iter != mChildList.end(); iter++)
 533	{
 534		LLViewerObject* child = *iter;
 535		boxes.push_back( LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned());
 536	}
 537
 538	bool result = (mRegionp && mRegionp->objectIsReturnable(getPositionRegion(), boxes)) ? 1 : 0;
 539	
 540	if ( !result )
 541	{		
 542		//Get list of neighboring regions relative to this vo's region
 543		std::vector<LLViewerRegion*> uniqueRegions;
 544		mRegionp->getNeighboringRegions( uniqueRegions );
 545	
 546		//Build aabb's - for root and all children
 547		std::vector<PotentialReturnableObject> returnables;
 548		typedef std::vector<LLViewerRegion*>::iterator RegionIt;
 549		RegionIt regionStart = uniqueRegions.begin();
 550		RegionIt regionEnd   = uniqueRegions.end();
 551		
 552		for (; regionStart != regionEnd; ++regionStart )
 553		{
 554			LLViewerRegion* pTargetRegion = *regionStart;
 555			//Add the root vo as there may be no children and we still want
 556			//to test for any edge overlap
 557			buildReturnablesForChildrenVO( returnables, this, pTargetRegion );
 558			//Add it's children
 559			for (child_list_t::iterator iter = mChildList.begin();  iter != mChildList.end(); iter++)
 560			{
 561				LLViewerObject* pChild = *iter;		
 562				buildReturnablesForChildrenVO( returnables, pChild, pTargetRegion );
 563			}
 564		}	
 565	
 566		//TBD#Eventually create a region -> box list map 
 567		typedef std::vector<PotentialReturnableObject>::iterator ReturnablesIt;
 568		ReturnablesIt retCurrentIt = returnables.begin();
 569		ReturnablesIt retEndIt = returnables.end();
 570	
 571		for ( ; retCurrentIt !=retEndIt; ++retCurrentIt )
 572		{
 573			boxes.clear();
 574			LLViewerRegion* pRegion = (*retCurrentIt).pRegion;
 575			boxes.push_back( (*retCurrentIt).box );	
 576			bool retResult = 	pRegion
 577							 && pRegion->childrenObjectReturnable( boxes )
 578							 && pRegion->canManageEstate();
 579			if ( retResult )
 580			{ 
 581				result = true;
 582				break;
 583			}
 584		}
 585	}
 586	return result;
 587}
 588
 589void LLViewerObject::buildReturnablesForChildrenVO( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion )
 590{
 591	if ( !pChild )
 592	{
 593		llerrs<<"child viewerobject is NULL "<<llendl;
 594	}
 595	
 596	constructAndAddReturnable( returnables, pChild, pTargetRegion );
 597	
 598	//We want to handle any children VO's as well
 599	for (child_list_t::iterator iter = pChild->mChildList.begin();  iter != pChild->mChildList.end(); iter++)
 600	{
 601		LLViewerObject* pChildofChild = *iter;
 602		buildReturnablesForChildrenVO( returnables, pChildofChild, pTargetRegion );
 603	}
 604}
 605
 606void LLViewerObject::constructAndAddReturnable( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion )
 607{
 608	
 609	LLVector3 targetRegionPos;
 610	targetRegionPos.setVec( pChild->getPositionGlobal() );	
 611	
 612	LLBBox childBBox = LLBBox( targetRegionPos, pChild->getRotationRegion(), pChild->getScale() * -0.5f, 
 613							    pChild->getScale() * 0.5f).getAxisAligned();
 614	
 615	LLVector3 edgeA = targetRegionPos + childBBox.getMinLocal();
 616	LLVector3 edgeB = targetRegionPos + childBBox.getMaxLocal();
 617	
 618	LLVector3d edgeAd, edgeBd;
 619	edgeAd.setVec(edgeA);
 620	edgeBd.setVec(edgeB);
 621	
 622	//Only add the box when either of the extents are in a neighboring region
 623	if ( pTargetRegion->pointInRegionGlobal( edgeAd ) || pTargetRegion->pointInRegionGlobal( edgeBd ) )
 624	{
 625		PotentialReturnableObject returnableObj;
 626		returnableObj.box		= childBBox;
 627		returnableObj.pRegion	= pTargetRegion;
 628		returnables.push_back( returnableObj );
 629	}
 630}
 631
 632bool LLViewerObject::crossesParcelBounds()
 633{
 634	std::vector<LLBBox> boxes;
 635	boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned());
 636	for (child_list_t::iterator iter = mChildList.begin();
 637		 iter != mChildList.end(); iter++)
 638	{
 639		LLViewerObject* child = *iter;
 640		boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned());
 641	}
 642
 643	return mRegionp && mRegionp->objectsCrossParcel(boxes);
 644}
 645
 646BOOL LLViewerObject::setParent(LLViewerObject* parent)
 647{
 648	if(mParent != parent)
 649	{
 650		LLViewerObject* old_parent = (LLViewerObject*)mParent ;		
 651		BOOL ret = LLPrimitive::setParent(parent);
 652		if(ret && old_parent && parent)
 653		{
 654			old_parent->removeChild(this) ;
 655		}
 656		return ret ;
 657	}
 658
 659	return FALSE ;
 660}
 661
 662void LLViewerObject::addChild(LLViewerObject *childp)
 663{
 664	for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
 665	{
 666		if (*i == childp)
 667		{	//already has child
 668			return;
 669		}
 670	}
 671	
 672	if (!isAvatar())
 673	{
 674		// propagate selection properties
 675		childp->mbCanSelect = mbCanSelect;
 676	}
 677
 678	if(childp->setParent(this))
 679	{
 680		mChildList.push_back(childp);
 681	}
 682}
 683
 684void LLViewerObject::removeChild(LLViewerObject *childp)
 685{
 686	for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
 687	{
 688		if (*i == childp)
 689		{
 690			if (!childp->isAvatar() && mDrawable.notNull() && mDrawable->isActive() && childp->mDrawable.notNull() && !isAvatar())
 691			{
 692				gPipeline.markRebuild(childp->mDrawable, LLDrawable::REBUILD_VOLUME);
 693			}
 694
 695			mChildList.erase(i);
 696
 697			if(childp->getParent() == this)
 698			{
 699				childp->setParent(NULL);			
 700			}
 701			break;
 702		}
 703	}
 704	
 705	if (childp->isSelected())
 706	{
 707		LLSelectMgr::getInstance()->deselectObjectAndFamily(childp);
 708		BOOL add_to_end = TRUE;
 709		LLSelectMgr::getInstance()->selectObjectAndFamily(childp, add_to_end);
 710	}
 711}
 712
 713void LLViewerObject::addThisAndAllChildren(std::vector<LLViewerObject*>& objects)
 714{
 715	objects.push_back(this);
 716	for (child_list_t::iterator iter = mChildList.begin();
 717		 iter != mChildList.end(); iter++)
 718	{
 719		LLViewerObject* child = *iter;
 720		if (!child->isAvatar())
 721		{
 722			child->addThisAndAllChildren(objects);
 723		}
 724	}
 725}
 726
 727void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects)
 728{
 729	objects.push_back(this);
 730	// don't add any attachments when temporarily selecting avatar
 731	if (isAvatar())
 732	{
 733		return;
 734	}
 735	for (child_list_t::iterator iter = mChildList.begin();
 736		 iter != mChildList.end(); iter++)
 737	{
 738		LLViewerObject* child = *iter;
 739		if ( (!child->isAvatar()) && (!child->isJointChild()))
 740		{
 741			child->addThisAndNonJointChildren(objects);
 742		}
 743	}
 744}
 745
 746BOOL LLViewerObject::isChild(LLViewerObject *childp) const
 747{
 748	for (child_list_t::const_iterator iter = mChildList.begin();
 749		 iter != mChildList.end(); iter++)
 750	{
 751		LLViewerObject* testchild = *iter;
 752		if (testchild == childp)
 753			return TRUE;
 754	}
 755	return FALSE;
 756}
 757
 758
 759// returns TRUE if at least one avatar is sitting on this object
 760BOOL LLViewerObject::isSeat() const
 761{
 762	for (child_list_t::const_iterator iter = mChildList.begin();
 763		 iter != mChildList.end(); iter++)
 764	{
 765		LLViewerObject* child = *iter;
 766		if (child->isAvatar())
 767		{
 768			return TRUE;
 769		}
 770	}
 771	return FALSE;
 772
 773}
 774
 775BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
 776{
 777	if (mDrawable.isNull())
 778	{
 779		return FALSE;
 780	}
 781
 782	BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
 783	if(!ret)
 784	{
 785		return FALSE ;
 786	}
 787	LLDrawable* old_parent = mDrawable->mParent;
 788	mDrawable->mParent = parentp; 
 789		
 790	gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 791	if(	(old_parent != parentp && old_parent)
 792		|| (parentp && parentp->isActive()))
 793	{
 794		// *TODO we should not be relying on setDrawable parent to call markMoved
 795		gPipeline.markMoved(mDrawable, FALSE);
 796	}
 797	else if (!mDrawable->isAvatar())
 798	{
 799		mDrawable->updateXform(TRUE);
 800		/*if (!mDrawable->getSpatialGroup())
 801		{
 802			mDrawable->movePartition();
 803		}*/
 804	}
 805	
 806	return ret;
 807}
 808
 809// Show or hide particles, icon and HUD
 810void LLViewerObject::hideExtraDisplayItems( BOOL hidden )
 811{
 812	if( mPartSourcep.notNull() )
 813	{
 814		LLViewerPartSourceScript *partSourceScript = mPartSourcep.get();
 815		partSourceScript->setSuspended( hidden );
 816	}
 817
 818	if( mText.notNull() )
 819	{
 820		LLHUDText *hudText = mText.get();
 821		hudText->setHidden( hidden );
 822	}
 823
 824	if( mIcon.notNull() )
 825	{
 826		LLHUDIcon *hudIcon = mIcon.get();
 827		hudIcon->setHidden( hidden );
 828	}
 829}
 830
 831U32 LLViewerObject::checkMediaURL(const std::string &media_url)
 832{
 833    U32 retval = (U32)0x0;
 834    if (!mMedia && !media_url.empty())
 835    {
 836        retval |= MEDIA_URL_ADDED;
 837        mMedia = new LLViewerObjectMedia;
 838        mMedia->mMediaURL = media_url;
 839        mMedia->mMediaType = LLViewerObject::MEDIA_SET;
 840        mMedia->mPassedWhitelist = FALSE;
 841    }
 842    else if (mMedia)
 843    {
 844        if (media_url.empty())
 845        {
 846            retval |= MEDIA_URL_REMOVED;
 847            delete mMedia;
 848            mMedia = NULL;
 849        }
 850        else if (mMedia->mMediaURL != media_url) // <-- This is an optimization.  If they are equal don't bother with below's test.
 851        {
 852            /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() &&
 853                   LLTextureEntry::getVersionFromMediaVersionString(media_url) == 
 854                        LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1))
 855			*/
 856            {
 857                // If the media URL is different and WE were not the one who
 858                // changed it, mark dirty.
 859                retval |= MEDIA_URL_UPDATED;
 860            }
 861            mMedia->mMediaURL = media_url;
 862            mMedia->mPassedWhitelist = FALSE;
 863        }
 864    }
 865    return retval;
 866}
 867
 868U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
 869					 void **user_data,
 870					 U32 block_num,
 871					 const EObjectUpdateType update_type,
 872					 LLDataPacker *dp)
 873{
 874	LLMemType mt(LLMemType::MTYPE_OBJECT);
 875	U32 retval = 0x0;
 876	
 877	// Coordinates of objects on simulators are region-local.
 878	U64 region_handle;
 879	mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
 880	
 881	{
 882		LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle);
 883		if(regionp != mRegionp && regionp && mRegionp)//region cross
 884		{
 885			//this is the redundant position and region update, but it is necessary in case the viewer misses the following 
 886			//position and region update messages from sim.
 887			//this redundant update should not cause any problems.
 888			LLVector3 delta_pos =  mRegionp->getOriginAgent() - regionp->getOriginAgent();
 889			setPositionParent(getPosition() + delta_pos); //update to the new region position immediately.
 890			setRegion(regionp) ; //change the region.
 891		}
 892		else
 893		{
 894			mRegionp = regionp ;
 895		}
 896	}	
 897	
 898	if (!mRegionp)
 899	{
 900		U32 x, y;
 901		from_region_handle(region_handle, &x, &y);
 902
 903		llerrs << "Object has invalid region " << x << ":" << y << "!" << llendl;
 904		return retval;
 905	}
 906
 907	U16 time_dilation16;
 908	mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16);
 909	F32 time_dilation = ((F32) time_dilation16) / 65535.f;
 910	mTimeDilation = time_dilation;
 911	mRegionp->setTimeDilation(time_dilation);
 912
 913	// this will be used to determine if we've really changed position
 914	// Use getPosition, not getPositionRegion, since this is what we're comparing directly against.
 915	LLVector3 test_pos_parent = getPosition();
 916
 917	U8  data[60+16]; // This needs to match the largest size below.
 918#ifdef LL_BIG_ENDIAN
 919	U16 valswizzle[4];
 920#endif
 921	U16	*val;
 922	const F32 size = LLWorld::getInstance()->getRegionWidthInMeters();	
 923	const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight();
 924	const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight();
 925	S32 length;
 926	S32	count;
 927	S32 this_update_precision = 32;		// in bits
 928
 929	// Temporaries, because we need to compare w/ previous to set dirty flags...
 930	LLVector3 new_pos_parent;
 931	LLVector3 new_vel;
 932	LLVector3 new_acc;
 933	LLVector3 new_angv;
 934	LLVector3 old_angv = getAngularVelocity();
 935	LLQuaternion new_rot;
 936	LLVector3 new_scale = getScale();
 937
 938	U32	parent_id = 0;
 939	U8	material = 0;
 940	U8 click_action = 0;
 941	U32 crc = 0;
 942
 943	bool old_special_hover_cursor = specialHoverCursor();
 944
 945	LLViewerObject *cur_parentp = (LLViewerObject *)getParent();
 946
 947	if (cur_parentp)
 948	{
 949		parent_id = cur_parentp->mLocalID;
 950	}
 951
 952	if (!dp)
 953	{
 954		switch(update_type)
 955		{
 956		case OUT_FULL:
 957			{
 958#ifdef DEBUG_UPDATE_TYPE
 959				llinfos << "Full:" << getID() << llendl;
 960#endif
 961				//clear cost and linkset cost
 962				mCostStale = true;
 963				if (isSelected())
 964				{
 965					gFloaterTools->dirty();
 966				}
 967
 968				LLUUID audio_uuid;
 969				LLUUID owner_id;	// only valid if audio_uuid or particle system is not null
 970				F32    gain;
 971				U8     sound_flags;
 972
 973				mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_CRC, crc, block_num);
 974				mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_ParentID, parent_id, block_num);
 975				mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_Sound, audio_uuid, block_num );
 976				// HACK: Owner id only valid if non-null sound id or particle system
 977				mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num );
 978				mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num );
 979				mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num );
 980				mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_Material, material, block_num );
 981				mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); 
 982				mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num );
 983				length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
 984				mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num);
 985
 986				mTotalCRC = crc;
 987
 988				// Owner ID used for sound muting or particle system muting
 989				setAttachedSound(audio_uuid, owner_id, gain, sound_flags);
 990
 991				U8 old_material = getMaterial();
 992				if (old_material != material)
 993				{
 994					setMaterial(material);
 995					if (mDrawable.notNull())
 996					{
 997						gPipeline.markMoved(mDrawable, FALSE); // undamped
 998					}
 999				}
1000				setClickAction(click_action);
1001
1002				count = 0;
1003				LLVector4 collision_plane;
1004				
1005				switch(length)
1006				{
1007				case (60 + 16):
1008					// pull out collision normal for avatar
1009					htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
1010					((LLVOAvatar*)this)->setFootPlane(collision_plane);
1011					count += sizeof(LLVector4);
1012					// fall through
1013				case 60:
1014					this_update_precision = 32;
1015					// this is a terse update
1016					// pos
1017					htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1018					count += sizeof(LLVector3);
1019					// vel
1020					htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1021					count += sizeof(LLVector3);
1022					// acc
1023					htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1024					count += sizeof(LLVector3);
1025					// theta
1026					{
1027						LLVector3 vec;
1028						htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1029						new_rot.unpackFromVector3(vec);
1030					}
1031					count += sizeof(LLVector3);
1032					// omega
1033					htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1034					if (new_angv.isExactlyZero())
1035					{
1036						// reset rotation time
1037						resetRot();
1038					}
1039					setAngularVelocity(new_angv);
1040#if LL_DARWIN
1041					if (length == 76)
1042					{
1043						setAngularVelocity(LLVector3::zero);
1044					}
1045#endif
1046					break;
1047				case(32 + 16):
1048					// pull out collision normal for avatar
1049					htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
1050					((LLVOAvatar*)this)->setFootPlane(collision_plane);
1051					count += sizeof(LLVector4);
1052					// fall through
1053				case 32:
1054					this_update_precision = 16;
1055					test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
1056
1057					// This is a terse 16 update, so treat data as an array of U16's.
1058#ifdef LL_BIG_ENDIAN
1059					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
1060					val = valswizzle;
1061#else
1062					val = (U16 *) &data[count];
1063#endif
1064					count += sizeof(U16)*3;
1065					new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
1066					new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
1067					new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
1068
1069#ifdef LL_BIG_ENDIAN
1070					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
1071					val = valswizzle;
1072#else
1073					val = (U16 *) &data[count];
1074#endif
1075					count += sizeof(U16)*3;
1076					setVelocity(LLVector3(U16_to_F32(val[VX], -size, size),
1077													   U16_to_F32(val[VY], -size, size),
1078													   U16_to_F32(val[VZ], -size, size)));
1079
1080#ifdef LL_BIG_ENDIAN
1081					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
1082					val = valswizzle;
1083#else
1084					val = (U16 *) &data[count];
1085#endif
1086					count += sizeof(U16)*3;
1087					setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size),
1088														   U16_to_F32(val[VY], -size, size),
1089														   U16_to_F32(val[VZ], -size, size)));
1090
1091#ifdef LL_BIG_ENDIAN
1092					htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 4); 
1093					val = valswizzle;
1094#else
1095					val = (U16 *) &data[count];
1096#endif
1097					count += sizeof(U16)*4;
1098					new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
1099					new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
1100					new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
1101					new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
1102
1103#ifdef LL_BIG_ENDIAN
1104					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
1105					val = valswizzle;
1106#else
1107					val = (U16 *) &data[count];
1108#endif
1109					new_angv.setVec(U16_to_F32(val[VX], -size, size),
1110										U16_to_F32(val[VY], -size, size),
1111										U16_to_F32(val[VZ], -size, size));
1112					if (new_angv.isExactlyZero())
1113					{
1114						// reset rotation time
1115						resetRot();
1116					}
1117					setAngularVelocity(new_angv);
1118					break;
1119
1120				case 16:
1121					this_update_precision = 8;
1122					test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
1123					// this is a terse 8 update
1124					new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
1125					new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
1126					new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
1127
1128					setVelocity(U8_to_F32(data[3], -size, size),
1129								U8_to_F32(data[4], -size, size),
1130								U8_to_F32(data[5], -size, size) );
1131
1132					setAcceleration(U8_to_F32(data[6], -size, size),
1133									U8_to_F32(data[7], -size, size),
1134									U8_to_F32(data[8], -size, size) );
1135
1136					new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
1137					new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
1138					new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
1139					new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
1140
1141					new_angv.setVec(U8_to_F32(data[13], -size, size),
1142										U8_to_F32(data[14], -size, size),
1143										U8_to_F32(data[15], -size, size) );
1144					if (new_angv.isExactlyZero())
1145					{
1146						// reset rotation time
1147						resetRot();
1148					}
1149					setAngularVelocity(new_angv);
1150					break;
1151				}
1152
1153				////////////////////////////////////////////////////
1154				//
1155				// Here we handle data specific to the full message.
1156				//
1157
1158				U32 flags;
1159				mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
1160				// clear all but local flags
1161				mFlags &= FLAGS_LOCAL;
1162				mFlags |= flags;
1163
1164				U8 state;
1165				mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
1166				mState = state;
1167
1168				// ...new objects that should come in selected need to be added to the selected list
1169				mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
1170
1171				// Set all name value pairs
1172				S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue);
1173				if (nv_size > 0)
1174				{
1175					std::string name_value_list;
1176					mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_NameValue, name_value_list, block_num);
1177					setNameValueList(name_value_list);
1178				}
1179
1180				// Clear out any existing generic data
1181				if (mData)
1182				{
1183					delete [] mData;
1184				}
1185
1186				// Check for appended generic data
1187				S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data);
1188				if (data_size <= 0)
1189				{
1190					mData = NULL;
1191				}
1192				else
1193				{
1194					// ...has generic data
1195					mData = new U8[data_size];
1196					mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num);
1197				}
1198
1199				S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text);
1200				if (text_size > 1)
1201				{
1202					// Setup object text
1203					if (!mText)
1204					{
1205						mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
1206						mText->setFont(LLFontGL::getFontSansSerif());
1207						mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
1208						mText->setMaxLines(-1);
1209						mText->setSourceObject(this);
1210						mText->setOnHUDAttachment(isHUDAttachment());
1211					}
1212
1213					std::string temp_string;
1214					mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num );
1215					
1216					LLColor4U coloru;
1217					mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num);
1218
1219					// alpha was flipped so that it zero encoded better
1220					coloru.mV[3] = 255 - coloru.mV[3];
1221					mText->setColor(LLColor4(coloru));
1222					mText->setString(temp_string);
1223					
1224					if (mDrawable.notNull())
1225					{
1226						setChanged(MOVED | SILHOUETTE);
1227						gPipeline.markMoved(mDrawable, FALSE); // undamped
1228					}
1229				}
1230				else if (mText.notNull())
1231				{
1232					mText->markDead();
1233					mText = NULL;
1234				}
1235
1236				std::string media_url;
1237				mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num);
1238                retval |= checkMediaURL(media_url);
1239                
1240				//
1241				// Unpack particle system data
1242				//
1243				unpackParticleSource(block_num, owner_id);
1244
1245				// Mark all extra parameters not used
1246				std::map<U16, ExtraParameter*>::iterator iter;
1247				for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
1248				{
1249					iter->second->in_use = FALSE;
1250				}
1251
1252				// Unpack extra parameters
1253				S32 size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ExtraParams);
1254				if (size > 0)
1255				{
1256					U8 *buffer = new U8[size];
1257					mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ExtraParams, buffer, size, block_num);
1258					LLDataPackerBinaryBuffer dp(buffer, size);
1259
1260					U8 num_parameters;
1261					dp.unpackU8(num_parameters, "num_params");
1262					U8 param_block[MAX_OBJECT_PARAMS_SIZE];
1263					for (U8 param=0; param<num_parameters; ++param)
1264					{
1265						U16 param_type;
1266						S32 param_size;
1267						dp.unpackU16(param_type, "param_type");
1268						dp.unpackBinaryData(param_block, param_size, "param_data");
1269						//llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl;
1270						LLDataPackerBinaryBuffer dp2(param_block, param_size);
1271						unpackParameterEntry(param_type, &dp2);
1272					}
1273					delete[] buffer;
1274				}
1275
1276				for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
1277				{
1278					if (!iter->second->in_use)
1279					{
1280						// Send an update message in case it was formerly in use
1281						parameterChanged(iter->first, iter->second->data, FALSE, false);
1282					}
1283				}
1284
1285				U8 joint_type = 0;
1286				mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_JointType, joint_type, block_num);
1287				if (joint_type)
1288				{
1289					// create new joint info 
1290					if (!mJointInfo)
1291					{
1292						mJointInfo = new LLVOJointInfo;
1293					}
1294					mJointInfo->mJointType = (EHavokJointType) joint_type;
1295					mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointPivot, mJointInfo->mPivot, block_num);
1296					mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointAxisOrAnchor, mJointInfo->mAxisOrAnchor, block_num);
1297				}
1298				else if (mJointInfo)
1299				{
1300					// this joint info is no longer needed
1301					delete mJointInfo;
1302					mJointInfo = NULL;
1303				}
1304
1305				break;
1306			}
1307
1308		case OUT_TERSE_IMPROVED:
1309			{
1310#ifdef DEBUG_UPDATE_TYPE
1311				llinfos << "TI:" << getID() << llendl;
1312#endif
1313				length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
1314				mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num);
1315				count = 0;
1316				LLVector4 collision_plane;
1317				
1318				switch(length)
1319				{
1320				case(60 + 16):
1321					// pull out collision normal for avatar
1322					htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
1323					((LLVOAvatar*)this)->setFootPlane(collision_plane);
1324					count += sizeof(LLVector4);
1325					// fall through
1326				case 60:
1327					// this is a terse 32 update
1328					// pos
1329					this_update_precision = 32;
1330					htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1331					count += sizeof(LLVector3);
1332					// vel
1333					htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1334					count += sizeof(LLVector3);
1335					// acc
1336					htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1337					count += sizeof(LLVector3);
1338					// theta
1339					{
1340						LLVector3 vec;
1341						htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1342						new_rot.unpackFromVector3(vec);
1343					}
1344					count += sizeof(LLVector3);
1345					// omega
1346					htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
1347					if (new_angv.isExactlyZero())
1348					{
1349						// reset rotation time
1350						resetRot();
1351					}
1352					setAngularVelocity(new_angv);
1353#if LL_DARWIN
1354					if (length == 76)
1355					{
1356						setAngularVelocity(LLVector3::zero);
1357					}
1358#endif
1359					break;
1360				case(32 + 16):
1361					// pull out collision normal for avatar
1362					htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
1363					((LLVOAvatar*)this)->setFootPlane(collision_plane);
1364					count += sizeof(LLVector4);
1365					// fall through
1366				case 32:
1367					// this is a terse 16 update
1368					this_update_precision = 16;
1369					test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
1370
1371#ifdef LL_BIG_ENDIAN
1372					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
1373					val = valswizzle;
1374#else
1375					val = (U16 *) &data[count];
1376#endif
1377					count += sizeof(U16)*3;
1378					new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
1379					new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
1380					new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
1381
1382#ifdef LL_BIG_ENDIAN
1383					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
1384					val = valswizzle;
1385#else
1386					val = (U16 *) &data[count];
1387#endif
1388					count += sizeof(U16)*3;
1389					setVelocity(U16_to_F32(val[VX], -size, size),
1390								U16_to_F32(val[VY], -size, size),
1391								U16_to_F32(val[VZ], -size, size));
1392
1393#ifdef LL_BIG_ENDIAN
1394					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
1395					val = valswizzle;
1396#else
1397					val = (U16 *) &data[count];
1398#endif
1399					count += sizeof(U16)*3;
1400					setAcceleration(U16_to_F32(val[VX], -size, size),
1401									U16_to_F32(val[VY], -size, size),
1402									U16_to_F32(val[VZ], -size, size));
1403
1404#ifdef LL_BIG_ENDIAN
1405					htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8); 
1406					val = valswizzle;
1407#else
1408					val = (U16 *) &data[count];
1409#endif
1410					count += sizeof(U16)*4;
1411					new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
1412					new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
1413					new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
1414					new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
1415
1416#ifdef LL_BIG_ENDIAN
1417					htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
1418					val = valswizzle;
1419#else
1420					val = (U16 *) &data[count];
1421#endif
1422					setAngularVelocity(	U16_to_F32(val[VX], -size, size),
1423										U16_to_F32(val[VY], -size, size),
1424										U16_to_F32(val[VZ], -size, size));
1425					break;
1426
1427				case 16:
1428					// this is a terse 8 update
1429					this_update_precision = 8;
1430					test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
1431					new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
1432					new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
1433					new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
1434
1435					setVelocity(U8_to_F32(data[3], -size, size),
1436								U8_to_F32(data[4], -size, size),
1437								U8_to_F32(data[5], -size, size) );
1438
1439					setAcceleration(U8_to_F32(data[6], -size, size),
1440									U8_to_F32(data[7], -size, size),
1441									U8_to_F32(data[8], -size, size) );
1442
1443					new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
1444					new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
1445					new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
1446					new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
1447
1448					setAngularVelocity(	U8_to_F32(data[13], -size, size),
1449										U8_to_F32(data[14], -size, size),
1450										U8_to_F32(data[15], -size, size) );
1451					break;
1452				}
1453
1454				U8 state;
1455				mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
1456				mState = state;
1457				break;
1458			}
1459
1460		default:
1461			break;
1462
1463		}
1464	}
1465	else
1466	{
1467		// handle the compressed case
1468		LLUUID sound_uuid;
1469		LLUUID	owner_id;
1470		F32    gain = 0;
1471		U8     sound_flags = 0;
1472		F32		cutoff = 0;
1473
1474		U16 val[4];
1475
1476		U8		state;
1477
1478		dp->unpackU8(state, "State");
1479		mState = state;
1480
1481		switch(update_type)
1482		{
1483			case OUT_TERSE_IMPROVED:
1484			{
1485#ifdef DEBUG_UPDATE_TYPE
1486				llinfos << "CompTI:" << getID() << llendl;
1487#endif
1488				U8		value;
1489				dp->unpackU8(value, "agent");
1490				if (value)
1491				{
1492					LLVector4 collision_plane;
1493					dp->unpackVector4(collision_plane, "Plane");
1494					((LLVOAvatar*)this)->setFootPlane(collision_plane);
1495				}
1496				test_pos_parent = getPosition();
1497				dp->unpackVector3(new_pos_parent, "Pos");
1498				dp->unpackU16(val[VX], "VelX");
1499				dp->unpackU16(val[VY], "VelY");
1500				dp->unpackU16(val[VZ], "VelZ");
1501				setVelocity(U16_to_F32(val[VX], -128.f, 128.f),
1502							U16_to_F32(val[VY], -128.f, 128.f),
1503							U16_to_F32(val[VZ], -128.f, 128.f));
1504				dp->unpackU16(val[VX], "AccX");
1505				dp->unpackU16(val[VY], "AccY");
1506				dp->unpackU16(val[VZ], "AccZ");
1507				setAcceleration(U16_to_F32(val[VX], -64.f, 64.f),
1508								U16_to_F32(val[VY], -64.f, 64.f),
1509								U16_to_F32(val[VZ], -64.f, 64.f));
1510
1511				dp->unpackU16(val[VX], "ThetaX");
1512				dp->unpackU16(val[VY], "ThetaY");
1513				dp->unpackU16(val[VZ], "ThetaZ");
1514				dp->unpackU16(val[VS], "ThetaS");
1515				new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
1516				new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
1517				new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
1518				new_rot.mQ[VS] = U16_to_F32(val[VS], -1.f, 1.f);
1519				dp->unpackU16(val[VX], "AccX");
1520				dp->unpackU16(val[VY], "AccY");
1521				dp->unpackU16(val[VZ], "AccZ");
1522				setAngularVelocity(	U16_to_F32(val[VX], -64.f, 64.f),
1523									U16_to_F32(val[VY], -64.f, 64.f),
1524									U16_to_F32(val[VZ], -64.f, 64.f));
1525			}
1526			break;
1527			case OUT_FULL_COMPRESSED:
1528			case OUT_FULL_CACHED:
1529			{
1530#ifdef DEBUG_UPDATE_TYPE
1531				llinfos << "CompFull:" << getID() << llendl;
1532#endif
1533				mCostStale = true;
1534
1535				if (isSelected())
1536				{
1537					gFloaterTools->dirty();
1538				}
1539	
1540				dp->unpackU32(crc, "CRC");
1541				mTotalCRC = crc;
1542				dp->unpackU8(material, "Material");
1543				U8 old_material = getMaterial();
1544				if (old_material != material)
1545				{
1546					setMaterial(material);
1547					if (mDrawable.notNull())
1548					{
1549						gPipeline.markMoved(mDrawable, FALSE); // undamped
1550					}
1551				}
1552				dp->unpackU8(click_action, "ClickAction");
1553				setClickAction(click_action);
1554				dp->unpackVector3(new_scale, "Scale");
1555				dp->unpackVector3(new_pos_parent, "Pos");
1556				LLVector3 vec;
1557				dp->unpackVector3(vec, "Rot");
1558				new_rot.unpackFromVector3(vec);
1559				setAcceleration(LLVector3::zero);
1560
1561				U32 value;
1562				dp->unpackU32(value, "SpecialCode");
1563				dp->setPassFlags(value);
1564				dp->unpackUUID(owner_id, "Owner");
1565
1566				if (value & 0x80)
1567				{
1568					dp->unpackVector3(vec, "Omega");
1569					setAngularVelocity(vec);
1570				}
1571
1572				if (value & 0x20)
1573				{
1574					dp->unpackU32(parent_id, "ParentID");
1575				}
1576				else
1577				{
1578					parent_id = 0;
1579				}
1580
1581				S32 sp_size;
1582				U32 size;
1583				if (value & 0x2)
1584				{
1585					sp_size = 1;
1586					delete [] mData;
1587					mData = new U8[1];
1588					dp->unpackU8(((U8*)mData)[0], "TreeData");
1589				}
1590				else if (value & 0x1)
1591				{
1592					dp->unpackU32(size, "ScratchPadSize");
1593					delete [] mData;
1594					mData = new U8[size];
1595					dp->unpackBinaryData((U8 *)mData, sp_size, "PartData");
1596				}
1597				else
1598				{
1599					mData = NULL;
1600				}
1601
1602				// Setup object text
1603				if (!mText && (value & 0x4))
1604				{
1605					mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
1606					mText->setFont(LLFontGL::getFontSansSerif());
1607					mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
1608					mText->setMaxLines(-1); // Set to match current agni behavior.
1609					mText->setSourceObject(this);
1610					mText->setOnHUDAttachment(isHUDAttachment());
1611				}
1612
1613				if (value & 0x4)
1614				{
1615					std::string temp_string;
1616					dp->unpackString(temp_string, "Text");
1617					LLColor4U coloru;
1618					dp->unpackBinaryDataFixed(coloru.mV, 4, "Color");
1619					coloru.mV[3] = 255 - coloru.mV[3];
1620					mText->setColor(LLColor4(coloru));
1621					mText->setString(temp_string);
1622
1623					setChanged(TEXTURE);
1624				}
1625				else if(mText.notNull())
1626				{
1627					mText->markDead();
1628					mText = NULL;
1629				}
1630
1631                std::string media_url;
1632				if (value & 0x200)
1633				{
1634					dp->unpackString(media_url, "MediaURL");
1635				}
1636                retval |= checkMediaURL(media_url);
1637
1638				//
1639				// Unpack particle system data
1640				//
1641				if (value & 0x8)
1642				{
1643					unpackParticleSource(*dp, owner_id);
1644				}
1645				else
1646				{
1647					deleteParticleSource();
1648				}
1649				
1650				// Mark all extra parameters not used
1651				std::map<U16, ExtraParameter*>::iterator iter;
1652				for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
1653				{
1654					iter->second->in_use = FALSE;
1655				}
1656
1657				// Unpack extra params
1658				U8 num_parameters;
1659				dp->unpackU8(num_parameters, "num_params");
1660				U8 param_block[MAX_OBJECT_PARAMS_SIZE];
1661				for (U8 param=0; param<num_parameters; ++param)
1662				{
1663					U16 param_type;
1664					S32 param_size;
1665					dp->unpackU16(param_type, "param_type");
1666					dp->unpackBinaryData(param_block, param_size, "param_data");
1667					//llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl;
1668					LLDataPackerBinaryBuffer dp2(param_block, param_size);
1669					unpackParameterEntry(param_type, &dp2);
1670				}
1671
1672				for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
1673				{
1674					if (!iter->second->in_use)
1675					{
1676						// Send an update message in case it was formerly in use
1677						parameterChanged(iter->first, iter->second->data, FALSE, false);
1678					}
1679				}
1680
1681				if (value & 0x10)
1682				{
1683					dp->unpackUUID(sound_uuid, "SoundUUID");
1684					dp->unpackF32(gain, "SoundGain");
1685					dp->unpackU8(sound_flags, "SoundFlags");
1686					dp->unpackF32(cutoff, "SoundRadius");
1687				}
1688
1689				if (value & 0x100)
1690				{
1691					std::string name_value_list;
1692					dp->unpackString(name_value_list, "NV");
1693
1694					setNameValueList(name_value_list);
1695				}
1696
1697				mTotalCRC = crc;
1698
1699				setAttachedSound(sound_uuid, owner_id, gain, sound_flags);
1700
1701				// only get these flags on updates from sim, not cached ones
1702				// Preload these five flags for every object.
1703				// Finer shades require the object to be selected, and the selection manager
1704				// stores the extended permission info.
1705				U32 flags;
1706				mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
1707				// keep local flags and overwrite remote-controlled flags
1708				mFlags = (mFlags & FLAGS_LOCAL) | flags;
1709
1710					// ...new objects that should come in selected need to be added to the selected list
1711				mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
1712			}
1713			break;
1714
1715		default:
1716			break;
1717		}
1718	}
1719
1720	//
1721	// Fix object parenting.
1722	//
1723	BOOL b_changed_status = FALSE;
1724
1725	if (OUT_TERSE_IMPROVED != update_type)
1726	{
1727		// We only need to update parenting on full updates, terse updates
1728		// don't send parenting information.
1729		if (!cur_parentp)
1730		{
1731			if (parent_id == 0)
1732			{
1733				// No parent now, no parent in message -> do nothing
1734			}
1735			else
1736			{
1737				// No parent now, new parent in message -> attach to that parent if possible
1738				LLUUID parent_uuid;
1739				LLViewerObjectList::getUUIDFromLocal(parent_uuid,
1740														parent_id,
1741														mesgsys->getSenderIP(),
1742														mesgsys->getSenderPort());
1743
1744				LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid);
1745
1746				//
1747				// Check to see if we have the corresponding viewer object for the parent.
1748				//
1749				if (sent_parentp && sent_parentp->getParent() == this)
1750				{
1751					// Try to recover if we attempt to attach a parent to its child
1752					llwarns << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parent

Large files files are truncated, but you can click here to view the full file