change DeleteModelOperator to handle multiple deletes in single pass

This commit is contained in:
ZappoMan 2014-06-25 16:47:46 -07:00
parent 5d4ce73499
commit 750ee639f0

View file

@ -274,54 +274,87 @@ void ModelTree::addModel(const ModelItemID& modelID, const ModelItemProperties&
storeModel(updateItem); storeModel(updateItem);
} }
class ModelToDeleteDetails {
public:
const ModelItem* model;
AACube cube;
ModelTreeElement* containingElement;
};
inline uint qHash(const ModelToDeleteDetails& a, uint seed) {
return qHash(a.model->getModelItemID(), seed);
}
inline bool operator==(const ModelToDeleteDetails& a, const ModelToDeleteDetails& b) {
return a.model->getModelItemID() == b.model->getModelItemID();
}
class DeleteModelOperator : public RecurseOctreeOperator { class DeleteModelOperator : public RecurseOctreeOperator {
public: public:
DeleteModelOperator(ModelTree* tree);
DeleteModelOperator(ModelTree* tree, const ModelItemID& searchModelID); DeleteModelOperator(ModelTree* tree, const ModelItemID& searchModelID);
void modelToDelete(const ModelItemID& searchModelID);
virtual bool PreRecursion(OctreeElement* element); virtual bool PreRecursion(OctreeElement* element);
virtual bool PostRecursion(OctreeElement* element); virtual bool PostRecursion(OctreeElement* element);
private: private:
ModelTree* _tree; ModelTree* _tree;
const ModelItem* _oldModel; QSet<ModelToDeleteDetails> _modelsToDelete;
AACube _oldModelCube;
ModelTreeElement* _containingElement;
bool _foundOld;
quint64 _changeTime; quint64 _changeTime;
bool subTreeContainsOldModel(OctreeElement* element); int _foundCount;
bool subTreeContainsNewModel(OctreeElement* element); int _lookingCount;
bool subTreeContainsSomeModelsToDelete(OctreeElement* element);
}; };
DeleteModelOperator::DeleteModelOperator(ModelTree* tree, const ModelItemID& searchModelID) : DeleteModelOperator::DeleteModelOperator(ModelTree* tree, const ModelItemID& searchModelID) :
_tree(tree), _tree(tree),
_oldModel(NULL), _changeTime(usecTimestampNow()),
_containingElement(NULL), _foundCount(0),
_foundOld(false), _lookingCount(0)
_changeTime(usecTimestampNow())
{ {
modelToDelete(searchModelID);
}
DeleteModelOperator::DeleteModelOperator(ModelTree* tree) :
_tree(tree),
_changeTime(usecTimestampNow()),
_foundCount(0),
_lookingCount(0)
{
}
void DeleteModelOperator::modelToDelete(const ModelItemID& searchModelID) {
// check our tree, to determine if this model is known // check our tree, to determine if this model is known
_containingElement = _tree->getContainingElement(searchModelID); ModelToDeleteDetails details;
if (_containingElement) { details.containingElement = _tree->getContainingElement(searchModelID);
_oldModel = _containingElement->getModelWithModelItemID(searchModelID);
if (!_oldModel) { if (details.containingElement) {
//assert(_oldModel); details.model = details.containingElement->getModelWithModelItemID(searchModelID);
if (!details.model) {
//assert(false);
qDebug() << "that's UNEXPECTED, we got a _containingElement, but couldn't find the oldModel!"; qDebug() << "that's UNEXPECTED, we got a _containingElement, but couldn't find the oldModel!";
} else {
details.cube = details.model->getAACube();
_modelsToDelete << details;
_lookingCount++;
} }
_oldModelCube = _oldModel->getAACube();
} else {
// if the old model is not known, then we can consider if found, and
// we'll only be searching for the new location
_foundOld = true;
} }
} }
// does this model tree element contain the old model // does this model tree element contain the old model
bool DeleteModelOperator::subTreeContainsOldModel(OctreeElement* element) { bool DeleteModelOperator::subTreeContainsSomeModelsToDelete(OctreeElement* element) {
bool containsModel = false; bool containsModel = false;
// If we don't have an old model, then we don't contain the model, otherwise // If we don't have an old model, then we don't contain the model, otherwise
// check the bounds // check the bounds
if (_oldModel) { if (_modelsToDelete.size() > 0) {
AACube elementCube = element->getAACube(); AACube elementCube = element->getAACube();
containsModel = elementCube.contains(_oldModelCube); foreach(const ModelToDeleteDetails& details, _modelsToDelete) {
if (elementCube.contains(details.cube)) {
containsModel = true;
break; // if it contains at least one, we're good to go
}
}
} }
return containsModel; return containsModel;
} }
@ -340,23 +373,27 @@ bool DeleteModelOperator::PreRecursion(OctreeElement* element) {
bool keepSearching = false; // assume we don't need to search any more bool keepSearching = false; // assume we don't need to search any more
// If we haven't yet found the old model, and this subTreeContains our old // If we haven't yet found all the models, and this sub tree contains at least one of our
// model, then we need to keep searching. // models, then we need to keep searching.
if (!_foundOld && subTreeContainsOldModel(element)) { if ((_foundCount < _lookingCount) && subTreeContainsSomeModelsToDelete(element)) {
// If this is the element we're looking for, then ask it to remove the old model // check against each of our search models
// and we can stop searching. foreach(const ModelToDeleteDetails& details, _modelsToDelete) {
if (modelTreeElement == _containingElement) {
// This is a good place to delete it!!! // If this is the element we're looking for, then ask it to remove the old model
ModelItemID modelItemID = _oldModel->getModelItemID(); // and we can stop searching.
modelTreeElement->removeModelWithModelItemID(modelItemID); if (modelTreeElement == details.containingElement) {
_tree->setContainingElement(modelItemID, NULL);
_foundOld = true; // This is a good place to delete it!!!
} else { ModelItemID modelItemID = details.model->getModelItemID();
// if this isn't the element we're looking for, then keep searching modelTreeElement->removeModelWithModelItemID(modelItemID);
keepSearching = true; _tree->setContainingElement(modelItemID, NULL);
_foundCount++;
}
} }
// if we haven't found all of our search for models, then keep looking
keepSearching = (_foundCount < _lookingCount);
} }
return keepSearching; // if we haven't yet found it, keep looking return keepSearching; // if we haven't yet found it, keep looking
@ -366,11 +403,11 @@ bool DeleteModelOperator::PostRecursion(OctreeElement* element) {
// Post-recursion is the unwinding process. For this operation, while we // 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. // unwind we want to mark the path as being dirty if we changed it below.
// We might have two paths, one for the old model and one for the new model. // We might have two paths, one for the old model and one for the new model.
bool keepSearching = !_foundOld; bool keepSearching = (_foundCount < _lookingCount);
// As we unwind, if we're in either of these two paths, we mark our element // As we unwind, if we're in either of these two paths, we mark our element
// as dirty. // as dirty.
if ((_foundOld && subTreeContainsOldModel(element))) { if ((subTreeContainsSomeModelsToDelete(element))) {
element->markWithChangedTime(); element->markWithChangedTime();
} }
return keepSearching; // if we haven't yet found it, keep looking return keepSearching; // if we haven't yet found it, keep looking