Merge pull request #8596 from huffman/feat/my-avatar-self-id

Add ability to parent overlays to MyAvatar for use across servers
This commit is contained in:
Clément Brisset 2016-10-05 12:03:01 -07:00 committed by GitHub
commit d18394f249
16 changed files with 77 additions and 50 deletions

View file

@ -682,10 +682,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
// send a location update immediately
discoverabilityManager->updateLocation();
auto myAvatar = getMyAvatar();
connect(nodeList.data(), &NodeList::nodeAdded, this, &Application::nodeAdded);
connect(nodeList.data(), &NodeList::nodeKilled, this, &Application::nodeKilled);
connect(nodeList.data(), &NodeList::nodeActivated, this, &Application::nodeActivated);
connect(nodeList.data(), &NodeList::uuidChanged, getMyAvatar(), &MyAvatar::setSessionUUID);
connect(nodeList.data(), &NodeList::uuidChanged, myAvatar.get(), &MyAvatar::setSessionUUID);
connect(nodeList.data(), &NodeList::uuidChanged, this, &Application::setSessionUUID);
connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &Application::notifyPacketVersionMismatch);
@ -715,7 +717,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount);
// Save avatar location immediately after a teleport.
connect(getMyAvatar(), &MyAvatar::positionGoneTo,
connect(myAvatar.get(), &MyAvatar::positionGoneTo,
DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
@ -752,7 +754,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent);
// send the identity packet for our avatar each second to our avatar mixer
connect(&identityPacketTimer, &QTimer::timeout, getMyAvatar(), &MyAvatar::sendIdentityPacket);
connect(&identityPacketTimer, &QTimer::timeout, myAvatar.get(), &MyAvatar::sendIdentityPacket);
identityPacketTimer.start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
const char** constArgv = const_cast<const char**>(argv);
@ -842,7 +844,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
// Tell our entity edit sender about our known jurisdictions
_entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
_entityEditSender.setMyAvatar(getMyAvatar());
_entityEditSender.setMyAvatar(myAvatar.get());
// For now we're going to set the PPS for outbound packets to be super high, this is
// probably not the right long term solution. But for now, we're going to do this to
@ -863,7 +865,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
bandwidthRecorder.data(), &BandwidthRecorder::updateInboundData);
// FIXME -- I'm a little concerned about this.
connect(getMyAvatar()->getSkeletonModel().get(), &SkeletonModel::skeletonLoaded,
connect(myAvatar->getSkeletonModel().get(), &SkeletonModel::skeletonLoaded,
this, &Application::checkSkeleton, Qt::QueuedConnection);
// Setup the userInputMapper with the actions
@ -1078,7 +1080,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
applicationUpdater->checkForUpdate();
// Now that menu is initialized we can sync myAvatar with it's state.
getMyAvatar()->updateMotionBehaviorFromMenu();
myAvatar->updateMotionBehaviorFromMenu();
// FIXME spacemouse code still needs cleanup
#if 0
@ -1113,10 +1115,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
static int SEND_STATS_INTERVAL_MS = 10000;
static int NEARBY_AVATAR_RADIUS_METERS = 10;
static glm::vec3 lastAvatarPosition = getMyAvatar()->getPosition();
static glm::vec3 lastAvatarPosition = myAvatar->getPosition();
static glm::mat4 lastHMDHeadPose = getHMDSensorPose();
static controller::Pose lastLeftHandPose = getMyAvatar()->getLeftHandPose();
static controller::Pose lastRightHandPose = getMyAvatar()->getRightHandPose();
static controller::Pose lastLeftHandPose = myAvatar->getLeftHandPose();
static controller::Pose lastRightHandPose = myAvatar->getRightHandPose();
// Periodically send fps as a user activity event
QTimer* sendStatsTimer = new QTimer(this);
@ -1165,7 +1167,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
glm::vec3 avatarPosition = getMyAvatar()->getPosition();
auto myAvatar = getMyAvatar();
glm::vec3 avatarPosition = myAvatar->getPosition();
properties["avatar_has_moved"] = lastAvatarPosition != avatarPosition;
lastAvatarPosition = avatarPosition;
@ -1183,8 +1186,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
properties["hmd_head_pose_changed"] = isHMDMode() && (hmdHeadPose != lastHMDHeadPose);
lastHMDHeadPose = hmdHeadPose;
auto leftHandPose = getMyAvatar()->getLeftHandPose();
auto rightHandPose = getMyAvatar()->getRightHandPose();
auto leftHandPose = myAvatar->getLeftHandPose();
auto rightHandPose = myAvatar->getRightHandPose();
// controller::Pose considers two poses to be different if either are invalid. In our case, we actually
// want to consider the pose to be unchanged if it was invalid and still is invalid, so we check that first.
properties["hand_pose_changed"] =
@ -1231,7 +1234,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
OctreeEditPacketSender* packetSender = entityScriptingInterface->getPacketSender();
EntityEditPacketSender* entityPacketSender = static_cast<EntityEditPacketSender*>(packetSender);
entityPacketSender->setMyAvatar(getMyAvatar());
entityPacketSender->setMyAvatar(myAvatar.get());
connect(this, &Application::applicationStateChanged, this, &Application::activeChanged);
qCDebug(interfaceapp, "Startup time: %4.2f seconds.", (double)startupTimer.elapsed() / 1000.0);
@ -1615,7 +1618,7 @@ void Application::initializeUi() {
FileScriptingInterface* fileDownload = new FileScriptingInterface(engine);
rootContext->setContextProperty("File", fileDownload);
connect(fileDownload, &FileScriptingInterface::unzipSuccess, this, &Application::showAssetServerWidget);
rootContext->setContextProperty("MyAvatar", getMyAvatar());
rootContext->setContextProperty("MyAvatar", getMyAvatar().get());
rootContext->setContextProperty("Messages", DependencyManager::get<MessagesClient>().data());
rootContext->setContextProperty("Recording", DependencyManager::get<RecordingScriptingInterface>().data());
rootContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
@ -3365,7 +3368,7 @@ void Application::init() {
entity->setCollisionSound(sound);
}
}, Qt::QueuedConnection);
connect(getMyAvatar(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) {
connect(getMyAvatar().get(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) {
if (auto avatar = getMyAvatar()) {
auto sound = DependencyManager::get<SoundCache>()->getSound(newURL);
avatar->setCollisionSound(sound);
@ -3421,7 +3424,7 @@ void Application::updateMyAvatarLookAtPosition() {
}
} else {
AvatarSharedPointer lookingAt = myAvatar->getLookAtTargetAvatar().lock();
if (lookingAt && myAvatar != lookingAt.get()) {
if (lookingAt && myAvatar.get() != lookingAt.get()) {
// If I am looking at someone else, look directly at one of their eyes
isLookingAtSomeone = true;
auto lookingAtHead = static_pointer_cast<Avatar>(lookingAt)->getHead();
@ -4270,7 +4273,7 @@ PickRay Application::computePickRay(float x, float y) const {
return result;
}
MyAvatar* Application::getMyAvatar() const {
std::shared_ptr<MyAvatar> Application::getMyAvatar() const {
return DependencyManager::get<AvatarManager>()->getMyAvatar();
}
@ -4863,7 +4866,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
scriptEngine->registerGlobalObject("Rates", new RatesScriptingInterface(this));
// hook our avatar and avatar hash map object into this script engine
scriptEngine->registerGlobalObject("MyAvatar", getMyAvatar());
scriptEngine->registerGlobalObject("MyAvatar", getMyAvatar().get());
qScriptRegisterMetaType(scriptEngine, audioListenModeToScriptValue, audioListenModeFromScriptValue);
scriptEngine->registerGlobalObject("AvatarList", DependencyManager::get<AvatarManager>().data());

View file

@ -401,7 +401,7 @@ private:
int sendNackPackets();
MyAvatar* getMyAvatar() const;
std::shared_ptr<MyAvatar> getMyAvatar() const;
void checkSkeleton() const;

View file

@ -13,6 +13,7 @@
#include <EntityTree.h>
#include <EntityTreeRenderer.h>
#include <avatar/AvatarManager.h>
#include <AvatarData.h>
#include "InterfaceParentFinder.h"
@ -45,6 +46,11 @@ SpatiallyNestableWeakPointer InterfaceParentFinder::find(QUuid parentID, bool& s
return parent;
}
if (parentID == AVATAR_SELF_ID) {
success = true;
return avatarManager->getMyAvatar();
}
success = false;
return parent;
}

View file

@ -166,7 +166,7 @@ Menu::Menu() {
// Avatar menu ----------------------------------
MenuWrapper* avatarMenu = addMenu("Avatar");
auto avatarManager = DependencyManager::get<AvatarManager>();
QObject* avatar = avatarManager->getMyAvatar();
auto avatar = avatarManager->getMyAvatar();
// Avatar > Attachments...
auto action = addActionToQMenuAndActionHash(avatarMenu, MenuOption::Attachments);
@ -182,19 +182,19 @@ Menu::Menu() {
addActionToQMenuAndActionHash(avatarSizeMenu,
MenuOption::IncreaseAvatarSize,
0, // QML Qt::Key_Plus,
avatar, SLOT(increaseSize()));
avatar.get(), SLOT(increaseSize()));
// Avatar > Size > Decrease
addActionToQMenuAndActionHash(avatarSizeMenu,
MenuOption::DecreaseAvatarSize,
0, // QML Qt::Key_Minus,
avatar, SLOT(decreaseSize()));
avatar.get(), SLOT(decreaseSize()));
// Avatar > Size > Reset
addActionToQMenuAndActionHash(avatarSizeMenu,
MenuOption::ResetAvatarSize,
0, // QML Qt::Key_Equal,
avatar, SLOT(resetSize()));
avatar.get(), SLOT(resetSize()));
// Avatar > Reset Sensors
addActionToQMenuAndActionHash(avatarMenu,
@ -517,38 +517,38 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderOtherLookAtVectors, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::FixGaze, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawDefaultPose, 0, false,
avatar, SLOT(setEnableDebugDrawDefaultPose(bool)));
avatar.get(), SLOT(setEnableDebugDrawDefaultPose(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawAnimPose, 0, false,
avatar, SLOT(setEnableDebugDrawAnimPose(bool)));
avatar.get(), SLOT(setEnableDebugDrawAnimPose(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawPosition, 0, false,
avatar, SLOT(setEnableDebugDrawPosition(bool)));
avatar.get(), SLOT(setEnableDebugDrawPosition(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::MeshVisible, 0, true,
avatar, SLOT(setEnableMeshVisible(bool)));
avatar.get(), SLOT(setEnableMeshVisible(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::TurnWithHead, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::UseAnimPreAndPostRotations, 0, true,
avatar, SLOT(setUseAnimPreAndPostRotations(bool)));
avatar.get(), SLOT(setUseAnimPreAndPostRotations(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableInverseKinematics, 0, true,
avatar, SLOT(setEnableInverseKinematics(bool)));
avatar.get(), SLOT(setEnableInverseKinematics(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSensorToWorldMatrix, 0, false,
avatar, SLOT(setEnableDebugDrawSensorToWorldMatrix(bool)));
avatar.get(), SLOT(setEnableDebugDrawSensorToWorldMatrix(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ActionMotorControl,
Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu()),
Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar.get(), SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ScriptedMotorControl, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()),
avatar.get(), SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableCharacterController, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()),
avatar.get(), SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
// Developer > Hands >>>
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false,
avatar, SLOT(setEnableDebugDrawHandControllers(bool)));
avatar.get(), SLOT(setEnableDebugDrawHandControllers(bool)));
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LowVelocityFilter, 0, true,
qApp, SLOT(setLowVelocityFilter(bool)));

View file

@ -48,7 +48,7 @@ AvatarActionHold::~AvatarActionHold() {
}
bool AvatarActionHold::getAvatarRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr;
if (!controller) {
qDebug() << "AvatarActionHold::getAvatarRigidBodyLocation failed to get character controller";

View file

@ -31,6 +31,7 @@
#include <SettingHandle.h>
#include <UsersScriptingInterface.h>
#include <UUID.h>
#include <AvatarData.h>
#include "Application.h"
#include "Avatar.h"
@ -323,7 +324,7 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
// an id of null. Thus this code handles any collision in which one of the participating objects is
// my avatar. (Other user machines will make a similar analysis and inject sound for their collisions.)
if (collision.idA.isNull() || collision.idB.isNull()) {
MyAvatar* myAvatar = getMyAvatar();
auto myAvatar = getMyAvatar();
auto collisionSound = myAvatar->getCollisionSound();
if (collisionSound) {
const auto characterController = myAvatar->getCharacterController();
@ -399,7 +400,7 @@ void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) {
AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) {
if (sessionID == _myAvatar->getSessionUUID()) {
if (sessionID == AVATAR_SELF_ID || sessionID == _myAvatar->getSessionUUID()) {
return _myAvatar;
}

View file

@ -39,7 +39,7 @@ public:
void init();
MyAvatar* getMyAvatar() { return _myAvatar.get(); }
std::shared_ptr<MyAvatar> getMyAvatar() { return _myAvatar; }
AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) override;
void updateMyAvatar(float deltaTime);

View file

@ -79,7 +79,7 @@ bool HMDScriptingInterface::getHUDLookAtPosition3D(glm::vec3& result) const {
}
glm::mat4 HMDScriptingInterface::getWorldHMDMatrix() const {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
return myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
}

View file

@ -43,7 +43,7 @@ bool OverlayConductor::headOutsideOverlay() const {
bool OverlayConductor::updateAvatarIsAtRest() {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
const quint64 REST_ENABLE_TIME_USECS = 1000 * 1000; // 1 s
const quint64 REST_DISABLE_TIME_USECS = 200 * 1000; // 200 ms
@ -69,7 +69,7 @@ bool OverlayConductor::updateAvatarIsAtRest() {
}
bool OverlayConductor::updateAvatarHasDriveInput() {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
const quint64 DRIVE_ENABLE_TIME_USECS = 200 * 1000; // 200 ms
const quint64 DRIVE_DISABLE_TIME_USECS = 1000 * 1000; // 1 s
@ -103,7 +103,7 @@ void OverlayConductor::update(float dt) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
bool currentVisible = !offscreenUi->getDesktop()->property("pinned").toBool();
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
// centerUI when hmd mode is first enabled and mounted
if (qApp->isHMDMode() && qApp->getActiveDisplayPlugin()->isDisplayVisible()) {
if (!_hmdMode) {

View file

@ -32,7 +32,7 @@
void setupPreferences() {
auto preferences = DependencyManager::get<Preferences>();
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
static const QString AVATAR_BASICS { "Avatar Basics" };
{
auto getter = [=]()->QString { return myAvatar->getDisplayName(); };

View file

@ -170,7 +170,7 @@ void Stats::updateStats(bool force) {
STAT_UPDATE(entitiesPing, octreeServerCount ? totalPingOctree / octreeServerCount : -1);
// Third column, avatar stats
MyAvatar* myAvatar = avatarManager->getMyAvatar();
auto myAvatar = avatarManager->getMyAvatar();
glm::vec3 avatarPos = myAvatar->getPosition();
STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z));
STAT_UPDATE_FLOAT(speed, glm::length(myAvatar->getVelocity()), 0.01f);

View file

@ -64,7 +64,7 @@ namespace render {
if (args) {
if (overlay->getAnchor() == Overlay::MY_AVATAR) {
auto batch = args->_batch;
MyAvatar* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
glm::quat myAvatarRotation = avatar->getOrientation();
glm::vec3 myAvatarPosition = avatar->getPosition();
float angle = glm::degrees(glm::angle(myAvatarRotation));

View file

@ -55,6 +55,7 @@ typedef unsigned long long quint64;
#include <NumericalConstants.h>
#include <Packed.h>
#include <ThreadSafeValueCache.h>
#include <SharedUtil.h>
#include "AABox.h"
#include "HeadData.h"
@ -138,10 +139,6 @@ class AttachmentData;
class Transform;
using TransformPointer = std::shared_ptr<Transform>;
// When writing out avatarEntities to a QByteArray, if the parentID is the ID of MyAvatar, use this ID instead. This allows
// the value to be reset when the sessionID changes.
const QUuid AVATAR_SELF_ID = QUuid("{00000000-0000-0000-0000-000000000001}");
class AvatarData : public QObject, public SpatiallyNestable {
Q_OBJECT

View file

@ -12,6 +12,7 @@
#include "EntityItemID.h"
#include <VariantMapToScriptValue.h>
#include <SharedUtil.h>
#include <SpatialParentFinder.h>
#include "EntitiesLogging.h"
@ -181,6 +182,11 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
propertiesWithSimID.setOwningAvatarID(myNodeID);
}
if (propertiesWithSimID.getParentID() == AVATAR_SELF_ID) {
qDebug() << "ERROR: Cannot set entity parent ID to the local-only MyAvatar ID";
propertiesWithSimID.setParentID(QUuid());
}
auto dimensions = propertiesWithSimID.getDimensions();
float volume = dimensions.x * dimensions.y * dimensions.z;
auto density = propertiesWithSimID.getDensity();
@ -357,6 +363,9 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
if (!scriptSideProperties.parentIDChanged()) {
properties.setParentID(entity->getParentID());
} else if (scriptSideProperties.getParentID() == AVATAR_SELF_ID) {
qDebug() << "ERROR: Cannot set entity parent ID to the local-only MyAvatar ID";
properties.setParentID(QUuid());
}
if (!scriptSideProperties.parentJointIndexChanged()) {
properties.setParentJointIndex(entity->getParentJointIndex());

View file

@ -23,6 +23,12 @@
#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
#include <QUuid>
// When writing out avatarEntities to a QByteArray, if the parentID is the ID of MyAvatar, use this ID instead. This allows
// the value to be reset when the sessionID changes.
const QUuid AVATAR_SELF_ID = QUuid("{00000000-0000-0000-0000-000000000001}");
// Access to the global instance pointer to enable setting / unsetting
template <typename T>

View file

@ -12,6 +12,7 @@
#include <QQueue>
#include "DependencyManager.h"
#include "SharedUtil.h"
#include "SpatiallyNestable.h"
const float defaultAACubeSize = 1.0f;
@ -856,7 +857,11 @@ QList<SpatiallyNestablePointer> SpatiallyNestable::getChildren() const {
_childrenLock.withReadLock([&] {
foreach(SpatiallyNestableWeakPointer childWP, _children.values()) {
SpatiallyNestablePointer child = childWP.lock();
if (child && child->_parentKnowsMe && child->getParentID() == getID()) {
// An object can set MyAvatar to be its parent using two IDs: the session ID and the special AVATAR_SELF_ID
// Because we only recognize an object as having one ID, we need to check for the second possible ID here.
// In practice, the AVATAR_SELF_ID should only be used for local-only objects.
if (child && child->_parentKnowsMe && (child->getParentID() == getID() ||
(getNestableType() == NestableType::Avatar && child->getParentID() == AVATAR_SELF_ID))) {
children << child;
}
}