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 
00026 // FIFE includes
00027 // These includes are split up in two parts, separated by one empty line
00028 // First block: files included from the FIFE root src directory
00029 // Second block: files included from the same folder
00030 #include "util/log/logger.h"
00031 #include "util/structures/purge.h"
00032 
00033 #include "layer.h"
00034 #include "instance.h"
00035 #include "map.h"
00036 #include "instancetree.h"
00037 
00038 namespace FIFE {
00039 
00040     static Logger _log(LM_STRUCTURES);
00041 
00042     Layer::Layer(const std::string& identifier, Map* map, CellGrid* grid)
00043         : m_id(identifier),
00044         m_map(map),
00045         m_instances_visibility(true),
00046         m_transparency(0),
00047         m_instanceTree(new InstanceTree()),
00048         m_grid(grid),
00049         m_pathingstrategy(CELL_EDGES_ONLY),
00050         m_changelisteners(),
00051         m_changedinstances(),
00052         m_changed(false) {
00053     }
00054 
00055     Layer::~Layer() {
00056         purge(m_instances);
00057         delete m_instanceTree;
00058     }
00059 
00060     bool Layer::hasInstances() const {
00061         return !m_instances.empty();
00062     }
00063 
00064     Instance* Layer::createInstance(Object* object, const ModelCoordinate& p, const std::string& id) {
00065         ExactModelCoordinate emc(static_cast<double>(p.x), static_cast<double>(p.y), static_cast<double>(p.z));
00066         return createInstance(object, emc, id);
00067     }
00068 
00069     Instance* Layer::createInstance(Object* object, const ExactModelCoordinate& p, const std::string& id) {
00070         Location location;
00071         location.setLayer(this);
00072         location.setExactLayerCoordinates(p);
00073 
00074         Instance* instance = new Instance(object, location, id);
00075         if(instance->isActive()) {
00076             setInstanceActivityStatus(instance, instance->isActive());
00077         }
00078         m_instances.push_back(instance);
00079         m_instanceTree->addInstance(instance);
00080 
00081         std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00082         while (i != m_changelisteners.end()) {
00083             (*i)->onInstanceCreate(this, instance);
00084             ++i;
00085         }
00086         m_changed = true;
00087         return instance;
00088     }
00089 
00090     bool Layer::addInstance(Instance* instance, const ExactModelCoordinate& p){
00091         if( !instance ){
00092             FL_ERR(_log, "Tried to add an instance to layer, but given instance is invalid");
00093             return false;
00094         }
00095 
00096         Location location;
00097         location.setLayer(this);
00098         location.setExactLayerCoordinates(p);
00099         instance->setLocation(location);
00100 
00101         m_instances.push_back(instance);
00102         m_instanceTree->addInstance(instance);
00103         if(instance->isActive()) {
00104             setInstanceActivityStatus(instance, instance->isActive());
00105         }
00106 
00107         std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00108         while (i != m_changelisteners.end()) {
00109             (*i)->onInstanceCreate(this, instance);
00110             ++i;
00111         }
00112         m_changed = true;
00113         return true;
00114     }
00115 
00116     void Layer::deleteInstance(Instance* instance) {
00117         std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00118         while (i != m_changelisteners.end()) {
00119             (*i)->onInstanceDelete(this, instance);
00120             ++i;
00121         }
00122         setInstanceActivityStatus(instance, false);
00123         std::vector<Instance*>::iterator it = m_instances.begin();
00124         for(; it != m_instances.end(); ++it) {
00125             if(*it == instance) {
00126                 m_instanceTree->removeInstance(*it);
00127                 delete *it;
00128                 m_instances.erase(it);
00129                 break;
00130             }
00131         }
00132         m_changed = true;
00133     }
00134 
00135     void Layer::setInstanceActivityStatus(Instance* instance, bool active) {
00136         if(active) {
00137             m_active_instances.insert(instance);
00138         } else {
00139             m_active_instances.erase(instance);
00140         }
00141     }
00142 
00143     Instance* Layer::getInstance(const std::string& id) {
00144         std::vector<Instance*>::iterator it = m_instances.begin();
00145         for(; it != m_instances.end(); ++it) {
00146             if((*it)->getId() == id)
00147                 return *it;
00148         }
00149 
00150         return 0;
00151     }
00152 
00153     std::vector<Instance*> Layer::getInstances(const std::string& id) {
00154         std::vector<Instance*> matching_instances;
00155         std::vector<Instance*>::iterator it = m_instances.begin();
00156         for(; it != m_instances.end(); ++it) {
00157             if((*it)->getId() == id)
00158                 matching_instances.push_back(*it);
00159         }
00160         return matching_instances;
00161     }
00162 
00163     std::vector<Instance*> Layer::getInstancesAt(Location& loc, bool use_exactcoordinates) {
00164         std::vector<Instance*> matching_instances;
00165         std::vector<Instance*>::iterator it = m_instances.begin();
00166 
00167         for(; it != m_instances.end(); ++it) {
00168             if (use_exactcoordinates) {
00169                 if ((*it)->getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
00170                     matching_instances.push_back(*it);
00171                 }
00172             } else {
00173                 if ((*it)->getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
00174                     matching_instances.push_back(*it);
00175                 }
00176             }
00177         }
00178 
00179         return matching_instances;
00180     }
00181 
00182     std::list<Instance*> Layer::getInstancesIn(Rect& rec) {
00183         std::list<Instance*> matching_instances;
00184         ModelCoordinate mc(rec.x, rec.y);
00185         m_instanceTree->findInstances(mc, rec.w, rec.h, matching_instances);
00186 
00187         return matching_instances;
00188     }
00189 
00190     void Layer::getMinMaxCoordinates(ModelCoordinate& min, ModelCoordinate& max, const Layer* layer) const {
00191         if (!layer) {
00192             layer = this;
00193         }
00194 
00195         if (m_instances.empty()) {
00196             min = ModelCoordinate();
00197             max = min;
00198         } else {
00199             min = m_instances.front()->getLocationRef().getLayerCoordinates(layer);
00200             max = min;
00201 
00202             for (std::vector<Instance*>::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i) {
00203                 ModelCoordinate coord = (*i)->getLocationRef().getLayerCoordinates(layer);
00204 
00205                 if(coord.x < min.x) {
00206                     min.x = coord.x;
00207                 }
00208 
00209                 if(coord.x > max.x) {
00210                     max.x = coord.x;
00211                 }
00212 
00213                 if(coord.y < min.y) {
00214                     min.y = coord.y;
00215                 }
00216 
00217                 if(coord.y > max.y) {
00218                     max.y = coord.y;
00219                 }
00220             }
00221         }
00222 
00223     }
00224 
00225     void Layer::setInstancesVisible(bool vis) {
00226         m_instances_visibility = vis;
00227     }
00228 
00229     void Layer::setLayerTransparency(uint8_t transparency) {
00230         m_transparency = transparency;
00231     }
00232 
00233     uint8_t Layer::getLayerTransparency() {
00234         return m_transparency;
00235     }
00236 
00237     void Layer::toggleInstancesVisible() {
00238         m_instances_visibility = !m_instances_visibility;
00239     }
00240 
00241     bool Layer::cellContainsBlockingInstance(const ModelCoordinate& cellCoordinate) {
00242         std::list<Instance*> adjacentInstances;
00243         m_instanceTree->findInstances(cellCoordinate, 0, 0, adjacentInstances);
00244         bool blockingInstance = false;
00245         for(std::list<Instance*>::const_iterator j = adjacentInstances.begin(); j != adjacentInstances.end(); ++j) {
00246             if((*j)->isBlocking() && (*j)->getLocationRef().getLayerCoordinates() == cellCoordinate) {
00247                 blockingInstance = true;
00248                 break;
00249             }
00250         }
00251         return blockingInstance;
00252     }
00253 
00254     bool Layer::update() {
00255         m_changedinstances.clear();
00256         std::vector<Instance*> inactive_instances;
00257         std::set<Instance*>::iterator it = m_active_instances.begin();
00258         for(; it != m_active_instances.end(); ++it) {
00259             if ((*it)->update() != ICHANGE_NO_CHANGES) {
00260                 m_changedinstances.push_back(*it);
00261                 m_changed = true;
00262             } else if (!(*it)->isActive()) {
00263                 inactive_instances.push_back(*it);
00264             }
00265         }
00266         if (!m_changedinstances.empty()) {
00267             std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00268             while (i != m_changelisteners.end()) {
00269                 (*i)->onLayerChanged(this, m_changedinstances);
00270                 ++i;
00271             }
00272             //std::cout << "Layer named " << Id() << " changed = 1\n";
00273         }
00274         // remove inactive instances from m_active_instances
00275         if (!inactive_instances.empty()) {
00276             std::vector<Instance*>::iterator i = inactive_instances.begin();
00277             while (i != inactive_instances.end()) {
00278                 m_active_instances.erase(*i);
00279                 ++i;
00280             }
00281         }
00282         //std::cout << "Layer named " << Id() << " changed = 0\n";
00283         bool retval = m_changed;
00284         m_changed = false;
00285         return retval;
00286     }
00287 
00288     void Layer::addChangeListener(LayerChangeListener* listener) {
00289         m_changelisteners.push_back(listener);
00290     }
00291 
00292     void Layer::removeChangeListener(LayerChangeListener* listener) {
00293         std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
00294         while (i != m_changelisteners.end()) {
00295             if ((*i) == listener) {
00296                 m_changelisteners.erase(i);
00297                 return;
00298             }
00299             ++i;
00300         }
00301     }
00302 } // FIFE