123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484 |
- /**
- * @file llviewerobjectlist.cpp
- * @brief Implementation of LLViewerObjectList class.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include <iterator>
- #include <utility>
- #include "zlib.h"
- #include "llviewerobjectlist.h"
- #include "llcommonmath.h"
- #include "llcorehttputil.h"
- #include "lldatapacker.h"
- #include "llfasttimer.h"
- #include "llkeyboard.h"
- #include "lllocale.h"
- #include "llrenderutils.h"
- #include "llmessage.h"
- #include "object_flags.h"
- #include "llagent.h"
- #include "llappviewer.h"
- #include "lldrawable.h"
- #include "llface.h"
- #include "llflexibleobject.h"
- #include "llhoverview.h"
- #include "llhudtext.h"
- #include "hbobjectbackup.h"
- #include "llpanelminimap.h"
- #include "llpipeline.h"
- #include "llselectmgr.h"
- #include "llsky.h"
- #include "llspatialpartition.h"
- #include "lltoolmgr.h"
- #include "lltoolpie.h"
- #include "hbviewerautomation.h"
- #include "llviewercamera.h"
- #include "llviewercontrol.h"
- #include "llviewermessage.h" // For add_newly_created_object()
- #include "llviewerobject.h"
- #include "llviewerregion.h"
- #include "llviewerstats.h"
- #include "llviewertextureanim.h"
- #include "llviewerwindow.h"
- #include "llvoavatarself.h"
- #include "llvocache.h"
- #include "llworld.h"
- extern F32 gMinObjectDistance;
- #define LL_IGNORE_DEAD 0
- // Global lists of objects - should go away soon.
- LLViewerObjectList gObjectList;
- extern LLPipeline gPipeline;
- // Maximum number of objects per cost/physics flags request (500 is the limit
- // seen in SL as of 2016-06-14):
- S32 gMaxObjectsPerFetch = 500;
- LLViewerObjectList::LLViewerObjectList()
- : mWasPaused(false),
- mNumVisCulled(0),
- mNumSizeCulled(0),
- mCurLazyUpdateIndex(0),
- mCurBin(0),
- mNumOrphans(0),
- mNumNewObjects(0),
- mNumDeadObjectUpdates(0),
- mNumUnknownUpdates(0),
- mKilledAttachments(0),
- mKilledAttachmentsStamp(0),
- mSimulatorMachineIndex(1), // Not zero to speed up index check
- mIdleListSlots(32768)
- {
- mIdleList.reserve(mIdleListSlots);
- }
- void LLViewerObjectList::cleanupClass()
- {
- llinfos << "Destroying all the objects in the list..." << llendl;
- killAllObjects();
- mDebugBeacons.clear();
- mUUIDObjectMap.clear();
- mUUIDAvatarMap.clear();
- llinfos << "All objects destroyed." << llendl;
- }
- void LLViewerObjectList::getUUIDFromLocal(LLUUID& id, U32 local_id, U32 ip,
- U32 port)
- {
- U64 ipport = (((U64)ip) << 32) | (U64)port;
- U32 index;
- ip_to_idx_map_t::iterator it = mIPAndPortToIndex.find(ipport);
- if (it == mIPAndPortToIndex.end())
- {
- index = mSimulatorMachineIndex++;
- mIPAndPortToIndex[ipport] = index;
- }
- else
- {
- index = it->second;
- }
- U64 indexid = (((U64)index) << 32) | (U64)local_id;
- id = get_if_there(mIndexAndLocalIDToUUID, indexid, LLUUID::null);
- }
- U64 LLViewerObjectList::getIndex(U32 local_id, U32 ip, U32 port)
- {
- U64 ipport = (((U64)ip) << 32) | (U64)port;
- U32 index = mIPAndPortToIndex[ipport];
- return index ? (((U64)index) << 32) | (U64)local_id : 0;
- }
- bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp)
- {
- LL_TRACY_TIMER(TRC_OBJ_REMOVE_LOCAL_ID);
- if (objectp && objectp->getRegion())
- {
- U32 local_id = objectp->mLocalID;
- LLHost region_host = objectp->getRegion()->getHost();
- U32 ip = region_host.getAddress();
- U32 port = region_host.getPort();
- U64 ipport = (((U64)ip) << 32) | (U64)port;
- U32 index = mIPAndPortToIndex[ipport];
- U64 indexid = (((U64)index) << 32) | (U64)local_id;
- idx_to_uuid_map_t::iterator it = mIndexAndLocalIDToUUID.find(indexid);
- if (it == mIndexAndLocalIDToUUID.end())
- {
- return false;
- }
- // Found existing entry
- if (it->second == objectp->getID())
- {
- // Full UUIDs match, so remove the entry
- mIndexAndLocalIDToUUID.erase(it);
- return true;
- }
- // UUIDs did not match: this would zap a valid entry, so do not erase
- // it
- }
- return false;
- }
- void LLViewerObjectList::setUUIDAndLocal(const LLUUID& id, U32 local_id,
- U32 ip, U32 port)
- {
- U64 ipport = (((U64)ip) << 32) | (U64)port;
-
- U32 index = mIPAndPortToIndex[ipport];
- if (!index)
- {
- index = mSimulatorMachineIndex++;
- mIPAndPortToIndex[ipport] = index;
- }
- U64 indexid = (((U64)index) << 32) | (U64)local_id;
- mIndexAndLocalIDToUUID[indexid] = id;
- LL_DEBUGS("ObjectCacheSpam") << "Local Id " << local_id
- << " associated with UUID " << id << LL_ENDL;
- }
- // Because there is a bug in message_template.msg, which define the "Set" field
- // in the ObjectData block of the ObjectPermissions message as an U8 instead of
- // a bool (it does not change anything at the message level, but it causes the
- // viewers to issue warnings when they set "Set" as a bool, which it should be.
- #define MESSAGE_TEMPLATE_FIXED 0
- void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
- void** user_data, U32 i,
- EObjectUpdateType update_type,
- LLDataPacker* dpp,
- bool just_created, bool from_cache)
- {
- LL_TRACY_TIMER(TRC_PROCESS_OBJECTS_CORE);
- LLMessageSystem* msg = from_cache ? NULL : gMessageSystemp;
- // Ignore returned flags
- objectp->processUpdateMessage(msg, user_data, i, update_type, dpp);
- if (objectp->isDead())
- {
- // The update failed
- return;
- }
- updateActive(objectp);
- if (just_created)
- {
- gPipeline.addObject(objectp);
- }
- else
- {
- HBObjectBackup::primUpdate(objectp);
- }
- // Also sets the approx. pixel area
- objectp->setPixelAreaAndAngle();
- // RN: this must be called after we have a drawable (from
- // gPipeline.addObject) so that the drawable parent is set properly.
- if (msg)
- {
- findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
- }
- else
- {
- LLViewerRegion* regionp = objectp->getRegion();
- if (regionp)
- {
- findOrphans(objectp, regionp->getHost().getAddress(),
- regionp->getHost().getPort());
- }
- }
- // If we are just wandering around, do not create new objects selected.
- if (just_created && update_type != OUT_TERSE_IMPROVED &&
- objectp->mCreateSelected)
- {
- if (!gToolMgr.isCurrentTool(&gToolPie))
- {
- LL_DEBUGS("ViewerObject") << "Selecting " << objectp->mID
- << LL_ENDL;
- gSelectMgr.selectObjectAndFamily(objectp);
- dialog_refresh_all();
- }
- objectp->mCreateSelected = false;
- gWindowp->decBusyCount();
- gWindowp->setCursor(UI_CURSOR_ARROW);
- // Set the object permission to the user-selected default ones
- LLViewerRegion* region = objectp->getRegion();
- if (region) // Paranoia
- {
- #if MESSAGE_TEMPLATE_FIXED
- bool perm_modify = gSavedSettings.getBool("NextOwnerModify");
- bool perm_copy = gSavedSettings.getBool("NextOwnerCopy");
- bool perm_transfer = gSavedSettings.getBool("NextOwnerTransfer");
- bool perm_all_copy = gSavedSettings.getBool("EveryoneCopy");
- bool perm_group = gSavedSettings.getBool("ShareWithGroup");
- #else
- U8 perm_modify = (U8)gSavedSettings.getBool("NextOwnerModify");
- U8 perm_copy = (U8)gSavedSettings.getBool("NextOwnerCopy");
- U8 perm_transfer = (U8)gSavedSettings.getBool("NextOwnerTransfer");
- U8 perm_all_copy = (U8)gSavedSettings.getBool("EveryoneCopy");
- U8 perm_group = (U8)gSavedSettings.getBool("ShareWithGroup");
- #endif
- U32 local_id = objectp->getLocalID();
- LLMessageSystem* msg = gMessageSystemp;
- msg->newMessageFast(_PREHASH_ObjectPermissions);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
- msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
- msg->nextBlockFast(_PREHASH_HeaderData);
- msg->addBoolFast(_PREHASH_Override, false);
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_ObjectLocalID, local_id);
- msg->addU8Fast(_PREHASH_Field, PERM_NEXT_OWNER);
- #if MESSAGE_TEMPLATE_FIXED
- msg->addBoolFast(_PREHASH_Set, perm_modify);
- #else
- msg->addU8Fast(_PREHASH_Set, perm_modify);
- #endif
- msg->addU32Fast(_PREHASH_Mask, PERM_MODIFY);
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_ObjectLocalID, local_id);
- msg->addU8Fast(_PREHASH_Field, PERM_NEXT_OWNER);
- #if MESSAGE_TEMPLATE_FIXED
- msg->addBoolFast(_PREHASH_Set, perm_copy);
- #else
- msg->addU8Fast(_PREHASH_Set, perm_copy);
- #endif
- msg->addU32Fast(_PREHASH_Mask, PERM_COPY);
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_ObjectLocalID, local_id);
- msg->addU8Fast(_PREHASH_Field, PERM_NEXT_OWNER);
- #if MESSAGE_TEMPLATE_FIXED
- msg->addBoolFast(_PREHASH_Set, perm_transfer);
- #else
- msg->addU8Fast(_PREHASH_Set, perm_transfer);
- #endif
- msg->addU32Fast(_PREHASH_Mask, PERM_TRANSFER);
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_ObjectLocalID, local_id);
- msg->addU8Fast(_PREHASH_Field, PERM_EVERYONE);
- #if MESSAGE_TEMPLATE_FIXED
- msg->addBoolFast(_PREHASH_Set, perm_all_copy);
- #else
- msg->addU8Fast(_PREHASH_Set, perm_all_copy);
- #endif
- msg->addU32Fast(_PREHASH_Mask, PERM_COPY);
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_ObjectLocalID, local_id);
- msg->addU8Fast(_PREHASH_Field, PERM_GROUP);
- #if MESSAGE_TEMPLATE_FIXED
- msg->addBoolFast(_PREHASH_Set, perm_group);
- #else
- msg->addU8Fast(_PREHASH_Set, perm_group);
- #endif
- msg->addU32Fast(_PREHASH_Mask,
- PERM_MODIFY | PERM_MOVE | PERM_COPY);
- msg->sendReliable(objectp->getRegion()->getHost());
- }
- HBObjectBackup::newPrim(objectp);
- }
- }
- LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* entry,
- LLViewerRegion* regionp)
- {
- LL_TRACY_TIMER(TRC_PROCESS_OBJECTS);
- LLDataPacker* cached_dpp = entry->getDP();
- if (!cached_dpp)
- {
- return NULL; // Nothing cached.
- }
- #if 0
- // Cache Hit.
- entry->recordHit();
- #endif
- cached_dpp->reset();
- LLUUID fullid;
- cached_dpp->unpackUUID(fullid, "ID");
- U32 local_id;
- cached_dpp->unpackU32(local_id, "LocalID");
- LLPCode pcode = 0;
- cached_dpp->unpackU8(pcode, "PCode");
- if (mBlackListedObjects.count(fullid))
- {
- // This object was blacklisted/derendered: do not restore it from
- // cache.
- return NULL;
- }
- bool just_created = false;
- LLViewerObject* 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->setlocalID(entry->getLocalID());
- }
- if (objectp->getRegion() != regionp)
- {
- // Object changed region, so update it
- objectp->updateRegion(regionp); // for LLVOAvatar
- }
- }
- #if 0 // Should fall through if already loaded because may need to update the
- // object.
- else
- {
- return objectp; // Already loaded.
- }
- #endif
- }
- else if (mDeadObjects.count(fullid))
- {
- LL_DEBUGS("ViewerObject") << "Attempt to re-create a dead object for: "
- << fullid << ". Skipping." << LL_ENDL;
- return NULL;
- }
- else
- {
- objectp = createObjectFromCache(pcode, regionp, fullid,
- entry->getLocalID());
- if (!objectp)
- {
- llinfos << "Failure to create object: " << fullid << llendl;
- return NULL;
- }
- just_created = true;
- ++mNumNewObjects;
- }
- if (objectp->isDead())
- {
- llwarns << "Dead object " << objectp->mID << " in UUID map" << llendl;
- }
- processUpdateCore(objectp, NULL, 0, OUT_FULL_CACHED, cached_dpp,
- just_created, true);
- // Just in case, reload update flags from cache:
- U32 flags = entry->getUpdateFlags();
- objectp->loadFlags(flags);
- if (entry->getHitCount() > 0)
- {
- objectp->setLastUpdateType(OUT_FULL_CACHED);
- }
- else
- {
- objectp->setLastUpdateType(OUT_FULL_COMPRESSED); // Newly cached
- objectp->setLastUpdateCached(true);
- }
- if (objectp->getPCode() == LL_PCODE_LEGACY_AVATAR)
- {
- LLVOAvatar::setAvatarCullingDirty();
- }
- return objectp;
- }
- void LLViewerObjectList::processObjectUpdate(LLMessageSystem* msg,
- void** user_data,
- EObjectUpdateType update_type,
- bool compressed)
- {
- LL_FAST_TIMER(FTM_PROCESS_OBJECTS);
- // 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.
- S32 num_objects = msg->getNumberOfBlocksFast(_PREHASH_ObjectData);
- #if 0
- if (!compressed && update_type != OUT_FULL)
- {
- S32 size;
- if (msg->getReceiveCompressedSize())
- {
- size = msg->getReceiveCompressedSize();
- }
- else
- {
- size = msg->getReceiveSize();
- }
- llinfos << "Received terse " << num_objects << " in " << size
- << " bytes (" << size / num_objects << ")" << llendl;
- }
- else
- {
- S32 size;
- if (msg->getReceiveCompressedSize())
- {
- size = msg->getReceiveCompressedSize();
- }
- else
- {
- size = msg->getReceiveSize();
- }
- llinfos << "Received " << num_objects << " in " << size
- << " bytes (" << size / num_objects << ")" << llendl;
- }
- #endif
- U64 region_handle;
- msg->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
- LLViewerRegion* regionp = gWorld.getRegionFromHandle(region_handle);
- if (!regionp)
- {
- llwarns << "Object update from unknown region ! " << region_handle
- << llendl;
- return;
- }
- U8 compressed_dpbuffer[2048];
- LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
- LLPCode pcode = 0;
- U32 local_id;
- LLUUID fullid;
- bool got_avatars = false;
- for (S32 i = 0; i < num_objects; ++i)
- {
- bool just_created = false;
- // Update object cache if it is a full-update or terse update
- bool update_cache = false;
- if (compressed)
- {
- compressed_dp.reset();
- S32 uncompressed_length = msg->getSizeFast(_PREHASH_ObjectData, i,
- _PREHASH_Data);
- msg->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data,
- compressed_dpbuffer, 0, i, 2048);
- compressed_dp.assignBuffer(compressed_dpbuffer,
- uncompressed_length);
- if (update_type != OUT_TERSE_IMPROVED)
- {
- U32 flags = 0;
- msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags,
- flags, i);
- compressed_dp.unpackUUID(fullid, "ID");
- compressed_dp.unpackU32(local_id, "LocalID");
- compressed_dp.unpackU8(pcode, "PCode");
- if (mDeadObjects.count(fullid))
- {
- LL_DEBUGS("ViewerObject") << "Attempt to update a dead object for: "
- << fullid << ". Skipping."
- << LL_ENDL;
- continue;
- }
- if (pcode == 0)
- {
- llwarns_once << "Invalid Pcode (0) for object " << fullid
- << " (LocalID: " << local_id << llendl;
- continue;
- }
- 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, msg->getSenderIP(),
- msg->getSenderPort());
- if (fullid.isNull())
- {
- LL_DEBUGS("ViewerObject") << "Update for unknown localid: "
- << local_id << " - Host: "
- << msg->getSender() << ":"
- << msg->getSenderPort()
- << LL_ENDL;
- ++mNumUnknownUpdates;
- }
- }
- }
- else if (update_type != OUT_FULL)
- {
- msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
- getUUIDFromLocal(fullid, local_id, msg->getSenderIP(),
- msg->getSenderPort());
- if (fullid.isNull())
- {
- LL_DEBUGS("ViewerObject") << "Update for unknown localid: "
- << local_id << " - Host: "
- << msg->getSender() << ":"
- << msg->getSenderPort()
- << LL_ENDL;
- ++mNumUnknownUpdates;
- }
- }
- else
- {
- update_cache = true;
- msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
- msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
- LL_DEBUGS("ViewerObject") << "Full Update, obj: " << local_id
- << " - Global ID: " << fullid
- << " - From: " << msg->getSender()
- << LL_ENDL;
- }
- if (mBlackListedObjects.count(fullid))
- {
- // This object was blaclisted/derendered: do not recreate it
- continue;
- }
- if (mDeadObjects.count(fullid))
- {
- LL_DEBUGS("ViewerObject") << "Attempt to update a dead object for: "
- << fullid << ". Skipping."
- << LL_ENDL;
- continue;
- }
-
- LLViewerObject* objectp = findObject(fullid);
- bool new_object = objectp == NULL;
- if (update_cache)
- {
- // Update object cache if the object receives a full-update or
- // terse update
- objectp = regionp->updateCacheEntry(local_id, objectp);
- }
- if (new_object && objectp)
- {
- add_newly_created_object(objectp->mID);
- }
- if (mKilledAttachments.count(fullid))
- {
- bool remove = true;
- LL_DEBUGS("Attachment") << "Update for a killed attachment object: "
- << fullid;
- if (!objectp && mDeadObjects.count(fullid))
- {
- #if LL_IGNORE_DEAD
- LL_CONT << " - Object is in dead list !";
- #else
- LL_CONT << " - Object is in dead list and this update will be discarded !";
- remove = false;
- #endif
- }
- LL_CONT << LL_ENDL;
- if (remove)
- {
- mKilledAttachments.erase(fullid);
- }
- }
- // This looks like it will break if the local_id of the object does not
- // 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 0
- if (objectp->getRegion())
- {
- llinfos << "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()
- << llendl;
- }
- #endif
- removeFromLocalIDTable(objectp);
- setUUIDAndLocal(fullid, local_id, msg->getSenderIP(),
- msg->getSenderPort());
- // Update local ID in object with the one sent from the region
- objectp->setlocalID(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_DEBUGS("ViewerObject") << "Terse update for an unknown object: "
- << fullid << LL_ENDL;
- continue;
- }
- }
- else
- {
- if (update_type != OUT_FULL)
- {
- LL_DEBUGS("ViewerObject") << "Terse update for an unknown object: "
- << fullid << LL_ENDL;
- continue;
- }
- msg->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i);
- }
- #if LL_IGNORE_DEAD
- if (mDeadObjects.count(fullid))
- {
- ++mNumDeadObjectUpdates;
- LL_DEBUGS("ViewerObject") << "Update for a dead object: "
- << fullid << LL_ENDL;
- continue;
- }
- #endif
- objectp = createObject(pcode, regionp, fullid, local_id,
- msg->getSender());
- if (!objectp)
- {
- llwarns << "CreateObject failure for object: " << fullid
- << llendl;
- continue;
- }
- just_created = true;
- ++mNumNewObjects;
- }
- if (objectp->isDead())
- {
- llwarns << "Dead object " << objectp->mID << " in UUID map"
- << llendl;
- }
- if (compressed)
- {
- if (update_type != OUT_TERSE_IMPROVED)
- {
- objectp->setlocalID(local_id);
- }
- processUpdateCore(objectp, user_data, i, update_type,
- &compressed_dp, just_created);
- #if 1
- if (update_type != OUT_TERSE_IMPROVED)
- {
- U32 flags = 0;
- msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags,
- flags, i);
- if (!(flags & FLAGS_TEMPORARY_ON_REZ))
- {
- objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp,
- flags);
- objectp->setLastUpdateCached(true);
- }
- }
- #endif
- }
- else
- {
- if (update_type == OUT_FULL)
- {
- objectp->setlocalID(local_id);
- }
- processUpdateCore(objectp, user_data, i, update_type, NULL,
- just_created);
- }
- objectp->setLastUpdateType(update_type);
- got_avatars |= objectp->getPCode() == LL_PCODE_LEGACY_AVATAR;
- }
- if (got_avatars)
- {
- LLVOAvatar::setAvatarCullingDirty();
- }
- }
- void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem* msg,
- void** user_data,
- EObjectUpdateType t)
- {
- processObjectUpdate(msg, user_data, t, true);
- }
- void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem* msg,
- void** user_data,
- EObjectUpdateType t)
- {
- #if 0
- processObjectUpdate(msg, user_data, t, false);
- #endif
- S32 num_objects = msg->getNumberOfBlocksFast(_PREHASH_ObjectData);
- U64 region_handle;
- msg->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
- LLViewerRegion* regionp = gWorld.getRegionFromHandle(region_handle);
- if (!regionp)
- {
- llwarns << "Object update from unknown region " << region_handle
- << llendl;
- return;
- }
- for (S32 i = 0; i < num_objects; ++i)
- {
- U32 local_id, crc, flags;
- msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
- msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
- msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags,
- flags, i);
- // Lookup data packer and add this id to cache miss lists if necessary.
- U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
- regionp->probeCache(local_id, crc, flags, cache_miss_type);
- }
- }
- void LLViewerObjectList::dirtyAllObjectInventory()
- {
- for (S32 i = 0, count = mObjects.size(); i < count; ++i)
- {
- LLViewerObject* objectp = mObjects[i];
- if (objectp)
- {
- objectp->dirtyInventory();
- }
- }
- }
- void LLViewerObjectList::updateApparentAngles()
- {
- const S32 objects_size = (S32)mObjects.size();
- // The list can have shrunken down since mCurLazyUpdateIndex was last
- // updated.
- if (mCurLazyUpdateIndex >= objects_size)
- {
- mCurLazyUpdateIndex = 0;
- }
- S32 num_updates, max_value;
- if (mCurBin == NUM_BINS - 1)
- {
- // Remainder (mObjects.size() could have changed)
- num_updates = objects_size - mCurLazyUpdateIndex;
- max_value = objects_size;
- }
- else
- {
- num_updates = objects_size / NUM_BINS + 1;
- max_value = llmin(objects_size, mCurLazyUpdateIndex + num_updates);
- }
- bool got_avatars = false;
- LLViewerObject* objectp;
- if (gHoverViewp)
- {
- // Slam priorities for textures that we care about (hovered, selected,
- // and focused). Hovered. Assumes only one level deep of parenting
- objectp = gHoverViewp->getLastHoverObject();
- if (objectp && !objectp->isDead())
- {
- objectp->boostTexturePriority();
- got_avatars |= objectp->getPCode() == LL_PCODE_LEGACY_AVATAR;
- }
- }
- // Focused
- objectp = gAgent.getFocusObject();
- if (objectp && !objectp->isDead())
- {
- objectp->boostTexturePriority();
- got_avatars |= objectp->getPCode() == LL_PCODE_LEGACY_AVATAR;
- }
- // Selected
- struct f final : public LLSelectedObjectFunctor
- {
- bool apply(LLViewerObject* objectp) override
- {
- if (objectp && !objectp->isDead())
- {
- objectp->boostTexturePriority();
- }
- return true;
- }
- } func;
- gSelectMgr.getSelection()->applyToRootObjects(&func);
- // Iterate through some of the objects and lazy update their texture
- // priorities
- #if LL_OPENMP
- objectp = NULL;
- size_t num_objects = max_value - mCurLazyUpdateIndex;
- std::vector<LLViewerObject*> objects(num_objects, objectp);
- # pragma omp parallel for private(objectp) reduction(|:got_avatars)
- for (S32 i = mCurLazyUpdateIndex; i < max_value; ++i)
- {
- objectp = mObjects[i];
- if (objectp && !objectp->isDead())
- {
- got_avatars |= objectp->getPCode() == LL_PCODE_LEGACY_AVATAR;
- // Update distance & gpw
- // Also sets the approx. pixel area:
- objectp->setPixelAreaAndAngle();
- // Store for later textures update
- objects[i - mCurLazyUpdateIndex] = objectp;
- }
- }
- // This CANNOT be called from an OMP thread, because updateTextures() may
- // result in OpenGL calls, that might themselves be threaded via pthread !
- for (S32 i = 0, count = objects.size(); i < count; ++i)
- {
- objectp = objects[i];
- if (objectp && !objectp->isDead())
- {
- // Update the image levels of textures for this object:
- objects[i]->updateTextures();
- }
- }
- #else
- for (S32 i = mCurLazyUpdateIndex; i < max_value; ++i)
- {
- objectp = mObjects[i];
- if (objectp && !objectp->isDead())
- {
- got_avatars |= objectp->getPCode() == LL_PCODE_LEGACY_AVATAR;
- // Update distance & gpw
- // Also sets the approx. pixel area:
- objectp->setPixelAreaAndAngle();
- // Update the image levels of textures for this object:
- objectp->updateTextures();
- }
- }
- #endif
- mCurLazyUpdateIndex = max_value;
- if ((size_t)mCurLazyUpdateIndex == mObjects.size())
- {
- // Restart
- mCurLazyUpdateIndex = 0;
- // Keep in sync with index (mObjects.size() could have changed)
- mCurBin = 0;
- }
- else
- {
- mCurBin = (mCurBin + 1) % NUM_BINS;
- }
- if (got_avatars || LLVOAvatar::avatarCullingDirty())
- {
- LLVOAvatar::cullAvatarsByPixelArea();
- }
- }
- void LLViewerObjectList::update()
- {
- // Update global timers
- F32 last_time = gFrameTimeSeconds;
- // This will become the new gFrameTime when the update is done
- U64 time = LLTimer::totalTime();
- F64 time_diff = U64_to_F64(time - gFrameTime) / (F64)SEC_TO_MICROSEC;
- if (time_diff < 0.0)
- {
- // Time went backwards... Use last frame interval as an approximation.
- time_diff = gFrameIntervalSeconds;
- // Adjust start time accordingly...
- gStartTime += time - gFrameTime;
- }
- gFrameTime = time;
- F64 time_since_start = U64_to_F64(gFrameTime - gStartTime) /
- (F64)SEC_TO_MICROSEC;
- gFrameTimeSeconds = (F32)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();
- // Make a copy of the list in case something in idleUpdate() messes with it
- S32 idle_count = 0;
- {
- LL_FAST_TIMER(FTM_OBJECTLIST_COPY);
- S32 count = mActiveObjects.size();
- if (count > mIdleListSlots)
- {
- // Minimize fragmentation and reallocation time overhead:
- mIdleList.clear();
- mIdleListSlots = 125 * count / 100;
- mIdleList.reserve(mIdleListSlots);
- }
- S32 idle_list_old_size = mIdleList.size();
- for (S32 i = 0; i < count; )
- {
- LLViewerObject* objectp = mActiveObjects[i];
- if (!objectp)
- {
- // There should not be any NULL pointer in the list, but they
- // have caused crashes before.
- llwarns << "mActiveObjects has a NULL object. Removing."
- << llendl;
- if (i != --count)
- {
- mActiveObjects[i] = std::move(mActiveObjects.back());
- }
- mActiveObjects.pop_back();
- continue;
- }
- if (objectp->isDead())
- {
- // There should not be any dead object in the list, but they
- // have caused crashes before.
- llwarns << "mActiveObjects has dead object "
- << objectp->getID() << ". Removing." << llendl;
- mDeadList.push_back(objectp);
- }
- else if (idle_count >= idle_list_old_size)
- {
- mIdleList.push_back(objectp);
- ++idle_count;
- }
- else
- {
- mIdleList[idle_count++] = objectp;
- }
- ++i;
- }
- }
- S32 count = mDeadList.size();
- if (count)
- {
- LL_DEBUGS("ViewerObject") << "Removing detected dead objects from the active objects list."
- << LL_ENDL;
- for (S32 i = 0; i < count; ++i )
- {
- cleanupReferences(mDeadList[i]);
- }
- mDeadList.clear();
- }
- if (LLPipeline::sFreezeTime)
- {
- for (S32 i = 0; i < idle_count; ++i)
- {
- LLViewerObject* objectp = mIdleList[i];
- if (objectp->isAvatar() ||
- objectp->getPCode() == LLViewerObject::LL_VO_CLOUDS)
- {
- objectp->idleUpdate(frame_time);
- }
- }
- }
- else
- {
- for (S32 i = 0; i < idle_count; ++i)
- {
- LLViewerObject* objectp = mIdleList[i];
- objectp->idleUpdate(frame_time);
- }
- // Update flexible objects
- LLVolumeImplFlexible::updateClass();
- if (LLVOVolume::sAnimateTextures)
- {
- // Update animated textures
- LLViewerTextureAnim::updateClass();
- }
- }
- fetchObjectCosts();
- fetchPhysicsFlags();
- mNumSizeCulled = 0;
- mNumVisCulled = 0;
- // Compute all sorts of time-based stats; do not factor frames that were
- // paused into the stats.
- if (!mWasPaused)
- {
- gViewerStats.updateFrameStats(time_diff);
- }
- #if 0
- // Debugging code for viewing orphans, and orphaned parents
- LLUUID id;
- std::string id_str;
- for (S32 i = 0, count = mOrphanParents.size(); i < count; ++i)
- {
- id = mIndexAndLocalIDToUUID[mOrphanParents[i]];
- LLViewerObject* objectp = findObject(id);
- if (objectp)
- {
- objectp->mID.toString(id_str);
- std::string tmpstr = "Parent: " + id_str;
- addDebugBeacon(objectp->getPositionAgent(), tmpstr, LLColor4::red,
- LLColor4::white);
- }
- }
- LLColor4 text_color;
- std::string tmpstr;
- for (S32 i = 0, count = mOrphanChildren.size(); i < count; ++i)
- {
- OrphanInfo oi = mOrphanChildren[i];
- LLViewerObject* objectp = findObject(oi.mChildInfo);
- if (objectp)
- {
- objectp->mID.toString(id_str);
- if (objectp->getParent())
- {
- tmpstr = "ChP: " + id_str;
- text_color = LLColor4::green;
- }
- else
- {
- tmpstr = "ChNoP: " + id_str;
- text_color = LLColor4::red;
- }
- id = mIndexAndLocalIDToUUID[oi.mParentInfo];
- addDebugBeacon(objectp->getPositionAgent() +
- LLVector3(0.f, 0.f, -0.25f),
- tmpstr, LLColor4::grey4,
- text_color);
- }
- }
- #endif
- mNumObjectsStat.addValue((S32)(mObjects.size() - mDeadObjects.size()));
- mNumActiveObjectsStat.addValue(idle_count);
- mNumSizeCulledStat.addValue(mNumSizeCulled);
- mNumVisCulledStat.addValue(mNumVisCulled);
- }
- // Issues HTTP request for stale object physics costs
- void LLViewerObjectList::fetchObjectCosts()
- {
- if (mStaleObjectCost.empty())
- {
- return;
- }
- const std::string& url = gAgent.getRegionCapability("GetObjectCost");
- if (url.empty())
- {
- mStaleObjectCost.clear();
- mPendingObjectCost.clear();
- return;
- }
- gCoros.launch("LLViewerObjectList::fetchObjectCostsCoro",
- boost::bind(&LLViewerObjectList::fetchObjectCostsCoro, this,
- url));
- }
- void LLViewerObjectList::fetchObjectCostsCoro(const std::string& url)
- {
- LLSD object_ids = LLSD::emptyArray();
- S32 count = 0;
- uuid_list_t::iterator it = mStaleObjectCost.begin();
- while (it != mStaleObjectCost.end() && count < gMaxObjectsPerFetch)
- {
- // Check to see if a request for this object has already been made.
- if (mPendingObjectCost.find(*it) == mPendingObjectCost.end())
- {
- mPendingObjectCost.emplace(*it);
- object_ids.append(*it);
- ++count;
- }
- mStaleObjectCost.erase(it++);
- }
- if (object_ids.size() < 1)
- {
- return;
- }
- LLSD body = LLSD::emptyMap();
- body["object_ids"] = object_ids;
- LLCoreHttpUtil::HttpCoroutineAdapter adapter("fetchObjectCostsCoro");
- LLSD result = adapter.postAndSuspend(url, body);
- LLCore::HttpStatus status =
- LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
- if (!status || result.has("error"))
- {
- if (result.has("error"))
- {
- const LLSD& error = result["error"];
- std::string identifier;
- if (error.has("identifier"))
- {
- identifier = error["identifier"].asString();
- }
- llwarns << "Application level error when fetching object cost. Message: "
- << error["message"].asString()
- << " - Identifier: " << identifier << llendl;
- if (gMaxObjectsPerFetch > 32 &&
- identifier.find("TooManyObjects") != std::string::npos)
- {
- // Reduce the maximum number of objects per fetch by 25%.
- gMaxObjectsPerFetch = 4 * gMaxObjectsPerFetch / 5;
- llinfos << "Reduced maximum objects limit per fetch to: "
- << gMaxObjectsPerFetch << llendl;
- }
- }
- // *TODO: No more hard coding
- for (LLSD::array_iterator iter = object_ids.beginArray(),
- end = object_ids.endArray();
- iter != end; ++iter)
- {
- onObjectCostFetchFailure(iter->asUUID());
- }
- return;
- }
- // Success, grab the resource cost and linked set costs for an object if
- // one was returned
- for (LLSD::array_iterator it = object_ids.beginArray(),
- end = object_ids.endArray();
- it != end; ++it)
- {
- LLUUID object_id = it->asUUID();
- // If the object was added to the StaleObjectCost set after it had been
- // added to mPendingObjectCost it would still be in the StaleObjectCost
- // set when we got the response back.
- mStaleObjectCost.erase(object_id);
- // Check to see if the request contains data for the object
- if (result.has(it->asString()))
- {
- LLSD data = result[it->asString()];
- F32 link_cost = data["linked_set_resource_cost"].asReal();
- F32 object_cost = data["resource_cost"].asReal();
- F32 physics_cost = data["physics_cost"].asReal();
- F32 linkset_cost = data["linked_set_physics_cost"].asReal();
- updateObjectCost(object_id, object_cost, link_cost, physics_cost,
- linkset_cost);
- }
- else
- {
- // *TODO: Give user feedback about the missing data ?
- onObjectCostFetchFailure(object_id);
- }
- }
- }
- // Issues HTTP request for stale object physics flags
- void LLViewerObjectList::fetchPhysicsFlags()
- {
- if (mStalePhysicsFlags.empty())
- {
- return;
- }
- const std::string& url =
- gAgent.getRegionCapability("GetObjectPhysicsData");
- if (url.empty())
- {
- mStalePhysicsFlags.clear();
- mPendingPhysicsFlags.clear();
- return;
- }
- gCoros.launch("LLViewerObjectList::fetchPhysicsFlagsCoro",
- boost::bind(&LLViewerObjectList::fetchPhysicsFlagsCoro, this,
- url));
- }
- void LLViewerObjectList::fetchPhysicsFlagsCoro(const std::string& url)
- {
- LLSD object_ids;
- S32 object_index = 0;
- uuid_list_t::iterator it = mStalePhysicsFlags.begin();
- while (it != mStalePhysicsFlags.end() &&
- object_index < gMaxObjectsPerFetch)
- {
- // Check to see if a request for this object has already been made.
- if (mPendingPhysicsFlags.find(*it) == mPendingPhysicsFlags.end())
- {
- mPendingPhysicsFlags.emplace(*it);
- object_ids[object_index++] = *it;
- }
- mStalePhysicsFlags.erase(it++);
- }
- if (object_ids.size() < 1)
- {
- return;
- }
- LLSD body = LLSD::emptyMap();
- body["object_ids"] = object_ids;
- LLCoreHttpUtil::HttpCoroutineAdapter adapter("fetchPhysicsFlagsCoro");
- LLSD result = adapter.postAndSuspend(url, body);
- LLCore::HttpStatus status =
- LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
- if (!status || result.has("error"))
- {
- if (result.has("error"))
- {
- const LLSD& error = result["error"];
- std::string identifier;
- if (error.has("identifier"))
- {
- identifier = error["identifier"].asString();
- }
- llwarns << "Application level error when fetching object physics flags. Message: "
- << error["message"].asString()
- << " - Identifier: " << identifier << llendl;
- if (gMaxObjectsPerFetch > 32 &&
- identifier.find("TooManyObjects") != std::string::npos)
- {
- // Reduce the maximum number of objects per fetch by 25%.
- gMaxObjectsPerFetch = 4 * gMaxObjectsPerFetch / 5;
- llinfos << "Reduced maximum objects limit per fetch to: "
- << gMaxObjectsPerFetch << llendl;
- }
- }
- for (LLSD::array_iterator iter = object_ids.beginArray(),
- end = object_ids.endArray();
- iter != end; ++iter)
- {
- onPhysicsFlagsFetchFailure(iter->asUUID());
- }
- return;
- }
- // Success, grab the physics parameters for an object if one was returned
- for (LLSD::array_iterator it = object_ids.beginArray(),
- end = object_ids.endArray();
- it != end; ++it)
- {
- LLUUID object_id = 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();
- updatePhysicsShapeType(object_id, shapeType);
- if (data.has("Density"))
- {
- F32 density = data["Density"].asReal();
- F32 friction = data["Friction"].asReal();
- F32 restitution = data["Restitution"].asReal();
- F32 gravity = data["GravityMultiplier"].asReal();
- updatePhysicsProperties(object_id, density, friction,
- restitution, gravity);
- }
- }
- else
- {
- // *TODO: Give user feedback about the missing data?
- onPhysicsFlagsFetchFailure(object_id);
- }
- }
- }
- bool LLViewerObjectList::gotObjectPhysicsFlags(LLViewerObject* objectp)
- {
- // This will insert objectp in mStalePhysicsFlags if needed:
- objectp->getPhysicsShapeType();
- // Data has been retrieved if the object is not in either of the two lists:
- const LLUUID& id = objectp->getID();
- return mPendingPhysicsFlags.count(id) == 0 &&
- mStalePhysicsFlags.count(id) == 0;
- }
- void LLViewerObjectList::clearDebugText()
- {
- for (S32 i = 0, count = mObjects.size(); i < count; ++i)
- {
- LLViewerObject* objectp = mObjects[i];
- if (objectp && !objectp->isDead())
- {
- objectp->setDebugText("");
- }
- }
- }
- void LLViewerObjectList::cleanupReferences(LLViewerObject* objectp)
- {
- LL_TRACY_TIMER(TRC_OBJ_CLEANUP_REF);
- if (!objectp)
- {
- llwarns << "NULL object pointer passed." << llendl;
- return;
- }
- const LLUUID& object_id = objectp->mID;
- // Cleanup any references we have to this object. Remove from object maps
- // so that no one can look it up.
- mUUIDObjectMap.erase(object_id);
- mUUIDAvatarMap.erase(object_id);
- if (mDeadObjects.count(object_id))
- {
- LL_DEBUGS("ViewerObject") << "Object " << object_id
- << " already on dead list !" << LL_ENDL;
- }
- else
- {
- mDeadObjects.emplace(object_id);
- }
- removeFromLocalIDTable(objectp);
- if (objectp->onActiveList())
- {
- LL_DEBUGS("ViewerObject") << "Removing " << object_id << " "
- << objectp->getPCodeString()
- << " from active list." << LL_ENDL;
- objectp->setOnActiveList(false);
- removeFromActiveList(objectp);
- }
- if (objectp->isOnMap())
- {
- removeFromMap(objectp);
- }
- }
- bool LLViewerObjectList::killObject(LLViewerObject* objectp)
- {
- // Do not 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 are killing objects, all we do is mark them as dead.
- // We clean up the dead objects later.
- if (objectp)
- {
- #if 0 // NOT needed for the Cool VL Viewer; the only occurrence of such
- // a self-destructing object in markDead() (puppet avatar unlinking)
- // was already identified and fixed by me in LLViewerObject::markDead()
- // (see the comment at the end of that method)... Plus, smart pointers
- // to killed objects are kept in mObjects till cleanDeadObjects() is
- // called, so the reason given below is bullshit. HB
- // We are going to cleanup a lot of smart pointers to this object; they
- // might be last, and object being NULLed while inside its own function
- // would cause a crash. So, create a smart pointer to make sure the
- // object will stay alive untill markDead() finishes.
- LLPointer<LLViewerObject> objp(objectp);
- objp->markDead(); // Does the right thing if object already dead
- #else
- objectp->markDead(); // Does the right thing if object already dead
- #endif
- return true;
- }
- return false;
- }
- void LLViewerObjectList::killObjects(LLViewerRegion* regionp)
- {
- LLTimer kill_timer;
- S32 killed = 0;
- for (S32 i = 0, count = mObjects.size(); i < count; ++i)
- {
- LLViewerObject* objectp = mObjects[i];
- if (objectp && objectp->mRegionp == regionp)
- {
- ++killed;
- killObject(objectp);
- }
- }
- // Have to clean right away because the region is becoming invalid.
- cleanDeadObjects();
- llinfos << "Removed " << killed << " objects for region "
- << regionp->getIdentity() << " in "
- << kill_timer.getElapsedTimeF64() * 1000.0 << "ms" << llendl;
- }
- // Used only on global destruction.
- void LLViewerObjectList::killAllObjects()
- {
- llinfos << "Marking all objects dead..." << llendl;
- for (S32 i = 0, count = mObjects.size(); i < count; ++i)
- {
- LLViewerObject* objectp = mObjects[i];
- if (objectp)
- {
- killObject(objectp);
- // Object must be dead, or it is the LLVOAvatarSelf which never
- // dies
- llassert(objectp == gAgentAvatarp || objectp->isDead());
- }
- }
- llinfos << "Cleaning up dead objects..." << llendl;
- cleanDeadObjects();
- if (!mDeadObjects.empty())
- {
- llwarns << "There are still has entries left in mDeadObjects: "
- << mObjects.size() << llendl;
- mDeadObjects.clear();
- }
- if (!mObjects.empty())
- {
- llwarns << "There are still has entries left in mObjects: "
- << mObjects.size() << llendl;
- mObjects.clear();
- }
- if (!mActiveObjects.empty())
- {
- llwarns << "Some objects still on active object list !" << llendl;
- mActiveObjects.clear();
- }
- if (!mMapObjects.empty())
- {
- llwarns << "Some objects still on map object list !" << llendl;
- mMapObjects.clear();
- }
- }
- void LLViewerObjectList::cleanDeadObjects()
- {
- U32 num_dead_objects = mDeadObjects.size();
- if (!num_dead_objects)
- {
- // No dead object, so we do not need to scan objects list.
- return;
- }
- U32 num_removed = 0;
- U32 null_objects = 0;
- vobj_list_t::iterator iter = mObjects.begin();
- while (iter != mObjects.end())
- {
- LLViewerObject* objectp = (*iter).get();
- if (!objectp || objectp->isDead())
- {
- if (iter + 1 != mObjects.end())
- {
- *iter = std::move(mObjects.back());
- }
- mObjects.pop_back();
- if (objectp)
- {
- ++num_removed;
- }
- else
- {
- ++null_objects;
- }
- }
- else
- {
- ++iter;
- }
- }
- if (num_removed != num_dead_objects)
- {
- llwarns << "Removed " << num_removed
- << " dead objects from the list while it was supposed to have "
- << num_dead_objects << " such objects in it." << llendl;
- llassert(false);
- }
- if (null_objects)
- {
- llwarns << "Found " << null_objects
- << " NULL objects in the list (now removed)." << llendl;
- llassert(false);
- }
- // Blow away the dead list.
- mDeadObjects.clear();
- }
- 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] = std::move(mActiveObjects[last_index]);
- mActiveObjects[idx]->setListIndex(idx);
- }
- mActiveObjects.pop_back();
- }
- }
- void LLViewerObjectList::updateActive(LLViewerObject* objectp)
- {
- LL_TRACY_TIMER(TRC_OBJ_UPDATE_ACTIVE);
- if (!objectp || objectp->isDead())
- {
- return; // We do not update dead objects !
- }
- bool active = objectp->isActive();
- if (active != objectp->onActiveList())
- {
- if (active)
- {
- S32 idx = objectp->getListIndex();
- if (idx <= -1)
- {
- mActiveObjects.push_back(objectp);
- objectp->setListIndex(mActiveObjects.size() - 1);
- objectp->setOnActiveList(true);
- }
- else if (idx >= (S32)mActiveObjects.size() ||
- mActiveObjects[idx] != objectp)
- {
- llwarns << "Invalid object list index detected !"
- << llendl;
- llassert(false);
- }
- }
- else
- {
- 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 && !object->isDead())
- {
- if (!object->isRoot() && object->getParent())
- {
- // Always fetch cost for the parent when fetching cost for children
- mStaleObjectCost.emplace(((LLViewerObject*)object->getParent())->getID());
- }
- mStaleObjectCost.emplace(object->getID());
- }
- }
- void LLViewerObjectList::updateObjectCost(const LLUUID& object_id,
- F32 object_cost, F32 link_cost,
- F32 physics_cost,
- F32 link_physics_cost)
- {
- mPendingObjectCost.erase(object_id);
- LLViewerObject* object = findObject(object_id);
- if (object && !object->isDead())
- {
- object->setObjectCost(object_cost);
- object->setLinksetCost(link_cost);
- object->setPhysicsCost(physics_cost);
- object->setLinksetPhysicsCost(link_physics_cost);
- }
- }
- void LLViewerObjectList::onObjectCostFetchFailure(const LLUUID& object_id)
- {
- mPendingObjectCost.erase(object_id);
- }
- void LLViewerObjectList::updatePhysicsFlags(const LLViewerObject* object)
- {
- mStalePhysicsFlags.emplace(object->getID());
- }
- void LLViewerObjectList::updatePhysicsShapeType(const LLUUID& object_id,
- S32 type)
- {
- mPendingPhysicsFlags.erase(object_id);
- LLViewerObject* object = findObject(object_id);
- if (object && !object->isDead())
- {
- 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->isDead())
- {
- object->setPhysicsDensity(density);
- object->setPhysicsFriction(friction);
- object->setPhysicsGravity(gravity_multiplier);
- object->setPhysicsRestitution(restitution);
- }
- }
- void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id)
- {
- mPendingPhysicsFlags.erase(object_id);
- }
- // This is called when we shift our origin when we cross region boundaries...
- // We need to update many object caches, I will document this more as I dig
- // through the code cleaning things out...
- void LLViewerObjectList::shiftObjects(const LLVector3& offset)
- {
- if (offset.lengthSquared() == 0.f)
- {
- return;
- }
- LL_FAST_TIMER(FTM_SHIFT_OBJECTS);
- for (S32 i = 0, count = mObjects.size(); i < count; ++i)
- {
- LLViewerObject* objectp = mObjects[i];
- // There could be dead objects on the object list, so do not update
- // stuff if the object is dead.
- if (objectp && !objectp->isDead())
- {
- objectp->updatePositionCaches();
- // NOTE: LLPipeline::markShift() tests for non-NULL and non-dead
- // drawable, so not need to perform these tests here. HB
- gPipeline.markShift(objectp->mDrawable);
- }
- }
- {
- LL_FAST_TIMER(FTM_PIPELINE_SHIFT);
- gPipeline.shiftObjects(offset);
- }
- {
- LL_FAST_TIMER(FTM_REGION_SHIFT);
- gWorld.shiftRegions(offset);
- }
- }
- void LLViewerObjectList::repartitionObjects()
- {
- for (S32 i = 0, count = mObjects.size(); i < count; ++i)
- {
- LLViewerObject* objectp = mObjects[i];
- if (objectp && !objectp->isDead())
- {
- LLDrawable* drawable = objectp->mDrawable;
- if (drawable && !drawable->isDead())
- {
- drawable->updateBinRadius();
- drawable->updateSpatialExtents();
- drawable->movePartition();
- }
- }
- }
- }
- void LLViewerObjectList::clearAllMapObjectsInRegion(LLViewerRegion* regionp)
- {
- for (S32 i = 0, count = mMapObjects.size(); i < count; ++i)
- {
- LLViewerObject* objectp = mMapObjects[i];
- // Clean up the list from invalid objects, while we are at it... HB
- if (!objectp || objectp->isDead() || objectp->isOrphaned() ||
- // ... and remove objects present in the specified region.
- objectp->getRegion() == regionp)
- {
- if (i != --count)
- {
- mMapObjects[i] = std::move(mMapObjects.back());
- }
- mMapObjects.pop_back();
- }
- }
- }
- void LLViewerObjectList::renderObjectsForMap(LLPanelMiniMap* map)
- {
- static LLCachedControl<LLColor4U>
- above_water_color(gColors, "MiniMapOtherOwnAboveWater");
- static LLCachedControl<LLColor4U>
- below_water_color(gColors, "MiniMapOtherOwnBelowWater");
- static LLCachedControl<LLColor4U>
- you_own_above_water_color(gColors, "MiniMapYouOwnAboveWater");
- static LLCachedControl<LLColor4U>
- you_own_below_water_color(gColors, "MiniMapYouOwnBelowWater");
- static LLCachedControl<LLColor4U>
- group_own_above_water_color(gColors, "MiniMapGroupOwnAboveWater");
- static LLCachedControl<LLColor4U>
- group_own_below_water_color(gColors, "MiniMapGroupOwnBelowWater");
- for (S32 i = 0, count = mMapObjects.size(); i < count; ++i)
- {
- LLViewerObject* objectp = mMapObjects[i];
- // Clean up the list from invalid objects, while we are at it. HB
- if (!objectp || objectp->isDead() || !objectp->getRegion() ||
- objectp->isOrphaned())
- {
- if (i != --count)
- {
- mMapObjects[i] = std::move(mMapObjects.back());
- }
- mMapObjects.pop_back();
- continue;
- }
- const LLVector3d pos = objectp->getPositionGlobal();
- if (objectp->flagCharacter())
- {
- if (objectp->isRoot())
- {
- // Path-finding characters are ploted by the mini-map code
- // itself.
- map->addPathFindingCharacter(pos);
- }
- continue;
- }
- const LLVector3& scale = objectp->getScale();
- const F64 water_height = F64(objectp->getRegion()->getWaterHeight());
- // Note: 0.325 = 0.5^2 * 1.3 (1.3 is a fudge)
- F32 approx_radius = (scale.mV[VX] + scale.mV[VY]) * 0.325f;
- // We draw physical objects after all others (and thus above them), to
- // be sure to see them on map...
- if (objectp->flagUsePhysics())
- {
- if (objectp->isRoot())
- {
- // Physcical objects (mobiles) are ploted by the mini-map code
- // itself.
- map->addPhysicalObject(pos);
- }
- continue;
- }
- LLColor4U color = above_water_color;
- if (objectp->permYouOwner())
- {
- constexpr 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;
- }
- map->renderScaledPointGlobal(pos, color, approx_radius);
- }
- }
- void LLViewerObjectList::addDebugBeacon(const LLVector3& pos_agent,
- const std::string& text,
- const LLColor4& color,
- const LLColor4& text_color,
- S32 line_width)
- {
- mDebugBeacons.emplace_back(pos_agent, text, text_color, color, line_width);
- }
- void LLViewerObjectList::resetObjectBeacons()
- {
- mDebugBeacons.clear();
- }
- LLViewerObject* LLViewerObjectList::createObjectViewer(LLPCode pcode,
- LLViewerRegion* regionp,
- S32 flags)
- {
- LLUUID fullid;
- fullid.generate();
- LLViewerObject* objectp = LLViewerObject::createObject(fullid, pcode,
- regionp, flags);
- if (!objectp)
- {
- LL_DEBUGS("ViewerObject") << "Could not create object of type "
- << LLPrimitive::pCodeToString(pcode)
- << LL_ENDL;
- return NULL;
- }
- mUUIDObjectMap[fullid] = objectp;
- if (objectp->isAvatar())
- {
- LLVOAvatar* avatarp = objectp->asAvatar();
- if (avatarp)
- {
- mUUIDAvatarMap[fullid] = avatarp;
- }
- }
- mObjects.push_back(objectp);
- updateActive(objectp);
- return objectp;
- }
- LLViewerObject* LLViewerObjectList::createObjectFromCache(LLPCode pcode,
- LLViewerRegion* regionp,
- const LLUUID& uuid,
- U32 local_id)
- {
- llassert_always(uuid.notNull());
- LLViewerObject* objectp = LLViewerObject::createObject(uuid, pcode,
- regionp);
- if (!objectp)
- {
- LL_DEBUGS("ViewerObject") << "Could not create object of type "
- << LLPrimitive::pCodeToString(pcode)
- << " - Id: " << uuid << LL_ENDL;
- return NULL;
- }
- LL_DEBUGS("ObjectCacheSpam") << "Created object " << uuid
- << " from cache." << LL_ENDL;
- objectp->setlocalID(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(LLPCode pcode,
- LLViewerRegion* regionp,
- const LLUUID& uuid,
- U32 local_id,
- const LLHost& sender)
- {
- LL_FAST_TIMER(FTM_CREATE_OBJECT);
- LLUUID fullid;
- if (uuid.isNull())
- {
- fullid.generate();
- }
- else if (mDeadObjects.count(uuid))
- {
- LL_DEBUGS("ViewerObject") << "Attempt to re-create a dead object for: "
- << uuid << ". Skipping." << LL_ENDL;
- return NULL;
- }
- else
- {
- fullid = uuid;
- }
- LLViewerObject* objectp = LLViewerObject::createObject(fullid, pcode,
- regionp);
- if (!objectp)
- {
- LL_DEBUGS("ViewerObject") << "Could not create object of type "
- << LLPrimitive::pCodeToString(pcode)
- << " id:" << fullid << LL_ENDL;
- return NULL;
- }
- if (regionp)
- {
- regionp->addToCreatedList(local_id);
- }
- mUUIDObjectMap[fullid] = objectp;
- if (objectp->isAvatar())
- {
- LLVOAvatar* avatarp = objectp->asAvatar();
- if (avatarp)
- {
- mUUIDAvatarMap[fullid] = avatarp;
- }
- }
- setUUIDAndLocal(fullid, local_id, gMessageSystemp->getSenderIP(),
- gMessageSystemp->getSenderPort());
- mObjects.push_back(objectp);
- if (gAutomationp && objectp->isAvatar())
- {
- gAutomationp->onAvatarRezzing(fullid);
- }
- updateActive(objectp);
- return objectp;
- }
- LLViewerObject* LLViewerObjectList::replaceObject(const LLUUID& id,
- LLPCode pcode,
- LLViewerRegion* regionp)
- {
- LLViewerObject* old_instance = findObject(id);
- if (old_instance)
- {
- #if 0
- cleanupReferences(old_instance);
- #endif
- old_instance->markDead();
- return createObject(pcode, regionp, id, old_instance->getLocalID(),
- LLHost());
- }
- return NULL;
- }
- #if LL_DEBUG && 0
- S32 LLViewerObjectList::findReferences(LLDrawable* drawablep) const
- {
- LLViewerObject* objectp;
- S32 num_refs = 0;
- for (S32 i = 0, count = mObjects.size(); i < count; ++i)
- {
- objectp = mObjects[i];
- if (objectp && objectp->mDrawable.notNull())
- {
- num_refs += objectp->mDrawable->findReferences(drawablep);
- }
- }
- return num_refs;
- }
- #endif
- void LLViewerObjectList::orphanize(LLViewerObject* childp, U32 parent_id,
- U32 ip, U32 port)
- {
- LL_DEBUGS("Orphans") << "Orphaning object " << childp->getID()
- << " with parent " << parent_id << llendl;
- // We are 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;
- }
- }
- if (make_invisible)
- {
- // Make sure that this object becomes invisible if it is 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_TRACY_TIMER(TRC_OBJ_FIND_ORPHANS);
- if (!objectp)
- {
- return;
- }
- if (objectp->isDead())
- {
- llwarns << "Trying to find orphans for dead obj " << objectp->mID
- << ":" << objectp->getPCodeString() << llendl;
- 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<OrphanInfo>::iterator iter = mOrphanChildren.begin();
- iter != mOrphanChildren.end(); )
- {
- if (iter->mParentInfo != parent_info)
- {
- ++iter;
- continue;
- }
- LLViewerObject* childp = findObject(iter->mChildInfo);
- if (childp)
- {
- if (childp == objectp)
- {
- llwarns << objectp->mID << " has self as parent, skipping !"
- << llendl;
- ++iter;
- continue;
- }
- LL_DEBUGS("Orphans") << "Reunited parent " << objectp->mID
- << " with child " << childp->mID
- << " - Global position: "
- << objectp->getPositionGlobal()
- << " - Position from agent: "
- << objectp->getPositionAgent();
- addDebugBeacon(objectp->getPositionAgent(), "");
- LL_CONT << LL_ENDL;
- 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);
- gPipeline.markRebuild(childp->mDrawable);
- }
- // Make certain particles, icon and HUD aren't hidden
- childp->hideExtraDisplayItems(false);
- objectp->addChild(childp);
- orphans_found = true;
- ++iter;
- }
- else
- {
- llinfos << "Missing orphan child, removing from list" << llendl;
- iter = mOrphanChildren.erase(iter);
- }
- }
- // Remove orphan parent and children from lists now that they have been
- // found
- {
- std::vector<U64>::iterator iter = std::find(mOrphanParents.begin(),
- mOrphanParents.end(),
- parent_info);
- if (iter != mOrphanParents.end())
- {
- mOrphanParents.erase(iter);
- }
- }
- for (std::vector<OrphanInfo>::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 = gSelectMgr.getSelection()->findNode(objectp);
- if (nodep && !nodep->mIndividualSelection)
- {
- // Rebuild selection with orphans
- gSelectMgr.deselectObjectAndFamily(objectp);
- gSelectMgr.selectObjectAndFamily(objectp);
- }
- }
- }
- void LLViewerObjectList::registerKilledAttachment(const LLUUID& id)
- {
- U64 handle = 0;
- LLViewerRegion* regionp = gAgent.getRegion();
- if (regionp)
- {
- handle = regionp->getHandle();
- }
- if (mKilledAttachmentsStamp != handle)
- {
- mKilledAttachmentsStamp = handle;
- mKilledAttachments.clear();
- }
- mKilledAttachments.emplace(id);
- }
- /*****************************************************************************/
- // Methods that used to be in llglsandbox.cpp
- void LLViewerObjectList::renderObjectBeacons()
- {
- if (mDebugBeacons.empty())
- {
- return;
- }
- LLGLSUIDefault gls_ui;
- gUIProgram.bind();
- LLTexUnit* unit0 = gGL.getTexUnit(0);
- {
- unit0->unbind(LLTexUnit::TT_TEXTURE);
- S32 last_line_width = -1;
- for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(),
- end = mDebugBeacons.end();
- iter != end; ++iter)
- {
- const LLDebugBeacon& debug_beacon = *iter;
- LLColor4 color = debug_beacon.mColor;
- color.mV[3] *= 0.25f;
- if (gUsePBRShaders)
- {
- color = linearColor4(color);
- }
- S32 line_width = debug_beacon.mLineWidth;
- if (line_width != last_line_width)
- {
- gGL.flush();
- gGL.lineWidth((F32)line_width);
- last_line_width = line_width;
- }
- const LLVector3& thisline = debug_beacon.mPositionAgent;
- const F32& x = thisline.mV[VX];
- const F32& y = thisline.mV[VY];
- const F32& z = thisline.mV[VZ];
- gGL.begin(LLRender::LINES);
- gGL.color4fv(color.mV);
- gGL.vertex3f(x, y, z - 50.f);
- gGL.vertex3f(x, y, z + 50.f);
- gGL.vertex3f(x - 2.f, y, z);
- gGL.vertex3f(x + 2.f, y, z);
- gGL.vertex3f(x, y - 2.f, z);
- gGL.vertex3f(x, y + 2.f, z);
- gl_draw_3d_line_cube(0.1f, thisline);
- gGL.end();
- }
- }
- {
- unit0->unbind(LLTexUnit::TT_TEXTURE);
- LLGLDepthTest gls_depth(GL_TRUE);
- S32 last_line_width = -1;
- for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(),
- end = mDebugBeacons.end();
- iter != end; ++iter)
- {
- const LLDebugBeacon& debug_beacon = *iter;
- S32 line_width = debug_beacon.mLineWidth;
- if (line_width != last_line_width)
- {
- gGL.flush();
- gGL.lineWidth((F32)line_width);
- last_line_width = line_width;
- }
- const LLVector3& thisline = debug_beacon.mPositionAgent;
- gGL.begin(LLRender::LINES);
- LLColor4 color = debug_beacon.mColor;
- if (gUsePBRShaders)
- {
- color = linearColor4(color);
- }
- gGL.color4fv(color.mV);
- gl_draw_3d_cross_lines(thisline, 0.5f, 0.5f, 0.5f);
- gl_draw_3d_line_cube(0.1f, thisline);
- gGL.end();
- }
- gGL.flush();
- gGL.lineWidth(1.f);
- LLHUDText* hudtp;
- for (std::vector<LLDebugBeacon>::iterator iter = mDebugBeacons.begin(),
- end = mDebugBeacons.end();
- iter != end; ++iter)
- {
- LLDebugBeacon& debug_beacon = *iter;
- if (debug_beacon.mString.empty())
- {
- continue;
- }
- hudtp = (LLHUDText*)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
- hudtp->setZCompare(false);
- LLColor4 color;
- color = debug_beacon.mTextColor;
- color.mV[3] *= 1.f;
- hudtp->setString(utf8str_to_wstring(debug_beacon.mString));
- hudtp->setColor(color);
- hudtp->setPositionAgent(debug_beacon.mPositionAgent);
- debug_beacon.mHUDObject = hudtp;
- }
- }
- stop_glerror();
- }
- ////////////////////////////////////////////////////////////////////////////
- LLViewerObjectList::OrphanInfo::OrphanInfo()
- : mParentInfo(0)
- {
- }
- LLViewerObjectList::OrphanInfo::OrphanInfo(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 mParentInfo != rhs.mParentInfo || mChildInfo != rhs.mChildInfo;
- }
- ////////////////////////////////////////////////////////////////////////////
- LLDebugBeacon::~LLDebugBeacon()
- {
- if (mHUDObject.notNull())
- {
- mHUDObject->markDead();
- }
- }
|