layer.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 
00024 // 3rd party library includes
00025 #include <SDL.h>
00026 
00027 // FIFE includes
00028 // These includes are split up in two parts, separated by one empty line
00029 // First block: files included from the FIFE root src directory
00030 // Second block: files included from the same folder
00031 #include "util/log/logger.h"
00032 #include "util/structures/purge.h"
00033 
00034 #include "layer.h"
00035 #include "instance.h"
00036 #include "map.h"
00037 #include "instancetree.h"
00038 
00039 namespace FIFE {
00040 
00041     static Logger _log(LM_STRUCTURES);
00042 
00043     Layer::Layer(const std::string& identifier, Map* map, CellGrid* grid)
00044         : m_id(identifier),
00045         m_map(map),
00046         m_instances_visibility(true),
00047         m_transparency(0),
00048         m_instanceTree(new InstanceTree()),
00049         m_grid(grid),
00050         m_pathingstrategy(CELL_EDGES_ONLY),
00051         m_changelisteners(),
00052         m_changedinstances(),
00053         m_changed(false) {
00054     }
00055 
00056     Layer::~Layer() {
00057         purge(m_instances);
00058         delete m_instanceTree;
00059     }
00060 
00061     bool Layer::hasInstances() const {
00062         return !m_instances.empty();
00063     }
00064 
00065     Instance* Layer::createInstance(Object* object, const ModelCoordinate& p, const std::string& id) {
00066         ExactModelCoordinate emc(static_cast<double>(p.x), static_cast<double>(p.y), static_cast<double>(p.z));
00067         return createInstance(object, emc, id);
00068     }
00069 
00070     Instance* Layer::createInstance(Object* object, const ExactModelCoordinate& p, const std::string& id) {
00071         Location location;
00072         location.setLayer(this);
00073         location.setExactLayerCoordinates(p);
00074 
00075         Instance* instance = new Instance(object, location, id);
00076         if(instance->isActive()) {
00077             setInstanceActivityStatus(instance, instance->isActive());
00078         }
00079         m_instances.push_back(instance);
00080         m_instanceTree->addInstance(instance);
00081 
00082         std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00083         while (i != m_changelisteners.end()) {
00084             (*i)->onInstanceCreate(this, instance);
00085             ++i;
00086         }
00087         m_changed = true;
00088         return instance;
00089     }
00090 
00091     bool Layer::addInstance(Instance* instance, const ExactModelCoordinate& p){
00092         if( !instance ){
00093             FL_ERR(_log, "Tried to add an instance to layer, but given instance is invalid");
00094             return false;
00095         }
00096 
00097         Location location;
00098         location.setLayer(this);
00099         location.setExactLayerCoordinates(p);
00100         instance->setLocation(location);
00101 
00102         m_instances.push_back(instance);
00103         m_instanceTree->addInstance(instance);
00104         if(instance->isActive()) {
00105             setInstanceActivityStatus(instance, instance->isActive());
00106         }
00107 
00108         std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00109         while (i != m_changelisteners.end()) {
00110             (*i)->onInstanceCreate(this, instance);
00111             ++i;
00112         }
00113         m_changed = true;
00114         return true;
00115     }
00116 
00117     void Layer::deleteInstance(Instance* instance) {
00118         std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00119         while (i != m_changelisteners.end()) {
00120             (*i)->onInstanceDelete(this, instance);
00121             ++i;
00122         }
00123         setInstanceActivityStatus(instance, false);
00124         std::vector<Instance*>::iterator it = m_instances.begin();
00125         for(; it != m_instances.end(); ++it) {
00126             if(*it == instance) {
00127                 m_instanceTree->removeInstance(*it);
00128                 delete *it;
00129                 m_instances.erase(it);
00130                 break;
00131             }
00132         }
00133         m_changed = true;
00134     }
00135 
00136     void Layer::setInstanceActivityStatus(Instance* instance, bool active) {
00137         if(active) {
00138             m_active_instances.insert(instance);
00139         } else {
00140             m_active_instances.erase(instance);
00141         }
00142     }
00143 
00144     Instance* Layer::getInstance(const std::string& id) {
00145         std::vector<Instance*>::iterator it = m_instances.begin();
00146         for(; it != m_instances.end(); ++it) {
00147             if((*it)->getId() == id)
00148                 return *it;
00149         }
00150 
00151         return 0;
00152     }
00153 
00154     std::vector<Instance*> Layer::getInstances(const std::string& id) {
00155         std::vector<Instance*> matching_instances;
00156         std::vector<Instance*>::iterator it = m_instances.begin();
00157         for(; it != m_instances.end(); ++it) {
00158             if((*it)->getId() == id)
00159                 matching_instances.push_back(*it);
00160         }
00161         return matching_instances;
00162     }
00163 
00164     std::vector<Instance*> Layer::getInstancesAt(Location& loc, bool use_exactcoordinates) {
00165         std::vector<Instance*> matching_instances;
00166         std::vector<Instance*>::iterator it = m_instances.begin();
00167 
00168         for(; it != m_instances.end(); ++it) {
00169             if (use_exactcoordinates) {
00170                 if ((*it)->getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
00171                     matching_instances.push_back(*it);
00172                 }
00173             } else {
00174                 if ((*it)->getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
00175                     matching_instances.push_back(*it);
00176                 }
00177             }
00178         }
00179 
00180         return matching_instances;
00181     }
00182 
00183     void Layer::getMinMaxCoordinates(ModelCoordinate& min, ModelCoordinate& max, const Layer* layer) const {
00184         if (!layer) {
00185             layer = this;
00186         }
00187 
00188         bool first_found = false;
00189         for (std::vector<Instance*>::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i) {
00190             if (!first_found) {
00191                 min = m_instances.front()->getLocationRef().getLayerCoordinates(layer);
00192                 max = min;
00193                 first_found = true;
00194             } else {
00195                 ModelCoordinate coord = (*i)->getLocationRef().getLayerCoordinates(layer);
00196 
00197                 if(coord.x < min.x) {
00198                     min.x = coord.x;
00199                 }
00200 
00201                 if(coord.x > max.x) {
00202                     max.x = coord.x;
00203                 }
00204 
00205                 if(coord.y < min.y) {
00206                     min.y = coord.y;
00207                 }
00208 
00209                 if(coord.y > max.y) {
00210                     max.y = coord.y;
00211                 }
00212             }
00213         }
00214         if (!first_found) {
00215             min = ModelCoordinate();
00216             max = min;
00217         }
00218     }
00219 
00220     void Layer::setInstancesVisible(bool vis) {
00221         m_instances_visibility = vis;
00222     }
00223 
00224     void Layer::setLayerTransparency(uint8_t transparency) {
00225         m_transparency = transparency;
00226     }
00227 
00228     uint8_t Layer::getLayerTransparency() {
00229         return m_transparency;
00230     }
00231 
00232     void Layer::toggleInstancesVisible() {
00233         m_instances_visibility = !m_instances_visibility;
00234     }
00235 
00236     bool Layer::cellContainsBlockingInstance(const ModelCoordinate& cellCoordinate) {
00237         std::list<Instance*> adjacentInstances;
00238         m_instanceTree->findInstances(cellCoordinate, 0, 0, adjacentInstances);
00239         bool blockingInstance = false;
00240         for(std::list<Instance*>::const_iterator j = adjacentInstances.begin(); j != adjacentInstances.end(); ++j) {
00241             if((*j)->isBlocking() && (*j)->getLocationRef().getLayerCoordinates() == cellCoordinate) {
00242                 blockingInstance = true;
00243             }
00244         }
00245         return blockingInstance;
00246     }
00247 
00248     bool Layer::update() {
00249         m_changedinstances.clear();
00250         std::set<Instance*>::iterator it = m_active_instances.begin();
00251         for(; it != m_active_instances.end(); ++it) {
00252             if ((*it)->update() != ICHANGE_NO_CHANGES) {
00253                 m_changedinstances.push_back(*it);
00254                 m_changed = true;
00255             }
00256         }
00257         if (!m_changedinstances.empty()) {
00258             std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00259             while (i != m_changelisteners.end()) {
00260                 (*i)->onLayerChanged(this, m_changedinstances);
00261                 ++i;
00262             }
00263             //std::cout << "Layer named " << Id() << " changed = 1\n";
00264         }
00265         //std::cout << "Layer named " << Id() << " changed = 0\n";
00266         bool retval = m_changed;
00267         m_changed = false;
00268         return retval;
00269     }
00270 
00271     void Layer::addChangeListener(LayerChangeListener* listener) {
00272         m_changelisteners.push_back(listener);
00273     }
00274 
00275     void Layer::removeChangeListener(LayerChangeListener* listener) {
00276         std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00277         while (i != m_changelisteners.end()) {
00278             if ((*i) == listener) {
00279                 m_changelisteners.erase(i);
00280                 return;
00281             }
00282             ++i;
00283         }
00284     }
00285 } // FIFE
Generated on Wed Nov 23 13:04:43 2011 for FIFE by  doxygen 1.6.3