llviewerobject.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewerobject.h"
00035 
00036 #include "audioengine.h"
00037 #include "imageids.h"
00038 #include "indra_constants.h"
00039 #include "llmath.h"
00040 #include "llflexibleobject.h"
00041 #include "llviewercontrol.h"
00042 #include "lldatapacker.h"
00043 #include "llfasttimer.h"
00044 #include "llfontgl.h"
00045 #include "llframetimer.h"
00046 #include "llinventory.h"
00047 #include "llmaterialtable.h"
00048 #include "llmutelist.h"
00049 #include "llnamevalue.h"
00050 #include "llprimitive.h"
00051 #include "llquantize.h"
00052 #include "llregionhandle.h"
00053 #include "lltree_common.h"
00054 #include "llxfermanager.h"
00055 #include "message.h"
00056 #include "object_flags.h"
00057 #include "timing.h"
00058 
00059 #include "llaudiosourcevo.h"
00060 #include "llagent.h"
00061 #include "llbbox.h"
00062 #include "llbox.h"
00063 #include "llcylinder.h"
00064 #include "lldrawable.h"
00065 #include "llface.h"
00066 #include "llfloaterproperties.h"
00067 #include "llfollowcam.h"
00068 #include "llnetmap.h"
00069 #include "llselectmgr.h"
00070 #include "llsphere.h"
00071 #include "lltooldraganddrop.h"
00072 #include "llviewercamera.h"
00073 #include "llviewerimagelist.h"
00074 #include "llviewerinventory.h"
00075 #include "llviewerobjectlist.h"
00076 #include "llviewerparceloverlay.h"
00077 #include "llviewerpartsource.h"
00078 #include "llviewerregion.h"
00079 #include "llviewertextureanim.h"
00080 #include "llviewerwindow.h" // For getSpinAxis
00081 #include "llvoavatar.h"
00082 #include "llvoclouds.h"
00083 #include "llvograss.h"
00084 #include "llvoground.h"
00085 #include "llvolume.h"
00086 #include "llvolumemessage.h"
00087 #include "llvopartgroup.h"
00088 #include "llvosky.h"
00089 #include "llvostars.h"
00090 #include "llvosurfacepatch.h"
00091 #include "llvotextbubble.h"
00092 #include "llvotree.h"
00093 #include "llvovolume.h"
00094 #include "llvowater.h"
00095 #include "llworld.h"
00096 #include "llui.h"
00097 #include "pipeline.h"
00098 #include "viewer.h"
00099 
00100 //#define DEBUG_UPDATE_TYPE
00101 
00102 extern BOOL             gVelocityInterpolate;
00103 extern BOOL             gPingInterpolate;
00104 extern U32              gFrameCount;
00105 
00106 U32                     LLViewerObject::sNumZombieObjects = 0;
00107 S32                     LLViewerObject::sNumObjects = 0;
00108 BOOL            LLViewerObject::sMapDebug = TRUE;
00109 LLColor4        LLViewerObject::sEditSelectColor(       1.0f, 1.f, 0.f, 0.3f);  // Edit OK
00110 LLColor4        LLViewerObject::sNoEditSelectColor(     1.0f, 0.f, 0.f, 0.3f);  // Can't edit
00111 S32                     LLViewerObject::sAxisArrowLength(50);
00112 BOOL            LLViewerObject::sPulseEnabled(FALSE);
00113 BOOL            LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
00114 
00115 // static
00116 LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
00117 {
00118         LLViewerObject *res = NULL;
00119         LLFastTimer t1(LLFastTimer::FTM_CREATE_OBJECT);
00120         
00121         switch (pcode)
00122         {
00123         case LL_PCODE_VOLUME:
00124           res = new LLVOVolume(id, pcode, regionp); break;
00125         case LL_PCODE_LEGACY_AVATAR:
00126           res = new LLVOAvatar(id, pcode, regionp); break;
00127         case LL_PCODE_LEGACY_GRASS:
00128           res = new LLVOGrass(id, pcode, regionp); break;
00129         case LL_PCODE_LEGACY_PART_SYS:
00130 //        llwarns << "Creating old part sys!" << llendl;
00131 //        res = new LLVOPart(id, pcode, regionp); break;
00132           res = NULL; break;
00133         case LL_PCODE_LEGACY_TREE:
00134           res = new LLVOTree(id, pcode, regionp); break;
00135         case LL_PCODE_TREE_NEW:
00136 //        llwarns << "Creating new tree!" << llendl;
00137 //        res = new LLVOTree(id, pcode, regionp); break;
00138           res = NULL; break;
00139         case LL_PCODE_LEGACY_TEXT_BUBBLE:
00140           res = new LLVOTextBubble(id, pcode, regionp); break;
00141         case LL_VO_CLOUDS:
00142           res = new LLVOClouds(id, pcode, regionp); break;
00143         case LL_VO_SURFACE_PATCH:
00144           res = new LLVOSurfacePatch(id, pcode, regionp); break;
00145         case LL_VO_SKY:
00146           res = new LLVOSky(id, pcode, regionp); break;
00147         case LL_VO_STARS:
00148           res = new LLVOStars(id, pcode, regionp); break;
00149         case LL_VO_WATER:
00150           res = new LLVOWater(id, pcode, regionp); break;
00151         case LL_VO_GROUND:
00152           res = new LLVOGround(id, pcode, regionp); break;
00153         case LL_VO_PART_GROUP:
00154           res = new LLVOPartGroup(id, pcode, regionp); break;
00155         default:
00156           llwarns << "Unknown object pcode " << (S32)pcode << llendl;
00157           res = NULL; break;
00158         }
00159         return res;
00160 }
00161 
00162 LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
00163 :       LLPrimitive(),
00164         mChildList(),
00165         mID(id),
00166         mLocalID(0),
00167         mTotalCRC(0),
00168         mTEImages(NULL),
00169         mGLName(0),
00170         mbCanSelect(TRUE),
00171         mFlags(0),
00172         mDrawable(),
00173         mCreateSelected(FALSE),
00174         mRenderMedia(FALSE),
00175         mBestUpdatePrecision(0),
00176         mText(),
00177         mLastInterpUpdateSecs(0.f),
00178         mLastMessageUpdateSecs(0.f),
00179         mLatestRecvPacketID(0),
00180         mData(NULL),
00181         mAudioSourcep(NULL),
00182         mAudioGain(1.f),
00183         mAppAngle(0.f),
00184         mPixelArea(1024.f),
00185         mInventory(NULL),
00186         mInventorySerialNum(0),
00187         mRegionp( regionp ),
00188         mInventoryPending(FALSE),
00189         mInventoryDirty(FALSE),
00190         mDead(FALSE),
00191         mOrphaned(FALSE),
00192         mUserSelected(FALSE),
00193         mOnActiveList(FALSE),
00194         mOnMap(FALSE),
00195         mStatic(FALSE),
00196         mNumFaces(0),
00197         mLastUpdateFrame(0),
00198         mTimeDilation(1.f),
00199         mRotTime(0.f),
00200         mJointInfo(NULL),
00201         mState(0),
00202         mMedia(NULL),
00203         mClickAction(0)
00204 {
00205         llassert(mRegionp);
00206 
00207         LLPrimitive::init(pcode);
00208 
00209         // CP: added 12/2/2005 - this was being initialised to 0, not the current frame time
00210         mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
00211 
00212         mPositionRegion = LLVector3(0.f, 0.f, 0.f);
00213         mPositionAgent = mRegionp->getOriginAgent();
00214 
00215         LLViewerObject::sNumObjects++;
00216 }
00217 
00218 LLViewerObject::~LLViewerObject()
00219 {
00220         deleteTEImages();
00221 
00222         if(mInventory)
00223         {
00224                 mInventory->clear();  // will deref and delete entries
00225                 delete mInventory;
00226                 mInventory = NULL;
00227         }
00228 
00229         if (mJointInfo)
00230         {
00231                 delete mJointInfo;
00232                 mJointInfo = NULL;
00233         }
00234 
00235         if (mPartSourcep)
00236         {
00237                 mPartSourcep->setDead();
00238                 mPartSourcep = NULL;
00239         }
00240 
00241         // Delete memory associated with extra parameters.
00242         std::map<U16, ExtraParameter*>::iterator iter;
00243         for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
00244         {
00245                 delete iter->second->data;
00246                 delete iter->second;
00247         }
00248         mExtraParameterList.clear();
00249 
00250         for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
00251         mNameValuePairs.clear();
00252         
00253         delete[] mData;
00254         mData = NULL;
00255 
00256         delete mMedia;
00257         mMedia = NULL;
00258 
00259         sNumObjects--;
00260         sNumZombieObjects--;
00261         llassert(mChildList.size() == 0);
00262 
00263         clearInventoryListeners();
00264 }
00265 
00266 void LLViewerObject::deleteTEImages()
00267 {
00268         delete[] mTEImages;
00269         mTEImages = NULL;
00270 }
00271 
00272 void LLViewerObject::markDead()
00273 {
00274         if (!mDead)
00275         {
00276                 //llinfos << "Marking self " << mLocalID << " as dead." << llendl;
00277                 
00278                 // Root object of this hierarchy unlinks itself.
00279                 if (getParent())
00280                 {
00281                         ((LLViewerObject *)getParent())->removeChild(this);
00282                         // go ahead and delete any jointinfo's that we find
00283                         delete mJointInfo;
00284                         mJointInfo = NULL;
00285                 }
00286 
00287                 // Mark itself as dead
00288                 mDead = TRUE;
00289                 gObjectList.cleanupReferences(this);
00290 
00291                 LLViewerObject *childp;
00292                 while (mChildList.size() > 0)
00293                 {
00294                         childp = mChildList[0];
00295                         if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR)
00296                         {
00297                                 //llinfos << "Marking child " << childp->getLocalID() << " as dead." << llendl;
00298                                 childp->setParent(NULL); // LLViewerObject::markDead 1
00299                                 childp->markDead();
00300                         }
00301                         else
00302                         {
00303                                 // make sure avatar is no longer parented, 
00304                                 // so we can properly set it's position
00305                                 childp->setDrawableParent(NULL);
00306                                 ((LLVOAvatar*)childp)->getOffObject();
00307                                 childp->setParent(NULL); // LLViewerObject::markDead 2
00308                         }
00309                         mChildList.erase(mChildList.begin());
00310                 }
00311 
00312                 if (mDrawable.notNull())
00313                 {
00314                         // Drawables are reference counted, mark as dead, then nuke the pointer.
00315                         mDrawable->markDead();
00316                         mDrawable = NULL;
00317                 }
00318 
00319                 if (mText)
00320                 {
00321                         mText->markDead();
00322                         mText = NULL;
00323                 }
00324 
00325                 if (mIcon)
00326                 {
00327                         mIcon->markDead();
00328                         mIcon = NULL;
00329                 }
00330 
00331                 if (mPartSourcep)
00332                 {
00333                         mPartSourcep->setDead();
00334                         mPartSourcep = NULL;
00335                 }
00336 
00337                 if (mAudioSourcep)
00338                 {
00339                         // Do some cleanup
00340                         if (gAudiop)
00341                         {
00342                                 gAudiop->cleanupAudioSource(mAudioSourcep);
00343                         }
00344                         mAudioSourcep = NULL;
00345                 }
00346 
00347                 if (flagAnimSource())
00348                 {
00349                         LLVOAvatar* avatarp = gAgent.getAvatarObject();
00350                         if (avatarp && !avatarp->isDead())
00351                         {
00352                                 // stop motions associated with this object
00353                                 avatarp->stopMotionFromSource(mID);
00354                         }
00355                 }
00356 
00357                 if (flagCameraSource())
00358                 {
00359                         LLFollowCamMgr::removeFollowCamParams(mID);
00360                 }
00361 
00362                 sNumZombieObjects++;
00363         }
00364 }
00365 
00366 void LLViewerObject::dump() const
00367 {
00368         llinfos << "Type: " << pCodeToString(mPrimitiveCode) << llendl;
00369         llinfos << "Drawable: " << (LLDrawable *)mDrawable << llendl;
00370         llinfos << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << llendl;
00371 
00372         llinfos << "Parent: " << getParent() << llendl;
00373         llinfos << "ID: " << mID << llendl;
00374         llinfos << "LocalID: " << mLocalID << llendl;
00375         llinfos << "PositionRegion: " << getPositionRegion() << llendl;
00376         llinfos << "PositionAgent: " << getPositionAgent() << llendl;
00377         llinfos << "PositionGlobal: " << getPositionGlobal() << llendl;
00378         llinfos << "Velocity: " << getVelocity() << llendl;
00379         if (mDrawable.notNull() && mDrawable->getNumFaces())
00380         {
00381                 LLFacePool *poolp = mDrawable->getFace(0)->getPool();
00382                 if (poolp)
00383                 {
00384                         llinfos << "Pool: " << poolp << llendl;
00385                         llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl;
00386                 }
00387         }
00388         //llinfos << "BoxTree Min: " << mDrawable->getBox()->getMin() << llendl;
00389         //llinfos << "BoxTree Max: " << mDrawable->getBox()->getMin() << llendl;
00390         /*
00391         llinfos << "Velocity: " << getVelocity() << llendl;
00392         llinfos << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << llendl;
00393         llinfos << "UsePhysics: " << usePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << llendl;
00394         llinfos << "AppAngle: " << mAppAngle << llendl;
00395         llinfos << "PixelArea: " << mPixelArea << llendl;
00396 
00397         char buffer[1000];
00398         char *key;
00399         for (key = mNameValuePairs.getFirstKey(); key; key = mNameValuePairs.getNextKey() )
00400         {
00401                 mNameValuePairs[key]->printNameValue(buffer);
00402                 llinfos << buffer << llendl;
00403         }
00404 
00405         S32 i;
00406 
00407         LLViewerObject *child;
00408         for (i = 0; i < mChildList.size(); i++)
00409         {
00410                 child = mChildList[i];
00411                 llinfos << "  child " << child->getID() << llendl;
00412         }
00413         */
00414 }
00415 
00416 void LLViewerObject::printNameValuePairs() const
00417 {
00418         for (name_value_map_t::const_iterator iter = mNameValuePairs.begin();
00419                  iter != mNameValuePairs.end(); iter++)
00420         {
00421                 LLNameValue* nv = iter->second;
00422                 llinfos << nv->printNameValue() << llendl;
00423         }
00424 }
00425 
00426 void LLViewerObject::initVOClasses()
00427 {
00428         // Initialized shared class stuff first.
00429         LLVOAvatar::initClass();
00430         LLVOTree::initClass();
00431         if (gNoRender)
00432         {
00433                 // Don't init anything else in drone mode
00434                 return;
00435         }
00436         llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl;
00437         LLVOGrass::initClass();
00438         LLVOWater::initClass();
00439         LLVOSky::initClass();
00440         LLVOVolume::initClass();
00441 }
00442 
00443 void LLViewerObject::cleanupVOClasses()
00444 {
00445         LLVOGrass::cleanupClass();
00446         LLVOWater::cleanupClass();
00447         LLVOTree::cleanupClass();
00448         LLVOAvatar::cleanupClass();
00449 }
00450 
00451 // Replaces all name value pairs with data from \n delimited list
00452 // Does not update server
00453 void LLViewerObject::setNameValueList(const std::string& name_value_list)
00454 {
00455         // Clear out the old
00456         for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
00457         mNameValuePairs.clear();
00458 
00459         // Bring in the new
00460         std::string::size_type length = name_value_list.length();
00461         std::string::size_type start = 0;
00462         while (start < length)
00463         {
00464                 std::string::size_type end = name_value_list.find_first_of("\n", start);
00465                 if (end == std::string::npos) end = length;
00466                 if (end > start)
00467                 {
00468                         std::string tok = name_value_list.substr(start, end - start);
00469                         addNVPair(tok.c_str());
00470                 }
00471                 start = end+1;
00472         }
00473 }
00474 
00475 
00476 // This method returns true if the object is over land owned by the
00477 // agent.
00478 BOOL LLViewerObject::isOverAgentOwnedLand() const
00479 {
00480         return mRegionp
00481                 && mRegionp->getParcelOverlay()
00482                 && mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion());
00483 }
00484 
00485 // This method returns true if the object is over land owned by the
00486 // agent.
00487 BOOL LLViewerObject::isOverGroupOwnedLand() const
00488 {
00489         return mRegionp 
00490                 && mRegionp->getParcelOverlay()
00491                 && mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion());
00492 }
00493 
00494 void LLViewerObject::setParent(LLViewerObject* parent)
00495 {
00496         LLPrimitive::setParent(parent);
00497 }
00498 
00499 void LLViewerObject::addChild(LLViewerObject *childp)
00500 {
00501         BOOL result = TRUE;
00502         
00503         for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
00504         {
00505                 if (*i == childp)
00506                 {       //already has child
00507                         return;
00508                 }
00509         }
00510         
00511         if (!isAvatar())
00512         {
00513                 // propagate selection properties
00514                 childp->mbCanSelect = mbCanSelect;
00515         }
00516 
00517         childp->setParent(this);
00518         mChildList.push_back(childp);
00519 
00520         if (!result) 
00521         {
00522                 llwarns << "Failed to attach child " << childp->getID() << " to object " << getID() << llendl;
00523                 removeChild(childp);
00524                 if (mJointInfo)
00525                 {
00526                         delete mJointInfo;
00527                         mJointInfo = NULL;
00528                 }
00529         }
00530 }
00531 
00532 void LLViewerObject::removeChild(LLViewerObject *childp)
00533 {
00534         for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
00535         {
00536                 if (*i == childp)
00537                 {
00538                         if (!childp->isAvatar() && mDrawable.notNull() && mDrawable->isActive() && childp->mDrawable.notNull() && !isAvatar())
00539                         {
00540                                 gPipeline.markRebuild(childp->mDrawable, LLDrawable::REBUILD_VOLUME);
00541                         }
00542 
00543                         mChildList.erase(i);
00544                         childp->setParent(NULL);                        
00545                         break;
00546                 }
00547         }
00548         
00549         if (childp->isSelected())
00550         {
00551                 gSelectMgr->deselectObjectAndFamily(childp);
00552                 BOOL add_to_end = TRUE;
00553                 gSelectMgr->selectObjectAndFamily(childp, add_to_end);
00554         }
00555 }
00556 
00557 LLViewerObject::child_list_t& LLViewerObject::getChildren()
00558 {
00559         return mChildList;
00560 }
00561 
00562 void LLViewerObject::addThisAndAllChildren(LLDynamicArray<LLViewerObject*>& objects)
00563 {
00564         objects.put(this);
00565         S32 count = mChildList.size();
00566         for(S32 i = 0; i < count; i++)
00567         {
00568                 if (!mChildList[i]->isAvatar())
00569                 {
00570                         (mChildList[i])->addThisAndAllChildren(objects);
00571                 }
00572         }
00573 }
00574 
00575 void LLViewerObject::addThisAndNonJointChildren(LLDynamicArray<LLViewerObject*>& objects)
00576 {
00577         objects.put(this);
00578         // don't add any attachments when temporarily selecting avatar
00579         if (isAvatar())
00580         {
00581                 return;
00582         }
00583         S32 count = mChildList.size();
00584         for(S32 i = 0; i < count; i++)
00585         {
00586                 if ( (!mChildList[i]->isAvatar())
00587                         && (!mChildList[i]->isJointChild()))
00588                 {
00589                         (mChildList[i])->addThisAndNonJointChildren(objects);
00590                 }
00591         }
00592 }
00593 
00594 BOOL LLViewerObject::isChild(LLViewerObject *childp) const
00595 {
00596         S32 count = mChildList.size();
00597         for(S32 i = 0; i < count; i++)
00598         {
00599                 const LLViewerObject *testChildp = &(*mChildList[i]);
00600                 if (testChildp == childp) return TRUE;
00601         }
00602         return FALSE;
00603 }
00604 
00605 
00606 // returns TRUE if at least one avatar is sitting on this object
00607 BOOL LLViewerObject::isSeat() const
00608 {
00609         S32 count = mChildList.size();
00610         for(S32 i = 0; i < count; i++)
00611         {
00612                 const LLViewerObject *childp = &(*mChildList[i]);
00613                 if (childp->isAvatar())
00614                 {
00615                         return TRUE;
00616                 }
00617         }
00618         return FALSE;
00619 
00620 }
00621 
00622 BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
00623 {
00624         if (mDrawable.isNull())
00625         {
00626                 return FALSE;
00627         }
00628 
00629         LLDrawable* old_parent = mDrawable->mParent;
00630 
00631         mDrawable->mParent = parentp; 
00632         
00633         BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
00634         gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
00635         if (old_parent || (parentp && parentp->isActive()))
00636         {
00637                 gPipeline.markMoved(mDrawable, FALSE);
00638         }
00639         else
00640         {
00641                 mDrawable->updateXform(TRUE);
00642                 if (!mDrawable->getSpatialGroup())
00643                 {
00644                         mDrawable->movePartition();
00645                 }
00646         }
00647         
00648         return ret;
00649 }
00650 
00651 // Show or hide particles, icon and HUD
00652 void LLViewerObject::hideExtraDisplayItems( BOOL hidden )
00653 {
00654         if( mPartSourcep.notNull() )
00655         {
00656                 LLViewerPartSourceScript *partSourceScript = mPartSourcep.get();
00657                 partSourceScript->setSuspended( hidden );
00658         }
00659 
00660         if( mText.notNull() )
00661         {
00662                 LLHUDText *hudText = mText.get();
00663                 hudText->setHidden( hidden );
00664         }
00665 
00666         if( mIcon.notNull() )
00667         {
00668                 LLHUDIcon *hudIcon = mIcon.get();
00669                 hudIcon->setHidden( hidden );
00670         }
00671 }
00672 
00673 
00674 U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
00675                                          void **user_data,
00676                                          U32 block_num,
00677                                          const EObjectUpdateType update_type,
00678                                          LLDataPacker *dp)
00679 {
00680         LLMemType mt(LLMemType::MTYPE_OBJECT);
00681         
00682         U32 retval = 0x0;
00683         
00684         // Coordinates of objects on simulators are region-local.
00685         U64 region_handle;
00686         mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
00687         mRegionp = gWorldPointer->getRegionFromHandle(region_handle);
00688         if (!mRegionp)
00689         {
00690                 U32 x, y;
00691                 from_region_handle(region_handle, &x, &y);
00692 
00693                 llerrs << "Object has invalid region " << x << ":" << y << "!" << llendl;
00694                 return retval;
00695         }
00696 
00697         U16 time_dilation16;
00698         mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16);
00699         F32 time_dilation = ((F32) time_dilation16) / 65535.f;
00700         mTimeDilation = time_dilation;
00701         mRegionp->setTimeDilation(time_dilation);
00702 
00703         // this will be used to determine if we've really changed position
00704         // Use getPosition, not getPositionRegion, since this is what we're comparing directly against.
00705         LLVector3 test_pos_parent = getPosition();
00706 
00707         U8  data[60+16]; // This needs to match the largest size below.
00708 #ifdef LL_BIG_ENDIAN
00709         U16 valswizzle[4];
00710 #endif
00711         U16     *val;
00712         const F32 size = gWorldPointer->getRegionWidthInMeters();       
00713         const F32 MAX_HEIGHT = gWorldPointer->getRegionMaxHeight();
00714         const F32 MIN_HEIGHT = gWorldPointer->getRegionMinHeight();
00715         S32 length;
00716         S32     count;
00717         S32 this_update_precision = 32;         // in bits
00718 
00719         // Temporaries, because we need to compare w/ previous to set dirty flags...
00720         LLVector3 new_pos_parent;
00721         LLVector3 new_vel;
00722         LLVector3 new_acc;
00723         LLVector3 new_angv;
00724         LLQuaternion new_rot;
00725         LLVector3 new_scale = getScale();
00726 
00727         U32     parent_id = 0;
00728         U8      material = 0;
00729         U8 click_action = 0;
00730         U32 crc = 0;
00731 
00732         bool old_special_hover_cursor = specialHoverCursor();
00733 
00734         LLViewerObject *cur_parentp = (LLViewerObject *)getParent();
00735 
00736         if (cur_parentp)
00737         {
00738                 parent_id = cur_parentp->mLocalID;
00739         }
00740 
00741         if (!dp)
00742         {
00743                 switch(update_type)
00744                 {
00745                 case OUT_FULL:
00746                         {
00747 #ifdef DEBUG_UPDATE_TYPE
00748                                 llinfos << "Full:" << getID() << llendl;
00749 #endif
00750                                 LLUUID audio_uuid;
00751                                 LLUUID owner_id;        // only valid if audio_uuid or particle system is not null
00752                                 F32    gain;
00753                                 U8     sound_flags;
00754 
00755                                 mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_CRC, crc, block_num);
00756                                 mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_ParentID, parent_id, block_num);
00757                                 mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_Sound, audio_uuid, block_num );
00758                                 // HACK: Owner id only valid if non-null sound id or particle system
00759                                 mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num );
00760                                 mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num );
00761                                 mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num );
00762                                 mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_Material, material, block_num );
00763                                 mesgsys->getU8Fast(  _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); 
00764                                 mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num );
00765                                 length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
00766                                 mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num);
00767 
00768                                 mTotalCRC = crc;
00769 
00770                                 // Owner ID used for sound muting or particle system muting
00771                                 setAttachedSound(audio_uuid, owner_id, gain, sound_flags);
00772 
00773                                 U8 old_material = getMaterial();
00774                                 if (old_material != material)
00775                                 {
00776                                         setMaterial(material);
00777                                         if (mDrawable.notNull())
00778                                         {
00779                                                 gPipeline.markMoved(mDrawable, FALSE); // undamped
00780                                         }
00781                                 }
00782                                 setClickAction(click_action);
00783 
00784                                 count = 0;
00785                                 LLVector4 collision_plane;
00786                                 
00787                                 switch(length)
00788                                 {
00789                                 case (60 + 16):
00790                                         // pull out collision normal for avatar
00791                                         htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
00792                                         ((LLVOAvatar*)this)->setFootPlane(collision_plane);
00793                                         count += sizeof(LLVector4);
00794                                 case 60:
00795                                         this_update_precision = 32;
00796                                         // this is a terse update
00797                                         // pos
00798                                         htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
00799                                         count += sizeof(LLVector3);
00800                                         // vel
00801                                         htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
00802                                         count += sizeof(LLVector3);
00803                                         // acc
00804                                         htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
00805                                         count += sizeof(LLVector3);
00806                                         // theta
00807                                         {
00808                                                 LLVector3 vec;
00809                                                 htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
00810                                                 new_rot.unpackFromVector3(vec);
00811                                         }
00812                                         count += sizeof(LLVector3);
00813                                         // omega
00814                                         htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
00815                                         if (new_angv.isExactlyZero())
00816                                         {
00817                                                 // reset rotation time
00818                                                 resetRot();
00819                                         }
00820                                         setAngularVelocity(new_angv);
00821 #if LL_DARWIN
00822                                         if (length == 76)
00823                                         {
00824                                                 setAngularVelocity(LLVector3::zero);
00825                                         }
00826 #endif
00827                                         break;
00828                                 case(32 + 16):
00829                                         // pull out collision normal for avatar
00830                                         htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
00831                                         ((LLVOAvatar*)this)->setFootPlane(collision_plane);
00832                                         count += sizeof(LLVector4);
00833                                 case 32:
00834                                         this_update_precision = 16;
00835                                         test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
00836 
00837                                         // This is a terse 16 update, so treat data as an array of U16's.
00838 #ifdef LL_BIG_ENDIAN
00839                                         htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
00840                                         val = valswizzle;
00841 #else
00842                                         val = (U16 *) &data[count];
00843 #endif
00844                                         count += sizeof(U16)*3;
00845                                         new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
00846                                         new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
00847                                         new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
00848 
00849 #ifdef LL_BIG_ENDIAN
00850                                         htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
00851                                         val = valswizzle;
00852 #else
00853                                         val = (U16 *) &data[count];
00854 #endif
00855                                         count += sizeof(U16)*3;
00856                                         setVelocity(LLVector3(U16_to_F32(val[VX], -size, size),
00857                                                                                                            U16_to_F32(val[VY], -size, size),
00858                                                                                                            U16_to_F32(val[VZ], -size, size)));
00859 
00860 #ifdef LL_BIG_ENDIAN
00861                                         htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
00862                                         val = valswizzle;
00863 #else
00864                                         val = (U16 *) &data[count];
00865 #endif
00866                                         count += sizeof(U16)*3;
00867                                         setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size),
00868                                                                                                                    U16_to_F32(val[VY], -size, size),
00869                                                                                                                    U16_to_F32(val[VZ], -size, size)));
00870 
00871 #ifdef LL_BIG_ENDIAN
00872                                         htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 4); 
00873                                         val = valswizzle;
00874 #else
00875                                         val = (U16 *) &data[count];
00876 #endif
00877                                         count += sizeof(U16)*4;
00878                                         new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
00879                                         new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
00880                                         new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
00881                                         new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
00882 
00883 #ifdef LL_BIG_ENDIAN
00884                                         htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
00885                                         val = valswizzle;
00886 #else
00887                                         val = (U16 *) &data[count];
00888 #endif
00889                                         new_angv.setVec(U16_to_F32(val[VX], -size, size),
00890                                                                                 U16_to_F32(val[VY], -size, size),
00891                                                                                 U16_to_F32(val[VZ], -size, size));
00892                                         if (new_angv.isExactlyZero())
00893                                         {
00894                                                 // reset rotation time
00895                                                 resetRot();
00896                                         }
00897                                         setAngularVelocity(new_angv);
00898                                         break;
00899 
00900                                 case 16:
00901                                         this_update_precision = 8;
00902                                         test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
00903                                         // this is a terse 8 update
00904                                         new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
00905                                         new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
00906                                         new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
00907 
00908                                         setVelocity(U8_to_F32(data[3], -size, size),
00909                                                                 U8_to_F32(data[4], -size, size),
00910                                                                 U8_to_F32(data[5], -size, size) );
00911 
00912                                         setAcceleration(U8_to_F32(data[6], -size, size),
00913                                                                         U8_to_F32(data[7], -size, size),
00914                                                                         U8_to_F32(data[8], -size, size) );
00915 
00916                                         new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
00917                                         new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
00918                                         new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
00919                                         new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
00920 
00921                                         new_angv.setVec(U8_to_F32(data[13], -size, size),
00922                                                                                 U8_to_F32(data[14], -size, size),
00923                                                                                 U8_to_F32(data[15], -size, size) );
00924                                         if (new_angv.isExactlyZero())
00925                                         {
00926                                                 // reset rotation time
00927                                                 resetRot();
00928                                         }
00929                                         setAngularVelocity(new_angv);
00930                                         break;
00931                                 }
00932 
00934                                 //
00935                                 // Here we handle data specific to the full message.
00936                                 //
00937 
00938                                 U32 flags;
00939                                 mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
00940                                 // clear all but local flags
00941                                 mFlags &= FLAGS_LOCAL;
00942                                 mFlags |= flags;
00943 
00944                                 U8 state;
00945                                 mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
00946                                 mState = state;
00947 
00948                                 // ...new objects that should come in selected need to be added to the selected list
00949                                 mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
00950 
00951                                 // Set all name value pairs
00952                                 S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue);
00953                                 if (nv_size > 0)
00954                                 {
00955                                         char* name_value_list = new char[nv_size];
00956                                         mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_NameValue, nv_size, name_value_list, block_num);
00957 
00958                                         setNameValueList(name_value_list);
00959 
00960                                         delete [] name_value_list;
00961                                 }
00962 
00963                                 // Clear out any existing generic data
00964                                 if (mData)
00965                                 {
00966                                         delete [] mData;
00967                                 }
00968 
00969                                 // Check for appended generic data
00970                                 S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data);
00971                                 if (data_size <= 0)
00972                                 {
00973                                         mData = NULL;
00974                                 }
00975                                 else
00976                                 {
00977                                         // ...has generic data
00978                                         mData = new U8[data_size];
00979                                         mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num);
00980                                 }
00981 
00982                                 S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text);
00983                                 if (text_size > 1)
00984                                 {
00985                                         // Setup object text
00986                                         if (!mText)
00987                                         {
00988                                                 mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
00989                                                 mText->setFont(LLFontGL::sSansSerif);
00990                                                 mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
00991                                                 mText->setMaxLines(-1);
00992                                                 mText->setSourceObject(this);
00993                                                 mText->setOnHUDAttachment(isHUDAttachment());
00994                                         }
00995 
00996                                         char temp_string[256];                  /* Flawfinder: ignore */                // not MAX_STRING, must hold 255 chars + \0
00997                                         mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, 256, temp_string, block_num );
00998                                         
00999                                         LLColor4U coloru;
01000                                         mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num);
01001 
01002                                         // alpha was flipped so that it zero encoded better
01003                                         coloru.mV[3] = 255 - coloru.mV[3];
01004                                         mText->setColor(LLColor4(coloru));
01005                                         mText->setStringUTF8(temp_string);
01006                                         
01007                                         if (mDrawable.notNull())
01008                                         {
01009                                                 setChanged(MOVED | SILHOUETTE);
01010                                                 gPipeline.markMoved(mDrawable, FALSE); // undamped
01011                                         }
01012                                 }
01013                                 else if (mText.notNull())
01014                                 {
01015                                         mText->markDead();
01016                                         mText = NULL;
01017                                 }
01018 
01019                                 char media_url[MAX_STRING+1];           /* Flawfinder: ignore */
01020                                 mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, MAX_STRING+1, media_url, block_num);
01021                                 //if (media_url[0])
01022                                 //{
01023                                 //      llinfos << "WEBONPRIM media_url " << media_url << llendl;
01024                                 //}
01025                                 if (!mMedia && media_url[0] != '\0')
01026                                 {
01027                                         retval |= MEDIA_URL_ADDED;
01028                                         mMedia = new LLViewerObjectMedia;
01029                                         mMedia->mMediaURL = media_url;
01030                                         mMedia->mMediaType = LLViewerObject::MEDIA_TYPE_WEB_PAGE;
01031                                         mMedia->mPassedWhitelist = FALSE;
01032                                 }
01033                                 else if (mMedia)
01034                                 {
01035                                         if (media_url[0] == '\0')
01036                                         {
01037                                                 retval |= MEDIA_URL_REMOVED;
01038                                                 delete mMedia;
01039                                                 mMedia = NULL;
01040                                         }
01041                                         else if (mMedia->mMediaURL != media_url)
01042                                         {
01043                                                 // We just added or changed a web page.
01044                                                 retval |= MEDIA_URL_UPDATED;
01045                                                 mMedia->mMediaURL = media_url;
01046                                                 mMedia->mPassedWhitelist = FALSE;
01047                                         }
01048                                 }
01049 
01050                                 //
01051                                 // Unpack particle system data
01052                                 //
01053                                 unpackParticleSource(block_num, owner_id);
01054 
01055                                 // Mark all extra parameters not used
01056                                 std::map<U16, ExtraParameter*>::iterator iter;
01057                                 for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
01058                                 {
01059                                         iter->second->in_use = FALSE;
01060                                 }
01061 
01062                                 // Unpack extra parameters
01063                                 S32 size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ExtraParams);
01064                                 if (size > 0)
01065                                 {
01066                                         U8 *buffer = new U8[size];
01067                                         mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ExtraParams, buffer, size, block_num);
01068                                         LLDataPackerBinaryBuffer dp(buffer, size);
01069 
01070                                         U8 num_parameters;
01071                                         dp.unpackU8(num_parameters, "num_params");
01072                                         U8 param_block[MAX_OBJECT_PARAMS_SIZE];
01073                                         for (U8 param=0; param<num_parameters; ++param)
01074                                         {
01075                                                 U16 param_type;
01076                                                 S32 param_size;
01077                                                 dp.unpackU16(param_type, "param_type");
01078                                                 dp.unpackBinaryData(param_block, param_size, "param_data");
01079                                                 //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl;
01080                                                 LLDataPackerBinaryBuffer dp2(param_block, param_size);
01081                                                 unpackParameterEntry(param_type, &dp2);
01082                                         }
01083                                         delete[] buffer;
01084                                 }
01085 
01086                                 for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
01087                                 {
01088                                         if (!iter->second->in_use)
01089                                         {
01090                                                 // Send an update message in case it was formerly in use
01091                                                 parameterChanged(iter->first, iter->second->data, FALSE, false);
01092                                         }
01093                                 }
01094 
01095                                 U8 joint_type = 0;
01096                                 mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_JointType, joint_type, block_num);
01097                                 if (joint_type)
01098                                 {
01099                                         // create new joint info 
01100                                         if (!mJointInfo)
01101                                         {
01102                                                 mJointInfo = new LLVOJointInfo;
01103                                         }
01104                                         mJointInfo->mJointType = (EHavokJointType) joint_type;
01105                                         mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointPivot, mJointInfo->mPivot, block_num);
01106                                         mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointAxisOrAnchor, mJointInfo->mAxisOrAnchor, block_num);
01107                                 }
01108                                 else if (mJointInfo)
01109                                 {
01110                                         // this joint info is no longer needed
01111                                         delete mJointInfo;
01112                                         mJointInfo = NULL;
01113                                 }
01114 
01115                                 break;
01116                         }
01117 
01118                 case OUT_TERSE_IMPROVED:
01119                         {
01120 #ifdef DEBUG_UPDATE_TYPE
01121                                 llinfos << "TI:" << getID() << llendl;
01122 #endif
01123                                 length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
01124                                 mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num);
01125                                 count = 0;
01126                                 LLVector4 collision_plane;
01127                                 
01128                                 switch(length)
01129                                 {
01130                                 case(60 + 16):
01131                                         // pull out collision normal for avatar
01132                                         htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
01133                                         ((LLVOAvatar*)this)->setFootPlane(collision_plane);
01134                                         count += sizeof(LLVector4);
01135                                 case 60:
01136                                         // this is a terse 32 update
01137                                         // pos
01138                                         this_update_precision = 32;
01139                                         htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
01140                                         count += sizeof(LLVector3);
01141                                         // vel
01142                                         htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
01143                                         count += sizeof(LLVector3);
01144                                         // acc
01145                                         htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
01146                                         count += sizeof(LLVector3);
01147                                         // theta
01148                                         {
01149                                                 LLVector3 vec;
01150                                                 htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
01151                                                 new_rot.unpackFromVector3(vec);
01152                                         }
01153                                         count += sizeof(LLVector3);
01154                                         // omega
01155                                         htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
01156                                         if (new_angv.isExactlyZero())
01157                                         {
01158                                                 // reset rotation time
01159                                                 resetRot();
01160                                         }
01161                                         setAngularVelocity(new_angv);
01162 #if LL_DARWIN
01163                                         if (length == 76)
01164                                         {
01165                                                 setAngularVelocity(LLVector3::zero);
01166                                         }
01167 #endif
01168                                         break;
01169                                 case(32 + 16):
01170                                         // pull out collision normal for avatar
01171                                         htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
01172                                         ((LLVOAvatar*)this)->setFootPlane(collision_plane);
01173                                         count += sizeof(LLVector4);
01174                                 case 32:
01175                                         // this is a terse 16 update
01176                                         this_update_precision = 16;
01177                                         test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
01178 
01179 #ifdef LL_BIG_ENDIAN
01180                                         htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
01181                                         val = valswizzle;
01182 #else
01183                                         val = (U16 *) &data[count];
01184 #endif
01185                                         count += sizeof(U16)*3;
01186                                         new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
01187                                         new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
01188                                         new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
01189 
01190 #ifdef LL_BIG_ENDIAN
01191                                         htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
01192                                         val = valswizzle;
01193 #else
01194                                         val = (U16 *) &data[count];
01195 #endif
01196                                         count += sizeof(U16)*3;
01197                                         setVelocity(U16_to_F32(val[VX], -size, size),
01198                                                                 U16_to_F32(val[VY], -size, size),
01199                                                                 U16_to_F32(val[VZ], -size, size));
01200 
01201 #ifdef LL_BIG_ENDIAN
01202                                         htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
01203                                         val = valswizzle;
01204 #else
01205                                         val = (U16 *) &data[count];
01206 #endif
01207                                         count += sizeof(U16)*3;
01208                                         setAcceleration(U16_to_F32(val[VX], -size, size),
01209                                                                         U16_to_F32(val[VY], -size, size),
01210                                                                         U16_to_F32(val[VZ], -size, size));
01211 
01212 #ifdef LL_BIG_ENDIAN
01213                                         htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8); 
01214                                         val = valswizzle;
01215 #else
01216                                         val = (U16 *) &data[count];
01217 #endif
01218                                         count += sizeof(U16)*4;
01219                                         new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
01220                                         new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
01221                                         new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
01222                                         new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
01223 
01224 #ifdef LL_BIG_ENDIAN
01225                                         htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); 
01226                                         val = valswizzle;
01227 #else
01228                                         val = (U16 *) &data[count];
01229 #endif
01230                                         setAngularVelocity(     U16_to_F32(val[VX], -size, size),
01231                                                                                 U16_to_F32(val[VY], -size, size),
01232                                                                                 U16_to_F32(val[VZ], -size, size));
01233                                         break;
01234 
01235                                 case 16:
01236                                         // this is a terse 8 update
01237                                         this_update_precision = 8;
01238                                         test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
01239                                         new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
01240                                         new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
01241                                         new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
01242 
01243                                         setVelocity(U8_to_F32(data[3], -size, size),
01244                                                                 U8_to_F32(data[4], -size, size),
01245                                                                 U8_to_F32(data[5], -size, size) );
01246 
01247                                         setAcceleration(U8_to_F32(data[6], -size, size),
01248                                                                         U8_to_F32(data[7], -size, size),
01249                                                                         U8_to_F32(data[8], -size, size) );
01250 
01251                                         new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
01252                                         new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
01253                                         new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
01254                                         new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
01255 
01256                                         setAngularVelocity(     U8_to_F32(data[13], -size, size),
01257                                                                                 U8_to_F32(data[14], -size, size),
01258                                                                                 U8_to_F32(data[15], -size, size) );
01259                                         break;
01260                                 }
01261 
01262                                 U8 state;
01263                                 mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
01264                                 mState = state;
01265                                 break;
01266                         }
01267 
01268                 default:
01269                         break;
01270 
01271                 }
01272         }
01273         else
01274         {
01275                 // handle the compressed case
01276                 LLUUID sound_uuid;
01277                 LLUUID  owner_id;
01278                 F32    gain = 0;
01279                 U8     sound_flags = 0;
01280                 F32             cutoff = 0;
01281 
01282                 U16 val[4];
01283 
01284                 U8              state;
01285 
01286                 dp->unpackU8(state, "State");
01287                 mState = state;
01288 
01289                 switch(update_type)
01290                 {
01291                         case OUT_TERSE_IMPROVED:
01292                         {
01293 #ifdef DEBUG_UPDATE_TYPE
01294                                 llinfos << "CompTI:" << getID() << llendl;
01295 #endif
01296                                 U8              value;
01297                                 dp->unpackU8(value, "agent");
01298                                 if (value)
01299                                 {
01300                                         LLVector4 collision_plane;
01301                                         dp->unpackVector4(collision_plane, "Plane");
01302                                         ((LLVOAvatar*)this)->setFootPlane(collision_plane);
01303                                 }
01304                                 test_pos_parent = getPosition();
01305                                 dp->unpackVector3(new_pos_parent, "Pos");
01306                                 dp->unpackU16(val[VX], "VelX");
01307                                 dp->unpackU16(val[VY], "VelY");
01308                                 dp->unpackU16(val[VZ], "VelZ");
01309                                 setVelocity(U16_to_F32(val[VX], -128.f, 128.f),
01310                                                         U16_to_F32(val[VY], -128.f, 128.f),
01311                                                         U16_to_F32(val[VZ], -128.f, 128.f));
01312                                 dp->unpackU16(val[VX], "AccX");
01313                                 dp->unpackU16(val[VY], "AccY");
01314                                 dp->unpackU16(val[VZ], "AccZ");
01315                                 setAcceleration(U16_to_F32(val[VX], -64.f, 64.f),
01316                                                                 U16_to_F32(val[VY], -64.f, 64.f),
01317                                                                 U16_to_F32(val[VZ], -64.f, 64.f));
01318 
01319                                 dp->unpackU16(val[VX], "ThetaX");
01320                                 dp->unpackU16(val[VY], "ThetaY");
01321                                 dp->unpackU16(val[VZ], "ThetaZ");
01322                                 dp->unpackU16(val[VS], "ThetaS");
01323                                 new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
01324                                 new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
01325                                 new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
01326                                 new_rot.mQ[VS] = U16_to_F32(val[VS], -1.f, 1.f);
01327                                 dp->unpackU16(val[VX], "AccX");
01328                                 dp->unpackU16(val[VY], "AccY");
01329                                 dp->unpackU16(val[VZ], "AccZ");
01330                                 setAngularVelocity(     U16_to_F32(val[VX], -64.f, 64.f),
01331                                                                         U16_to_F32(val[VY], -64.f, 64.f),
01332                                                                         U16_to_F32(val[VZ], -64.f, 64.f));
01333                         }
01334                         break;
01335                         case OUT_FULL_COMPRESSED:
01336                         case OUT_FULL_CACHED:
01337                         {
01338 #ifdef DEBUG_UPDATE_TYPE
01339                                 llinfos << "CompFull:" << getID() << llendl;
01340 #endif
01341                                 dp->unpackU32(crc, "CRC");
01342                                 mTotalCRC = crc;
01343                                 dp->unpackU8(material, "Material");
01344                                 U8 old_material = getMaterial();
01345                                 if (old_material != material)
01346                                 {
01347                                         setMaterial(material);
01348                                         if (mDrawable.notNull())
01349                                         {
01350                                                 gPipeline.markMoved(mDrawable, FALSE); // undamped
01351                                         }
01352                                 }
01353                                 dp->unpackU8(click_action, "ClickAction");
01354                                 setClickAction(click_action);
01355                                 dp->unpackVector3(new_scale, "Scale");
01356                                 dp->unpackVector3(new_pos_parent, "Pos");
01357                                 LLVector3 vec;
01358                                 dp->unpackVector3(vec, "Rot");
01359                                 new_rot.unpackFromVector3(vec);
01360                                 setAcceleration(LLVector3::zero);
01361 
01362                                 U32 value;
01363                                 dp->unpackU32(value, "SpecialCode");
01364                                 dp->setPassFlags(value);
01365                                 dp->unpackUUID(owner_id, "Owner");
01366 
01367                                 if (value & 0x80)
01368                                 {
01369                                         dp->unpackVector3(vec, "Omega");
01370                                         setAngularVelocity(vec);
01371                                 }
01372 
01373                                 if (value & 0x20)
01374                                 {
01375                                         dp->unpackU32(parent_id, "ParentID");
01376                                 }
01377                                 else
01378                                 {
01379                                         parent_id = 0;
01380                                 }
01381 
01382                                 S32 sp_size;
01383                                 U32 size;
01384                                 if (value & 0x2)
01385                                 {
01386                                         sp_size = 1;
01387                                         delete [] mData;
01388                                         mData = new U8[1];
01389                                         dp->unpackU8(((U8*)mData)[0], "TreeData");
01390                                 }
01391                                 else if (value & 0x1)
01392                                 {
01393                                         dp->unpackU32(size, "ScratchPadSize");
01394                                         delete [] mData;
01395                                         mData = new U8[size];
01396                                         dp->unpackBinaryData((U8 *)mData, sp_size, "PartData");
01397                                 }
01398                                 else
01399                                 {
01400                                         mData = NULL;
01401                                 }
01402 
01403                                 // Setup object text
01404                                 if (!mText)
01405                                 {
01406                                         mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
01407                                         mText->setFont(LLFontGL::sSansSerif);
01408                                         mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
01409                                         mText->setMaxLines(-1); // Set to match current agni behavior.
01410                                         mText->setSourceObject(this);
01411                                         mText->setOnHUDAttachment(isHUDAttachment());
01412                                 }
01413 
01414                                 if (value & 0x4)
01415                                 {
01416                                         std::string temp_string;
01417                                         dp->unpackString(temp_string, "Text");
01418                                         LLColor4U coloru;
01419                                         dp->unpackBinaryDataFixed(coloru.mV, 4, "Color");
01420                                         coloru.mV[3] = 255 - coloru.mV[3];
01421                                         mText->setColor(LLColor4(coloru));
01422                                         mText->setStringUTF8(temp_string);
01423 
01424                                         setChanged(TEXTURE);
01425                                 }
01426                                 else
01427                                 {
01428                                         mText->markDead();
01429                                         mText = NULL;
01430                                 }
01431 
01432                                 if (value & 0x200)
01433                                 {
01434                                         std::string media_url;
01435                                         dp->unpackString(media_url, "MediaURL");
01436                                         if (!mMedia)
01437                                         {
01438                                                 retval |= MEDIA_URL_ADDED;
01439                                                 mMedia = new LLViewerObjectMedia;
01440                                                 mMedia->mMediaURL = media_url;
01441                                                 mMedia->mMediaType = LLViewerObject::MEDIA_TYPE_WEB_PAGE;
01442                                                 mMedia->mPassedWhitelist = FALSE;
01443                                         }
01444                                         else if (mMedia->mMediaURL != media_url)
01445                                         {
01446                                                 retval |= MEDIA_URL_UPDATED;
01447                                                 mMedia->mMediaURL = media_url;
01448                                                 mMedia->mPassedWhitelist = FALSE;
01449                                         }
01450                                 }
01451                                 else if (mMedia)
01452                                 {
01453                                         retval |= MEDIA_URL_REMOVED;
01454                                         delete mMedia;
01455                                         mMedia = NULL;
01456                                 }
01457 
01458                                 //
01459                                 // Unpack particle system data
01460                                 //
01461                                 if (value & 0x8)
01462                                 {
01463                                         unpackParticleSource(*dp, owner_id);
01464                                 }
01465                                 else
01466                                 {
01467                                         deleteParticleSource();
01468                                 }
01469                                 
01470                                 // Mark all extra parameters not used
01471                                 std::map<U16, ExtraParameter*>::iterator iter;
01472                                 for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
01473                                 {
01474                                         iter->second->in_use = FALSE;
01475                                 }
01476 
01477                                 // Unpack extra params
01478                                 U8 num_parameters;
01479                                 dp->unpackU8(num_parameters, "num_params");
01480                                 U8 param_block[MAX_OBJECT_PARAMS_SIZE];
01481                                 for (U8 param=0; param<num_parameters; ++param)
01482                                 {
01483                                         U16 param_type;
01484                                         S32 param_size;
01485                                         dp->unpackU16(param_type, "param_type");
01486                                         dp->unpackBinaryData(param_block, param_size, "param_data");
01487                                         //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl;
01488                                         LLDataPackerBinaryBuffer dp2(param_block, param_size);
01489                                         unpackParameterEntry(param_type, &dp2);
01490                                 }
01491 
01492                                 for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
01493                                 {
01494                                         if (!iter->second->in_use)
01495                                         {
01496                                                 // Send an update message in case it was formerly in use
01497                                                 parameterChanged(iter->first, iter->second->data, FALSE, false);
01498                                         }
01499                                 }
01500 
01501                                 if (value & 0x10)
01502                                 {
01503                                         dp->unpackUUID(sound_uuid, "SoundUUID");
01504                                         dp->unpackF32(gain, "SoundGain");
01505                                         dp->unpackU8(sound_flags, "SoundFlags");
01506                                         dp->unpackF32(cutoff, "SoundRadius");
01507                                 }
01508 
01509                                 if (value & 0x100)
01510                                 {
01511                                         std::string name_value_list;
01512                                         dp->unpackString(name_value_list, "NV");
01513 
01514                                         setNameValueList(name_value_list.c_str());
01515                                 }
01516 
01517                                 mTotalCRC = crc;
01518 
01519                                 setAttachedSound(sound_uuid, owner_id, gain, sound_flags);
01520 
01521                                 // only get these flags on updates from sim, not cached ones
01522                                 // Preload these five flags for every object.
01523                                 // Finer shades require the object to be selected, and the selection manager
01524                                 // stores the extended permission info.
01525                                 U32 flags;
01526                                 mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
01527                                 // keep local flags and overwrite remote-controlled flags
01528                                 mFlags = (mFlags & FLAGS_LOCAL) | flags;
01529 
01530                                         // ...new objects that should come in selected need to be added to the selected list
01531                                 mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
01532                         }
01533                         break;
01534 
01535                 default:
01536                         break;
01537                 }
01538         }
01539 
01540         //
01541         // Fix object parenting.
01542         //
01543         BOOL b_changed_status = FALSE;
01544 
01545         if (OUT_TERSE_IMPROVED != update_type)
01546         {
01547                 // We only need to update parenting on full updates, terse updates
01548                 // don't send parenting information.
01549                 if (!cur_parentp)
01550                 {
01551                         if (parent_id == 0)
01552                         {
01553                                 // No parent now, no parent in message -> do nothing
01554                         }
01555                         else
01556                         {
01557                                 // No parent now, new parent in message -> attach to that parent if possible
01558                                 LLUUID parent_uuid;
01559                                 LLViewerObjectList::getUUIDFromLocal(parent_uuid,
01560                                                                                                                 parent_id,
01561                                                                                                                 mesgsys->getSenderIP(),
01562                                                                                                                 mesgsys->getSenderPort());
01563 
01564                                 LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid);
01565 
01566                                 //
01567                                 // Check to see if we have the corresponding viewer object for the parent.
01568                                 //
01569                                 if (sent_parentp && sent_parentp->getParent() == this)
01570                                 {
01571                                         // Try to recover if we attempt to attach a parent to its child
01572                                         llwarns << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << llendl;
01573                                         this->removeChild(sent_parentp);
01574                                         sent_parentp->setDrawableParent(NULL);
01575                                 }
01576                                 
01577                                 if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead())
01578                                 {
01579                                         //
01580                                         // We have a viewer object for the parent, and it's not dead.
01581                                         // Do the actual reparenting here.
01582                                         //
01583 
01584                                         // new parent is valid
01585                                         b_changed_status = TRUE;
01586                                         // ...no current parent, so don't try to remove child
01587                                         if (mDrawable.notNull())
01588                                         {
01589                                                 if (mDrawable->isDead() || !mDrawable->getVObj())
01590                                                 {
01591                                                         llwarns << "Drawable is dead or no VObj!" << llendl;
01592                                                         sent_parentp->addChild(this);
01593                                                 }
01594                                                 else
01595                                                 {
01596                                                         if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 1
01597                                                         {
01598                                                                 // Bad, we got a cycle somehow.
01599                                                                 // Kill both the parent and the child, and
01600                                                                 // set cache misses for both of them.
01601                                                                 llwarns << "Attempting to recover from parenting cycle!" << llendl;
01602                                                                 llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl;
01603                                                                 llwarns << "Adding to cache miss list" << llendl;
01604                                                                 setParent(NULL);
01605                                                                 sent_parentp->setParent(NULL);
01606                                                                 getRegion()->addCacheMissFull(getLocalID());
01607                                                                 getRegion()->addCacheMissFull(sent_parentp->getLocalID());
01608                                                                 gObjectList.killObject(sent_parentp);
01609                                                                 gObjectList.killObject(this);
01610                                                                 return retval;
01611                                                         }
01612                                                         sent_parentp->addChild(this);
01613                                                         // make sure this object gets a non-damped update
01614                                                         if (sent_parentp->mDrawable.notNull())
01615                                                         {
01616                                                                 gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped
01617                                                         }
01618                                                 }
01619                                         }
01620                                         else
01621                                         {
01622                                                 sent_parentp->addChild(this);
01623                                         }
01624                                         
01625                                         // Show particles, icon and HUD
01626                                         hideExtraDisplayItems( FALSE );
01627 
01628                                         setChanged(MOVED | SILHOUETTE);
01629                                 }
01630                                 else
01631                                 {
01632                                         //
01633                                         // No corresponding viewer object for the parent, put the various
01634                                         // pieces on the orphan list.
01635                                         //
01636                                         
01637                                         //parent_id
01638                                         U32 ip = mesgsys->getSenderIP();
01639                                         U32 port = mesgsys->getSenderPort();
01640                                         
01641                                         gObjectList.orphanize(this, parent_id, ip, port);
01642 
01643                                         // Hide particles, icon and HUD
01644                                         hideExtraDisplayItems( TRUE );
01645                                 }
01646                         }
01647                 }
01648                 else
01649                 {
01650                         // BUG: this is a bad assumption once border crossing is alowed
01651                         if (  (parent_id == cur_parentp->mLocalID)
01652                                 &&(update_type == OUT_TERSE_IMPROVED))
01653                         {
01654                                 // Parent now, same parent in message -> do nothing
01655 
01656                                 // Debugging for suspected problems with local ids.
01657                                 //LLUUID parent_uuid;
01658                                 //LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort() );
01659                                 //if (parent_uuid != cur_parentp->getID() )
01660                                 //{
01661                                 //      llerrs << "Local ID match but UUID mismatch of viewer object" << llendl;
01662                                 //}
01663                         }
01664                         else
01665                         {
01666                                 // Parented now, different parent in message
01667                                 LLViewerObject *sent_parentp;
01668                                 if (parent_id == 0)
01669                                 {
01670                                         //
01671                                         // This object is no longer parented, we sent in a zero parent ID.
01672                                         //
01673                                         sent_parentp = NULL;
01674                                 }
01675                                 else
01676                                 {
01677                                         LLUUID parent_uuid;
01678                                         LLViewerObjectList::getUUIDFromLocal(parent_uuid,
01679                                                                                                                 parent_id,
01680                                                                                                                 gMessageSystem->getSenderIP(),
01681                                                                                                                 gMessageSystem->getSenderPort());
01682                                         sent_parentp = gObjectList.findObject(parent_uuid);
01683                                         
01684                                         if (isAvatar())
01685                                         {
01686                                                 // This logic is meant to handle the case where a sitting avatar has reached a new sim
01687                                                 // ahead of the object she was sitting on (which is common as objects are transfered through
01688                                                 // a slower route than agents)...
01689                                                 // In this case, the local id for the object will not be valid, since the viewer has not received
01690                                                 // a full update for the object from that sim yet, so we assume that the agent is still sitting
01691                                                 // where she was originally. --RN
01692                                                 if (!sent_parentp)
01693                                                 {
01694                                                         sent_parentp = cur_parentp;
01695                                                 }
01696                                         }
01697                                         else if (!sent_parentp)
01698                                         {
01699                                                 //
01700                                                 // Switching parents, but we don't know the new parent.
01701                                                 //
01702                                                 U32 ip = mesgsys->getSenderIP();
01703                                                 U32 port = mesgsys->getSenderPort();
01704 
01705                                                 // We're an orphan, flag things appropriately.
01706                                                 gObjectList.orphanize(this, parent_id, ip, port);
01707                                         }
01708                                 }
01709 
01710                                 // Reattach if possible.
01711                                 if (sent_parentp && sent_parentp != cur_parentp && sent_parentp != this)
01712                                 {
01713                                         // New parent is valid, detach and reattach
01714                                         b_changed_status = TRUE;
01715                                         if (mDrawable.notNull())
01716                                         {
01717                                                 if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 2
01718                                                 {
01719                                                         // Bad, we got a cycle somehow.
01720                                                         // Kill both the parent and the child, and
01721                                                         // set cache misses for both of them.
01722                                                         llwarns << "Attempting to recover from parenting cycle!" << llendl;
01723                                                         llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl;
01724                                                         llwarns << "Adding to cache miss list" << llendl;
01725                                                         setParent(NULL);
01726                                                         sent_parentp->setParent(NULL);
01727                                                         getRegion()->addCacheMissFull(getLocalID());
01728                                                         getRegion()->addCacheMissFull(sent_parentp->getLocalID());
01729                                                         gObjectList.killObject(sent_parentp);
01730                                                         gObjectList.killObject(this);
01731                                                         return retval;
01732                                                 }
01733                                                 // make sure this object gets a non-damped update
01734                                         }
01735                                         cur_parentp->removeChild(this);
01736                                         sent_parentp->addChild(this);
01737                                         setChanged(MOVED | SILHOUETTE);
01738                                         sent_parentp->setChanged(MOVED | SILHOUETTE);
01739                                         if (sent_parentp->mDrawable.notNull())
01740                                         {
01741                                                 gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped
01742                                         }
01743                                 }
01744                                 else if (!sent_parentp)
01745                                 {
01746                                         bool remove_parent = true;
01747                                         // No new parent, or the parent that we sent doesn't exist on the viewer.
01748                                         LLViewerObject *parentp = (LLViewerObject *)getParent();
01749                                         if (parentp)
01750                                         {
01751                                                 if (parentp->getRegion() != getRegion())
01752                                                 {
01753                                                         // This is probably an object flying across a region boundary, the
01754                                                         // object probably ISN'T being reparented, but just got an object
01755                                                         // update out of order (child update before parent).
01756                                                         //llinfos << "Don't reparent object handoffs!" << llendl;
01757                                                         remove_parent = false;
01758                                                 }
01759                                         }
01760 
01761                                         if (remove_parent)
01762                                         {
01763                                                 b_changed_status = TRUE;
01764                                                 if (mDrawable.notNull())
01765                                                 {
01766                                                         // clear parent to removeChild can put the drawable on the damped list
01767                                                         setDrawableParent(NULL); // LLViewerObject::processUpdateMessage 3
01768                                                 }
01769 
01770                                                 cur_parentp->removeChild(this);
01771 
01772                                                 if (mJointInfo && !parent_id)
01773                                                 {
01774                                                         // since this object is no longer parent-relative
01775                                                         // we make sure we delete any joint info
01776                                                         delete mJointInfo;
01777                                                         mJointInfo = NULL;
01778                                                 }
01779 
01780                                                 setChanged(MOVED | SILHOUETTE);
01781 
01782                                                 if (mDrawable.notNull())
01783                                                 {
01784                                                         // make sure this object gets a non-damped update
01785                                                         gPipeline.markMoved(mDrawable, FALSE); // undamped
01786                                                 }
01787                                         }
01788                                 }
01789                         }
01790                 }
01791         }
01792 
01793         new_rot.normQuat();
01794 
01795         if (gPingInterpolate)
01796         { 
01797                 LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender());
01798                 if (cdp)
01799                 {
01800                         F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped);
01801                         LLVector3 diff = getVelocity() * (0.5f*mTimeDilation*(gFrameDTClamped + ((F32)ping_delay)*0.001f)); 
01802                         new_pos_parent += diff;
01803                 }
01804                 else
01805                 {
01806                         llwarns << "findCircuit() returned NULL; skipping interpolation" << llendl;
01807                 }
01808         }
01809 
01811         //
01812         // Set the generic change flags...
01813         //
01814         //
01815 
01816         U32 packet_id = mesgsys->getCurrentRecvPacketID(); 
01817         if (packet_id < mLatestRecvPacketID && 
01818                 mLatestRecvPacketID - packet_id < 65536)
01819         {
01820                 //skip application of this message, it's old
01821                 return retval;
01822         }
01823 
01824         mLatestRecvPacketID = packet_id;
01825 
01826         // Set the change flags for scale
01827         if (new_scale != getScale())
01828         {
01829                 setChanged(SCALED | SILHOUETTE);
01830                 setScale(new_scale);  // Must follow setting permYouOwner()
01831         }
01832 
01833         // first, let's see if the new position is actually a change
01834 
01835         //static S32 counter = 0;
01836 
01837         F32 vel_mag_sq = getVelocity().magVecSquared();
01838         F32 accel_mag_sq = getAcceleration().magVecSquared();
01839 
01840         if (  ((b_changed_status)||(test_pos_parent != new_pos_parent))
01841                 ||(  (!isSelected())
01842                    &&(  (vel_mag_sq != 0.f)
01843                           ||(accel_mag_sq != 0.f)
01844                           ||(this_update_precision > mBestUpdatePrecision))))
01845         {
01846                 mBestUpdatePrecision = this_update_precision;
01847                 setPositionParent(new_pos_parent);
01848 
01849                 if (mParent && ((LLViewerObject*)mParent)->isAvatar())
01850                 {
01851                         // we have changed the position of an attachment, so we need to clamp it
01852                         LLVOAvatar *avatar = (LLVOAvatar*)mParent;
01853 
01854                         avatar->clampAttachmentPositions();
01855                 }
01856         }
01857 
01858         if (new_rot != mLastRot)
01859         {
01860                 mLastRot = new_rot;
01861                 setChanged(ROTATED | SILHOUETTE);
01862                 setRotation(new_rot);
01863                 resetRot();
01864         }
01865 
01866 
01867         if ( gShowObjectUpdates )
01868         {
01869                 if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->mIsSelf))
01870                         && mRegionp)
01871                 {
01872                         LLViewerObject* object = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, mRegionp);
01873                         LLVOTextBubble* bubble = (LLVOTextBubble*) object;
01874 
01875                         if (update_type == OUT_TERSE_IMPROVED)
01876                         {
01877                                 bubble->mColor.setVec(0.f, 0.f, 1.f, 1.f);
01878                         }
01879                         else
01880                         {
01881                                 bubble->mColor.setVec(1.f, 0.f, 0.f, 1.f);
01882                         }
01883                         object->setPositionGlobal(getPositionGlobal());
01884                         gPipeline.addObject(object);
01885                 }
01886         }
01887 
01888         if ((0.0f == vel_mag_sq) && 
01889                 (0.0f == accel_mag_sq) &&
01890                 (0.0f == getAngularVelocity().magVecSquared()))
01891         {
01892                 mStatic = TRUE; // This object doesn't move!
01893         }
01894         else
01895         {
01896                 mStatic = FALSE;
01897         }
01898 
01899 // BUG: This code leads to problems during group rotate and any scale operation.
01900 // Small discepencies between the simulator and viewer representations cause the 
01901 // selection center to creep, leading to objects moving around the wrong center.
01902 // 
01903 // Removing this, however, means that if someone else drags an object you have
01904 // selected, your selection center and dialog boxes will be wrong.  It also means
01905 // that higher precision information on selected objects will be ignored.
01906 //
01907 // I believe the group rotation problem is fixed.  JNC 1.21.2002
01908 //
01909         // Additionally, if any child is selected, need to update the dialogs and selection
01910         // center.
01911         BOOL needs_refresh = mUserSelected;
01912         LLViewerObject *childp;
01913         for (U32 i = 0; i < mChildList.size(); i++)
01914         {
01915                 childp = mChildList[i];
01916                 needs_refresh = needs_refresh || childp->mUserSelected;
01917         }
01918 
01919         if (needs_refresh)
01920         {
01921                 gSelectMgr->updateSelectionCenter();
01922                 dialog_refresh_all();
01923         } 
01924 
01925 
01926         // Mark update time as approx. now, with the ping delay.
01927         // Ping delay is off because it's not set for velocity interpolation, causing
01928         // much jumping and hopping around...
01929 
01930 //      U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay();
01931         mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
01932         mLastMessageUpdateSecs = LLFrameTimer::getElapsedSeconds();
01933         if (mDrawable.notNull())
01934         {
01935                 // Don't clear invisibility flag on update if still orphaned!
01936                 if (mDrawable->isState(LLDrawable::FORCE_INVISIBLE) && !mOrphaned)
01937                 {
01938 //                      lldebugs << "Clearing force invisible: " << mID << ":" << getPCodeString() << ":" << getPositionAgent() << llendl;
01939                         mDrawable->setState(LLDrawable::CLEAR_INVISIBLE);
01940                 }
01941         }
01942 
01943         // Update special hover cursor status
01944         bool special_hover_cursor = specialHoverCursor();
01945         if (old_special_hover_cursor != special_hover_cursor
01946                 && mDrawable.notNull())
01947         {
01948                 mDrawable->updateSpecialHoverCursor(special_hover_cursor);
01949         }
01950 
01951         return retval;
01952 }
01953 
01954 BOOL LLViewerObject::isActive() const
01955 {
01956         return TRUE;
01957 }
01958 
01959 BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
01960 {
01961         if (mDead)
01962         {
01963                 // It's dead.  Don't update it.
01964                 return TRUE;
01965         }
01966 
01967         // CRO - don't velocity interp linked objects!
01968         // Leviathan - but DO velocity interp joints
01969         if (!mStatic && gVelocityInterpolate && !isSelected())
01970         {
01971                 // calculate dt from last update
01972                 F32 dt_raw = (F32)(time - mLastInterpUpdateSecs);
01973                 F32 dt = mTimeDilation * dt_raw;
01974 
01975                 if (!mUserSelected && !mJointInfo)
01976                 {
01977                         applyAngularVelocity(dt);
01978                 }
01979 
01980                 LLViewerObject *parentp = (LLViewerObject *) getParent();
01981                 if (mJointInfo)
01982                 {
01983                         if (parentp)
01984                         {
01985                                 // do parent-relative stuff
01986                                 LLVector3 ang_vel = getAngularVelocity();
01987                                 F32 omega = ang_vel.magVecSquared();
01988                                 F32 angle = 0.0f;
01989                                 LLQuaternion dQ;
01990                                 if (omega > 0.00001f)
01991                                 {
01992                                         omega = sqrt(omega);
01993                                         angle = omega * dt;
01994                                         dQ.setQuat(angle, ang_vel);
01995                                 }
01996                                 LLVector3 pos = getPosition();
01997         
01998                                 if (HJT_HINGE == mJointInfo->mJointType)
01999                                 {
02000                                         // hinge = uniform circular motion
02001                                         LLVector3 parent_pivot = getVelocity();
02002                                         LLVector3 parent_axis = getAcceleration();
02003         
02004                                         angle = dt * (ang_vel * mJointInfo->mAxisOrAnchor);     // AxisOrAnchor = axis
02005                                         dQ.setQuat(angle, mJointInfo->mAxisOrAnchor);           // AxisOrAnchor = axis
02006                                         LLVector3 pivot_offset = pos - mJointInfo->mPivot;      // pos in pivot-frame
02007                                         pivot_offset = pivot_offset * dQ;                                       // new rotated pivot-frame pos
02008                                         pos = mJointInfo->mPivot + pivot_offset;                        // parent-frame
02009                                         LLViewerObject::setPosition(pos);
02010                                         LLQuaternion Q_PC = getRotation();
02011                                         setRotation(Q_PC * dQ);
02012                                         mLastInterpUpdateSecs = time;
02013                                 }
02014                                 else if (HJT_POINT == mJointInfo->mJointType)
02015                                                 // || HJT_LPOINT == mJointInfo->mJointType)
02016                                 {
02017                                         // point-to-point = spin about axis and uniform circular motion
02018                                         //                                      of axis about the pivot point
02019                                         //
02020                                         // NOTE: this interpolation scheme is not quite good enough to
02021                                         // reduce the bandwidth -- needs a gravitational correction. 
02022                                         // Similarly for hinges with axes that deviate from vertical.
02023         
02024                                         LLQuaternion Q_PC = getRotation();
02025                                         Q_PC = Q_PC * dQ;
02026                                         setRotation(Q_PC);
02027 
02028                                         LLVector3 pivot_to_child = - mJointInfo->mAxisOrAnchor; // AxisOrAnchor = anchor
02029                                         pos = mJointInfo->mPivot + pivot_to_child * Q_PC;
02030                                         LLViewerObject::setPosition(pos);
02031                                         mLastInterpUpdateSecs = time;
02032                                 }
02033                                 /* else if (HJT_WHEEL == mJointInfo->mJointInfo)
02034                                 {
02035                                         // wheel = uniform rotation about axis, with linear
02036                                         //                 velocity interpolation (if any)
02037                                         LLVector3 parent_axis = getAcceleration();      // HACK -- accel stores the parent-axis (parent-frame)
02038         
02039                                         LLQuaternion Q_PC = getRotation();
02040         
02041                                         angle = dt * (parent_axis * ang_vel);
02042                                         dQ.setQuat(angle, parent_axis);
02043         
02044                                         Q_PC = Q_PC * dQ;
02045                                         setRotation(Q_PC);
02046 
02047                                         pos = getPosition() + dt * getVelocity();
02048                                         LLViewerObject::setPosition(pos);
02049                                         mLastInterpUpdateSecs = time;
02050                                 }*/
02051                         }
02052                 }
02053                 else if (isAttachment())
02054                 {
02055                         mLastInterpUpdateSecs = time;
02056                         return TRUE;
02057                 }
02058                 else
02059                 {
02060                         // linear motion
02061                         // HAVOK_TIMESTEP is used below to correct for the fact that the velocity in object
02062                         // updates represents the average velocity of the last timestep, rather than the final velocity.
02063                         // the time dilation above should guarrantee that dt is never less than HAVOK_TIMESTEP, theoretically
02064                         // 
02065                         // There is a problem here if dt is negative. . .
02066 
02067                         // *TODO: should also wrap linear accel/velocity in check
02068                         // to see if object is selected, instead of explicitly
02069                         // zeroing it out       
02070                         LLVector3 accel = getAcceleration();
02071                         LLVector3 vel   = getVelocity();
02072                         
02073                         if (!(accel.isExactlyZero() && vel.isExactlyZero()))
02074                         {
02075                                 LLVector3 pos   = (vel + (0.5f * (dt-HAVOK_TIMESTEP)) * accel) * dt;    
02076                         
02077                                 // region local  
02078                                 setPositionRegion(pos + getPositionRegion());
02079                                 setVelocity(vel + accel*dt);    
02080                                 
02081                                 // for objects that are spinning but not translating, make sure to flag them as having moved
02082                                 setChanged(MOVED | SILHOUETTE);
02083                         }
02084                         
02085                         mLastInterpUpdateSecs = time;
02086                 }
02087         }
02088 
02089         if (gNoRender)
02090         {
02091                 // Skip drawable stuff if not rendering.
02092                 return TRUE;
02093         }
02094 
02095         updateDrawable(FALSE);
02096 
02097         return TRUE;
02098 }
02099 
02100 
02101 BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size)
02102 {
02103         LLMemType mt(LLMemType::MTYPE_OBJECT);
02104         
02105         delete [] mData;
02106 
02107         if (datap)
02108         {
02109                 mData = new U8[data_size];
02110                 if (!mData)
02111                 {
02112                         return FALSE;
02113                 }
02114                 memcpy(mData, datap, data_size);                /* Flawfinder: ignore */
02115         }
02116         return TRUE;
02117 }
02118 
02119 // delete an item in the inventory, but don't tell the server. This is
02120 // used internally by remove, update, and savescript.
02121 // This will only delete the first item with an item_id in the list
02122 void LLViewerObject::deleteInventoryItem(const LLUUID& item_id)
02123 {
02124         if(mInventory)
02125         {
02126                 InventoryObjectList::iterator it = mInventory->begin();
02127                 InventoryObjectList::iterator end = mInventory->end();
02128                 for( ; it != end; ++it )
02129                 {
02130                         if((*it)->getUUID() == item_id)
02131                         {
02132                                 // This is safe only because we return immediatly.
02133                                 mInventory->erase(it); // will deref and delete it
02134                                 return;
02135                         }
02136                 }
02137                 doInventoryCallback();
02138         }
02139 }
02140 
02141 void LLViewerObject::doUpdateInventory(
02142         LLViewerInventoryItem* item,
02143         U8 key,
02144         bool is_new)
02145 {
02146         LLMemType mt(LLMemType::MTYPE_OBJECT);
02147 
02148         LLViewerInventoryItem* old_item = NULL;
02149         if(TASK_INVENTORY_ITEM_KEY == key)
02150         {
02151                 old_item = (LLViewerInventoryItem*)getInventoryObject(item->getUUID());
02152         }
02153         else if(TASK_INVENTORY_ASSET_KEY == key)
02154         {
02155                 old_item = getInventoryItemByAsset(item->getAssetUUID());
02156         }
02157         LLUUID item_id;
02158         LLUUID new_owner;
02159         LLUUID new_group;
02160         BOOL group_owned = FALSE;
02161         if(old_item)
02162         {
02163                 item_id = old_item->getUUID();
02164                 new_owner = old_item->getPermissions().getOwner();
02165                 new_group = old_item->getPermissions().getGroup();
02166                 group_owned = old_item->getPermissions().isGroupOwned();
02167                 old_item = NULL;
02168         }
02169         else
02170         {
02171                 item_id = item->getUUID();
02172         }
02173         if(!is_new && mInventory)
02174         {
02175                 // Attempt to update the local inventory. If we can get the
02176                 // object perm, we have perfect visibility, so we want the
02177                 // serial number to match. Otherwise, take our best guess and
02178                 // make sure that the serial number does not match.
02179                 deleteInventoryItem(item_id);
02180                 LLPermissions perm(item->getPermissions());
02181                 LLPermissions* obj_perm = gSelectMgr->findObjectPermissions(this);
02182                 bool is_atomic = ((S32)LLAssetType::AT_OBJECT == item->getType()) ? false : true;
02183                 if(obj_perm)
02184                 {
02185                         perm.setOwnerAndGroup(LLUUID::null, obj_perm->getOwner(), obj_perm->getGroup(), is_atomic);
02186                 }
02187                 else
02188                 {
02189                         if(group_owned)
02190                         {
02191                                 perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic);
02192                         }
02193                         else if(!new_owner.isNull())
02194                         {
02195                                 // The object used to be in inventory, so we can
02196                                 // assume the owner and group will match what they are
02197                                 // there.
02198                                 perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic);
02199                         }
02200                         // *FIX: can make an even better guess by using the mPermGroup flags
02201                         else if(permYouOwner())
02202                         {
02203                                 // best guess.
02204                                 perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
02205                                 --mInventorySerialNum;
02206                         }
02207                         else
02208                         {
02209                                 // dummy it up.
02210                                 perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
02211                                 --mInventorySerialNum;
02212                         }
02213                 }
02214                 LLViewerInventoryItem* new_item = new LLViewerInventoryItem(item);
02215                 new_item->setPermissions(perm);
02216                 mInventory->push_front(new_item);
02217                 doInventoryCallback();
02218                 ++mInventorySerialNum;
02219         }
02220 }
02221 
02222 // save a script, which involves removing the old one, and rezzing
02223 // in the new one. This method should be called with the asset id
02224 // of the new and old script AFTER the bytecode has been saved.
02225 void LLViewerObject::saveScript(
02226         const LLViewerInventoryItem* item,
02227         BOOL active,
02228         bool is_new)
02229 {
02230         LLMemType mt(LLMemType::MTYPE_OBJECT);
02231 
02232         /*
02233          * XXXPAM Investigate not making this copy.  Seems unecessary, but I'm unsure about the
02234          * interaction with doUpdateInventory() called below.
02235          */
02236         lldebugs << "LLViewerObject::saveScript() " << item->getUUID() << " " << item->getAssetUUID() << llendl;
02237         LLPointer<LLViewerInventoryItem> task_item =
02238                 new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
02239                                                                   item->getAssetUUID(), item->getType(),
02240                                                                   item->getInventoryType(),
02241                                                                   item->getName(), item->getDescription(),
02242                                                                   item->getSaleInfo(), item->getFlags(),
02243                                                                   item->getCreationDate());
02244         task_item->setTransactionID(item->getTransactionID());
02245 
02246         LLMessageSystem* msg = gMessageSystem;
02247         msg->newMessageFast(_PREHASH_RezScript);
02248         msg->nextBlockFast(_PREHASH_AgentData);
02249         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
02250         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
02251         msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
02252         msg->nextBlockFast(_PREHASH_UpdateBlock);
02253         msg->addU32Fast(_PREHASH_ObjectLocalID, (mLocalID));
02254         U8 enabled = active;
02255         msg->addBOOLFast(_PREHASH_Enabled, enabled);
02256         msg->nextBlockFast(_PREHASH_InventoryBlock);
02257         task_item->packMessage(msg);
02258         msg->sendReliable(mRegionp->getHost());
02259 
02260         // do the internal logic
02261         doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, is_new);
02262 }
02263 
02264 void LLViewerObject::moveInventory(const LLUUID& folder_id,
02265                                                                    const LLUUID& item_id)
02266 {
02267         lldebugs << "LLViewerObject::moveInventory " << item_id << llendl;
02268         LLMessageSystem* msg = gMessageSystem;
02269         msg->newMessageFast(_PREHASH_MoveTaskInventory);
02270         msg->nextBlockFast(_PREHASH_AgentData);
02271         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
02272         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
02273         msg->addUUIDFast(_PREHASH_FolderID, folder_id);
02274         msg->nextBlockFast(_PREHASH_InventoryData);
02275         msg->addU32Fast(_PREHASH_LocalID, mLocalID);
02276         msg->addUUIDFast(_PREHASH_ItemID, item_id);
02277         msg->sendReliable(mRegionp->getHost());
02278 
02279         LLInventoryObject* inv_obj = getInventoryObject(item_id);
02280         if(inv_obj)
02281         {
02282                 LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_obj;
02283                 if(!item->getPermissions().allowCopyBy(gAgent.getID()))
02284                 {
02285                         deleteInventoryItem(item_id);
02286                         ++mInventorySerialNum;
02287                 }
02288         }
02289 }
02290 
02291 void LLViewerObject::dirtyInventory()
02292 {
02293         // If there aren't any LLVOInventoryListeners, we won't be
02294         // able to update our mInventory when it comes back from the
02295         // simulator, so we should not clear the inventory either.
02296         if(mInventory && !mInventoryCallbacks.isEmpty())
02297         {
02298                 mInventory->clear(); // will deref and delete entries
02299                 delete mInventory;
02300                 mInventory = NULL;
02301                 mInventoryDirty = TRUE;
02302         }
02303 }
02304 
02305 void LLViewerObject::registerInventoryListener(LLVOInventoryListener* listener, void* user_data)
02306 {
02307         LLMemType mt(LLMemType::MTYPE_OBJECT);
02308         
02309         LLInventoryCallbackInfo* info = new LLInventoryCallbackInfo;
02310         info->mListener = listener;
02311         info->mInventoryData = user_data;
02312         mInventoryCallbacks.addData(info);
02313 }
02314 
02315 void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener)
02316 {
02317         if (listener == NULL) return;
02318         LLInventoryCallbackInfo* info;
02319         for (info = mInventoryCallbacks.getFirstData();
02320                 info;
02321                 info = mInventoryCallbacks.getNextData() )
02322         {
02323                 if (info->mListener == listener)
02324                 {
02325                         mInventoryCallbacks.deleteCurrentData();
02326                         break;
02327                 }
02328         }
02329 }
02330 
02331 void LLViewerObject::clearInventoryListeners()
02332 {
02333         mInventoryCallbacks.deleteAllData();
02334 }
02335 
02336 void LLViewerObject::requestInventory()
02337 {
02338         mInventoryDirty = FALSE;
02339         if(mInventory)
02340         {
02341                 //mInventory->clear() // will deref and delete it
02342                 //delete mInventory;
02343                 //mInventory = NULL;
02344                 doInventoryCallback();
02345         }
02346         // throw away duplicate requests
02347         else if (! mInventoryPending)
02348         {
02349                 LLMessageSystem* msg = gMessageSystem;
02350                 msg->newMessageFast(_PREHASH_RequestTaskInventory);
02351                 msg->nextBlockFast(_PREHASH_AgentData);
02352                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
02353                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
02354                 msg->nextBlockFast(_PREHASH_InventoryData);
02355                 msg->addU32Fast(_PREHASH_LocalID, mLocalID);
02356                 msg->sendReliable(mRegionp->getHost());
02357 
02358                 // this will get reset by dirtyInventory or doInventoryCallback
02359                 mInventoryPending = TRUE;
02360         }
02361 }
02362 
02363 struct LLFilenameAndTask
02364 {
02365         LLUUID mTaskID;
02366         char mFilename[MAX_STRING];             /* Flawfinder: ignore */                // Just the filename, not the path
02367 #ifdef _DEBUG
02368         static S32 sCount;
02369         LLFilenameAndTask()
02370         {
02371                 ++sCount;
02372                 lldebugs << "Constructing LLFilenameAndTask: " << sCount << llendl;
02373         }
02374         ~LLFilenameAndTask()
02375         {
02376                 --sCount;
02377                 lldebugs << "Destroying LLFilenameAndTask: " << sCount << llendl;
02378         }
02379 private:
02380         LLFilenameAndTask(const LLFilenameAndTask& rhs);
02381         const LLFilenameAndTask& operator=(const LLFilenameAndTask& rhs) const;
02382 #endif
02383 };
02384 
02385 #ifdef _DEBUG
02386 S32 LLFilenameAndTask::sCount = 0;
02387 #endif
02388 
02389 // static
02390 void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
02391 {
02392         LLMemType mt(LLMemType::MTYPE_OBJECT);
02393         
02394         LLUUID task_id;
02395         msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
02396         LLViewerObject* object = gObjectList.findObject(task_id);
02397         if(!object)
02398         {
02399                 llwarns << "LLViewerObject::processTaskInv object "
02400                         << task_id << " does not exist." << llendl;
02401                 return;
02402         }
02403 
02404         msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum);
02405         LLFilenameAndTask* ft = new LLFilenameAndTask;
02406         ft->mTaskID = task_id;
02407         msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, MAX_STRING, ft->mFilename);
02408         if(!ft->mFilename[0])
02409         {
02410                 lldebugs << "Task has no inventory" << llendl;
02411                 // mock up some inventory to make a drop target.
02412                 if(object->mInventory)
02413                 {
02414                         object->mInventory->clear(); // will deref and delete it
02415                 }
02416                 else
02417                 {
02418                         object->mInventory = new InventoryObjectList();
02419                 }
02420                 LLPointer<LLInventoryObject> obj;
02421                 obj = new LLInventoryObject(object->mID, LLUUID::null,
02422                                                                         LLAssetType::AT_CATEGORY,
02423                                                                         "Contents");
02424                 object->mInventory->push_front(obj);
02425                 object->doInventoryCallback();
02426                 delete ft;
02427                 return;
02428         }
02429         gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename).c_str(), 
02430                                                                 ft->mFilename, LL_PATH_CACHE,
02431                                                                 object->mRegionp->getHost(),
02432                                                                 TRUE,
02433                                                                 &LLViewerObject::processTaskInvFile,
02434                                                                 (void**)ft,
02435                                                                 LLXferManager::HIGH_PRIORITY);
02436 }
02437 
02438 void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
02439 {
02440         LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data;
02441         LLViewerObject* object = NULL;
02442         if(ft && (0 == error_code) &&
02443            (object = gObjectList.findObject(ft->mTaskID)))
02444         {
02445                 object->loadTaskInvFile(ft->mFilename);
02446         }
02447         else
02448         {
02449                 // This Occurs When to requests were made, and the first one
02450                 // has already handled it.
02451                 lldebugs << "Problem loading task inventory. Return code: "
02452                                  << error_code << llendl;
02453         }
02454         delete ft;
02455 }
02456 
02457 void LLViewerObject::loadTaskInvFile(const char* filename)
02458 {
02459         LLMemType mt(LLMemType::MTYPE_OBJECT);
02460         
02461         std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename);
02462         llifstream ifs(filename_and_local_path.c_str());
02463         if(ifs.good())
02464         {
02465                 char buffer[MAX_STRING];        /* Flawfinder: ignore */
02466                 // *NOTE: This buffer size is hard coded into scanf() below.
02467                 char keyword[MAX_STRING];       /* Flawfinder: ignore */
02468                 if(mInventory)
02469                 {
02470                         mInventory->clear(); // will deref and delete it
02471                 }
02472                 else
02473                 {
02474                         mInventory = new InventoryObjectList;
02475                 }
02476                 while(ifs.good())
02477                 {
02478                         ifs.getline(buffer, MAX_STRING);
02479                         sscanf(buffer, " %254s", keyword);      /* Flawfinder: ignore */
02480                         if(0 == strcmp("inv_item", keyword))
02481                         {
02482                                 LLPointer<LLInventoryObject> inv = new LLViewerInventoryItem;
02483                                 inv->importLegacyStream(ifs);
02484                                 mInventory->push_front(inv);
02485                         }
02486                         else if(0 == strcmp("inv_object", keyword))
02487                         {
02488                                 LLPointer<LLInventoryObject> inv = new LLInventoryObject;
02489                                 inv->importLegacyStream(ifs);
02490                                 mInventory->push_front(inv);
02491                         }
02492                         else
02493                         {
02494                                 llwarns << "Unknown token in inventory file '"
02495                                                 << keyword << "'" << llendl;
02496                         }
02497                 }
02498                 ifs.close();
02499                 LLFile::remove(filename_and_local_path.c_str());
02500         }
02501         else
02502         {
02503                 llwarns << "unable to load task inventory: " << filename_and_local_path
02504                                 << llendl;
02505         }
02506         doInventoryCallback();
02507 }
02508 
02509 void LLViewerObject::doInventoryCallback()
02510 {
02511         for(LLInventoryCallbackInfo* info = mInventoryCallbacks.getFirstData();
02512                 info != NULL;
02513                 info = mInventoryCallbacks.getNextData())
02514         {
02515                 if (info->mListener != NULL)
02516                 {
02517                         info->mListener->inventoryChanged(this,
02518                                                                  mInventory,
02519                                                                  mInventorySerialNum,
02520                                                                  info->mInventoryData);
02521                 }
02522                 else
02523                 {
02524                         llinfos << "LLViewerObject::doInventoryCallback() deleting bad listener entry." << llendl;
02525                         mInventoryCallbacks.deleteCurrentData();
02526                 }
02527         }
02528         mInventoryPending = FALSE;
02529 }
02530 
02531 void LLViewerObject::removeInventory(const LLUUID& item_id)
02532 {
02533         // close any associated floater properties
02534         LLFloaterProperties::closeByID(item_id, mID);
02535 
02536         LLMessageSystem* msg = gMessageSystem;
02537         msg->newMessageFast(_PREHASH_RemoveTaskInventory);
02538         msg->nextBlockFast(_PREHASH_AgentData);
02539         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
02540         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
02541         msg->nextBlockFast(_PREHASH_InventoryData);
02542         msg->addU32Fast(_PREHASH_LocalID, mLocalID);
02543         msg->addUUIDFast(_PREHASH_ItemID, item_id);
02544         msg->sendReliable(mRegionp->getHost());
02545         deleteInventoryItem(item_id);
02546         ++mInventorySerialNum;
02547 
02548         // The viewer object should not refresh UI since this is a utility
02549         // function. The UI functionality that called this method should
02550         // refresh the views if necessary.
02551         //gBuildView->refresh();
02552 }
02553 
02554 void LLViewerObject::updateInventory(
02555         LLViewerInventoryItem* item,
02556         U8 key,
02557         bool is_new)
02558 {
02559         LLMemType mt(LLMemType::MTYPE_OBJECT);
02560         
02561         // This slices the object into what we're concerned about on the
02562         // viewer. The simulator will take the permissions and transfer
02563         // ownership.
02564         LLPointer<LLViewerInventoryItem> task_item =
02565                 new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
02566                                                                   item->getAssetUUID(), item->getType(),
02567                                                                   item->getInventoryType(),
02568                                                                   item->getName(), item->getDescription(),
02569                                                                   item->getSaleInfo(),
02570                                                                   item->getFlags(),
02571                                                                   item->getCreationDate());
02572         task_item->setTransactionID(item->getTransactionID());
02573         LLMessageSystem* msg = gMessageSystem;
02574         msg->newMessageFast(_PREHASH_UpdateTaskInventory);
02575         msg->nextBlockFast(_PREHASH_AgentData);
02576         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
02577         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
02578         msg->nextBlockFast(_PREHASH_UpdateData);
02579         msg->addU32Fast(_PREHASH_LocalID, mLocalID);
02580         msg->addU8Fast(_PREHASH_Key, key);
02581         msg->nextBlockFast(_PREHASH_InventoryData);
02582         task_item->packMessage(msg);
02583         msg->sendReliable(mRegionp->getHost());
02584 
02585         // do the internal logic
02586         doUpdateInventory(task_item, key, is_new);
02587 }
02588 
02589 LLInventoryObject* LLViewerObject::getInventoryObject(const LLUUID& item_id)
02590 {
02591         LLInventoryObject* rv = NULL;
02592         if(mInventory)
02593         {
02594                 InventoryObjectList::iterator it = mInventory->begin();
02595                 InventoryObjectList::iterator end = mInventory->end();
02596                 for ( ; it != end; ++it)
02597                 {
02598                         if((*it)->getUUID() == item_id)
02599                         {
02600                                 rv = *it;
02601                                 break;
02602                         }
02603                 }               
02604         }
02605         return rv;
02606 }
02607 
02608 void LLViewerObject::getInventoryContents(InventoryObjectList& objects)
02609 {
02610         if(mInventory)
02611         {
02612                 InventoryObjectList::iterator it = mInventory->begin();
02613                 InventoryObjectList::iterator end = mInventory->end();
02614                 for( ; it != end; ++it)
02615                 {
02616                         if ((*it)->getType() != LLAssetType::AT_CATEGORY)
02617                         {
02618                                 objects.push_back(*it);
02619                         }
02620                 }
02621         }
02622 }
02623 
02624 LLInventoryObject* LLViewerObject::getInventoryRoot()
02625 {
02626         if (!mInventory || !mInventory->size())
02627         {
02628                 return NULL;
02629         }
02630         return mInventory->back();
02631 }
02632 
02633 LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& asset_id)
02634 {
02635         LLViewerInventoryItem* rv = NULL;
02636         if(mInventory)
02637         {
02638                 LLViewerInventoryItem* item = NULL;
02639 
02640                 InventoryObjectList::iterator it = mInventory->begin();
02641                 InventoryObjectList::iterator end = mInventory->end();
02642                 for( ; it != end; ++it)
02643                 {
02644                         LLInventoryObject* obj = *it;
02645                         if(obj->getType() != LLAssetType::AT_CATEGORY)
02646                         {
02647                                 // *FIX: gank-ass down cast!
02648                                 item = (LLViewerInventoryItem*)obj;
02649                                 if(item->getAssetUUID() == asset_id)
02650                                 {
02651                                         rv = item;
02652                                         break;
02653                                 }
02654                         }
02655                 }               
02656         }
02657         return rv;
02658 }
02659 
02660 void LLViewerObject::updateViewerInventoryAsset(
02661                                         const LLViewerInventoryItem* item,
02662                                         const LLUUID& new_asset)
02663 {
02664         LLPointer<LLViewerInventoryItem> task_item =
02665                 new LLViewerInventoryItem(item);
02666         task_item->setAssetUUID(new_asset);
02667 
02668         // do the internal logic
02669         doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, false);
02670 }
02671 
02672 void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent)
02673 {
02674         if (getVolume())
02675         {       //volumes calculate pixel area and angle per face
02676                 return;
02677         }
02678         
02679         LLVector3 viewer_pos_agent = agent.getCameraPositionAgent();
02680         LLVector3 pos_agent = getRenderPosition();
02681 
02682         F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX];
02683         F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY];
02684         F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ];
02685 
02686         F32 max_scale = getMaxScale();
02687         F32 mid_scale = getMidScale();
02688         F32 min_scale = getMinScale();
02689 
02690         // IW: esitmate - when close to large objects, computing range based on distance from center is no good
02691         // to try to get a min distance from face, subtract min_scale/2 from the range.
02692         // This means we'll load too much detail sometimes, but that's better than not enough
02693         // I don't think there's a better way to do this without calculating distance per-poly
02694         F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2;
02695 
02696         if (range < 0.001f || isHUDAttachment())                // range == zero
02697         {
02698                 mAppAngle = 180.f;
02699                 mPixelArea = (F32)gCamera->getScreenPixelArea();
02700         }
02701         else
02702         {
02703                 mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
02704 
02705                 F32 pixels_per_meter = gCamera->getPixelMeterRatio() / range;
02706 
02707                 mPixelArea = (pixels_per_meter * max_scale) * (pixels_per_meter * mid_scale);
02708                 if (mPixelArea > gCamera->getScreenPixelArea())
02709                 {
02710                         mAppAngle = 180.f;
02711                         mPixelArea = (F32)gCamera->getScreenPixelArea();
02712                 }
02713         }
02714 }
02715 
02716 BOOL LLViewerObject::updateLOD()
02717 {
02718         // Update volume of looping sounds
02719         if (mAudioSourcep && mAudioSourcep->isLoop())
02720         {
02721                 F32 volume = mAudioGain * gSavedSettings.getF32("AudioLevelSFX");
02722                 mAudioSourcep->setGain(volume);
02723         }
02724         return FALSE;
02725 }
02726 
02727 BOOL LLViewerObject::updateGeometry(LLDrawable *drawable)
02728 {
02729         return TRUE;
02730 }
02731 
02732 void LLViewerObject::updateFaceSize(S32 idx)
02733 {
02734         
02735 }
02736 
02737 LLDrawable* LLViewerObject::createDrawable(LLPipeline *pipeline)
02738 {
02739         return NULL;
02740 }
02741 
02742 void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped)
02743 {
02744         LLPrimitive::setScale(scale);
02745         if (mDrawable.notNull())
02746         {
02747                 //encompass completely sheared objects by taking 
02748                 //the most extreme point possible (<1,1,0.5>)
02749                 mDrawable->setRadius(LLVector3(1,1,0.5f).scaleVec(scale).magVec());
02750                 updateDrawable(damped);
02751         }
02752 
02753         if( (LL_PCODE_VOLUME == getPCode()) && !isDead() )
02754         {
02755                 if (permYouOwner() || (scale.magVecSquared() > (7.5f * 7.5f)) )
02756                 {
02757                         if (!mOnMap)
02758                         {
02759                                 gObjectList.addToMap(this);
02760                                 mOnMap = TRUE;
02761                         }
02762                 }
02763                 else
02764                 {
02765                         if (mOnMap)
02766                         {
02767                                 gObjectList.removeFromMap(this);
02768                                 mOnMap = FALSE;
02769                         }
02770                 }
02771         }
02772 }
02773 
02774 void LLViewerObject::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax)
02775 {
02776         LLVector3 center = getRenderPosition();
02777         LLVector3 size = getScale();
02778         newMin.setVec(center-size);
02779         newMax.setVec(center+size);
02780         mDrawable->setPositionGroup((newMin + newMax) * 0.5f);
02781 }
02782 
02783 F32 LLViewerObject::getBinRadius()
02784 {
02785         if (mDrawable.notNull())
02786         {
02787                 const LLVector3* ext = mDrawable->getSpatialExtents();
02788                 return (ext[1]-ext[0]).magVec();
02789         }
02790         
02791         return getScale().magVec();
02792 }
02793 
02794 F32 LLViewerObject::getMaxScale() const
02795 {
02796         return llmax(getScale().mV[VX],getScale().mV[VY], getScale().mV[VZ]);
02797 }
02798 
02799 F32 LLViewerObject::getMinScale() const
02800 {
02801         return llmin(getScale().mV[0],getScale().mV[1],getScale().mV[2]);
02802 }
02803 
02804 F32 LLViewerObject::getMidScale() const
02805 {
02806         if (getScale().mV[VX] < getScale().mV[VY])
02807         {
02808                 if (getScale().mV[VY] < getScale().mV[VZ])
02809                 {
02810                         return getScale().mV[VY];
02811                 }
02812                 else if (getScale().mV[VX] < getScale().mV[VZ])
02813                 {
02814                         return getScale().mV[VZ];
02815                 }
02816                 else
02817                 {
02818                         return getScale().mV[VX];
02819                 }
02820         }
02821         else if (getScale().mV[VX] < getScale().mV[VZ])
02822         {
02823                 return getScale().mV[VX];
02824         }
02825         else if (getScale().mV[VY] < getScale().mV[VZ])
02826         {
02827                 return getScale().mV[VZ];
02828         }
02829         else
02830         {
02831                 return getScale().mV[VY];
02832         }
02833 }
02834 
02835 
02836 void LLViewerObject::updateTextures(LLAgent &agent)
02837 {
02838 }
02839 
02840 void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */)
02841 {
02842         if (isDead())
02843         {
02844                 return;
02845         }
02846 
02847         S32 i;
02848         S32 tex_count = getNumTEs();
02849         for (i = 0; i < tex_count; i++)
02850         {
02851                 getTEImage(i)->setBoostLevel(LLViewerImage::BOOST_SELECTED);
02852         }
02853 
02854         if (boost_children)
02855         {
02856                 S32 num_children = mChildList.size();
02857                 for (i = 0; i < num_children; i++)
02858                 {
02859                         LLViewerObject *childp = mChildList[i];
02860                         childp->boostTexturePriority();
02861                 }
02862         }
02863 }
02864 
02865 
02866 void LLViewerObject::setLineWidthForWindowSize(S32 window_width)
02867 {
02868         if (window_width < 700)
02869         {
02870                 LLUI::setLineWidth(2.0f);
02871         }
02872         else if (window_width < 1100)
02873         {
02874                 LLUI::setLineWidth(3.0f);
02875         }
02876         else if (window_width < 2000)
02877         {
02878                 LLUI::setLineWidth(4.0f);
02879         }
02880         else
02881         {
02882                 // _damn_, what a nice monitor!
02883                 LLUI::setLineWidth(5.0f);
02884         }
02885 }
02886 
02887 void LLViewerObject::increaseArrowLength()
02888 {
02889 /* ???
02890         if (mAxisArrowLength == 50)
02891         {
02892                 mAxisArrowLength = 100;
02893         }
02894         else
02895         {
02896                 mAxisArrowLength = 150;
02897         }
02898 */
02899 }
02900 
02901 
02902 void LLViewerObject::decreaseArrowLength()
02903 {
02904 /* ???
02905         if (mAxisArrowLength == 150)
02906         {
02907                 mAxisArrowLength = 100;
02908         }
02909         else
02910         {
02911                 mAxisArrowLength = 50;
02912         }
02913 */
02914 }
02915 
02916 // Culled from newsim LLTask::addNVPair
02917 void LLViewerObject::addNVPair(const std::string& data)
02918 {
02919         // cout << "LLViewerObject::addNVPair() with ---" << data << "---" << endl;
02920         LLNameValue *nv = new LLNameValue(data.c_str());
02921 
02922 //      char splat[MAX_STRING];
02923 //      temp->printNameValue(splat);
02924 //      llinfos << "addNVPair " << splat << llendl;
02925 
02926         name_value_map_t::iterator iter = mNameValuePairs.find(nv->mName);
02927         if (iter != mNameValuePairs.end())
02928         {
02929                 LLNameValue* foundnv = iter->second;
02930                 if (foundnv->mClass != NVC_READ_ONLY)
02931                 {
02932                         delete foundnv;
02933                         mNameValuePairs.erase(iter);
02934                 }
02935                 else
02936                 {
02937                         delete nv;
02938 //                      llinfos << "Trying to write to Read Only NVPair " << temp->mName << " in addNVPair()" << llendl;
02939                         return;
02940                 }
02941         }
02942         mNameValuePairs[nv->mName] = nv;
02943 }
02944 
02945 BOOL LLViewerObject::removeNVPair(const char *name)
02946 {
02947         char* canonical_name = gNVNameTable.addString(name);
02948 
02949         lldebugs << "LLViewerObject::removeNVPair(): " << name << llendl;
02950 
02951         name_value_map_t::iterator iter = mNameValuePairs.find(canonical_name);
02952         if (iter != mNameValuePairs.end())
02953         {
02954                 if( mRegionp )
02955                 {
02956                         LLNameValue* nv = iter->second;
02957 /*
02958                         std::string buffer = nv->printNameValue();
02959                         gMessageSystem->newMessageFast(_PREHASH_RemoveNameValuePair);
02960                         gMessageSystem->nextBlockFast(_PREHASH_TaskData);
02961                         gMessageSystem->addUUIDFast(_PREHASH_ID, mID);
02962                         
02963                         gMessageSystem->nextBlockFast(_PREHASH_NameValueData);
02964                         gMessageSystem->addStringFast(_PREHASH_NVPair, buffer.c_str());
02965 
02966                         gMessageSystem->sendReliable( mRegionp->getHost() );
02967 */
02968                         // Remove the NV pair from the local list.
02969                         delete nv;
02970                         mNameValuePairs.erase(iter);
02971                         return TRUE;
02972                 }
02973                 else
02974                 {
02975                         lldebugs << "removeNVPair - No region for object" << llendl;
02976                 }
02977         }
02978         return FALSE;
02979 }
02980 
02981 
02982 LLNameValue *LLViewerObject::getNVPair(const char *name) const
02983 {
02984         char            *canonical_name;
02985 
02986         canonical_name = gNVNameTable.addString(name);
02987 
02988         // If you access a map with a name that isn't in it, it will add the name and a null pointer.
02989         // So first check if the data is in the map.
02990         name_value_map_t::const_iterator iter = mNameValuePairs.find(canonical_name);
02991         if (iter != mNameValuePairs.end())
02992         {
02993                 return iter->second;
02994         }
02995         else
02996         {
02997                 return NULL;
02998         }
02999 }
03000 
03001 void LLViewerObject::updatePositionCaches() const
03002 {
03003         if (!isRoot())
03004         {
03005                 mPositionRegion = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation();
03006                 mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
03007         }
03008         else
03009         {
03010                 mPositionRegion = getPosition();
03011                 mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
03012         }
03013 }
03014 
03015 const LLVector3d LLViewerObject::getPositionGlobal() const
03016 {
03017         LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion());;
03018 
03019         if (isAttachment())
03020         {
03021                 position_global = gAgent.getPosGlobalFromAgent(getRenderPosition());
03022         }
03023 
03024         return position_global;
03025 }
03026 
03027 const LLVector3 &LLViewerObject::getPositionAgent() const
03028 {
03029         if (mRegionp)
03030         {
03031                 if (mDrawable.notNull() && (!mDrawable->isRoot() && getParent()))
03032                 {
03033                         // Don't return cached position if you have a parent, recalc (until all dirtying is done correctly.
03034                         LLVector3 position_region;
03035                         position_region = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation();
03036                         mPositionAgent = mRegionp->getPosAgentFromRegion(position_region);
03037                 }
03038                 else
03039                 {
03040                         mPositionAgent = mRegionp->getPosAgentFromRegion(getPosition());
03041                 }
03042         }
03043         return mPositionAgent;
03044 }
03045 
03046 const LLVector3 &LLViewerObject::getPositionRegion() const
03047 {
03048         if (!isRoot())
03049         {
03050                 LLViewerObject *parent = (LLViewerObject *)getParent();
03051                 mPositionRegion = parent->getPositionRegion() + (getPosition() * parent->getRotation());
03052         }
03053         return mPositionRegion;
03054 }
03055 
03056 const LLVector3 LLViewerObject::getPositionEdit() const
03057 {
03058         if (isRootEdit())
03059         {
03060                 return getPosition();
03061         }
03062         else
03063         {
03064                 LLViewerObject *parent = (LLViewerObject *)getParent();
03065                 LLVector3 position_edit = parent->getPositionEdit() + getPosition() * parent->getRotationEdit();
03066                 return position_edit;
03067         }
03068 }
03069 
03070 const LLVector3 LLViewerObject::getRenderPosition() const
03071 {
03072         if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
03073         {
03074                 return getPositionAgent();
03075         }
03076         else
03077         {
03078                 if (isAvatar())
03079                 {
03080                         if (isRoot())
03081                         {
03082                                 return mDrawable->getPositionAgent();
03083                         }
03084                         else
03085                         {
03086                                 return getPosition() * mDrawable->getParent()->getRenderMatrix();
03087                         }
03088                 }
03089 
03090                 return mDrawable->getPositionAgent();
03091         }
03092 }
03093 
03094 const LLVector3 LLViewerObject::getPivotPositionAgent() const
03095 {
03096         return getRenderPosition();
03097 }
03098 
03099 const LLQuaternion LLViewerObject::getRenderRotation() const
03100 {
03101         LLQuaternion ret;
03102         if (mDrawable.isNull() || mDrawable->isStatic())
03103         {
03104                 ret = getRotationEdit();
03105         }
03106         else
03107         {
03108                 if (!mDrawable->isRoot())
03109                 {
03110                         ret = getRotation() * LLQuaternion(mDrawable->getParent()->getWorldMatrix());
03111                 }
03112                 else
03113                 {
03114                         ret = LLQuaternion(mDrawable->getWorldMatrix());
03115                 }
03116         }
03117         
03118         return ret;
03119 }
03120 
03121 const LLMatrix4 LLViewerObject::getRenderMatrix() const
03122 {
03123         return mDrawable->getWorldMatrix();
03124 }
03125 
03126 const LLQuaternion LLViewerObject::getRotationRegion() const
03127 {
03128         LLQuaternion global_rotation = getRotation();
03129         if (!((LLXform *)this)->isRoot())
03130         {
03131                 global_rotation = global_rotation * getParent()->getRotation();
03132         }
03133         return global_rotation;
03134 }
03135 
03136 const LLQuaternion LLViewerObject::getRotationEdit() const
03137 {
03138         LLQuaternion global_rotation = getRotation();
03139         if (!((LLXform *)this)->isRootEdit())
03140         {
03141                 global_rotation = global_rotation * getParent()->getRotation();
03142         }
03143         return global_rotation;
03144 }
03145 
03146 void LLViewerObject::setPositionAbsoluteGlobal( const LLVector3d &pos_global, BOOL damped )
03147 {
03148         if (isAttachment())
03149         {
03150                 LLVector3 new_pos = mRegionp->getPosRegionFromGlobal(pos_global);
03151                 if (isRootEdit())
03152                 {
03153                         new_pos -= mDrawable->mXform.getParent()->getWorldPosition();
03154                         LLQuaternion world_rotation = mDrawable->mXform.getParent()->getWorldRotation();
03155                         new_pos = new_pos * ~world_rotation;
03156                 }
03157                 else
03158                 {
03159                         LLViewerObject* parentp = (LLViewerObject*)getParent();
03160                         new_pos -= parentp->getPositionAgent();
03161                         new_pos = new_pos * ~parentp->getRotationRegion();
03162                 }
03163                 LLViewerObject::setPosition(new_pos);
03164                 
03165                 if (mParent && ((LLViewerObject*)mParent)->isAvatar())
03166                 {
03167                         // we have changed the position of an attachment, so we need to clamp it
03168                         LLVOAvatar *avatar = (LLVOAvatar*)mParent;
03169 
03170                         avatar->clampAttachmentPositions();
03171                 }
03172         }
03173         else
03174         {
03175                 if( isRoot() )
03176                 {
03177                         setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global));
03178                 }
03179                 else
03180                 {
03181                         // the relative position with the parent is not constant
03182                         LLViewerObject* parent = (LLViewerObject *)getParent();
03183                         //RN: this assumes we are only calling this function from the edit tools
03184                         gPipeline.updateMoveNormalAsync(parent->mDrawable);
03185 
03186                         LLVector3 pos_local = mRegionp->getPosRegionFromGlobal(pos_global) - parent->getPositionRegion();
03187                         pos_local = pos_local * ~parent->getRotationRegion();
03188                         LLViewerObject::setPosition( pos_local );
03189                 }
03190         }
03191         //RN: assumes we always want to snap the object when calling this function
03192         gPipeline.updateMoveNormalAsync(mDrawable);
03193 }
03194 
03195 void LLViewerObject::setPosition(const LLVector3 &pos, BOOL damped)
03196 {
03197         if (getPosition() != pos)
03198         {
03199                 setChanged(TRANSLATED | SILHOUETTE);
03200         }
03201                 
03202         LLXform::setPosition(pos);
03203         updateDrawable(damped);
03204         if (isRoot())
03205         {
03206                 // position caches need to be up to date on root objects
03207                 updatePositionCaches();
03208         }
03209 }
03210 
03211 void LLViewerObject::setPositionGlobal(const LLVector3d &pos_global, BOOL damped)
03212 {
03213         if (isAttachment())
03214         {
03215                 if (isRootEdit())
03216                 {
03217                         LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global);
03218                         newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition();
03219 
03220                         LLQuaternion invWorldRotation = mDrawable->mXform.getParent()->getWorldRotation();
03221                         invWorldRotation.transQuat();
03222 
03223                         newPos = newPos * invWorldRotation;
03224                         LLViewerObject::setPosition(newPos);
03225                 }
03226                 else
03227                 {
03228                         // assumes parent is root editable (root of attachment)
03229                         LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global);
03230                         newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition();
03231                         LLVector3 delta_pos = newPos - getPosition();
03232 
03233                         LLQuaternion invRotation = mDrawable->getRotation();
03234                         invRotation.transQuat();
03235                         
03236                         delta_pos = delta_pos * invRotation;
03237 
03238                         // *FIX: is this right?  Shouldn't we be calling the
03239                         // LLViewerObject version of setPosition?
03240                         LLVector3 old_pos = mDrawable->mXform.getParent()->getPosition();
03241                         mDrawable->mXform.getParent()->setPosition(old_pos + delta_pos);
03242                         setChanged(TRANSLATED | SILHOUETTE);
03243                 }
03244                 if (mParent && ((LLViewerObject*)mParent)->isAvatar())
03245                 {
03246                         // we have changed the position of an attachment, so we need to clamp it
03247                         LLVOAvatar *avatar = (LLVOAvatar*)mParent;
03248 
03249                         avatar->clampAttachmentPositions();
03250                 }
03251         }
03252         else
03253         {
03254                 if (isRoot())
03255                 {
03256                         setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global));
03257                 }
03258                 else
03259                 {
03260                         // the relative position with the parent is constant, but the parent's position needs to be changed
03261                         LLVector3d position_offset;
03262                         position_offset.setVec(getPosition()*getParent()->getRotation());
03263                         LLVector3d new_pos_global = pos_global - position_offset;
03264                         ((LLViewerObject *)getParent())->setPositionGlobal(new_pos_global);
03265                 }
03266         }
03267         updateDrawable(damped);
03268 }
03269 
03270 
03271 void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, BOOL damped)
03272 {
03273         // Set position relative to parent, if no parent, relative to region
03274         if (!isRoot())
03275         {
03276                 LLViewerObject::setPosition(pos_parent);
03277                 updateDrawable(damped);
03278         }
03279         else
03280         {
03281                 setPositionRegion(pos_parent, damped);
03282         }
03283 }
03284 
03285 void LLViewerObject::setPositionRegion(const LLVector3 &pos_region, BOOL damped)
03286 {
03287         if (!isRootEdit())
03288         {
03289                 LLViewerObject* parent = (LLViewerObject*) getParent();
03290                 LLViewerObject::setPosition((pos_region-parent->getPositionRegion())*~parent->getRotationRegion());
03291         }
03292         else
03293         {
03294                 LLViewerObject::setPosition(pos_region);
03295                 mPositionRegion = pos_region;
03296                 mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
03297         }
03298 }
03299 
03300 void LLViewerObject::setPositionAgent(const LLVector3 &pos_agent, BOOL damped)
03301 {
03302         LLVector3 pos_region = getRegion()->getPosRegionFromAgent(pos_agent);
03303         setPositionRegion(pos_region, damped);
03304 }
03305 
03306 // identical to setPositionRegion() except it checks for child-joints 
03307 // and doesn't also move the joint-parent
03308 // TODO -- implement similar intelligence for joint-parents toward
03309 // their joint-children
03310 void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped)
03311 {
03312         if (!isRootEdit())
03313         {
03314                 // the relative position with the parent is constant, but the parent's position needs to be changed
03315                 LLVector3 position_offset = getPosition() * getParent()->getRotation();
03316 
03317                 ((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset);
03318         }
03319         else if (isJointChild())
03320         {
03321                 // compute new parent-relative position
03322                 LLViewerObject *parent = (LLViewerObject *) getParent();
03323                 LLQuaternion inv_parent_rot = parent->getRotation();
03324                 inv_parent_rot.transQuat();
03325                 LLVector3 pos_parent = (pos_edit - parent->getPositionRegion()) * inv_parent_rot;
03326                 LLViewerObject::setPosition(pos_parent);
03327         }
03328         else
03329         {
03330                 LLViewerObject::setPosition(pos_edit);
03331                 mPositionRegion = pos_edit;
03332                 mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
03333         }
03334         updateDrawable(damped);
03335 }
03336 
03337 
03338 LLViewerObject* LLViewerObject::getRootEdit() const
03339 {
03340         const LLViewerObject* root = this;
03341         while (root->mParent 
03342                    && !(root->mJointInfo
03343                            || ((LLViewerObject*)root->mParent)->isAvatar()) )
03344         {
03345                 root = (LLViewerObject*)root->mParent;
03346         }
03347         return (LLViewerObject*)root;
03348 }
03349 
03350 U8 LLViewerObject::getMediaType() const
03351 {
03352         if (mMedia)
03353         {
03354                 return mMedia->mMediaType;
03355         }
03356         else
03357         {
03358                 return LLViewerObject::MEDIA_TYPE_NONE;
03359         }
03360 }
03361 
03362 void LLViewerObject::setMediaType(U8 media_type)
03363 {
03364         if (!mMedia)
03365         {
03366                 // JAMESDEBUG TODO what if we don't have a media pointer?
03367         }
03368         else if (mMedia->mMediaType != media_type)
03369         {
03370                 mMedia->mMediaType = media_type;
03371 
03372                 // TODO: update materials with new image
03373         }
03374 }
03375 
03376 const LLString& LLViewerObject::getMediaURL() const
03377 {
03378         if (mMedia)
03379         {
03380                 return mMedia->mMediaURL;
03381         }
03382         else
03383         {
03384                 return LLString::null;
03385         }
03386 }
03387 
03388 void LLViewerObject::setMediaURL(const LLString& media_url)
03389 {
03390         LLMemType mt(LLMemType::MTYPE_OBJECT);
03391         
03392         if (!mMedia)
03393         {
03394                 mMedia = new LLViewerObjectMedia;
03395                 mMedia->mMediaURL = media_url;
03396                 mMedia->mPassedWhitelist = FALSE;
03397 
03398                 // TODO: update materials with new image
03399         }
03400         else if (mMedia->mMediaURL != media_url)
03401         {
03402                 mMedia->mMediaURL = media_url;
03403                 mMedia->mPassedWhitelist = FALSE;
03404 
03405                 // TODO: update materials with new image
03406         }
03407 }
03408 
03409 BOOL LLViewerObject::getMediaPassedWhitelist() const
03410 {
03411         if (mMedia)
03412         {
03413                 return mMedia->mPassedWhitelist;
03414         }
03415         else
03416         {
03417                 return FALSE;
03418         }
03419 }
03420 
03421 void LLViewerObject::setMediaPassedWhitelist(BOOL passed)
03422 {
03423         if (mMedia)
03424         {
03425                 mMedia->mPassedWhitelist = passed;
03426         }
03427 }
03428 
03429 BOOL LLViewerObject::setMaterial(const U8 material)
03430 {
03431         BOOL res = LLPrimitive::setMaterial(material);
03432         if (res)
03433         {
03434                 setChanged(TEXTURE);
03435         }
03436         return res;
03437 }
03438 
03439 void LLViewerObject::setNumTEs(const U8 num_tes)
03440 {
03441         LLMemType mt(LLMemType::MTYPE_OBJECT);
03442         
03443         U32 i;
03444         if (num_tes != getNumTEs())
03445         {
03446                 if (num_tes)
03447                 {
03448                         LLPointer<LLViewerImage> *new_images;
03449                         new_images = new LLPointer<LLViewerImage>[num_tes];
03450                         for (i = 0; i < num_tes; i++)
03451                         {
03452                                 if (i < getNumTEs())
03453                                 {
03454                                         new_images[i] = mTEImages[i];
03455                                 }
03456                                 else if (getNumTEs())
03457                                 {
03458                                         new_images[i] = mTEImages[getNumTEs()-1];
03459                                 }
03460                                 else
03461                                 {
03462                                         new_images[i] = NULL;
03463                                 }
03464                         }
03465 
03466                         deleteTEImages();
03467                         
03468                         mTEImages = new_images;
03469                 }
03470                 else
03471                 {
03472                         deleteTEImages();
03473                 }
03474                 LLPrimitive::setNumTEs(num_tes);
03475                 setChanged(TEXTURE);
03476 
03477                 if (mDrawable.notNull())
03478                 {
03479                         gPipeline.markTextured(mDrawable);
03480                 }
03481         }
03482 }
03483 
03484 void LLViewerObject::sendMaterialUpdate() const
03485 {
03486         LLViewerRegion* regionp = getRegion();
03487         if(!regionp) return;
03488         gMessageSystem->newMessageFast(_PREHASH_ObjectMaterial);
03489         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03490         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03491         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03492         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03493         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID,      mLocalID );
03494         gMessageSystem->addU8Fast(_PREHASH_Material, getMaterial() );
03495         gMessageSystem->sendReliable( regionp->getHost() );
03496 
03497 }
03498 
03499 // formerly send_object_rotation
03500 void LLViewerObject::sendRotationUpdate() const
03501 {
03502         LLViewerRegion* regionp = getRegion();
03503         if(!regionp) return;
03504         gMessageSystem->newMessageFast(_PREHASH_ObjectRotation);
03505         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03506         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03507         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03508         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03509         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID);
03510         gMessageSystem->addQuatFast(_PREHASH_Rotation, getRotationEdit());
03511         //llinfos << "Sent rotation " << getRotationEdit() << llendl;
03512         gMessageSystem->sendReliable( regionp->getHost() );
03513 }
03514 
03515 // formerly send_object_position_global
03516 void LLViewerObject::sendPositionUpdate() const
03517 {
03518         gMessageSystem->newMessageFast(_PREHASH_ObjectPosition);
03519         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03520         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03521         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03522         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03523         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID,      mLocalID );
03524         gMessageSystem->addVector3Fast(_PREHASH_Position, getPositionRegion());
03525         LLViewerRegion* regionp = getRegion();
03526         gMessageSystem->sendReliable(regionp->getHost());
03527 }
03528 
03529 
03530 //formerly send_object_scale
03531 void LLViewerObject::sendScaleUpdate()
03532 {
03533         gMessageSystem->newMessageFast(_PREHASH_ObjectScale);
03534         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03535         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03536         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03537         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03538         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID,      mLocalID );
03539         gMessageSystem->addVector3Fast(_PREHASH_Scale,  (getScale()));
03540 
03541         LLViewerRegion *regionp = getRegion();
03542         gMessageSystem->sendReliable(regionp->getHost() );
03543 }
03544 
03545 
03546 //formerly send_object_shape(LLViewerObject *object)
03547 void LLViewerObject::sendShapeUpdate()
03548 {
03549         gMessageSystem->newMessageFast(_PREHASH_ObjectShape);
03550         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
03551         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03552         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03553         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
03554         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID );
03555 
03556         LLVolumeMessage::packVolumeParams(&getVolume()->getParams(), gMessageSystem);
03557 
03558         LLViewerRegion *regionp = getRegion();
03559         gMessageSystem->sendReliable( regionp->getHost() );
03560 }
03561 
03562 
03563 void LLViewerObject::sendTEUpdate() const
03564 {
03565         LLMessageSystem* msg = gMessageSystem;
03566         msg->newMessageFast(_PREHASH_ObjectImage);
03567 
03568         msg->nextBlockFast(_PREHASH_AgentData);
03569         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
03570         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
03571 
03572         msg->nextBlockFast(_PREHASH_ObjectData);
03573         msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID );
03574         if (mMedia)
03575         {
03576                 msg->addString("MediaURL", mMedia->mMediaURL);
03577         }
03578         else
03579         {
03580                 msg->addString("MediaURL", NULL);
03581         }
03582 
03583         // JAMESDEBUG TODO send media type
03584 
03585         packTEMessage(msg);
03586 
03587         LLViewerRegion *regionp = getRegion();
03588         msg->sendReliable( regionp->getHost() );
03589 }
03590 
03591 void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
03592 {
03593         LLPrimitive::setTE(te, texture_entry);
03594 // JAMESDEBUG This doesn't work, don't get any textures.
03595 //      if (mDrawable.notNull() && mDrawable->isVisible())
03596 //      {
03597                 const LLUUID& image_id = getTE(te)->getID();
03598                 mTEImages[te] = gImageList.getImage(image_id);
03599 //      }
03600 }
03601 
03602 void LLViewerObject::setTEImage(const U8 te, LLViewerImage *imagep)
03603 {
03604         if (mTEImages[te] != imagep)
03605         {
03606                 mTEImages[te] = imagep;
03607                 LLPrimitive::setTETexture(te, imagep->getID());
03608                 setChanged(TEXTURE);
03609                 if (mDrawable.notNull())
03610                 {
03611                         gPipeline.markTextured(mDrawable);
03612                 }
03613         }
03614 }
03615 
03616 
03617 S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host)
03618 {
03619         S32 retval = 0;
03620         if (uuid != getTE(te)->getID() ||
03621                 uuid == LLUUID::null)
03622         {
03623                 retval = LLPrimitive::setTETexture(te, uuid);
03624                 mTEImages[te] = gImageList.getImageFromHost(uuid, host);
03625                 setChanged(TEXTURE);
03626                 if (mDrawable.notNull())
03627                 {
03628                         gPipeline.markTextured(mDrawable);
03629                 }
03630         }
03631         return retval;
03632 }
03633 
03634 
03635 S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid)
03636 {
03637         // Invalid host == get from the agent's sim
03638         return setTETextureCore(te, uuid, LLHost::invalid);
03639 }
03640 
03641 
03642 S32 LLViewerObject::setTEColor(const U8 te, const LLColor4 &color)
03643 {
03644         S32 retval = 0;
03645         const LLTextureEntry *tep = getTE(te);
03646         if (!tep)
03647         {
03648                 llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
03649         }
03650         else if (color != tep->getColor())
03651         {
03652                 retval = LLPrimitive::setTEColor(te, color);
03653                 setChanged(TEXTURE);
03654                 if (mDrawable.notNull() && retval)
03655                 {
03656                         // These should only happen on updates which are not the initial update.
03657                         gPipeline.markTextured(mDrawable);
03658                 }
03659         }
03660         return retval;
03661 }
03662 
03663 S32 LLViewerObject::setTEBumpmap(const U8 te, const U8 bump)
03664 {
03665         S32 retval = 0;
03666         const LLTextureEntry *tep = getTE(te);
03667         if (!tep)
03668         {
03669                 llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
03670         }
03671         else if (bump != tep->getBumpmap())
03672         {
03673                 retval = LLPrimitive::setTEBumpmap(te, bump);
03674                 setChanged(TEXTURE);
03675                 if (mDrawable.notNull() && retval)
03676                 {
03677                         gPipeline.markTextured(mDrawable);
03678                         gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
03679                 }
03680         }
03681         return retval;
03682 }
03683 
03684 S32 LLViewerObject::setTETexGen(const U8 te, const U8 texgen)
03685 {
03686         S32 retval = 0;
03687         const LLTextureEntry *tep = getTE(te);
03688         if (!tep)
03689         {
03690                 llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
03691         }
03692         else if (texgen != tep->getTexGen())
03693         {
03694                 retval = LLPrimitive::setTETexGen(te, texgen);
03695                 setChanged(TEXTURE);
03696         }
03697         return retval;
03698 }
03699 
03700 S32 LLViewerObject::setTEShiny(const U8 te, const U8 shiny)
03701 {
03702         S32 retval = 0;
03703         const LLTextureEntry *tep = getTE(te);
03704         if (!tep)
03705         {
03706                 llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
03707         }
03708         else if (shiny != tep->getShiny())
03709         {
03710                 retval = LLPrimitive::setTEShiny(te, shiny);
03711                 setChanged(TEXTURE);
03712         }
03713         return retval;
03714 }
03715 
03716 S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright)
03717 {
03718         S32 retval = 0;
03719         const LLTextureEntry *tep = getTE(te);
03720         if (!tep)
03721         {
03722                 llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
03723         }
03724         else if (fullbright != tep->getFullbright())
03725         {
03726                 retval = LLPrimitive::setTEFullbright(te, fullbright);
03727                 setChanged(TEXTURE);
03728                 if (mDrawable.notNull() && retval)
03729                 {
03730                         gPipeline.markTextured(mDrawable);
03731                 }
03732         }
03733         return retval;
03734 }
03735 
03736 
03737 S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags)
03738 {
03739         // JAMESDEBUG this might need work for media type
03740         S32 retval = 0;
03741         const LLTextureEntry *tep = getTE(te);
03742         if (!tep)
03743         {
03744                 llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
03745         }
03746         else if (media_flags != tep->getMediaFlags())
03747         {
03748                 retval = LLPrimitive::setTEMediaFlags(te, media_flags);
03749                 setChanged(TEXTURE);
03750                 if (mDrawable.notNull() && retval)
03751                 {
03752                         gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, TRUE);
03753                         gPipeline.markTextured(mDrawable);
03754                         // JC - probably only need this if changes texture coords
03755                         //gPipeline.markRebuild(mDrawable);
03756                 }
03757         }
03758         return retval;
03759 }
03760 
03761 
03762 S32 LLViewerObject::setTEScale(const U8 te, const F32 s, const F32 t)
03763 {
03764         S32 retval = 0;
03765         retval = LLPrimitive::setTEScale(te, s, t);
03766         setChanged(TEXTURE);
03767         if (mDrawable.notNull() && retval)
03768         {
03769                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
03770         }
03771         return retval;
03772 }
03773 
03774 S32 LLViewerObject::setTEScaleS(const U8 te, const F32 s)
03775 {
03776         S32 retval = LLPrimitive::setTEScaleS(te, s);
03777         if (mDrawable.notNull() && retval)
03778         {
03779                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
03780         }
03781 
03782         return retval;
03783 }
03784 
03785 S32 LLViewerObject::setTEScaleT(const U8 te, const F32 t)
03786 {
03787         S32 retval = LLPrimitive::setTEScaleT(te, t);
03788         if (mDrawable.notNull() && retval)
03789         {
03790                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
03791         }
03792 
03793         return retval;
03794 }
03795 
03796 S32 LLViewerObject::setTEOffset(const U8 te, const F32 s, const F32 t)
03797 {
03798         S32 retval = LLPrimitive::setTEOffset(te, s, t);
03799         if (mDrawable.notNull() && retval)
03800         {
03801                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
03802         }
03803         return retval;
03804 }
03805 
03806 S32 LLViewerObject::setTEOffsetS(const U8 te, const F32 s)
03807 {
03808         S32 retval = LLPrimitive::setTEOffsetS(te, s);
03809         if (mDrawable.notNull() && retval)
03810         {
03811                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
03812         }
03813 
03814         return retval;
03815 }
03816 
03817 S32 LLViewerObject::setTEOffsetT(const U8 te, const F32 t)
03818 {
03819         S32 retval = LLPrimitive::setTEOffsetT(te, t);
03820         if (mDrawable.notNull() && retval)
03821         {
03822                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
03823         }
03824 
03825         return retval;
03826 }
03827 
03828 S32 LLViewerObject::setTERotation(const U8 te, const F32 r)
03829 {
03830         S32 retval = LLPrimitive::setTERotation(te, r);
03831         if (mDrawable.notNull() && retval)
03832         {
03833                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
03834         }
03835         return retval;
03836 }
03837 
03838 
03839 LLViewerImage *LLViewerObject::getTEImage(const U8 face) const
03840 {
03841 //      llassert(mTEImages);
03842 
03843         if (face < getNumTEs())
03844         {
03845                 LLViewerImage* image = mTEImages[face];
03846                 if (image)
03847                 {
03848                         return image;
03849                 }
03850                 else
03851                 {
03852                         return (LLViewerImage*)((LLImageGL*)LLViewerImage::sDefaultImagep);
03853                 }
03854         }
03855 
03856         llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl;
03857 
03858         return NULL;
03859 }
03860 
03861 
03862 void LLViewerObject::fitFaceTexture(const U8 face)
03863 {
03864         llinfos << "fitFaceTexture not implemented" << llendl;
03865 }
03866 
03867 
03868 LLBBox LLViewerObject::getBoundingBoxAgent() const
03869 {
03870         LLVector3 position_agent;
03871         LLQuaternion rot;
03872         LLViewerObject* root_edit = (LLViewerObject*)getRootEdit();
03873         LLViewerObject* avatar_parent = (LLViewerObject*)root_edit->getParent();
03874         if (avatar_parent && avatar_parent->isAvatar() && root_edit->mDrawable.notNull())
03875         {
03876                 LLXform* parent_xform = root_edit->mDrawable->getXform()->getParent();
03877                 position_agent = (getPositionEdit() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();
03878                 rot = getRotationEdit() * parent_xform->getWorldRotation();
03879         }
03880         else
03881         {
03882                 position_agent = getPositionAgent();
03883                 rot = getRotationRegion();
03884         }
03885         
03886         return LLBBox( position_agent, rot, getScale() * -0.5f, getScale() * 0.5f );
03887 }
03888 
03889 U32 LLViewerObject::getNumVertices() const
03890 {
03891         U32 num_vertices = 0;
03892         if (mDrawable.notNull())
03893         {
03894                 S32 i, num_faces;
03895                 num_faces = mDrawable->getNumFaces();
03896                 for (i = 0; i < num_faces; i++)
03897                 {
03898                         num_vertices += mDrawable->getFace(i)->getGeomCount();
03899                 }
03900         }
03901         return num_vertices;
03902 }
03903 
03904 U32 LLViewerObject::getNumIndices() const
03905 {
03906         U32 num_indices = 0;
03907         if (mDrawable.notNull())
03908         {
03909                 S32 i, num_faces;
03910                 num_faces = mDrawable->getNumFaces();
03911                 for (i = 0; i < num_faces; i++)
03912                 {
03913                         num_indices += mDrawable->getFace(i)->getIndicesCount();
03914                 }
03915         }
03916         return num_indices;
03917 }
03918 
03919 // Find the number of instances of this object's inventory that are of the given type
03920 S32 LLViewerObject::countInventoryContents(LLAssetType::EType type)
03921 {
03922         S32 count = 0;
03923         if( mInventory )
03924         {
03925                 InventoryObjectList::const_iterator it = mInventory->begin();
03926                 InventoryObjectList::const_iterator end = mInventory->end();
03927                 for(  ; it != end ; ++it )
03928                 {
03929                         if( (*it)->getType() == type )
03930                         {
03931                                 ++count;
03932                         }
03933                 }
03934         }
03935         return count;
03936 }
03937 
03938 
03939 void LLViewerObject::setCanSelect(BOOL canSelect)
03940 {
03941         mbCanSelect = canSelect;
03942         for (U32 i = 0; i < mChildList.size(); i++)
03943         {
03944                 mChildList[i]->mbCanSelect = canSelect;
03945         }
03946 }
03947 
03948 void LLViewerObject::setDebugText(const std::string &utf8text)
03949 {
03950         if (utf8text.empty() && !mText)
03951         {
03952                 return;
03953         }
03954 
03955         if (!mText)
03956         {
03957                 mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
03958                 mText->setFont(LLFontGL::sSansSerif);
03959                 mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
03960                 mText->setMaxLines(-1);
03961                 mText->setSourceObject(this);
03962                 mText->setOnHUDAttachment(isHUDAttachment());
03963         }
03964         mText->setColor(LLColor4::white);
03965         mText->setStringUTF8(utf8text);
03966         mText->setZCompare(FALSE);
03967         mText->setDoFade(FALSE);
03968         updateText();
03969 }
03970 
03971 void LLViewerObject::setIcon(LLViewerImage* icon_image)
03972 {
03973         if (!mIcon)
03974         {
03975                 mIcon = (LLHUDIcon *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_ICON);
03976                 mIcon->setSourceObject(this);
03977                 mIcon->setImage(icon_image);
03978                 // *TODO: make this user configurable
03979                 mIcon->setScale(0.03f);
03980         }
03981         else
03982         {
03983                 mIcon->restartLifeTimer();
03984         }
03985 }
03986 
03987 void LLViewerObject::clearIcon()
03988 {
03989         if (mIcon)
03990         {
03991                 mIcon = NULL;
03992         }
03993 }
03994 
03995 LLViewerObject* LLViewerObject::getSubParent() 
03996 { 
03997         if (isJointChild())
03998         {
03999                 return this;
04000         }
04001         return (LLViewerObject*) getParent();
04002 }
04003 
04004 const LLViewerObject* LLViewerObject::getSubParent() const
04005 {
04006         if (isJointChild())
04007         {
04008                 return this;
04009         }
04010         return (const LLViewerObject*) getParent();
04011 }
04012 
04013 BOOL LLViewerObject::isOnMap()
04014 {
04015         return mOnMap;
04016 }
04017 
04018 
04019 void LLViewerObject::updateText()
04020 {
04021         if (!isDead())
04022         {
04023                 if (mText.notNull())
04024                 {               
04025                         LLVector3 up_offset(0,0,0);
04026                         up_offset.mV[2] = getScale().mV[VZ]*0.6f;
04027                         
04028                         if (mDrawable.notNull())
04029                         {
04030                                 mText->setPositionAgent(getRenderPosition() + up_offset);
04031                         }
04032                         else
04033                         {
04034                                 mText->setPositionAgent(getPositionAgent() + up_offset);
04035                         }
04036                 }
04037         }
04038 }
04039 
04040 BOOL LLViewerObject::isParticleSource() const
04041 {
04042         return !mPartSourcep.isNull() && !mPartSourcep->isDead();
04043 }
04044 
04045 void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& owner_id)
04046 {
04047         if (!mPartSourcep.isNull() && mPartSourcep->isDead())
04048         {
04049                 mPartSourcep = NULL;
04050         }
04051         if (mPartSourcep)
04052         {
04053                 // If we've got one already, just update the existing source (or remove it)
04054                 if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, block_num))
04055                 {
04056                         mPartSourcep->setDead();
04057                         mPartSourcep = NULL;
04058                 }
04059         }
04060         else
04061         {
04062                 LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, block_num);
04063                 //If the owner is muted, don't create the system
04064                 if(gMuteListp->isMuted(owner_id, LLMute::flagParticles)) return;
04065 
04066                 // We need to be able to deal with a particle source that hasn't changed, but still got an update!
04067                 if (pss)
04068                 {
04069 //                      llinfos << "Making particle system with owner " << owner_id << llendl;
04070                         pss->setOwnerUUID(owner_id);
04071                         mPartSourcep = pss;
04072                         gWorldPointer->mPartSim.addPartSource(pss);
04073                 }
04074         }
04075         if (mPartSourcep)
04076         {
04077                 if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID)
04078                 {
04079                         LLViewerImage* image;
04080                         if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null)
04081                         {
04082                                 LLUUID id(gViewerArt.getString("pixiesmall.tga"));
04083                                 image = gImageList.getImage(id);
04084                         }
04085                         else
04086                         {
04087                                 image = gImageList.getImage(mPartSourcep->mPartSysData.mPartImageID);
04088                         }
04089                         mPartSourcep->setImage(image);
04090                 }
04091         }
04092 }
04093 
04094 void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id)
04095 {
04096         if (!mPartSourcep.isNull() && mPartSourcep->isDead())
04097         {
04098                 mPartSourcep = NULL;
04099         }
04100         if (mPartSourcep)
04101         {
04102                 // If we've got one already, just update the existing source (or remove it)
04103                 if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp))
04104                 {
04105                         mPartSourcep->setDead();
04106                         mPartSourcep = NULL;
04107                 }
04108         }
04109         else
04110         {
04111                 LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp);
04112                 //If the owner is muted, don't create the system
04113                 if(gMuteListp->isMuted(owner_id, LLMute::flagParticles)) return;
04114                 // We need to be able to deal with a particle source that hasn't changed, but still got an update!
04115                 if (pss)
04116                 {
04117 //                      llinfos << "Making particle system with owner " << owner_id << llendl;
04118                         pss->setOwnerUUID(owner_id);
04119                         mPartSourcep = pss;
04120                         gWorldPointer->mPartSim.addPartSource(pss);
04121                 }
04122         }
04123         if (mPartSourcep)
04124         {
04125                 if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID)
04126                 {
04127                         LLViewerImage* image;
04128                         if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null)
04129                         {
04130                                 LLUUID id(gViewerArt.getString("pixiesmall.tga"));
04131                                 image = gImageList.getImage(id);
04132                         }
04133                         else
04134                         {
04135                                 image = gImageList.getImage(mPartSourcep->mPartSysData.mPartImageID);
04136                         }
04137                         mPartSourcep->setImage(image);
04138                 }
04139         }
04140 }
04141 
04142 void LLViewerObject::deleteParticleSource()
04143 {
04144         if (mPartSourcep.notNull())
04145         {
04146                 mPartSourcep->setDead();
04147                 mPartSourcep = NULL;
04148         }
04149 }
04150 
04151 // virtual
04152 void LLViewerObject::updateDrawable(BOOL force_damped)
04153 {
04154         if (mDrawable.notNull() && 
04155                 !mDrawable->isState(LLDrawable::ON_MOVE_LIST) &&
04156                 isChanged(MOVED) && 
04157                 !isAvatar())
04158         {
04159                 mLastUpdateFrame = LLFrameTimer::getFrameCount();
04160                 BOOL damped_motion = 
04161                         !isChanged(SHIFTED) &&                                                                          // not shifted between regions this frame and...
04162                                 (force_damped ||                                                                                // ...forced into damped motion by application logic or...
04163                                         (!isSelected() &&                                                                       // ...not selected and...
04164                                         (mDrawable->isRoot() ||                                                         // ... is root or ...
04165                                         !((LLViewerObject*)getParent())->isSelected()) &&       // ... parent is not selected and ...
04166                                         getPCode() == LL_PCODE_VOLUME &&                                        // ...is a volume object and...
04167                                         getVelocity().isExactlyZero() &&                                        // ...is not moving physically and...
04168                                         mDrawable->getGeneration() != -1)                                       // ...was not created this frame.
04169                         );
04170                 gPipeline.markMoved(mDrawable, damped_motion);
04171         }
04172         clearChanged(SHIFTED);
04173 }
04174 
04175 // virtual, overridden by LLVOVolume
04176 F32 LLViewerObject::getVObjRadius() const
04177 {
04178         return mDrawable.notNull() ? mDrawable->getRadius() : 0.f;
04179 }
04180 
04181 void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags)
04182 {
04183         if (!gAudiop)
04184         {
04185                 return;
04186         }
04187         
04188         if (audio_uuid.isNull())
04189         {
04190                 if (!mAudioSourcep)
04191                 {
04192                         return;
04193                 }
04194                 if (mAudioSourcep->isLoop() && !mAudioSourcep->hasPendingPreloads())
04195                 {
04196                         // We don't clear the sound if it's a loop, it'll go away on its own.
04197                         // At least, this appears to be how the scripts work.
04198                         // The attached sound ID is set to NULL to avoid it playing back when the
04199                         // object rezzes in on non-looping sounds.
04200                         //llinfos << "Clearing attached sound " << mAudioSourcep->getCurrentData()->getID() << llendl;
04201                         gAudiop->cleanupAudioSource(mAudioSourcep);
04202                         mAudioSourcep = NULL;
04203                 }
04204                 else if (flags & LL_SOUND_FLAG_STOP)
04205         {
04206                         // Just shut off the sound
04207                         mAudioSourcep->play(LLUUID::null);
04208                 }
04209                 return;
04210         }
04211         if (flags & LL_SOUND_FLAG_LOOP
04212                 && mAudioSourcep && mAudioSourcep->isLoop() && mAudioSourcep->getCurrentData()
04213                 && mAudioSourcep->getCurrentData()->getID() == audio_uuid)
04214         {
04215                 //llinfos << "Already playing this sound on a loop, ignoring" << llendl;
04216                 return;
04217         }
04218 
04219         // don't clean up before previous sound is done. Solves: SL-33486
04220         if ( mAudioSourcep && mAudioSourcep->isDone() ) 
04221         {
04222                 gAudiop->cleanupAudioSource(mAudioSourcep);
04223                 mAudioSourcep = NULL;
04224         }
04225 
04226         getAudioSource(owner_id);
04227 
04228         if (mAudioSourcep)
04229         {
04230                 BOOL queue = flags & LL_SOUND_FLAG_QUEUE;
04231                 mAudioGain = gain;
04232                 F32 volume = gain * gSavedSettings.getF32("AudioLevelSFX");
04233                 mAudioSourcep->setGain(volume);
04234                 mAudioSourcep->setLoop(flags & LL_SOUND_FLAG_LOOP);
04235                 mAudioSourcep->setSyncMaster(flags & LL_SOUND_FLAG_SYNC_MASTER);
04236                 mAudioSourcep->setSyncSlave(flags & LL_SOUND_FLAG_SYNC_SLAVE);
04237                 mAudioSourcep->setQueueSounds(queue);
04238                 if(!queue) // stop any current sound first to avoid "farts of doom" (SL-1541) -MG
04239                 {
04240                         mAudioSourcep->play(LLUUID::null);
04241                 }
04242                 //llinfos << "Playing attached sound " << audio_uuid << llendl;
04243                 mAudioSourcep->play(audio_uuid);
04244         }
04245 }
04246 
04247 LLAudioSource *LLViewerObject::getAudioSource(const LLUUID& owner_id)
04248 {
04249         if (!mAudioSourcep)
04250         {
04251                 // Arbitrary low gain for a sound that's not playing.
04252                 // This is used for sound preloads, for example.
04253                 LLAudioSourceVO *asvop = new LLAudioSourceVO(mID, owner_id, 0.01f, this);
04254 
04255                 mAudioSourcep = asvop;
04256                 if(gAudiop) gAudiop->addAudioSource(asvop);
04257         }
04258 
04259         return mAudioSourcep;
04260 }
04261 
04262 void LLViewerObject::adjustAudioGain(const F32 gain)
04263 {
04264         if (!gAudiop)
04265         {
04266                 return;
04267         }
04268         if (mAudioSourcep)
04269         {
04270                 mAudioGain = gain;
04271                 F32 volume = mAudioGain * gSavedSettings.getF32("AudioLevelSFX");
04272                 mAudioSourcep->setGain(volume);
04273         }
04274 }
04275 
04276 //----------------------------------------------------------------------------
04277 
04278 bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp)
04279 {
04280         ExtraParameter* param = getExtraParameterEntryCreate(param_type);
04281         if (param)
04282         {
04283                 param->data->unpack(*dp);
04284                 param->in_use = TRUE;
04285                 parameterChanged(param_type, param->data, TRUE, false);
04286                 return true;
04287         }
04288         else
04289         {
04290                 return false;
04291         }
04292 }
04293 
04294 LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 param_type)
04295 {
04296         LLNetworkData* new_block = NULL;
04297         switch (param_type)
04298         {
04299           case LLNetworkData::PARAMS_FLEXIBLE:
04300           {
04301                   new_block = new LLFlexibleObjectData();
04302                   break;
04303           }
04304           case LLNetworkData::PARAMS_LIGHT:
04305           {
04306                   new_block = new LLLightParams();
04307                   break;
04308           }
04309           case LLNetworkData::PARAMS_SCULPT:
04310           {
04311                   new_block = new LLSculptParams();
04312                   break;
04313           }
04314 
04315           default:
04316           {
04317                   llinfos << "Unknown param type." << llendl;
04318                   break;
04319           }
04320         };
04321 
04322         if (new_block)
04323         {
04324                 ExtraParameter* new_entry = new ExtraParameter;
04325                 new_entry->data = new_block;
04326                 new_entry->in_use = false; // not in use yet
04327                 mExtraParameterList[param_type] = new_entry;
04328                 return new_entry;
04329         }
04330         return NULL;
04331 }
04332 
04333 LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const
04334 {
04335         std::map<U16, ExtraParameter*>::const_iterator itor = mExtraParameterList.find(param_type);
04336         if (itor != mExtraParameterList.end())
04337         {
04338                 return itor->second;
04339         }
04340         return NULL;
04341 }
04342 
04343 LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntryCreate(U16 param_type)
04344 {
04345         ExtraParameter* param = getExtraParameterEntry(param_type);
04346         if (!param)
04347         {
04348                 param = createNewParameterEntry(param_type);
04349         }
04350         return param;
04351 }
04352 
04353 LLNetworkData* LLViewerObject::getParameterEntry(U16 param_type) const
04354 {
04355         ExtraParameter* param = getExtraParameterEntry(param_type);
04356         if (param)
04357         {
04358                 return param->data;
04359         }
04360         else
04361         {
04362                 return NULL;
04363         }
04364 }
04365 
04366 BOOL LLViewerObject::getParameterEntryInUse(U16 param_type) const
04367 {
04368         ExtraParameter* param = getExtraParameterEntry(param_type);
04369         if (param)
04370         {
04371                 return param->in_use;
04372         }
04373         else
04374         {
04375                 return FALSE;
04376         }
04377 }
04378 
04379 bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin)
04380 {
04381         ExtraParameter* param = getExtraParameterEntryCreate(param_type);
04382         if (param)
04383         {
04384                 if (param->in_use && new_value == *(param->data))
04385                 {
04386                         return false;
04387                 }
04388                 param->in_use = true;
04389                 param->data->copy(new_value);
04390                 parameterChanged(param_type, param->data, TRUE, local_origin);
04391                 return true;
04392         }
04393         else
04394         {
04395                 return false;
04396         }
04397 }
04398 
04399 // Assumed to be called locally
04400 // If in_use is TRUE, will crate a new extra parameter if none exists.
04401 // Should always return true.
04402 bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin)
04403 {
04404         ExtraParameter* param = getExtraParameterEntryCreate(param_type);
04405         if (param->in_use != in_use)
04406         {
04407                 param->in_use = in_use;
04408                 parameterChanged(param_type, param->data, in_use, local_origin);
04409                 return true;
04410         }
04411         return false;
04412 }
04413 
04414 void LLViewerObject::parameterChanged(U16 param_type, bool local_origin)
04415 {
04416         ExtraParameter* param = getExtraParameterEntry(param_type);
04417         if (param)
04418         {
04419                 parameterChanged(param_type, param->data, param->in_use, local_origin);
04420         }
04421 }
04422 
04423 void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin)
04424 {
04425         if (local_origin)
04426         {
04427                 LLViewerRegion* regionp = getRegion();
04428                 if(!regionp) return;
04429 
04430                 // Change happened on the viewer. Send the change up
04431                 U8 tmp[MAX_OBJECT_PARAMS_SIZE];
04432                 LLDataPackerBinaryBuffer dpb(tmp, MAX_OBJECT_PARAMS_SIZE);
04433                 if (data->pack(dpb))
04434                 {
04435                         U32 datasize = (U32)dpb.getCurrentSize();
04436 
04437                         LLMessageSystem* msg = gMessageSystem;
04438                         msg->newMessageFast(_PREHASH_ObjectExtraParams);
04439                         msg->nextBlockFast(_PREHASH_AgentData);
04440                         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
04441                         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
04442                         msg->nextBlockFast(_PREHASH_ObjectData);
04443                         msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID );
04444 
04445                         msg->addU16Fast(_PREHASH_ParamType, param_type);
04446                         msg->addBOOLFast(_PREHASH_ParamInUse, in_use);
04447 
04448                         msg->addU32Fast(_PREHASH_ParamSize, datasize);
04449                         msg->addBinaryDataFast(_PREHASH_ParamData, tmp, datasize);
04450 
04451                         msg->sendReliable( regionp->getHost() );
04452                 }
04453                 else
04454                 {
04455                         llwarns << "Failed to send object extra parameters: " << param_type << llendl;
04456                 }
04457         }
04458 }
04459 
04460 void LLViewerObject::setDrawableState(U32 state, BOOL recursive)
04461 {
04462         if (mDrawable)
04463         {
04464                 mDrawable->setState(state);
04465         }
04466         if (recursive)
04467         {
04468                 for (U32 i = 0; i < mChildList.size(); i++)
04469                 {
04470                         mChildList[i]->setDrawableState(state, recursive);
04471                 }
04472         }
04473 }
04474 
04475 void LLViewerObject::clearDrawableState(U32 state, BOOL recursive)
04476 {
04477         if (mDrawable)
04478         {
04479                 mDrawable->clearState(state);
04480         }
04481         if (recursive)
04482         {
04483                 for (U32 i = 0; i < mChildList.size(); i++)
04484                 {
04485                         mChildList[i]->clearDrawableState(state, recursive);
04486                 }
04487         }
04488 }
04489 
04491 // RN: these functions assume a 2-level hierarchy 
04493 
04494 // Owned by anyone?
04495 BOOL LLViewerObject::permAnyOwner() const
04496 { 
04497         if (isRootEdit())
04498         {
04499                 return ((mFlags & FLAGS_OBJECT_ANY_OWNER) != 0); 
04500         }
04501         else
04502         {
04503                 return ((LLViewerObject*)getParent())->permAnyOwner();
04504         }
04505 }       
04506 // Owned by this viewer?
04507 BOOL LLViewerObject::permYouOwner() const
04508 { 
04509         if (isRootEdit())
04510         {
04511 #ifdef HACKED_GODLIKE_VIEWER
04512                 return TRUE;
04513 #else
04514 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
04515                 if (!gInProductionGrid && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
04516                 {
04517                         return TRUE;
04518                 }
04519 # endif
04520                 return ((mFlags & FLAGS_OBJECT_YOU_OWNER) != 0); 
04521 #endif
04522         }
04523         else
04524         {
04525                 return ((LLViewerObject*)getParent())->permYouOwner();
04526         }
04527 }
04528 
04529 // Owned by a group?
04530 BOOL LLViewerObject::permGroupOwner() const             
04531 { 
04532         if (isRootEdit())
04533         {
04534                 return ((mFlags & FLAGS_OBJECT_GROUP_OWNED) != 0); 
04535         }
04536         else
04537         {
04538                 return ((LLViewerObject*)getParent())->permGroupOwner();
04539         }
04540 }
04541 
04542 // Can the owner edit
04543 BOOL LLViewerObject::permOwnerModify() const
04544 { 
04545         if (isRootEdit())
04546         {
04547 #ifdef HACKED_GODLIKE_VIEWER
04548                 return TRUE;
04549 #else
04550 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
04551                 if (!gInProductionGrid && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
04552         {
04553                         return TRUE;
04554         }
04555 # endif
04556                 return ((mFlags & FLAGS_OBJECT_OWNER_MODIFY) != 0); 
04557 #endif
04558         }
04559         else
04560         {
04561                 return ((LLViewerObject*)getParent())->permOwnerModify();
04562         }
04563 }
04564 
04565 // Can edit
04566 BOOL LLViewerObject::permModify() const
04567 { 
04568         if (isRootEdit())
04569         {
04570 #ifdef HACKED_GODLIKE_VIEWER
04571                 return TRUE;
04572 #else
04573 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
04574                 if (!gInProductionGrid && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
04575         {
04576                         return TRUE;
04577         }
04578 # endif
04579                 return ((mFlags & FLAGS_OBJECT_MODIFY) != 0); 
04580 #endif
04581         }
04582         else
04583         {
04584                 return ((LLViewerObject*)getParent())->permModify();
04585         }
04586 }
04587 
04588 // Can copy
04589 BOOL LLViewerObject::permCopy() const
04590 { 
04591         if (isRootEdit())
04592         {
04593 #ifdef HACKED_GODLIKE_VIEWER
04594                 return TRUE;
04595 #else
04596 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
04597                 if (!gInProductionGrid && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
04598                 {
04599                         return TRUE;
04600                 }
04601 # endif
04602                 return ((mFlags & FLAGS_OBJECT_COPY) != 0); 
04603 #endif
04604         }
04605         else
04606         {
04607                 return ((LLViewerObject*)getParent())->permCopy();
04608         }
04609 }
04610 
04611 // Can move
04612 BOOL LLViewerObject::permMove() const
04613 {
04614         if (isRootEdit())
04615         {
04616 #ifdef HACKED_GODLIKE_VIEWER
04617                 return TRUE;
04618 #else
04619 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
04620                 if (!gInProductionGrid && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
04621                 {
04622                         return TRUE;
04623                 }
04624 # endif
04625                 return ((mFlags & FLAGS_OBJECT_MOVE) != 0); 
04626 #endif
04627         }
04628         else
04629         {
04630                 return ((LLViewerObject*)getParent())->permMove();
04631         }
04632 }
04633 
04634 // Can be transferred
04635 BOOL LLViewerObject::permTransfer() const
04636 { 
04637         if (isRootEdit())
04638         {
04639 #ifdef HACKED_GODLIKE_VIEWER
04640                 return TRUE;
04641 #else
04642 # ifdef TOGGLE_HACKED_GODLIKE_VIEWER
04643                 if (!gInProductionGrid && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
04644                 {
04645                         return TRUE;
04646                 }
04647 # endif
04648                 return ((mFlags & FLAGS_OBJECT_TRANSFER) != 0); 
04649 #endif
04650         }
04651         else
04652         {
04653                 return ((LLViewerObject*)getParent())->permTransfer();
04654         }
04655 }
04656 
04657 // Can only open objects that you own, or that someone has
04658 // given you modify rights to.  JC
04659 BOOL LLViewerObject::allowOpen() const
04660 {
04661         return !flagInventoryEmpty() && (permYouOwner() || permModify());
04662 }
04663 
04664 LLViewerObject::LLInventoryCallbackInfo::~LLInventoryCallbackInfo()
04665 {
04666         if (mListener)
04667         {
04668                 mListener->clearVOInventoryListener();
04669         }
04670 }
04671 
04672 void LLViewerObject::updateVolume(const LLVolumeParams& volume_params)
04673 {
04674         if (setVolume(volume_params, 1)) // *FIX: magic number, ack!
04675         {
04676                 // Transmit the update to the simulator
04677                 sendShapeUpdate();
04678                 markForUpdate(TRUE);
04679         }
04680 }
04681 
04682 void LLViewerObject::markForUpdate(BOOL priority)
04683 {
04684         if (mDrawable.notNull())
04685         {
04686                 gPipeline.markTextured(mDrawable);
04687                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, priority);
04688         }
04689 }
04690 
04691 bool LLViewerObject::getIncludeInSearch() const
04692 {
04693         return ((mFlags & FLAGS_INCLUDE_IN_SEARCH) != 0);
04694 }
04695 
04696 void LLViewerObject::setIncludeInSearch(bool include_in_search)
04697 {
04698         if (include_in_search)
04699         {
04700                 mFlags |= FLAGS_INCLUDE_IN_SEARCH;
04701         }
04702         else
04703         {
04704                 mFlags &= ~FLAGS_INCLUDE_IN_SEARCH;
04705         }
04706 }
04707 
04708 void LLViewerObject::setRegion(LLViewerRegion *regionp)
04709 {
04710         llassert(regionp);
04711         mLatestRecvPacketID = 0;
04712         mRegionp = regionp;
04713 
04714         for (child_list_t::iterator i = getChildren().begin(); i != getChildren().end(); ++i)
04715         {
04716                 LLViewerObject* child = *i;
04717                 child->setRegion(regionp);
04718         }
04719 
04720         setChanged(MOVED | SILHOUETTE);
04721         updateDrawable(FALSE);
04722 }
04723 
04724 bool LLViewerObject::specialHoverCursor() const
04725 {
04726         return (mFlags & FLAGS_USE_PHYSICS)
04727                         || (mFlags & FLAGS_HANDLE_TOUCH)
04728                         || (mClickAction != 0);
04729 }
04730 
04731 void LLViewerObject::updateFlags()
04732 {
04733         LLViewerRegion* regionp = getRegion();
04734         if(!regionp) return;
04735         gMessageSystem->newMessage("ObjectFlagUpdate");
04736         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
04737         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
04738         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
04739         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, getLocalID() );
04740         gMessageSystem->addBOOLFast(_PREHASH_UsePhysics, usePhysics() );
04741         gMessageSystem->addBOOL("IsTemporary", flagTemporaryOnRez() );
04742         gMessageSystem->addBOOL("IsPhantom", flagPhantom() );
04743         gMessageSystem->addBOOL("CastsShadows", flagCastShadows() );
04744         gMessageSystem->sendReliable( regionp->getHost() );
04745 }
04746 
04747 BOOL LLViewerObject::setFlags(U32 flags, BOOL state)
04748 {
04749         BOOL setit = FALSE;
04750         if (state)
04751         {
04752                 if ((mFlags & flags) != flags)
04753                 {
04754                         mFlags |= flags;
04755                         setit = TRUE;
04756                 }
04757         }
04758         else
04759         {
04760                 if ((mFlags & flags) != 0)
04761                 {
04762                         mFlags &= ~flags;
04763                         setit = TRUE;
04764                 }
04765         }
04766 
04767         // BUG: Sometimes viewer physics and simulator physics get
04768         // out of sync.  To fix this, always send update to simulator.
04769 //      if (setit)
04770         {
04771                 updateFlags();
04772         }
04773         return setit;
04774 }
04775 
04776 BOOL LLViewerObject::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
04777 {
04778         return FALSE;
04779 }
04780 
04781 void LLViewerObject::applyAngularVelocity(F32 dt)
04782 {
04783         //do target omega here
04784         mRotTime += dt;
04785         LLVector3 ang_vel = getAngularVelocity();
04786         F32 omega = ang_vel.magVecSquared();
04787         F32 angle = 0.0f;
04788         LLQuaternion dQ;
04789         if (omega > 0.00001f)
04790         {
04791                 omega = sqrt(omega);
04792                 angle = omega * dt;
04793 
04794                 ang_vel *= 1.f/omega;
04795                 
04796                 dQ.setQuat(angle, ang_vel);
04797                 
04798                 setRotation(getRotation()*dQ);
04799                 setChanged(MOVED | SILHOUETTE);
04800         }
04801 }
04802 
04803 void LLViewerObject::resetRot()
04804 {
04805         mRotTime = 0.0f;
04806 }
04807 
04808 U32 LLViewerObject::getPartitionType() const
04809 { 
04810         return LLPipeline::PARTITION_NONE; 
04811 }
04812 
04813 BOOL LLAlphaObject::isParticle()
04814 {
04815         return FALSE;
04816 }
04817 
04818 F32 LLAlphaObject::getPartSize(S32 idx)
04819 {
04820         return 0.f;
04821 }
04822 
04823 // virtual
04824 void LLStaticViewerObject::updateDrawable(BOOL force_damped)
04825 {
04826         // Force an immediate rebuild on any update
04827         if (mDrawable.notNull())
04828         {
04829                 mDrawable->updateXform(TRUE);
04830                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
04831         }
04832         clearChanged(SHIFTED);
04833 }

Generated on Thu Jul 1 06:09:32 2010 for Second Life Viewer by  doxygen 1.4.7