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

Generated on Fri May 16 08:34:15 2008 for SecondLife by  doxygen 1.5.5