void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) { if (gNoRender) { return; } if (objectp->isDead()) { llwarns << "Trying to find orphans for dead obj " << objectp->mID << ":" << objectp->getPCodeString() << llendl; return; } // 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 (0 == mOrphanParents.count()) { // no known orphan parents return; } if (-1 == mOrphanParents.find(getIndex(objectp->mLocalID, ip, port))) { // did not find objectp in OrphanParent list return; } S32 i; U64 parent_info = getIndex(objectp->mLocalID, ip, port); BOOL orphans_found = FALSE; // Iterate through the orphan list, and set parents of matching children. for (i = 0; i < mOrphanChildren.count(); i++) { if (mOrphanChildren[i].mParentInfo != parent_info) { continue; } LLViewerObject *childp = findObject(mOrphanChildren[i].mChildInfo); if (childp) { if (childp == objectp) { llwarns << objectp->mID << " has self as parent, skipping!" << llendl; continue; } #ifdef ORPHAN_SPAM llinfos << "Reunited parent " << objectp->mID << " with child " << childp->mID << llendl; llinfos << "Glob: " << objectp->getPositionGlobal() << llendl; llinfos << "Agent: " << objectp->getPositionAgent() << llendl; 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->setState(LLDrawable::CLEAR_INVISIBLE); childp->setDrawableParent(objectp->mDrawable); // LLViewerObjectList::findOrphans() } // Make certain particles, icon and HUD aren't hidden childp->hideExtraDisplayItems( FALSE ); objectp->addChild(childp); orphans_found = TRUE; } else { llinfos << "Missing orphan child, removing from list" << llendl; mOrphanChildren.remove(i); i--; } } // Remove orphan parent and children from lists now that they've been found mOrphanParents.remove(mOrphanParents.find(parent_info)); i = 0; while (i < mOrphanChildren.count()) { if (mOrphanChildren[i].mParentInfo == parent_info) { mOrphanChildren.remove(i); mNumOrphans--; } else { i++; } } 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); } } }