From 0a2fb77698143db3e61776484998fada944c610e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 13 Mar 2016 07:04:50 -0700 Subject: [PATCH] delete child entities when parent is deleted --- .../src/entities/EntityServer.cpp | 12 ++++++++++ assignment-client/src/entities/EntityServer.h | 2 ++ assignment-client/src/octree/OctreeServer.h | 4 ++-- libraries/entities/src/EntityTree.cpp | 23 +++++++++++++++++++ libraries/entities/src/EntityTree.h | 11 +++++++-- 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index b177d2a9a0..867412f6c0 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -272,6 +272,18 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio tree->setWantTerseEditLogging(wantTerseEditLogging); } +void EntityServer::nodeAdded(SharedNodePointer node) { + EntityTreePointer tree = std::static_pointer_cast(_tree); + tree->knowAvatarID(node->getUUID()); + OctreeServer::nodeAdded(node); +} + +void EntityServer::nodeKilled(SharedNodePointer node) { + EntityTreePointer tree = std::static_pointer_cast(_tree); + tree->deleteDescendantsOfAvatar(node->getUUID()); + tree->forgetAvatarID(node->getUUID()); + OctreeServer::nodeKilled(node); +} // FIXME - this stats tracking is somewhat temporary to debug the Whiteboard issues. It's not a bad // set of stats to have, but we'd probably want a different data structure if we keep it very long. diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index 74057bfa5d..ec58cda6cd 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -58,6 +58,8 @@ public: virtual void trackViewerGone(const QUuid& sessionID) override; public slots: + virtual void nodeAdded(SharedNodePointer node); + virtual void nodeKilled(SharedNodePointer node); void pruneDeletedEntities(); protected: diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 1430715571..c96c4bb5ad 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -127,8 +127,8 @@ public: public slots: /// runs the octree server assignment void run(); - void nodeAdded(SharedNodePointer node); - void nodeKilled(SharedNodePointer node); + virtual void nodeAdded(SharedNodePointer node); + virtual void nodeKilled(SharedNodePointer node); void sendStatsPacket(); private slots: diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 4c3412edd3..416fc5add3 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -448,6 +448,18 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) const RemovedEntities& entities = theOperator.getEntities(); foreach(const EntityToDeleteDetails& details, entities) { EntityItemPointer theEntity = details.entity; + + qDebug() << "processRemovedEntities on " << theEntity->getID() << theEntity->getName(); + if (getIsServer()) { + QSet childrenIDs; + theEntity->forEachChild([&](SpatiallyNestablePointer child) { + if (child->getNestableType() == NestableType::Entity) { + childrenIDs += child->getID(); + } + }); + deleteEntities(childrenIDs, true, true); + } + theEntity->die(); if (getIsServer()) { @@ -1000,6 +1012,10 @@ void EntityTree::fixupMissingParents() { moveOperator.addEntityToMoveList(entity, newCube); iter.remove(); entity->markAncestorMissing(false); + } else if (_avatarIDs.contains(entity->getParentID())) { + _childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID(); + iter.remove(); + entity->markAncestorMissing(false); } } else { // entity was deleted before we found its parent. @@ -1014,6 +1030,13 @@ void EntityTree::fixupMissingParents() { } +void EntityTree::deleteDescendantsOfAvatar(QUuid avatarID) { + if (_childrenOfAvatars.contains(avatarID)) { + deleteEntities(_childrenOfAvatars[avatarID]); + _childrenOfAvatars.remove(avatarID); + } +} + void EntityTree::update() { fixupMissingParents(); if (_simulation) { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 8190f7225b..1c5a696b17 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -241,6 +241,10 @@ public: Q_INVOKABLE int getJointIndex(const QUuid& entityID, const QString& name) const; Q_INVOKABLE QStringList getJointNames(const QUuid& entityID) const; + void knowAvatarID(QUuid avatarID) { _avatarIDs += avatarID; } + void forgetAvatarID(QUuid avatarID) { _avatarIDs -= avatarID; } + void deleteDescendantsOfAvatar(QUuid avatarID); + public slots: void callLoader(EntityItemID entityID); @@ -313,8 +317,11 @@ protected: quint64 _maxEditDelta = 0; quint64 _treeResetTime = 0; - void fixupMissingParents(); - QVector _missingParent; + void fixupMissingParents(); // try to hook members of _missingParent to parent instances + QVector _missingParent; // entites with a parentID but no (yet) known parent instance + // we maintain a list of avatarIDs to notice when an entity is a child of one. + QSet _avatarIDs; // IDs of avatars connected to entity server + QHash> _childrenOfAvatars; // which entities are children of which avatars }; #endif // hifi_EntityTree_h