changeset 86:493f23225972

Layer::addInstance for moving instances around layers. Useful when we have multi-level buildings
author Sleek@33b003aa-7bff-0310-803a-e67f0ece8222
date Sat, 19 Jul 2008 10:27:47 +0000
parents 35f6cfea565e
children b12d25014b6a
files layer.cpp
diffstat 1 files changed, 237 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/layer.cpp	Sat Jul 19 10:27:47 2008 +0000
@@ -0,0 +1,237 @@
+/***************************************************************************
+ *   Copyright (C) 2005-2008 by the FIFE team                              *
+ *   http://www.fifengine.de                                               *
+ *   This file is part of FIFE.                                            *
+ *                                                                         *
+ *   FIFE is free software; you can redistribute it and/or modify          *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA              *
+ ***************************************************************************/
+
+// Standard C++ library includes
+
+// 3rd party library includes
+#include <SDL.h>
+
+// FIFE includes
+// 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/structures/purge.h"
+
+#include "layer.h"
+#include "instance.h"
+#include "map.h"
+#include "instancetree.h"
+
+namespace FIFE {
+
+	Layer::Layer(const std::string& identifier, Map* map, CellGrid* grid)
+		: m_id(identifier),
+		m_map(map),
+		m_instances_visibility(true),
+		m_instanceTree(new InstanceTree()),
+		m_grid(grid),
+		m_pathingstrategy(CELL_EDGES_ONLY),
+		m_changelisteners(),
+		m_changedinstances(),
+		m_changed(false) {
+	}
+
+	Layer::~Layer() {
+		purge(m_instances);
+		delete m_instanceTree;
+	}
+
+	bool Layer::hasInstances() const {
+		return !m_instances.empty();
+	}
+
+	Instance* Layer::createInstance(Object* object, const ModelCoordinate& p, const std::string& id) {
+		ExactModelCoordinate emc(static_cast<double>(p.x), static_cast<double>(p.y), static_cast<double>(p.z));
+		return createInstance(object, emc, id);	
+	}
+
+	Instance* Layer::createInstance(Object* object, const ExactModelCoordinate& p, const std::string& id) {
+		Location l;
+		l.setLayer(this);
+		l.setExactLayerCoordinates(p);
+
+		if(id != "") {
+			std::vector<Instance*>::iterator it = m_instances.begin();
+			for(; it != m_instances.end(); ++it) {
+				if((*it)->getId() == id)
+					throw NameClash(id);
+			}
+		}
+
+		Instance* instance = new Instance(object, l, id);
+		m_instances.push_back(instance);
+		m_instanceTree->addInstance(instance);
+		
+		std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
+		while (i != m_changelisteners.end()) {
+			(*i)->onInstanceCreate(this, instance);
+			++i;
+		}
+		m_changed = true;
+		return instance;
+	}
+	
+	Instance* Layer::addInstance(Instance* instance, const ExactModelCoordinate& p){
+	    Location l;
+		l.setLayer(this);
+		l.setExactLayerCoordinates(p);
+        std::string id = instance->getId();
+
+		if(id != "") {
+			std::vector<Instance*>::iterator it = m_instances.begin();
+			for(; it != m_instances.end(); ++it) {
+				if((*it)->getId() == id)
+					throw NameClash(id);
+			}
+		}
+
+		m_instances.push_back(instance);
+		m_instanceTree->addInstance(instance);
+
+		std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
+		while (i != m_changelisteners.end()) {
+			(*i)->onInstanceCreate(this, instance);
+			++i;
+		}
+		m_changed = true;
+		return instance;
+	}
+	
+	void Layer::deleteInstance(Instance* instance) {
+		std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
+		while (i != m_changelisteners.end()) {
+			(*i)->onInstanceDelete(this, instance);
+			++i;
+		}
+	
+		std::vector<Instance*>::iterator it = m_instances.begin();
+		for(; it != m_instances.end(); ++it) {
+			if(*it == instance) {
+				m_instanceTree->removeInstance(*it);
+				delete *it;
+				m_instances.erase(it);
+				break;
+			}
+		}
+		m_changed = true;
+	}
+
+	Instance* Layer::getInstance(const std::string& id) {
+		std::vector<Instance*>::iterator it = m_instances.begin();
+		for(; it != m_instances.end(); ++it) {
+			if((*it)->getId() == id)
+				return *it;
+		}
+
+		throw NotFound(id);
+	}
+
+	void Layer::getMinMaxCoordinates(ModelCoordinate& min, ModelCoordinate& max, const Layer* layer) const {
+		
+		if(layer == 0) {
+			layer = this;
+		}
+		
+		min = m_instances.front()->getLocationRef().getLayerCoordinates(layer);
+		max = min;
+
+		for(std::vector<Instance*>::const_iterator i = m_instances.begin();
+			i != m_instances.end();
+			++i) {
+
+			ModelCoordinate coord = (*i)->getLocationRef().getLayerCoordinates(layer);
+
+			if(coord.x < min.x) {
+				min.x = coord.x;
+			}
+			
+			if(coord.x > max.x) {
+				max.x = coord.x;
+			}
+
+			if(coord.y < min.y) {
+				min.y = coord.y;
+			}
+			
+			if(coord.y > max.y) {
+				max.y = coord.y;
+			}
+		}
+	}
+
+	void Layer::setInstancesVisible(bool vis) {
+		m_instances_visibility = vis;
+	}
+	void Layer::toggleInstancesVisible() {
+		m_instances_visibility = !m_instances_visibility;
+	}
+
+	bool Layer::cellContainsBlockingInstance(const ModelCoordinate& cellCoordinate) {
+		std::list<Instance*> adjacentInstances;
+		m_instanceTree->findInstances(cellCoordinate, 0, 0, adjacentInstances);
+		bool blockingInstance = false;
+		for(std::list<Instance*>::const_iterator j = adjacentInstances.begin(); j != adjacentInstances.end(); ++j) {
+			if((*j)->getObject()->isBlocking() && (*j)->getLocationRef().getLayerCoordinates() == cellCoordinate) {
+				blockingInstance = true;
+			}
+		}
+		return blockingInstance;
+	}
+
+	bool Layer::update() {
+		m_changedinstances.clear();
+		unsigned int curticks = SDL_GetTicks();
+		std::vector<Instance*>::iterator it = m_instances.begin();
+		for(; it != m_instances.end(); ++it) {
+			if ((*it)->update(curticks) != ICHANGE_NO_CHANGES) {
+				m_changedinstances.push_back(*it);
+				m_changed = true;
+			}
+		}
+		if (!m_changedinstances.empty()) {
+			std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
+			while (i != m_changelisteners.end()) {
+				(*i)->onLayerChanged(this, m_changedinstances);
+				++i;
+			}
+			//std::cout << "Layer named " << Id() << " changed = 1\n";
+		}
+		//std::cout << "Layer named " << Id() << " changed = 0\n";
+		bool retval = m_changed;
+		m_changed = false;
+		return retval;
+	}
+	
+	void Layer::addChangeListener(LayerChangeListener* listener) {
+		m_changelisteners.push_back(listener);
+	}
+
+	void Layer::removeChangeListener(LayerChangeListener* listener) {
+		std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
+		while (i != m_changelisteners.end()) {
+			if ((*i) == listener) {
+				m_changelisteners.erase(i);
+				return;
+			}
+			++i;
+		}
+	}
+} // FIFE