From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llviewerobjectlist.cpp | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'indra/newview/llviewerobjectlist.cpp') diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 5bc7523be1..8e22576265 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -86,7 +86,7 @@ #include extern F32 gMinObjectDistance; -extern BOOL gAnimateTextures; +extern bool gAnimateTextures; #define MAX_CONCURRENT_PHYSICS_REQUESTS 256 @@ -109,7 +109,7 @@ LLViewerObjectList::LLViewerObjectList() mNumDeadObjects = 0; mNumOrphans = 0; mNumNewObjects = 0; - mWasPaused = FALSE; + mWasPaused = false; mNumDeadObjectUpdates = 0; mNumUnknownUpdates = 0; } @@ -167,7 +167,7 @@ U64 LLViewerObjectList::getIndex(const U32 local_id, return (((U64)index) << 32) | (U64)local_id; } -BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) +bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) { LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; @@ -186,21 +186,21 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) std::map::iterator iter = sIndexAndLocalIDToUUID.find(indexid); if (iter == sIndexAndLocalIDToUUID.end()) { - return FALSE; + return false; } // Found existing entry if (iter->second == objectp->getID()) { // Full UUIDs match, so remove the entry sIndexAndLocalIDToUUID.erase(iter); - return TRUE; + return true; } // UUIDs did not match - this would zap a valid entry, so don't erase it //LL_INFOS() << "Tried to erase entry where id in table (" // << iter->second << ") did not match object " << object.getID() << LL_ENDL; } - return FALSE ; + return false ; } void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, @@ -391,7 +391,7 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* else { objectp->setLastUpdateType(OUT_FULL_COMPRESSED); //newly cached - objectp->setLastUpdateCached(TRUE); + objectp->setLastUpdateCached(true); } LLVOAvatar::cullAvatarsByPixelArea(); @@ -471,7 +471,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, for (i = 0; i < num_objects; i++) { - BOOL justCreated = FALSE; + bool justCreated = false; bool update_cache = false; //update object cache if it is a full-update or terse update if (compressed) @@ -646,7 +646,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, continue; } - justCreated = TRUE; + justCreated = true; mNumNewObjects++; } @@ -1318,7 +1318,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) if (objectp->onActiveList()) { //LL_INFOS() << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << LL_ENDL; - objectp->setOnActiveList(FALSE); + objectp->setOnActiveList(false); removeFromActiveList(objectp); } @@ -1335,7 +1335,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) } } -BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) +bool LLViewerObjectList::killObject(LLViewerObject *objectp) { LL_PROFILE_ZONE_SCOPED; // Don't ever kill gAgentAvatarp, just force it to the agent's region @@ -1343,7 +1343,7 @@ BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) if ((objectp == gAgentAvatarp) && gAgent.getRegion()) { objectp->setRegion(gAgent.getRegion()); - return FALSE; + return false; } // When we're killing objects, all we do is mark them as dead. @@ -1356,10 +1356,10 @@ BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) // so create a pointer to make sure object will stay alive untill markDead() finishes LLPointer sp(objectp); sp->markDead(); // does the right thing if object already dead - return TRUE; + return true; } - return FALSE; + return false; } void LLViewerObjectList::killObjects(LLViewerRegion *regionp) @@ -1379,7 +1379,7 @@ void LLViewerObjectList::killObjects(LLViewerRegion *regionp) } // Have to clean right away because the region is becoming invalid. - cleanDeadObjects(FALSE); + cleanDeadObjects(false); } void LLViewerObjectList::killAllObjects() @@ -1395,7 +1395,7 @@ void LLViewerObjectList::killAllObjects() llassert((objectp == gAgentAvatarp) || objectp->isDead()); } - cleanDeadObjects(FALSE); + cleanDeadObjects(false); if(!mObjects.empty()) { @@ -1416,7 +1416,7 @@ void LLViewerObjectList::killAllObjects() } } -void LLViewerObjectList::cleanDeadObjects(BOOL use_timer) +void LLViewerObjectList::cleanDeadObjects(bool use_timer) { if (!mNumDeadObjects) { @@ -1501,7 +1501,7 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) return; // We don't update dead objects! } - BOOL active = objectp->isActive(); + bool active = objectp->isActive(); if (active != objectp->onActiveList()) { if (active) @@ -1512,7 +1512,7 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) { mActiveObjects.push_back(objectp); objectp->setListIndex(mActiveObjects.size()-1); - objectp->setOnActiveList(TRUE); + objectp->setOnActiveList(true); } else { @@ -1530,7 +1530,7 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) { //LL_INFOS() << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << LL_ENDL; removeFromActiveList(objectp); - objectp->setOnActiveList(FALSE); + objectp->setOnActiveList(false); } } @@ -1804,7 +1804,7 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er) { } -extern BOOL gCubeSnapshot; +extern bool gCubeSnapshot; void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent, const std::string &string, @@ -1953,7 +1953,7 @@ void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip LL_DEBUGS("ORPHANS") << "Orphaning object " << childp->getID() << " with parent " << parent_id << LL_ENDL; // We're an orphan, flag things appropriately. - childp->mOrphaned = TRUE; + childp->mOrphaned = true; if (childp->mDrawable.notNull()) { bool make_invisible = true; @@ -2026,7 +2026,7 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) } U64 parent_info = getIndex(objectp->mLocalID, ip, port); - BOOL orphans_found = FALSE; + bool orphans_found = false; // Iterate through the orphan list, and set parents of matching children. for (std::vector::iterator iter = mOrphanChildren.begin(); iter != mOrphanChildren.end(); ) @@ -2057,7 +2057,7 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE); // Flag the object as no longer orphaned - childp->mOrphaned = FALSE; + childp->mOrphaned = false; if (childp->mDrawable.notNull()) { // Make the drawable visible again and set the drawable parent @@ -2067,10 +2067,10 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) } // Make certain particles, icon and HUD aren't hidden - childp->hideExtraDisplayItems( FALSE ); + childp->hideExtraDisplayItems( false ); objectp->addChild(childp); - orphans_found = TRUE; + orphans_found = true; ++iter; } else -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llviewerobjectlist.cpp | 4296 +++++++++++++++++----------------- 1 file changed, 2148 insertions(+), 2148 deletions(-) (limited to 'indra/newview/llviewerobjectlist.cpp') diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index f68a3da6ea..2f8e71c5e9 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1,2148 +1,2148 @@ -/** - * @file llviewerobjectlist.cpp - * @brief Implementation of LLViewerObjectList class. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llviewerobjectlist.h" - -#include "message.h" -#include "llfasttimer.h" -#include "llrender.h" -#include "llwindow.h" // decBusyCount() - -#include "llviewercontrol.h" -#include "llface.h" -#include "llvoavatar.h" -#include "llviewerobject.h" -#include "llviewerwindow.h" -#include "llnetmap.h" -#include "llagent.h" -#include "llagentcamera.h" -#include "pipeline.h" -#include "llspatialpartition.h" -#include "lltooltip.h" -#include "llworld.h" -#include "llstring.h" -#include "llhudicon.h" -#include "llhudnametag.h" -#include "lldrawable.h" -#include "llflexibleobject.h" -#include "llviewertextureanim.h" -#include "xform.h" -#include "llsky.h" -#include "llviewercamera.h" -#include "llselectmgr.h" -#include "llresmgr.h" -#include "llsdutil.h" -#include "llviewerregion.h" -#include "llviewerstats.h" -#include "llviewerstatsrecorder.h" -#include "llvovolume.h" -#include "llvoavatarself.h" -#include "lltoolmgr.h" -#include "lltoolpie.h" -#include "llkeyboard.h" -#include "u64.h" -#include "llviewertexturelist.h" -#include "lldatapacker.h" -#include "llcallstack.h" -#ifdef LL_USESYSTEMLIBS -#include -#else -#include "zlib-ng/zlib.h" -#endif -#include "object_flags.h" - -#include "llappviewer.h" -#include "llfloaterperms.h" -#include "llvocache.h" -#include "llcorehttputil.h" -#include "llstartup.h" - -#include -#include - -extern F32 gMinObjectDistance; -extern bool gAnimateTextures; - -#define MAX_CONCURRENT_PHYSICS_REQUESTS 256 - -void dialog_refresh_all(); - -// Global lists of objects - should go away soon. -LLViewerObjectList gObjectList; - -extern LLPipeline gPipeline; - -// Statics for object lookup tables. -U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check. -std::map LLViewerObjectList::sIPAndPortToIndex; -std::map LLViewerObjectList::sIndexAndLocalIDToUUID; - -LLViewerObjectList::LLViewerObjectList() -{ - mCurLazyUpdateIndex = 0; - mCurBin = 0; - mNumDeadObjects = 0; - mNumOrphans = 0; - mNumNewObjects = 0; - mWasPaused = false; - mNumDeadObjectUpdates = 0; - mNumUnknownUpdates = 0; -} - -LLViewerObjectList::~LLViewerObjectList() -{ - destroy(); -} - -void LLViewerObjectList::destroy() -{ - killAllObjects(); - - resetObjectBeacons(); - mActiveObjects.clear(); - mDeadObjects.clear(); - mMapObjects.clear(); - mUUIDObjectMap.clear(); -} - - -void LLViewerObjectList::getUUIDFromLocal(LLUUID &id, - const U32 local_id, - const U32 ip, - const U32 port) -{ - U64 ipport = (((U64)ip) << 32) | (U64)port; - - U32 index = sIPAndPortToIndex[ipport]; - - if (!index) - { - index = sSimulatorMachineIndex++; - sIPAndPortToIndex[ipport] = index; - } - - U64 indexid = (((U64)index) << 32) | (U64)local_id; - - id = get_if_there(sIndexAndLocalIDToUUID, indexid, LLUUID::null); -} - -U64 LLViewerObjectList::getIndex(const U32 local_id, - const U32 ip, - const U32 port) -{ - U64 ipport = (((U64)ip) << 32) | (U64)port; - - U32 index = sIPAndPortToIndex[ipport]; - - if (!index) - { - return 0; - } - - return (((U64)index) << 32) | (U64)local_id; -} - -bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - - if(objectp && objectp->getRegion()) - { - U32 local_id = objectp->mLocalID; - U32 ip = objectp->getRegion()->getHost().getAddress(); - U32 port = objectp->getRegion()->getHost().getPort(); - U64 ipport = (((U64)ip) << 32) | (U64)port; - U32 index = sIPAndPortToIndex[ipport]; - - // LL_INFOS() << "Removing object from table, local ID " << local_id << ", ip " << ip << ":" << port << LL_ENDL; - - U64 indexid = (((U64)index) << 32) | (U64)local_id; - - std::map::iterator iter = sIndexAndLocalIDToUUID.find(indexid); - if (iter == sIndexAndLocalIDToUUID.end()) - { - return false; - } - - // Found existing entry - if (iter->second == objectp->getID()) - { // Full UUIDs match, so remove the entry - sIndexAndLocalIDToUUID.erase(iter); - return true; - } - // UUIDs did not match - this would zap a valid entry, so don't erase it - //LL_INFOS() << "Tried to erase entry where id in table (" - // << iter->second << ") did not match object " << object.getID() << LL_ENDL; - } - - return false ; -} - -void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, - const U32 local_id, - const U32 ip, - const U32 port) -{ - U64 ipport = (((U64)ip) << 32) | (U64)port; - - U32 index = sIPAndPortToIndex[ipport]; - - if (!index) - { - index = sSimulatorMachineIndex++; - sIPAndPortToIndex[ipport] = index; - } - - U64 indexid = (((U64)index) << 32) | (U64)local_id; - - sIndexAndLocalIDToUUID[indexid] = id; - - //LL_INFOS() << "Adding object to table, full ID " << id - // << ", local ID " << local_id << ", ip " << ip << ":" << port << LL_ENDL; -} - -S32 gFullObjectUpdates = 0; -S32 gTerseObjectUpdates = 0; - -void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, - void** user_data, - U32 i, - const EObjectUpdateType update_type, - LLDataPacker* dpp, - bool just_created, - bool from_cache) -{ - LLMessageSystem* msg = NULL; - - if(!from_cache) - { - msg = gMessageSystem; - } - - // ignore returned flags - LL_DEBUGS("ObjectUpdate") << "uuid " << objectp->mID << " calling processUpdateMessage " - << objectp << " just_created " << just_created << " from_cache " << from_cache << " msg " << msg << LL_ENDL; - dumpStack("ObjectUpdateStack"); - - objectp->processUpdateMessage(msg, user_data, i, update_type, dpp); - - if (objectp->isDead()) - { - // The update failed - return; - } - - updateActive(objectp); - - if (just_created) - { - gPipeline.addObject(objectp); - } - - // Also sets the approx. pixel area - objectp->setPixelAreaAndAngle(gAgent); - - // RN: this must be called after we have a drawable - // (from gPipeline.addObject) - // so that the drawable parent is set properly - if(msg != NULL) - { - findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); - } - else - { - LLViewerRegion* regionp = objectp->getRegion(); - if(regionp != NULL) - { - findOrphans(objectp, regionp->getHost().getAddress(), regionp->getHost().getPort()); - } - } - - // If we're just wandering around, don't create new objects selected. - if (just_created - && update_type != OUT_TERSE_IMPROVED - && objectp->mCreateSelected) - { - if ( LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() ) - { - // LL_INFOS() << "DEBUG selecting " << objectp->mID << " " - // << objectp->mLocalID << LL_ENDL; - LLSelectMgr::getInstance()->selectObjectAndFamily(objectp); - dialog_refresh_all(); - } - - objectp->mCreateSelected = false; - gViewerWindow->getWindow()->decBusyCount(); - gViewerWindow->setCursor( UI_CURSOR_ARROW ); - } -} - -static LLTrace::BlockTimerStatHandle FTM_PROCESS_OBJECTS("Process Objects"); - -LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* entry, LLViewerRegion* regionp) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - - LLDataPacker *cached_dpp = entry->getDP(); - - if (!cached_dpp || gNonInteractive) - { - return NULL; //nothing cached. - } - - LLViewerObject *objectp; - U32 local_id; - LLPCode pcode = 0; - LLUUID fullid; - LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); - - // Cache Hit. - record(LLStatViewer::OBJECT_CACHE_HIT_RATE, LLUnits::Ratio::fromValue(1)); - - cached_dpp->reset(); - cached_dpp->unpackUUID(fullid, "ID"); - cached_dpp->unpackU32(local_id, "LocalID"); - cached_dpp->unpackU8(pcode, "PCode"); - - objectp = findObject(fullid); - - if (objectp) - { - if(!objectp->isDead() && (objectp->mLocalID != entry->getLocalID() || - objectp->getRegion() != regionp)) - { - removeFromLocalIDTable(objectp); - setUUIDAndLocal(fullid, entry->getLocalID(), - regionp->getHost().getAddress(), - regionp->getHost().getPort()); - - if (objectp->mLocalID != entry->getLocalID()) - { // Update local ID in object with the one sent from the region - objectp->mLocalID = entry->getLocalID(); - } - - if (objectp->getRegion() != regionp) - { // Object changed region, so update it - objectp->updateRegion(regionp); // for LLVOAvatar - } - } - else - { - //should fall through if already loaded because may need to update the object. - //return objectp; //already loaded. - } - } - - bool justCreated = false; - if (!objectp) - { - objectp = createObjectFromCache(pcode, regionp, fullid, entry->getLocalID()); - - LL_DEBUGS("ObjectUpdate") << "uuid " << fullid << " created objectp " << objectp << LL_ENDL; - dumpStack("ObjectUpdateStack"); - - if (!objectp) - { - LL_INFOS() << "createObject failure for object: " << fullid << LL_ENDL; - recorder.objectUpdateFailure(); - return NULL; - } - justCreated = true; - mNumNewObjects++; - } - - if (objectp->isDead()) - { - LL_WARNS() << "Dead object " << objectp->mID << " in UUID map 1!" << LL_ENDL; - } - - processUpdateCore(objectp, NULL, 0, OUT_FULL_CACHED, cached_dpp, justCreated, true); - objectp->loadFlags(entry->getUpdateFlags()); //just in case, reload update flags from cache. - - if(entry->getHitCount() > 0) - { - objectp->setLastUpdateType(OUT_FULL_CACHED); - } - else - { - objectp->setLastUpdateType(OUT_FULL_COMPRESSED); //newly cached - objectp->setLastUpdateCached(true); - } - LLVOAvatar::cullAvatarsByPixelArea(); - - return objectp; -} - -void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, - void **user_data, - const EObjectUpdateType update_type, - bool compressed) -{ - LL_RECORD_BLOCK_TIME(FTM_PROCESS_OBJECTS); - - LLViewerObject *objectp; - S32 num_objects; - U32 local_id; - LLPCode pcode = 0; - LLUUID fullid; - S32 i; - - // figure out which simulator these are from and get it's index - // Coordinates in simulators are region-local - // Until we get region-locality working on viewer we - // have to transform to absolute coordinates. - num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); - - // I don't think this case is ever hit. TODO* Test this. - if (!compressed && update_type != OUT_FULL) - { - //LL_INFOS() << "TEST: !cached && !compressed && update_type != OUT_FULL" << LL_ENDL; - gTerseObjectUpdates += num_objects; - /* - S32 size; - if (mesgsys->getReceiveCompressedSize()) - { - size = mesgsys->getReceiveCompressedSize(); - } - else - { - size = mesgsys->getReceiveSize(); - } - LL_INFOS() << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << LL_ENDL; - */ - } - else - { - /* - S32 size; - if (mesgsys->getReceiveCompressedSize()) - { - size = mesgsys->getReceiveCompressedSize(); - } - else - { - size = mesgsys->getReceiveSize(); - } - - LL_INFOS() << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << LL_ENDL; - */ - gFullObjectUpdates += num_objects; - } - - U64 region_handle; - mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); - - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); - - if (!regionp) - { - LL_WARNS() << "Object update from unknown region! " << region_handle << LL_ENDL; - return; - } - - U8 compressed_dpbuffer[2048]; - LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048); - LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); - - for (i = 0; i < num_objects; i++) - { - bool justCreated = false; - bool update_cache = false; //update object cache if it is a full-update or terse update - - if (compressed) - { - compressed_dp.reset(); - - S32 uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); - LL_DEBUGS("ObjectUpdate") << "got binary data from message to compressed_dpbuffer" << LL_ENDL; - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i, 2048); - compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); - - if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? - { - U32 flags = 0; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); - - compressed_dp.unpackUUID(fullid, "ID"); - compressed_dp.unpackU32(local_id, "LocalID"); - compressed_dp.unpackU8(pcode, "PCode"); - - if (pcode == 0) - { - // object creation will fail, LLViewerObject::createObject() - LL_WARNS() << "Received object " << fullid - << " with 0 PCode. Local id: " << local_id - << " Flags: " << flags - << " Region: " << regionp->getName() - << " Region id: " << regionp->getRegionID() << LL_ENDL; - recorder.objectUpdateFailure(); - continue; - } - else if ((flags & FLAGS_TEMPORARY_ON_REZ) == 0) - { - //send to object cache - regionp->cacheFullUpdate(compressed_dp, flags); - continue; - } - } - else //OUT_TERSE_IMPROVED - { - update_cache = true; - compressed_dp.unpackU32(local_id, "LocalID"); - getUUIDFromLocal(fullid, - local_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); - if (fullid.isNull()) - { - LL_DEBUGS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << LL_ENDL; - mNumUnknownUpdates++; - } - } - } - else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only? - { - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); - - getUUIDFromLocal(fullid, - local_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); - if (fullid.isNull()) - { - // LL_WARNS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << LL_ENDL; - mNumUnknownUpdates++; - } - else - { - LL_DEBUGS("ObjectUpdate") << "Non-full, non-compressed update, obj " << local_id << ", global ID " << fullid << " from " << mesgsys->getSender() << LL_ENDL; - } - } - else // OUT_FULL only? - { - update_cache = true; - mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); - LL_DEBUGS("ObjectUpdate") << "Full Update, obj " << local_id << ", global ID " << fullid << " from " << mesgsys->getSender() << LL_ENDL; - } - objectp = findObject(fullid); - - if (compressed) - { - LL_DEBUGS("ObjectUpdate") << "uuid " << fullid << " received compressed data from message (earlier in function)" << LL_ENDL; - } - LL_DEBUGS("ObjectUpdate") << "uuid " << fullid << " objectp " << objectp - << " update_cache " << (S32) update_cache << " compressed " << compressed - << " update_type " << update_type << LL_ENDL; - dumpStack("ObjectUpdateStack"); - - if(update_cache) - { - //update object cache if the object receives a full-update or terse update - objectp = regionp->updateCacheEntry(local_id, objectp); - } - - // This looks like it will break if the local_id of the object doesn't change - // upon boundary crossing, but we check for region id matching later... - // Reset object local id and region pointer if things have changed - if (objectp && - ((objectp->mLocalID != local_id) || - (objectp->getRegion() != regionp))) - { - //if (objectp->getRegion()) - //{ - // LL_INFOS() << "Local ID change: Removing object from table, local ID " << objectp->mLocalID - // << ", id from message " << local_id << ", from " - // << LLHost(objectp->getRegion()->getHost().getAddress(), objectp->getRegion()->getHost().getPort()) - // << ", full id " << fullid - // << ", objects id " << objectp->getID() - // << ", regionp " << (U32) regionp << ", object region " << (U32) objectp->getRegion() - // << LL_ENDL; - //} - removeFromLocalIDTable(objectp); - setUUIDAndLocal(fullid, - local_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); - - if (objectp->mLocalID != local_id) - { // Update local ID in object with the one sent from the region - objectp->mLocalID = local_id; - } - - if (objectp->getRegion() != regionp) - { // Object changed region, so update it - objectp->updateRegion(regionp); // for LLVOAvatar - } - } - - if (!objectp) - { - if (compressed) - { - if (update_type == OUT_TERSE_IMPROVED) - { - // LL_INFOS() << "terse update for an unknown object (compressed):" << fullid << LL_ENDL; - recorder.objectUpdateFailure(); - continue; - } - } - else - { - if (update_type != OUT_FULL) - { - //LL_INFOS() << "terse update for an unknown object:" << fullid << LL_ENDL; - recorder.objectUpdateFailure(); - continue; - } - - mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i); - - } -#ifdef IGNORE_DEAD - if (mDeadObjects.find(fullid) != mDeadObjects.end()) - { - mNumDeadObjectUpdates++; - //LL_INFOS() << "update for a dead object:" << fullid << LL_ENDL; - recorder.objectUpdateFailure(); - continue; - } -#endif - - objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender()); - - LL_DEBUGS("ObjectUpdate") << "creating object " << fullid << " result " << objectp << LL_ENDL; - dumpStack("ObjectUpdateStack"); - - if (!objectp) - { - LL_INFOS() << "createObject failure for object: " << fullid << LL_ENDL; - recorder.objectUpdateFailure(); - continue; - } - - justCreated = true; - mNumNewObjects++; - } - - if (objectp->isDead()) - { - LL_WARNS() << "Dead object " << objectp->mID << " in UUID map 1!" << LL_ENDL; - } - - //bool bCached = false; - if (compressed) - { - if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? - { - objectp->mLocalID = local_id; - } - processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); - -#if 0 - if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? - { - U32 flags = 0; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); - - if(!(flags & FLAGS_TEMPORARY_ON_REZ)) - { - bCached = true; - LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags); - recorder.cacheFullUpdate(result); - } - } -#endif - } - else - { - if (update_type == OUT_FULL) - { - objectp->mLocalID = local_id; - } - processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated); - } - recorder.objectUpdateEvent(update_type); - objectp->setLastUpdateType(update_type); - } - - LLVOAvatar::cullAvatarsByPixelArea(); -} - -void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem *mesgsys, - void **user_data, - const EObjectUpdateType update_type) -{ - processObjectUpdate(mesgsys, user_data, update_type, true); -} - -void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys, - void **user_data, - const EObjectUpdateType update_type) -{ - //processObjectUpdate(mesgsys, user_data, update_type, true, false); - - S32 num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); - gFullObjectUpdates += num_objects; - - U64 region_handle; - mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); - if (!regionp) - { - LL_WARNS() << "Object update from unknown region! " << region_handle << LL_ENDL; - return; - } - - LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); - - for (S32 i = 0; i < num_objects; i++) - { - U32 id; - U32 crc; - U32 flags; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); - - LL_DEBUGS("ObjectUpdate") << "got probe for id " << id << " crc " << crc << LL_ENDL; - dumpStack("ObjectUpdateStack"); - - // Lookup data packer and add this id to cache miss lists if necessary. - U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; - if (regionp->probeCache(id, crc, flags, cache_miss_type)) - { // Cache Hit - recorder.cacheHitEvent(); - } - else - { // Cache Miss - LL_DEBUGS("ObjectUpdate") << "cache miss for id " << id << " crc " << crc << " miss type " << (S32) cache_miss_type << LL_ENDL; - recorder.cacheMissEvent(cache_miss_type); - } - } - - return; -} - -void LLViewerObjectList::dirtyAllObjectInventory() -{ - for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) - { - (*iter)->dirtyInventory(); - } -} - -void LLViewerObjectList::updateApparentAngles(LLAgent &agent) -{ - S32 i; - LLViewerObject *objectp; - - S32 num_updates, max_value; - if (NUM_BINS - 1 == mCurBin) - { - // Remainder (mObjects.size() could have changed) - num_updates = (S32) mObjects.size() - mCurLazyUpdateIndex; - max_value = (S32) mObjects.size(); - } - else - { - num_updates = ((S32) mObjects.size() / NUM_BINS) + 1; - max_value = llmin((S32) mObjects.size(), mCurLazyUpdateIndex + num_updates); - } - - // Iterate through some of the objects and lazy update their texture priorities - for (i = mCurLazyUpdateIndex; i < max_value; i++) - { - objectp = mObjects[i]; - if (!objectp->isDead()) - { - // Update distance & gpw - objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area - objectp->updateTextures(); // Update the image levels of textures for this object. - } - } - - mCurLazyUpdateIndex = max_value; - if (mCurLazyUpdateIndex == mObjects.size()) - { - // restart - mCurLazyUpdateIndex = 0; - mCurBin = 0; // keep in sync with index (mObjects.size() could have changed) - } - else - { - mCurBin = (mCurBin + 1) % NUM_BINS; - } - -#if 0 - // Slam priorities for textures that we care about (hovered, selected, and focused) - // Hovered - // Assumes only one level deep of parenting - LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); - if (nodep) - { - objectp = nodep->getObject(); - if (objectp) - { - objectp->boostTexturePriority(); - } - } - - // Focused - objectp = gAgentCamera.getFocusObject(); - if (objectp) - { - objectp->boostTexturePriority(); - } -#endif - - // Selected - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* objectp) - { - if (objectp) - { - objectp->boostTexturePriority(); - } - return true; - } - } func; - LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func); - - LLVOAvatar::cullAvatarsByPixelArea(); -} - -void LLViewerObjectList::update(LLAgent &agent) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - - // Update globals - LLViewerObject::setVelocityInterpolate( gSavedSettings.getBOOL("VelocityInterpolate") ); - LLViewerObject::setPingInterpolate( gSavedSettings.getBOOL("PingInterpolate") ); - - F32 interp_time = gSavedSettings.getF32("InterpolationTime"); - F32 phase_out_time = gSavedSettings.getF32("InterpolationPhaseOut"); - F32 region_interp_time = llclamp(gSavedSettings.getF32("RegionCrossingInterpolationTime"), 0.5f, 5.f); - if (interp_time < 0.0 || - phase_out_time < 0.0 || - phase_out_time > interp_time) - { - LL_WARNS() << "Invalid values for InterpolationTime or InterpolationPhaseOut, resetting to defaults" << LL_ENDL; - interp_time = 3.0f; - phase_out_time = 1.0f; - } - LLViewerObject::setPhaseOutUpdateInterpolationTime( interp_time ); - LLViewerObject::setMaxUpdateInterpolationTime( phase_out_time ); - LLViewerObject::setMaxRegionCrossingInterpolationTime(region_interp_time); - - gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures"); - - // update global timer - F32 last_time = gFrameTimeSeconds; - U64Microseconds time = totalTime(); // this will become the new gFrameTime when the update is done - // Time _can_ go backwards, for example if the user changes the system clock. - // It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here. -// llassert(time > gFrameTime); - F64Seconds time_diff = time - gFrameTime; - gFrameTime = time; - F64Seconds time_since_start = gFrameTime - gStartTime; - gFrameTimeSeconds = time_since_start; - - gFrameIntervalSeconds = gFrameTimeSeconds - last_time; - if (gFrameIntervalSeconds < 0.f) - { - gFrameIntervalSeconds = 0.f; - } - - //clear avatar LOD change counter - LLVOAvatar::sNumLODChangesThisFrame = 0; - - const F64 frame_time = LLFrameTimer::getElapsedSeconds(); - - LLViewerObject *objectp = NULL; - - // Make a copy of the list in case something in idleUpdate() messes with it - static std::vector idle_list; - - U32 idle_count = 0; - - { - for (std::vector >::iterator active_iter = mActiveObjects.begin(); - active_iter != mActiveObjects.end(); active_iter++) - { - objectp = *active_iter; - if (objectp) - { - if (idle_count >= idle_list.size()) - { - idle_list.push_back( objectp ); - } - else - { - idle_list[idle_count] = objectp; - } - ++idle_count; - } - else - { // There shouldn't be any NULL pointers in the list, but they have caused - // crashes before. This may be idleUpdate() messing with the list. - LL_WARNS() << "LLViewerObjectList::update has a NULL objectp" << LL_ENDL; - } - } - } - - std::vector::iterator idle_end = idle_list.begin()+idle_count; - - if (gSavedSettings.getBOOL("FreezeTime")) - { - - for (std::vector::iterator iter = idle_list.begin(); - iter != idle_end; iter++) - { - objectp = *iter; - if (objectp->isAvatar()) - { - objectp->idleUpdate(agent, frame_time); - } - } - } - else - { - for (std::vector::iterator idle_iter = idle_list.begin(); - idle_iter != idle_end; idle_iter++) - { - objectp = *idle_iter; - llassert(objectp->isActive()); - objectp->idleUpdate(agent, frame_time); - } - - //update flexible objects - LLVolumeImplFlexible::updateClass(); - - //update animated textures - if (gAnimateTextures) - { - LLViewerTextureAnim::updateClass(); - } - } - - - - fetchObjectCosts(); - fetchPhysicsFlags(); - - // update max computed render cost - LLVOVolume::updateRenderComplexity(); - - // compute all sorts of time-based stats - // don't factor frames that were paused into the stats - if (! mWasPaused) - { - LLViewerStats::getInstance()->updateFrameStats(time_diff); - } - - /* - // Debugging code for viewing orphans, and orphaned parents - LLUUID id; - for (i = 0; i < mOrphanParents.size(); i++) - { - id = sIndexAndLocalIDToUUID[mOrphanParents[i]]; - LLViewerObject *objectp = findObject(id); - if (objectp) - { - std::string id_str; - objectp->mID.toString(id_str); - std::string tmpstr = std::string("Par: ") + id_str; - addDebugBeacon(objectp->getPositionAgent(), - tmpstr, - LLColor4(1.f,0.f,0.f,1.f), - LLColor4(1.f,1.f,1.f,1.f)); - } - } - - LLColor4 text_color; - for (i = 0; i < mOrphanChildren.size(); i++) - { - OrphanInfo oi = mOrphanChildren[i]; - LLViewerObject *objectp = findObject(oi.mChildInfo); - if (objectp) - { - std::string id_str; - objectp->mID.toString(id_str); - std::string tmpstr; - if (objectp->getParent()) - { - tmpstr = std::string("ChP: ") + id_str; - text_color = LLColor4(0.f, 1.f, 0.f, 1.f); - } - else - { - tmpstr = std::string("ChNoP: ") + id_str; - text_color = LLColor4(1.f, 0.f, 0.f, 1.f); - } - id = sIndexAndLocalIDToUUID[oi.mParentInfo]; - addDebugBeacon(objectp->getPositionAgent() + LLVector3(0.f, 0.f, -0.25f), - tmpstr, - LLColor4(0.25f,0.25f,0.25f,1.f), - text_color); - } - i++; - } - */ - - sample(LLStatViewer::NUM_OBJECTS, mObjects.size()); - sample(LLStatViewer::NUM_ACTIVE_OBJECTS, idle_count); -} - -void LLViewerObjectList::fetchObjectCosts() -{ - // issue http request for stale object physics costs - if (!mStaleObjectCost.empty()) - { - LLViewerRegion* regionp = gAgent.getRegion(); - - if (regionp) - { - std::string url = regionp->getCapability("GetObjectCost"); - - if (!url.empty()) - { - LLCoros::instance().launch("LLViewerObjectList::fetchObjectCostsCoro", - boost::bind(&LLViewerObjectList::fetchObjectCostsCoro, this, url)); - } - else - { - mStaleObjectCost.clear(); - mPendingObjectCost.clear(); - } - } - } -} - -/*static*/ -void LLViewerObjectList::reportObjectCostFailure(LLSD &objectList) -{ - // TODO*: No more hard coding - for (LLSD::array_iterator it = objectList.beginArray(); it != objectList.endArray(); ++it) - { - gObjectList.onObjectCostFetchFailure(it->asUUID()); - } -} - - -void LLViewerObjectList::fetchObjectCostsCoro(std::string url) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - - - uuid_set_t diff; - - std::set_difference(mStaleObjectCost.begin(), mStaleObjectCost.end(), - mPendingObjectCost.begin(), mPendingObjectCost.end(), - std::inserter(diff, diff.begin())); - - mStaleObjectCost.clear(); - - if (diff.empty()) - { - LL_INFOS() << "No outstanding object IDs to request. Pending count: " << mPendingObjectCost.size() << LL_ENDL; - return; - } - - LLSD idList(LLSD::emptyArray()); - - for (uuid_set_t::iterator it = diff.begin(); it != diff.end(); ++it) - { - idList.append(*it); - } - - mPendingObjectCost.insert(diff.begin(), diff.end()); - - LLSD postData = LLSD::emptyMap(); - - postData["object_ids"] = idList; - - LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - if (!status || result.has("error")) - { - if (result.has("error")) - { - LL_WARNS() << "Application level error when fetching object " - << "cost. Message: " << result["error"]["message"].asString() - << ", identifier: " << result["error"]["identifier"].asString() - << LL_ENDL; - - // TODO*: Adaptively adjust request size if the - // service says we've requested too many and retry - } - reportObjectCostFailure(idList); - - return; - } - - // Success, grab the resource cost and linked set costs - // for an object if one was returned - for (LLSD::array_iterator it = idList.beginArray(); it != idList.endArray(); ++it) - { - LLUUID objectId = it->asUUID(); - - // Object could have been added to the mStaleObjectCost after request started - mStaleObjectCost.erase(objectId); - mPendingObjectCost.erase(objectId); - - // Check to see if the request contains data for the object - if (result.has(it->asString())) - { - LLSD objectData = result[it->asString()]; - - F32 linkCost = objectData["linked_set_resource_cost"].asReal(); - F32 objectCost = objectData["resource_cost"].asReal(); - F32 physicsCost = objectData["physics_cost"].asReal(); - F32 linkPhysicsCost = objectData["linked_set_physics_cost"].asReal(); - - gObjectList.updateObjectCost(objectId, objectCost, linkCost, physicsCost, linkPhysicsCost); - } - else - { - // TODO*: Give user feedback about the missing data? - gObjectList.onObjectCostFetchFailure(objectId); - } - } - -} - -void LLViewerObjectList::fetchPhysicsFlags() -{ - // issue http request for stale object physics flags - if (!mStalePhysicsFlags.empty()) - { - LLViewerRegion* regionp = gAgent.getRegion(); - - if (regionp) - { - std::string url = regionp->getCapability("GetObjectPhysicsData"); - - if (!url.empty()) - { - LLCoros::instance().launch("LLViewerObjectList::fetchPhisicsFlagsCoro", - boost::bind(&LLViewerObjectList::fetchPhisicsFlagsCoro, this, url)); - } - else - { - mStalePhysicsFlags.clear(); - mPendingPhysicsFlags.clear(); - } - } - } -} - -/*static*/ -void LLViewerObjectList::reportPhysicsFlagFailure(LLSD &objectList) -{ - // TODO*: No more hard coding - for (LLSD::array_iterator it = objectList.beginArray(); it != objectList.endArray(); ++it) - { - gObjectList.onPhysicsFlagsFetchFailure(it->asUUID()); - } -} - -void LLViewerObjectList::fetchPhisicsFlagsCoro(std::string url) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - LLSD idList; - U32 objectIndex = 0; - - for (uuid_set_t::iterator it = mStalePhysicsFlags.begin(); it != mStalePhysicsFlags.end();) - { - // Check to see if a request for this object - // has already been made. - if (mPendingPhysicsFlags.find(*it) == mPendingPhysicsFlags.end()) - { - mPendingPhysicsFlags.insert(*it); - idList[objectIndex++] = *it; - } - - mStalePhysicsFlags.erase(it++); - - if (objectIndex >= MAX_CONCURRENT_PHYSICS_REQUESTS) - { - break; - } - } - - if (idList.size() < 1) - { - LL_INFOS() << "No outstanding object physics flags to request." << LL_ENDL; - return; - } - - LLSD postData = LLSD::emptyMap(); - - postData["object_ids"] = idList; - - LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - if (!status || result.has("error")) - { - if (result.has("error")) - { - LL_WARNS() << "Application level error when fetching object " - << "physics flags. Message: " << result["error"]["message"].asString() - << ", identifier: " << result["error"]["identifier"].asString() - << LL_ENDL; - - // TODO*: Adaptively adjust request size if the - // service says we've requested too many and retry - } - reportPhysicsFlagFailure(idList); - - return; - } - - // Success, grab the resource cost and linked set costs - // for an object if one was returned - for (LLSD::array_iterator it = idList.beginArray(); it != idList.endArray(); ++it) - { - LLUUID objectId = it->asUUID(); - - // Check to see if the request contains data for the object - if (result.has(it->asString())) - { - const LLSD& data = result[it->asString()]; - - S32 shapeType = data["PhysicsShapeType"].asInteger(); - - gObjectList.updatePhysicsShapeType(objectId, shapeType); - - if (data.has("Density")) - { - F32 density = data["Density"].asReal(); - F32 friction = data["Friction"].asReal(); - F32 restitution = data["Restitution"].asReal(); - F32 gravityMult = data["GravityMultiplier"].asReal(); - - gObjectList.updatePhysicsProperties(objectId, density, - friction, restitution, gravityMult); - } - } - else - { - // TODO*: Give user feedback about the missing data? - gObjectList.onPhysicsFlagsFetchFailure(objectId); - } - } -} - -void LLViewerObjectList::clearDebugText() -{ - for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) - { - (*iter)->restoreHudText(); - } -} - - -void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - - bool new_dead_object = true; - if (mDeadObjects.find(objectp->mID) != mDeadObjects.end()) - { - LL_INFOS() << "Object " << objectp->mID << " already on dead list!" << LL_ENDL; - new_dead_object = false; - } - else - { - mDeadObjects.insert(objectp->mID); - } - - // Cleanup any references we have to this object - // Remove from object map so noone can look it up. - - LL_DEBUGS("ObjectUpdate") << " dereferencing id " << objectp->mID << LL_ENDL; - dumpStack("ObjectUpdateStack"); - - mUUIDObjectMap.erase(objectp->mID); - - //if (objectp->getRegion()) - //{ - // LL_INFOS() << "cleanupReferences removing object from table, local ID " << objectp->mLocalID << ", ip " - // << objectp->getRegion()->getHost().getAddress() << ":" - // << objectp->getRegion()->getHost().getPort() << LL_ENDL; - //} - - removeFromLocalIDTable(objectp); - - if (objectp->onActiveList()) - { - //LL_INFOS() << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << LL_ENDL; - objectp->setOnActiveList(false); - removeFromActiveList(objectp); - } - - if (objectp->isOnMap()) - { - removeFromMap(objectp); - } - - // Don't clean up mObject references, these will be cleaned up more efficiently later! - - if(new_dead_object) - { - mNumDeadObjects++; - } -} - -bool LLViewerObjectList::killObject(LLViewerObject *objectp) -{ - LL_PROFILE_ZONE_SCOPED; - // Don't ever kill gAgentAvatarp, just force it to the agent's region - // unless region is NULL which is assumed to mean you are logging out. - if ((objectp == gAgentAvatarp) && gAgent.getRegion()) - { - objectp->setRegion(gAgent.getRegion()); - return false; - } - - // When we're killing objects, all we do is mark them as dead. - // We clean up the dead objects later. - - if (objectp) - { - // We are going to cleanup a lot of smart pointers to this object, they might be last, - // and object being NULLed while inside it's own function won't be pretty - // so create a pointer to make sure object will stay alive untill markDead() finishes - LLPointer sp(objectp); - sp->markDead(); // does the right thing if object already dead - return true; - } - - return false; -} - -void LLViewerObjectList::killObjects(LLViewerRegion *regionp) -{ - LL_PROFILE_ZONE_SCOPED; - LLViewerObject *objectp; - - - for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) - { - objectp = *iter; - - if (objectp->mRegionp == regionp) - { - killObject(objectp); - } - } - - // Have to clean right away because the region is becoming invalid. - cleanDeadObjects(false); -} - -void LLViewerObjectList::killAllObjects() -{ - // Used only on global destruction. - LLViewerObject *objectp; - - for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) - { - objectp = *iter; - killObject(objectp); - // Object must be dead, or it's the LLVOAvatarSelf which never dies. - llassert((objectp == gAgentAvatarp) || objectp->isDead()); - } - - cleanDeadObjects(false); - - if(!mObjects.empty()) - { - LL_WARNS() << "LLViewerObjectList::killAllObjects still has entries in mObjects: " << mObjects.size() << LL_ENDL; - mObjects.clear(); - } - - if (!mActiveObjects.empty()) - { - LL_WARNS() << "Some objects still on active object list!" << LL_ENDL; - mActiveObjects.clear(); - } - - if (!mMapObjects.empty()) - { - LL_WARNS() << "Some objects still on map object list!" << LL_ENDL; - mMapObjects.clear(); - } -} - -void LLViewerObjectList::cleanDeadObjects(bool use_timer) -{ - if (!mNumDeadObjects) - { - // No dead objects, don't need to scan object list. - return; - } - - LL_PROFILE_ZONE_SCOPED; - - S32 num_removed = 0; - LLViewerObject *objectp; - - vobj_list_t::reverse_iterator target = mObjects.rbegin(); - - vobj_list_t::iterator iter = mObjects.begin(); - for ( ; iter != mObjects.end(); ) - { - // Scan for all of the dead objects and put them all on the end of the list with no ref count ops - objectp = *iter; - if (objectp == NULL) - { //we caught up to the dead tail - break; - } - - if (objectp->isDead()) - { - LLPointer::swap(*iter, *target); - *target = NULL; - ++target; - num_removed++; - - if (num_removed == mNumDeadObjects || iter->isNull()) - { - // We've cleaned up all of the dead objects or caught up to the dead tail - break; - } - } - else - { - ++iter; - } - } - - llassert(num_removed == mNumDeadObjects); - - //erase as a block - mObjects.erase(mObjects.begin()+(mObjects.size()-mNumDeadObjects), mObjects.end()); - - // We've cleaned the global object list, now let's do some paranoia testing on objects - // before blowing away the dead list. - mDeadObjects.clear(); - mNumDeadObjects = 0; -} - -void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) -{ - S32 idx = objectp->getListIndex(); - if (idx != -1) - { //remove by moving last element to this object's position - llassert(mActiveObjects[idx] == objectp); - - objectp->setListIndex(-1); - - S32 last_index = mActiveObjects.size()-1; - - if (idx != last_index) - { - mActiveObjects[idx] = mActiveObjects[last_index]; - mActiveObjects[idx]->setListIndex(idx); - } - - mActiveObjects.pop_back(); - } -} - -void LLViewerObjectList::updateActive(LLViewerObject *objectp) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; - - if (objectp->isDead()) - { - return; // We don't update dead objects! - } - - bool active = objectp->isActive(); - if (active != objectp->onActiveList()) - { - if (active) - { - //LL_INFOS() << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << LL_ENDL; - S32 idx = objectp->getListIndex(); - if (idx <= -1) - { - mActiveObjects.push_back(objectp); - objectp->setListIndex(mActiveObjects.size()-1); - objectp->setOnActiveList(true); - } - else - { - llassert(idx < mActiveObjects.size()); - llassert(mActiveObjects[idx] == objectp); - - if (idx >= mActiveObjects.size() || - mActiveObjects[idx] != objectp) - { - LL_WARNS() << "Invalid object list index detected!" << LL_ENDL; - } - } - } - else - { - //LL_INFOS() << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << LL_ENDL; - removeFromActiveList(objectp); - objectp->setOnActiveList(false); - } - } - - //post condition: if object is active, it must be on the active list - llassert(!active || std::find(mActiveObjects.begin(), mActiveObjects.end(), objectp) != mActiveObjects.end()); - - //post condition: if object is not active, it must not be on the active list - llassert(active || std::find(mActiveObjects.begin(), mActiveObjects.end(), objectp) == mActiveObjects.end()); -} - -void LLViewerObjectList::updateObjectCost(LLViewerObject* object) -{ - if (!object->isRoot()) - { //always fetch cost for the parent when fetching cost for children - mStaleObjectCost.insert(((LLViewerObject*)object->getParent())->getID()); - } - mStaleObjectCost.insert(object->getID()); -} - -void LLViewerObjectList::updateObjectCost(const LLUUID& object_id, F32 object_cost, F32 link_cost, F32 physics_cost, F32 link_physics_cost) -{ - LLViewerObject* object = findObject(object_id); - if (object) - { - object->setObjectCost(object_cost); - object->setLinksetCost(link_cost); - object->setPhysicsCost(physics_cost); - object->setLinksetPhysicsCost(link_physics_cost); - } -} - -void LLViewerObjectList::onObjectCostFetchFailure(const LLUUID& object_id) -{ - //LL_WARNS() << "Failed to fetch object cost for object: " << object_id << LL_ENDL; - mPendingObjectCost.erase(object_id); -} - -void LLViewerObjectList::updatePhysicsFlags(const LLViewerObject* object) -{ - mStalePhysicsFlags.insert(object->getID()); -} - -void LLViewerObjectList::updatePhysicsShapeType(const LLUUID& object_id, S32 type) -{ - mPendingPhysicsFlags.erase(object_id); - LLViewerObject* object = findObject(object_id); - if (object) - { - object->setPhysicsShapeType(type); - } -} - -void LLViewerObjectList::updatePhysicsProperties(const LLUUID& object_id, - F32 density, - F32 friction, - F32 restitution, - F32 gravity_multiplier) -{ - mPendingPhysicsFlags.erase(object_id); - - LLViewerObject* object = findObject(object_id); - if (object) - { - object->setPhysicsDensity(density); - object->setPhysicsFriction(friction); - object->setPhysicsGravity(gravity_multiplier); - object->setPhysicsRestitution(restitution); - } -} - -void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) -{ - //LL_WARNS() << "Failed to fetch physics flags for object: " << object_id << LL_ENDL; - mPendingPhysicsFlags.erase(object_id); -} - -void LLViewerObjectList::shiftObjects(const LLVector3 &offset) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - // This is called when we shift our origin when we cross region boundaries... - // We need to update many object caches, I'll document this more as I dig through the code - // cleaning things out... - - if (0 == offset.magVecSquared()) - { - return; - } - - - LLViewerObject *objectp; - for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) - { - objectp = *iter; - // There could be dead objects on the object list, so don't update stuff if the object is dead. - if (!objectp->isDead()) - { - objectp->updatePositionCaches(); - - if (objectp->mDrawable.notNull() && !objectp->mDrawable->isDead()) - { - gPipeline.markShift(objectp->mDrawable); - } - } - } - - gPipeline.shiftObjects(offset); - - LLWorld::getInstance()->shiftRegions(offset); -} - -void LLViewerObjectList::repartitionObjects() -{ - for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - if (!objectp->isDead()) - { - LLDrawable* drawable = objectp->mDrawable; - if (drawable && !drawable->isDead()) - { - drawable->updateBinRadius(); - drawable->updateSpatialExtents(); - drawable->movePartition(); - } - } - } -} - -//debug code -bool LLViewerObjectList::hasMapObjectInRegion(LLViewerRegion* regionp) -{ - for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - - if(objectp->isDead() || objectp->getRegion() == regionp) - { - return true ; - } - } - - return false ; -} - -//make sure the region is cleaned up. -void LLViewerObjectList::clearAllMapObjectsInRegion(LLViewerRegion* regionp) -{ - std::set dead_object_list ; - std::set region_object_list ; - for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - - if(objectp->isDead()) - { - dead_object_list.insert(objectp) ; - } - else if(objectp->getRegion() == regionp) - { - region_object_list.insert(objectp) ; - } - } - - if(dead_object_list.size() > 0) - { - LL_WARNS() << "There are " << dead_object_list.size() << " dead objects on the map!" << LL_ENDL ; - - for(std::set::iterator iter = dead_object_list.begin(); iter != dead_object_list.end(); ++iter) - { - cleanupReferences(*iter) ; - } - } - if(region_object_list.size() > 0) - { - LL_WARNS() << "There are " << region_object_list.size() << " objects not removed from the deleted region!" << LL_ENDL ; - - for(std::set::iterator iter = region_object_list.begin(); iter != region_object_list.end(); ++iter) - { - (*iter)->markDead() ; - } - } -} - - -void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap) -{ - LLColor4 above_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnAboveWater" ); - LLColor4 below_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnBelowWater" ); - LLColor4 you_own_above_water_color = - LLUIColorTable::instance().getColor( "NetMapYouOwnAboveWater" ); - LLColor4 you_own_below_water_color = - LLUIColorTable::instance().getColor( "NetMapYouOwnBelowWater" ); - LLColor4 group_own_above_water_color = - LLUIColorTable::instance().getColor( "NetMapGroupOwnAboveWater" ); - LLColor4 group_own_below_water_color = - LLUIColorTable::instance().getColor( "NetMapGroupOwnBelowWater" ); - - F32 max_radius = gSavedSettings.getF32("MiniMapPrimMaxRadius"); - - for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - - if(objectp->isDead())//some dead objects somehow not cleaned. - { - continue ; - } - - if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment()) - { - continue; - } - const LLVector3& scale = objectp->getScale(); - const LLVector3d pos = objectp->getPositionGlobal(); - const F64 water_height = F64( objectp->getRegion()->getWaterHeight() ); - // LLWorld::getInstance()->getWaterHeight(); - - F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f; // 1.3 is a fudge - - // Limit the size of megaprims so they don't blot out everything on the minimap. - // Attempting to draw very large megaprims also causes client lag. - // See DEV-17370 and DEV-29869/SNOW-79 for details. - approx_radius = llmin(approx_radius, max_radius); - - LLColor4U color = above_water_color; - if( objectp->permYouOwner() ) - { - const F32 MIN_RADIUS_FOR_OWNED_OBJECTS = 2.f; - if( approx_radius < MIN_RADIUS_FOR_OWNED_OBJECTS ) - { - approx_radius = MIN_RADIUS_FOR_OWNED_OBJECTS; - } - - if( pos.mdV[VZ] >= water_height ) - { - if ( objectp->permGroupOwner() ) - { - color = group_own_above_water_color; - } - else - { - color = you_own_above_water_color; - } - } - else - { - if ( objectp->permGroupOwner() ) - { - color = group_own_below_water_color; - } - else - { - color = you_own_below_water_color; - } - } - } - else - if( pos.mdV[VZ] < water_height ) - { - color = below_water_color; - } - - netmap.renderScaledPointGlobal( - pos, - color, - approx_radius ); - } -} - -void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er) -{ -} - -extern bool gCubeSnapshot; - -void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent, - const std::string &string, - const LLColor4 &color, - const LLColor4 &text_color, - S32 line_width) -{ - llassert(!gCubeSnapshot); - LLDebugBeacon beacon; - beacon.mPositionAgent = pos_agent; - beacon.mString = string; - beacon.mColor = color; - beacon.mTextColor = text_color; - beacon.mLineWidth = line_width; - - mDebugBeacons.push_back(beacon); -} - -void LLViewerObjectList::resetObjectBeacons() -{ - mDebugBeacons.clear(); -} - -LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp, S32 flags) -{ - LLUUID fullid; - fullid.generate(); - - LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp, flags); - if (!objectp) - { -// LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << LL_ENDL; - return NULL; - } - - mUUIDObjectMap[fullid] = objectp; - - mObjects.push_back(objectp); - - updateActive(objectp); - - return objectp; -} - -LLViewerObject *LLViewerObjectList::createObjectFromCache(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id) -{ - llassert_always(uuid.notNull()); - - LL_DEBUGS("ObjectUpdate") << "creating " << uuid << " local_id " << local_id << LL_ENDL; - dumpStack("ObjectUpdateStack"); - - LLViewerObject *objectp = LLViewerObject::createObject(uuid, pcode, regionp); - if (!objectp) - { -// LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << LL_ENDL; - return NULL; - } - - objectp->mLocalID = local_id; - mUUIDObjectMap[uuid] = objectp; - setUUIDAndLocal(uuid, - local_id, - regionp->getHost().getAddress(), - regionp->getHost().getPort()); - mObjects.push_back(objectp); - - updateActive(objectp); - - return objectp; -} - -LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp, - const LLUUID &uuid, const U32 local_id, const LLHost &sender) -{ - LLUUID fullid; - if (uuid == LLUUID::null) - { - fullid.generate(); - } - else - { - fullid = uuid; - } - - LL_DEBUGS("ObjectUpdate") << "createObject creating " << fullid << LL_ENDL; - dumpStack("ObjectUpdateStack"); - - LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp); - if (!objectp) - { -// LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << LL_ENDL; - return NULL; - } - if(regionp) - { - regionp->addToCreatedList(local_id); - } - - mUUIDObjectMap[fullid] = objectp; - setUUIDAndLocal(fullid, - local_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); - - mObjects.push_back(objectp); - - updateActive(objectp); - - return objectp; -} - -LLViewerObject *LLViewerObjectList::replaceObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -{ - LLViewerObject *old_instance = findObject(id); - if (old_instance) - { - //cleanupReferences(old_instance); - old_instance->markDead(); - - return createObject(pcode, regionp, id, old_instance->getLocalID(), LLHost()); - } - return NULL; -} - -S32 LLViewerObjectList::findReferences(LLDrawable *drawablep) const -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; - - LLViewerObject *objectp; - S32 num_refs = 0; - - for (vobj_list_t::const_iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) - { - objectp = *iter; - if (objectp->mDrawable.notNull()) - { - num_refs += objectp->mDrawable->findReferences(drawablep); - } - } - return num_refs; -} - - -void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip, U32 port) -{ - LL_DEBUGS("ORPHANS") << "Orphaning object " << childp->getID() << " with parent " << parent_id << LL_ENDL; - - // We're an orphan, flag things appropriately. - childp->mOrphaned = true; - if (childp->mDrawable.notNull()) - { - bool make_invisible = true; - LLViewerObject *parentp = (LLViewerObject *)childp->getParent(); - if (parentp) - { - if (parentp->getRegion() != childp->getRegion()) - { - // This is probably an object flying across a region boundary, the - // object probably ISN'T being reparented, but just got an object - // update out of order (child update before parent). - make_invisible = false; - //LL_INFOS() << "Don't make object handoffs invisible!" << LL_ENDL; - } - } - - if (make_invisible) - { - // Make sure that this object becomes invisible if it's an orphan - childp->mDrawable->setState(LLDrawable::FORCE_INVISIBLE); - } - } - - // Unknown parent, add to orpaned child list - U64 parent_info = getIndex(parent_id, ip, port); - - if (std::find(mOrphanParents.begin(), mOrphanParents.end(), parent_info) == mOrphanParents.end()) - { - mOrphanParents.push_back(parent_info); - } - - LLViewerObjectList::OrphanInfo oi(parent_info, childp->mID); - if (std::find(mOrphanChildren.begin(), mOrphanChildren.end(), oi) == mOrphanChildren.end()) - { - mOrphanChildren.push_back(oi); - mNumOrphans++; - } -} - - -void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - - if (objectp->isDead()) - { - LL_WARNS() << "Trying to find orphans for dead obj " << objectp->mID - << ":" << objectp->getPCodeString() << LL_ENDL; - return; - } - - //search object cache to get orphans - if(objectp->getRegion()) - { - objectp->getRegion()->findOrphans(objectp->getLocalID()); - } - - // See if we are a parent of an orphan. - // Note: This code is fairly inefficient but it should happen very rarely. - // It can be sped up if this is somehow a performance issue... - if (mOrphanParents.empty()) - { - // no known orphan parents - return; - } - if (std::find(mOrphanParents.begin(), mOrphanParents.end(), getIndex(objectp->mLocalID, ip, port)) == mOrphanParents.end()) - { - // did not find objectp in OrphanParent list - return; - } - - U64 parent_info = getIndex(objectp->mLocalID, ip, port); - bool orphans_found = false; - // Iterate through the orphan list, and set parents of matching children. - - for (std::vector::iterator iter = mOrphanChildren.begin(); iter != mOrphanChildren.end(); ) - { - if (iter->mParentInfo != parent_info) - { - ++iter; - continue; - } - LLViewerObject *childp = findObject(iter->mChildInfo); - if (childp) - { - if (childp == objectp) - { - LL_WARNS() << objectp->mID << " has self as parent, skipping!" - << LL_ENDL; - ++iter; - continue; - } - - LL_DEBUGS("ORPHANS") << "Reunited parent " << objectp->mID - << " with child " << childp->mID << LL_ENDL; - LL_DEBUGS("ORPHANS") << "Glob: " << objectp->getPositionGlobal() << LL_ENDL; - LL_DEBUGS("ORPHANS") << "Agent: " << objectp->getPositionAgent() << LL_ENDL; -#ifdef ORPHAN_SPAM - addDebugBeacon(objectp->getPositionAgent(),""); -#endif - gPipeline.markMoved(objectp->mDrawable); - objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE); - - // Flag the object as no longer orphaned - childp->mOrphaned = false; - if (childp->mDrawable.notNull()) - { - // Make the drawable visible again and set the drawable parent - childp->mDrawable->clearState(LLDrawable::FORCE_INVISIBLE); - childp->setDrawableParent(objectp->mDrawable); // LLViewerObjectList::findOrphans() - gPipeline.markRebuild( childp->mDrawable, LLDrawable::REBUILD_ALL); - } - - // Make certain particles, icon and HUD aren't hidden - childp->hideExtraDisplayItems( false ); - - objectp->addChild(childp); - orphans_found = true; - ++iter; - } - else - { - LL_INFOS() << "Missing orphan child, removing from list" << LL_ENDL; - - iter = mOrphanChildren.erase(iter); - } - } - - // Remove orphan parent and children from lists now that they've been found - { - std::vector::iterator iter = std::find(mOrphanParents.begin(), mOrphanParents.end(), parent_info); - if (iter != mOrphanParents.end()) - { - mOrphanParents.erase(iter); - } - } - - for (std::vector::iterator iter = mOrphanChildren.begin(); iter != mOrphanChildren.end(); ) - { - if (iter->mParentInfo == parent_info) - { - iter = mOrphanChildren.erase(iter); - mNumOrphans--; - } - else - { - ++iter; - } - } - - if (orphans_found && objectp->isSelected()) - { - LLSelectNode* nodep = LLSelectMgr::getInstance()->getSelection()->findNode(objectp); - if (nodep && !nodep->mIndividualSelection) - { - // rebuild selection with orphans - LLSelectMgr::getInstance()->deselectObjectAndFamily(objectp); - LLSelectMgr::getInstance()->selectObjectAndFamily(objectp); - } - } -} - -//////////////////////////////////////////////////////////////////////////// - -LLViewerObjectList::OrphanInfo::OrphanInfo() - : mParentInfo(0) -{ -} - -LLViewerObjectList::OrphanInfo::OrphanInfo(const U64 parent_info, const LLUUID child_info) - : mParentInfo(parent_info), mChildInfo(child_info) -{ -} - -bool LLViewerObjectList::OrphanInfo::operator==(const OrphanInfo &rhs) const -{ - return (mParentInfo == rhs.mParentInfo) && (mChildInfo == rhs.mChildInfo); -} - -bool LLViewerObjectList::OrphanInfo::operator!=(const OrphanInfo &rhs) const -{ - return !operator==(rhs); -} - - -LLDebugBeacon::~LLDebugBeacon() -{ - if (mHUDObject.notNull()) - { - mHUDObject->markDead(); - } -} +/** + * @file llviewerobjectlist.cpp + * @brief Implementation of LLViewerObjectList class. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llviewerobjectlist.h" + +#include "message.h" +#include "llfasttimer.h" +#include "llrender.h" +#include "llwindow.h" // decBusyCount() + +#include "llviewercontrol.h" +#include "llface.h" +#include "llvoavatar.h" +#include "llviewerobject.h" +#include "llviewerwindow.h" +#include "llnetmap.h" +#include "llagent.h" +#include "llagentcamera.h" +#include "pipeline.h" +#include "llspatialpartition.h" +#include "lltooltip.h" +#include "llworld.h" +#include "llstring.h" +#include "llhudicon.h" +#include "llhudnametag.h" +#include "lldrawable.h" +#include "llflexibleobject.h" +#include "llviewertextureanim.h" +#include "xform.h" +#include "llsky.h" +#include "llviewercamera.h" +#include "llselectmgr.h" +#include "llresmgr.h" +#include "llsdutil.h" +#include "llviewerregion.h" +#include "llviewerstats.h" +#include "llviewerstatsrecorder.h" +#include "llvovolume.h" +#include "llvoavatarself.h" +#include "lltoolmgr.h" +#include "lltoolpie.h" +#include "llkeyboard.h" +#include "u64.h" +#include "llviewertexturelist.h" +#include "lldatapacker.h" +#include "llcallstack.h" +#ifdef LL_USESYSTEMLIBS +#include +#else +#include "zlib-ng/zlib.h" +#endif +#include "object_flags.h" + +#include "llappviewer.h" +#include "llfloaterperms.h" +#include "llvocache.h" +#include "llcorehttputil.h" +#include "llstartup.h" + +#include +#include + +extern F32 gMinObjectDistance; +extern bool gAnimateTextures; + +#define MAX_CONCURRENT_PHYSICS_REQUESTS 256 + +void dialog_refresh_all(); + +// Global lists of objects - should go away soon. +LLViewerObjectList gObjectList; + +extern LLPipeline gPipeline; + +// Statics for object lookup tables. +U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check. +std::map LLViewerObjectList::sIPAndPortToIndex; +std::map LLViewerObjectList::sIndexAndLocalIDToUUID; + +LLViewerObjectList::LLViewerObjectList() +{ + mCurLazyUpdateIndex = 0; + mCurBin = 0; + mNumDeadObjects = 0; + mNumOrphans = 0; + mNumNewObjects = 0; + mWasPaused = false; + mNumDeadObjectUpdates = 0; + mNumUnknownUpdates = 0; +} + +LLViewerObjectList::~LLViewerObjectList() +{ + destroy(); +} + +void LLViewerObjectList::destroy() +{ + killAllObjects(); + + resetObjectBeacons(); + mActiveObjects.clear(); + mDeadObjects.clear(); + mMapObjects.clear(); + mUUIDObjectMap.clear(); +} + + +void LLViewerObjectList::getUUIDFromLocal(LLUUID &id, + const U32 local_id, + const U32 ip, + const U32 port) +{ + U64 ipport = (((U64)ip) << 32) | (U64)port; + + U32 index = sIPAndPortToIndex[ipport]; + + if (!index) + { + index = sSimulatorMachineIndex++; + sIPAndPortToIndex[ipport] = index; + } + + U64 indexid = (((U64)index) << 32) | (U64)local_id; + + id = get_if_there(sIndexAndLocalIDToUUID, indexid, LLUUID::null); +} + +U64 LLViewerObjectList::getIndex(const U32 local_id, + const U32 ip, + const U32 port) +{ + U64 ipport = (((U64)ip) << 32) | (U64)port; + + U32 index = sIPAndPortToIndex[ipport]; + + if (!index) + { + return 0; + } + + return (((U64)index) << 32) | (U64)local_id; +} + +bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + + if(objectp && objectp->getRegion()) + { + U32 local_id = objectp->mLocalID; + U32 ip = objectp->getRegion()->getHost().getAddress(); + U32 port = objectp->getRegion()->getHost().getPort(); + U64 ipport = (((U64)ip) << 32) | (U64)port; + U32 index = sIPAndPortToIndex[ipport]; + + // LL_INFOS() << "Removing object from table, local ID " << local_id << ", ip " << ip << ":" << port << LL_ENDL; + + U64 indexid = (((U64)index) << 32) | (U64)local_id; + + std::map::iterator iter = sIndexAndLocalIDToUUID.find(indexid); + if (iter == sIndexAndLocalIDToUUID.end()) + { + return false; + } + + // Found existing entry + if (iter->second == objectp->getID()) + { // Full UUIDs match, so remove the entry + sIndexAndLocalIDToUUID.erase(iter); + return true; + } + // UUIDs did not match - this would zap a valid entry, so don't erase it + //LL_INFOS() << "Tried to erase entry where id in table (" + // << iter->second << ") did not match object " << object.getID() << LL_ENDL; + } + + return false ; +} + +void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, + const U32 local_id, + const U32 ip, + const U32 port) +{ + U64 ipport = (((U64)ip) << 32) | (U64)port; + + U32 index = sIPAndPortToIndex[ipport]; + + if (!index) + { + index = sSimulatorMachineIndex++; + sIPAndPortToIndex[ipport] = index; + } + + U64 indexid = (((U64)index) << 32) | (U64)local_id; + + sIndexAndLocalIDToUUID[indexid] = id; + + //LL_INFOS() << "Adding object to table, full ID " << id + // << ", local ID " << local_id << ", ip " << ip << ":" << port << LL_ENDL; +} + +S32 gFullObjectUpdates = 0; +S32 gTerseObjectUpdates = 0; + +void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, + void** user_data, + U32 i, + const EObjectUpdateType update_type, + LLDataPacker* dpp, + bool just_created, + bool from_cache) +{ + LLMessageSystem* msg = NULL; + + if(!from_cache) + { + msg = gMessageSystem; + } + + // ignore returned flags + LL_DEBUGS("ObjectUpdate") << "uuid " << objectp->mID << " calling processUpdateMessage " + << objectp << " just_created " << just_created << " from_cache " << from_cache << " msg " << msg << LL_ENDL; + dumpStack("ObjectUpdateStack"); + + objectp->processUpdateMessage(msg, user_data, i, update_type, dpp); + + if (objectp->isDead()) + { + // The update failed + return; + } + + updateActive(objectp); + + if (just_created) + { + gPipeline.addObject(objectp); + } + + // Also sets the approx. pixel area + objectp->setPixelAreaAndAngle(gAgent); + + // RN: this must be called after we have a drawable + // (from gPipeline.addObject) + // so that the drawable parent is set properly + if(msg != NULL) + { + findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); + } + else + { + LLViewerRegion* regionp = objectp->getRegion(); + if(regionp != NULL) + { + findOrphans(objectp, regionp->getHost().getAddress(), regionp->getHost().getPort()); + } + } + + // If we're just wandering around, don't create new objects selected. + if (just_created + && update_type != OUT_TERSE_IMPROVED + && objectp->mCreateSelected) + { + if ( LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() ) + { + // LL_INFOS() << "DEBUG selecting " << objectp->mID << " " + // << objectp->mLocalID << LL_ENDL; + LLSelectMgr::getInstance()->selectObjectAndFamily(objectp); + dialog_refresh_all(); + } + + objectp->mCreateSelected = false; + gViewerWindow->getWindow()->decBusyCount(); + gViewerWindow->setCursor( UI_CURSOR_ARROW ); + } +} + +static LLTrace::BlockTimerStatHandle FTM_PROCESS_OBJECTS("Process Objects"); + +LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* entry, LLViewerRegion* regionp) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + + LLDataPacker *cached_dpp = entry->getDP(); + + if (!cached_dpp || gNonInteractive) + { + return NULL; //nothing cached. + } + + LLViewerObject *objectp; + U32 local_id; + LLPCode pcode = 0; + LLUUID fullid; + LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); + + // Cache Hit. + record(LLStatViewer::OBJECT_CACHE_HIT_RATE, LLUnits::Ratio::fromValue(1)); + + cached_dpp->reset(); + cached_dpp->unpackUUID(fullid, "ID"); + cached_dpp->unpackU32(local_id, "LocalID"); + cached_dpp->unpackU8(pcode, "PCode"); + + objectp = findObject(fullid); + + if (objectp) + { + if(!objectp->isDead() && (objectp->mLocalID != entry->getLocalID() || + objectp->getRegion() != regionp)) + { + removeFromLocalIDTable(objectp); + setUUIDAndLocal(fullid, entry->getLocalID(), + regionp->getHost().getAddress(), + regionp->getHost().getPort()); + + if (objectp->mLocalID != entry->getLocalID()) + { // Update local ID in object with the one sent from the region + objectp->mLocalID = entry->getLocalID(); + } + + if (objectp->getRegion() != regionp) + { // Object changed region, so update it + objectp->updateRegion(regionp); // for LLVOAvatar + } + } + else + { + //should fall through if already loaded because may need to update the object. + //return objectp; //already loaded. + } + } + + bool justCreated = false; + if (!objectp) + { + objectp = createObjectFromCache(pcode, regionp, fullid, entry->getLocalID()); + + LL_DEBUGS("ObjectUpdate") << "uuid " << fullid << " created objectp " << objectp << LL_ENDL; + dumpStack("ObjectUpdateStack"); + + if (!objectp) + { + LL_INFOS() << "createObject failure for object: " << fullid << LL_ENDL; + recorder.objectUpdateFailure(); + return NULL; + } + justCreated = true; + mNumNewObjects++; + } + + if (objectp->isDead()) + { + LL_WARNS() << "Dead object " << objectp->mID << " in UUID map 1!" << LL_ENDL; + } + + processUpdateCore(objectp, NULL, 0, OUT_FULL_CACHED, cached_dpp, justCreated, true); + objectp->loadFlags(entry->getUpdateFlags()); //just in case, reload update flags from cache. + + if(entry->getHitCount() > 0) + { + objectp->setLastUpdateType(OUT_FULL_CACHED); + } + else + { + objectp->setLastUpdateType(OUT_FULL_COMPRESSED); //newly cached + objectp->setLastUpdateCached(true); + } + LLVOAvatar::cullAvatarsByPixelArea(); + + return objectp; +} + +void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, + void **user_data, + const EObjectUpdateType update_type, + bool compressed) +{ + LL_RECORD_BLOCK_TIME(FTM_PROCESS_OBJECTS); + + LLViewerObject *objectp; + S32 num_objects; + U32 local_id; + LLPCode pcode = 0; + LLUUID fullid; + S32 i; + + // figure out which simulator these are from and get it's index + // Coordinates in simulators are region-local + // Until we get region-locality working on viewer we + // have to transform to absolute coordinates. + num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); + + // I don't think this case is ever hit. TODO* Test this. + if (!compressed && update_type != OUT_FULL) + { + //LL_INFOS() << "TEST: !cached && !compressed && update_type != OUT_FULL" << LL_ENDL; + gTerseObjectUpdates += num_objects; + /* + S32 size; + if (mesgsys->getReceiveCompressedSize()) + { + size = mesgsys->getReceiveCompressedSize(); + } + else + { + size = mesgsys->getReceiveSize(); + } + LL_INFOS() << "Received terse " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << LL_ENDL; + */ + } + else + { + /* + S32 size; + if (mesgsys->getReceiveCompressedSize()) + { + size = mesgsys->getReceiveCompressedSize(); + } + else + { + size = mesgsys->getReceiveSize(); + } + + LL_INFOS() << "Received " << num_objects << " in " << size << " byte (" << size/num_objects << ")" << LL_ENDL; + */ + gFullObjectUpdates += num_objects; + } + + U64 region_handle; + mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); + + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); + + if (!regionp) + { + LL_WARNS() << "Object update from unknown region! " << region_handle << LL_ENDL; + return; + } + + U8 compressed_dpbuffer[2048]; + LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048); + LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); + + for (i = 0; i < num_objects; i++) + { + bool justCreated = false; + bool update_cache = false; //update object cache if it is a full-update or terse update + + if (compressed) + { + compressed_dp.reset(); + + S32 uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); + LL_DEBUGS("ObjectUpdate") << "got binary data from message to compressed_dpbuffer" << LL_ENDL; + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i, 2048); + compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); + + if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? + { + U32 flags = 0; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); + + compressed_dp.unpackUUID(fullid, "ID"); + compressed_dp.unpackU32(local_id, "LocalID"); + compressed_dp.unpackU8(pcode, "PCode"); + + if (pcode == 0) + { + // object creation will fail, LLViewerObject::createObject() + LL_WARNS() << "Received object " << fullid + << " with 0 PCode. Local id: " << local_id + << " Flags: " << flags + << " Region: " << regionp->getName() + << " Region id: " << regionp->getRegionID() << LL_ENDL; + recorder.objectUpdateFailure(); + continue; + } + else if ((flags & FLAGS_TEMPORARY_ON_REZ) == 0) + { + //send to object cache + regionp->cacheFullUpdate(compressed_dp, flags); + continue; + } + } + else //OUT_TERSE_IMPROVED + { + update_cache = true; + compressed_dp.unpackU32(local_id, "LocalID"); + getUUIDFromLocal(fullid, + local_id, + gMessageSystem->getSenderIP(), + gMessageSystem->getSenderPort()); + if (fullid.isNull()) + { + LL_DEBUGS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << ":" << gMessageSystem->getSenderPort() << LL_ENDL; + mNumUnknownUpdates++; + } + } + } + else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only? + { + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); + + getUUIDFromLocal(fullid, + local_id, + gMessageSystem->getSenderIP(), + gMessageSystem->getSenderPort()); + if (fullid.isNull()) + { + // LL_WARNS() << "update for unknown localid " << local_id << " host " << gMessageSystem->getSender() << LL_ENDL; + mNumUnknownUpdates++; + } + else + { + LL_DEBUGS("ObjectUpdate") << "Non-full, non-compressed update, obj " << local_id << ", global ID " << fullid << " from " << mesgsys->getSender() << LL_ENDL; + } + } + else // OUT_FULL only? + { + update_cache = true; + mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); + LL_DEBUGS("ObjectUpdate") << "Full Update, obj " << local_id << ", global ID " << fullid << " from " << mesgsys->getSender() << LL_ENDL; + } + objectp = findObject(fullid); + + if (compressed) + { + LL_DEBUGS("ObjectUpdate") << "uuid " << fullid << " received compressed data from message (earlier in function)" << LL_ENDL; + } + LL_DEBUGS("ObjectUpdate") << "uuid " << fullid << " objectp " << objectp + << " update_cache " << (S32) update_cache << " compressed " << compressed + << " update_type " << update_type << LL_ENDL; + dumpStack("ObjectUpdateStack"); + + if(update_cache) + { + //update object cache if the object receives a full-update or terse update + objectp = regionp->updateCacheEntry(local_id, objectp); + } + + // This looks like it will break if the local_id of the object doesn't change + // upon boundary crossing, but we check for region id matching later... + // Reset object local id and region pointer if things have changed + if (objectp && + ((objectp->mLocalID != local_id) || + (objectp->getRegion() != regionp))) + { + //if (objectp->getRegion()) + //{ + // LL_INFOS() << "Local ID change: Removing object from table, local ID " << objectp->mLocalID + // << ", id from message " << local_id << ", from " + // << LLHost(objectp->getRegion()->getHost().getAddress(), objectp->getRegion()->getHost().getPort()) + // << ", full id " << fullid + // << ", objects id " << objectp->getID() + // << ", regionp " << (U32) regionp << ", object region " << (U32) objectp->getRegion() + // << LL_ENDL; + //} + removeFromLocalIDTable(objectp); + setUUIDAndLocal(fullid, + local_id, + gMessageSystem->getSenderIP(), + gMessageSystem->getSenderPort()); + + if (objectp->mLocalID != local_id) + { // Update local ID in object with the one sent from the region + objectp->mLocalID = local_id; + } + + if (objectp->getRegion() != regionp) + { // Object changed region, so update it + objectp->updateRegion(regionp); // for LLVOAvatar + } + } + + if (!objectp) + { + if (compressed) + { + if (update_type == OUT_TERSE_IMPROVED) + { + // LL_INFOS() << "terse update for an unknown object (compressed):" << fullid << LL_ENDL; + recorder.objectUpdateFailure(); + continue; + } + } + else + { + if (update_type != OUT_FULL) + { + //LL_INFOS() << "terse update for an unknown object:" << fullid << LL_ENDL; + recorder.objectUpdateFailure(); + continue; + } + + mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i); + + } +#ifdef IGNORE_DEAD + if (mDeadObjects.find(fullid) != mDeadObjects.end()) + { + mNumDeadObjectUpdates++; + //LL_INFOS() << "update for a dead object:" << fullid << LL_ENDL; + recorder.objectUpdateFailure(); + continue; + } +#endif + + objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender()); + + LL_DEBUGS("ObjectUpdate") << "creating object " << fullid << " result " << objectp << LL_ENDL; + dumpStack("ObjectUpdateStack"); + + if (!objectp) + { + LL_INFOS() << "createObject failure for object: " << fullid << LL_ENDL; + recorder.objectUpdateFailure(); + continue; + } + + justCreated = true; + mNumNewObjects++; + } + + if (objectp->isDead()) + { + LL_WARNS() << "Dead object " << objectp->mID << " in UUID map 1!" << LL_ENDL; + } + + //bool bCached = false; + if (compressed) + { + if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? + { + objectp->mLocalID = local_id; + } + processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); + +#if 0 + if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? + { + U32 flags = 0; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); + + if(!(flags & FLAGS_TEMPORARY_ON_REZ)) + { + bCached = true; + LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags); + recorder.cacheFullUpdate(result); + } + } +#endif + } + else + { + if (update_type == OUT_FULL) + { + objectp->mLocalID = local_id; + } + processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated); + } + recorder.objectUpdateEvent(update_type); + objectp->setLastUpdateType(update_type); + } + + LLVOAvatar::cullAvatarsByPixelArea(); +} + +void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem *mesgsys, + void **user_data, + const EObjectUpdateType update_type) +{ + processObjectUpdate(mesgsys, user_data, update_type, true); +} + +void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys, + void **user_data, + const EObjectUpdateType update_type) +{ + //processObjectUpdate(mesgsys, user_data, update_type, true, false); + + S32 num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); + gFullObjectUpdates += num_objects; + + U64 region_handle; + mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); + if (!regionp) + { + LL_WARNS() << "Object update from unknown region! " << region_handle << LL_ENDL; + return; + } + + LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); + + for (S32 i = 0; i < num_objects; i++) + { + U32 id; + U32 crc; + U32 flags; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); + + LL_DEBUGS("ObjectUpdate") << "got probe for id " << id << " crc " << crc << LL_ENDL; + dumpStack("ObjectUpdateStack"); + + // Lookup data packer and add this id to cache miss lists if necessary. + U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; + if (regionp->probeCache(id, crc, flags, cache_miss_type)) + { // Cache Hit + recorder.cacheHitEvent(); + } + else + { // Cache Miss + LL_DEBUGS("ObjectUpdate") << "cache miss for id " << id << " crc " << crc << " miss type " << (S32) cache_miss_type << LL_ENDL; + recorder.cacheMissEvent(cache_miss_type); + } + } + + return; +} + +void LLViewerObjectList::dirtyAllObjectInventory() +{ + for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) + { + (*iter)->dirtyInventory(); + } +} + +void LLViewerObjectList::updateApparentAngles(LLAgent &agent) +{ + S32 i; + LLViewerObject *objectp; + + S32 num_updates, max_value; + if (NUM_BINS - 1 == mCurBin) + { + // Remainder (mObjects.size() could have changed) + num_updates = (S32) mObjects.size() - mCurLazyUpdateIndex; + max_value = (S32) mObjects.size(); + } + else + { + num_updates = ((S32) mObjects.size() / NUM_BINS) + 1; + max_value = llmin((S32) mObjects.size(), mCurLazyUpdateIndex + num_updates); + } + + // Iterate through some of the objects and lazy update their texture priorities + for (i = mCurLazyUpdateIndex; i < max_value; i++) + { + objectp = mObjects[i]; + if (!objectp->isDead()) + { + // Update distance & gpw + objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area + objectp->updateTextures(); // Update the image levels of textures for this object. + } + } + + mCurLazyUpdateIndex = max_value; + if (mCurLazyUpdateIndex == mObjects.size()) + { + // restart + mCurLazyUpdateIndex = 0; + mCurBin = 0; // keep in sync with index (mObjects.size() could have changed) + } + else + { + mCurBin = (mCurBin + 1) % NUM_BINS; + } + +#if 0 + // Slam priorities for textures that we care about (hovered, selected, and focused) + // Hovered + // Assumes only one level deep of parenting + LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); + if (nodep) + { + objectp = nodep->getObject(); + if (objectp) + { + objectp->boostTexturePriority(); + } + } + + // Focused + objectp = gAgentCamera.getFocusObject(); + if (objectp) + { + objectp->boostTexturePriority(); + } +#endif + + // Selected + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* objectp) + { + if (objectp) + { + objectp->boostTexturePriority(); + } + return true; + } + } func; + LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func); + + LLVOAvatar::cullAvatarsByPixelArea(); +} + +void LLViewerObjectList::update(LLAgent &agent) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + + // Update globals + LLViewerObject::setVelocityInterpolate( gSavedSettings.getBOOL("VelocityInterpolate") ); + LLViewerObject::setPingInterpolate( gSavedSettings.getBOOL("PingInterpolate") ); + + F32 interp_time = gSavedSettings.getF32("InterpolationTime"); + F32 phase_out_time = gSavedSettings.getF32("InterpolationPhaseOut"); + F32 region_interp_time = llclamp(gSavedSettings.getF32("RegionCrossingInterpolationTime"), 0.5f, 5.f); + if (interp_time < 0.0 || + phase_out_time < 0.0 || + phase_out_time > interp_time) + { + LL_WARNS() << "Invalid values for InterpolationTime or InterpolationPhaseOut, resetting to defaults" << LL_ENDL; + interp_time = 3.0f; + phase_out_time = 1.0f; + } + LLViewerObject::setPhaseOutUpdateInterpolationTime( interp_time ); + LLViewerObject::setMaxUpdateInterpolationTime( phase_out_time ); + LLViewerObject::setMaxRegionCrossingInterpolationTime(region_interp_time); + + gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures"); + + // update global timer + F32 last_time = gFrameTimeSeconds; + U64Microseconds time = totalTime(); // this will become the new gFrameTime when the update is done + // Time _can_ go backwards, for example if the user changes the system clock. + // It doesn't cause any fatal problems (just some oddness with stats), so we shouldn't assert here. +// llassert(time > gFrameTime); + F64Seconds time_diff = time - gFrameTime; + gFrameTime = time; + F64Seconds time_since_start = gFrameTime - gStartTime; + gFrameTimeSeconds = time_since_start; + + gFrameIntervalSeconds = gFrameTimeSeconds - last_time; + if (gFrameIntervalSeconds < 0.f) + { + gFrameIntervalSeconds = 0.f; + } + + //clear avatar LOD change counter + LLVOAvatar::sNumLODChangesThisFrame = 0; + + const F64 frame_time = LLFrameTimer::getElapsedSeconds(); + + LLViewerObject *objectp = NULL; + + // Make a copy of the list in case something in idleUpdate() messes with it + static std::vector idle_list; + + U32 idle_count = 0; + + { + for (std::vector >::iterator active_iter = mActiveObjects.begin(); + active_iter != mActiveObjects.end(); active_iter++) + { + objectp = *active_iter; + if (objectp) + { + if (idle_count >= idle_list.size()) + { + idle_list.push_back( objectp ); + } + else + { + idle_list[idle_count] = objectp; + } + ++idle_count; + } + else + { // There shouldn't be any NULL pointers in the list, but they have caused + // crashes before. This may be idleUpdate() messing with the list. + LL_WARNS() << "LLViewerObjectList::update has a NULL objectp" << LL_ENDL; + } + } + } + + std::vector::iterator idle_end = idle_list.begin()+idle_count; + + if (gSavedSettings.getBOOL("FreezeTime")) + { + + for (std::vector::iterator iter = idle_list.begin(); + iter != idle_end; iter++) + { + objectp = *iter; + if (objectp->isAvatar()) + { + objectp->idleUpdate(agent, frame_time); + } + } + } + else + { + for (std::vector::iterator idle_iter = idle_list.begin(); + idle_iter != idle_end; idle_iter++) + { + objectp = *idle_iter; + llassert(objectp->isActive()); + objectp->idleUpdate(agent, frame_time); + } + + //update flexible objects + LLVolumeImplFlexible::updateClass(); + + //update animated textures + if (gAnimateTextures) + { + LLViewerTextureAnim::updateClass(); + } + } + + + + fetchObjectCosts(); + fetchPhysicsFlags(); + + // update max computed render cost + LLVOVolume::updateRenderComplexity(); + + // compute all sorts of time-based stats + // don't factor frames that were paused into the stats + if (! mWasPaused) + { + LLViewerStats::getInstance()->updateFrameStats(time_diff); + } + + /* + // Debugging code for viewing orphans, and orphaned parents + LLUUID id; + for (i = 0; i < mOrphanParents.size(); i++) + { + id = sIndexAndLocalIDToUUID[mOrphanParents[i]]; + LLViewerObject *objectp = findObject(id); + if (objectp) + { + std::string id_str; + objectp->mID.toString(id_str); + std::string tmpstr = std::string("Par: ") + id_str; + addDebugBeacon(objectp->getPositionAgent(), + tmpstr, + LLColor4(1.f,0.f,0.f,1.f), + LLColor4(1.f,1.f,1.f,1.f)); + } + } + + LLColor4 text_color; + for (i = 0; i < mOrphanChildren.size(); i++) + { + OrphanInfo oi = mOrphanChildren[i]; + LLViewerObject *objectp = findObject(oi.mChildInfo); + if (objectp) + { + std::string id_str; + objectp->mID.toString(id_str); + std::string tmpstr; + if (objectp->getParent()) + { + tmpstr = std::string("ChP: ") + id_str; + text_color = LLColor4(0.f, 1.f, 0.f, 1.f); + } + else + { + tmpstr = std::string("ChNoP: ") + id_str; + text_color = LLColor4(1.f, 0.f, 0.f, 1.f); + } + id = sIndexAndLocalIDToUUID[oi.mParentInfo]; + addDebugBeacon(objectp->getPositionAgent() + LLVector3(0.f, 0.f, -0.25f), + tmpstr, + LLColor4(0.25f,0.25f,0.25f,1.f), + text_color); + } + i++; + } + */ + + sample(LLStatViewer::NUM_OBJECTS, mObjects.size()); + sample(LLStatViewer::NUM_ACTIVE_OBJECTS, idle_count); +} + +void LLViewerObjectList::fetchObjectCosts() +{ + // issue http request for stale object physics costs + if (!mStaleObjectCost.empty()) + { + LLViewerRegion* regionp = gAgent.getRegion(); + + if (regionp) + { + std::string url = regionp->getCapability("GetObjectCost"); + + if (!url.empty()) + { + LLCoros::instance().launch("LLViewerObjectList::fetchObjectCostsCoro", + boost::bind(&LLViewerObjectList::fetchObjectCostsCoro, this, url)); + } + else + { + mStaleObjectCost.clear(); + mPendingObjectCost.clear(); + } + } + } +} + +/*static*/ +void LLViewerObjectList::reportObjectCostFailure(LLSD &objectList) +{ + // TODO*: No more hard coding + for (LLSD::array_iterator it = objectList.beginArray(); it != objectList.endArray(); ++it) + { + gObjectList.onObjectCostFetchFailure(it->asUUID()); + } +} + + +void LLViewerObjectList::fetchObjectCostsCoro(std::string url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + + + uuid_set_t diff; + + std::set_difference(mStaleObjectCost.begin(), mStaleObjectCost.end(), + mPendingObjectCost.begin(), mPendingObjectCost.end(), + std::inserter(diff, diff.begin())); + + mStaleObjectCost.clear(); + + if (diff.empty()) + { + LL_INFOS() << "No outstanding object IDs to request. Pending count: " << mPendingObjectCost.size() << LL_ENDL; + return; + } + + LLSD idList(LLSD::emptyArray()); + + for (uuid_set_t::iterator it = diff.begin(); it != diff.end(); ++it) + { + idList.append(*it); + } + + mPendingObjectCost.insert(diff.begin(), diff.end()); + + LLSD postData = LLSD::emptyMap(); + + postData["object_ids"] = idList; + + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status || result.has("error")) + { + if (result.has("error")) + { + LL_WARNS() << "Application level error when fetching object " + << "cost. Message: " << result["error"]["message"].asString() + << ", identifier: " << result["error"]["identifier"].asString() + << LL_ENDL; + + // TODO*: Adaptively adjust request size if the + // service says we've requested too many and retry + } + reportObjectCostFailure(idList); + + return; + } + + // Success, grab the resource cost and linked set costs + // for an object if one was returned + for (LLSD::array_iterator it = idList.beginArray(); it != idList.endArray(); ++it) + { + LLUUID objectId = it->asUUID(); + + // Object could have been added to the mStaleObjectCost after request started + mStaleObjectCost.erase(objectId); + mPendingObjectCost.erase(objectId); + + // Check to see if the request contains data for the object + if (result.has(it->asString())) + { + LLSD objectData = result[it->asString()]; + + F32 linkCost = objectData["linked_set_resource_cost"].asReal(); + F32 objectCost = objectData["resource_cost"].asReal(); + F32 physicsCost = objectData["physics_cost"].asReal(); + F32 linkPhysicsCost = objectData["linked_set_physics_cost"].asReal(); + + gObjectList.updateObjectCost(objectId, objectCost, linkCost, physicsCost, linkPhysicsCost); + } + else + { + // TODO*: Give user feedback about the missing data? + gObjectList.onObjectCostFetchFailure(objectId); + } + } + +} + +void LLViewerObjectList::fetchPhysicsFlags() +{ + // issue http request for stale object physics flags + if (!mStalePhysicsFlags.empty()) + { + LLViewerRegion* regionp = gAgent.getRegion(); + + if (regionp) + { + std::string url = regionp->getCapability("GetObjectPhysicsData"); + + if (!url.empty()) + { + LLCoros::instance().launch("LLViewerObjectList::fetchPhisicsFlagsCoro", + boost::bind(&LLViewerObjectList::fetchPhisicsFlagsCoro, this, url)); + } + else + { + mStalePhysicsFlags.clear(); + mPendingPhysicsFlags.clear(); + } + } + } +} + +/*static*/ +void LLViewerObjectList::reportPhysicsFlagFailure(LLSD &objectList) +{ + // TODO*: No more hard coding + for (LLSD::array_iterator it = objectList.beginArray(); it != objectList.endArray(); ++it) + { + gObjectList.onPhysicsFlagsFetchFailure(it->asUUID()); + } +} + +void LLViewerObjectList::fetchPhisicsFlagsCoro(std::string url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD idList; + U32 objectIndex = 0; + + for (uuid_set_t::iterator it = mStalePhysicsFlags.begin(); it != mStalePhysicsFlags.end();) + { + // Check to see if a request for this object + // has already been made. + if (mPendingPhysicsFlags.find(*it) == mPendingPhysicsFlags.end()) + { + mPendingPhysicsFlags.insert(*it); + idList[objectIndex++] = *it; + } + + mStalePhysicsFlags.erase(it++); + + if (objectIndex >= MAX_CONCURRENT_PHYSICS_REQUESTS) + { + break; + } + } + + if (idList.size() < 1) + { + LL_INFOS() << "No outstanding object physics flags to request." << LL_ENDL; + return; + } + + LLSD postData = LLSD::emptyMap(); + + postData["object_ids"] = idList; + + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status || result.has("error")) + { + if (result.has("error")) + { + LL_WARNS() << "Application level error when fetching object " + << "physics flags. Message: " << result["error"]["message"].asString() + << ", identifier: " << result["error"]["identifier"].asString() + << LL_ENDL; + + // TODO*: Adaptively adjust request size if the + // service says we've requested too many and retry + } + reportPhysicsFlagFailure(idList); + + return; + } + + // Success, grab the resource cost and linked set costs + // for an object if one was returned + for (LLSD::array_iterator it = idList.beginArray(); it != idList.endArray(); ++it) + { + LLUUID objectId = it->asUUID(); + + // Check to see if the request contains data for the object + if (result.has(it->asString())) + { + const LLSD& data = result[it->asString()]; + + S32 shapeType = data["PhysicsShapeType"].asInteger(); + + gObjectList.updatePhysicsShapeType(objectId, shapeType); + + if (data.has("Density")) + { + F32 density = data["Density"].asReal(); + F32 friction = data["Friction"].asReal(); + F32 restitution = data["Restitution"].asReal(); + F32 gravityMult = data["GravityMultiplier"].asReal(); + + gObjectList.updatePhysicsProperties(objectId, density, + friction, restitution, gravityMult); + } + } + else + { + // TODO*: Give user feedback about the missing data? + gObjectList.onPhysicsFlagsFetchFailure(objectId); + } + } +} + +void LLViewerObjectList::clearDebugText() +{ + for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) + { + (*iter)->restoreHudText(); + } +} + + +void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + + bool new_dead_object = true; + if (mDeadObjects.find(objectp->mID) != mDeadObjects.end()) + { + LL_INFOS() << "Object " << objectp->mID << " already on dead list!" << LL_ENDL; + new_dead_object = false; + } + else + { + mDeadObjects.insert(objectp->mID); + } + + // Cleanup any references we have to this object + // Remove from object map so noone can look it up. + + LL_DEBUGS("ObjectUpdate") << " dereferencing id " << objectp->mID << LL_ENDL; + dumpStack("ObjectUpdateStack"); + + mUUIDObjectMap.erase(objectp->mID); + + //if (objectp->getRegion()) + //{ + // LL_INFOS() << "cleanupReferences removing object from table, local ID " << objectp->mLocalID << ", ip " + // << objectp->getRegion()->getHost().getAddress() << ":" + // << objectp->getRegion()->getHost().getPort() << LL_ENDL; + //} + + removeFromLocalIDTable(objectp); + + if (objectp->onActiveList()) + { + //LL_INFOS() << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << LL_ENDL; + objectp->setOnActiveList(false); + removeFromActiveList(objectp); + } + + if (objectp->isOnMap()) + { + removeFromMap(objectp); + } + + // Don't clean up mObject references, these will be cleaned up more efficiently later! + + if(new_dead_object) + { + mNumDeadObjects++; + } +} + +bool LLViewerObjectList::killObject(LLViewerObject *objectp) +{ + LL_PROFILE_ZONE_SCOPED; + // Don't ever kill gAgentAvatarp, just force it to the agent's region + // unless region is NULL which is assumed to mean you are logging out. + if ((objectp == gAgentAvatarp) && gAgent.getRegion()) + { + objectp->setRegion(gAgent.getRegion()); + return false; + } + + // When we're killing objects, all we do is mark them as dead. + // We clean up the dead objects later. + + if (objectp) + { + // We are going to cleanup a lot of smart pointers to this object, they might be last, + // and object being NULLed while inside it's own function won't be pretty + // so create a pointer to make sure object will stay alive untill markDead() finishes + LLPointer sp(objectp); + sp->markDead(); // does the right thing if object already dead + return true; + } + + return false; +} + +void LLViewerObjectList::killObjects(LLViewerRegion *regionp) +{ + LL_PROFILE_ZONE_SCOPED; + LLViewerObject *objectp; + + + for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) + { + objectp = *iter; + + if (objectp->mRegionp == regionp) + { + killObject(objectp); + } + } + + // Have to clean right away because the region is becoming invalid. + cleanDeadObjects(false); +} + +void LLViewerObjectList::killAllObjects() +{ + // Used only on global destruction. + LLViewerObject *objectp; + + for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) + { + objectp = *iter; + killObject(objectp); + // Object must be dead, or it's the LLVOAvatarSelf which never dies. + llassert((objectp == gAgentAvatarp) || objectp->isDead()); + } + + cleanDeadObjects(false); + + if(!mObjects.empty()) + { + LL_WARNS() << "LLViewerObjectList::killAllObjects still has entries in mObjects: " << mObjects.size() << LL_ENDL; + mObjects.clear(); + } + + if (!mActiveObjects.empty()) + { + LL_WARNS() << "Some objects still on active object list!" << LL_ENDL; + mActiveObjects.clear(); + } + + if (!mMapObjects.empty()) + { + LL_WARNS() << "Some objects still on map object list!" << LL_ENDL; + mMapObjects.clear(); + } +} + +void LLViewerObjectList::cleanDeadObjects(bool use_timer) +{ + if (!mNumDeadObjects) + { + // No dead objects, don't need to scan object list. + return; + } + + LL_PROFILE_ZONE_SCOPED; + + S32 num_removed = 0; + LLViewerObject *objectp; + + vobj_list_t::reverse_iterator target = mObjects.rbegin(); + + vobj_list_t::iterator iter = mObjects.begin(); + for ( ; iter != mObjects.end(); ) + { + // Scan for all of the dead objects and put them all on the end of the list with no ref count ops + objectp = *iter; + if (objectp == NULL) + { //we caught up to the dead tail + break; + } + + if (objectp->isDead()) + { + LLPointer::swap(*iter, *target); + *target = NULL; + ++target; + num_removed++; + + if (num_removed == mNumDeadObjects || iter->isNull()) + { + // We've cleaned up all of the dead objects or caught up to the dead tail + break; + } + } + else + { + ++iter; + } + } + + llassert(num_removed == mNumDeadObjects); + + //erase as a block + mObjects.erase(mObjects.begin()+(mObjects.size()-mNumDeadObjects), mObjects.end()); + + // We've cleaned the global object list, now let's do some paranoia testing on objects + // before blowing away the dead list. + mDeadObjects.clear(); + mNumDeadObjects = 0; +} + +void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) +{ + S32 idx = objectp->getListIndex(); + if (idx != -1) + { //remove by moving last element to this object's position + llassert(mActiveObjects[idx] == objectp); + + objectp->setListIndex(-1); + + S32 last_index = mActiveObjects.size()-1; + + if (idx != last_index) + { + mActiveObjects[idx] = mActiveObjects[last_index]; + mActiveObjects[idx]->setListIndex(idx); + } + + mActiveObjects.pop_back(); + } +} + +void LLViewerObjectList::updateActive(LLViewerObject *objectp) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; + + if (objectp->isDead()) + { + return; // We don't update dead objects! + } + + bool active = objectp->isActive(); + if (active != objectp->onActiveList()) + { + if (active) + { + //LL_INFOS() << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << LL_ENDL; + S32 idx = objectp->getListIndex(); + if (idx <= -1) + { + mActiveObjects.push_back(objectp); + objectp->setListIndex(mActiveObjects.size()-1); + objectp->setOnActiveList(true); + } + else + { + llassert(idx < mActiveObjects.size()); + llassert(mActiveObjects[idx] == objectp); + + if (idx >= mActiveObjects.size() || + mActiveObjects[idx] != objectp) + { + LL_WARNS() << "Invalid object list index detected!" << LL_ENDL; + } + } + } + else + { + //LL_INFOS() << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << LL_ENDL; + removeFromActiveList(objectp); + objectp->setOnActiveList(false); + } + } + + //post condition: if object is active, it must be on the active list + llassert(!active || std::find(mActiveObjects.begin(), mActiveObjects.end(), objectp) != mActiveObjects.end()); + + //post condition: if object is not active, it must not be on the active list + llassert(active || std::find(mActiveObjects.begin(), mActiveObjects.end(), objectp) == mActiveObjects.end()); +} + +void LLViewerObjectList::updateObjectCost(LLViewerObject* object) +{ + if (!object->isRoot()) + { //always fetch cost for the parent when fetching cost for children + mStaleObjectCost.insert(((LLViewerObject*)object->getParent())->getID()); + } + mStaleObjectCost.insert(object->getID()); +} + +void LLViewerObjectList::updateObjectCost(const LLUUID& object_id, F32 object_cost, F32 link_cost, F32 physics_cost, F32 link_physics_cost) +{ + LLViewerObject* object = findObject(object_id); + if (object) + { + object->setObjectCost(object_cost); + object->setLinksetCost(link_cost); + object->setPhysicsCost(physics_cost); + object->setLinksetPhysicsCost(link_physics_cost); + } +} + +void LLViewerObjectList::onObjectCostFetchFailure(const LLUUID& object_id) +{ + //LL_WARNS() << "Failed to fetch object cost for object: " << object_id << LL_ENDL; + mPendingObjectCost.erase(object_id); +} + +void LLViewerObjectList::updatePhysicsFlags(const LLViewerObject* object) +{ + mStalePhysicsFlags.insert(object->getID()); +} + +void LLViewerObjectList::updatePhysicsShapeType(const LLUUID& object_id, S32 type) +{ + mPendingPhysicsFlags.erase(object_id); + LLViewerObject* object = findObject(object_id); + if (object) + { + object->setPhysicsShapeType(type); + } +} + +void LLViewerObjectList::updatePhysicsProperties(const LLUUID& object_id, + F32 density, + F32 friction, + F32 restitution, + F32 gravity_multiplier) +{ + mPendingPhysicsFlags.erase(object_id); + + LLViewerObject* object = findObject(object_id); + if (object) + { + object->setPhysicsDensity(density); + object->setPhysicsFriction(friction); + object->setPhysicsGravity(gravity_multiplier); + object->setPhysicsRestitution(restitution); + } +} + +void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) +{ + //LL_WARNS() << "Failed to fetch physics flags for object: " << object_id << LL_ENDL; + mPendingPhysicsFlags.erase(object_id); +} + +void LLViewerObjectList::shiftObjects(const LLVector3 &offset) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + // This is called when we shift our origin when we cross region boundaries... + // We need to update many object caches, I'll document this more as I dig through the code + // cleaning things out... + + if (0 == offset.magVecSquared()) + { + return; + } + + + LLViewerObject *objectp; + for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) + { + objectp = *iter; + // There could be dead objects on the object list, so don't update stuff if the object is dead. + if (!objectp->isDead()) + { + objectp->updatePositionCaches(); + + if (objectp->mDrawable.notNull() && !objectp->mDrawable->isDead()) + { + gPipeline.markShift(objectp->mDrawable); + } + } + } + + gPipeline.shiftObjects(offset); + + LLWorld::getInstance()->shiftRegions(offset); +} + +void LLViewerObjectList::repartitionObjects() +{ + for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + if (!objectp->isDead()) + { + LLDrawable* drawable = objectp->mDrawable; + if (drawable && !drawable->isDead()) + { + drawable->updateBinRadius(); + drawable->updateSpatialExtents(); + drawable->movePartition(); + } + } + } +} + +//debug code +bool LLViewerObjectList::hasMapObjectInRegion(LLViewerRegion* regionp) +{ + for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + + if(objectp->isDead() || objectp->getRegion() == regionp) + { + return true ; + } + } + + return false ; +} + +//make sure the region is cleaned up. +void LLViewerObjectList::clearAllMapObjectsInRegion(LLViewerRegion* regionp) +{ + std::set dead_object_list ; + std::set region_object_list ; + for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + + if(objectp->isDead()) + { + dead_object_list.insert(objectp) ; + } + else if(objectp->getRegion() == regionp) + { + region_object_list.insert(objectp) ; + } + } + + if(dead_object_list.size() > 0) + { + LL_WARNS() << "There are " << dead_object_list.size() << " dead objects on the map!" << LL_ENDL ; + + for(std::set::iterator iter = dead_object_list.begin(); iter != dead_object_list.end(); ++iter) + { + cleanupReferences(*iter) ; + } + } + if(region_object_list.size() > 0) + { + LL_WARNS() << "There are " << region_object_list.size() << " objects not removed from the deleted region!" << LL_ENDL ; + + for(std::set::iterator iter = region_object_list.begin(); iter != region_object_list.end(); ++iter) + { + (*iter)->markDead() ; + } + } +} + + +void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap) +{ + LLColor4 above_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnAboveWater" ); + LLColor4 below_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnBelowWater" ); + LLColor4 you_own_above_water_color = + LLUIColorTable::instance().getColor( "NetMapYouOwnAboveWater" ); + LLColor4 you_own_below_water_color = + LLUIColorTable::instance().getColor( "NetMapYouOwnBelowWater" ); + LLColor4 group_own_above_water_color = + LLUIColorTable::instance().getColor( "NetMapGroupOwnAboveWater" ); + LLColor4 group_own_below_water_color = + LLUIColorTable::instance().getColor( "NetMapGroupOwnBelowWater" ); + + F32 max_radius = gSavedSettings.getF32("MiniMapPrimMaxRadius"); + + for (vobj_list_t::iterator iter = mMapObjects.begin(); iter != mMapObjects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + + if(objectp->isDead())//some dead objects somehow not cleaned. + { + continue ; + } + + if (!objectp->getRegion() || objectp->isOrphaned() || objectp->isAttachment()) + { + continue; + } + const LLVector3& scale = objectp->getScale(); + const LLVector3d pos = objectp->getPositionGlobal(); + const F64 water_height = F64( objectp->getRegion()->getWaterHeight() ); + // LLWorld::getInstance()->getWaterHeight(); + + F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.5f * 0.5f * 1.3f; // 1.3 is a fudge + + // Limit the size of megaprims so they don't blot out everything on the minimap. + // Attempting to draw very large megaprims also causes client lag. + // See DEV-17370 and DEV-29869/SNOW-79 for details. + approx_radius = llmin(approx_radius, max_radius); + + LLColor4U color = above_water_color; + if( objectp->permYouOwner() ) + { + const F32 MIN_RADIUS_FOR_OWNED_OBJECTS = 2.f; + if( approx_radius < MIN_RADIUS_FOR_OWNED_OBJECTS ) + { + approx_radius = MIN_RADIUS_FOR_OWNED_OBJECTS; + } + + if( pos.mdV[VZ] >= water_height ) + { + if ( objectp->permGroupOwner() ) + { + color = group_own_above_water_color; + } + else + { + color = you_own_above_water_color; + } + } + else + { + if ( objectp->permGroupOwner() ) + { + color = group_own_below_water_color; + } + else + { + color = you_own_below_water_color; + } + } + } + else + if( pos.mdV[VZ] < water_height ) + { + color = below_water_color; + } + + netmap.renderScaledPointGlobal( + pos, + color, + approx_radius ); + } +} + +void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er) +{ +} + +extern bool gCubeSnapshot; + +void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent, + const std::string &string, + const LLColor4 &color, + const LLColor4 &text_color, + S32 line_width) +{ + llassert(!gCubeSnapshot); + LLDebugBeacon beacon; + beacon.mPositionAgent = pos_agent; + beacon.mString = string; + beacon.mColor = color; + beacon.mTextColor = text_color; + beacon.mLineWidth = line_width; + + mDebugBeacons.push_back(beacon); +} + +void LLViewerObjectList::resetObjectBeacons() +{ + mDebugBeacons.clear(); +} + +LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp, S32 flags) +{ + LLUUID fullid; + fullid.generate(); + + LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp, flags); + if (!objectp) + { +// LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << LL_ENDL; + return NULL; + } + + mUUIDObjectMap[fullid] = objectp; + + mObjects.push_back(objectp); + + updateActive(objectp); + + return objectp; +} + +LLViewerObject *LLViewerObjectList::createObjectFromCache(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id) +{ + llassert_always(uuid.notNull()); + + LL_DEBUGS("ObjectUpdate") << "creating " << uuid << " local_id " << local_id << LL_ENDL; + dumpStack("ObjectUpdateStack"); + + LLViewerObject *objectp = LLViewerObject::createObject(uuid, pcode, regionp); + if (!objectp) + { +// LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << LL_ENDL; + return NULL; + } + + objectp->mLocalID = local_id; + mUUIDObjectMap[uuid] = objectp; + setUUIDAndLocal(uuid, + local_id, + regionp->getHost().getAddress(), + regionp->getHost().getPort()); + mObjects.push_back(objectp); + + updateActive(objectp); + + return objectp; +} + +LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp, + const LLUUID &uuid, const U32 local_id, const LLHost &sender) +{ + LLUUID fullid; + if (uuid == LLUUID::null) + { + fullid.generate(); + } + else + { + fullid = uuid; + } + + LL_DEBUGS("ObjectUpdate") << "createObject creating " << fullid << LL_ENDL; + dumpStack("ObjectUpdateStack"); + + LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp); + if (!objectp) + { +// LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << LL_ENDL; + return NULL; + } + if(regionp) + { + regionp->addToCreatedList(local_id); + } + + mUUIDObjectMap[fullid] = objectp; + setUUIDAndLocal(fullid, + local_id, + gMessageSystem->getSenderIP(), + gMessageSystem->getSenderPort()); + + mObjects.push_back(objectp); + + updateActive(objectp); + + return objectp; +} + +LLViewerObject *LLViewerObjectList::replaceObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) +{ + LLViewerObject *old_instance = findObject(id); + if (old_instance) + { + //cleanupReferences(old_instance); + old_instance->markDead(); + + return createObject(pcode, regionp, id, old_instance->getLocalID(), LLHost()); + } + return NULL; +} + +S32 LLViewerObjectList::findReferences(LLDrawable *drawablep) const +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE; + + LLViewerObject *objectp; + S32 num_refs = 0; + + for (vobj_list_t::const_iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) + { + objectp = *iter; + if (objectp->mDrawable.notNull()) + { + num_refs += objectp->mDrawable->findReferences(drawablep); + } + } + return num_refs; +} + + +void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip, U32 port) +{ + LL_DEBUGS("ORPHANS") << "Orphaning object " << childp->getID() << " with parent " << parent_id << LL_ENDL; + + // We're an orphan, flag things appropriately. + childp->mOrphaned = true; + if (childp->mDrawable.notNull()) + { + bool make_invisible = true; + LLViewerObject *parentp = (LLViewerObject *)childp->getParent(); + if (parentp) + { + if (parentp->getRegion() != childp->getRegion()) + { + // This is probably an object flying across a region boundary, the + // object probably ISN'T being reparented, but just got an object + // update out of order (child update before parent). + make_invisible = false; + //LL_INFOS() << "Don't make object handoffs invisible!" << LL_ENDL; + } + } + + if (make_invisible) + { + // Make sure that this object becomes invisible if it's an orphan + childp->mDrawable->setState(LLDrawable::FORCE_INVISIBLE); + } + } + + // Unknown parent, add to orpaned child list + U64 parent_info = getIndex(parent_id, ip, port); + + if (std::find(mOrphanParents.begin(), mOrphanParents.end(), parent_info) == mOrphanParents.end()) + { + mOrphanParents.push_back(parent_info); + } + + LLViewerObjectList::OrphanInfo oi(parent_info, childp->mID); + if (std::find(mOrphanChildren.begin(), mOrphanChildren.end(), oi) == mOrphanChildren.end()) + { + mOrphanChildren.push_back(oi); + mNumOrphans++; + } +} + + +void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + + if (objectp->isDead()) + { + LL_WARNS() << "Trying to find orphans for dead obj " << objectp->mID + << ":" << objectp->getPCodeString() << LL_ENDL; + return; + } + + //search object cache to get orphans + if(objectp->getRegion()) + { + objectp->getRegion()->findOrphans(objectp->getLocalID()); + } + + // See if we are a parent of an orphan. + // Note: This code is fairly inefficient but it should happen very rarely. + // It can be sped up if this is somehow a performance issue... + if (mOrphanParents.empty()) + { + // no known orphan parents + return; + } + if (std::find(mOrphanParents.begin(), mOrphanParents.end(), getIndex(objectp->mLocalID, ip, port)) == mOrphanParents.end()) + { + // did not find objectp in OrphanParent list + return; + } + + U64 parent_info = getIndex(objectp->mLocalID, ip, port); + bool orphans_found = false; + // Iterate through the orphan list, and set parents of matching children. + + for (std::vector::iterator iter = mOrphanChildren.begin(); iter != mOrphanChildren.end(); ) + { + if (iter->mParentInfo != parent_info) + { + ++iter; + continue; + } + LLViewerObject *childp = findObject(iter->mChildInfo); + if (childp) + { + if (childp == objectp) + { + LL_WARNS() << objectp->mID << " has self as parent, skipping!" + << LL_ENDL; + ++iter; + continue; + } + + LL_DEBUGS("ORPHANS") << "Reunited parent " << objectp->mID + << " with child " << childp->mID << LL_ENDL; + LL_DEBUGS("ORPHANS") << "Glob: " << objectp->getPositionGlobal() << LL_ENDL; + LL_DEBUGS("ORPHANS") << "Agent: " << objectp->getPositionAgent() << LL_ENDL; +#ifdef ORPHAN_SPAM + addDebugBeacon(objectp->getPositionAgent(),""); +#endif + gPipeline.markMoved(objectp->mDrawable); + objectp->setChanged(LLXform::MOVED | LLXform::SILHOUETTE); + + // Flag the object as no longer orphaned + childp->mOrphaned = false; + if (childp->mDrawable.notNull()) + { + // Make the drawable visible again and set the drawable parent + childp->mDrawable->clearState(LLDrawable::FORCE_INVISIBLE); + childp->setDrawableParent(objectp->mDrawable); // LLViewerObjectList::findOrphans() + gPipeline.markRebuild( childp->mDrawable, LLDrawable::REBUILD_ALL); + } + + // Make certain particles, icon and HUD aren't hidden + childp->hideExtraDisplayItems( false ); + + objectp->addChild(childp); + orphans_found = true; + ++iter; + } + else + { + LL_INFOS() << "Missing orphan child, removing from list" << LL_ENDL; + + iter = mOrphanChildren.erase(iter); + } + } + + // Remove orphan parent and children from lists now that they've been found + { + std::vector::iterator iter = std::find(mOrphanParents.begin(), mOrphanParents.end(), parent_info); + if (iter != mOrphanParents.end()) + { + mOrphanParents.erase(iter); + } + } + + for (std::vector::iterator iter = mOrphanChildren.begin(); iter != mOrphanChildren.end(); ) + { + if (iter->mParentInfo == parent_info) + { + iter = mOrphanChildren.erase(iter); + mNumOrphans--; + } + else + { + ++iter; + } + } + + if (orphans_found && objectp->isSelected()) + { + LLSelectNode* nodep = LLSelectMgr::getInstance()->getSelection()->findNode(objectp); + if (nodep && !nodep->mIndividualSelection) + { + // rebuild selection with orphans + LLSelectMgr::getInstance()->deselectObjectAndFamily(objectp); + LLSelectMgr::getInstance()->selectObjectAndFamily(objectp); + } + } +} + +//////////////////////////////////////////////////////////////////////////// + +LLViewerObjectList::OrphanInfo::OrphanInfo() + : mParentInfo(0) +{ +} + +LLViewerObjectList::OrphanInfo::OrphanInfo(const U64 parent_info, const LLUUID child_info) + : mParentInfo(parent_info), mChildInfo(child_info) +{ +} + +bool LLViewerObjectList::OrphanInfo::operator==(const OrphanInfo &rhs) const +{ + return (mParentInfo == rhs.mParentInfo) && (mChildInfo == rhs.mChildInfo); +} + +bool LLViewerObjectList::OrphanInfo::operator!=(const OrphanInfo &rhs) const +{ + return !operator==(rhs); +} + + +LLDebugBeacon::~LLDebugBeacon() +{ + if (mHUDObject.notNull()) + { + mHUDObject->markDead(); + } +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/newview/llviewerobjectlist.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llviewerobjectlist.cpp') diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 2f8e71c5e9..08a1ba0f9b 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1480,7 +1480,7 @@ void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) objectp->setListIndex(-1); - S32 last_index = mActiveObjects.size()-1; + S32 last_index = static_cast(mActiveObjects.size()) - 1; if (idx != last_index) { @@ -1511,7 +1511,7 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) if (idx <= -1) { mActiveObjects.push_back(objectp); - objectp->setListIndex(mActiveObjects.size()-1); + objectp->setListIndex(static_cast(mActiveObjects.size()) - 1); objectp->setOnActiveList(true); } else -- cgit v1.2.3 From 9fdca96f8bd2211a99fe88e57b70cbecefa20b6d Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 8 Jul 2024 20:27:14 +0200 Subject: Re-enable compiler warnings C4244 and C4396 except for lltracerecording.h and llunittype.h for now --- indra/newview/llviewerobjectlist.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra/newview/llviewerobjectlist.cpp') diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 08a1ba0f9b..9e274e0566 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1129,10 +1129,10 @@ void LLViewerObjectList::fetchObjectCostsCoro(std::string url) { LLSD objectData = result[it->asString()]; - F32 linkCost = objectData["linked_set_resource_cost"].asReal(); - F32 objectCost = objectData["resource_cost"].asReal(); - F32 physicsCost = objectData["physics_cost"].asReal(); - F32 linkPhysicsCost = objectData["linked_set_physics_cost"].asReal(); + F32 linkCost = (F32)objectData["linked_set_resource_cost"].asReal(); + F32 objectCost = (F32)objectData["resource_cost"].asReal(); + F32 physicsCost = (F32)objectData["physics_cost"].asReal(); + F32 linkPhysicsCost = (F32)objectData["linked_set_physics_cost"].asReal(); gObjectList.updateObjectCost(objectId, objectCost, linkCost, physicsCost, linkPhysicsCost); } @@ -1257,10 +1257,10 @@ void LLViewerObjectList::fetchPhisicsFlagsCoro(std::string url) if (data.has("Density")) { - F32 density = data["Density"].asReal(); - F32 friction = data["Friction"].asReal(); - F32 restitution = data["Restitution"].asReal(); - F32 gravityMult = data["GravityMultiplier"].asReal(); + F32 density = (F32)data["Density"].asReal(); + F32 friction = (F32)data["Friction"].asReal(); + F32 restitution = (F32)data["Restitution"].asReal(); + F32 gravityMult = (F32)data["GravityMultiplier"].asReal(); gObjectList.updatePhysicsProperties(objectId, density, friction, restitution, gravityMult); -- cgit v1.2.3 From 7d2cd036ead5212f724aea706346e4dbe5386c09 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Sun, 21 Jul 2024 20:10:02 -0400 Subject: Fix rare shutdown crash in LLViewerObjectList --- indra/newview/llviewerobjectlist.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'indra/newview/llviewerobjectlist.cpp') diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 9e274e0566..cda8c99594 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -99,8 +99,6 @@ extern LLPipeline gPipeline; // Statics for object lookup tables. U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check. -std::map LLViewerObjectList::sIPAndPortToIndex; -std::map LLViewerObjectList::sIndexAndLocalIDToUUID; LLViewerObjectList::LLViewerObjectList() { @@ -138,17 +136,17 @@ void LLViewerObjectList::getUUIDFromLocal(LLUUID &id, { U64 ipport = (((U64)ip) << 32) | (U64)port; - U32 index = sIPAndPortToIndex[ipport]; + U32 index = mIPAndPortToIndex[ipport]; if (!index) { index = sSimulatorMachineIndex++; - sIPAndPortToIndex[ipport] = index; + mIPAndPortToIndex[ipport] = index; } U64 indexid = (((U64)index) << 32) | (U64)local_id; - id = get_if_there(sIndexAndLocalIDToUUID, indexid, LLUUID::null); + id = get_if_there(mIndexAndLocalIDToUUID, indexid, LLUUID::null); } U64 LLViewerObjectList::getIndex(const U32 local_id, @@ -157,7 +155,7 @@ U64 LLViewerObjectList::getIndex(const U32 local_id, { U64 ipport = (((U64)ip) << 32) | (U64)port; - U32 index = sIPAndPortToIndex[ipport]; + U32 index = mIPAndPortToIndex[ipport]; if (!index) { @@ -177,14 +175,14 @@ bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) U32 ip = objectp->getRegion()->getHost().getAddress(); U32 port = objectp->getRegion()->getHost().getPort(); U64 ipport = (((U64)ip) << 32) | (U64)port; - U32 index = sIPAndPortToIndex[ipport]; + U32 index = mIPAndPortToIndex[ipport]; // LL_INFOS() << "Removing object from table, local ID " << local_id << ", ip " << ip << ":" << port << LL_ENDL; U64 indexid = (((U64)index) << 32) | (U64)local_id; - std::map::iterator iter = sIndexAndLocalIDToUUID.find(indexid); - if (iter == sIndexAndLocalIDToUUID.end()) + std::map::iterator iter = mIndexAndLocalIDToUUID.find(indexid); + if (iter == mIndexAndLocalIDToUUID.end()) { return false; } @@ -192,7 +190,7 @@ bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) // Found existing entry if (iter->second == objectp->getID()) { // Full UUIDs match, so remove the entry - sIndexAndLocalIDToUUID.erase(iter); + mIndexAndLocalIDToUUID.erase(iter); return true; } // UUIDs did not match - this would zap a valid entry, so don't erase it @@ -210,17 +208,17 @@ void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, { U64 ipport = (((U64)ip) << 32) | (U64)port; - U32 index = sIPAndPortToIndex[ipport]; + U32 index = mIPAndPortToIndex[ipport]; if (!index) { index = sSimulatorMachineIndex++; - sIPAndPortToIndex[ipport] = index; + mIPAndPortToIndex[ipport] = index; } U64 indexid = (((U64)index) << 32) | (U64)local_id; - sIndexAndLocalIDToUUID[indexid] = id; + mIndexAndLocalIDToUUID[indexid] = id; //LL_INFOS() << "Adding object to table, full ID " << id // << ", local ID " << local_id << ", ip " << ip << ":" << port << LL_ENDL; -- cgit v1.2.3 From c4e921828a41c0e759ee103c6cfdb2cc40c1a581 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Sat, 3 Aug 2024 10:10:17 -0400 Subject: Optimization and cleanup of various color finds during draw --- indra/newview/llviewerobjectlist.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'indra/newview/llviewerobjectlist.cpp') diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index cda8c99594..ae64ee7b92 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1715,15 +1715,15 @@ void LLViewerObjectList::clearAllMapObjectsInRegion(LLViewerRegion* regionp) void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap) { - LLColor4 above_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnAboveWater" ); - LLColor4 below_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnBelowWater" ); - LLColor4 you_own_above_water_color = + static const LLUIColor above_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnAboveWater" ); + static const LLUIColor below_water_color = LLUIColorTable::instance().getColor( "NetMapOtherOwnBelowWater" ); + static const LLUIColor you_own_above_water_color = LLUIColorTable::instance().getColor( "NetMapYouOwnAboveWater" ); - LLColor4 you_own_below_water_color = + static const LLUIColor you_own_below_water_color = LLUIColorTable::instance().getColor( "NetMapYouOwnBelowWater" ); - LLColor4 group_own_above_water_color = + static const LLUIColor group_own_above_water_color = LLUIColorTable::instance().getColor( "NetMapGroupOwnAboveWater" ); - LLColor4 group_own_below_water_color = + static const LLUIColor group_own_below_water_color = LLUIColorTable::instance().getColor( "NetMapGroupOwnBelowWater" ); F32 max_radius = gSavedSettings.getF32("MiniMapPrimMaxRadius"); @@ -1753,7 +1753,7 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap) // See DEV-17370 and DEV-29869/SNOW-79 for details. approx_radius = llmin(approx_radius, max_radius); - LLColor4U color = above_water_color; + LLColor4U color = above_water_color.get(); if( objectp->permYouOwner() ) { const F32 MIN_RADIUS_FOR_OWNED_OBJECTS = 2.f; @@ -1766,29 +1766,29 @@ void LLViewerObjectList::renderObjectsForMap(LLNetMap &netmap) { if ( objectp->permGroupOwner() ) { - color = group_own_above_water_color; + color = group_own_above_water_color.get(); } else { - color = you_own_above_water_color; + color = you_own_above_water_color.get(); } } else { if ( objectp->permGroupOwner() ) { - color = group_own_below_water_color; + color = group_own_below_water_color.get(); } else { - color = you_own_below_water_color; + color = you_own_below_water_color.get(); } } } else if( pos.mdV[VZ] < water_height ) { - color = below_water_color; + color = below_water_color.get(); } netmap.renderScaledPointGlobal( -- cgit v1.2.3 From fe0f1be17bfd83323f2fcda124f3327cc14b0cad Mon Sep 17 00:00:00 2001 From: Beq Janus Date: Thu, 8 Aug 2024 17:10:03 +0100 Subject: Auto-scaling amortisation of dynamic BB calcs (#2226) * Auto-scaling amortisation of dynamic BB calcs This fix limits the overhead of the dynamic BB calcs to AvatarExtentRefreshMaxPerBatch per AvatarExtentRefreshPeriodBatch frames default is 5 avatar per 4 frames. Thus a standard busy region 25 avatars would take 20 frames to refresh the BBs. * Add comments to give context to the amortised BB recalcs explain the frequency of updates given the number of avatars present as to how that limits the impact on frame rate in busy scenes --- indra/newview/llviewerobjectlist.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/newview/llviewerobjectlist.cpp') diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index ae64ee7b92..435bd60917 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -889,6 +889,7 @@ void LLViewerObjectList::update(LLAgent &agent) static std::vector idle_list; U32 idle_count = 0; + mNumAvatars = 0; { for (std::vector >::iterator active_iter = mActiveObjects.begin(); @@ -906,6 +907,10 @@ void LLViewerObjectList::update(LLAgent &agent) idle_list[idle_count] = objectp; } ++idle_count; + if (objectp->isAvatar()) + { + mNumAvatars++; + } } else { // There shouldn't be any NULL pointers in the list, but they have caused -- cgit v1.2.3