Commits

Anonymous committed 0d79dc7

split levelobjects into model and view

Comments (0)

Files changed (20)

media/editor/editor.material

     {
       	pass
       	{
+			depth_write off
+			depth_func always_pass
 			polygon_mode wireframe
 	        texture_unit
 	        {
     {
       	pass
       	{
+			depth_write off
+			depth_func always_pass
 			polygon_mode wireframe
 	        texture_unit
 	        {
     {
       	pass
       	{
+			depth_write off
+			depth_func always_pass
 			polygon_mode wireframe
 	        texture_unit
 	        {

src/GameObjects/CCharacter.cpp

 
 	// walk/jump/fall
 	if (goLevel != NULL) {
-		Ogre::Rectangle boundingRect;
+		Game::Rectangle boundingRect;
 		Ogre::Vector3 position = GetPosition();
-		boundingRect.left = position.z - bounds.left;
-		boundingRect.right = position.z + bounds.right;
-		boundingRect.top = position.y + bounds.top;
-		boundingRect.bottom = position.y - bounds.bottom;
+		boundingRect.SetExtends(position.z - bounds.left, position.y - bounds.bottom,
+				position.z + bounds.right, position.y + bounds.top);
 
 		// make temporary levelobject
-		GameObjects::PLevelObject temp(new GameObjects::CLevelObject(GetPosition()));
-		Ogre::AxisAlignedBox bbox;
-		bbox.setExtents(-1, boundingRect.bottom, boundingRect.left, 1, boundingRect.top, boundingRect.right );
-		temp->SetBoundingBox(bbox);
+		GameObjects::PLevelObject temp(new GameObjects::CLevelObject(Ogre::Vector2(GetPosition().z, GetPosition().y)));
+		temp->SetBoundingBox(boundingRect);
 
 
 		if (!bJumping) {
 			// EXPERIMENTAL: stairs
 
 			translation = goLevel->ResolveCollision(temp, Ogre::Vector2(0, 4.0f));
-			temp->SetPosition(temp->GetPosition() + Ogre::Vector3(0.0f, translation.y, translation.x));
+			temp->SetPosition(temp->GetPosition() + translation);
 
 			Ogre::Vector2 trans = goLevel->ResolveCollision(temp, Ogre::Vector2(deltaTime*fSpeed, 0));
-			temp->SetPosition(temp->GetPosition() + Ogre::Vector3(0.0f, trans.y, trans.x));
+			temp->SetPosition(temp->GetPosition() + trans);
 
 			translation = translation+trans;
 

src/GameObjects/CLevelData.cpp

 CLevelData::~CLevelData() {
 }
 
-Ogre::Rectangle CLevelData::Collision(const Ogre::Rectangle& rect, float range) {
-	Ogre::Rectangle constraints;
-	constraints.right = constraints.top = constraints.bottom = std::numeric_limits<Ogre::Real>::infinity();
-	constraints.left = constraints.bottom = -std::numeric_limits<Ogre::Real>::infinity();
-
-	/* TODO implement as quadtree
-	Ogre::Rectangle rangeRect;
-	rangeRect.left = rect.left - range;
-	rangeRect.right = rect.right + range;
-	rangeRect.top = rect.top + range;
-	rangeRect.bottom = rect.bottom - range;
-
-*/
-
-	Ogre::Rectangle objConstraints;
-
-	// collide with static geometry
-	for (LevelObjectListItor it = staticLevelData.begin(); it != staticLevelData.end(); ++it) {
-		PLevelObject obj(*it);
-
-		objConstraints = obj->GetConstraints(rect);
-
-		if (objConstraints.left > constraints.left)
-			constraints.left = objConstraints.left;
-
-		if (objConstraints.right < constraints.right)
-			constraints.right = objConstraints.right;
-
-		if (objConstraints.top < constraints.top)
-			constraints.top = objConstraints.top;
-
-		if (objConstraints.bottom > constraints.bottom)
-			constraints.bottom = objConstraints.bottom;
-	}
-
-	return constraints;
-}
-
 void CLevelData::ClearData() {
 	staticLevelData.clear();
 	dynamicLevelData.clear();
 	}
 }
 
+void CLevelData::InsertView(POgreEntityView view, ObjectType type) {
+	ogreViews.push_back(view);
+}
+
 Ogre::SceneNode* CLevelData::Draw(Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode) {
 	Ogre::SceneNode* node = NULL;
 	if (ogreNode == NULL)
 	else
 		node = ogreNode->createChildSceneNode(Ogre::Vector3::ZERO);
 
-	for (LevelObjectListItor it = staticLevelData.begin(); it != staticLevelData.end(); ++it) {
-		PLevelObject obj(*it);
-		if (obj->IsOgreObject())
-			static_cast<COgreLevelObject*>(obj.get())->Draw(ogreScene, node);
-	}
-
-	for (LevelObjectListItor it = backgroundLevelData.begin(); it != backgroundLevelData.end(); ++it) {
-		PLevelObject obj(*it);
-		if (obj->IsOgreObject())
-			static_cast<COgreLevelObject*>(obj.get())->Draw(ogreScene, node);
-	}
-
-	for (LevelObjectListItor it = dynamicLevelData.begin(); it != dynamicLevelData.end(); ++it) {
-		PLevelObject obj(*it);
-		if (obj->IsOgreObject())
-			static_cast<COgreLevelObject*>(obj.get())->Draw(ogreScene, node);
+	for (OgreViewList::iterator it = ogreViews.begin(); it != ogreViews.end(); ++it) {
+		(*it)->SetOgreScene(ogreScene, node);
 	}
 
 	return node;
 }
 
 
-CLevelData::LevelObjectList CLevelData::GetObjectRectangle(const Ogre::Rectangle& rect, LevelObjectList& list) {
+CLevelData::LevelObjectList CLevelData::GetObjectRectangle(const Game::Rectangle& rect, LevelObjectList& list) {
 	LevelObjectList results;
-	for (LevelObjectListItor it = list.begin(); it != list.end(); ++it) {
+	for (LevelObjectList::iterator it = list.begin(); it != list.end(); ++it) {
 		const PLevelObject& obj = *it;
-		if (Game::Intersect(obj->GetBoundingRectangle(), rect))
+		if (obj->GetBoundingBox().Intersects(rect))
 			results.push_back(obj);
 	}
 	return results;
 }
 
-CLevelData::LevelObjectList CLevelData::GetObjectRectangle(const Ogre::Rectangle& rect) {
+CLevelData::LevelObjectList CLevelData::GetObjectRectangle(const Game::Rectangle& rect) {
 	// TODO: use space partitioning here
 	LevelObjectList results = GetObjectRectangle(rect, this->staticLevelData);
 	LevelObjectList temp = GetObjectRectangle(rect, this->dynamicLevelData);
 	return results;
 }
 
-Game::Polygon MakePolygon(const Ogre::Rectangle& rect, const Ogre::Vector2& translation) {
+Game::Polygon MakePolygon(const Game::Rectangle& rect, const Ogre::Vector2& translation) {
 	Game::Polygon polygon;
 	if (translation.x > 0 && translation.y > 0) { // top right
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.left+translation.x, rect.top+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.right+translation.x, rect.top+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.right+translation.x, rect.bottom+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.bottom));
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.bottom));
+		polygon.AddPoint(rect.TopLeft());
+		polygon.AddPoint(rect.TopLeft() + translation);
+		polygon.AddPoint(rect.TopRight() + translation);
+		polygon.AddPoint(rect.BottomRight() + translation);
+		polygon.AddPoint(rect.BottomRight());
+		polygon.AddPoint(rect.BottomLeft());
 	} else if (translation.x > 0 && translation.y == 0) { // right
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right+translation.x, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right+translation.x, rect.bottom));
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.bottom));
+		polygon.AddPoint(rect.TopLeft());
+		polygon.AddPoint(rect.TopRight() + Ogre::Vector2(translation.x, 0.0f));
+		polygon.AddPoint(rect.BottomRight() + Ogre::Vector2(translation.x, 0.0f));
+		polygon.AddPoint(rect.BottomLeft());
 	} else if (translation.x > 0 && translation.y < 0) { // bottom right
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right+translation.x, rect.top+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.right+translation.x, rect.bottom+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.left+translation.x, rect.bottom+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.bottom));
+		polygon.AddPoint(rect.TopLeft());
+		polygon.AddPoint(rect.TopRight());
+		polygon.AddPoint(rect.TopRight() + translation);
+		polygon.AddPoint(rect.BottomRight() + translation);
+		polygon.AddPoint(rect.BottomLeft() + translation);
+		polygon.AddPoint(rect.BottomLeft());
 	} else if (translation.x == 0 && translation.y > 0) { // top
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.top + translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.top + translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.bottom));
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.bottom));
+		polygon.AddPoint(rect.TopLeft() + Ogre::Vector2(0.0f, translation.y));
+		polygon.AddPoint(rect.TopRight() + Ogre::Vector2(0.0f, translation.y));
+		polygon.AddPoint(rect.BottomRight());
+		polygon.AddPoint(rect.BottomLeft());
 	} else if (translation.x == 0 && translation.y < 0) { // bottom
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.bottom + translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.bottom + translation.y));
+		polygon.AddPoint(rect.TopLeft());
+		polygon.AddPoint(rect.TopRight());
+		polygon.AddPoint(rect.BottomRight() + Ogre::Vector2(0.0f, translation.y));
+		polygon.AddPoint(rect.BottomLeft() + Ogre::Vector2(0.0f, translation.y));
 	} else if (translation.x < 0 && translation.y > 0) { // top left
-		polygon.AddPoint(Ogre::Vector2(rect.left+translation.x, rect.top+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.right+translation.x, rect.top+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.bottom));
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.bottom));
-		polygon.AddPoint(Ogre::Vector2(rect.left+translation.x, rect.bottom+translation.y));
-	} else if (translation.x < 0 && translation.y == 0) { // left
-		polygon.AddPoint(Ogre::Vector2(rect.left+translation.x, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.bottom));
-		polygon.AddPoint(Ogre::Vector2(rect.left+translation.x, rect.bottom));
-	} else if (translation.x < 0 && translation.y < 0) { // bottom left
-		polygon.AddPoint(Ogre::Vector2(rect.left+translation.x, rect.top+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.left, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.top));
-		polygon.AddPoint(Ogre::Vector2(rect.right, rect.bottom));
-		polygon.AddPoint(Ogre::Vector2(rect.right+translation.x, rect.bottom+translation.y));
-		polygon.AddPoint(Ogre::Vector2(rect.left+translation.x, rect.bottom+translation.y));
+		polygon.AddPoint(rect.TopLeft() + translation);
+		polygon.AddPoint(rect.TopRight() + translation);
+		polygon.AddPoint(rect.TopRight());
+		polygon.AddPoint(rect.BottomRight());
+		polygon.AddPoint(rect.BottomLeft());
+		polygon.AddPoint(rect.BottomLeft() + translation);
+	} else if (translation.x < 0 && translation.y == 0) { // Left()
+		polygon.AddPoint(rect.TopLeft() + Ogre::Vector2(translation.x, 0.0f));
+		polygon.AddPoint(rect.TopRight());
+		polygon.AddPoint(rect.BottomRight());
+		polygon.AddPoint(rect.BottomLeft() + Ogre::Vector2(translation.x, 0.0f));
+	} else if (translation.x < 0 && translation.y < 0) { // Bottom() Left()
+		polygon.AddPoint(rect.TopLeft() + translation);
+		polygon.AddPoint(rect.TopLeft());
+		polygon.AddPoint(rect.TopRight());
+		polygon.AddPoint(rect.BottomRight());
+		polygon.AddPoint(rect.BottomRight() + translation);
+		polygon.AddPoint(rect.BottomLeft() + translation);
 	}
 	return polygon;
 }
 	bool bResolveFinished = false;
 
 	// get Rectangle and corresponding Polygon once; change manually if needed
