mirror of
https://github.com/overte-org/overte.git
synced 2025-07-15 21:16:39 +02:00
change DeleteModelOperator to handle multiple deletes in single pass
This commit is contained in:
parent
5d4ce73499
commit
750ee639f0
1 changed files with 77 additions and 40 deletions
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue