FIFE  2008.0
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 
26 // FIFE includes
27 // These includes are split up in two parts, separated by one empty line
28 // First block: files included from the FIFE root src directory
29 // Second block: files included from the same folder
30 #include "util/log/logger.h"
31 #include "util/structures/purge.h"
32 
33 #include "layer.h"
34 #include "instance.h"
35 #include "map.h"
36 #include "instancetree.h"
37 
38 namespace FIFE {
39 
40  static Logger _log(LM_STRUCTURES);
41 
42  Layer::Layer(const std::string& identifier, Map* map, CellGrid* grid)
43  : m_id(identifier),
44  m_map(map),
45  m_instances_visibility(true),
46  m_transparency(0),
47  m_instanceTree(new InstanceTree()),
48  m_grid(grid),
49  m_pathingstrategy(CELL_EDGES_ONLY),
50  m_changelisteners(),
51  m_changedinstances(),
52  m_changed(false) {
53  }
54 
56  purge(m_instances);
57  delete m_instanceTree;
58  }
59 
60  bool Layer::hasInstances() const {
61  return !m_instances.empty();
62  }
63 
64  Instance* Layer::createInstance(Object* object, const ModelCoordinate& p, const std::string& id) {
65  ExactModelCoordinate emc(static_cast<double>(p.x), static_cast<double>(p.y), static_cast<double>(p.z));
66  return createInstance(object, emc, id);
67  }
68 
69  Instance* Layer::createInstance(Object* object, const ExactModelCoordinate& p, const std::string& id) {
70  Location location;
71  location.setLayer(this);
72  location.setExactLayerCoordinates(p);
73 
74  Instance* instance = new Instance(object, location, id);
75  if(instance->isActive()) {
76  setInstanceActivityStatus(instance, instance->isActive());
77  }
78  m_instances.push_back(instance);
79  m_instanceTree->addInstance(instance);
80 
81  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
82  while (i != m_changelisteners.end()) {
83  (*i)->onInstanceCreate(this, instance);
84  ++i;
85  }
86  m_changed = true;
87  return instance;
88  }
89 
91  if( !instance ){
92  FL_ERR(_log, "Tried to add an instance to layer, but given instance is invalid");
93  return false;
94  }
95 
96  Location location;
97  location.setLayer(this);
98  location.setExactLayerCoordinates(p);
99  instance->setLocation(location);
100 
101  m_instances.push_back(instance);
102  m_instanceTree->addInstance(instance);
103  if(instance->isActive()) {
104  setInstanceActivityStatus(instance, instance->isActive());
105  }
106 
107  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
108  while (i != m_changelisteners.end()) {
109  (*i)->onInstanceCreate(this, instance);
110  ++i;
111  }
112  m_changed = true;
113  return true;
114  }
115 
116  void Layer::deleteInstance(Instance* instance) {
117  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
118  while (i != m_changelisteners.end()) {
119  (*i)->onInstanceDelete(this, instance);
120  ++i;
121  }
122  setInstanceActivityStatus(instance, false);
123  std::vector<Instance*>::iterator it = m_instances.begin();
124  for(; it != m_instances.end(); ++it) {
125  if(*it == instance) {
126  m_instanceTree->removeInstance(*it);
127  delete *it;
128  m_instances.erase(it);
129  break;
130  }
131  }
132  m_changed = true;
133  }
134 
135  void Layer::setInstanceActivityStatus(Instance* instance, bool active) {
136  if(active) {
137  m_active_instances.insert(instance);
138  } else {
139  m_active_instances.erase(instance);
140  }
141  }
142 
143  Instance* Layer::getInstance(const std::string& id) {
144  std::vector<Instance*>::iterator it = m_instances.begin();
145  for(; it != m_instances.end(); ++it) {
146  if((*it)->getId() == id)
147  return *it;
148  }
149 
150  return 0;
151  }
152 
153  std::vector<Instance*> Layer::getInstances(const std::string& id) {
154  std::vector<Instance*> matching_instances;
155  std::vector<Instance*>::iterator it = m_instances.begin();
156  for(; it != m_instances.end(); ++it) {
157  if((*it)->getId() == id)
158  matching_instances.push_back(*it);
159  }
160  return matching_instances;
161  }
162 
163  std::vector<Instance*> Layer::getInstancesAt(Location& loc, bool use_exactcoordinates) {
164  std::vector<Instance*> matching_instances;
165  std::vector<Instance*>::iterator it = m_instances.begin();
166 
167  for(; it != m_instances.end(); ++it) {
168  if (use_exactcoordinates) {
169  if ((*it)->getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
170  matching_instances.push_back(*it);
171  }
172  } else {
173  if ((*it)->getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
174  matching_instances.push_back(*it);
175  }
176  }
177  }
178 
179  return matching_instances;
180  }
181 
182  std::list<Instance*> Layer::getInstancesIn(Rect& rec) {
183  std::list<Instance*> matching_instances;
184  ModelCoordinate mc(rec.x, rec.y);
185  m_instanceTree->findInstances(mc, rec.w, rec.h, matching_instances);
186 
187  return matching_instances;
188  }
189 
190  void Layer::getMinMaxCoordinates(ModelCoordinate& min, ModelCoordinate& max, const Layer* layer) const {
191  if (!layer) {
192  layer = this;
193  }
194 
195  if (m_instances.empty()) {
196  min = ModelCoordinate();
197  max = min;
198  } else {
199  min = m_instances.front()->getLocationRef().getLayerCoordinates(layer);
200  max = min;
201 
202  for (std::vector<Instance*>::const_iterator i = m_instances.begin(); i != m_instances.end(); ++i) {
203  ModelCoordinate coord = (*i)->getLocationRef().getLayerCoordinates(layer);
204 
205  if(coord.x < min.x) {
206  min.x = coord.x;
207  }
208 
209  if(coord.x > max.x) {
210  max.x = coord.x;
211  }
212 
213  if(coord.y < min.y) {
214  min.y = coord.y;
215  }
216 
217  if(coord.y > max.y) {
218  max.y = coord.y;
219  }
220  }
221  }
222 
223  }
224 
225  void Layer::setInstancesVisible(bool vis) {
226  m_instances_visibility = vis;
227  }
228 
229  void Layer::setLayerTransparency(uint8_t transparency) {
230  m_transparency = transparency;
231  }
232 
234  return m_transparency;
235  }
236 
238  m_instances_visibility = !m_instances_visibility;
239  }
240 
242  std::list<Instance*> adjacentInstances;
243  m_instanceTree->findInstances(cellCoordinate, 0, 0, adjacentInstances);
244  bool blockingInstance = false;
245  for(std::list<Instance*>::const_iterator j = adjacentInstances.begin(); j != adjacentInstances.end(); ++j) {
246  if((*j)->isBlocking() && (*j)->getLocationRef().getLayerCoordinates() == cellCoordinate) {
247  blockingInstance = true;
248  break;
249  }
250  }
251  return blockingInstance;
252  }
253 
254  bool Layer::update() {
255  m_changedinstances.clear();
256  std::vector<Instance*> inactive_instances;
257  std::set<Instance*>::iterator it = m_active_instances.begin();
258  for(; it != m_active_instances.end(); ++it) {
259  if ((*it)->update() != ICHANGE_NO_CHANGES) {
260  m_changedinstances.push_back(*it);
261  m_changed = true;
262  } else if (!(*it)->isActive()) {
263  inactive_instances.push_back(*it);
264  }
265  }
266  if (!m_changedinstances.empty()) {
267  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
268  while (i != m_changelisteners.end()) {
269  (*i)->onLayerChanged(this, m_changedinstances);
270  ++i;
271  }
272  //std::cout << "Layer named " << Id() << " changed = 1\n";
273  }
274  // remove inactive instances from m_active_instances
275  if (!inactive_instances.empty()) {
276  std::vector<Instance*>::iterator i = inactive_instances.begin();
277  while (i != inactive_instances.end()) {
278  m_active_instances.erase(*i);
279  ++i;
280  }
281  }
282  //std::cout << "Layer named " << Id() << " changed = 0\n";
283  bool retval = m_changed;
284  m_changed = false;
285  return retval;
286  }
287 
289  m_changelisteners.push_back(listener);
290  }
291 
293  std::vector<LayerChangeListener*>::iterator i = m_changelisteners.begin();
294  while (i != m_changelisteners.end()) {
295  if ((*i) == listener) {
296  m_changelisteners.erase(i);
297  return;
298  }
299  ++i;
300  }
301  }
302 } // FIFE
void setInstancesVisible(bool vis)
Definition: layer.cpp:225
std::vector< Instance * > getInstancesAt(Location &loc, bool use_exactcoordinates=false)
Definition: layer.cpp:163
bool isActive() const
Definition: instance.cpp:227
void toggleInstancesVisible()
Definition: layer.cpp:237
bool hasInstances() const
Definition: layer.cpp:60
std::list< Instance * > getInstancesIn(Rect &rec)
Definition: layer.cpp:182
const std::vector< Instance * > & getInstances() const
Definition: layer.h:156
Instance * createInstance(Object *object, const ModelCoordinate &p, const std::string &id="")
Definition: layer.cpp:64
Layer(const std::string &identifier, Map *map, CellGrid *grid)
Definition: layer.cpp:42
bool update()
Definition: layer.cpp:254
void getMinMaxCoordinates(ModelCoordinate &min, ModelCoordinate &max, const Layer *layer=0) const
Definition: layer.cpp:190
void removeChangeListener(LayerChangeListener *listener)
Definition: layer.cpp:292
bool addInstance(Instance *instance, const ExactModelCoordinate &p)
Definition: layer.cpp:90
Instance * getInstance(const std::string &identifier)
Definition: layer.cpp:143
void addChangeListener(LayerChangeListener *listener)
Definition: layer.cpp:288
void deleteInstance(Instance *object)
Definition: layer.cpp:116
void setLayerTransparency(uint8_t transparency)
Definition: layer.cpp:229
bool cellContainsBlockingInstance(const ModelCoordinate &cellCoordinate)
Definition: layer.cpp:241
Definition: map.h:86
uint8_t getLayerTransparency()
Definition: layer.cpp:233
void setLocation(const Location &loc)
Definition: instance.cpp:231
credit to phoku for his NodeDisplay example which the visitor code is adapted from ( he coded the qua...
Definition: soundclip.cpp:39