Mercurial > fife-parpg
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