From 0a2fb77698143db3e61776484998fada944c610e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 13 Mar 2016 07:04:50 -0700 Subject: [PATCH 1/3] 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 From 415f21c189a7dbf79530fda644161036afba3641 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 13 Mar 2016 08:35:21 -0700 Subject: [PATCH 2/3] be more aggressive about putting entities into the missing-its-parent list --- libraries/entities/src/EntityTree.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 416fc5add3..82cef91ca5 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -86,6 +86,11 @@ void EntityTree::postAddEntity(EntityItemPointer entity) { if (_simulation) { _simulation->addEntity(entity); } + + if (!entity->isParentIDValid()) { + _missingParent.append(entity); + } + _isDirty = true; maybeNotifyNewCollisionSoundURL("", entity->getCollisionSoundURL()); emit addingEntity(entity->getEntityItemID()); @@ -252,6 +257,9 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI _missingParent.append(childEntity); continue; } + if (!childEntity->isParentIDValid()) { + _missingParent.append(childEntity); + } UpdateEntityOperator theChildOperator(getThisPointer(), containingElement, childEntity, queryCube); recurseTreeWithOperator(&theChildOperator); @@ -1004,15 +1012,20 @@ void EntityTree::fixupMissingParents() { EntityItemWeakPointer entityWP = iter.next(); EntityItemPointer entity = entityWP.lock(); if (entity) { - bool success; - AACube newCube = entity->getQueryAACube(success); - if (success) { - // this entity's parent (or ancestry) was previously not fully known, and now is. Update its - // location in the EntityTree. + if (entity->isParentIDValid()) { + // this entity's parent was previously not known, and now is. Update its location in the EntityTree... + bool success; + AACube newCube = entity->getQueryAACube(success); + if (!success) { + continue; + } moveOperator.addEntityToMoveList(entity, newCube); iter.remove(); entity->markAncestorMissing(false); } else if (_avatarIDs.contains(entity->getParentID())) { + if (!_childrenOfAvatars.contains(entity->getParentID())) { + _childrenOfAvatars[entity->getParentID()] = QSet(); + } _childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID(); iter.remove(); entity->markAncestorMissing(false); From 7641b1e99d6d649e97da3795a18a36bc753e9480 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 13 Mar 2016 08:45:23 -0700 Subject: [PATCH 3/3] remove debug print --- libraries/entities/src/EntityTree.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 82cef91ca5..34ed55e0bb 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -457,7 +457,6 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) foreach(const EntityToDeleteDetails& details, entities) { EntityItemPointer theEntity = details.entity; - qDebug() << "processRemovedEntities on " << theEntity->getID() << theEntity->getName(); if (getIsServer()) { QSet childrenIDs; theEntity->forEachChild([&](SpatiallyNestablePointer child) {