-	Ogre::Rectangle rect = object->GetBoundingRectangle();
+	Game::Rectangle rect = object->GetBoundingBox();
 	Game::Polygon objectPolygon = object->GetBoundingBoxPolygon();
 
 	Ogre::Vector2 currentTranslation = translation; // translation we are performing currently
 			currentTranslation = (maxLength / currentLength) * currentTranslation;
 		}
 
-		TEST_LOG("ResolveCollision: (" << rect.left << ", " << rect.top << ", " << rect.right << ", " << rect.bottom << ") "
-				 << currentTranslation);
+		TEST_LOG("ResolveCollision: (" << rect << ") " << currentTranslation);
 
 		// I. get all objects inside the smallest rectangle containing rect and rect+translation
-		Ogre::Rectangle broadRect( rect );
+		Game::Rectangle broadRect( rect );
 		if (currentTranslation.x > 0)
-			broadRect.right = rect.right + currentTranslation.x;
+			broadRect.SetRight( rect.Right() + currentTranslation.x );
 		else
-			broadRect.left = rect.left + currentTranslation.x;
+			broadRect.SetLeft( rect.Left() + currentTranslation.x );
 		if (currentTranslation.y > 0)
-			broadRect.top = rect.top + currentTranslation.y;
+			broadRect.SetTop( rect.Top() + currentTranslation.y );
 		else
-			broadRect.bottom = rect.bottom + currentTranslation.y;
+			broadRect.SetBottom( rect.Bottom() + currentTranslation.y );
+
 		LevelObjectList objects = GetObjectRectangle(broadRect);
 
 		// if no objects are in range, we will not collide
 		LevelObjectList collisionObjects; // objects we could collide with
 		LevelObjectList intersectingObjects; // objects we currently are colliding with
 
