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
00084
00085
00086
00087 LLViewerObjectList gObjectList;
00088
00089 extern LLPipeline gPipeline;
00090
00091
00092 U32 LLViewerObjectList::sSimulatorMachineIndex = 1;
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
00210 objectp->processUpdateMessage(msg, user_data, i, update_type, dpp);
00211
00212 if (objectp->isDead())
00213 {
00214
00215 return;
00216 }
00217
00218 updateActive(objectp);
00219
00220 if (just_created)
00221 {
00222 gPipeline.addObject(objectp);
00223 }
00224
00225
00226 objectp->setPixelAreaAndAngle(gAgent);
00227
00228
00229
00230
00231 findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
00232
00233
00234 if (just_created
00235 && update_type != OUT_TERSE_IMPROVED
00236 && objectp->mCreateSelected)
00237 {
00238 if ( LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() )
00239 {
00240
00241
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
00268
00269
00270
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
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
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
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;
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
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
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
00412 }
00413 objectp = findObject(fullid);
00414
00415
00416
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
00433 continue;
00434 }
00435 }
00436 else if (cached)
00437 {
00438 }
00439 else
00440 {
00441 if (update_type != OUT_FULL)
00442 {
00443
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
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
00471 removeFromLocalIDTable(*objectp);
00472 setUUIDAndLocal(fullid,
00473 local_id,
00474 gMessageSystem->getSenderIP(),
00475 gMessageSystem->getSenderPort());
00476 objectp->setRegion(regionp);
00477 }
00478 objectp->updateRegion(regionp);
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
00563
00564
00565 objectp = gHoverView->getLastHoverObject();
00566 if (objectp)
00567 {
00568 objectp->boostTexturePriority();
00569 }
00570 }
00571
00572
00573 objectp = gAgent.getFocusObject();
00574 if (objectp)
00575 {
00576 objectp->boostTexturePriority();
00577 }
00578
00579
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
00591 for (i = mCurLazyUpdateIndex; i < max_value; i++)
00592 {
00593 objectp = mObjects[i];
00594 if (!objectp->isDead())
00595 {
00596 num_objects++;
00597
00598
00599 objectp->setPixelAreaAndAngle(agent);
00600 objectp->updateTextures(agent);
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
00620 gVelocityInterpolate = gSavedSettings.getBOOL("VelocityInterpolate");
00621 gPingInterpolate = gSavedSettings.getBOOL("PingInterpolate");
00622 gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures");
00623
00624
00625 F32 last_time = gFrameTimeSeconds;
00626 U64 time = totalTime();
00627
00628
00629
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
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
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 {
00664
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
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
00710
00711 if (! mWasPaused)
00712 {
00713 LLViewerStats::getInstance()->updateFrameStats(time_diff);
00714 }
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
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 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
00790
00791
00792 mUUIDObjectMap.erase(objectp->mID);
00793 removeFromLocalIDTable(*objectp);
00794
00795 if (objectp->onActiveList())
00796 {
00797
00798 objectp->setOnActiveList(FALSE);
00799 mActiveObjects.erase(objectp);
00800 }
00801
00802 if (objectp->isOnMap())
00803 {
00804 mMapObjects.removeObj(objectp);
00805 }
00806
00807
00808
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
00831
00832
00833 if (objectp)
00834 {
00835 if (objectp->isDead())
00836 {
00837
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
00866 cleanDeadObjects(FALSE);
00867 }
00868
00869 void LLViewerObjectList::killAllObjects()
00870 {
00871
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
00908 return;
00909 }
00910
00911 S32 i = 0;
00912 S32 num_removed = 0;
00913 LLViewerObject *objectp;
00914 while (i < mObjects.count())
00915 {
00916
00917 objectp = mObjects[i];
00918 if (objectp->isDead())
00919 {
00920 mObjects.remove(i);
00921 num_removed++;
00922
00923 if (num_removed == mNumDeadObjects)
00924 {
00925
00926 break;
00927 }
00928 }
00929 else
00930 {
00931
00932 i++;
00933 }
00934 }
00935
00936
00937
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;
00948 }
00949
00950 BOOL active = objectp->isActive();
00951 if (active != objectp->onActiveList())
00952 {
00953 if (active)
00954 {
00955
00956 mActiveObjects.insert(objectp);
00957 objectp->setOnActiveList(TRUE);
00958 }
00959 else
00960 {
00961
00962 mActiveObjects.erase(objectp);
00963 objectp->setOnActiveList(FALSE);
00964 }
00965 }
00966 }
00967
00968
00969
00970 void LLViewerObjectList::shiftObjects(const LLVector3 &offset)
00971 {
00972
00973
00974
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
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
01027
01028 F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f;
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 ¢er)
01076 {
01077 }
01078
01079
01080 U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parcel_wall, BOOL keep_pick_list)
01081 {
01082 gRenderForSelect = TRUE;
01083
01084
01085 if (!keep_pick_list)
01086 {
01087 LLViewerObject *objectp;
01088 S32 i;
01089
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
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
01202 gPipeline.renderForSelect(mSelectPickList);
01203 }
01204 }
01205
01206
01207
01208
01209 gGL.color4f(1,1,1,1);
01210 gViewerWindow->renderSelections( TRUE, pick_parcel_wall, FALSE );
01211
01212
01213 LLHUDObject::renderAllForSelect();
01214 gGL.flush();
01215 LLVertexBuffer::unbind();
01216
01217 gRenderForSelect = FALSE;
01218
01219
01220
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
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
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
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
01364
01365
01366 make_invisible = false;
01367
01368 }
01369 }
01370
01371 if (make_invisible)
01372 {
01373
01374 childp->mDrawable->setState(LLDrawable::FORCE_INVISIBLE);
01375 }
01376 }
01377
01378
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
01410
01411
01412 if (0 == mOrphanParents.count())
01413 {
01414
01415 return;
01416 }
01417 if (-1 == mOrphanParents.find(getIndex(objectp->mLocalID, ip, port)))
01418 {
01419
01420 return;
01421 }
01422
01423 S32 i;
01424 U64 parent_info = getIndex(objectp->mLocalID, ip, port);
01425 BOOL orphans_found = FALSE;
01426
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
01454 childp->mOrphaned = FALSE;
01455 if (childp->mDrawable.notNull())
01456 {
01457
01458 childp->mDrawable->setState(LLDrawable::CLEAR_INVISIBLE);
01459 childp->setDrawableParent(objectp->mDrawable);
01460 }
01461
01462
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
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
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