llviewerobject.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:132k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llviewerobject.cpp
  3.  * @brief Base class for viewer objects
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llviewerobject.h"
  34. #include "llaudioengine.h"
  35. #include "imageids.h"
  36. #include "indra_constants.h"
  37. #include "llmath.h"
  38. #include "llflexibleobject.h"
  39. #include "llviewercontrol.h"
  40. #include "lldatapacker.h"
  41. #include "llfasttimer.h"
  42. #include "llfloaterreg.h"
  43. #include "llfontgl.h"
  44. #include "llframetimer.h"
  45. #include "llinventory.h"
  46. #include "llmaterialtable.h"
  47. #include "llmutelist.h"
  48. #include "llnamevalue.h"
  49. #include "llprimitive.h"
  50. #include "llquantize.h"
  51. #include "llregionhandle.h"
  52. #include "lltree_common.h"
  53. #include "llxfermanager.h"
  54. #include "message.h"
  55. #include "object_flags.h"
  56. #include "timing.h"
  57. #include "llaudiosourcevo.h"
  58. #include "llagent.h"
  59. #include "llbbox.h"
  60. #include "llbox.h"
  61. #include "llcylinder.h"
  62. #include "lldrawable.h"
  63. #include "llface.h"
  64. #include "llfloaterproperties.h"
  65. #include "llfollowcam.h"
  66. #include "llselectmgr.h"
  67. #include "llrendersphere.h"
  68. #include "lltooldraganddrop.h"
  69. #include "llviewercamera.h"
  70. #include "llviewertexturelist.h"
  71. #include "llviewerinventory.h"
  72. #include "llviewerobjectlist.h"
  73. #include "llviewerparceloverlay.h"
  74. #include "llviewerpartsource.h"
  75. #include "llviewerregion.h"
  76. #include "llviewertextureanim.h"
  77. #include "llviewerwindow.h" // For getSpinAxis
  78. #include "llvoavatar.h"
  79. #include "llvoavatarself.h"
  80. #include "llvoclouds.h"
  81. #include "llvograss.h"
  82. #include "llvoground.h"
  83. #include "llvolume.h"
  84. #include "llvolumemessage.h"
  85. #include "llvopartgroup.h"
  86. #include "llvosky.h"
  87. #include "llvosurfacepatch.h"
  88. #include "llvotextbubble.h"
  89. #include "llvotree.h"
  90. #include "llvovolume.h"
  91. #include "llvowater.h"
  92. #include "llworld.h"
  93. #include "llui.h"
  94. #include "pipeline.h"
  95. #include "llviewernetwork.h"
  96. #include "llvowlsky.h"
  97. #include "llmanip.h"
  98. #include "lltrans.h"
  99. #include "llsdutil.h"
  100. #include "llmediaentry.h"
  101. //#define DEBUG_UPDATE_TYPE
  102. BOOL gVelocityInterpolate = TRUE;
  103. BOOL gPingInterpolate = TRUE; 
  104. U32 LLViewerObject::sNumZombieObjects = 0;
  105. S32 LLViewerObject::sNumObjects = 0;
  106. BOOL LLViewerObject::sMapDebug = TRUE;
  107. LLColor4 LLViewerObject::sEditSelectColor( 1.0f, 1.f, 0.f, 0.3f); // Edit OK
  108. LLColor4 LLViewerObject::sNoEditSelectColor( 1.0f, 0.f, 0.f, 0.3f); // Can't edit
  109. S32 LLViewerObject::sAxisArrowLength(50);
  110. BOOL LLViewerObject::sPulseEnabled(FALSE);
  111. BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
  112. static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object");
  113. // static
  114. LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
  115. {
  116. LLViewerObject *res = NULL;
  117. LLFastTimer t1(FTM_CREATE_OBJECT);
  118. switch (pcode)
  119. {
  120. case LL_PCODE_VOLUME:
  121.   res = new LLVOVolume(id, pcode, regionp); break;
  122. case LL_PCODE_LEGACY_AVATAR:
  123. {
  124. if (id == gAgentID)
  125. {
  126. res = new LLVOAvatarSelf(id, pcode, regionp);
  127. }
  128. else
  129. {
  130. res = new LLVOAvatar(id, pcode, regionp); 
  131. }
  132. static_cast<LLVOAvatar*>(res)->initInstance();
  133. break;
  134. }
  135. case LL_PCODE_LEGACY_GRASS:
  136.   res = new LLVOGrass(id, pcode, regionp); break;
  137. case LL_PCODE_LEGACY_PART_SYS:
  138. //    llwarns << "Creating old part sys!" << llendl;
  139. //    res = new LLVOPart(id, pcode, regionp); break;
  140.   res = NULL; break;
  141. case LL_PCODE_LEGACY_TREE:
  142.   res = new LLVOTree(id, pcode, regionp); break;
  143. case LL_PCODE_TREE_NEW:
  144. //    llwarns << "Creating new tree!" << llendl;
  145. //    res = new LLVOTree(id, pcode, regionp); break;
  146.   res = NULL; break;
  147. case LL_PCODE_LEGACY_TEXT_BUBBLE:
  148.   res = new LLVOTextBubble(id, pcode, regionp); break;
  149. case LL_VO_CLOUDS:
  150.   res = new LLVOClouds(id, pcode, regionp); break;
  151. case LL_VO_SURFACE_PATCH:
  152.   res = new LLVOSurfacePatch(id, pcode, regionp); break;
  153. case LL_VO_SKY:
  154.   res = new LLVOSky(id, pcode, regionp); break;
  155. case LL_VO_WATER:
  156.   res = new LLVOWater(id, pcode, regionp); break;
  157. case LL_VO_GROUND:
  158.   res = new LLVOGround(id, pcode, regionp); break;
  159. case LL_VO_PART_GROUP:
  160.   res = new LLVOPartGroup(id, pcode, regionp); break;
  161. case LL_VO_HUD_PART_GROUP:
  162.   res = new LLVOHUDPartGroup(id, pcode, regionp); break;
  163. case LL_VO_WL_SKY:
  164.   res = new LLVOWLSky(id, pcode, regionp); break;
  165. default:
  166.   llwarns << "Unknown object pcode " << (S32)pcode << llendl;
  167.   res = NULL; break;
  168. }
  169. return res;
  170. }
  171. LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global)
  172. : LLPrimitive(),
  173. mChildList(),
  174. mID(id),
  175. mLocalID(0),
  176. mTotalCRC(0),
  177. mTEImages(NULL),
  178. mGLName(0),
  179. mbCanSelect(TRUE),
  180. mFlags(0),
  181. mDrawable(),
  182. mCreateSelected(FALSE),
  183. mRenderMedia(FALSE),
  184. mBestUpdatePrecision(0),
  185. mText(),
  186. mLastInterpUpdateSecs(0.f),
  187. mLastMessageUpdateSecs(0.f),
  188. mLatestRecvPacketID(0),
  189. mData(NULL),
  190. mAudioSourcep(NULL),
  191. mAudioGain(1.f),
  192. mAppAngle(0.f),
  193. mPixelArea(1024.f),
  194. mInventory(NULL),
  195. mInventorySerialNum(0),
  196. mRegionp( regionp ),
  197. mInventoryPending(FALSE),
  198. mInventoryDirty(FALSE),
  199. mDead(FALSE),
  200. mOrphaned(FALSE),
  201. mUserSelected(FALSE),
  202. mOnActiveList(FALSE),
  203. mOnMap(FALSE),
  204. mStatic(FALSE),
  205. mNumFaces(0),
  206. mTimeDilation(1.f),
  207. mRotTime(0.f),
  208. mJointInfo(NULL),
  209. mState(0),
  210. mMedia(NULL),
  211. mClickAction(0),
  212. mAttachmentItemID(LLUUID::null)
  213. {
  214. if(!is_global)
  215. {
  216. llassert(mRegionp);
  217. }
  218. LLPrimitive::init_primitive(pcode);
  219. // CP: added 12/2/2005 - this was being initialised to 0, not the current frame time
  220. mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
  221. mPositionRegion = LLVector3(0.f, 0.f, 0.f);
  222. if(!is_global)
  223. {
  224. mPositionAgent = mRegionp->getOriginAgent();
  225. }
  226. LLViewerObject::sNumObjects++;
  227. }
  228. LLViewerObject::~LLViewerObject()
  229. {
  230. deleteTEImages();
  231. if(mInventory)
  232. {
  233. mInventory->clear();  // will deref and delete entries
  234. delete mInventory;
  235. mInventory = NULL;
  236. }
  237. if (mJointInfo)
  238. {
  239. delete mJointInfo;
  240. mJointInfo = NULL;
  241. }
  242. if (mPartSourcep)
  243. {
  244. mPartSourcep->setDead();
  245. mPartSourcep = NULL;
  246. }
  247. // Delete memory associated with extra parameters.
  248. std::map<U16, ExtraParameter*>::iterator iter;
  249. for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
  250. {
  251. if(iter->second != NULL)
  252. {
  253. delete iter->second->data;
  254. delete iter->second;
  255. }
  256. }
  257. mExtraParameterList.clear();
  258. for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
  259. mNameValuePairs.clear();
  260. delete[] mData;
  261. mData = NULL;
  262. delete mMedia;
  263. mMedia = NULL;
  264. sNumObjects--;
  265. sNumZombieObjects--;
  266. llassert(mChildList.size() == 0);
  267. clearInventoryListeners();
  268. }
  269. void LLViewerObject::deleteTEImages()
  270. {
  271. delete[] mTEImages;
  272. mTEImages = NULL;
  273. }
  274. void LLViewerObject::markDead()
  275. {
  276. if (!mDead)
  277. {
  278. //llinfos << "Marking self " << mLocalID << " as dead." << llendl;
  279. // Root object of this hierarchy unlinks itself.
  280. if (getParent())
  281. {
  282. ((LLViewerObject *)getParent())->removeChild(this);
  283. // go ahead and delete any jointinfo's that we find
  284. delete mJointInfo;
  285. mJointInfo = NULL;
  286. }
  287. // Mark itself as dead
  288. mDead = TRUE;
  289. gObjectList.cleanupReferences(this);
  290. LLViewerObject *childp;
  291. while (mChildList.size() > 0)
  292. {
  293. childp = mChildList.back();
  294. if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR)
  295. {
  296. //llinfos << "Marking child " << childp->getLocalID() << " as dead." << llendl;
  297. childp->setParent(NULL); // LLViewerObject::markDead 1
  298. childp->markDead();
  299. }
  300. else
  301. {
  302. // make sure avatar is no longer parented, 
  303. // so we can properly set it's position
  304. childp->setDrawableParent(NULL);
  305. ((LLVOAvatar*)childp)->getOffObject();
  306. childp->setParent(NULL); // LLViewerObject::markDead 2
  307. }
  308. mChildList.pop_back();
  309. }
  310. if (mDrawable.notNull())
  311. {
  312. // Drawables are reference counted, mark as dead, then nuke the pointer.
  313. mDrawable->markDead();
  314. mDrawable = NULL;
  315. }
  316. if (mText)
  317. {
  318. mText->markDead();
  319. mText = NULL;
  320. }
  321. if (mIcon)
  322. {
  323. mIcon->markDead();
  324. mIcon = NULL;
  325. }
  326. if (mPartSourcep)
  327. {
  328. mPartSourcep->setDead();
  329. mPartSourcep = NULL;
  330. }
  331. if (mAudioSourcep)
  332. {
  333. // Do some cleanup
  334. if (gAudiop)
  335. {
  336. gAudiop->cleanupAudioSource(mAudioSourcep);
  337. }
  338. mAudioSourcep = NULL;
  339. }
  340. if (flagAnimSource())
  341. {
  342. LLVOAvatar* avatarp = gAgent.getAvatarObject();
  343. if (avatarp && !avatarp->isDead())
  344. {
  345. // stop motions associated with this object
  346. avatarp->stopMotionFromSource(mID);
  347. }
  348. }
  349. if (flagCameraSource())
  350. {
  351. LLFollowCamMgr::removeFollowCamParams(mID);
  352. }
  353. sNumZombieObjects++;
  354. }
  355. }
  356. void LLViewerObject::dump() const
  357. {
  358. llinfos << "Type: " << pCodeToString(mPrimitiveCode) << llendl;
  359. llinfos << "Drawable: " << (LLDrawable *)mDrawable << llendl;
  360. llinfos << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << llendl;
  361. llinfos << "Parent: " << getParent() << llendl;
  362. llinfos << "ID: " << mID << llendl;
  363. llinfos << "LocalID: " << mLocalID << llendl;
  364. llinfos << "PositionRegion: " << getPositionRegion() << llendl;
  365. llinfos << "PositionAgent: " << getPositionAgent() << llendl;
  366. llinfos << "PositionGlobal: " << getPositionGlobal() << llendl;
  367. llinfos << "Velocity: " << getVelocity() << llendl;
  368. if (mDrawable.notNull() && mDrawable->getNumFaces())
  369. {
  370. LLFacePool *poolp = mDrawable->getFace(0)->getPool();
  371. if (poolp)
  372. {
  373. llinfos << "Pool: " << poolp << llendl;
  374. llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl;
  375. }
  376. }
  377. //llinfos << "BoxTree Min: " << mDrawable->getBox()->getMin() << llendl;
  378. //llinfos << "BoxTree Max: " << mDrawable->getBox()->getMin() << llendl;
  379. /*
  380. llinfos << "Velocity: " << getVelocity() << llendl;
  381. llinfos << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << llendl;
  382. llinfos << "UsePhysics: " << usePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << llendl;
  383. llinfos << "AppAngle: " << mAppAngle << llendl;
  384. llinfos << "PixelArea: " << mPixelArea << llendl;
  385. char buffer[1000];
  386. char *key;
  387. for (key = mNameValuePairs.getFirstKey(); key; key = mNameValuePairs.getNextKey() )
  388. {
  389. mNameValuePairs[key]->printNameValue(buffer);
  390. llinfos << buffer << llendl;
  391. }
  392. for (child_list_t::iterator iter = mChildList.begin();
  393.  iter != mChildList.end(); iter++)
  394. {
  395. LLViewerObject* child = *iter;
  396. llinfos << "  child " << child->getID() << llendl;
  397. }
  398. */
  399. }
  400. void LLViewerObject::printNameValuePairs() const
  401. {
  402. for (name_value_map_t::const_iterator iter = mNameValuePairs.begin();
  403.  iter != mNameValuePairs.end(); iter++)
  404. {
  405. LLNameValue* nv = iter->second;
  406. llinfos << nv->printNameValue() << llendl;
  407. }
  408. }
  409. void LLViewerObject::initVOClasses()
  410. {
  411. // Initialized shared class stuff first.
  412. LLVOAvatar::initClass();
  413. LLVOTree::initClass();
  414. if (gNoRender)
  415. {
  416. // Don't init anything else in drone mode
  417. return;
  418. }
  419. llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl;
  420. LLVOGrass::initClass();
  421. LLVOWater::initClass();
  422. LLVOSky::initClass();
  423. LLVOVolume::initClass();
  424. }
  425. void LLViewerObject::cleanupVOClasses()
  426. {
  427. LLVOGrass::cleanupClass();
  428. LLVOWater::cleanupClass();
  429. LLVOTree::cleanupClass();
  430. LLVOAvatar::cleanupClass();
  431. LLVOVolume::cleanupClass();
  432. }
  433. // Replaces all name value pairs with data from n delimited list
  434. // Does not update server
  435. void LLViewerObject::setNameValueList(const std::string& name_value_list)
  436. {
  437. // Clear out the old
  438. for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
  439. mNameValuePairs.clear();
  440. // Bring in the new
  441. std::string::size_type length = name_value_list.length();
  442. std::string::size_type start = 0;
  443. while (start < length)
  444. {
  445. std::string::size_type end = name_value_list.find_first_of("n", start);
  446. if (end == std::string::npos) end = length;
  447. if (end > start)
  448. {
  449. std::string tok = name_value_list.substr(start, end - start);
  450. addNVPair(tok);
  451. }
  452. start = end+1;
  453. }
  454. }
  455. // This method returns true if the object is over land owned by the
  456. // agent.
  457. BOOL LLViewerObject::isOverAgentOwnedLand() const
  458. {
  459. return mRegionp
  460. && mRegionp->getParcelOverlay()
  461. && mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion());
  462. }
  463. // This method returns true if the object is over land owned by the
  464. // agent.
  465. BOOL LLViewerObject::isOverGroupOwnedLand() const
  466. {
  467. return mRegionp 
  468. && mRegionp->getParcelOverlay()
  469. && mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
  470. }
  471. BOOL LLViewerObject::setParent(LLViewerObject* parent)
  472. {
  473. if(mParent != parent)
  474. {
  475. LLViewerObject* old_parent = (LLViewerObject*)mParent ;
  476. BOOL ret = LLPrimitive::setParent(parent);
  477. if(ret && old_parent && parent)
  478. {
  479. old_parent->removeChild(this) ;
  480. }
  481. return ret ;
  482. }
  483. return FALSE ;
  484. }
  485. void LLViewerObject::addChild(LLViewerObject *childp)
  486. {
  487. for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
  488. {
  489. if (*i == childp)
  490. { //already has child
  491. return;
  492. }
  493. }
  494. if (!isAvatar())
  495. {
  496. // propagate selection properties
  497. childp->mbCanSelect = mbCanSelect;
  498. }
  499. if(childp->setParent(this))
  500. {
  501. mChildList.push_back(childp);
  502. }
  503. }
  504. void LLViewerObject::removeChild(LLViewerObject *childp)
  505. {
  506. for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
  507. {
  508. if (*i == childp)
  509. {
  510. if (!childp->isAvatar() && mDrawable.notNull() && mDrawable->isActive() && childp->mDrawable.notNull() && !isAvatar())
  511. {
  512. gPipeline.markRebuild(childp->mDrawable, LLDrawable::REBUILD_VOLUME);
  513. }
  514. mChildList.erase(i);
  515. if(childp->getParent() == this)
  516. {
  517. childp->setParent(NULL);
  518. }
  519. break;
  520. }
  521. }
  522. if (childp->isSelected())
  523. {
  524. LLSelectMgr::getInstance()->deselectObjectAndFamily(childp);
  525. BOOL add_to_end = TRUE;
  526. LLSelectMgr::getInstance()->selectObjectAndFamily(childp, add_to_end);
  527. }
  528. }
  529. void LLViewerObject::addThisAndAllChildren(std::vector<LLViewerObject*>& objects)
  530. {
  531. objects.push_back(this);
  532. for (child_list_t::iterator iter = mChildList.begin();
  533.  iter != mChildList.end(); iter++)
  534. {
  535. LLViewerObject* child = *iter;
  536. if (!child->isAvatar())
  537. {
  538. child->addThisAndAllChildren(objects);
  539. }
  540. }
  541. }
  542. void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects)
  543. {
  544. objects.push_back(this);
  545. // don't add any attachments when temporarily selecting avatar
  546. if (isAvatar())
  547. {
  548. return;
  549. }
  550. for (child_list_t::iterator iter = mChildList.begin();
  551.  iter != mChildList.end(); iter++)
  552. {
  553. LLViewerObject* child = *iter;
  554. if ( (!child->isAvatar()) && (!child->isJointChild()))
  555. {
  556. child->addThisAndNonJointChildren(objects);
  557. }
  558. }
  559. }
  560. BOOL LLViewerObject::isChild(LLViewerObject *childp) const
  561. {
  562. for (child_list_t::const_iterator iter = mChildList.begin();
  563.  iter != mChildList.end(); iter++)
  564. {
  565. LLViewerObject* testchild = *iter;
  566. if (testchild == childp)
  567. return TRUE;
  568. }
  569. return FALSE;
  570. }
  571. // returns TRUE if at least one avatar is sitting on this object
  572. BOOL LLViewerObject::isSeat() const
  573. {
  574. for (child_list_t::const_iterator iter = mChildList.begin();
  575.  iter != mChildList.end(); iter++)
  576. {
  577. LLViewerObject* child = *iter;
  578. if (child->isAvatar())
  579. {
  580. return TRUE;
  581. }
  582. }
  583. return FALSE;
  584. }
  585. BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
  586. {
  587. if (mDrawable.isNull())
  588. {
  589. return FALSE;
  590. }
  591. BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
  592. if(!ret)
  593. {
  594. return FALSE ;
  595. }
  596. LLDrawable* old_parent = mDrawable->mParent;
  597. mDrawable->mParent = parentp; 
  598. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
  599. if( (old_parent != parentp && old_parent)
  600. || (parentp && parentp->isActive()))
  601. {
  602. // *TODO we should not be relying on setDrawable parent to call markMoved
  603. gPipeline.markMoved(mDrawable, FALSE);
  604. }
  605. else if (!mDrawable->isAvatar())
  606. {
  607. mDrawable->updateXform(TRUE);
  608. /*if (!mDrawable->getSpatialGroup())
  609. {
  610. mDrawable->movePartition();
  611. }*/
  612. }
  613. return ret;
  614. }
  615. // Show or hide particles, icon and HUD
  616. void LLViewerObject::hideExtraDisplayItems( BOOL hidden )
  617. {
  618. if( mPartSourcep.notNull() )
  619. {
  620. LLViewerPartSourceScript *partSourceScript = mPartSourcep.get();
  621. partSourceScript->setSuspended( hidden );
  622. }
  623. if( mText.notNull() )
  624. {
  625. LLHUDText *hudText = mText.get();
  626. hudText->setHidden( hidden );
  627. }
  628. if( mIcon.notNull() )
  629. {
  630. LLHUDIcon *hudIcon = mIcon.get();
  631. hudIcon->setHidden( hidden );
  632. }
  633. }
  634. U32 LLViewerObject::checkMediaURL(const std::string &media_url)
  635. {
  636.     U32 retval = (U32)0x0;
  637.     if (!mMedia && !media_url.empty())
  638.     {
  639.         retval |= MEDIA_URL_ADDED;
  640.         mMedia = new LLViewerObjectMedia;
  641.         mMedia->mMediaURL = media_url;
  642.         mMedia->mMediaType = LLViewerObject::MEDIA_SET;
  643.         mMedia->mPassedWhitelist = FALSE;
  644.     }
  645.     else if (mMedia)
  646.     {
  647.         if (media_url.empty())
  648.         {
  649.             retval |= MEDIA_URL_REMOVED;
  650.             delete mMedia;
  651.             mMedia = NULL;
  652.         }
  653.         else if (mMedia->mMediaURL != media_url) // <-- This is an optimization.  If they are equal don't bother with below's test.
  654.         {
  655.             /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() &&
  656.                    LLTextureEntry::getVersionFromMediaVersionString(media_url) == 
  657.                         LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1))
  658. */
  659.             {
  660.                 // If the media URL is different and WE were not the one who
  661.                 // changed it, mark dirty.
  662.                 retval |= MEDIA_URL_UPDATED;
  663.             }
  664.             mMedia->mMediaURL = media_url;
  665.             mMedia->mPassedWhitelist = FALSE;
  666.         }
  667.     }
  668.     return retval;
  669. }
  670. U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
  671.  void **user_data,
  672.  U32 block_num,
  673.  const EObjectUpdateType update_type,
  674.  LLDataPacker *dp)
  675. {
  676. LLMemType mt(LLMemType::MTYPE_OBJECT);
  677. U32 retval = 0x0;
  678. // Coordinates of objects on simulators are region-local.
  679. U64 region_handle;
  680. mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
  681. mRegionp = LLWorld::getInstance()->getRegionFromHandle(region_handle);
  682. if (!mRegionp)
  683. {
  684. U32 x, y;
  685. from_region_handle(region_handle, &x, &y);
  686. llerrs << "Object has invalid region " << x << ":" << y << "!" << llendl;
  687. return retval;
  688. }
  689. U16 time_dilation16;
  690. mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16);
  691. F32 time_dilation = ((F32) time_dilation16) / 65535.f;
  692. mTimeDilation = time_dilation;
  693. mRegionp->setTimeDilation(time_dilation);
  694. // this will be used to determine if we've really changed position
  695. // Use getPosition, not getPositionRegion, since this is what we're comparing directly against.
  696. LLVector3 test_pos_parent = getPosition();
  697. U8  data[60+16]; // This needs to match the largest size below.
  698. #ifdef LL_BIG_ENDIAN
  699. U16 valswizzle[4];
  700. #endif
  701. U16 *val;
  702. const F32 size = LLWorld::getInstance()->getRegionWidthInMeters();
  703. const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight();
  704. const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight();
  705. S32 length;
  706. S32 count;
  707. S32 this_update_precision = 32; // in bits
  708. // Temporaries, because we need to compare w/ previous to set dirty flags...
  709. LLVector3 new_pos_parent;
  710. LLVector3 new_vel;
  711. LLVector3 new_acc;
  712. LLVector3 new_angv;
  713. LLVector3 old_angv = getAngularVelocity();
  714. LLQuaternion new_rot;
  715. LLVector3 new_scale = getScale();
  716. U32 parent_id = 0;
  717. U8 material = 0;
  718. U8 click_action = 0;
  719. U32 crc = 0;
  720. bool old_special_hover_cursor = specialHoverCursor();
  721. LLViewerObject *cur_parentp = (LLViewerObject *)getParent();
  722. if (cur_parentp)
  723. {
  724. parent_id = cur_parentp->mLocalID;
  725. }
  726. if (!dp)
  727. {
  728. switch(update_type)
  729. {
  730. case OUT_FULL:
  731. {
  732. #ifdef DEBUG_UPDATE_TYPE
  733. llinfos << "Full:" << getID() << llendl;
  734. #endif
  735. LLUUID audio_uuid;
  736. LLUUID owner_id; // only valid if audio_uuid or particle system is not null
  737. F32    gain;
  738. U8     sound_flags;
  739. mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_CRC, crc, block_num);
  740. mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_ParentID, parent_id, block_num);
  741. mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_Sound, audio_uuid, block_num );
  742. // HACK: Owner id only valid if non-null sound id or particle system
  743. mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num );
  744. mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num );
  745. mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num );
  746. mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_Material, material, block_num );
  747. mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); 
  748. mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num );
  749. length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
  750. mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num);
  751. mTotalCRC = crc;
  752. // Owner ID used for sound muting or particle system muting
  753. setAttachedSound(audio_uuid, owner_id, gain, sound_flags);
  754. U8 old_material = getMaterial();
  755. if (old_material != material)
  756. {
  757. setMaterial(material);
  758. if (mDrawable.notNull())
  759. {
  760. gPipeline.markMoved(mDrawable, FALSE); // undamped
  761. }
  762. }
  763. setClickAction(click_action);
  764. count = 0;
  765. LLVector4 collision_plane;
  766. switch(length)
  767. {
  768. case (60 + 16):
  769. // pull out collision normal for avatar
  770. htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
  771. ((LLVOAvatar*)this)->setFootPlane(collision_plane);
  772. count += sizeof(LLVector4);
  773. // fall through
  774. case 60:
  775. this_update_precision = 32;
  776. // this is a terse update
  777. // pos
  778. htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  779. count += sizeof(LLVector3);
  780. // vel
  781. htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  782. count += sizeof(LLVector3);
  783. // acc
  784. htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  785. count += sizeof(LLVector3);
  786. // theta
  787. {
  788. LLVector3 vec;
  789. htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  790. new_rot.unpackFromVector3(vec);
  791. }
  792. count += sizeof(LLVector3);
  793. // omega
  794. htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  795. if (new_angv.isExactlyZero())
  796. {
  797. // reset rotation time
  798. resetRot();
  799. }
  800. setAngularVelocity(new_angv);
  801. #if LL_DARWIN
  802. if (length == 76)
  803. {
  804. setAngularVelocity(LLVector3::zero);
  805. }
  806. #endif
  807. break;
  808. case(32 + 16):
  809. // pull out collision normal for avatar
  810. htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
  811. ((LLVOAvatar*)this)->setFootPlane(collision_plane);
  812. count += sizeof(LLVector4);
  813. // fall through
  814. case 32:
  815. this_update_precision = 16;
  816. test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
  817. // This is a terse 16 update, so treat data as an array of U16's.
  818. #ifdef LL_BIG_ENDIAN
  819. htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
  820. val = valswizzle;
  821. #else
  822. val = (U16 *) &data[count];
  823. #endif
  824. count += sizeof(U16)*3;
  825. new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
  826. new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
  827. new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
  828. #ifdef LL_BIG_ENDIAN
  829. htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
  830. val = valswizzle;
  831. #else
  832. val = (U16 *) &data[count];
  833. #endif
  834. count += sizeof(U16)*3;
  835. setVelocity(LLVector3(U16_to_F32(val[VX], -size, size),
  836.    U16_to_F32(val[VY], -size, size),
  837.    U16_to_F32(val[VZ], -size, size)));
  838. #ifdef LL_BIG_ENDIAN
  839. htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
  840. val = valswizzle;
  841. #else
  842. val = (U16 *) &data[count];
  843. #endif
  844. count += sizeof(U16)*3;
  845. setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size),
  846.    U16_to_F32(val[VY], -size, size),
  847.    U16_to_F32(val[VZ], -size, size)));
  848. #ifdef LL_BIG_ENDIAN
  849. htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 4); 
  850. val = valswizzle;
  851. #else
  852. val = (U16 *) &data[count];
  853. #endif
  854. count += sizeof(U16)*4;
  855. new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
  856. new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
  857. new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
  858. new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
  859. #ifdef LL_BIG_ENDIAN
  860. htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
  861. val = valswizzle;
  862. #else
  863. val = (U16 *) &data[count];
  864. #endif
  865. new_angv.setVec(U16_to_F32(val[VX], -size, size),
  866. U16_to_F32(val[VY], -size, size),
  867. U16_to_F32(val[VZ], -size, size));
  868. if (new_angv.isExactlyZero())
  869. {
  870. // reset rotation time
  871. resetRot();
  872. }
  873. setAngularVelocity(new_angv);
  874. break;
  875. case 16:
  876. this_update_precision = 8;
  877. test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
  878. // this is a terse 8 update
  879. new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
  880. new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
  881. new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
  882. setVelocity(U8_to_F32(data[3], -size, size),
  883. U8_to_F32(data[4], -size, size),
  884. U8_to_F32(data[5], -size, size) );
  885. setAcceleration(U8_to_F32(data[6], -size, size),
  886. U8_to_F32(data[7], -size, size),
  887. U8_to_F32(data[8], -size, size) );
  888. new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
  889. new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
  890. new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
  891. new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
  892. new_angv.setVec(U8_to_F32(data[13], -size, size),
  893. U8_to_F32(data[14], -size, size),
  894. U8_to_F32(data[15], -size, size) );
  895. if (new_angv.isExactlyZero())
  896. {
  897. // reset rotation time
  898. resetRot();
  899. }
  900. setAngularVelocity(new_angv);
  901. break;
  902. }
  903. ////////////////////////////////////////////////////
  904. //
  905. // Here we handle data specific to the full message.
  906. //
  907. U32 flags;
  908. mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
  909. // clear all but local flags
  910. mFlags &= FLAGS_LOCAL;
  911. mFlags |= flags;
  912. U8 state;
  913. mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
  914. mState = state;
  915. // ...new objects that should come in selected need to be added to the selected list
  916. mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
  917. // Set all name value pairs
  918. S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue);
  919. if (nv_size > 0)
  920. {
  921. std::string name_value_list;
  922. mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_NameValue, name_value_list, block_num);
  923. setNameValueList(name_value_list);
  924. }
  925. // Clear out any existing generic data
  926. if (mData)
  927. {
  928. delete [] mData;
  929. }
  930. // Check for appended generic data
  931. S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data);
  932. if (data_size <= 0)
  933. {
  934. mData = NULL;
  935. }
  936. else
  937. {
  938. // ...has generic data
  939. mData = new U8[data_size];
  940. mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num);
  941. }
  942. S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text);
  943. if (text_size > 1)
  944. {
  945. // Setup object text
  946. if (!mText)
  947. {
  948. mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
  949. mText->setFont(LLFontGL::getFontSansSerif());
  950. mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
  951. mText->setMaxLines(-1);
  952. mText->setSourceObject(this);
  953. mText->setOnHUDAttachment(isHUDAttachment());
  954. }
  955. std::string temp_string;
  956. mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num );
  957. LLColor4U coloru;
  958. mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num);
  959. // alpha was flipped so that it zero encoded better
  960. coloru.mV[3] = 255 - coloru.mV[3];
  961. mText->setColor(LLColor4(coloru));
  962. mText->setStringUTF8(temp_string);
  963. if (mDrawable.notNull())
  964. {
  965. setChanged(MOVED | SILHOUETTE);
  966. gPipeline.markMoved(mDrawable, FALSE); // undamped
  967. }
  968. }
  969. else if (mText.notNull())
  970. {
  971. mText->markDead();
  972. mText = NULL;
  973. }
  974. std::string media_url;
  975. mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num);
  976.                 retval |= checkMediaURL(media_url);
  977.                 
  978. //
  979. // Unpack particle system data
  980. //
  981. unpackParticleSource(block_num, owner_id);
  982. // Mark all extra parameters not used
  983. std::map<U16, ExtraParameter*>::iterator iter;
  984. for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
  985. {
  986. iter->second->in_use = FALSE;
  987. }
  988. // Unpack extra parameters
  989. S32 size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ExtraParams);
  990. if (size > 0)
  991. {
  992. U8 *buffer = new U8[size];
  993. mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ExtraParams, buffer, size, block_num);
  994. LLDataPackerBinaryBuffer dp(buffer, size);
  995. U8 num_parameters;
  996. dp.unpackU8(num_parameters, "num_params");
  997. U8 param_block[MAX_OBJECT_PARAMS_SIZE];
  998. for (U8 param=0; param<num_parameters; ++param)
  999. {
  1000. U16 param_type;
  1001. S32 param_size;
  1002. dp.unpackU16(param_type, "param_type");
  1003. dp.unpackBinaryData(param_block, param_size, "param_data");
  1004. //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl;
  1005. LLDataPackerBinaryBuffer dp2(param_block, param_size);
  1006. unpackParameterEntry(param_type, &dp2);
  1007. }
  1008. delete[] buffer;
  1009. }
  1010. for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
  1011. {
  1012. if (!iter->second->in_use)
  1013. {
  1014. // Send an update message in case it was formerly in use
  1015. parameterChanged(iter->first, iter->second->data, FALSE, false);
  1016. }
  1017. }
  1018. U8 joint_type = 0;
  1019. mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_JointType, joint_type, block_num);
  1020. if (joint_type)
  1021. {
  1022. // create new joint info 
  1023. if (!mJointInfo)
  1024. {
  1025. mJointInfo = new LLVOJointInfo;
  1026. }
  1027. mJointInfo->mJointType = (EHavokJointType) joint_type;
  1028. mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointPivot, mJointInfo->mPivot, block_num);
  1029. mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointAxisOrAnchor, mJointInfo->mAxisOrAnchor, block_num);
  1030. }
  1031. else if (mJointInfo)
  1032. {
  1033. // this joint info is no longer needed
  1034. delete mJointInfo;
  1035. mJointInfo = NULL;
  1036. }
  1037. break;
  1038. }
  1039. case OUT_TERSE_IMPROVED:
  1040. {
  1041. #ifdef DEBUG_UPDATE_TYPE
  1042. llinfos << "TI:" << getID() << llendl;
  1043. #endif
  1044. length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
  1045. mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num);
  1046. count = 0;
  1047. LLVector4 collision_plane;
  1048. switch(length)
  1049. {
  1050. case(60 + 16):
  1051. // pull out collision normal for avatar
  1052. htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
  1053. ((LLVOAvatar*)this)->setFootPlane(collision_plane);
  1054. count += sizeof(LLVector4);
  1055. // fall through
  1056. case 60:
  1057. // this is a terse 32 update
  1058. // pos
  1059. this_update_precision = 32;
  1060. htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  1061. count += sizeof(LLVector3);
  1062. // vel
  1063. htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  1064. count += sizeof(LLVector3);
  1065. // acc
  1066. htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  1067. count += sizeof(LLVector3);
  1068. // theta
  1069. {
  1070. LLVector3 vec;
  1071. htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  1072. new_rot.unpackFromVector3(vec);
  1073. }
  1074. count += sizeof(LLVector3);
  1075. // omega
  1076. htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
  1077. if (new_angv.isExactlyZero())
  1078. {
  1079. // reset rotation time
  1080. resetRot();
  1081. }
  1082. setAngularVelocity(new_angv);
  1083. #if LL_DARWIN
  1084. if (length == 76)
  1085. {
  1086. setAngularVelocity(LLVector3::zero);
  1087. }
  1088. #endif
  1089. break;
  1090. case(32 + 16):
  1091. // pull out collision normal for avatar
  1092. htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
  1093. ((LLVOAvatar*)this)->setFootPlane(collision_plane);
  1094. count += sizeof(LLVector4);
  1095. // fall through
  1096. case 32:
  1097. // this is a terse 16 update
  1098. this_update_precision = 16;
  1099. test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
  1100. #ifdef LL_BIG_ENDIAN
  1101. htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
  1102. val = valswizzle;
  1103. #else
  1104. val = (U16 *) &data[count];
  1105. #endif
  1106. count += sizeof(U16)*3;
  1107. new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
  1108. new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
  1109. new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
  1110. #ifdef LL_BIG_ENDIAN
  1111. htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
  1112. val = valswizzle;
  1113. #else
  1114. val = (U16 *) &data[count];
  1115. #endif
  1116. count += sizeof(U16)*3;
  1117. setVelocity(U16_to_F32(val[VX], -size, size),
  1118. U16_to_F32(val[VY], -size, size),
  1119. U16_to_F32(val[VZ], -size, size));
  1120. #ifdef LL_BIG_ENDIAN
  1121. htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
  1122. val = valswizzle;
  1123. #else
  1124. val = (U16 *) &data[count];
  1125. #endif
  1126. count += sizeof(U16)*3;
  1127. setAcceleration(U16_to_F32(val[VX], -size, size),
  1128. U16_to_F32(val[VY], -size, size),
  1129. U16_to_F32(val[VZ], -size, size));
  1130. #ifdef LL_BIG_ENDIAN
  1131. htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8); 
  1132. val = valswizzle;
  1133. #else
  1134. val = (U16 *) &data[count];
  1135. #endif
  1136. count += sizeof(U16)*4;
  1137. new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
  1138. new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
  1139. new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
  1140. new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
  1141. #ifdef LL_BIG_ENDIAN
  1142. htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
  1143. val = valswizzle;
  1144. #else
  1145. val = (U16 *) &data[count];
  1146. #endif
  1147. setAngularVelocity( U16_to_F32(val[VX], -size, size),
  1148. U16_to_F32(val[VY], -size, size),
  1149. U16_to_F32(val[VZ], -size, size));
  1150. break;
  1151. case 16:
  1152. // this is a terse 8 update
  1153. this_update_precision = 8;
  1154. test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
  1155. new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
  1156. new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
  1157. new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
  1158. setVelocity(U8_to_F32(data[3], -size, size),
  1159. U8_to_F32(data[4], -size, size),
  1160. U8_to_F32(data[5], -size, size) );
  1161. setAcceleration(U8_to_F32(data[6], -size, size),
  1162. U8_to_F32(data[7], -size, size),
  1163. U8_to_F32(data[8], -size, size) );
  1164. new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
  1165. new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
  1166. new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
  1167. new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
  1168. setAngularVelocity( U8_to_F32(data[13], -size, size),
  1169. U8_to_F32(data[14], -size, size),
  1170. U8_to_F32(data[15], -size, size) );
  1171. break;
  1172. }
  1173. U8 state;
  1174. mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
  1175. mState = state;
  1176. break;
  1177. }
  1178. default:
  1179. break;
  1180. }
  1181. }
  1182. else
  1183. {
  1184. // handle the compressed case
  1185. LLUUID sound_uuid;
  1186. LLUUID owner_id;
  1187. F32    gain = 0;
  1188. U8     sound_flags = 0;
  1189. F32 cutoff = 0;
  1190. U16 val[4];
  1191. U8 state;
  1192. dp->unpackU8(state, "State");
  1193. mState = state;
  1194. switch(update_type)
  1195. {
  1196. case OUT_TERSE_IMPROVED:
  1197. {
  1198. #ifdef DEBUG_UPDATE_TYPE
  1199. llinfos << "CompTI:" << getID() << llendl;
  1200. #endif
  1201. U8 value;
  1202. dp->unpackU8(value, "agent");
  1203. if (value)
  1204. {
  1205. LLVector4 collision_plane;
  1206. dp->unpackVector4(collision_plane, "Plane");
  1207. ((LLVOAvatar*)this)->setFootPlane(collision_plane);
  1208. }
  1209. test_pos_parent = getPosition();
  1210. dp->unpackVector3(new_pos_parent, "Pos");
  1211. dp->unpackU16(val[VX], "VelX");
  1212. dp->unpackU16(val[VY], "VelY");
  1213. dp->unpackU16(val[VZ], "VelZ");
  1214. setVelocity(U16_to_F32(val[VX], -128.f, 128.f),
  1215. U16_to_F32(val[VY], -128.f, 128.f),
  1216. U16_to_F32(val[VZ], -128.f, 128.f));
  1217. dp->unpackU16(val[VX], "AccX");
  1218. dp->unpackU16(val[VY], "AccY");
  1219. dp->unpackU16(val[VZ], "AccZ");
  1220. setAcceleration(U16_to_F32(val[VX], -64.f, 64.f),
  1221. U16_to_F32(val[VY], -64.f, 64.f),
  1222. U16_to_F32(val[VZ], -64.f, 64.f));
  1223. dp->unpackU16(val[VX], "ThetaX");
  1224. dp->unpackU16(val[VY], "ThetaY");
  1225. dp->unpackU16(val[VZ], "ThetaZ");
  1226. dp->unpackU16(val[VS], "ThetaS");
  1227. new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
  1228. new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
  1229. new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
  1230. new_rot.mQ[VS] = U16_to_F32(val[VS], -1.f, 1.f);
  1231. dp->unpackU16(val[VX], "AccX");
  1232. dp->unpackU16(val[VY], "AccY");
  1233. dp->unpackU16(val[VZ], "AccZ");
  1234. setAngularVelocity( U16_to_F32(val[VX], -64.f, 64.f),
  1235. U16_to_F32(val[VY], -64.f, 64.f),
  1236. U16_to_F32(val[VZ], -64.f, 64.f));
  1237. }
  1238. break;
  1239. case OUT_FULL_COMPRESSED:
  1240. case OUT_FULL_CACHED:
  1241. {
  1242. #ifdef DEBUG_UPDATE_TYPE
  1243. llinfos << "CompFull:" << getID() << llendl;
  1244. #endif
  1245. dp->unpackU32(crc, "CRC");
  1246. mTotalCRC = crc;
  1247. dp->unpackU8(material, "Material");
  1248. U8 old_material = getMaterial();
  1249. if (old_material != material)
  1250. {
  1251. setMaterial(material);
  1252. if (mDrawable.notNull())
  1253. {
  1254. gPipeline.markMoved(mDrawable, FALSE); // undamped
  1255. }
  1256. }
  1257. dp->unpackU8(click_action, "ClickAction");
  1258. setClickAction(click_action);
  1259. dp->unpackVector3(new_scale, "Scale");
  1260. dp->unpackVector3(new_pos_parent, "Pos");
  1261. LLVector3 vec;
  1262. dp->unpackVector3(vec, "Rot");
  1263. new_rot.unpackFromVector3(vec);
  1264. setAcceleration(LLVector3::zero);
  1265. U32 value;
  1266. dp->unpackU32(value, "SpecialCode");
  1267. dp->setPassFlags(value);
  1268. dp->unpackUUID(owner_id, "Owner");
  1269. if (value & 0x80)
  1270. {
  1271. dp->unpackVector3(vec, "Omega");
  1272. setAngularVelocity(vec);
  1273. }
  1274. if (value & 0x20)
  1275. {
  1276. dp->unpackU32(parent_id, "ParentID");
  1277. }
  1278. else
  1279. {
  1280. parent_id = 0;
  1281. }
  1282. S32 sp_size;
  1283. U32 size;
  1284. if (value & 0x2)
  1285. {
  1286. sp_size = 1;
  1287. delete [] mData;
  1288. mData = new U8[1];
  1289. dp->unpackU8(((U8*)mData)[0], "TreeData");
  1290. }
  1291. else if (value & 0x1)
  1292. {
  1293. dp->unpackU32(size, "ScratchPadSize");
  1294. delete [] mData;
  1295. mData = new U8[size];
  1296. dp->unpackBinaryData((U8 *)mData, sp_size, "PartData");
  1297. }
  1298. else
  1299. {
  1300. mData = NULL;
  1301. }
  1302. // Setup object text
  1303. if (!mText && (value & 0x4))
  1304. {
  1305. mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
  1306. mText->setFont(LLFontGL::getFontSansSerif());
  1307. mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
  1308. mText->setMaxLines(-1); // Set to match current agni behavior.
  1309. mText->setSourceObject(this);
  1310. mText->setOnHUDAttachment(isHUDAttachment());
  1311. }
  1312. if (value & 0x4)
  1313. {
  1314. std::string temp_string;
  1315. dp->unpackString(temp_string, "Text");
  1316. LLColor4U coloru;
  1317. dp->unpackBinaryDataFixed(coloru.mV, 4, "Color");
  1318. coloru.mV[3] = 255 - coloru.mV[3];
  1319. mText->setColor(LLColor4(coloru));
  1320. mText->setStringUTF8(temp_string);
  1321. setChanged(TEXTURE);
  1322. }
  1323. else if(mText.notNull())
  1324. {
  1325. mText->markDead();
  1326. mText = NULL;
  1327. }
  1328.                 std::string media_url;
  1329. if (value & 0x200)
  1330. {
  1331. dp->unpackString(media_url, "MediaURL");
  1332. }
  1333.                 retval |= checkMediaURL(media_url);
  1334. //
  1335. // Unpack particle system data
  1336. //
  1337. if (value & 0x8)
  1338. {
  1339. unpackParticleSource(*dp, owner_id);
  1340. }
  1341. else
  1342. {
  1343. deleteParticleSource();
  1344. }
  1345. // Mark all extra parameters not used
  1346. std::map<U16, ExtraParameter*>::iterator iter;
  1347. for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
  1348. {
  1349. iter->second->in_use = FALSE;
  1350. }
  1351. // Unpack extra params
  1352. U8 num_parameters;
  1353. dp->unpackU8(num_parameters, "num_params");
  1354. U8 param_block[MAX_OBJECT_PARAMS_SIZE];
  1355. for (U8 param=0; param<num_parameters; ++param)
  1356. {
  1357. U16 param_type;
  1358. S32 param_size;
  1359. dp->unpackU16(param_type, "param_type");
  1360. dp->unpackBinaryData(param_block, param_size, "param_data");
  1361. //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl;
  1362. LLDataPackerBinaryBuffer dp2(param_block, param_size);
  1363. unpackParameterEntry(param_type, &dp2);
  1364. }
  1365. for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
  1366. {
  1367. if (!iter->second->in_use)
  1368. {
  1369. // Send an update message in case it was formerly in use
  1370. parameterChanged(iter->first, iter->second->data, FALSE, false);
  1371. }
  1372. }
  1373. if (value & 0x10)
  1374. {
  1375. dp->unpackUUID(sound_uuid, "SoundUUID");
  1376. dp->unpackF32(gain, "SoundGain");
  1377. dp->unpackU8(sound_flags, "SoundFlags");
  1378. dp->unpackF32(cutoff, "SoundRadius");
  1379. }
  1380. if (value & 0x100)
  1381. {
  1382. std::string name_value_list;
  1383. dp->unpackString(name_value_list, "NV");
  1384. setNameValueList(name_value_list);
  1385. }
  1386. mTotalCRC = crc;
  1387. setAttachedSound(sound_uuid, owner_id, gain, sound_flags);
  1388. // only get these flags on updates from sim, not cached ones
  1389. // Preload these five flags for every object.
  1390. // Finer shades require the object to be selected, and the selection manager
  1391. // stores the extended permission info.
  1392. U32 flags;
  1393. mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
  1394. // keep local flags and overwrite remote-controlled flags
  1395. mFlags = (mFlags & FLAGS_LOCAL) | flags;
  1396. // ...new objects that should come in selected need to be added to the selected list
  1397. mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
  1398. }
  1399. break;
  1400. default:
  1401. break;
  1402. }
  1403. }
  1404. //
  1405. // Fix object parenting.
  1406. //
  1407. BOOL b_changed_status = FALSE;
  1408. if (OUT_TERSE_IMPROVED != update_type)
  1409. {
  1410. // We only need to update parenting on full updates, terse updates
  1411. // don't send parenting information.
  1412. if (!cur_parentp)
  1413. {
  1414. if (parent_id == 0)
  1415. {
  1416. // No parent now, no parent in message -> do nothing
  1417. }
  1418. else
  1419. {
  1420. // No parent now, new parent in message -> attach to that parent if possible
  1421. LLUUID parent_uuid;
  1422. LLViewerObjectList::getUUIDFromLocal(parent_uuid,
  1423. parent_id,
  1424. mesgsys->getSenderIP(),
  1425. mesgsys->getSenderPort());
  1426. LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid);
  1427. //
  1428. // Check to see if we have the corresponding viewer object for the parent.
  1429. //
  1430. if (sent_parentp && sent_parentp->getParent() == this)
  1431. {
  1432. // Try to recover if we attempt to attach a parent to its child
  1433. llwarns << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << llendl;
  1434. this->removeChild(sent_parentp);
  1435. sent_parentp->setDrawableParent(NULL);
  1436. }
  1437. if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead())
  1438. {
  1439. //
  1440. // We have a viewer object for the parent, and it's not dead.
  1441. // Do the actual reparenting here.
  1442. //
  1443. // new parent is valid
  1444. b_changed_status = TRUE;
  1445. // ...no current parent, so don't try to remove child
  1446. if (mDrawable.notNull())
  1447. {
  1448. if (mDrawable->isDead() || !mDrawable->getVObj())
  1449. {
  1450. llwarns << "Drawable is dead or no VObj!" << llendl;
  1451. sent_parentp->addChild(this);
  1452. }
  1453. else
  1454. {
  1455. if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 1
  1456. {
  1457. // Bad, we got a cycle somehow.
  1458. // Kill both the parent and the child, and
  1459. // set cache misses for both of them.
  1460. llwarns << "Attempting to recover from parenting cycle!" << llendl;
  1461. llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl;
  1462. llwarns << "Adding to cache miss list" << llendl;
  1463. setParent(NULL);
  1464. sent_parentp->setParent(NULL);
  1465. getRegion()->addCacheMissFull(getLocalID());
  1466. getRegion()->addCacheMissFull(sent_parentp->getLocalID());
  1467. gObjectList.killObject(sent_parentp);
  1468. gObjectList.killObject(this);
  1469. return retval;
  1470. }
  1471. sent_parentp->addChild(this);
  1472. // make sure this object gets a non-damped update
  1473. if (sent_parentp->mDrawable.notNull())
  1474. {
  1475. gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped
  1476. }
  1477. }
  1478. }
  1479. else
  1480. {
  1481. sent_parentp->addChild(this);
  1482. }
  1483. // Show particles, icon and HUD
  1484. hideExtraDisplayItems( FALSE );
  1485. setChanged(MOVED | SILHOUETTE);
  1486. }
  1487. else
  1488. {
  1489. //
  1490. // No corresponding viewer object for the parent, put the various
  1491. // pieces on the orphan list.
  1492. //
  1493. //parent_id
  1494. U32 ip = mesgsys->getSenderIP();
  1495. U32 port = mesgsys->getSenderPort();
  1496. gObjectList.orphanize(this, parent_id, ip, port);
  1497. // Hide particles, icon and HUD
  1498. hideExtraDisplayItems( TRUE );
  1499. }
  1500. }
  1501. }
  1502. else
  1503. {
  1504. // BUG: this is a bad assumption once border crossing is alowed
  1505. if (  (parent_id == cur_parentp->mLocalID)
  1506. &&(update_type == OUT_TERSE_IMPROVED))
  1507. {
  1508. // Parent now, same parent in message -> do nothing
  1509. // Debugging for suspected problems with local ids.
  1510. //LLUUID parent_uuid;
  1511. //LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort() );
  1512. //if (parent_uuid != cur_parentp->getID() )
  1513. //{
  1514. // llerrs << "Local ID match but UUID mismatch of viewer object" << llendl;
  1515. //}
  1516. }
  1517. else
  1518. {
  1519. // Parented now, different parent in message
  1520. LLViewerObject *sent_parentp;
  1521. if (parent_id == 0)
  1522. {
  1523. //
  1524. // This object is no longer parented, we sent in a zero parent ID.
  1525. //
  1526. sent_parentp = NULL;
  1527. }
  1528. else
  1529. {
  1530. LLUUID parent_uuid;
  1531. LLViewerObjectList::getUUIDFromLocal(parent_uuid,
  1532. parent_id,
  1533. gMessageSystem->getSenderIP(),
  1534. gMessageSystem->getSenderPort());
  1535. sent_parentp = gObjectList.findObject(parent_uuid);
  1536. if (isAvatar())
  1537. {
  1538. // This logic is meant to handle the case where a sitting avatar has reached a new sim
  1539. // ahead of the object she was sitting on (which is common as objects are transfered through
  1540. // a slower route than agents)...
  1541. // In this case, the local id for the object will not be valid, since the viewer has not received
  1542. // a full update for the object from that sim yet, so we assume that the agent is still sitting
  1543. // where she was originally. --RN
  1544. if (!sent_parentp)
  1545. {
  1546. sent_parentp = cur_parentp;
  1547. }
  1548. }
  1549. else if (!sent_parentp)
  1550. {
  1551. //
  1552. // Switching parents, but we don't know the new parent.
  1553. //
  1554. U32 ip = mesgsys->getSenderIP();
  1555. U32 port = mesgsys->getSenderPort();
  1556. // We're an orphan, flag things appropriately.
  1557. gObjectList.orphanize(this, parent_id, ip, port);
  1558. }
  1559. }
  1560. // Reattach if possible.
  1561. if (sent_parentp && sent_parentp != cur_parentp && sent_parentp != this)
  1562. {
  1563. // New parent is valid, detach and reattach
  1564. b_changed_status = TRUE;
  1565. if (mDrawable.notNull())
  1566. {
  1567. if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 2
  1568. {
  1569. // Bad, we got a cycle somehow.
  1570. // Kill both the parent and the child, and
  1571. // set cache misses for both of them.
  1572. llwarns << "Attempting to recover from parenting cycle!" << llendl;
  1573. llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl;
  1574. llwarns << "Adding to cache miss list" << llendl;
  1575. setParent(NULL);
  1576. sent_parentp->setParent(NULL);
  1577. getRegion()->addCacheMissFull(getLocalID());
  1578. getRegion()->addCacheMissFull(sent_parentp->getLocalID());
  1579. gObjectList.killObject(sent_parentp);
  1580. gObjectList.killObject(this);
  1581. return retval;
  1582. }
  1583. // make sure this object gets a non-damped update
  1584. }
  1585. cur_parentp->removeChild(this);
  1586. sent_parentp->addChild(this);
  1587. setChanged(MOVED | SILHOUETTE);
  1588. sent_parentp->setChanged(MOVED | SILHOUETTE);
  1589. if (sent_parentp->mDrawable.notNull())
  1590. {
  1591. gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped
  1592. }
  1593. }
  1594. else if (!sent_parentp)
  1595. {
  1596. bool remove_parent = true;
  1597. // No new parent, or the parent that we sent doesn't exist on the viewer.
  1598. LLViewerObject *parentp = (LLViewerObject *)getParent();
  1599. if (parentp)
  1600. {
  1601. if (parentp->getRegion() != getRegion())
  1602. {
  1603. // This is probably an object flying across a region boundary, the
  1604. // object probably ISN'T being reparented, but just got an object
  1605. // update out of order (child update before parent).
  1606. //llinfos << "Don't reparent object handoffs!" << llendl;
  1607. remove_parent = false;
  1608. }
  1609. }
  1610. if (remove_parent)
  1611. {
  1612. b_changed_status = TRUE;
  1613. if (mDrawable.notNull())
  1614. {
  1615. // clear parent to removeChild can put the drawable on the damped list
  1616. setDrawableParent(NULL); // LLViewerObject::processUpdateMessage 3
  1617. }
  1618. cur_parentp->removeChild(this);
  1619. if (mJointInfo && !parent_id)
  1620. {
  1621. // since this object is no longer parent-relative
  1622. // we make sure we delete any joint info
  1623. delete mJointInfo;
  1624. mJointInfo = NULL;
  1625. }
  1626. setChanged(MOVED | SILHOUETTE);
  1627. if (mDrawable.notNull())
  1628. {
  1629. // make sure this object gets a non-damped update
  1630. gPipeline.markMoved(mDrawable, FALSE); // undamped
  1631. }
  1632. }
  1633. }
  1634. }
  1635. }
  1636. }
  1637. new_rot.normQuat();
  1638. if (gPingInterpolate)
  1639. LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender());
  1640. if (cdp)
  1641. {
  1642. F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped);
  1643. LLVector3 diff = getVelocity() * (0.5f*mTimeDilation*(gFrameDTClamped + ((F32)ping_delay)*0.001f)); 
  1644. new_pos_parent += diff;
  1645. }
  1646. else
  1647. {
  1648. llwarns << "findCircuit() returned NULL; skipping interpolation" << llendl;
  1649. }
  1650. }
  1651. //////////////////////////
  1652. //
  1653. // Set the generic change flags...
  1654. //
  1655. //
  1656. U32 packet_id = mesgsys->getCurrentRecvPacketID(); 
  1657. if (packet_id < mLatestRecvPacketID && 
  1658. mLatestRecvPacketID - packet_id < 65536)
  1659. {
  1660. //skip application of this message, it's old
  1661. return retval;
  1662. }
  1663. mLatestRecvPacketID = packet_id;
  1664. // Set the change flags for scale
  1665. if (new_scale != getScale())
  1666. {
  1667. setChanged(SCALED | SILHOUETTE);
  1668. setScale(new_scale);  // Must follow setting permYouOwner()
  1669. }
  1670. // first, let's see if the new position is actually a change
  1671. //static S32 counter = 0;
  1672. F32 vel_mag_sq = getVelocity().magVecSquared();
  1673. F32 accel_mag_sq = getAcceleration().magVecSquared();
  1674. if (  ((b_changed_status)||(test_pos_parent != new_pos_parent))
  1675. ||(  (!isSelected())
  1676.    &&(  (vel_mag_sq != 0.f)
  1677.   ||(accel_mag_sq != 0.f)
  1678.   ||(this_update_precision > mBestUpdatePrecision))))
  1679. {
  1680. mBestUpdatePrecision = this_update_precision;
  1681. LLVector3 diff = new_pos_parent - test_pos_parent ;
  1682. F32 mag_sqr = diff.magVecSquared() ;
  1683. if(llfinite(mag_sqr)) 
  1684. {
  1685. setPositionParent(new_pos_parent);
  1686. }
  1687. else
  1688. {
  1689. llwarns << "Can not move the object/avatar to an infinite location!" << llendl ;
  1690. retval |= INVALID_UPDATE ;
  1691. }
  1692. if (mParent && ((LLViewerObject*)mParent)->isAvatar())
  1693. {
  1694. // we have changed the position of an attachment, so we need to clamp it
  1695. LLVOAvatar *avatar = (LLVOAvatar*)mParent;
  1696. avatar->clampAttachmentPositions();
  1697. }
  1698. }
  1699. if (new_rot != mLastRot
  1700. || new_angv != old_angv)
  1701. {
  1702. if (new_rot != mLastRot)
  1703. {
  1704. mLastRot = new_rot;
  1705. setRotation(new_rot);
  1706. }
  1707. setChanged(ROTATED | SILHOUETTE);
  1708. resetRot();
  1709. }
  1710. if ( gShowObjectUpdates )
  1711. {
  1712. if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->isSelf()))
  1713. && mRegionp)
  1714. {
  1715. LLViewerObject* object = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, mRegionp);
  1716. LLVOTextBubble* bubble = (LLVOTextBubble*) object;
  1717. if (update_type == OUT_TERSE_IMPROVED)
  1718. {
  1719. bubble->mColor.setVec(0.f, 0.f, 1.f, 1.f);
  1720. }
  1721. else
  1722. {
  1723. bubble->mColor.setVec(1.f, 0.f, 0.f, 1.f);
  1724. }
  1725. object->setPositionGlobal(getPositionGlobal());
  1726. gPipeline.addObject(object);
  1727. }
  1728. }
  1729. if ((0.0f == vel_mag_sq) && 
  1730. (0.0f == accel_mag_sq) &&
  1731. (0.0f == getAngularVelocity().magVecSquared()))
  1732. {
  1733. mStatic = TRUE; // This object doesn't move!
  1734. }
  1735. else
  1736. {
  1737. mStatic = FALSE;
  1738. }
  1739. // BUG: This code leads to problems during group rotate and any scale operation.
  1740. // Small discepencies between the simulator and viewer representations cause the 
  1741. // selection center to creep, leading to objects moving around the wrong center.
  1742. // 
  1743. // Removing this, however, means that if someone else drags an object you have
  1744. // selected, your selection center and dialog boxes will be wrong.  It also means
  1745. // that higher precision information on selected objects will be ignored.
  1746. //
  1747. // I believe the group rotation problem is fixed.  JNC 1.21.2002
  1748. //
  1749. // Additionally, if any child is selected, need to update the dialogs and selection
  1750. // center.
  1751. BOOL needs_refresh = mUserSelected;
  1752. for (child_list_t::iterator iter = mChildList.begin();
  1753.  iter != mChildList.end(); iter++)
  1754. {
  1755. LLViewerObject* child = *iter;
  1756. needs_refresh = needs_refresh || child->mUserSelected;
  1757. }
  1758. if (needs_refresh)
  1759. {
  1760. LLSelectMgr::getInstance()->updateSelectionCenter();
  1761. dialog_refresh_all();
  1762. // Mark update time as approx. now, with the ping delay.
  1763. // Ping delay is off because it's not set for velocity interpolation, causing
  1764. // much jumping and hopping around...
  1765. // U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay();
  1766. mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
  1767. mLastMessageUpdateSecs = LLFrameTimer::getElapsedSeconds();
  1768. if (mDrawable.notNull())
  1769. {
  1770. // Don't clear invisibility flag on update if still orphaned!
  1771. if (mDrawable->isState(LLDrawable::FORCE_INVISIBLE) && !mOrphaned)
  1772. {
  1773. //  lldebugs << "Clearing force invisible: " << mID << ":" << getPCodeString() << ":" << getPositionAgent() << llendl;
  1774. mDrawable->setState(LLDrawable::CLEAR_INVISIBLE);
  1775. }
  1776. }
  1777. // Update special hover cursor status
  1778. bool special_hover_cursor = specialHoverCursor();
  1779. if (old_special_hover_cursor != special_hover_cursor
  1780. && mDrawable.notNull())
  1781. {
  1782. mDrawable->updateSpecialHoverCursor(special_hover_cursor);
  1783. }
  1784. return retval;
  1785. }
  1786. BOOL LLViewerObject::isActive() const
  1787. {
  1788. return TRUE;
  1789. }
  1790. BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
  1791. {
  1792. if (mDead)
  1793. {
  1794. // It's dead.  Don't update it.
  1795. return TRUE;
  1796. }
  1797. // CRO - don't velocity interp linked objects!
  1798. // Leviathan - but DO velocity interp joints
  1799. if (!mStatic && gVelocityInterpolate && !isSelected())
  1800. {
  1801. // calculate dt from last update
  1802. F32 dt_raw = (F32)(time - mLastInterpUpdateSecs);
  1803. F32 dt = mTimeDilation * dt_raw;
  1804. if (!mJointInfo)
  1805. {
  1806. applyAngularVelocity(dt);
  1807. }
  1808. LLViewerObject *parentp = (LLViewerObject *) getParent();
  1809. if (mJointInfo)
  1810. {
  1811. if (parentp)
  1812. {
  1813. // do parent-relative stuff
  1814. LLVector3 ang_vel = getAngularVelocity();
  1815. F32 omega = ang_vel.magVecSquared();
  1816. F32 angle = 0.0f;
  1817. LLQuaternion dQ;
  1818. if (omega > 0.00001f)
  1819. {
  1820. omega = sqrt(omega);
  1821. angle = omega * dt;
  1822. dQ.setQuat(angle, ang_vel);
  1823. }
  1824. LLVector3 pos = getPosition();
  1825. if (HJT_HINGE == mJointInfo->mJointType)
  1826. {
  1827. // hinge = uniform circular motion
  1828. LLVector3 parent_pivot = getVelocity();
  1829. LLVector3 parent_axis = getAcceleration();
  1830. angle = dt * (ang_vel * mJointInfo->mAxisOrAnchor); // AxisOrAnchor = axis
  1831. dQ.setQuat(angle, mJointInfo->mAxisOrAnchor); // AxisOrAnchor = axis
  1832. LLVector3 pivot_offset = pos - mJointInfo->mPivot; // pos in pivot-frame
  1833. pivot_offset = pivot_offset * dQ; // new rotated pivot-frame pos
  1834. pos = mJointInfo->mPivot + pivot_offset; // parent-frame
  1835. LLViewerObject::setPosition(pos);
  1836. LLQuaternion Q_PC = getRotation();
  1837. setRotation(Q_PC * dQ);
  1838. mLastInterpUpdateSecs = time;
  1839. }
  1840. else if (HJT_POINT == mJointInfo->mJointType)
  1841. // || HJT_LPOINT == mJointInfo->mJointType)
  1842. {
  1843. // point-to-point = spin about axis and uniform circular motion
  1844. //  of axis about the pivot point
  1845. //
  1846. // NOTE: this interpolation scheme is not quite good enough to
  1847. // reduce the bandwidth -- needs a gravitational correction. 
  1848. // Similarly for hinges with axes that deviate from vertical.
  1849. LLQuaternion Q_PC = getRotation();
  1850. Q_PC = Q_PC * dQ;
  1851. setRotation(Q_PC);
  1852. LLVector3 pivot_to_child = - mJointInfo->mAxisOrAnchor; // AxisOrAnchor = anchor
  1853. pos = mJointInfo->mPivot + pivot_to_child * Q_PC;
  1854. LLViewerObject::setPosition(pos);
  1855. mLastInterpUpdateSecs = time;
  1856. }
  1857. /* else if (HJT_WHEEL == mJointInfo->mJointInfo)
  1858. {
  1859. // wheel = uniform rotation about axis, with linear
  1860. //    velocity interpolation (if any)
  1861. LLVector3 parent_axis = getAcceleration(); // HACK -- accel stores the parent-axis (parent-frame)
  1862. LLQuaternion Q_PC = getRotation();
  1863. angle = dt * (parent_axis * ang_vel);
  1864. dQ.setQuat(angle, parent_axis);
  1865. Q_PC = Q_PC * dQ;
  1866. setRotation(Q_PC);
  1867. pos = getPosition() + dt * getVelocity();
  1868. LLViewerObject::setPosition(pos);
  1869. mLastInterpUpdateSecs = time;
  1870. }*/
  1871. }
  1872. }
  1873. else if (isAttachment())
  1874. {
  1875. mLastInterpUpdateSecs = time;
  1876. return TRUE;
  1877. }
  1878. else
  1879. {
  1880. // linear motion
  1881. // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object
  1882. // updates represents the average velocity of the last timestep, rather than the final velocity.
  1883. // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically
  1884. // 
  1885. // There is a problem here if dt is negative. . .
  1886. // *TODO: should also wrap linear accel/velocity in check
  1887. // to see if object is selected, instead of explicitly
  1888. // zeroing it out
  1889. LLVector3 accel = getAcceleration();
  1890. LLVector3 vel  = getVelocity();
  1891. if (!(accel.isExactlyZero() && vel.isExactlyZero()))
  1892. {
  1893. LLVector3 pos  = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
  1894. // region local  
  1895. setPositionRegion(pos + getPositionRegion());
  1896. setVelocity(vel + accel*dt);
  1897. // for objects that are spinning but not translating, make sure to flag them as having moved
  1898. setChanged(MOVED | SILHOUETTE);
  1899. }
  1900. mLastInterpUpdateSecs = time;
  1901. }
  1902. }
  1903. if (gNoRender)
  1904. {
  1905. // Skip drawable stuff if not rendering.
  1906. return TRUE;
  1907. }
  1908. updateDrawable(FALSE);
  1909. return TRUE;
  1910. }
  1911. BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size)
  1912. {
  1913. LLMemType mt(LLMemType::MTYPE_OBJECT);
  1914. delete [] mData;
  1915. if (datap)
  1916. {
  1917. mData = new U8[data_size];
  1918. if (!mData)
  1919. {
  1920. return FALSE;
  1921. }
  1922. memcpy(mData, datap, data_size); /* Flawfinder: ignore */
  1923. }
  1924. return TRUE;
  1925. }
  1926. // delete an item in the inventory, but don't tell the server. This is
  1927. // used internally by remove, update, and savescript.
  1928. // This will only delete the first item with an item_id in the list
  1929. void LLViewerObject::deleteInventoryItem(const LLUUID& item_id)
  1930. {
  1931. if(mInventory)
  1932. {
  1933. InventoryObjectList::iterator it = mInventory->begin();
  1934. InventoryObjectList::iterator end = mInventory->end();
  1935. for( ; it != end; ++it )
  1936. {
  1937. if((*it)->getUUID() == item_id)
  1938. {
  1939. // This is safe only because we return immediatly.
  1940. mInventory->erase(it); // will deref and delete it
  1941. return;
  1942. }
  1943. }
  1944. doInventoryCallback();
  1945. }
  1946. }
  1947. void LLViewerObject::doUpdateInventory(
  1948. LLPointer<LLViewerInventoryItem>& item,
  1949. U8 key,
  1950. bool is_new)
  1951. {
  1952. LLMemType mt(LLMemType::MTYPE_OBJECT);
  1953. LLViewerInventoryItem* old_item = NULL;
  1954. if(TASK_INVENTORY_ITEM_KEY == key)
  1955. {
  1956. old_item = (LLViewerInventoryItem*)getInventoryObject(item->getUUID());
  1957. }
  1958. else if(TASK_INVENTORY_ASSET_KEY == key)
  1959. {
  1960. old_item = getInventoryItemByAsset(item->getAssetUUID());
  1961. }
  1962. LLUUID item_id;
  1963. LLUUID new_owner;
  1964. LLUUID new_group;
  1965. BOOL group_owned = FALSE;
  1966. if(old_item)
  1967. {
  1968. item_id = old_item->getUUID();
  1969. new_owner = old_item->getPermissions().getOwner();
  1970. new_group = old_item->getPermissions().getGroup();
  1971. group_owned = old_item->getPermissions().isGroupOwned();
  1972. old_item = NULL;
  1973. }
  1974. else
  1975. {
  1976. item_id = item->getUUID();
  1977. }
  1978. if(!is_new && mInventory)
  1979. {
  1980. // Attempt to update the local inventory. If we can get the
  1981. // object perm, we have perfect visibility, so we want the
  1982. // serial number to match. Otherwise, take our best guess and
  1983. // make sure that the serial number does not match.
  1984. deleteInventoryItem(item_id);
  1985. LLPermissions perm(item->getPermissions());
  1986. LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this);
  1987. bool is_atomic = ((S32)LLAssetType::AT_OBJECT == item->getType()) ? false : true;
  1988. if(obj_perm)
  1989. {
  1990. perm.setOwnerAndGroup(LLUUID::null, obj_perm->getOwner(), obj_perm->getGroup(), is_atomic);
  1991. }
  1992. else
  1993. {
  1994. if(group_owned)
  1995. {
  1996. perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic);
  1997. }
  1998. else if(!new_owner.isNull())
  1999. {
  2000. // The object used to be in inventory, so we can
  2001. // assume the owner and group will match what they are
  2002. // there.
  2003. perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic);
  2004. }
  2005. // *FIX: can make an even better guess by using the mPermGroup flags
  2006. else if(permYouOwner())
  2007. {
  2008. // best guess.
  2009. perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
  2010. --mInventorySerialNum;
  2011. }
  2012. else
  2013. {
  2014. // dummy it up.
  2015. perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
  2016. --mInventorySerialNum;
  2017. }
  2018. }
  2019. LLViewerInventoryItem* oldItem = item;
  2020. LLViewerInventoryItem* new_item = new LLViewerInventoryItem(oldItem);
  2021. new_item->setPermissions(perm);
  2022. mInventory->push_front(new_item);
  2023. doInventoryCallback();
  2024. ++mInventorySerialNum;
  2025. }
  2026. }
  2027. // save a script, which involves removing the old one, and rezzing
  2028. // in the new one. This method should be called with the asset id
  2029. // of the new and old script AFTER the bytecode has been saved.
  2030. void LLViewerObject::saveScript(
  2031. const LLViewerInventoryItem* item,
  2032. BOOL active,
  2033. bool is_new)
  2034. {
  2035. LLMemType mt(LLMemType::MTYPE_OBJECT);
  2036. /*
  2037.  * XXXPAM Investigate not making this copy.  Seems unecessary, but I'm unsure about the
  2038.  * interaction with doUpdateInventory() called below.
  2039.  */
  2040. lldebugs << "LLViewerObject::saveScript() " << item->getUUID() << " " << item->getAssetUUID() << llendl;
  2041. LLPointer<LLViewerInventoryItem> task_item =
  2042. new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
  2043.   item->getAssetUUID(), item->getType(),
  2044.   item->getInventoryType(),
  2045.   item->getName(), item->getDescription(),
  2046.   item->getSaleInfo(), item->getFlags(),
  2047.   item->getCreationDate());
  2048. task_item->setTransactionID(item->getTransactionID());
  2049. LLMessageSystem* msg = gMessageSystem;
  2050. msg->newMessageFast(_PREHASH_RezScript);
  2051. msg->nextBlockFast(_PREHASH_AgentData);
  2052. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  2053. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  2054. msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
  2055. msg->nextBlockFast(_PREHASH_UpdateBlock);
  2056. msg->addU32Fast(_PREHASH_ObjectLocalID, (mLocalID));
  2057. U8 enabled = active;
  2058. msg->addBOOLFast(_PREHASH_Enabled, enabled);
  2059. msg->nextBlockFast(_PREHASH_InventoryBlock);
  2060. task_item->packMessage(msg);
  2061. msg->sendReliable(mRegionp->getHost());
  2062. // do the internal logic
  2063. doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, is_new);
  2064. }
  2065. void LLViewerObject::moveInventory(const LLUUID& folder_id,
  2066.    const LLUUID& item_id)
  2067. {
  2068. lldebugs << "LLViewerObject::moveInventory " << item_id << llendl;
  2069. LLMessageSystem* msg = gMessageSystem;
  2070. msg->newMessageFast(_PREHASH_MoveTaskInventory);
  2071. msg->nextBlockFast(_PREHASH_AgentData);
  2072. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  2073. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  2074. msg->addUUIDFast(_PREHASH_FolderID, folder_id);
  2075. msg->nextBlockFast(_PREHASH_InventoryData);
  2076. msg->addU32Fast(_PREHASH_LocalID, mLocalID);
  2077. msg->addUUIDFast(_PREHASH_ItemID, item_id);
  2078. msg->sendReliable(mRegionp->getHost());
  2079. LLInventoryObject* inv_obj = getInventoryObject(item_id);
  2080. if(inv_obj)
  2081. {
  2082. LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_obj;
  2083. if(!item->getPermissions().allowCopyBy(gAgent.getID()))
  2084. {
  2085. deleteInventoryItem(item_id);
  2086. ++mInventorySerialNum;
  2087. }
  2088. }
  2089. }
  2090. void LLViewerObject::dirtyInventory()
  2091. {
  2092. // If there aren't any LLVOInventoryListeners, we won't be
  2093. // able to update our mInventory when it comes back from the
  2094. // simulator, so we should not clear the inventory either.
  2095. if(mInventory && !mInventoryCallbacks.empty())
  2096. {
  2097. mInventory->clear(); // will deref and delete entries
  2098. delete mInventory;
  2099. mInventory = NULL;
  2100. mInventoryDirty = TRUE;
  2101. }
  2102. }
  2103. void LLViewerObject::registerInventoryListener(LLVOInventoryListener* listener, void* user_data)
  2104. {
  2105. LLMemType mt(LLMemType::MTYPE_OBJECT);
  2106. LLInventoryCallbackInfo* info = new LLInventoryCallbackInfo;
  2107. info->mListener = listener;
  2108. info->mInventoryData = user_data;
  2109. mInventoryCallbacks.push_front(info);
  2110. }
  2111. void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener)
  2112. {
  2113. if (listener == NULL)
  2114. return;
  2115. for (callback_list_t::iterator iter = mInventoryCallbacks.begin();
  2116.  iter != mInventoryCallbacks.end(); )
  2117. {
  2118. callback_list_t::iterator curiter = iter++;
  2119. LLInventoryCallbackInfo* info = *curiter;
  2120. if (info->mListener == listener)
  2121. {
  2122. delete info;
  2123. mInventoryCallbacks.erase(curiter);
  2124. break;
  2125. }
  2126. }
  2127. }
  2128. void LLViewerObject::clearInventoryListeners()
  2129. {
  2130. for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer());
  2131. mInventoryCallbacks.clear();
  2132. }
  2133. void LLViewerObject::requestInventory()
  2134. {
  2135. mInventoryDirty = FALSE;
  2136. if(mInventory)
  2137. {
  2138. //mInventory->clear() // will deref and delete it
  2139. //delete mInventory;
  2140. //mInventory = NULL;
  2141. doInventoryCallback();
  2142. }
  2143. // throw away duplicate requests
  2144. else
  2145. {
  2146. fetchInventoryFromServer();
  2147. }
  2148. }
  2149. void LLViewerObject::fetchInventoryFromServer()
  2150. {
  2151. if (!mInventoryPending)
  2152. {
  2153. delete mInventory;
  2154. mInventory = NULL;
  2155. mInventoryDirty = FALSE;
  2156. LLMessageSystem* msg = gMessageSystem;
  2157. msg->newMessageFast(_PREHASH_RequestTaskInventory);
  2158. msg->nextBlockFast(_PREHASH_AgentData);
  2159. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  2160. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  2161. msg->nextBlockFast(_PREHASH_InventoryData);
  2162. msg->addU32Fast(_PREHASH_LocalID, mLocalID);
  2163. msg->sendReliable(mRegionp->getHost());
  2164. // this will get reset by dirtyInventory or doInventoryCallback
  2165. mInventoryPending = TRUE;
  2166. }
  2167. }
  2168. struct LLFilenameAndTask
  2169. {
  2170. LLUUID mTaskID;
  2171. std::string mFilename;
  2172. #ifdef _DEBUG
  2173. static S32 sCount;
  2174. LLFilenameAndTask()
  2175. {
  2176. ++sCount;
  2177. lldebugs << "Constructing LLFilenameAndTask: " << sCount << llendl;
  2178. }
  2179. ~LLFilenameAndTask()
  2180. {
  2181. --sCount;
  2182. lldebugs << "Destroying LLFilenameAndTask: " << sCount << llendl;
  2183. }
  2184. private:
  2185. LLFilenameAndTask(const LLFilenameAndTask& rhs);
  2186. const LLFilenameAndTask& operator=(const LLFilenameAndTask& rhs) const;
  2187. #endif
  2188. };
  2189. #ifdef _DEBUG
  2190. S32 LLFilenameAndTask::sCount = 0;
  2191. #endif
  2192. // static
  2193. void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
  2194. {
  2195. LLMemType mt(LLMemType::MTYPE_OBJECT);
  2196. LLUUID task_id;
  2197. msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
  2198. LLViewerObject* object = gObjectList.findObject(task_id);
  2199. if(!object)
  2200. {
  2201. llwarns << "LLViewerObject::processTaskInv object "
  2202. << task_id << " does not exist." << llendl;
  2203. return;
  2204. }
  2205. msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum);
  2206. LLFilenameAndTask* ft = new LLFilenameAndTask;
  2207. ft->mTaskID = task_id;
  2208. std::string unclean_filename;
  2209. msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
  2210. ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
  2211. if(ft->mFilename.empty())
  2212. {
  2213. lldebugs << "Task has no inventory" << llendl;
  2214. // mock up some inventory to make a drop target.
  2215. if(object->mInventory)
  2216. {
  2217. object->mInventory->clear(); // will deref and delete it
  2218. }
  2219. else
  2220. {
  2221. object->mInventory = new InventoryObjectList();
  2222. }
  2223. LLPointer<LLInventoryObject> obj;
  2224. obj = new LLInventoryObject(object->mID, LLUUID::null,
  2225. LLAssetType::AT_CATEGORY,
  2226. LLTrans::getString("ViewerObjectContents").c_str());
  2227. object->mInventory->push_front(obj);
  2228. object->doInventoryCallback();
  2229. delete ft;
  2230. return;
  2231. }
  2232. gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename), 
  2233. ft->mFilename, LL_PATH_CACHE,
  2234. object->mRegionp->getHost(),
  2235. TRUE,
  2236. &LLViewerObject::processTaskInvFile,
  2237. (void**)ft,
  2238. LLXferManager::HIGH_PRIORITY);
  2239. }
  2240. void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
  2241. {
  2242. LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data;
  2243. LLViewerObject* object = NULL;
  2244. if(ft && (0 == error_code) &&
  2245.    (object = gObjectList.findObject(ft->mTaskID)))
  2246. {
  2247. object->loadTaskInvFile(ft->mFilename);
  2248. }
  2249. else
  2250. {
  2251. // This Occurs When to requests were made, and the first one
  2252. // has already handled it.
  2253. lldebugs << "Problem loading task inventory. Return code: "
  2254.  << error_code << llendl;
  2255. }
  2256. delete ft;
  2257. }
  2258. void LLViewerObject::loadTaskInvFile(const std::string& filename)
  2259. {
  2260. LLMemType mt(LLMemType::MTYPE_OBJECT);
  2261. std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename);
  2262. llifstream ifs(filename_and_local_path);
  2263. if(ifs.good())
  2264. {
  2265. char buffer[MAX_STRING]; /* Flawfinder: ignore */
  2266. // *NOTE: This buffer size is hard coded into scanf() below.
  2267. char keyword[MAX_STRING]; /* Flawfinder: ignore */
  2268. if(mInventory)
  2269. {
  2270. mInventory->clear(); // will deref and delete it
  2271. }
  2272. else
  2273. {
  2274. mInventory = new InventoryObjectList;
  2275. }
  2276. while(ifs.good())
  2277. {
  2278. ifs.getline(buffer, MAX_STRING);
  2279. sscanf(buffer, " %254s", keyword); /* Flawfinder: ignore */
  2280. if(0 == strcmp("inv_item", keyword))
  2281. {
  2282. LLPointer<LLInventoryObject> inv = new LLViewerInventoryItem;
  2283. inv->importLegacyStream(ifs);
  2284. mInventory->push_front(inv);
  2285. }
  2286. else if(0 == strcmp("inv_object", keyword))
  2287. {
  2288. LLPointer<LLInventoryObject> inv = new LLInventoryObject;
  2289. inv->importLegacyStream(ifs);
  2290. inv->rename(LLTrans::getString("ViewerObjectContents").c_str());
  2291. mInventory->push_front(inv);
  2292. }
  2293. else
  2294. {
  2295. llwarns << "Unknown token in inventory file '"
  2296. << keyword << "'" << llendl;
  2297. }
  2298. }
  2299. ifs.close();
  2300. LLFile::remove(filename_and_local_path);
  2301. }
  2302. else
  2303. {
  2304. llwarns << "unable to load task inventory: " << filename_and_local_path
  2305. << llendl;
  2306. }
  2307. doInventoryCallback();
  2308. }
  2309. void LLViewerObject::doInventoryCallback()
  2310. {
  2311. for (callback_list_t::iterator iter = mInventoryCallbacks.begin();
  2312.  iter != mInventoryCallbacks.end(); )
  2313. {
  2314. callback_list_t::iterator curiter = iter++;
  2315. LLInventoryCallbackInfo* info = *curiter;
  2316. if (info->mListener != NULL)
  2317. {
  2318. info->mListener->inventoryChanged(this,
  2319.  mInventory,
  2320.  mInventorySerialNum,
  2321.  info->mInventoryData);
  2322. }
  2323. else
  2324. {
  2325. llinfos << "LLViewerObject::doInventoryCallback() deleting bad listener entry." << llendl;
  2326. delete info;
  2327. mInventoryCallbacks.erase(curiter);
  2328. }
  2329. }
  2330. mInventoryPending = FALSE;
  2331. }
  2332. void LLViewerObject::removeInventory(const LLUUID& item_id)
  2333. {
  2334. // close any associated floater properties