overte-JulianGro/libraries/entities/src/AddEntityOperator.cpp

93 lines
3.7 KiB
C++

//
// AddEntityOperator.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 "EntityItem.h"
#include "EntityTree.h"
#include "EntityTreeElement.h"
#include "AddEntityOperator.h"
AddEntityOperator::AddEntityOperator(EntityTreePointer tree, EntityItemPointer newEntity) :
_tree(tree),
_newEntity(newEntity),
_foundNew(false),
_changeTime(usecTimestampNow()),
_newEntityBox()
{
// caller must have verified existence of newEntity
assert(_newEntity);
bool success;
auto queryCube = _newEntity->getQueryAACube(success);
_newEntityBox = queryCube.clamp((float)(-HALF_TREE_SCALE), (float)HALF_TREE_SCALE);
}
bool AddEntityOperator::preRecursion(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
// any of the following are true:
// * We have not yet found the location for the new entity, and this branch contains the bounds of the new entity
bool keepSearching = false; // assume we don't need to search any more
// If we haven't yet found the new entity, and this subTreeContains our new
// entity, then we need to keep searching.
if (!_foundNew && element->getAACube().contains(_newEntityBox)) {
// If this element is the best fit for the new entity properties, then add/or update it
if (entityTreeElement->bestFitBounds(_newEntityBox)) {
entityTreeElement->addEntityItem(_newEntity);
_tree->setContainingElement(_newEntity->getEntityItemID(), entityTreeElement);
_foundNew = true;
keepSearching = false;
} else {
keepSearching = true;
}
}
return keepSearching; // if we haven't yet found it, keep looking
}
bool AddEntityOperator::postRecursion(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 = !_foundNew;
// As we unwind, if we're in either of these two paths, we mark our element
// as dirty.
if ((_foundNew && element->getAACube().contains(_newEntityBox))) {
element->markWithChangedTime();
}
return keepSearching; // if we haven't yet found it, keep looking
}
OctreeElementPointer AddEntityOperator::possiblyCreateChildAt(OctreeElementPointer element, int childIndex) {
// If we're getting called, it's because there was no child element at this index while recursing.
// We only care if this happens while still searching for the new entity location.
// Check to see if
if (!_foundNew) {
float childElementScale = element->getAACube().getScale() / 2.0f; // all of our children will be half our scale
// if the scale of our desired cube is smaller than our children, then consider making a child
if (_newEntityBox.getLargestDimension() <= childElementScale) {
int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntityBox);
if (childIndex == indexOfChildContainingNewEntity) {
return element->addChildAtIndex(childIndex);
}
}
}
return NULL;
}