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

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