diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index cea1a4a654..df620b9a08 100755 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -532,13 +532,32 @@ void AvatarManager::handleProcessedPhysicsTransaction(PhysicsEngine::Transaction } void AvatarManager::removeDeadAvatarEntities(const SetOfEntities& deadEntities) { + auto treeRenderer = DependencyManager::get(); + EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; for (auto entity : deadEntities) { - QUuid sessionID = entity->getOwningAvatarID(); - AvatarSharedPointer avatar = getAvatarBySessionID(sessionID); + QUuid entityOwnerID = entity->getOwningAvatarID(); + AvatarSharedPointer avatar = getAvatarBySessionID(entityOwnerID); + const bool REQUIRES_REMOVAL_FROM_TREE = false; if (avatar) { - const bool REQUIRES_REMOVAL_FROM_TREE = false; avatar->clearAvatarEntity(entity->getID(), REQUIRES_REMOVAL_FROM_TREE); } + if (entityTree && entity->isMyAvatarEntity()) { + entityTree->withWriteLock([&] { + // We only need to delete the direct children (rather than the descendants) because + // when the child is deleted, it will take care of its own children. If the child + // is also an avatar-entity, we'll end up back here. If it's not, the entity-server + // will take care of it in the usual way. + entity->forEachChild([&](SpatiallyNestablePointer child) { + EntityItemPointer childEntity = std::dynamic_pointer_cast(child); + if (childEntity) { + entityTree->deleteEntity(childEntity->getID(), true, true); + if (avatar) { + avatar->clearAvatarEntity(childEntity->getID(), REQUIRES_REMOVAL_FROM_TREE); + } + } + }); + }); + } } } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d91c11e726..4232e9d1b9 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3431,6 +3431,10 @@ bool EntityItem::isWearable() const { (getParentID() == DependencyManager::get()->getSessionUUID() || getParentID() == AVATAR_SELF_ID); } +bool EntityItem::isMyAvatarEntity() const { + return _hostType == entity::HostType::AVATAR && Physics::getSessionUUID() == _owningAvatarID; +}; + void EntityItem::addGrab(GrabPointer grab) { enableNoBootstrap(); SpatiallyNestable::addGrab(grab); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index ea4b11e0b0..a8c3d31344 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -503,6 +503,7 @@ public: virtual bool isWearable() const; bool isDomainEntity() const { return _hostType == entity::HostType::DOMAIN; } bool isAvatarEntity() const { return _hostType == entity::HostType::AVATAR; } + bool isMyAvatarEntity() const; bool isLocalEntity() const { return _hostType == entity::HostType::LOCAL; } entity::HostType getEntityHostType() const { return _hostType; } virtual void setEntityHostType(entity::HostType hostType) { _hostType = hostType; }