diff engine/core/model/structures/instancetree.cpp @ 338:d266506ff4f9

Bug fix. It turned out the instance tree contained ghost instances, since InstanceTree.removeInstance sometimes failed. This caused those random crashes in UH. Now the InstanceTree enforces that remove/add Instance work in pairs. A new Exception is raised in case this ever goes wrong again. (InconsitencyDetected) Furthermore the removeInstancheChangeListener stuff had a fix to become reentrant. It is not clear wether this was shadowed by the aforementioned bug or was never triggered.
author phoku@33b003aa-7bff-0310-803a-e67f0ece8222
date Mon, 24 Aug 2009 18:32:03 +0000
parents 90005975cdbb
children 0fd74235b34d
line wrap: on
line diff
--- a/engine/core/model/structures/instancetree.cpp	Mon Aug 24 16:06:30 2009 +0000
+++ b/engine/core/model/structures/instancetree.cpp	Mon Aug 24 18:32:03 2009 +0000
@@ -28,6 +28,7 @@
 // These includes are split up in two parts, separated by one empty line
 // First block: files included from the FIFE root src directory
 // Second block: files included from the same folder
+#include "util/base/exception.h"
 #include "model/structures/instance.h"
 #include "util/structures/rect.h"
 
@@ -44,22 +45,28 @@
 
 	bool InstanceTree::addInstance(Instance* instance) {
 		ModelCoordinate coords = instance->getLocationRef().getLayerCoordinates();
-		InstanceList& list = m_tree.find_container(coords.x,coords.y,0,0)->data();
+		InstanceTreeNode * node = m_tree.find_container(coords.x,coords.y,0,0);
+		InstanceList& list = node->data();
 		list.push_back(instance);
+		if( m_reverse.find(instance) != m_reverse.end() )
+			throw new InconsistencyDetected("Duplicate Instance.");
+		m_reverse[instance] = node;
 		return true;
 	}
 
 	bool InstanceTree::removeInstance(Instance* instance) {
 		ModelCoordinate coords = instance->getLocationRef().getLayerCoordinates();
-		InstanceList& list = m_tree.find_container(coords.x,coords.y, 0, 0)->data();
-
+		InstanceTreeNode * node = m_reverse[instance];
+		if( !node )
+			throw new InconsistencyDetected("Removing Ghost Instance.");
+		m_reverse.erase(instance);
+		InstanceList& list = node->data();
 		for(InstanceList::iterator i = list.begin(); i != list.end(); ++i) {
 			if((*i) == instance) {
 				list.erase(i);
 				return true;
 			}
 		}
-
 		return false;
 	}