-		for (LevelObjectListItor it = objects.begin(); it != objects.end(); ++it) {
+		for (LevelObjectList::iterator it = objects.begin(); it != objects.end(); ++it) {
 			const PLevelObject& obj = *it;
 			if (std::find(ignoreObjects.begin(), ignoreObjects.end(), obj) != ignoreObjects.end())
 				continue;
 
-			Ogre::Rectangle boundingRect = obj->GetBoundingRectangle();
-			Game::Polygon objPolygon = obj->GetPolygon();
+			Game::Rectangle boundingRect = obj->GetBoundingBox();
+			Game::Polygon objPolygon = obj->GetCollisionPolygon();
 
 			// check for intersection
-			if (Game::Intersect(rect, boundingRect)) {
+			if (rect.Intersects(boundingRect)) {
 				std::pair<bool, Ogre::Vector2> result = objPolygon.SeparatingAxesTest(objectPolygon);
 				if (!result.first) {
 					if (obj->HandleCollision(object, currentTranslation) == CLevelObject::ctBlocking) {
 			TEST_LOG("COLLISION");
 
 			const PLevelObject& obj = intersectingObjects[0];
-			Game::Polygon objPoly = obj->GetPolygon();
+			Game::Polygon objPoly = obj->GetCollisionPolygon();
 
 			// get minimum translation vector
 			std::pair<bool, Ogre::Vector2> SATresult = objectPolygon.SeparatingAxesTest(objPoly);
 
 			TEST_LOG(translationResolve);
 
-			rect.left = rect.left + translationResolve.x;
-			rect.right = rect.right + translationResolve.x;
-			rect.top = rect.top + translationResolve.y;
-			rect.bottom = rect.bottom + translationResolve.y;
+			rect.Translate(translationResolve);
 			objectPolygon.Translate(translationResolve);
 
 			result = result + translationResolve;
 			bNotFound = true;
 			LastCollisionNonBlocking = false;
 
-			for (LevelObjectListItor it = collisionObjects.begin(); it != collisionObjects.end(); ++it) {
+			for (LevelObjectList::iterator it = collisionObjects.begin(); it != collisionObjects.end(); ++it) {
 				const PLevelObject& obj = *it;
 				if (std::find(ignoreObjects.begin(), ignoreObjects.end(), obj) != ignoreObjects.end())
 					continue;
 
 				// check all faces for possible collision
-				objFaces = obj->GetPolygon().GetFaces(false);
+				objFaces = obj->GetCollisionPolygon().GetFaces(false);
 				for (int i = 0; i < objFaces.size(); i++) {
 					// only process faces facing against movement direction
 					if (objFaces[i].normal.dotProduct(currentTranslation) >= 0)
 				result += maxTranslation;
 				maxLength -= maxTranslation.length();
 				objectPolygon.Translate(maxTranslation);
-				rect.left = rect.left + maxTranslation.x;
-				rect.right = rect.right + maxTranslation.x;
-				rect.top = rect.top + maxTranslation.y;
-				rect.bottom = rect.bottom + maxTranslation.y;
+				rect.Translate(maxTranslation);
 
 				currentTranslation -= maxTranslation;
 

src/GameObjects/CLevelData.h

 
 #include "Geometry.h"
 #include "LevelObjects.h"
+#include "LevelDataReader.h"
 #include "../testlog.h"
 #include "../Core/CLog.h"
 
 class CLevelData;
 typedef boost::shared_ptr<CLevelData> PLevelData;
 
-class CLevelData {
+class CLevelData : public LevelDataReaderListener {
 public:
-	enum ObjectType {otStatic, otDynamic, otBackground};
-
 	CLevelData();
 	virtual ~CLevelData();
 
 	@return newly created scene node */
 	Ogre::SceneNode* Draw(Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode = NULL);
 
-	/** Check for Collision; return constraints
-	@param rect bounding box for which to check for collision
-	@param range Maximum distance to check for constraints */
-	Ogre::Rectangle Collision(const Ogre::Rectangle& rect, float range);
-
 	/** Resolve Collision for a given LevelObject which moves along translation (handles levelobject as its 2D bounding box)
 	@return Translation vector which avoids collision; returns translation if no collision occurs; a multiple of translation otherwise */
 	Ogre::Vector2 ResolveCollision(PLevelObject object, const Ogre::Vector2& translation);
 	@param type Specify where to insert (static, dynamic, background) */
 	virtual void InsertObject(PLevelObject object, ObjectType type);
 
+	/** Insert view as specified type
+	@param object The object
+	@param type Specify where to insert (static, dynamic, background) */
+	virtual void InsertView(POgreEntityView view, ObjectType type);
+
 	static PLevelData Create() {
 		CLevelData* leveldata = new CLevelData();
 		PLevelData leveldataPtr(leveldata);
 		return leveldataPtr;
 	}
+
+	/** Implementation of LevelDataReaderListener */
+	virtual void ReadLevelObject(PLevelObject object, ObjectType layer) {
+		InsertObject(object, static_cast<ObjectType>(layer) );
+	}
+	/** Implementation of LevelDataReaderListener */
+	virtual void ReadOgreEntityView(POgreEntityView view, ObjectType layer) {
+		InsertView(view, static_cast<ObjectType>(layer));
+	}
 private:
 	typedef std::vector<PLevelObject> LevelObjectList;
-	typedef std::vector<PLevelObject>::iterator LevelObjectListItor;
+	typedef std::vector<POgreEntityView> OgreViewList;
 
-	LevelObjectList GetObjectRectangle(const Ogre::Rectangle& rect, LevelObjectList& list);
-	LevelObjectList GetObjectRectangle(const Ogre::Rectangle& rect);
+	LevelObjectList GetObjectRectangle(const Game::Rectangle& rect, LevelObjectList& list);
+	LevelObjectList GetObjectRectangle(const Game::Rectangle& rect);
 
 	LevelObjectList staticLevelData;
 	LevelObjectList backgroundLevelData;
 	LevelObjectList dynamicLevelData;
+	OgreViewList ogreViews;
 };
 
-Game::Polygon MakePolygon(const Ogre::Rectangle& rect, const Ogre::Vector2& translation);
-bool IsSeparatingAxis(const std::vector<Ogre::Vector2>& polygon1, const std::vector<Ogre::Vector2>& polygon2, const Ogre::Vector2& axis);
-
 }
 }
 

src/GameObjects/Geometry.cpp

 
 namespace Game {
 
+/*------------------
+ * Rectangle
+ *------------------*/
+
+Rectangle::Rectangle()
+	: left(0.0f), bottom(0.0f), right(0.0f), top(0.0f)
+{ }
+
+Rectangle::Rectangle(float fLeft, float fBottom, float fRight, float fTop)
+{
+	SetExtends(fLeft, fBottom, fRight, fTop);
+}
+
+Rectangle::Rectangle(const Ogre::Vector2& vMin, const Ogre::Vector2& vMax)
+{
+	SetExtends(vMin, vMax);
+}
+
+void Rectangle::SetExtends(const Ogre::Vector2& vMin, const Ogre::Vector2& vMax) {
+	left = vMin.x; bottom = vMin.y;
+	right = vMax.x; top = vMax.y;
+	assert(left <= right);
+	assert(bottom <= top);
+}
+
+void Rectangle::SetExtends(float fLeft, float fBottom, float fRight, float fTop) {
+	left = fLeft; bottom = fBottom;
+	right = fRight; top = fTop;
+	assert(left <= right);
+	assert(bottom <= top);
+}
+
+void Rectangle::Translate(const Ogre::Vector2& translate) {
+	left += translate.x; right += translate.x;
+	top += translate.y; bottom += translate.y;
+}
+
+void Rectangle::SetLeft(float fLeft) {
+	assert(fLeft <= right);
+	left = fLeft;
+}
+void Rectangle::SetBottom(float fBottom) {
+	assert(fBottom <= top);
+	bottom = fBottom;
+}
+void Rectangle::SetRight(float fRight) {
+	assert(fRight >= left);
+	right = fRight;
+}
+void Rectangle::SetTop(float fTop) {
+	assert(fTop >= bottom);
+	top = fTop;
+}
+
+std::ostream& operator<< (std::ostream& os, const Rectangle &rect) {
+	os << "Rectangle( " << rect.Left() << ", " << rect.Bottom() << "; " << rect.Right() << ", " << rect.Top() << " )";
+	return os;
+}
 
 /*------------------
  * Face
 	this->Points.push_back(face.v2);
 }
 
-Polygon::Polygon(const Ogre::Rectangle& rect) {
-	Points.push_back(Ogre::Vector2(rect.left, rect.bottom));
-	Points.push_back(Ogre::Vector2(rect.right, rect.bottom));
-	Points.push_back(Ogre::Vector2(rect.right, rect.top));
-	Points.push_back(Ogre::Vector2(rect.left, rect.top));
+Polygon::Polygon(const Game::Rectangle& rect) {
+	Points.push_back(Ogre::Vector2(rect.Left(), rect.Bottom()));
+	Points.push_back(Ogre::Vector2(rect.Right(), rect.Bottom()));
+	Points.push_back(Ogre::Vector2(rect.Right(), rect.Top()));
+	Points.push_back(Ogre::Vector2(rect.Left(), rect.Top()));
 }
 
 Polygon::~Polygon() {
 	return std::pair<bool, float>(bIntersection, factor);
 }
 
+Game::Rectangle Polygon::GetMinimumEnclosingRectangle() const {
+	Game::Rectangle result;
+	if (Points.size() < 1)
+		return result;
+
+	// get maximum/minimum coordinates
+	result.SetExtends(Points[0], Points[0]);
+	for (int i = 1; i < Points.size(); i++) {
+		if (Points[i].x > result.Right())
+			result.SetRight(Points[i].x);
+		if (Points[i].x < result.Left())
+			result.SetLeft(Points[i].x);
+		if (Points[i].y > result.Top())
+			result.SetTop(Points[i].y);
+		if (Points[i].y < result.Bottom())
+			result.SetBottom(Points[i].y);
+	}
+	return result;
+}
+
 std::ostream& operator<< (std::ostream& os, const Polygon& polygon) {
-	os << "Polygon( NumFaces=" << polygon.FaceCount() << " )";
+	os << "Polygon(";
+
+	for (int i = 0; i < polygon.GetPoints().size(); i++) {
+		os << polygon.GetPoints()[i];
+		if (i != polygon.GetPoints().size()-1)
+			os << ", ";
+	}
+
+	os << " )";
 	return os;
 }
 

src/GameObjects/Geometry.h

 	return !approximatelyEqual(det, 0.0f);
 }
 
-/** Check if first rectangle contains the other one (fast) */
-inline bool Contains(const Ogre::Rectangle& r1, const Ogre::Rectangle& r2) {
-	return ((r2.left >= r1.left) && (r2.right <= r1.right) &&
-			(r2.top >= r1.top) && (r2.bottom <= r1.bottom));
-}
+class Rectangle {
+public:
+	Rectangle();
+	Rectangle(float fLeft, float fBottom, float fRight, float fTop);
+	Rectangle(const Ogre::Vector2& vMin, const Ogre::Vector2& vMax);
 
-/** Check if rectangles intersect (fast) */
-inline bool Intersect(const Ogre::Rectangle& r1, const Ogre::Rectangle& r2) {
-	return (r1.left < r2.right) &&
-		   (r1.right > r2.left) &&
-		   (r1.top > r2.bottom) &&
-		   (r1.bottom < r2.top);
-}
+	/** Returns bottom left Point */
+	inline Ogre::Vector2 GetMinimum() const { return Ogre::Vector2(left, bottom); }
+	/** Returns top right Point */
+	inline Ogre::Vector2 GetMaximum() const { return Ogre::Vector2(right, top); }
+
+	inline bool operator==(const Rectangle& rect2) const {
+		return left == rect2.left && right == rect2.right && top == rect2.top && bottom == rect2.bottom;
+	}
+	inline bool operator!=(const Rectangle& rect2) const { return !(*this == rect2); }
+
+	inline float Left() const { return left; }
+	inline float Bottom() const { return bottom; }
+	inline float Right() const { return right; }
+	inline float Top() const { return top; }
+	inline Ogre::Vector2 TopLeft() const { return Ogre::Vector2(left, top); }
+	inline Ogre::Vector2 TopRight() const { return Ogre::Vector2(right, top); }
+	inline Ogre::Vector2 BottomLeft() const { return Ogre::Vector2(left, bottom); }
+	inline Ogre::Vector2 BottomRight() const { return Ogre::Vector2(right, bottom); }
+
+	void SetLeft(float fLeft);
+	void SetBottom(float fBottom);
+	void SetRight(float fRight);
+	void SetTop(float fTop);
+
+	void SetExtends(const Ogre::Vector2& vMin, const Ogre::Vector2& vMax);
+	void SetExtends(float fLeft, float fBottom, float fRight, float fTop);
+
+	/** Translates Rectangle by given vector */
+	void Translate(const Ogre::Vector2& translate);
+
+	inline bool Contains(const Rectangle& rect) const {
+		return ((rect.left >= left) && (rect.right <= right) &&
+				(rect.top >= top) && (rect.bottom <= bottom));
+	}
+
+	inline bool Intersects(const Rectangle& rect) const {
+		return (left < rect.right) &&
+			   (right > rect.left) &&
+			   (top > rect.bottom) &&
+			   (bottom < rect.top);
+	}
+private:
+	float left, bottom, right, top;
+};
+
+std::ostream& operator<< (std::ostream& os, const Rectangle &rect);
 
 struct Face {
 	Ogre::Vector2 v1;
 	/** Create Polygon from one Face */
 	Polygon(const Face& face);
 	/** Create Polygon from Rectangle */
-	Polygon(const Ogre::Rectangle& rect);
+	Polygon(const Game::Rectangle& rect);
 	virtual ~Polygon();
 
 	bool operator==(const Polygon& poly2) const;
 	@param NoNormals Set true to not calculate any normals (faster)
 	@see AddPoint */
 	std::vector<Face> GetFaces(bool NoNormals = false) const;
+	/** Get Points*/
+	const std::vector<Ogre::Vector2>& GetPoints() const { return Points; }
 	/** Moves all Points by translation */
 	void Translate(const Ogre::Vector2& translation);
 
+	/** Get Minimum Enclosing Rectangle */
+	Game::Rectangle GetMinimumEnclosingRectangle() const;
+
 	/** Performs separating axis test for a given axis and polygon; uses left hand normal of axis
 	 *  Use result.MinimumOverlap * LeftHandNormal(axis) to get translation vector
 	@return Test Result

src/GameObjects/LevelDataReader.cpp

 namespace Game {
 namespace GameObjects {
 
-CSimplePlainTextReader::CSimplePlainTextReader(const std::string& filename)
-	: sFilename(filename) {
-
-}
-
-CSimplePlainTextReader::~CSimplePlainTextReader() {
-
-}
-
-bool CSimplePlainTextReader::Read(PLevelData target) {
-	target->ClearData();
-
-	std::fstream config;
-
-	try {
-		config.open(sFilename.c_str(), std::ios::in);
-
-		POgreLevelObject cube;
-		POgreLevelObject house;
-
-		std::string line;
-		std::string material;
-		Ogre::Vector3 position;
-		Ogre::Vector3 size(10,10,10); // all cubes are 10x10x10
-		Ogre::Vector3 hsize(70,100,70);
-
-		// start with an offset of 5, as (z,y) specifies center of cubes
-		float z = 5;
-		float y = -5;
-
-		// for each character, move 10 to the left (z-axis)
-		// for each line, move 10 down (y-axis)
-		while( getline(config,line) ){
-			for (int i = 0; i < line.length(); ++i) {
-				// ignore spaces
-				if (line[i] != ' ') {
-					if (line[i] == 'H') {
-
-						position.x = 2.0f;
-						position.y = y - 45.0f;
-						position.z = z + 30.0f;
-						house = POgreLevelObject(new COgreLevelObject("tudorhouse.mesh", position));
-						house->SetAABBSize(hsize);
-						house->SetScale(Ogre::Vector3(0.1,0.1,0.1));
-						target->InsertObject(house, CLevelData::otStatic);
-
-					} else {
-
-						// add house in background if lowercase
-						if (std::islower(line[i])) {
-							position.x = 45.0f;
-							position.y = y + 5.0f;
-							position.z = z + 30.0f;
-							house = POgreLevelObject(new COgreLevelObject("tudorhouse.mesh", position));
-							house->SetAABBSize(hsize);
-							house->SetScale(Ogre::Vector3(0.1,0.1,0.1));
-							target->InsertObject(house, CLevelData::otBackground);
-						}
-
-						if (line[i] == 'W' || line[i] == 'w')
-							material = "Textures/Rockwall";
-						else if (line[i] == 'X' || line[i] == 'x')
-							material = "Textures/Marmor";
-						else
-							continue;
-
-						position.x = -5.0f;
-						position.y = y;
-						position.z = z;
-
-						cube = POgreLevelObject(new COgreLevelObject("cube.mesh", position));
-						cube->SetMaterial(material);
-						cube->SetScale(Ogre::Vector3(0.1,0.1,0.1));
-						cube->SetAABBSize(size);
-						target->InsertObject(cube, CLevelData::otStatic);
-
-						position.x = 5.0f;
-
-						cube = POgreLevelObject(new COgreLevelObject("cube.mesh", position));
-						cube->SetMaterial(material);
-						cube->SetScale(Ogre::Vector3(0.1,0.1,0.1));
-						cube->SetAABBSize(size);
-						target->InsertObject(cube, CLevelData::otStatic);
-
-					}
-				}
-				z += 10.0f;
-			}
-			y -= 10.0f;
-			z = 5.0f;
-		}
-
-		config.close();
-	} catch (...) {
-		config.close();
-		return false;
-	}
-
-	return true;
-}
-
-
 CXMLReader::CXMLReader() {
 }
 
 	return node.GetAttribute<std::string>(name);
 }
 
+Ogre::Vector2 CXMLReader::ReadVector2(const ticpp::Element& node, const std::string& prefix) {
+	Ogre::Vector2 result;
+	result.x = node.GetAttribute<float>(prefix + "x");
+	result.y = node.GetAttribute<float>(prefix + "y");
+	return result;
+}
+
+Game::Rectangle CXMLReader::ReadRectangle(const ticpp::Element& node) {
+	Ogre::Vector2 vMin = ReadVector2(node, "min_");
+	Ogre::Vector2 vMax = ReadVector2(node, "max_");
+	return Game::Rectangle(vMin, vMax);
+}
+
+Game::Polygon CXMLReader::ReadPolygon(const ticpp::Element& node) {
+	// TODO
+}
+
 Ogre::Vector3 CXMLReader::ReadVector(const ticpp::Element& node, const std::string& prefix) {
 	Ogre::Vector3 result;
 	result.x = node.GetAttribute<float>(prefix + "x");
 	return Ogre::Quaternion(w,x,y,z);
 }
 
-Ogre::AxisAlignedBox CXMLReader::ReadAABB(const ticpp::Element& node) {
-	Ogre::Vector3 vMin = ReadVector(node, "min_");
-	Ogre::Vector3 vMax = ReadVector(node, "max_");
-	Ogre::AxisAlignedBox result(vMin, vMax);
-	return result;
-}
-
-void CXMLReader::ReadLevelObject(const ticpp::Element& node, POgreLevelObject object) {
-	assert(object != NULL);
+void CXMLReader::ReadLevelObject(const ticpp::Element& node, PLevelObject object, POgreEntityView view) {
+	assert(object != NULL); assert(view != NULL);
 
 	ticpp::Element* position = node.FirstChildElement("position", false);
 	if (position) {
-		object->SetPosition(ReadVector(*position));
+		//Ogre::Vector3 pos = ReadVector(*position);
+		//object->SetPosition(object->GetPosition() + Ogre::Vector2(pos.z, pos.y));
+		//view->SetPositionOffset(view->GetPositionOffset() + Ogre::Vector3(pos.x, 0.0f, 0.0f));
+		view->SetPositionOffset(ReadVector(*position));
 	}
 
 	ticpp::Element* entity = node.FirstChildElement("entity", false);
 	if (entity) {
-		object->SetEntityName(ReadString(*entity));
+		view->SetEntityName(ReadString(*entity));
 	}
 
 	ticpp::Element* scale = node.FirstChildElement("scale", false);
 	if (scale) {
-		object->SetScale(ReadVector(*scale));
+		view->SetScale(ReadVector(*scale));
 	}
 
 	ticpp::Element* material = node.FirstChildElement("material", false);
 	if (material) {
-		object->SetMaterial(ReadString(*material));
+		view->SetMaterial(ReadString(*material));
 	}
 
 	ticpp::Element* AABBsize = node.FirstChildElement("AABBsize", false);
 	if (AABBsize) {
-		object->SetAABBSize(ReadVector(*AABBsize));
+		object->SetAABBSize(ReadVector2(*AABBsize));
 	}
 
 	ticpp::Element* AABBextends = node.FirstChildElement("AABBextends", false);
 	if (AABBextends) {
-		object->SetBoundingBox(ReadAABB(*AABBextends));
+		object->SetBoundingBox(ReadRectangle(*AABBextends));
 	}
 
 	ticpp::Element* orientation = node.FirstChildElement("orientation", false);
 	if (orientation) {
-		object->SetOrientation(ReadQuaternion(*orientation));
+		view->SetOrientation(ReadQuaternion(*orientation));
 	}
 }
 
-void CXMLReader::ReadTemplate(const ticpp::Element& node) {
+void CXMLReader::ReadTemplate(const ticpp::Element& node, LevelDataReaderListener* listener) {
 	try {
 		std::string sName = ReadString(node);
 		std::string sType = ReadString(node, "type");
 
-		POgreLevelObject object;
+		PLevelObject object;
+		POgreEntityView view;
 
 		if (sType != "CustomAABB") {
-			object = templates[sType];
-			if (object != NULL) {
+			ModelViewPair Template = templates[sType];
+			if (Template.first != NULL && Template.second != NULL) {
 				// copy template
-				object = POgreLevelObject(new COgreLevelObject(*(object.get())));
+				object = Template.first->Copy();
+				view = Template.second->Copy(object);
 			} else {
+				// template not found
+				// TODO throw exception
 				return;
 			}
 		} else {
-			object = POgreLevelObject(new COgreLevelObject("", Ogre::Vector3::ZERO));
+			object = PLevelObject(new CLevelObject());
+			view = COgreEntityView::Create(object);
 		}
 
-		ReadLevelObject(node, object);
+		ReadLevelObject(node, object, view);
 
-		templates[sName] = object;
+		templates[sName] = ModelViewPair(object, view);
+		listener->ReadTemplate(sName, object, view);
+
 	} catch (ticpp::Exception& ex) {
 	}
 }
 
-void CXMLReader::ReadObject(const ticpp::Element& node) {
+void CXMLReader::ReadObject(const ticpp::Element& node, LevelDataReaderListener* listener) {
 	try {
 		//<object type="house" layer="static" x="2" y="-50" z="115" />
 		std::string sType = ReadString(node, "type");
 		std::string sLayer = ReadString(node, "layer");
-		Ogre::Vector3 position = ReadVector(node);
+		Ogre::Vector2 position = ReadVector2(node);
 
-		POgreLevelObject object;
+		PLevelObject object;
+		POgreEntityView view;
 
 		if (sType == "CustomAABB") {
 			// create new
-			object = POgreLevelObject(new COgreLevelObject("", Ogre::Vector3::ZERO));
-		} else if (templates[sType] != NULL) {
+			object = PLevelObject(new CLevelObject());
+			view = COgreEntityView::Create(object);
+		} else {
 			// copy template
-			object = templates[sType];
-			object = POgreLevelObject(new COgreLevelObject(*(object.get())));
-		} else {
-			// template not found
-			return;
+			ModelViewPair Template = templates[sType];
+			if (Template.first != NULL && Template.second != NULL) {
+				// copy template
+				object = Template.first->Copy();
+				view = Template.second->Copy(object);
+			}
+			else {
+				// template not found
+				return;
+			}
 		}
 
-		CLevelData::ObjectType otype;
+		ObjectType otype;
 		if (sLayer == "static")
-			otype = CLevelData::otStatic;
+			otype = otStatic;
 		else if (sLayer == "background")
-			otype = CLevelData::otBackground;
+			otype = otBackground;
 		else if (sLayer == "dynamic")
-			otype = CLevelData::otDynamic;
+			otype = otDynamic;
 		else
 			return;
 
-		object->SetPosition(object->GetPosition() + position);
+		// add position from object tag
+		object->SetPosition(position);
+		//object->SetPosition(object->GetPosition() + Ogre::Vector2(position.z, position.y));
+		//view->SetPositionOffset(view->GetPositionOffset() + Ogre::Vector3(position.x, 0.0f, 0.0f));
 
 		// read additional data if exists
-		ReadLevelObject(node, object);
+		ReadLevelObject(node, object, view);
 
-		InsertObject(object, otype);
+		listener->ReadLevelObject(object, otype);
+		listener->ReadOgreEntityView(view, otype);
 	} catch(ticpp::Exception& ex) {
 	}
 }
 
-void CXMLReader::InsertObject(POgreLevelObject obj, CLevelData::ObjectType target) {
-	if (leveldata != NULL)
-		leveldata->InsertObject(obj, target);
-	if (pStatic != NULL && pBackground != NULL && pDynamic != NULL) {
-		switch (target) {
-		case CLevelData::otStatic:
-			pStatic->push_back(obj);
-			break;
-		case CLevelData::otBackground:
-			pBackground->push_back(obj);
-			break;
-		case CLevelData::otDynamic:
-			pDynamic->push_back(obj);
-			break;
-		}
-	}
-}
 
-bool CXMLReader::Read() {
+bool CXMLReader::Read(const std::string& filename, LevelDataReaderListener* listener, bool TemplatesOnly) {
 	try {
-		ticpp::Document document(sFilename);
+		ticpp::Document document(filename);
 		document.LoadFile();
 		ticpp::Element* root = document.FirstChildElement("leveldata", false);
 		if (!root) return false;
 			// iterate <template>..</template>
 			ticpp::Iterator< ticpp::Element > child("template");
 			for (child = child.begin( templatesNode ); child != child.end(); child++) {
-				ReadTemplate(*child);
+				ReadTemplate(*child, listener);
 			}
 		}
 
-		if (!bTemplatesOnly) {
+		if (!TemplatesOnly) {
 			// read objects
 			ticpp::Element* objectsNode = root->FirstChildElement("levelobjects", false);
 			if (objectsNode) {
 				// iterate <object... />
 				ticpp::Iterator< ticpp::Element > child("object");
 				for (child = child.begin( objectsNode ); child != child.end(); child++) {
-					ReadObject(*child);
+					ReadObject(*child, listener);
 				}
 			}
 		}
 	return true;
 }
 
-bool CXMLReader::Read(const std::string& filename) {
-	bTemplatesOnly = true;
-	sFilename = filename;
-	return Read();
 }
-
-bool CXMLReader::Read(const std::string& filename, PLevelData target) {
-	bTemplatesOnly = false;
-	sFilename = filename;
-	leveldata = target;
-	pStatic = pBackground = pDynamic = NULL;
-	bool result = Read();
-	leveldata.reset();
-	return result;
 }
-
-bool CXMLReader::Read(const std::string& filename, ObjectList& lStatic, ObjectList& lDynamic, ObjectList& lBackground) {
-	bTemplatesOnly = false;
-	sFilename = filename;
-	leveldata.reset();
-	pStatic = &lStatic;
-	pDynamic = &lDynamic;
-	pBackground = &lBackground;
-	bool result = Read();
-	pStatic = pBackground = pDynamic = NULL;
-	return result;
-}
-
-}
-}

src/GameObjects/LevelDataReader.h

 #define LEVELDATAREADER_H_
 
 #include "../Core/CLog.h"
-#include "CLevelData.h"
+#include "ObjectType.h"
+#include "LevelObjects.h"
 
 #define TIXML_USE_TICPP
 #include "ticpp.h"
 namespace Game {
 namespace GameObjects {
 
-/** Simple Level Data Loader
- *  Reads plain-text files and creates 20x10x10 cubes for each character which is not ' ' */
-class CSimplePlainTextReader {
+class LevelDataReaderListener {
 public:
-	CSimplePlainTextReader(const std::string& filename);
-	virtual ~CSimplePlainTextReader();
+	LevelDataReaderListener() { }
+	virtual ~LevelDataReaderListener() { }
 
-	virtual bool Read(PLevelData target);
-private:
-	std::string sFilename;
+	virtual void ReadTemplate(std::string name, PLevelObject object, POgreEntityView view) { }
+	virtual void ReadLevelObject(PLevelObject object, ObjectType layer) { }
+	virtual void ReadOgreEntityView(POgreEntityView view, ObjectType layer) { }
 };
-typedef boost::shared_ptr<CSimplePlainTextReader> PSimplePlainTextReader;
-
 
 class CXMLReader {
 public:
-	typedef std::map<std::string, POgreLevelObject> TemplateMap;
-	typedef std::vector<POgreLevelObject> ObjectList;
+	typedef std::pair<PLevelObject, POgreEntityView> ModelViewPair;
+	typedef std::map<std::string, ModelViewPair> TemplateMap;
 
 	CXMLReader();
 	virtual ~CXMLReader();
 
-	bool Read(const std::string& filename);
-	bool Read(const std::string& filename, PLevelData target);
-	bool Read(const std::string& filename, ObjectList& lStatic, ObjectList& lDynamic, ObjectList& lBackground);
+	bool Read(const std::string& filename, LevelDataReaderListener* listener, bool TemplatesOnly = false);
+private:
+	TemplateMap templates;
 
-	TemplateMap templates;
-private:
-	void ReadLevelObject(const ticpp::Element& node, POgreLevelObject object);
-	void ReadTemplate(const ticpp::Element& node);
-	void ReadObject(const ticpp::Element& node);
-	bool Read();
-	void InsertObject(POgreLevelObject obj, CLevelData::ObjectType target);
+	void ReadLevelObject(const ticpp::Element& node, PLevelObject object, POgreEntityView view);
+	void ReadTemplate(const ticpp::Element& node, LevelDataReaderListener* listener);
+	void ReadObject(const ticpp::Element& node, LevelDataReaderListener* listener);
 
 	Ogre::Quaternion ReadQuaternion(const ticpp::Element& node);
 	std::string ReadString(const ticpp::Element& node, const std::string& name = "name");
 	Ogre::Vector3 ReadVector(const ticpp::Element& node, const std::string& prefix = "");
-	Ogre::AxisAlignedBox ReadAABB(const ticpp::Element& node);
-
-	std::string sFilename;
-	ObjectList *pStatic, *pDynamic, *pBackground;
-	PLevelData leveldata;
-
-	bool bTemplatesOnly;
+	Ogre::Vector2 ReadVector2(const ticpp::Element& node, const std::string& prefix = "");
+	Game::Rectangle ReadRectangle(const ticpp::Element& node);
+	Game::Polygon ReadPolygon(const ticpp::Element& node);
 };
 typedef boost::shared_ptr<CXMLReader> PXMLReader;
 

src/GameObjects/LevelDataWriter.cpp

 namespace GameObjects {
 
 CXMLWriter::CXMLWriter() {
-	// TODO Auto-generated constructor stub
-
+	root = (Element*)document.InsertEndChild(Element("leveldata"));
+	root->SetAttribute("version", 1);
+	templates = new Element("templates");
+	levelobjects = new Element("levelobjects");
+	root->LinkEndChild(templates);
+	root->LinkEndChild(levelobjects);
 }
 
 CXMLWriter::~CXMLWriter() {
-	// TODO Auto-generated destructor stub
+	// ticpp nodes are deleted automatically when document dies
+}
+
+void CXMLWriter::Save(const std::string& filename) {
+	document.SaveFile(filename);
+}
+
+void CXMLWriter::WriteTemplate(const std::string& name, PLevelObject object, POgreEntityView view) {
+	Element* element = new Element("template");
+
+	element->SetAttribute("type", "CustomAABB");
+	element->SetAttribute("name", name);
+
+	WriteString(*element, "entity", view->GetEntityName());
+	if (view->GetMaterial() != "")
+		WriteString(*element, "material", view->GetMaterial());
+	WriteVector(*element, "scale", view->GetScale());
+	WriteVector(*element, "position", view->GetPositionOffset());
+	WriteQuaternion(*element, "orientation", view->GetOrientation());
+	WriteRectangle(*element, "AABBextends", object->GetBoundingBox());
+
+	levelobjects->LinkEndChild(element);
+}
+
+void CXMLWriter::WriteObject(ObjectType layer, PLevelObject object, POgreEntityView view) {
+	Element* element = new Element("object");
+
+	std::string sLayer = "";
+	if (layer == otStatic) sLayer = "static";
+	else if (layer == otDynamic) sLayer = "dynamic";
+	else if (layer == otBackground) sLayer == "background";
+
+	element->SetAttribute("type", "CustomAABB");
+	element->SetAttribute("layer", sLayer);
+
+	Ogre::Vector2 position = object->GetPosition();
+	element->SetAttribute("x", position.x);
+	element->SetAttribute("y", position.y);
+
+	WriteString(*element, "entity", view->GetEntityName());
+	if (view->GetMaterial() != "")
+		WriteString(*element, "material", view->GetMaterial());
+	WriteVector(*element, "scale", view->GetScale());
+	WriteVector(*element, "position", view->GetPositionOffset());
+	WriteQuaternion(*element, "orientation", view->GetOrientation());
+	WriteRectangle(*element, "AABBextends", object->GetBoundingBox());
+
+	levelobjects->LinkEndChild(element);
 }
 
 void CXMLWriter::WriteVector(Element& node, const string& name, const Ogre::Vector3& vec) {
 	node.LinkEndChild(element);
 }
 
+void CXMLWriter::WriteRectangle(ticpp::Element& node, const std::string& name, const Game::Rectangle& rect) {
+	Element* element = new Element(name);
+	Ogre::Vector2 vMin = rect.GetMinimum();
+	element->SetAttribute("min_x", vMin.x);
+	element->SetAttribute("min_y", vMin.y);
+	Ogre::Vector2 vMax = rect.GetMaximum();
+	element->SetAttribute("max_x", vMax.x);
+	element->SetAttribute("max_y", vMax.y);
+	node.LinkEndChild(element);
+}
+
 void CXMLWriter::WriteQuaternion(Element& node, const string& name, const Ogre::Quaternion& quater) {
 	Element* element = new Element(name);
 	element->SetAttribute("w", quater.w);
 	node.LinkEndChild(element);
 }
 
-void CXMLWriter::WriteObject(Element node, POgreLevelObject obj, const std::string& layer) {
-	Element* element = new Element("object");
-
-	element->SetAttribute("type", "CustomAABB");
-	element->SetAttribute("layer", layer);
-
-	Ogre::Vector3 position = obj->GetPosition();
-	element->SetAttribute("x", position.x);
-	element->SetAttribute("y", position.y);
-	element->SetAttribute("z", position.z);
-
-	WriteString(*element, "entity", obj->GetEntityName());
-	if (obj->GetMaterial() != "")
-		WriteString(*element, "material", obj->GetMaterial());
-	WriteVector(*element, "scale", obj->GetScale());
-	WriteQuaternion(*element, "orientation", obj->GetOrientation());
-	WriteAABB(*element, "AABBextends", obj->GetBoundingBox());
-
-	node.LinkEndChild(element);
 }
-
-void CXMLWriter::Write(const std::string& filename, LevelObjectList& staticObj, LevelObjectList& dynamicObj, LevelObjectList& backgroundObj) {
-	Document doc;
-	try {
-		Element* root = (Element*)doc.InsertEndChild(Element("leveldata"));
-		root->SetAttribute("version", 1);
-
-		// Write Levelobjects
-		Element* levelobjects = new Element("levelobjects");
-
-		for (LevelObjectList::iterator it = staticObj.begin(); it != staticObj.end(); ++it)
-			WriteObject(*levelobjects, *it, "static");
-
-		for (LevelObjectList::iterator it = dynamicObj.begin(); it != dynamicObj.end(); ++it)
-			WriteObject(*levelobjects, *it, "dynamic");
-
-		for (LevelObjectList::iterator it = backgroundObj.begin(); it != backgroundObj.end(); ++it)
-			WriteObject(*levelobjects, *it, "background");
-
-		root->LinkEndChild(levelobjects);
-
-		doc.SaveFile(filename);
-	} catch (...) {
-	}
 }
-
-}
-}

src/GameObjects/LevelDataWriter.h

 #define LEVELDATAWRITER_H_
 
 #include "../Core/CLog.h"
-#include "CLevelData.h"
+#include "ObjectType.h"
+#include "LevelObjects.h"
 
 #define TIXML_USE_TICPP
 #include "ticpp.h"
 #include "Ogre.h"
 
 #include <vector>
+#include "boost/utility.hpp"
 #include "boost/smart_ptr.hpp"
 
 namespace Game {
 namespace GameObjects {
 
-class CXMLWriter {
+/** XML Writer
+ *
+ *  Call WriteTemplate/ WriteObject for each template or object you want to save; then write to file using Save() */
+class CXMLWriter : boost::noncopyable { //TODO: copy constructor etc
 public:
-	typedef std::vector<POgreLevelObject> LevelObjectList;
-
 	CXMLWriter();
 	virtual ~CXMLWriter();
 
-	void Write(const std::string& filename, LevelObjectList& staticObj, LevelObjectList& dynamicObj, LevelObjectList& backgroundObj);
-
+	void WriteTemplate(const std::string& name, PLevelObject object, POgreEntityView view);
+	void WriteObject(ObjectType layer, PLevelObject object, POgreEntityView view);
+	void Save(const std::string& filename);
 private:
 	void WriteQuaternion(ticpp::Element& node, const std::string& name, const Ogre::Quaternion& quater);
 	void WriteVector(ticpp::Element& node, const std::string& name, const Ogre::Vector3& vec);
 	void WriteAABB(ticpp::Element& node, const std::string& name, const Ogre::AxisAlignedBox& box);
+	void WriteRectangle(ticpp::Element& node, const std::string& name, const Game::Rectangle& rect);
 	void WriteString(ticpp::Element& node, const std::string& name, const std::string& value);
-	void WriteObject(ticpp::Element node, POgreLevelObject obj, const std::string& layer);
+
+	ticpp::Document document;
+	ticpp::Element *root, *templates, *levelobjects;
 };
 
 typedef boost::shared_ptr<CXMLWriter> PXMLWriter;

src/GameObjects/LevelObjects.cpp

 namespace Game {
 namespace GameObjects {
 
-Ogre::Rectangle CLevelObject::GetBoundingRectangle() const {
-	Ogre::Rectangle rect;
-	rect.left = aabBounds.getMinimum().z;
-	rect.bottom = aabBounds.getMinimum().y;
-	rect.right = aabBounds.getMaximum().z;
-	rect.top = aabBounds.getMaximum().y;
-	return rect;
+CLevelObject::CLevelObject()
+	: vPosition(0.0f, 0.0f), collisionType(ctBlocking)
+{
+	EnableBoundingBoxCollision();
 }
 
-Game::Polygon CLevelObject::GetPolygon() const {
-	return Game::Polygon(GetBoundingRectangle());
+CLevelObject::CLevelObject(const Ogre::Vector2& position)
+	: vPosition(position), collisionType(ctBlocking)
+{
+	EnableBoundingBoxCollision();
 }
 
-Ogre::Rectangle CLevelObject::GetConstraints(const Ogre::Rectangle& rect) const {
-	Ogre::Rectangle constraints;
+CLevelObject::CLevelObject(const Game::Rectangle& bounds)
+	: vPosition(0.0f, 0.0f), aabBounds(bounds), collisionType(ctBlocking)
+{
+	EnableBoundingBoxCollision();
+}
 
-	// map 3D bounding box to 2D Rectangle
-	Ogre::Rectangle boundingRect;
-	boundingRect.bottom = aabBounds.getMinimum().y;
-	boundingRect.top = aabBounds.getMaximum().y;
-	boundingRect.left = aabBounds.getMinimum().z;
-	boundingRect.right = aabBounds.getMaximum().z;
+CLevelObject::CLevelObject(const CLevelObject& obj) {
+	// don't copy listeners
+	aabBounds = obj.aabBounds;
+	vPosition = obj.vPosition;
+	collisionType = obj.collisionType;
+}
 
-	// check for collision
-	if (::Game::Contains(boundingRect, rect) || ::Game::Intersect(boundingRect, rect)) {
-		// resolve collision in all directions
-		constraints.right = boundingRect.left - rect.right;
-		constraints.bottom = boundingRect.top - rect.bottom;
-		constraints.left = boundingRect.right - rect.left;
-		constraints.top = boundingRect.bottom - rect.top;
-/*
-		constraints.left = -std::numeric_limits<Ogre::Real>::infinity();
-		constraints.bottom = -std::numeric_limits<Ogre::Real>::infinity();
-		constraints.right = std::numeric_limits<Ogre::Real>::infinity();
-		constraints.top = std::numeric_limits<Ogre::Real>::infinity();
-*/
-	} else {
+PLevelObject CLevelObject::Copy() {
+	CLevelObject* copy = new CLevelObject(*this);
+	PLevelObject copyPtr(copy);
+	return copyPtr;
+}
 
-		/* How it works:
-		 *
-		 * exemplarily for constraints.left:
-		 **********************************
-		 * boundingRect
-		 *    \ +-----+               ------- boundingRect.top
-		 *      |     |        rect
-		 *      |     |   +--+ /      ------- rect.top
-		 *      +-----+   |  |        ------- boundingRect.bottom
-		 *                +--+        ------- rect.bottom
-		 *
-		 *            |   |
-		 *            |   |
-		 *            |   rect.left
-		 *            |
-		 * boundingRect.right
-		 *
-		 * In this case, clearly
-		 * 			rect.bottom < boundRect.top
-		 * 			rect.top > boundringRect.bottom
-		 * 			rect.left >= boundingRect.right
-		 *
-		 * If any of these conditions is false, rect could never collide with boundingRect by moving it to the left
-		 * Example:
-		 *
-		 * boundingRect
-		 *    \ +-----+               ------- boundingRect.top
-		 *      |     |
-		 *      |     |
-		 *      +-----+   rect        ------- boundingRect.bottom
-		 *          +--+ /            ------- rect.top
-		 *          |  |
-		 *          +--+              ------- rect.bottom
-		 *
-		 *          | |
-		 *          | |
-		 *  rect.left |
-		 *            |
-		 * boundingRect.right
-		 *
-		 * In this case, rect can move arbitrary far to left (-infinity) without colliding
-		 */
+void CLevelObject::notifyPositionChanged() {
+	for (ListenerList::iterator it = Listeners.begin(); it != Listeners.end(); ++it) {
+		(*it)->PositionChanged(this);
+	}
+}
 
-		if (rect.bottom < boundingRect.top && rect.top > boundingRect.bottom && rect.left >= boundingRect.right)
-			constraints.left = (boundingRect.right - rect.left);
-		else
-			constraints.left = -std::numeric_limits<Ogre::Real>::infinity();
+void CLevelObject::notifyBoundsChanged() {
+	for (ListenerList::iterator it = Listeners.begin(); it != Listeners.end(); ++it) {
+		(*it)->PositionChanged(this);
+	}
+}
 
-		if (rect.bottom < boundingRect.top && rect.top > boundingRect.bottom && rect.right <= boundingRect.left)
-			constraints.right = (boundingRect.left - rect.right);
-		else
-			constraints.right = std::numeric_limits<Ogre::Real>::infinity();
+void CLevelObject::notifyCollisionTypeChanged() {
+	for (ListenerList::iterator it = Listeners.begin(); it != Listeners.end(); ++it) {
+		(*it)->PositionChanged(this);
+	}
+}
 
-		if (rect.left < boundingRect.right && rect.right > boundingRect.left && rect.top <= boundingRect.bottom)
-			constraints.top = (boundingRect.bottom - rect.top);
-		else
-			constraints.top = std::numeric_limits<Ogre::Real>::infinity();
+void CLevelObject::AddListener(PListener listener) {
+	if (listener)
+		Listeners.insert(listener);
+}
 
-		if (rect.left < boundingRect.right && rect.right > boundingRect.left && rect.bottom >= boundingRect.top)
-			constraints.bottom = (boundingRect.top - rect.bottom);
-		else
-			constraints.bottom = -std::numeric_limits<Ogre::Real>::infinity();
+void CLevelObject::RemoveListener(PListener listener) {
+	Listeners.erase(listener);
+}
 
+void CLevelObject::EnableBoundingBoxCollision() {
+	collisionData = Game::Polygon(aabBounds);
+	BoundingBoxCollision = true;
+	notifyBoundsChanged();
+}
+
+void CLevelObject::SetCollisionPolygon(const Game::Polygon& polygon) {
+	if (collisionData != polygon) {
+		collisionData = polygon;
+		BoundingBoxCollision = false;
+		aabBounds = polygon.GetMinimumEnclosingRectangle();
+		notifyBoundsChanged();
+	}
+}
+
+void CLevelObject::SetPosition(const Ogre::Vector2& position) {
+	if (vPosition != position) {
+		Ogre::Vector2 translate = position - vPosition;
+		aabBounds.Translate(translate);
+		collisionData.Translate(position);
+		vPosition = position;
+		notifyPositionChanged();
+		notifyBoundsChanged();
+	}
+}
+
+void CLevelObject::SetCollisionType(CollisionType collisionType) {
+	if (this->collisionType != collisionType) {
+		this->collisionType = collisionType;
+		notifyCollisionTypeChanged();
+	}
+}
+
+void CLevelObject::SetAABBSize(const Ogre::Vector2& size) {
+	Game::Rectangle newRect(vPosition - 0.5f*size, vPosition + 0.5f*size);
+
+	if (aabBounds != newRect) {
+		aabBounds = newRect;
+		if (BoundingBoxCollision)
+			collisionData = Game::Polygon(aabBounds);
+		notifyBoundsChanged();
+	}
+}
+
+void CLevelObject::SetBoundingBox(const Game::Rectangle& box) {
+	if (aabBounds != box) {
+		aabBounds = box;
+		if (BoundingBoxCollision)
+			collisionData = Game::Polygon(aabBounds);
+		notifyBoundsChanged();
+	}
+}
+
+COgreEntityView::COgreEntityView(PLevelObject model, Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode)
+	: sEntityName(""),
+	  vScale(1.0, 1.0, 1.0),
+	  sMaterial(""),
+	  vPositionOffset(Ogre::Vector3::ZERO),
+	  oScene(ogreScene),
+	  oEntity(NULL),
+	  oParentNode(ogreNode),
+	  oNode(NULL),
+	  qOrientation(Ogre::Quaternion::IDENTITY),
+	  Model(model)
+{
+	assert(model != NULL);
+	UpdateGeometry();
+}
+
+POgreEntityView COgreEntityView::Create(PLevelObject model, Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode) {
+	COgreEntityView* obj = new COgreEntityView(model, ogreScene, ogreNode);
+	POgreEntityView objPtr( obj );
+	obj->self = objPtr;
+	model->AddListener(objPtr);
+	return objPtr;
+}
+
+COgreEntityView::~COgreEntityView() {
+	PLevelObject model = Model.lock();
+	if (model)
+		model->RemoveListener(self.lock());
+}
+
+POgreEntityView COgreEntityView::Copy(PLevelObject model) {
+	COgreEntityView* copy = new COgreEntityView(model);
+	POgreEntityView copyPtr( copy );
+	copy->self = copyPtr;
+	model->AddListener(copyPtr);
+	copy->qOrientation = this->qOrientation;
+	copy->sEntityName = this->sEntityName;
+	copy->sMaterial = this->sMaterial;
+	copy->vPositionOffset = this->vPositionOffset;
+	copy->vScale = this->vScale;
+	return copyPtr;
+}
+
+void COgreEntityView::UpdateGeometry() {
+	PLevelObject model = Model.lock();
+	if (oScene) {
+		if (!oParentNode) {
+			oParentNode = oScene->getRootSceneNode();
+		}
+		if (!oNode) {
+			oNode = oParentNode->createChildSceneNode(Ogre::Vector3::ZERO);
+		}
+		if (oNode) {
+			if (!oEntity && !sEntityName.empty()) {
+				oEntity = oScene->createEntity(sEntityName);
+				if (sMaterial != "")
+					oEntity->setMaterialName(sMaterial);
+				oNode->attachObject(oEntity);
+			}
+			Ogre::Vector2 modelPosition(0.0f, 0.0f);
+			if (model)
+				modelPosition = model->GetPosition();
+			oNode->setPosition(vPositionOffset + Ogre::Vector3(0.0f, modelPosition.y, modelPosition.x));
+			oNode->setScale(vScale);
+			oNode->setOrientation(qOrientation);
+		}
+	}
+}
+
+void COgreEntityView::SetOgreScene(Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode) {
+	oScene = ogreScene;
+	if (oParentNode != ogreNode) {
+		oParentNode = ogreNode;
+		oNode = NULL; oEntity = NULL;
+	}
+	if (ogreScene && !oParentNode)
+		oParentNode = ogreScene->getRootSceneNode();
+	UpdateGeometry();
+}
+
+
+void COgreEntityView::PositionChanged(CLevelObject*) {
+	UpdateGeometry();
+}
+
+void COgreEntityView::SetPositionOffset(const Ogre::Vector3& offset) {
+	if (vPositionOffset != offset) {
+		vPositionOffset = offset;
+		UpdateGeometry();
+	}
+}
+
+void COgreEntityView::SetEntityName(const std::string& name) {
+	if (sEntityName != name) {
+		if (oEntity) {
+			oNode->detachObject(oEntity);
+			oScene->destroyEntity(oEntity);
+		}
+		oEntity = NULL;
+		sEntityName = name;
+		UpdateGeometry();
+	}
+}
+
+void COgreEntityView::SetScale(const Ogre::Vector3& scale) {
+	vScale = scale;
+	UpdateGeometry();
+}
+
+void COgreEntityView::SetMaterial(const std::string& material) {
+	if (sMaterial != material) {
+		sMaterial = material;
+		if (oEntity && sMaterial != "") {
+			oEntity->setMaterialName(sMaterial);
+		}
+		UpdateGeometry();
+	}
+}
+
+void COgreEntityView::SetOrientation(const Ogre::Quaternion& orientation) {
+	qOrientation = orientation;
+	UpdateGeometry();
+}
+
+
+COgreBoundsView::COgreBoundsView(PLevelObject model, Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode)
+	: COgreEntityView(model, ogreScene, ogreNode)
+{
+	this->sEntityName = "cube.mesh";
+	UpdateGeometry();
+}
+
+POgreBoundsView COgreBoundsView::Create(PLevelObject model, Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode) {
+	COgreBoundsView* obj = new COgreBoundsView(model, ogreScene, ogreNode);
+	POgreBoundsView objPtr( obj );
+	obj->self = objPtr;
+	model->AddListener(objPtr);
+	return objPtr;
+}
+
+POgreEntityView COgreBoundsView::Copy(PLevelObject model) {
+	COgreBoundsView* copy = new COgreBoundsView(model);
+	POgreBoundsView copyPtr( copy );
+	copy->self = copyPtr;
+	model->AddListener(copyPtr);
+	copy->qOrientation = this->qOrientation;
+	copy->sEntityName = this->sEntityName;
+	copy->sMaterial = this->sMaterial;
+	copy->vPositionOffset = this->vPositionOffset;
+	copy->vScale = this->vScale;
+	return copyPtr;
+}
+
+void COgreBoundsView::BoundsChanged(CLevelObject*) {
+	UpdateGeometry();
+}
+
+void COgreBoundsView::UpdateGeometry() {
+	PLevelObject model = Model.lock();
+	if (model) {
+		Game::Rectangle bounds = model->GetBoundingBox();
+		Ogre::Vector2 center = 0.5f*(bounds.GetMaximum() + bounds.GetMinimum());
+		this->vPositionOffset = Ogre::Vector3(0.0f, center.y, center.x);
+
+		// cube.mesh is 100x100x100
+		this->vScale.x = 1.0f * 0.01f;
+		Ogre::Vector2 scale2d =  bounds.GetMaximum() - bounds.GetMinimum();
+		this->vScale.y = scale2d.y * 0.01f;
+		this->vScale.z = scale2d.x * 0.01f;
 	}
 
-	return constraints;
-}
+	if (oScene) {
+		if (!oParentNode) {
+			oParentNode = oScene->getRootSceneNode();
+		}
+		if (!oNode) {
+			oNode = oParentNode->createChildSceneNode(Ogre::Vector3::ZERO);
+		}
+		if (oNode) {
+			if (!oEntity && !sEntityName.empty()) {
+				oEntity = oScene->createEntity(sEntityName);
+				if (sMaterial != "")
+					oEntity->setMaterialName(sMaterial);
+				oNode->attachObject(oEntity);
+			}
+			oNode->setPosition(vPositionOffset);
+			oNode->setScale(vScale);
+			oNode->setOrientation(qOrientation);
+		}
+	}
 
-COgreLevelObject::COgreLevelObject(std::string ogreEntityName, const Ogre::Vector3& position)
-	: CLevelObject(position),
-	  sEntityName(ogreEntityName),
-	  vScale(1.0, 1.0, 1.0),
-	  sMaterial("") {
-	this->SetAABBSize(Ogre::Vector3::UNIT_SCALE*10.0f);
-}
-
-COgreLevelObject::~COgreLevelObject() {
-}
-
-void COgreLevelObject::Draw(Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode) {
-	oEntity = ogreScene->createEntity(sEntityName);
-	if (sMaterial != "")
-		oEntity->setMaterialName(sMaterial);
-
-	oNode = ogreNode->createChildSceneNode(Ogre::Vector3::ZERO);
-	oNode->attachObject(oEntity);
-
-	oNode->scale(vScale);
-	oNode->translate(vPosition, Ogre::Node::TS_PARENT);
-	oNode->setOrientation(qOrientation);
+	if (oEntity) {
+		oEntity->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY - 1);
+	}
 }
 
 }

src/GameObjects/LevelObjects.h

 #include "Geometry.h"
 #include "Ogre.h"
 #include "boost/smart_ptr.hpp"
+#include "boost/utility.hpp"
+#include <set>
 
 namespace Game {
 namespace GameObjects {
 
 class CLevelObject;
 typedef boost::shared_ptr<CLevelObject> PLevelObject;
+typedef boost::weak_ptr<CLevelObject> WLevelObject;
 
-/** Basic Level Object with Convex Polygon Collision */
+/** Level Object Model with Convex Polygon Collision */
 class CLevelObject {
 public:
 	enum CollisionType {ctBlocking, ctNonBlocking};
 	typedef std::vector<Game::Face> FaceList;
 
-	CLevelObject() : vPosition(0.0f, 0.0f, 0.0f), collisionType(ctBlocking) {}
-	CLevelObject(const Ogre::Vector3& position) : vPosition(position), collisionType(ctBlocking) {}
-	CLevelObject(const Ogre::Vector3& vMin, const Ogre::Vector3& vMax) : vPosition(0.0f, 0.0f, 0.0f), aabBounds(vMin, vMax), collisionType(ctBlocking) {}
+	class Listener {
+	public:
+		Listener() { }
+		virtual ~Listener() { }
+
+		/** Called when Position has changed */
+		virtual void PositionChanged(CLevelObject*) { }
+		/** Called when Bounding Box has changed */
+		virtual void BoundsChanged(CLevelObject*) { }
+		/** Called when Collision Type has changed */
+		virtual void CollisionTypeChanged(CLevelObject*) { }
+	};
+	typedef boost::shared_ptr<Listener> PListener;
+
+public:
+	CLevelObject();
+	CLevelObject(const Ogre::Vector2& position);
+	CLevelObject(const Game::Rectangle& bounds);
+	CLevelObject(const CLevelObject& obj);
 	virtual ~CLevelObject() {}
 
+	virtual PLevelObject Copy();
+
+	virtual void AddListener(PListener listener);
+	virtual void RemoveListener(PListener listener);
+
 	/** Returns bounding box of object */
-	virtual inline const Ogre::AxisAlignedBox& GetBoundingBox() const { return aabBounds; }
+	virtual const Game::Rectangle& GetBoundingBox() const { return aabBounds; }
 	/** Set bounding box of object */
-	virtual inline void SetBoundingBox(const Ogre::AxisAlignedBox& box) { aabBounds = box; }
-	/** Returns 2D Projection of Bounding Box */
-	virtual Ogre::Rectangle GetBoundingRectangle() const;
+	virtual void SetBoundingBox(const Game::Rectangle& box);
+	/** Returns Bounding Box as Polygon */
+	virtual Game::Polygon GetBoundingBoxPolygon() const { return Game::Polygon(aabBounds); }
 
-	/** Return constraints for given rectangle (obsolete?) */
-	virtual Ogre::Rectangle GetConstraints(const Ogre::Rectangle& rect) const;
-
+	/** Resets collision data to bounding box */
+	virtual void EnableBoundingBoxCollision();
+	virtual bool BoundingBoxCollisionEnabled() const { return BoundingBoxCollision; }
+	/** Set collision polygon */
+	virtual void SetCollisionPolygon(const Game::Polygon& polygon);
 	/** Returns Collision Polygon */
-	virtual Game::Polygon GetPolygon() const;
-	/** Returns Bounding Box as Polygon */
-	inline Game::Polygon GetBoundingBoxPolygon() const { return Game::Polygon(this->GetBoundingRectangle()); }
-
-	/** Return true if object is of type COgreLevelObject*/
-	virtual bool IsOgreObject() { return false; }
+	virtual const Game::Polygon& GetCollisionPolygon() const { return collisionData; }
 
 	virtual CollisionType GetCollisionType() const { return collisionType; };
-	virtual void SetCollisionType(CollisionType collisionType) { this->collisionType = collisionType; };
+	virtual void SetCollisionType(CollisionType collisionType);
 
 	/** Called when another object collides
 	@param sender Origin of collision
 	virtual CollisionType HandleCollision(PLevelObject sender, const Ogre::Vector2& direction) { return collisionType; }
 
 	/** Set Position (also updates bounding box) */
-	inline void SetPosition(const Ogre::Vector3& position) {
-		if (vPosition != position) {
-			Ogre::Vector3 translate = position - vPosition;
-			if (!aabBounds.isNull())
-				aabBounds.setExtents(aabBounds.getMinimum()+translate, aabBounds.getMaximum()+translate);
-			vPosition = position;
-		}
-	}
+	virtual void SetPosition(const Ogre::Vector2& position);
 	/** Returns Center Position */
-	inline const Ogre::Vector3& GetPosition() const { return vPosition; }
+	virtual const Ogre::Vector2& GetPosition() const { return vPosition; }
 
 	/** Set AABB Size (symmetric to center) */
-	inline void SetAABBSize(const Ogre::Vector3& size) { aabBounds.setExtents(vPosition - 0.5f*size, vPosition + 0.5f*size); }
-
+	virtual void SetAABBSize(const Ogre::Vector2& size);
 protected:
 	/** Bounding Box */
-	Ogre::AxisAlignedBox aabBounds;
+	Game::Rectangle aabBounds;
 	/** Position of Center */
-	Ogre::Vector3 vPosition;
+	Ogre::Vector2 vPosition;
 	/** Define if Collision is blocking */
 	CollisionType collisionType;
+	/** Collision Polygon */
+	Game::Polygon collisionData;
+
+	bool BoundingBoxCollision;
+
+	typedef std::set<PListener> ListenerList;
+	ListenerList Listeners;
+
+	void notifyPositionChanged();
+	void notifyBoundsChanged();
+	void notifyCollisionTypeChanged();
 };
 
 
+class COgreEntityView;
+typedef boost::shared_ptr<COgreEntityView> POgreEntityView;
+typedef boost::weak_ptr<COgreEntityView> WOgreEntityView;
 
-/** Level Object bound to Ogre Entity */
-class COgreLevelObject : public CLevelObject {
+/** Level Object View bound to Ogre Entity
+
+@remarks If you don't need to know about the view object, you can just create one and forget about it.
+         The view object will be deleted when the Model is deleted. */
+class COgreEntityView : boost::noncopyable, public CLevelObject::Listener {
 public:
-	/** Create Object from ogre entity name
-	@param ogreEntityName ogre entity name
-	@param position Position in world coordinates
-	@remarks Initializes to 10x10x10 bounding box*/
-	COgreLevelObject(std::string ogreEntityName, const Ogre::Vector3& position);
-	virtual ~COgreLevelObject();
+	/** Factory Method */
+	static POgreEntityView Create(PLevelObject model, Ogre::SceneManager* ogreScene = NULL, Ogre::SceneNode* ogreNode = NULL);
+
+	virtual ~COgreEntityView();
+
+	/** Copy object, set new model
+	@remarks Sets Ogre Scene Manager and Node to NULL */
+	virtual POgreEntityView Copy(PLevelObject model);
+
+	/** Implementation of CLevelObject::Listener::PositionChanged */
+	virtual void PositionChanged(CLevelObject*);
+
+	/** Set Ogre SceneManager and Node. Use rootSceneNode if no Scene Node given
+	@remarks Existing Ogre Entity and Ogre Node will not be deleted */
+	void SetOgreScene(Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode = NULL);
+
+	virtual void SetPositionOffset(const Ogre::Vector3& offset);
+	virtual const Ogre::Vector3& GetPositionOffset() const { return vPositionOffset; }
 
 	/** Set ogre entity name */
-	inline void SetEntityName(const std::string& name) { sEntityName = name; }
-	inline const std::string& GetEntityName() const { return sEntityName; }
+	virtual void SetEntityName(const std::string& name);
+	virtual const std::string& GetEntityName() const { return sEntityName; }
 
 	/** Set scale factor */
-	inline void SetScale(const Ogre::Vector3& scale) { vScale = scale; }
-	inline const Ogre::Vector3& GetScale() const { return vScale; }
+	virtual void SetScale(const Ogre::Vector3& scale);
+	virtual const Ogre::Vector3& GetScale() const { return vScale; }
 
 	/** Set Material */
-	inline void SetMaterial(const std::string& material) { sMaterial = material; }
-	inline const std::string& GetMaterial() const { return sMaterial; }
+	virtual void SetMaterial(const std::string& material);
+	virtual const std::string& GetMaterial() const { return sMaterial; }
 
 	/** Set Orientation */
-	inline void SetOrientation(const Ogre::Quaternion& orientation) { qOrientation = orientation; }
-	inline const Ogre::Quaternion& GetOrientation() const { return qOrientation; }
+	virtual void SetOrientation(const Ogre::Quaternion& orientation);
+	virtual const Ogre::Quaternion& GetOrientation() const { return qOrientation; }
 
-	inline Ogre::Entity* GetOgreEntity() { return oEntity; }
-	inline Ogre::SceneNode* GetOgreNode() { return oNode; }
+	/** Returns corresponding model (can return NULL) */
+	virtual PLevelObject GetModel() { return Model.lock(); }
 
-	virtual bool IsOgreObject() { return true; }
+	virtual Ogre::Entity* GetOgreEntity() { return oEntity; }
+	virtual Ogre::SceneNode* GetOgreNode() { return oNode; }
 
-	virtual void Draw(Ogre::SceneManager* ogreScene, Ogre::SceneNode* ogreNode);
+	/** Returns true if object should be updated every frame */
+	virtual bool IsUpdateable() const { return false; }
+
+	/** Override this to do some updating every frame
+	@param deltaTime Time since last update */
+	virtual void Update(float deltaTime) { }
 protected:
+	COgreEntityView(PLevelObject model, Ogre::SceneManager* ogreScene = NULL, Ogre::SceneNode* ogreNode = NULL);
+	virtual void UpdateGeometry();
+
 	/** ogre entity name*/
 	std::string sEntityName;
 	/** scale factor of ogre entity */
 	Ogre::Vector3 vScale;
 	/** material for ogre entity */
 	std::string sMaterial;
+	/** position offset */
+	Ogre::Vector3 vPositionOffset;
 
+	/** Ogre Scene Manager */
+	Ogre::SceneManager* oScene;
 	/** Pointer to actual ogre entity*/
 	Ogre::Entity* oEntity;
-	/** Pointer to ogre node */
+	/** Pointer to parent ogre node */
+	Ogre::SceneNode* oParentNode;
+	/** Pointer to own ogre node */
 	Ogre::SceneNode* oNode;
 
 	/** orientation of ogre entity */
 	Ogre::Quaternion qOrientation;
+
+	/** Model */
+	WLevelObject Model;
+	/** Smart Pointer of this */
+	WOgreEntityView self;
 };
-typedef boost::shared_ptr<COgreLevelObject> POgreLevelObject;
 
 
+class COgreBoundsView;
+typedef boost::shared_ptr<COgreBoundsView> POgreBoundsView;
+typedef boost::weak_ptr<COgreBoundsView> WOgreBoundsView;
 
-bool Intersect(const Ogre::Rectangle& r1, const Ogre::Rectangle& r2);
-bool Contains(const Ogre::Rectangle& r1, const Ogre::Rectangle& r2);
+/** Level Object View which displays Bounding Box using cube.mesh */
+class COgreBoundsView : public COgreEntityView {
+public:
+	static POgreBoundsView Create(PLevelObject model, Ogre::SceneManager* ogreScene = NULL, Ogre::SceneNode* ogreNode = NULL);
+
+	virtual POgreEntityView Copy(PLevelObject model);
+
+	virtual void BoundsChanged(CLevelObject*);
+protected:
+	COgreBoundsView(PLevelObject model, Ogre::SceneManager* ogreScene = NULL, Ogre::SceneNode* ogreNode = NULL);
+
+	virtual void UpdateGeometry();
+};
+
 
 }
 }

src/GameObjects/ObjectType.h

+/*
+ * LevelDataReaderListener.h
+ *
+ *  Created on: Oct 2, 2010
+ *      Author: crt
+ */
+
+#ifndef LEVELDATAREADERLISTENER_H_
+#define LEVELDATAREADERLISTENER_H_
+
+namespace Game {
+namespace GameObjects {
+
+enum ObjectType {otStatic = 1, otDynamic = 2, otBackground = 3};
+
+}
+}
+
+#endif /* LEVELDATAREADERLISTENER_H_ */

src/States/CEditorState.cpp

 	  oGreenListener(Ogre::ColourValue(0.3, 1, 0.3), Ogre::ColourValue(0.3, 1, 0.3)),
 	  oRedListener(Ogre::ColourValue(1, 0.3, 0.3), Ogre::ColourValue(1, 0.3, 0.3)),
 	  oDarkListener(Ogre::ColourValue(0.1, 0.1, 0.1), Ogre::ColourValue(0.1, 0.1, 0.1)),
-	  ActiveLayer(GameObjects::CLevelData::otStatic),
+	  ActiveLayer(GameObjects::otStatic),
 	  ActiveMode(emMove),
 	  ogreGrid(NULL),
 	  AlignX(alCenter),
 	ogreLevelNode = NULL;
 	DestroySceneNode(oBBNode);
 	oBBNode = NULL;
+
+	for (OgreViewList::iterator it = staticViews.begin(); it != staticViews.end(); ++it) {
+		(*it)->GetModel()->RemoveListener(*it);
+	}
+	for (OgreViewList::iterator it = dynamicViews.begin(); it != dynamicViews.end(); ++it) {
+		(*it)->GetModel()->RemoveListener(*it);
+	}
+	for (OgreViewList::iterator it = backgroundViews.begin(); it != backgroundViews.end(); ++it) {
+		(*it)->GetModel()->RemoveListener(*it);
+	}
+
 	staticLevelData.clear();
+	staticViews.clear();
 	backgroundLevelData.clear();
+	backgroundViews.clear();
 	dynamicLevelData.clear();
+	dynamicViews.clear();
+
+	for (ViewViewMap::iterator it = backupObjects.begin(); it != backupObjects.end(); ++it) {
+		it->second->GetModel()->RemoveListener(it->second);
+	}
 	backupObjects.clear();
+
+	for (OgreViewQueue::iterator it = deletedObjects.begin(); it != deletedObjects.end(); ++it) {
+		(*it)->GetModel()->RemoveListener(*it);
+	}
 	deletedObjects.clear();
+
+	for (OgreViewBoundsMap::iterator it = mBoundingBoxes.begin(); it != mBoundingBoxes.end(); ++it) {
+		it->second->GetModel()->RemoveListener(it->second);
+	}
 	mBoundingBoxes.clear();
 
 	// destroy data reader and reload templates
-	xmlReader = GameObjects::PXMLReader(new GameObjects::CXMLReader());
+	GameObjects::CXMLReader xmlReader;
 
-	if (!xmlReader->Read("media/leveldata/templates.xml"))
+	if (!xmlReader.Read("media/leveldata/templates.xml", this, true))
 		CLog::Get().Write("error loading templates", CLog::logRelease);
 }
 
+void CEditorState::ReadTemplate(std