141 lines · 5.7 KB · C++
RawDownload
////  DeleteEntityOperator.cpp//  libraries/entities/src////  Created by Brad Hefta-Gaub on 8/11/2014.//  Copyright 2014 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #include "DeleteEntityOperator.h" #include "EntityItem.h"#include "EntityTree.h"#include "EntityTreeElement.h"#include "EntitiesLogging.h" DeleteEntityOperator::DeleteEntityOperator(EntityTreePointer tree, const EntityItemID& searchEntityID) :    _tree(tree),    _changeTime(usecTimestampNow()),    _foundCount(0),    _lookingCount(0){    addEntityIDToDeleteList(searchEntityID);} DeleteEntityOperator::~DeleteEntityOperator() {} DeleteEntityOperator::DeleteEntityOperator(EntityTreePointer tree) :    _tree(tree),    _changeTime(usecTimestampNow()),    _foundCount(0),    _lookingCount(0){} void DeleteEntityOperator::addEntityIDToDeleteList(const EntityItemID& searchEntityID) {    // check our tree, to determine if this entity is known    EntityToDeleteDetails details;    details.containingElement = _tree->getContainingElement(searchEntityID);    if (details.containingElement) {        details.entity = details.containingElement->getEntityWithEntityItemID(searchEntityID);        if (!details.entity) {            //assert(false);            qCDebug(entities) << "that's UNEXPECTED, we got a _containingElement, but couldn't find the oldEntity!";        } else {            details.cube = details.containingElement->getAACube();            _entitiesToDelete << details;            _lookingCount++;        }    }} void DeleteEntityOperator::addEntityToDeleteList(const EntityItemPointer& entity) {    assert(entity && entity->getElement());    EntityToDeleteDetails details;    details.entity = entity;    details.containingElement = entity->getElement();    details.cube = details.containingElement->getAACube();    _entitiesToDelete << details;    _lookingCount++;} // does this entity tree element contain the old entitybool DeleteEntityOperator::subTreeContainsSomeEntitiesToDelete(const OctreeElementPointer& element) {    bool containsEntity = false;     // If we don't have an old entity, then we don't contain the entity, otherwise    // check the bounds    if (_entitiesToDelete.size() > 0) {        const AACube& elementCube = element->getAACube();        foreach(const EntityToDeleteDetails& details, _entitiesToDelete) {            if (elementCube.contains(details.cube)) {                containsEntity = true;                break; // if it contains at least one, we're good to go            }        }    }    return containsEntity;} bool DeleteEntityOperator::preRecursion(const OctreeElementPointer& element) {    EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);     // In Pre-recursion, we're generally deciding whether or not we want to recurse this    // path of the tree. For this operation, we want to recurse the branch of the tree if:    //   * We have not yet found the all entities, and     //   * this branch contains our some of the entities we're looking for.        bool keepSearching = false; // assume we don't need to search any more        // If we haven't yet found all the entities, and this sub tree contains at least one of our    // entities, then we need to keep searching.    if ((_foundCount < _lookingCount) && subTreeContainsSomeEntitiesToDelete(element)) {         // check against each of our search entities        foreach(const EntityToDeleteDetails& details, _entitiesToDelete) {             // If this is the element we're looking for, then ask it to remove the old entity            // and we can stop searching.            if (entityTreeElement == details.containingElement) {                EntityItemPointer theEntity = details.entity;                bool entityDeleted = entityTreeElement->removeEntityItem(theEntity, true); // remove it from the element                assert(entityDeleted);                (void)entityDeleted; // quiet warning about unused variable                _tree->clearEntityMapEntry(details.entity->getEntityItemID());                _foundCount++;            }        }                // if we haven't found all of our search for entities, then keep looking        keepSearching = (_foundCount < _lookingCount);    }     return keepSearching; // if we haven't yet found it, keep looking} bool DeleteEntityOperator::postRecursion(const OctreeElementPointer& element) {    // Post-recursion is the unwinding process. For this operation, while we    // unwind we want to mark the path as being dirty if we changed it below.    // We might have two paths, one for the old entity and one for the new entity.    bool keepSearching = (_foundCount < _lookingCount);     // As we unwind, if we're in either of these two paths, we mark our element    // as dirty.    if ((subTreeContainsSomeEntitiesToDelete(element))) {        element->markWithChangedTime();    }        // It should always be ok to prune children. Because we are only in this PostRecursion function if    // we've already finished processing all of the children of this current element. If any of those    // children are the containing element for any entity in our lists of entities to delete, then they    // must have already deleted the entity, and they are safe to prune. Since this operation doesn't    // ever add any elements we don't have to worry about memory being reused within this recursion pass.    EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);    entityTreeElement->pruneChildren(); // take this opportunity to prune any empty leaves    return keepSearching; // if we haven't yet found it, keep looking}