FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
model.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/structures/purge.h"
31 #include "model/metamodel/abstractpather.h"
32 #include "model/metamodel/object.h"
33 #include "model/metamodel/grids/cellgrid.h"
34 #include "structures/map.h"
35 #include "structures/layer.h"
36 #include "structures/instance.h"
37 #include "util/base/exception.h"
38 #include "view/rendererbase.h"
39 #include "video/renderbackend.h"
40 #include "video/imagepool.h"
41 #include "video/animationpool.h"
42 
43 #include "model.h"
44 
45 namespace FIFE {
46 
47  Model::Model(RenderBackend* renderbackend, const std::vector<RendererBase*>& renderers,
48  ImagePool* imagepool, AnimationPool* animpool):
49  FifeClass(),
50  m_last_namespace(NULL),
51  m_timeprovider(NULL),
52  m_renderbackend(renderbackend),
53  m_imagepool(imagepool),
54  m_animpool(animpool),
55  m_renderers(renderers){
56  }
57 
59  purge(m_maps);
60  for(std::list<namespace_t>::iterator nspace = m_namespaces.begin(); nspace != m_namespaces.end(); ++nspace)
61  purge_map(nspace->second);
62  purge(m_pathers);
63  purge(m_created_grids);
64  purge(m_adopted_grids);
65  }
66 
67  Map* Model::createMap(const std::string& identifier) {
68  std::list<Map*>::const_iterator it = m_maps.begin();
69  for(; it != m_maps.end(); ++it) {
70  if(identifier == (*it)->getId()) {
71  throw NameClash(identifier);
72  }
73  }
74 
75  Map* map = new Map(identifier, m_renderbackend, m_renderers, m_imagepool, m_animpool, &m_timeprovider);
76  m_maps.push_back(map);
77  return map;
78  }
79 
80  void Model::adoptPather(AbstractPather* pather) {
81  m_pathers.push_back(pather);
82  }
83 
84  AbstractPather* Model::getPather(const std::string& pathername) {
85  std::vector<AbstractPather*>::const_iterator it = m_pathers.begin();
86  for(; it != m_pathers.end(); ++it) {
87  if ((*it)->getName() == pathername) {
88  return *it;
89  }
90  }
91  return NULL;
92  }
93 
94  void Model::adoptCellGrid(CellGrid* grid) {
95  m_adopted_grids.push_back(grid);
96  }
97 
98  CellGrid* Model::getCellGrid(const std::string& gridtype) {
99  std::vector<CellGrid*>::const_iterator it = m_adopted_grids.begin();
100  for(; it != m_adopted_grids.end(); ++it) {
101  if ((*it)->getType() == gridtype) {
102  CellGrid* newcg = (*it)->clone();
103  m_created_grids.push_back(newcg);
104  return newcg;
105  }
106  }
107  return NULL;
108  }
109 
110 
111  Map* Model::getMap(const std::string& identifier) const {
112  std::list<Map*>::const_iterator it = m_maps.begin();
113  for(; it != m_maps.end(); ++it) {
114  if((*it)->getId() == identifier)
115  return *it;
116  }
117 
118  throw NotFound(std::string("Tried to get non-existent map: ") + identifier + ".");
119  }
120 
121  void Model::deleteMap(Map* map) {
122  std::list<Map*>::iterator it = m_maps.begin();
123  for(; it != m_maps.end(); ++it) {
124  if(*it == map) {
125  delete *it;
126  m_maps.erase(it);
127  return ;
128  }
129  }
130  }
131 
132  uint32_t Model::getNumMaps() const {
133  return m_maps.size();
134  }
135 
137  purge(m_maps);
138  m_maps.clear();
139  }
140 
141  std::list<std::string> Model::getNamespaces() const {
142  std::list<std::string> namespace_list;
143  std::list<namespace_t>::const_iterator nspace = m_namespaces.begin();
144  for(; nspace != m_namespaces.end(); ++nspace) {
145  namespace_list.push_back(nspace->first);
146  }
147  return namespace_list;
148  }
149 
150  Object* Model::createObject(const std::string& identifier, const std::string& name_space, Object* parent) {
151  // Find or create namespace
152  namespace_t* nspace = selectNamespace(name_space);
153  if(!nspace) {
154  m_namespaces.push_back(namespace_t(name_space,objectmap_t()));
155  nspace = selectNamespace(name_space);
156  }
157 
158  // Check for nameclashes
159  objectmap_t::const_iterator it = nspace->second.find(identifier);
160  if( it != nspace->second.end() ) {
161  throw NameClash(identifier);
162  }
163 
164  // Finally insert & create
165  Object* object = new Object(identifier, name_space, parent);
166  nspace->second[identifier] = object;
167  return object;
168  }
169 
170  bool Model::deleteObject(Object* object) {
171  // WARNING: This code has obviously not been tested (thoroughly).
172 
173  // Check if any instances exist. If yes - bail out.
174  std::list<Layer*>::const_iterator jt;
175  std::vector<Instance*>::const_iterator kt;
176  for(std::list<Map*>::iterator it = m_maps.begin(); it != m_maps.end(); ++it) {
177  for(jt = (*it)->getLayers().begin(); jt != (*it)->getLayers().end(); ++jt) {
178  for(kt = (*jt)->getInstances().begin(); kt != (*jt)->getInstances().end(); ++kt) {
179  Object* o = (*kt)->getObject();
180  if(o == object) {
181  return false;
182  }
183  }
184  }
185  }
186 
187  // Check if the namespace exists
188  namespace_t* nspace = selectNamespace(object->getNamespace());
189  if(!nspace)
190  return true;
191 
192  // If yes - delete+erase object.
193  objectmap_t::iterator it = nspace->second.find(object->getId());
194  if( it != nspace->second.end()) {
195  delete it->second;
196  nspace->second.erase(it);
197  }
198 
199  return true;
200  }
201 
203  // If we have layers with instances - bail out.
204  std::list<Layer*>::const_iterator jt;
205  for(std::list<Map*>::iterator it = m_maps.begin(); it != m_maps.end(); ++it) {
206  for(jt = (*it)->getLayers().begin(); jt != (*it)->getLayers().end(); ++jt) {
207  if((*jt)->hasInstances())
208  return false;
209  }
210  }
211 
212  // Otherwise delete every object in every namespace
213  std::list<namespace_t>::iterator nspace = m_namespaces.begin();
214  while(nspace != m_namespaces.end()) {
215  objectmap_t::iterator it = nspace->second.begin();
216  for(; it != nspace->second.end(); ++it) {
217  delete it->second;
218  }
219  nspace = m_namespaces.erase(nspace);
220  }
221  m_last_namespace = 0;
222  return true;
223  }
224 
225  Object* Model::getObject(const std::string& id, const std::string& name_space) {
226  namespace_t* nspace = selectNamespace(name_space);
227  if(nspace) {
228  objectmap_t::iterator it = nspace->second.find(id);
229  if( it != nspace->second.end() )
230  return it->second;
231  }
232  return 0;
233  }
234 
235  std::list<Object*> Model::getObjects(const std::string& name_space) const {
236  std::list<Object*> object_list;
237  const namespace_t* nspace = selectNamespace(name_space);
238  if(nspace) {
239  objectmap_t::const_iterator it = nspace->second.begin();
240  for(; it != nspace->second.end(); ++it )
241  object_list.push_back(it->second);
242  }
243 
244  return object_list;
245  }
246 
247  const Model::namespace_t* Model::selectNamespace(const std::string& name_space) const {
248  std::list<namespace_t>::const_iterator nspace = m_namespaces.begin();
249  for(; nspace != m_namespaces.end(); ++nspace) {
250  if( nspace->first == name_space ) {
251  return &(*nspace);
252  }
253  }
254  return 0;
255  }
256 
257  Model::namespace_t* Model::selectNamespace(const std::string& name_space) {
258  if( m_last_namespace && m_last_namespace->first == name_space )
259  return m_last_namespace;
260  std::list<namespace_t>::iterator nspace = m_namespaces.begin();
261  for(; nspace != m_namespaces.end(); ++nspace) {
262  if( nspace->first == name_space ) {
263  m_last_namespace = &(*nspace);
264  return m_last_namespace;
265  }
266  }
267  m_last_namespace = 0;
268  return 0;
269  }
270 
271  void Model::update() {
272  std::list<Map*>::iterator it = m_maps.begin();
273  for(; it != m_maps.end(); ++it) {
274  (*it)->update();
275  }
276  std::vector<AbstractPather*>::iterator jt = m_pathers.begin();
277  for(; jt != m_pathers.end(); ++jt) {
278  (*jt)->update();
279  }
280  }
281 
282 } //FIFE
283