FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
layer.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2008 by the FIFE team *
3  * http://www.fifengine.de *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // 3rd party library includes
25 #include <SDL.h>
26 
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
31 #include "util/log/logger.h"
32 #include "util/structures/purge.h"
33 
34 #include "layer.h"
35 #include "instance.h"
36 #include "map.h"
37 #include "instancetree.h"
38 
39 namespace FIFE {
40 
41  static Logger _log(LM_STRUCTURES);
42 
43  Layer::Layer(const std::string& identifier, Map* map, CellGrid* grid)
44  : m_id(identifier),
45  m_map(map),
46  m_instances_visibility(true),
47  m_transparency(0),
48  m_instanceTree(new InstanceTree()),
49  m_grid(grid),
50  m_pathingstrategy(CELL_EDGES_ONLY),
51  m_changelisteners(),
52  m_changedinstances(),
53  m_changed(false) {
54  }
55 
57  purge(m_instances);
58  delete m_instanceTree;
59  }
60 
61  bool Layer::hasInstances() const {
62  return !m_instances.empty();
63  }
64 
65  Instance* Layer::createInstance(Object* object, const ModelCoordinate& p, const std::string& id) {
66  ExactModelCoordinate emc(static_cast<double>(p.x), static_cast<double>(p.y), static_cast<double>(p.z));
67  return createInstance(object, emc, id);
68  }
69 
70  Instance* Layer::createInstance(Object* object, const ExactModelCoordinate& p, const std::string& id) {
71  Location location;
72  location.setLayer(this);
73  location.setExactLayerCoordinates(p);
74 
75  Instance* instance = new Instance(object, location, id);
76  if(instance->isActive()) {
77  setInstanceActivityStatus(instance, instance->isActive());
78  }
79  m_instances.push_back(instance);
80  m_instanceTree->addInstance(instance);
81 
82  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
83  while (i != m_changelisteners.end()) {
84  (*i)->onInstanceCreate(this, instance);
85  ++i;
86  }
87  m_changed = true;
88  return instance;
89  }
90 
92  if( !instance ){
93  FL_ERR(_log, "Tried to add an instance to layer, but given instance is invalid");
94  return false;
95  }
96 
97  Location location;
98  location.setLayer(this);
99  location.setExactLayerCoordinates(p);
100  instance->setLocation(location);
101 
102  m_instances.push_back(instance);
103  m_instanceTree->addInstance(instance);
104  if(instance->isActive()) {
105  setInstanceActivityStatus(instance, instance->isActive());
106  }
107 
108  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
109  while (i != m_changelisteners.end()) {
110  (*i)->onInstanceCreate(this, instance);
111  ++i;
112  }
113  m_changed = true;
114  return true;
115  }
116 
117  void Layer::deleteInstance(Instance* instance) {
118  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
119  while (i != m_changelisteners.end()) {
120  (*i)->onInstanceDelete(this, instance);
121  ++i;
122  }
123  setInstanceActivityStatus(instance, false);
124  std::vector<Instance*>::iterator it = m_instances.begin();
125  for(; it != m_instances.end(); ++it) {
126  if(*it == instance) {
127  m_instanceTree->removeInstance(*it);
128  delete *it;
129  m_instances.erase(it);
130  break;
131  }
132  }
133  m_changed = true;
134  }
135 
136  void Layer::setInstanceActivityStatus(Instance* instance, bool active) {
137  if(active) {
138  m_active_instances.insert(instance);
139  } else {
140  m_active_instances.erase(instance);
141  }
142  }
143 
144  Instance* Layer::getInstance(const std::string& id) {
145  std::vector<Instance*>::iterator it = m_instances.begin();
146  for(; it != m_instances.end(); ++it) {
147  if((*it)->getId() == id)
148  return *it;
149  }
150 
151  return 0;
152  }
153 
154  std::vector<Instance*> Layer::getInstances(const std::string& id) {
155  std::vector<Instance*> matching_instances;
156  std::vector<Instance*>::iterator it = m_instances.begin();
157  for(; it != m_instances.end(); ++it) {
158  if((*it)->getId() == id)
159  matching_instances.push_back(*it);
160  }
161  return matching_instances;
162  }
163 
164  std::vector<Instance*> Layer::getInstancesAt(Location& loc, bool use_exactcoordinates) {
165  std::vector<Instance*> matching_instances;
166  std::vector<Instance*>::iterator it = m_instances.begin();
167 
168  for(; it != m_instances.end(); ++it) {
169  if (use_exactcoordinates) {
170  if ((*it)->getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
171  matching_instances.push_back(*it);
172  }
173  } else {
174  if ((*it)->getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
175  matching_instances.push_back(*it);
176  }
177  }
178  }
179 
180  return matching_instances;
181  }
182 
183  void Layer::getMinMaxCoordinates(ModelCoordinate& min, ModelCoordinate& max, const Layer* layer) const {
184  if (!layer) {
185  layer = this;
186  }
187 
188  bool first_found = false;
189  for (std::vector<Instance*>::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i) {
190  if (!first_found) {
191  min = m_instances.front()->getLocationRef().getLayerCoordinates(layer);
192  max = min;
193  first_found = true;
194  } else {
195  ModelCoordinate coord = (*i)->getLocationRef().getLayerCoordinates(layer);
196 
197  if(coord.x < min.x) {
198  min.x = coord.x;
199  }
200 
201  if(coord.x > max.x) {
202  max.x = coord.x;
203  }
204 
205  if(coord.y < min.y) {
206  min.y = coord.y;
207  }
208 
209  if(coord.y > max.y) {
210  max.y = coord.y;
211  }
212  }
213  }
214  if (!first_found) {
215  min = ModelCoordinate();
216  max = min;
217  }
218  }
219 
220  void Layer::setInstancesVisible(bool vis) {
221  m_instances_visibility = vis;
222  }
223 
224  void Layer::setLayerTransparency(uint8_t transparency) {
225  m_transparency = transparency;
226  }
227 
229  return m_transparency;
230  }
231 
233  m_instances_visibility = !m_instances_visibility;
234  }
235 
237  std::list<Instance*> adjacentInstances;
238  m_instanceTree->findInstances(cellCoordinate, 0, 0, adjacentInstances);
239  bool blockingInstance = false;
240  for(std::list<Instance*>::const_iterator j = adjacentInstances.begin(); j != adjacentInstances.end(); ++j) {
241  if((*j)->isBlocking() && (*j)->getLocationRef().getLayerCoordinates() == cellCoordinate) {
242  blockingInstance = true;
243  }
244  }
245  return blockingInstance;
246  }
247 
248  bool Layer::update() {
249  m_changedinstances.clear();
250  std::set<Instance*>::iterator it = m_active_instances.begin();
251  for(; it != m_active_instances.end(); ++it) {
252  if ((*it)->update() != ICHANGE_NO_CHANGES) {
253  m_changedinstances.push_back(*it);
254  m_changed = true;
255  }
256  }
257  if (!m_changedinstances.empty()) {
258  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
259  while (i != m_changelisteners.end()) {
260  (*i)->onLayerChanged(this, m_changedinstances);
261  ++i;
262  }
263  //std::cout << "Layer named " << Id() << " changed = 1\n";
264  }
265  //std::cout << "Layer named " << Id() << " changed = 0\n";
266  bool retval = m_changed;
267  m_changed = false;
268  return retval;
269  }
270 
272  m_changelisteners.push_back(listener);
273  }
274 
276  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
277  while (i != m_changelisteners.end()) {
278  if ((*i) == listener) {
279  m_changelisteners.erase(i);
280  return;
281  }
282  ++i;
283  }
284  }
285 } // FIFE