llviewerobjectlist.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewerobjectlist.h"
00035 
00036 #include "message.h"
00037 #include "timing.h"
00038 #include "llfasttimer.h"
00039 
00040 #include "llviewercontrol.h"
00041 #include "llface.h"
00042 #include "llvoavatar.h"
00043 #include "llviewerobject.h"
00044 #include "llviewerwindow.h"
00045 #include "viewer.h"
00046 #include "llnetmap.h"
00047 #include "llagent.h"
00048 #include "pipeline.h"
00049 #include "llhoverview.h"
00050 #include "llworld.h"
00051 #include "llstring.h"
00052 #include "llhudtext.h"
00053 #include "lldrawable.h"
00054 #include "xform.h"
00055 #include "llsky.h"
00056 #include "llviewercamera.h"
00057 #include "llselectmgr.h"
00058 #include "llresmgr.h"
00059 #include "llviewerregion.h"
00060 #include "llviewerstats.h"
00061 #include "lltoolmgr.h"
00062 #include "lltoolpie.h"
00063 #include "llkeyboard.h"
00064 #include "u64.h"
00065 #include "llviewerimagelist.h"
00066 #include "lldatapacker.h"
00067 #ifdef LL_STANDALONE
00068 #include <zlib.h>
00069 #else
00070 #include "zlib/zlib.h"
00071 #endif
00072 #include "object_flags.h"
00073 
00074 extern BOOL gVelocityInterpolate;
00075 extern BOOL gPingInterpolate;
00076 extern F32 gMinObjectDistance;
00077 extern U32 gFrameCount;
00078 extern LLTimer gRenderStartTime;
00079 extern BOOL gAnimateTextures;
00080 
00081 void dialog_refresh_all();
00082 
00083 #define CULL_VIS
00084 //#define ORPHAN_SPAM
00085 //#define IGNORE_DEAD
00086 
00087 // Global lists of objects - should go away soon.
00088 LLViewerObjectList gObjectList;
00089 
00090 extern LLPipeline       gPipeline;
00091 
00092 // Statics for object lookup tables.
00093 U32                                             LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check.
00094 LLMap<U64, U32>                 LLViewerObjectList::sIPAndPortToIndex;
00095 std::map<U64, LLUUID>   LLViewerObjectList::sIndexAndLocalIDToUUID;
00096 
00097 LLViewerObjectList::LLViewerObjectList()
00098 {
00099         mNumVisCulled = 0;
00100         mNumSizeCulled = 0;
00101         mCurLazyUpdateIndex = 0;
00102         mCurBin = 0;
00103         mNumDeadObjects = 0;
00104         mNumOrphans = 0;
00105         mNumNewObjects = 0;
00106         mWasPaused = FALSE;
00107         mNumDeadObjectUpdates = 0;
00108         mNumUnknownKills = 0;
00109         mNumUnknownUpdates = 0;
00110 }
00111 
00112 LLViewerObjectList::~LLViewerObjectList()
00113 {
00114         destroy();
00115 }
00116 
00117 void LLViewerObjectList::destroy()
00118 {
00119         killAllObjects();
00120 
00121         resetObjectBeacons();
00122         mActiveObjects.clear();
00123         mDeadObjects.clear();
00124         mMapObjects.clear();
00125         mUUIDObjectMap.clear();
00126 }
00127 
00128 
00129 void LLViewerObjectList::getUUIDFromLocal(LLUUID &id,
00130                                                                                   const U32 local_id,
00131                                                                                   const U32 ip,
00132                                                                                   const U32 port)
00133 {
00134         U64 ipport = (((U64)ip) << 32) | (U64)port;
00135 
00136         U32 index = sIPAndPortToIndex[ipport];
00137 
00138         if (!index)
00139         {
00140                 index = sSimulatorMachineIndex++;
00141                 sIPAndPortToIndex[ipport] = index;
00142         }
00143 
00144         U64     indexid = (((U64)index) << 32) | (U64)local_id;
00145 
00146         id = get_if_there(sIndexAndLocalIDToUUID, indexid, LLUUID::null);
00147 }
00148 
00149 U64 LLViewerObjectList::getIndex(const U32 local_id,
00150                                                                  const U32 ip,
00151                                                                  const U32 port)
00152 {
00153         U64 ipport = (((U64)ip) << 32) | (U64)port;
00154 
00155         U32 index = sIPAndPortToIndex[ipport];
00156 
00157         if (!index)
00158         {
00159                 return 0;
00160         }
00161 
00162         return (((U64)index) << 32) | (U64)local_id;
00163 }
00164 
00165 BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object)
00166 {
00167         U32 local_id = object.mLocalID;
00168         LLHost region_host = object.getRegion()->getHost();
00169         U32 ip = region_host.getAddress();
00170         U32 port = region_host.getPort();
00171         U64 ipport = (((U64)ip) << 32) | (U64)port;
00172         U32 index = sIPAndPortToIndex[ipport];
00173 
00174         U64     indexid = (((U64)index) << 32) | (U64)local_id;
00175         return sIndexAndLocalIDToUUID.erase(indexid) > 0 ? TRUE : FALSE;
00176 }
00177 
00178 void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id,
00179                                                                                   const U32 local_id,
00180                                                                                   const U32 ip,
00181                                                                                   const U32 port)
00182 {
00183         U64 ipport = (((U64)ip) << 32) | (U64)port;
00184 
00185         U32 index = sIPAndPortToIndex[ipport];
00186 
00187         if (!index)
00188         {
00189                 index = sSimulatorMachineIndex++;
00190                 sIPAndPortToIndex[ipport] = index;
00191         }
00192 
00193         U64     indexid = (((U64)index) << 32) | (U64)local_id;
00194 
00195         sIndexAndLocalIDToUUID[indexid] = id;
00196 }
00197 
00198 S32 gFullObjectUpdates = 0;
00199 S32 gTerseObjectUpdates = 0;
00200 
00201 void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, 
00202                                                                                    void** user_data, 
00203                                                                                    U32 i, 
00204                                                                                    const EObjectUpdateType update_type, 
00205                                                                                    LLDataPacker* dpp, 
00206                                                                                    BOOL just_created)
00207 {
00208         LLMessageSystem* msg = gMessageSystem;
00209 
00210         // ignore returned flags
00211         objectp->processUpdateMessage(msg, user_data, i, update_type, dpp);
00212 
00213         if (objectp->isDead())
00214         {
00215                 // The update failed
00216                 return;
00217         }
00218         updateActive(objectp);
00219 
00220         // Also sets the approx. pixel area
00221         objectp->setPixelAreaAndAngle(gAgent);
00222 
00223         // Update the image levels of textures for this object.
00224         objectp->updateTextures(gAgent);
00225 
00226         if (just_created) 
00227         {
00228                 gPipeline.addObject(objectp);
00229         }
00230 
00231         // RN: this must be called after we have a drawable 
00232         // (from gPipeline.addObject)
00233         // so that the drawable parent is set properly
00234         findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
00235 
00236         // If we're just wandering around, don't create new objects selected.
00237         if (just_created 
00238                 && update_type != OUT_TERSE_IMPROVED 
00239                 && objectp->mCreateSelected)
00240         {
00241                 if ( gToolMgr->getCurrentTool() != gToolPie )
00242                 {
00243                         //llinfos << "DEBUG selecting " << objectp->mID << " " 
00244                         //              << objectp->mLocalID << llendl;
00245                         gSelectMgr->selectObjectAndFamily(objectp);
00246                         dialog_refresh_all();
00247                 }
00248 
00249                 objectp->mCreateSelected = false;
00250                 gViewerWindow->getWindow()->decBusyCount();
00251                 gViewerWindow->getWindow()->setCursor( UI_CURSOR_ARROW );
00252         }
00253 }
00254 
00255 void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
00256                                                                                          void **user_data,
00257                                                                                          const EObjectUpdateType update_type,
00258                                                                                          bool cached, bool compressed)
00259 {
00260         LLFastTimer t(LLFastTimer::FTM_PROCESS_OBJECTS);        
00261         
00262         LLVector3d camera_global = gAgent.getCameraPositionGlobal();
00263         LLViewerObject *objectp;
00264         S32                     num_objects;
00265         U32                     local_id;
00266         LLPCode         pcode = 0;
00267         LLUUID          fullid;
00268         S32                     i;
00269 
00270         // figure out which simulator these are from and get it's index
00271         // Coordinates in simulators are region-local
00272         // Until we get region-locality working on viewer we
00273         // have to transform to absolute coordinates.
00274         num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
00275 
00276         if (!cached && !compressed && update_type != OUT_FULL)
00277         {
00278                 gTerseObjectUpdates += num_objects;
00279                 S32 size;
00280                 if (mesgsys->getReceiveCompressedSize())
00281                 {
00282                         size = mesgsys->getReceiveCompressedSize();
00283                 }
00284                 else
00285                 {
00286                         size = mesgsys->getReceiveSize();
00287                 }
00288 //              llinfos << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
00289         }
00290         else
00291         {
00292                 S32 size;
00293                 if (mesgsys->getReceiveCompressedSize())
00294                 {
00295                         size = mesgsys->getReceiveCompressedSize();
00296                 }
00297                 else
00298                 {
00299                         size = mesgsys->getReceiveSize();
00300                 }
00301 
00302 //              llinfos << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << llendl;
00303                 gFullObjectUpdates += num_objects;
00304         }
00305 
00306         U64 region_handle;
00307         mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
00308         LLViewerRegion *regionp = gWorldPointer->getRegionFromHandle(region_handle);
00309 
00310         if (!regionp)
00311         {
00312                 llwarns << "Object update from unknown region!" << llendl;
00313                 return;
00314         }
00315 
00316         U8 compressed_dpbuffer[2048];
00317         LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
00318         LLDataPacker *cached_dpp = NULL;
00319         
00320         for (i = 0; i < num_objects; i++)
00321         {
00322                 LLTimer update_timer;
00323                 BOOL justCreated = FALSE;
00324 
00325                 if (cached)
00326                 {
00327                         U32 id;
00328                         U32 crc;
00329                         mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);
00330                         mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
00331                 
00332                         // Lookup data packer and add this id to cache miss lists if necessary.
00333                         cached_dpp = regionp->getDP(id, crc);
00334                         if (cached_dpp)
00335                         {
00336                                 cached_dpp->reset();
00337                                 cached_dpp->unpackUUID(fullid, "ID");
00338                                 cached_dpp->unpackU32(local_id, "LocalID");
00339                                 cached_dpp->unpackU8(pcode, "PCode");
00340                         }
00341                         else
00342                         {
00343                                 continue; // no data packer, skip this object
00344                         }
00345                 }
00346                 else if (compressed)
00347                 {
00348                         U8                                                      compbuffer[2048];
00349                         S32                                                     uncompressed_length = 2048;
00350                         S32                                                     compressed_length;
00351                         
00352                         compressed_dp.reset();
00353 
00354                         U32 flags = 0;
00355                         if (update_type != OUT_TERSE_IMPROVED)
00356                         {
00357                                 mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
00358                         }
00359                         
00360                         if (flags & FLAGS_ZLIB_COMPRESSED)
00361                         {
00362                                 compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
00363                                 mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i);
00364                                 uncompressed_length = 2048;
00365                                 uncompress(compressed_dpbuffer, (unsigned long *)&uncompressed_length,
00366                                                    compbuffer, compressed_length);
00367                                 compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
00368                         }
00369                         else
00370                         {
00371                                 uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
00372                                 mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i);
00373                                 compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
00374                         }
00375 
00376 
00377                         if (update_type != OUT_TERSE_IMPROVED)
00378                         {
00379                                 compressed_dp.unpackUUID(fullid, "ID");
00380                                 compressed_dp.unpackU32(local_id, "LocalID");
00381                                 compressed_dp.unpackU8(pcode, "PCode");
00382                         }
00383                         else
00384                         {
00385                                 compressed_dp.unpackU32(local_id, "LocalID");
00386                                 getUUIDFromLocal(fullid,
00387                                                                  local_id,
00388                                                                  gMessageSystem->getSenderIP(),
00389                                                                  gMessageSystem->getSenderPort());
00390                                 if (fullid.isNull())
00391                                 {
00392                                         //llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl;
00393                                         mNumUnknownUpdates++;
00394                                 }
00395                         }
00396                 }
00397                 else if (update_type != OUT_FULL)
00398                 {
00399                         mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
00400                         getUUIDFromLocal(fullid,
00401                                                         local_id,
00402                                                         gMessageSystem->getSenderIP(),
00403                                                         gMessageSystem->getSenderPort());
00404                         if (fullid.isNull())
00405                         {
00406                                 //llwarns << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << llendl;
00407                                 mNumUnknownUpdates++;
00408                         }
00409                 }
00410                 else
00411                 {
00412                         mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
00413                         mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
00414                 //      llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl;
00415                 }
00416                 objectp = findObject(fullid);
00417 
00418                 // This looks like it will break if the local_id of the object doesn't change
00419                 // upon boundary crossing, but we check for region id matching later...
00420                 if (objectp && (objectp->mLocalID != local_id))
00421                 {
00422                         removeFromLocalIDTable(*objectp);
00423                         setUUIDAndLocal(fullid,
00424                                                         local_id,
00425                                                         gMessageSystem->getSenderIP(),
00426                                                         gMessageSystem->getSenderPort());
00427                 }
00428 
00429                 if (!objectp)
00430                 {
00431                         if (compressed)
00432                         {
00433                                 if (update_type == OUT_TERSE_IMPROVED)
00434                                 {
00435                                         //      llinfos << "terse update for an unknown object:" << fullid << llendl;
00436                                         continue;
00437                                 }
00438                         }
00439                         else if (cached)
00440                         {
00441                         }
00442                         else
00443                         {
00444                                 if (update_type != OUT_FULL)
00445                                 {
00446 //                                      llinfos << "terse update for an unknown object:" << fullid << llendl;
00447                                         continue;
00448                                 }
00449 
00450                                 mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i);
00451                         }
00452 #ifdef IGNORE_DEAD
00453                         if (mDeadObjects.find(fullid) != mDeadObjects.end())
00454                         {
00455                                 mNumDeadObjectUpdates++;
00456                                 //llinfos << "update for a dead object:" << fullid << llendl;
00457                                 continue;
00458                         }
00459 #endif
00460 
00461                         objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());
00462                         if (!objectp)
00463                         {
00464                                 continue;
00465                         }
00466                         justCreated = TRUE;
00467                         mNumNewObjects++;
00468                 }
00469                 else
00470                 {
00471                         if (objectp->getRegion() != regionp)
00472                         {
00473                                 // Object has changed region!  Update lookup tables, set region pointer.
00474                                 removeFromLocalIDTable(*objectp);
00475                                 setUUIDAndLocal(fullid,
00476                                                                 local_id,
00477                                                                 gMessageSystem->getSenderIP(),
00478                                                                 gMessageSystem->getSenderPort());
00479                                 objectp->setRegion(regionp);
00480                         }
00481                         objectp->updateRegion(regionp); // for LLVOAvatar
00482                 }
00483 
00484 
00485                 if (objectp->isDead())
00486                 {
00487                         llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;
00488                 }
00489 
00490                 if (compressed)
00491                 {
00492                         if (update_type != OUT_TERSE_IMPROVED)
00493                         {
00494                                 objectp->mLocalID = local_id;
00495                         }
00496                         processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated);
00497                         if (update_type != OUT_TERSE_IMPROVED)
00498                         {
00499                                 objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
00500                         }
00501                 }
00502                 else if (cached)
00503                 {
00504                         objectp->mLocalID = local_id;
00505                         processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated);
00506                 }
00507                 else
00508                 {
00509                         if (update_type == OUT_FULL)
00510                         {
00511                                 objectp->mLocalID = local_id;
00512                         }
00513                         processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);
00514                 }
00515         }
00516 
00517         LLVOAvatar::cullAvatarsByPixelArea();
00518 }
00519 
00520 void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem *mesgsys,
00521                                                                                          void **user_data,
00522                                                                                          const EObjectUpdateType update_type)
00523 {
00524         processObjectUpdate(mesgsys, user_data, update_type, false, true);
00525 }
00526 
00527 void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,
00528                                                                                          void **user_data,
00529                                                                                          const EObjectUpdateType update_type)
00530 {
00531         processObjectUpdate(mesgsys, user_data, update_type, true, false);
00532 }       
00533 
00534 void LLViewerObjectList::relightAllObjects()
00535 {
00536         for (S32 i = 0; i < mObjects.count(); i++)
00537         {
00538                 LLDrawable *drawable = mObjects[i]->mDrawable;
00539                 if (drawable)
00540                 {
00541                         gPipeline.markRelight(drawable);
00542                 }
00543         }
00544 }
00545 
00546 void LLViewerObjectList::dirtyAllObjectInventory()
00547 {
00548         S32 count = mObjects.count();
00549         for(S32 i = 0; i < count; ++i)
00550         {
00551                 mObjects[i]->dirtyInventory();
00552         }
00553 }
00554 
00555 void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
00556 {
00557         S32 i;
00558         S32 num_objects = 0;
00559         LLViewerObject *objectp;
00560 
00561         S32 num_updates, max_value;
00562         if (NUM_BINS - 1 == mCurBin)
00563         {
00564                 num_updates = mObjects.count() - mCurLazyUpdateIndex;
00565                 max_value = mObjects.count();
00566                 gImageList.setUpdateStats(TRUE);
00567         }
00568         else
00569         {
00570                 num_updates = (mObjects.count() / NUM_BINS) + 1;
00571                 max_value = llmin(mObjects.count(), mCurLazyUpdateIndex + num_updates);
00572         }
00573 
00574 
00575         if (!gNoRender)
00576         {
00577                 // Slam priorities for textures that we care about (hovered, selected, and focused)
00578                 // Hovered
00579                 // Assumes only one level deep of parenting
00580                 objectp = gHoverView->getLastHoverObject();
00581                 if (objectp)
00582                 {
00583                         objectp->boostTexturePriority();
00584                 }
00585         }
00586 
00587         // Focused
00588         objectp = gAgent.getFocusObject();
00589         if (objectp)
00590         {
00591                 objectp->boostTexturePriority();
00592         }
00593 
00594         // Selected
00595         struct f : public LLSelectedObjectFunctor
00596         {
00597                 virtual bool apply(LLViewerObject* objectp)
00598                 {
00599                         objectp->boostTexturePriority();
00600                         return true;
00601                 }
00602         } func;
00603         gSelectMgr->getSelection()->applyToRootObjects(&func);
00604 
00605         // Iterate through some of the objects and lazy update their texture priorities
00606         for (i = mCurLazyUpdateIndex; i < max_value; i++)
00607         {
00608                 objectp = mObjects[i];
00609                 if (!objectp->isDead())
00610                 {
00611                         num_objects++;
00612 
00613                         //  Update distance & gpw 
00614                         objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area
00615                         objectp->updateTextures(agent); // Update the image levels of textures for this object.
00616                 }
00617         }
00618 
00619         mCurLazyUpdateIndex = max_value;
00620         if (mCurLazyUpdateIndex == mObjects.count())
00621         {
00622                 mCurLazyUpdateIndex = 0;
00623         }
00624 
00625         mCurBin = (++mCurBin) % NUM_BINS;
00626 
00627         LLVOAvatar::cullAvatarsByPixelArea();
00628 }
00629 
00630 
00631 void LLViewerObjectList::update(LLAgent &agent, LLWorld &world)
00632 {
00633         LLMemType mt(LLMemType::MTYPE_OBJECT);
00634         // Update globals
00635         gVelocityInterpolate = gSavedSettings.getBOOL("VelocityInterpolate");
00636         gPingInterpolate = gSavedSettings.getBOOL("PingInterpolate");
00637         gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures");
00638 
00639         // update global timer
00640         F32 last_time = gFrameTimeSeconds;
00641         U64 time = totalTime();                 // this will become the new gFrameTime when the update is done
00642         // Time _can_ go backwards, for example if the user changes the system clock.
00643         // It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here.
00644 //      llassert(time > gFrameTime);
00645         F64 time_diff = U64_to_F64(time - gFrameTime)/(F64)SEC_TO_MICROSEC;
00646         gFrameTime    = time;
00647         F64 time_since_start = U64_to_F64(gFrameTime - gStartTime)/(F64)SEC_TO_MICROSEC;
00648         gFrameTimeSeconds = (F32)time_since_start;
00649 
00650         gFrameIntervalSeconds = gFrameTimeSeconds - last_time;
00651         if (gFrameIntervalSeconds < 0.f)
00652         {
00653                 gFrameIntervalSeconds = 0.f;
00654         }
00655 
00656         //clear avatar LOD change counter
00657         LLVOAvatar::sNumLODChangesThisFrame = 0;
00658 
00659         const F64 frame_time = LLFrameTimer::getElapsedSeconds();
00660         
00661         std::vector<LLViewerObject*> kill_list;
00662         S32 num_active_objects = 0;
00663         LLViewerObject *objectp = NULL; 
00664         
00665         // Make a copy of the list in case something in idleUpdate() messes with it
00666         std::vector<LLViewerObject*> idle_list;
00667         idle_list.reserve( mActiveObjects.size() );
00668 
00669         for (std::set<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin();
00670                 active_iter != mActiveObjects.end(); active_iter++)
00671         {
00672                 objectp = *active_iter;
00673                 if (objectp)
00674                 {
00675                         idle_list.push_back( objectp );
00676                 }
00677                 else
00678                 {       // There shouldn't be any NULL pointers in the list, but they have caused
00679                         // crashes before.  This may be idleUpdate() messing with the list.
00680                         llwarns << "LLViewerObjectList::update has a NULL objectp" << llendl;
00681                 }
00682         }
00683 
00684         if (gSavedSettings.getBOOL("FreezeTime"))
00685         {
00686                 for (std::vector<LLViewerObject*>::iterator iter = idle_list.begin();
00687                         iter != idle_list.end(); iter++)
00688                 {
00689                         objectp = *iter;
00690                         if (objectp->getPCode() == LLViewerObject::LL_VO_CLOUDS ||
00691                                 objectp->isAvatar())
00692                         {
00693                                 objectp->idleUpdate(agent, world, frame_time);
00694                         }
00695                 }
00696         }
00697         else
00698         {
00699                 for (std::vector<LLViewerObject*>::iterator idle_iter = idle_list.begin();
00700                         idle_iter != idle_list.end(); idle_iter++)
00701                 {
00702                         objectp = *idle_iter;
00703                         if (!objectp->idleUpdate(agent, world, frame_time))
00704                         {
00705                                 //  If Idle Update returns false, kill object!
00706                                 kill_list.push_back(objectp);
00707                         }
00708                         else
00709                         {
00710                                 num_active_objects++;
00711                         }
00712                 }
00713                 for (std::vector<LLViewerObject*>::iterator kill_iter = kill_list.begin();
00714                         kill_iter != kill_list.end(); kill_iter++)
00715                 {
00716                         objectp = *kill_iter;
00717                         killObject(objectp);
00718                 }
00719         }
00720 
00721         mNumSizeCulled = 0;
00722         mNumVisCulled = 0;
00723 
00724         // compute all sorts of time-based stats
00725         // don't factor frames that were paused into the stats
00726         if (! mWasPaused)
00727         {
00728                 gViewerStats->updateFrameStats(time_diff);
00729         }
00730 
00731         /*
00732         // Debugging code for viewing orphans, and orphaned parents
00733         LLUUID id;
00734         char id_str[UUID_STR_LENGTH + 20];
00735         for (i = 0; i < mOrphanParents.count(); i++)
00736         {
00737                 id = sIndexAndLocalIDToUUID[mOrphanParents[i]];
00738                 LLViewerObject *objectp = findObject(id);
00739                 if (objectp)
00740                 {
00741                         sprintf(id_str, "Par:    ");
00742                         objectp->mID.toString(id_str + 5);
00743                         addDebugBeacon(objectp->getPositionAgent(),
00744                                                         id_str,
00745                                                         LLColor4(1.f,0.f,0.f,1.f),
00746                                                         LLColor4(1.f,1.f,1.f,1.f));
00747                 }
00748         }
00749 
00750         LLColor4 text_color;
00751         for (i = 0; i < mOrphanChildren.count(); i++)
00752         {
00753                 OrphanInfo oi = mOrphanChildren[i];
00754                 LLViewerObject *objectp = findObject(oi.mChildInfo);
00755                 if (objectp)
00756                 {
00757                         if (objectp->getParent())
00758                         {
00759                                 sprintf(id_str, "ChP:     ");
00760                                 text_color = LLColor4(0.f, 1.f, 0.f, 1.f);
00761                         }
00762                         else
00763                         {
00764                                 sprintf(id_str, "ChNoP:    ");
00765                                 text_color = LLColor4(1.f, 0.f, 0.f, 1.f);
00766                         }
00767                         id = sIndexAndLocalIDToUUID[oi.mParentInfo];
00768                         objectp->mID.toString(id_str + 8);
00769                         addDebugBeacon(objectp->getPositionAgent() + LLVector3(0.f, 0.f, -0.25f),
00770                                                         id_str,
00771                                                         LLColor4(0.25f,0.25f,0.25f,1.f),
00772                                                         text_color);
00773                 }
00774                 i++;
00775         }
00776         */
00777 
00778         mNumObjectsStat.addValue(mObjects.count());
00779         mNumActiveObjectsStat.addValue(num_active_objects);
00780         mNumSizeCulledStat.addValue(mNumSizeCulled);
00781         mNumVisCulledStat.addValue(mNumVisCulled);
00782 }
00783 
00784 void LLViewerObjectList::clearDebugText()
00785 {
00786         for (S32 i = 0; i < mObjects.count(); i++)
00787         {
00788                 mObjects[i]->setDebugText("");
00789         }
00790 }
00791 
00792 
00793 void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
00794 {
00795         LLMemType mt(LLMemType::MTYPE_OBJECT);
00796         if (mDeadObjects.count(objectp->mID))
00797         {
00798                 llinfos << "Object " << objectp->mID << " already on dead list, ignoring cleanup!" << llendl;   
00799                 return;
00800         }
00801 
00802         mDeadObjects.insert(std::pair<LLUUID, LLPointer<LLViewerObject> >(objectp->mID, objectp));
00803 
00804         // Cleanup any references we have to this object
00805         // Remove from object map so noone can look it up.
00806 
00807         mUUIDObjectMap.erase(objectp->mID);
00808         removeFromLocalIDTable(*objectp);
00809 
00810         if (objectp->onActiveList())
00811         {
00812                 //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << llendl;
00813                 objectp->setOnActiveList(FALSE);
00814                 mActiveObjects.erase(objectp);
00815         }
00816 
00817         if (objectp->isOnMap())
00818         {
00819                 mMapObjects.removeObj(objectp);
00820         }
00821 
00822         // Don't clean up mObject references, these will be cleaned up more efficiently later!
00823         // Also, not cleaned up
00824         removeDrawable(objectp->mDrawable);
00825 
00826         mNumDeadObjects++;
00827 }
00828 
00829 void LLViewerObjectList::removeDrawable(LLDrawable* drawablep)
00830 {
00831         if (!drawablep)
00832         {
00833                 return;
00834         }
00835 
00836         for (S32 i = 0; i < drawablep->getNumFaces(); i++)
00837         {
00838                 LLViewerObject* objectp = drawablep->getFace(i)->getViewerObject();
00839                 mSelectPickList.erase(objectp);
00840         }
00841 }
00842 
00843 BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
00844 {
00845         // When we're killing objects, all we do is mark them as dead.
00846         // We clean up the dead objects later.
00847 
00848         if (objectp)
00849         {
00850                 if (objectp->isDead())
00851                 {
00852                         // This object is already dead.  Don't need to do more.
00853                         return TRUE;
00854                 }
00855                 else
00856                 {
00857                         objectp->markDead();
00858                 }
00859 
00860                 return TRUE;
00861         }
00862         return FALSE;
00863 }
00864 
00865 void LLViewerObjectList::killObjects(LLViewerRegion *regionp)
00866 {
00867         LLViewerObject *objectp;
00868 
00869         S32 i;
00870         for (i = 0; i < mObjects.count(); i++)
00871         {
00872                 objectp = mObjects[i];
00873                 
00874                 if (objectp->mRegionp == regionp)
00875                 {
00876                         killObject(objectp);
00877                 }
00878         }
00879 
00880         // Have to clean right away because the region is becoming invalid.
00881         cleanDeadObjects(FALSE);
00882 }
00883 
00884 void LLViewerObjectList::killAllObjects()
00885 {
00886         // Used only on global destruction.
00887         LLViewerObject *objectp;
00888 
00889         for (S32 i = 0; i < mObjects.count(); i++)
00890         {
00891                 objectp = mObjects[i];
00892                 
00893                 killObject(objectp);
00894                 llassert(objectp->isDead());
00895         }
00896 
00897         cleanDeadObjects(FALSE);
00898 
00899         if(!mObjects.empty())
00900         {
00901                 llwarns << "LLViewerObjectList::killAllObjects still has entries in mObjects: " << mObjects.count() << llendl;
00902                 mObjects.clear();
00903         }
00904 
00905         if (!mActiveObjects.empty())
00906         {
00907                 llwarns << "Some objects still on active object list!" << llendl;
00908                 mActiveObjects.clear();
00909         }
00910 
00911         if (!mMapObjects.empty())
00912         {
00913                 llwarns << "Some objects still on map object list!" << llendl;
00914                 mActiveObjects.clear();
00915         }
00916 }
00917 
00918 void LLViewerObjectList::cleanDeadObjects(BOOL use_timer)
00919 {
00920         if (!mNumDeadObjects)
00921         {
00922                 // No dead objects, don't need to scan object list.
00923                 return;
00924         }
00925 
00926         S32 i = 0;
00927         S32 num_removed = 0;
00928         LLViewerObject *objectp;
00929         while (i < mObjects.count())
00930         {
00931                 // Scan for all of the dead objects and remove any "global" references to them.
00932                 objectp = mObjects[i];
00933                 if (objectp->isDead())
00934                 {
00935                         mObjects.remove(i);
00936                         num_removed++;
00937 
00938                         if (num_removed == mNumDeadObjects)
00939                         {
00940                                 // We've cleaned up all of the dead objects.
00941                                 break;
00942                         }
00943                 }
00944                 else
00945                 {
00946                         // iterate, this isn't a dead object.
00947                         i++;
00948                 }
00949         }
00950 
00951         // We've cleaned the global object list, now let's do some paranoia testing on objects
00952         // before blowing away the dead list.
00953         mDeadObjects.clear();
00954         mNumDeadObjects = 0;
00955 }
00956 
00957 void LLViewerObjectList::updateActive(LLViewerObject *objectp)
00958 {
00959         LLMemType mt(LLMemType::MTYPE_OBJECT);
00960         if (objectp->isDead())
00961         {
00962                 return; // We don't update dead objects!
00963         }
00964 
00965         BOOL active = objectp->isActive();
00966         if (active != objectp->onActiveList())
00967         {
00968                 if (active)
00969                 {
00970                         //llinfos << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << llendl;
00971                         mActiveObjects.insert(objectp);
00972                         objectp->setOnActiveList(TRUE);
00973                 }
00974                 else
00975                 {
00976                         //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << llendl;
00977                         mActiveObjects.erase(objectp);
00978                         objectp->setOnActiveList(FALSE);
00979                 }
00980         }
00981 }
00982 
00983 
00984 
00985 void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
00986 {
00987         // This is called when we shift our origin when we cross region boundaries...
00988         // We need to update many object caches, I'll document this more as I dig through the code
00989         // cleaning things out...
00990 
00991         if (gNoRender || 0 == offset.magVecSquared())
00992         {
00993                 return;
00994         }
00995 
00996         LLViewerObject *objectp;
00997         S32 i;
00998         for (i = 0; i < mObjects.count(); i++)
00999         {
01000                 objectp = getObject(i);
01001                 // There could be dead objects on the object list, so don't update stuff if the object is dead.
01002                 if (objectp)
01003                 {
01004                         objectp->updatePositionCaches();
01005 
01006                         if (objectp->mDrawable.notNull() && !objectp->mDrawable->isDead())
01007                         {
01008                                 gPipeline.markShift(objectp->mDrawable);
01009                         }
01010                 }
01011         }
01012 
01013         gPipeline.shiftObjects(offset);
01014         gWorldPointer->mPartSim.shift(offset);
01015 }
01016 
01017 void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap)
01018 {
01019         LLColor4 above_water_color = gColors.getColor( "NetMapOtherOwnAboveWater" );
01020         LLColor4 below_water_color = gColors.getColor( "NetMapOtherOwnBelowWater" );
01021         LLColor4 you_own_above_water_color = 
01022                                                 gColors.getColor( "NetMapYouOwnAboveWater" );
01023         LLColor4 you_own_below_water_color = 
01024                                                 gColors.getColor( "NetMapYouOwnBelowWater" );
01025         LLColor4 group_own_above_water_color = 
01026                                                 gColors.getColor( "NetMapGroupOwnAboveWater" );
01027         LLColor4 group_own_below_water_color = 
01028                                                 gColors.getColor( "NetMapGroupOwnBelowWater" );
01029 
01030 
01031         for (S32 i = 0; i < mMapObjects.count(); i++)
01032         {
01033                 LLViewerObject* objectp = mMapObjects[i];
01034                 if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment())
01035                 {
01036                         continue;
01037                 }
01038                 const LLVector3& scale = objectp->getScale();
01039                 const LLVector3d pos = objectp->getPositionGlobal();
01040                 const F64 water_height = F64( objectp->getRegion()->getWaterHeight() );
01041                 // gWorldPointer->getWaterHeight();
01042 
01043                 F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f;  // 1.3 is a fudge
01044 
01045                 LLColor4U color = above_water_color;
01046                 if( objectp->permYouOwner() )
01047                 {
01048                         const F32 MIN_RADIUS_FOR_OWNED_OBJECTS = 2.f;
01049                         if( approx_radius < MIN_RADIUS_FOR_OWNED_OBJECTS )
01050                         {
01051                                 approx_radius = MIN_RADIUS_FOR_OWNED_OBJECTS;
01052                         }
01053 
01054                         if( pos.mdV[VZ] >= water_height )
01055                         {
01056                                 if ( objectp->permGroupOwner() )
01057                                 {
01058                                         color = group_own_above_water_color;
01059                                 }
01060                                 else
01061                                 {
01062                                 color = you_own_above_water_color;
01063                         }
01064                         }
01065                         else
01066                         {
01067                                 if ( objectp->permGroupOwner() )
01068                                 {
01069                                         color = group_own_below_water_color;
01070                                 }
01071                         else
01072                         {
01073                                 color = you_own_below_water_color;
01074                         }
01075                 }
01076                 }
01077                 else
01078                 if( pos.mdV[VZ] < water_height )
01079                 {
01080                         color = below_water_color;
01081                 }
01082 
01083                 netmap.renderScaledPointGlobal( 
01084                         pos, 
01085                         color,
01086                         approx_radius );
01087         }
01088 }
01089 
01090 void LLViewerObjectList::renderObjectBounds(const LLVector3 &center)
01091 {
01092 }
01093 
01094 
01095 U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall, BOOL keep_pick_list)
01096 {
01097         gRenderForSelect = TRUE;
01098 
01099         //      LLTimer pick_timer;
01100         if (!keep_pick_list)
01101         {
01102                 LLViewerObject *objectp;
01103                 S32 i;
01104                 // Reset all of the GL names to zero.
01105                 for (i = 0; i < mObjects.count(); i++)
01106                 {
01107                         objectp = mObjects[i];
01108                         objectp->mGLName = 0;
01109                 }
01110 
01111                 mSelectPickList.clear();
01112 
01113                 std::vector<LLDrawable*> pick_drawables;
01114 
01115                 for (i = 0; i < LLPipeline::NUM_PARTITIONS-1; i++)
01116                 {
01117                         LLSpatialPartition* part = gPipeline.getSpatialPartition(i);
01118                         if (part)
01119                         {
01120                                 part->cull(camera, &pick_drawables, TRUE);
01121                         }
01122                 }
01123 
01124                 for (std::vector<LLDrawable*>::iterator iter = pick_drawables.begin();
01125                         iter != pick_drawables.end(); iter++)
01126                 {
01127                         LLDrawable* drawablep = *iter;
01128                         if( !drawablep )
01129                                 continue;
01130 
01131                         LLViewerObject* last_objectp = NULL;
01132                         for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
01133                         {
01134                                 LLViewerObject* objectp = drawablep->getFace(face_num)->getViewerObject();
01135 
01136                                 if (objectp && objectp != last_objectp)
01137                                 {
01138                                         mSelectPickList.insert(objectp);
01139                                         last_objectp = objectp;
01140                                 }
01141                         }
01142                 }
01143 
01144                 LLHUDText::addPickable(mSelectPickList);
01145 
01146                 for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
01147                         iter != LLCharacter::sInstances.end(); ++iter)
01148                 {
01149                         objectp = (LLVOAvatar*) *iter;
01150                         if (!objectp->isDead())
01151                         {
01152                                 if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible())
01153                                 {
01154                                         mSelectPickList.insert(objectp);
01155                                 }
01156                         }
01157                 }
01158 
01159                 // add all hud objects to pick list
01160                 LLVOAvatar* avatarp = gAgent.getAvatarObject();
01161                 if (avatarp)
01162                 {
01163                         LLViewerJointAttachment* attachmentp;
01164                         for (attachmentp = avatarp->mAttachmentPoints.getFirstData();
01165                                 attachmentp;
01166                                 attachmentp = avatarp->mAttachmentPoints.getNextData())
01167                         {
01168                                 if (attachmentp->getIsHUDAttachment())
01169                                 {
01170                                         LLViewerObject* objectp = attachmentp->getObject();
01171                                         if (objectp)
01172                                         {
01173                                                 mSelectPickList.insert(objectp);                
01174                                                 for (U32 i = 0; i < objectp->mChildList.size(); i++)
01175                                                 {
01176                                                         LLViewerObject* childp = objectp->mChildList[i];
01177                                                         if (childp)
01178                                                         {
01179                                                                 mSelectPickList.insert(childp);
01180                                                         }
01181                                                 }
01182                                         }
01183                                 }
01184                         }
01185                 }
01186                 
01187                 S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances();
01188 
01189                 if (num_pickables != 0)
01190                 {
01191                         S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables;
01192 
01193                         std::set<LLViewerObject*>::iterator pick_it;
01194                         i = 0;
01195                         for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();)
01196                         {
01197                                 LLViewerObject* objp = (*pick_it);
01198                                 if (!objp || objp->isDead() || !objp->mbCanSelect)
01199                                 {
01200                                         mSelectPickList.erase(pick_it++);
01201                                         continue;
01202                                 }
01203                                 
01204                                 objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET;
01205                                 i++;
01206                                 ++pick_it;
01207                         }
01208 
01209                         LLHUDIcon::generatePickIDs(i * step, step);
01210                 
01211                         // At this point, we should only have live drawables/viewer objects
01212                         gPipeline.renderForSelect(mSelectPickList);
01213                 }
01214         }
01215 
01216         //
01217         // Render pass for selected objects
01218         //
01219         gViewerWindow->renderSelections( TRUE, pick_parcel_wall, FALSE );
01220 
01221         // render pickable ui elements, like names, etc.
01222         LLHUDObject::renderAllForSelect();
01223 
01224         gRenderForSelect = FALSE;
01225 
01226         //llinfos << "Rendered " << count << " for select" << llendl;
01227         //llinfos << "Took " << pick_timer.getElapsedTimeF32()*1000.f << "ms to pick" << llendl;
01228         return 0;
01229 }
01230 
01231 LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id)
01232 {
01233         std::set<LLViewerObject*>::iterator pick_it;
01234         for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end(); ++pick_it)
01235         {
01236                 if ((*pick_it)->mGLName == object_id)
01237                 {
01238                         return (*pick_it);
01239                 }
01240         }
01241         return NULL;
01242 }
01243 
01244 void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent,
01245                                                                                 const LLString &string,
01246                                                                                 const LLColor4 &color,
01247                                                                                 const LLColor4 &text_color,
01248                                                                                 S32 line_width)
01249 {
01250         LLDebugBeacon *beaconp = mDebugBeacons.reserve_block(1);
01251         beaconp->mPositionAgent = pos_agent;
01252         beaconp->mString = string;
01253         beaconp->mColor = color;
01254         beaconp->mTextColor = text_color;
01255         beaconp->mLineWidth = line_width;
01256 }
01257 
01258 void LLViewerObjectList::resetObjectBeacons()
01259 {
01260         mDebugBeacons.reset();
01261 }
01262 
01263 LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp)
01264 {
01265         LLMemType mt(LLMemType::MTYPE_OBJECT);
01266         LLUUID fullid;
01267         fullid.generate();
01268 
01269         LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp);
01270         if (!objectp)
01271         {
01272 //              llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << llendl;
01273                 return NULL;
01274         }
01275 
01276         mUUIDObjectMap[fullid] = objectp;
01277 
01278         mObjects.put(objectp);
01279 
01280         updateActive(objectp);
01281 
01282         return objectp;
01283 }
01284 
01285 
01286 
01287 LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp,
01288                                                                                                  const LLUUID &uuid, const U32 local_id, const LLHost &sender)
01289 {
01290         LLMemType mt(LLMemType::MTYPE_OBJECT);
01291         LLFastTimer t(LLFastTimer::FTM_CREATE_OBJECT);
01292         
01293         LLUUID fullid;
01294         if (uuid == LLUUID::null)
01295         {
01296                 fullid.generate();
01297         }
01298         else
01299         {
01300                 fullid = uuid;
01301         }
01302 
01303         LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp);
01304         if (!objectp)
01305         {
01306 //              llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << llendl;
01307                 return NULL;
01308         }
01309 
01310         mUUIDObjectMap[fullid] = objectp;
01311         setUUIDAndLocal(fullid,
01312                                         local_id,
01313                                         gMessageSystem->getSenderIP(),
01314                                         gMessageSystem->getSenderPort());
01315 
01316         mObjects.put(objectp);
01317 
01318         updateActive(objectp);
01319 
01320         return objectp;
01321 }
01322 
01323 LLViewerObject *LLViewerObjectList::replaceObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
01324 {
01325         LLViewerObject *old_instance = findObject(id);
01326         if (old_instance)
01327         {
01328                 cleanupReferences(old_instance);
01329                 old_instance->markDead();
01330                 
01331                 return createObject(pcode, regionp, id, old_instance->getLocalID(), LLHost());
01332         }
01333         return NULL;
01334 }
01335 
01336 S32 LLViewerObjectList::findReferences(LLDrawable *drawablep) const
01337 {
01338         LLViewerObject *objectp;
01339         S32 i;
01340         S32 num_refs = 0;
01341         for (i = 0; i < mObjects.count(); i++)
01342         {
01343                 objectp = mObjects[i];
01344                 if (objectp->mDrawable.notNull())
01345                 {
01346                         num_refs += objectp->mDrawable->findReferences(drawablep);
01347                 }
01348         }
01349         return num_refs;
01350 }
01351 
01352 
01353 void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip, U32 port)
01354 {
01355         LLMemType mt(LLMemType::MTYPE_OBJECT);
01356 #ifdef ORPHAN_SPAM
01357         llinfos << "Orphaning object " << childp->getID() << " with parent " << parent_id << llendl;
01358 #endif
01359 
01360         // We're an orphan, flag things appropriately.
01361         childp->mOrphaned = TRUE;
01362         if (childp->mDrawable.notNull())
01363         {
01364                 bool make_invisible = true;
01365                 LLViewerObject *parentp = (LLViewerObject *)childp->getParent();
01366                 if (parentp)
01367                 {
01368                         if (parentp->getRegion() != childp->getRegion())
01369                         {
01370                                 // This is probably an object flying across a region boundary, the
01371                                 // object probably ISN'T being reparented, but just got an object
01372                                 // update out of order (child update before parent).
01373                                 make_invisible = false;
01374                                 //llinfos << "Don't make object handoffs invisible!" << llendl;
01375                         }
01376                 }
01377 
01378                 if (make_invisible)
01379                 {
01380                         // Make sure that this object becomes invisible if it's an orphan
01381                         childp->mDrawable->setState(LLDrawable::FORCE_INVISIBLE);
01382                 }
01383         }
01384 
01385         // Unknown parent, add to orpaned child list
01386         U64 parent_info = getIndex(parent_id, ip, port);
01387 
01388         if (-1 == mOrphanParents.find(parent_info))
01389         {
01390                 mOrphanParents.put(parent_info);
01391         }
01392 
01393         LLViewerObjectList::OrphanInfo oi(parent_info, childp->mID);
01394         if (-1 == mOrphanChildren.find(oi))
01395         {
01396                 mOrphanChildren.put(oi);
01397                 mNumOrphans++;
01398         }
01399 }
01400 
01401 
01402 void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port)
01403 {
01404         if (gNoRender)
01405         {
01406                 return;
01407         }
01408 
01409         if (objectp->isDead())
01410         {
01411                 llwarns << "Trying to find orphans for dead obj " << objectp->mID 
01412                         << ":" << objectp->getPCodeString() << llendl;
01413                 return;
01414         }
01415 
01416         // See if we are a parent of an orphan.
01417         // Note:  This code is fairly inefficient but it should happen very rarely.
01418         // It can be sped up if this is somehow a performance issue...
01419         if (0 == mOrphanParents.count())
01420         {
01421                 // no known orphan parents
01422                 return;
01423         }
01424         if (-1 == mOrphanParents.find(getIndex(objectp->mLocalID, ip, port)))
01425         {
01426                 // did not find objectp in OrphanParent list
01427                 return;
01428         }
01429 
01430         S32 i;
01431         U64 parent_info = getIndex(objectp->mLocalID, ip, port);
01432         BOOL orphans_found = FALSE;
01433         // Iterate through the orphan list, and set parents of matching children.
01434         for (i = 0; i < mOrphanChildren.count(); i++)
01435         {
01436                 if (mOrphanChildren[i].mParentInfo != parent_info)
01437                 {
01438                         continue;
01439                 }
01440                 LLViewerObject *childp = findObject(mOrphanChildren[i].mChildInfo);
01441                 if (childp)
01442                 {
01443                         if (childp == objectp)
01444                         {
01445                                 llwarns << objectp->mID << " has self as parent, skipping!" 
01446                                         << llendl;
01447                                 continue;
01448                         }
01449 
01450 #ifdef ORPHAN_SPAM
01451                         llinfos << "Reunited parent " << objectp->mID 
01452                                 << " with child " << childp->mID << llendl;
01453                         llinfos << "Glob: " << objectp->getPositionGlobal() << llendl;
01454                         llinfos << "Agent: " << objectp->getPositionAgent() << llendl;
01455                         addDebugBeacon(objectp->getPositionAgent(),"");
01456 #endif
01457             gPipeline.markMoved(objectp->mDrawable);                
01458             objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE);
01459 
01460                         // Flag the object as no longer orphaned
01461                         childp->mOrphaned = FALSE;
01462                         if (childp->mDrawable.notNull())
01463                         {
01464                                 // Make the drawable visible again and set the drawable parent
01465                                 childp->mDrawable->setState(LLDrawable::CLEAR_INVISIBLE);
01466                                 childp->setDrawableParent(objectp->mDrawable); // LLViewerObjectList::findOrphans()
01467                         }
01468 
01469                         // Make certain particles, icon and HUD aren't hidden
01470                         childp->hideExtraDisplayItems( FALSE );
01471 
01472                         objectp->addChild(childp);
01473                         orphans_found = TRUE;
01474                 }
01475                 else
01476                 {
01477                         llinfos << "Missing orphan child, removing from list" << llendl;
01478                         mOrphanChildren.remove(i);
01479                         i--;
01480                 }
01481         }
01482 
01483         // Remove orphan parent and children from lists now that they've been found
01484         mOrphanParents.remove(mOrphanParents.find(parent_info));
01485 
01486         i = 0;
01487         while (i < mOrphanChildren.count())
01488         {
01489                 if (mOrphanChildren[i].mParentInfo == parent_info)
01490                 {
01491                         mOrphanChildren.remove(i);
01492                         mNumOrphans--;
01493                 }
01494                 else
01495                 {
01496                         i++;
01497                 }
01498         }
01499 
01500         if (orphans_found && objectp->isSelected())
01501         {
01502                 LLSelectNode* nodep = gSelectMgr->getSelection()->findNode(objectp);
01503                 if (nodep && !nodep->mIndividualSelection)
01504                 {
01505                         // rebuild selection with orphans
01506                         gSelectMgr->deselectObjectAndFamily(objectp);
01507                         gSelectMgr->selectObjectAndFamily(objectp);
01508                 }
01509         }
01510 }
01511 
01513 
01514 LLViewerObjectList::OrphanInfo::OrphanInfo()
01515 {
01516 }
01517 
01518 LLViewerObjectList::OrphanInfo::OrphanInfo(const U64 parent_info, const LLUUID child_info)
01519         : mParentInfo(parent_info), mChildInfo(child_info)
01520 {
01521 }
01522 
01523 bool LLViewerObjectList::OrphanInfo::operator==(const OrphanInfo &rhs) const
01524 {
01525         return (mParentInfo == rhs.mParentInfo) && (mChildInfo == rhs.mChildInfo);
01526 }
01527 
01528 bool LLViewerObjectList::OrphanInfo::operator!=(const OrphanInfo &rhs) const
01529 {
01530         return !operator==(rhs);
01531 }
01532 

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