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
00085
00086
00087
00088 LLViewerObjectList gObjectList;
00089
00090 extern LLPipeline gPipeline;
00091
00092
00093 U32 LLViewerObjectList::sSimulatorMachineIndex = 1;
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
00211 objectp->processUpdateMessage(msg, user_data, i, update_type, dpp);
00212
00213 if (objectp->isDead())
00214 {
00215
00216 return;
00217 }
00218 updateActive(objectp);
00219
00220
00221 objectp->setPixelAreaAndAngle(gAgent);
00222
00223
00224 objectp->updateTextures(gAgent);
00225
00226 if (just_created)
00227 {
00228 gPipeline.addObject(objectp);
00229 }
00230
00231
00232
00233
00234 findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
00235
00236
00237 if (just_created
00238 && update_type != OUT_TERSE_IMPROVED
00239 && objectp->mCreateSelected)
00240 {
00241 if ( gToolMgr->getCurrentTool() != gToolPie )
00242 {
00243
00244
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
00271
00272
00273
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
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
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
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;
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
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
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
00415 }
00416 objectp = findObject(fullid);
00417
00418
00419
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
00436 continue;
00437 }
00438 }
00439 else if (cached)
00440 {
00441 }
00442 else
00443 {
00444 if (update_type != OUT_FULL)
00445 {
00446
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
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
00474 removeFromLocalIDTable(*objectp);
00475 setUUIDAndLocal(fullid,
00476 local_id,
00477 gMessageSystem->getSenderIP(),
00478 gMessageSystem->getSenderPort());
00479 objectp->setRegion(regionp);
00480 }
00481 objectp->updateRegion(regionp);
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
00578
00579
00580 objectp = gHoverView->getLastHoverObject();
00581 if (objectp)
00582 {
00583 objectp->boostTexturePriority();
00584 }
00585 }
00586
00587
00588 objectp = gAgent.getFocusObject();
00589 if (objectp)
00590 {
00591 objectp->boostTexturePriority();
00592 }
00593
00594
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
00606 for (i = mCurLazyUpdateIndex; i < max_value; i++)
00607 {
00608 objectp = mObjects[i];
00609 if (!objectp->isDead())
00610 {
00611 num_objects++;
00612
00613
00614 objectp->setPixelAreaAndAngle(agent);
00615 objectp->updateTextures(agent);
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
00635 gVelocityInterpolate = gSavedSettings.getBOOL("VelocityInterpolate");
00636 gPingInterpolate = gSavedSettings.getBOOL("PingInterpolate");
00637 gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures");
00638
00639
00640 F32 last_time = gFrameTimeSeconds;
00641 U64 time = totalTime();
00642
00643
00644
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
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
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 {
00679
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
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
00725
00726 if (! mWasPaused)
00727 {
00728 gViewerStats->updateFrameStats(time_diff);
00729 }
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
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
00805
00806
00807 mUUIDObjectMap.erase(objectp->mID);
00808 removeFromLocalIDTable(*objectp);
00809
00810 if (objectp->onActiveList())
00811 {
00812
00813 objectp->setOnActiveList(FALSE);
00814 mActiveObjects.erase(objectp);
00815 }
00816
00817 if (objectp->isOnMap())
00818 {
00819 mMapObjects.removeObj(objectp);
00820 }
00821
00822
00823
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
00846
00847
00848 if (objectp)
00849 {
00850 if (objectp->isDead())
00851 {
00852
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
00881 cleanDeadObjects(FALSE);
00882 }
00883
00884 void LLViewerObjectList::killAllObjects()
00885 {
00886
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
00923 return;
00924 }
00925
00926 S32 i = 0;
00927 S32 num_removed = 0;
00928 LLViewerObject *objectp;
00929 while (i < mObjects.count())
00930 {
00931
00932 objectp = mObjects[i];
00933 if (objectp->isDead())
00934 {
00935 mObjects.remove(i);
00936 num_removed++;
00937
00938 if (num_removed == mNumDeadObjects)
00939 {
00940
00941 break;
00942 }
00943 }
00944 else
00945 {
00946
00947 i++;
00948 }
00949 }
00950
00951
00952
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;
00963 }
00964
00965 BOOL active = objectp->isActive();
00966 if (active != objectp->onActiveList())
00967 {
00968 if (active)
00969 {
00970
00971 mActiveObjects.insert(objectp);
00972 objectp->setOnActiveList(TRUE);
00973 }
00974 else
00975 {
00976
00977 mActiveObjects.erase(objectp);
00978 objectp->setOnActiveList(FALSE);
00979 }
00980 }
00981 }
00982
00983
00984
00985 void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
00986 {
00987
00988
00989
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
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
01042
01043 F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f;
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 ¢er)
01091 {
01092 }
01093
01094
01095 U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall, BOOL keep_pick_list)
01096 {
01097 gRenderForSelect = TRUE;
01098
01099
01100 if (!keep_pick_list)
01101 {
01102 LLViewerObject *objectp;
01103 S32 i;
01104
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
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
01212 gPipeline.renderForSelect(mSelectPickList);
01213 }
01214 }
01215
01216
01217
01218
01219 gViewerWindow->renderSelections( TRUE, pick_parcel_wall, FALSE );
01220
01221
01222 LLHUDObject::renderAllForSelect();
01223
01224 gRenderForSelect = FALSE;
01225
01226
01227
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
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
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
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
01371
01372
01373 make_invisible = false;
01374
01375 }
01376 }
01377
01378 if (make_invisible)
01379 {
01380
01381 childp->mDrawable->setState(LLDrawable::FORCE_INVISIBLE);
01382 }
01383 }
01384
01385
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
01417
01418
01419 if (0 == mOrphanParents.count())
01420 {
01421
01422 return;
01423 }
01424 if (-1 == mOrphanParents.find(getIndex(objectp->mLocalID, ip, port)))
01425 {
01426
01427 return;
01428 }
01429
01430 S32 i;
01431 U64 parent_info = getIndex(objectp->mLocalID, ip, port);
01432 BOOL orphans_found = FALSE;
01433
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
01461 childp->mOrphaned = FALSE;
01462 if (childp->mDrawable.notNull())
01463 {
01464
01465 childp->mDrawable->setState(LLDrawable::CLEAR_INVISIBLE);
01466 childp->setDrawableParent(objectp->mDrawable);
01467 }
01468
01469
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
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
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