FIFE
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
mapsaver.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 * Copyright (C) 2005-2013 by the FIFE team *
3 * http://www.fifengine.net *
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 "ext/tinyxml/fife_tinyxml.h"
31 #include "model/structures/map.h"
32 #include "model/structures/layer.h"
34 #include "model/structures/cell.h"
36 #include "model/metamodel/object.h"
38 #include "util/structures/point.h"
39 #include "util/structures/rect.h"
40 #include "view/visual.h"
41 #include "view/camera.h"
42 
43 #include "mapsaver.h"
44 
45 namespace FIFE {
46  static Logger _log(LM_NATIVE_SAVERS);
47 
49  //m_objectSaver = new ObjectSaver();
50  //m_animationSaver = new AnimationSaver();
51  //m_atlasSaver = new AtlasSaver();
52  }
53 
55  {
56 
57  }
58 
60  m_objectSaver = objectSaver;
61  }
62 
63 
65  m_animationSaver = animationSaver;
66  }
67 
68 
69  void MapSaver::setAtlasSaver(const FIFE::AtlasSaverPtr& atlasSaver) {
70  m_atlasSaver = atlasSaver;
71  }
72 
73  void MapSaver::save(const Map& map, const std::string& filename, const std::vector<std::string>& importFiles) {
74  TiXmlDocument doc;
75 
76  // add xml declaration
77  TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "ascii", "");
78  doc.LinkEndChild(decl);
79 
80  // add map element
81  TiXmlElement* mapElement = new TiXmlElement("map");
82  mapElement->SetAttribute("id", map.getId());
83  mapElement->SetAttribute("format", "1.0");
84  doc.LinkEndChild(mapElement);
85 
86  for (std::vector<std::string>::const_iterator iter = importFiles.begin(); iter != importFiles.end(); ++iter)
87  {
88  TiXmlElement* importElement = new TiXmlElement("import");
89  importElement->SetAttribute("file", *iter);
90 
91  // link to map element
92  mapElement->LinkEndChild(importElement);
93  }
94 
95  typedef std::list<Layer*> LayerList;
96  LayerList layers = map.getLayers();
97  for (LayerList::iterator iter = layers.begin(); iter != layers.end(); ++iter)
98  {
99  TiXmlElement* layerElement = new TiXmlElement("layer");
100  CellGrid* grid = (*iter)->getCellGrid();
101  layerElement->SetAttribute("id", (*iter)->getId());
102  layerElement->SetDoubleAttribute("x_offset", grid->getXShift());
103  layerElement->SetDoubleAttribute("y_offset", grid->getYShift());
104  layerElement->SetDoubleAttribute("z_offset", grid->getZShift());
105  layerElement->SetDoubleAttribute("x_scale", grid->getXScale());
106  layerElement->SetDoubleAttribute("y_scale", grid->getYScale());
107  layerElement->SetDoubleAttribute("rotation", grid->getRotation());
108  layerElement->SetAttribute("grid_type", grid->getType());
109  layerElement->SetAttribute("transparency", (*iter)->getLayerTransparency());
110 
111  std::string pathingStrategy;
112  switch ((*iter)->getPathingStrategy())
113  {
114  case CELL_EDGES_ONLY:
115  {
116  pathingStrategy = "cell_edges_only";
117  }
118  break;
120  {
121  pathingStrategy = "cell_edges_and_diagonals";
122  }
123  break;
124  default:
125  {
126  pathingStrategy = "cell_edges_only";
127  }
128  break;
129  }
130  layerElement->SetAttribute("pathing", pathingStrategy);
131 
132  std::string sortingStrategy;
133  switch ((*iter)->getSortingStrategy()) {
134  case SORTING_CAMERA:
135  {
136  sortingStrategy = "camera";
137  }
138  break;
139  case SORTING_LOCATION:
140  {
141  sortingStrategy = "location";
142  }
143  break;
145  {
146  sortingStrategy = "camera_and_location";
147  }
148  break;
149  default:
150  {
151  sortingStrategy = "camera";
152  }
153  break;
154  }
155  layerElement->SetAttribute("sorting", sortingStrategy);
156 
157  if ((*iter)->isWalkable()) {
158  layerElement->SetAttribute("layer_type", "walkable");
159  } else if ((*iter)->isInteract()) {
160  layerElement->SetAttribute("layer_type", "interact");
161  layerElement->SetAttribute("layer_type_id", (*iter)->getWalkableId());
162  }
163 
164  // add layer to document
165  mapElement->LinkEndChild(layerElement);
166 
167  // add instances tag to document
168  TiXmlElement* instancesElement = new TiXmlElement("instances");
169  layerElement->LinkEndChild(instancesElement);
170 
171  std::string currentNamespace = "";
172  typedef std::vector<Instance*> InstancesContainer;
173  InstancesContainer instances = (*iter)->getInstances();
174  for (InstancesContainer::iterator iter = instances.begin(); iter != instances.end(); ++iter)
175  {
176  Object* obj = (*iter)->getObject();
177  // don't save part instances
178  if (obj->isMultiPart()) {
179  continue;
180  }
181 
182  // create instance element
183  TiXmlElement* instanceElement = new TiXmlElement("i");
184 
185  if (!obj->getNamespace().empty() && currentNamespace != obj->getNamespace())
186  {
187  instanceElement->SetAttribute("ns", obj->getNamespace());
188 
189  // update current namespace
190  currentNamespace = obj->getNamespace();
191  }
192 
193  if (!(*iter)->getId().empty())
194  {
195  instanceElement->SetAttribute("id", (*iter)->getId());
196  }
197 
198  instanceElement->SetAttribute("o", obj->getId());
199 
200  ExactModelCoordinate position = (*iter)->getLocationRef().getExactLayerCoordinates();
201  instanceElement->SetDoubleAttribute("x", position.x);
202  instanceElement->SetDoubleAttribute("y", position.y);
203  instanceElement->SetDoubleAttribute("z", position.z);
204  instanceElement->SetAttribute("r", (*iter)->getRotation());
205 
206  if ((*iter)->isBlocking())
207  {
208  instanceElement->SetAttribute("blocking", (*iter)->isBlocking());
209  }
210 
211  if ((*iter)->getCellStackPosition() != obj->getCellStackPosition()) {
212  instanceElement->SetAttribute("cellstack", (*iter)->getCellStackPosition());
213  }
214 
215  if ((*iter)->isVisitor()) {
216  instanceElement->SetAttribute("visitor_radius", (*iter)->getVisitorRadius());
217  std::string shape("none");
218  if ((*iter)->getVisitorShape() == ITYPE_QUAD_SHAPE) {
219  shape = "quad";
220  } else if ((*iter)->getVisitorShape() == ITYPE_CIRCLE_SHAPE) {
221  shape = "circle";
222  }
223  instanceElement->SetAttribute("visitor_shape", shape);
224  }
225 
226  if ((*iter)->isSpecialCost()) {
227  if (!obj->isSpecialCost()) {
228  instanceElement->SetAttribute("cost_id", (*iter)->getCostId());
229  instanceElement->SetDoubleAttribute("cost", (*iter)->getCost());
230  } else if ((*iter)->getCostId() != obj->getCostId() ||
231  !Mathd::Equal((*iter)->getCost(), obj->getCost())) {
232  instanceElement->SetAttribute("cost_id", (*iter)->getCostId());
233  instanceElement->SetDoubleAttribute("cost", (*iter)->getCost());
234  }
235  }
236 
237  InstanceVisual* instanceVisual = (*iter)->getVisual<InstanceVisual>();
238  instanceElement->SetAttribute("stackpos", instanceVisual->getStackPosition());
239 
240  instancesElement->LinkEndChild(instanceElement);
241  }
242  }
243  // add cellcaches tag to document
244  TiXmlElement* cellcachesElement = new TiXmlElement("cellcaches");
245  mapElement->LinkEndChild(cellcachesElement);
246  for (LayerList::iterator iter = layers.begin(); iter != layers.end(); ++iter) {
247  CellCache* cache = (*iter)->getCellCache();
248  if (!cache) {
249  continue;
250  }
251  // add cellcache tag to document
252  TiXmlElement* cellcacheElement = new TiXmlElement("cellcache");
253  cellcacheElement->SetAttribute("id", (*iter)->getId());
254  cellcacheElement->SetDoubleAttribute("default_cost", cache->getDefaultCostMultiplier());
255  cellcacheElement->SetDoubleAttribute("default_speed", cache->getDefaultSpeedMultiplier());
256  cellcacheElement->SetAttribute("search_narrow", cache->isSearchNarrowCells());
257 
258  const std::set<Cell*>& narrowCells = cache->getNarrowCells();
259  bool saveNarrows = !cache->isSearchNarrowCells() && !narrowCells.empty();
260 
261  const std::vector<std::vector<Cell*> >& cells = cache->getCells();
262  std::vector<std::vector<Cell*> >::const_iterator it = cells.begin();
263  for (; it != cells.end(); ++it) {
264  std::vector<Cell*>::const_iterator cit = (*it).begin();
265  for (; cit != (*it).end(); ++cit) {
266  Cell* cell = *cit;
267  std::list<std::string> costIds = cache->getCosts();
268  bool costsEmpty = costIds.empty();
269  bool defaultCost = cell->defaultCost();
270  bool defaultSpeed = cell->defaultSpeed();
271 
272  // check if area is part of the cell or object
273  std::vector<std::string> areaIds = cache->getCellAreas(cell);
274  std::vector<std::string> cellAreaIds;
275  bool areasEmpty = areaIds.empty();
276  if (!areasEmpty) {
277  const std::set<Instance*>& cellInstances = cell->getInstances();
278  if (!cellInstances.empty()) {
279  std::vector<std::string>::iterator area_it = areaIds.begin();
280  for (; area_it != areaIds.end(); ++area_it) {
281  bool objectArea = false;
282  std::set<Instance*>::const_iterator instance_it = cellInstances.begin();
283  for (; instance_it != cellInstances.end(); ++instance_it) {
284  if ((*instance_it)->getObject()->getArea() == *area_it) {
285  objectArea = true;
286  break;
287  }
288  }
289  if (!objectArea) {
290  cellAreaIds.push_back(*area_it);
291  }
292  }
293  } else {
294  cellAreaIds = areaIds;
295  }
296  areasEmpty = cellAreaIds.empty();
297  }
298 
299  CellVisualEffect cve = cell->getFoWType();
300  bool cellVisual = cve == CELLV_CONCEALED;
301  CellTypeInfo cti = cell->getCellType();
302  bool cellBlocker = (cti != CTYPE_CELL_NO_BLOCKER && cti != CTYPE_CELL_BLOCKER);
303  TransitionInfo* transition = cell->getTransition();
304  bool isNarrow = false;
305  if (saveNarrows) {
306  std::set<Cell*>::const_iterator narrow_it = narrowCells.find(cell);
307  if (narrow_it != narrowCells.end()) {
308  isNarrow = true;
309  }
310  }
311  if (costsEmpty && defaultCost && defaultSpeed && areasEmpty &&
312  cellVisual && cellBlocker && !transition && !isNarrow) {
313  continue;
314  }
315  // add cell tag to document
316  ModelCoordinate cellCoord = cell->getLayerCoordinates();
317  TiXmlElement* cellElement = new TiXmlElement("cell");
318  cellElement->SetAttribute("x", cellCoord.x);
319  cellElement->SetAttribute("y", cellCoord.y);
320  if (!defaultCost) {
321  cellElement->SetDoubleAttribute("default_cost", cell->getCostMultiplier());
322  }
323  if (!defaultSpeed) {
324  cellElement->SetDoubleAttribute("default_speed", cell->getSpeedMultiplier());
325  }
326  if (!cellVisual) {
327  if (cve == CELLV_REVEALED) {
328  cellElement->SetAttribute("state", "revealed");
329  } else {
330  cellElement->SetAttribute("state", "masked");
331  }
332  }
333  if (!cellBlocker) {
334  if (cti == CTYPE_CELL_NO_BLOCKER) {
335  cellElement->SetAttribute("blocker_type", "no_blocker");
336  } else {
337  cellElement->SetAttribute("blocker_type", "blocker");
338  }
339  }
340  if (isNarrow) {
341  cellElement->SetAttribute("narrow", true);
342  }
343  // add cost tag
344  if (!costsEmpty) {
345  std::list<std::string>::iterator cost_it = costIds.begin();
346  for (; cost_it != costIds.end(); ++cost_it) {
347  if (cache->existsCostForCell(*cost_it, cell)) {
348  TiXmlElement* costElement = new TiXmlElement("cost");
349  costElement->SetAttribute("id", *cost_it);
350  costElement->SetDoubleAttribute("value", cache->getCost(*cost_it));
351  cellElement->LinkEndChild(costElement);
352  }
353  }
354  }
355  // add area tag
356  if (!areasEmpty) {
357  std::vector<std::string>::iterator area_it = cellAreaIds.begin();
358  for (; area_it != cellAreaIds.end(); ++area_it) {
359  TiXmlElement* areaElement = new TiXmlElement("area");
360  areaElement->SetAttribute("id", *area_it);
361  areaElement->LinkEndChild(areaElement);
362  }
363  }
364  // add transition tag
365  if (transition) {
366  TiXmlElement* transitionElement = new TiXmlElement("transition");
367  transitionElement->SetAttribute("id", transition->m_layer->getId());
368  transitionElement->SetAttribute("x", transition->m_mc.x);
369  transitionElement->SetAttribute("y", transition->m_mc.y);
370  if (transition->m_mc.z != 0) {
371  transitionElement->SetAttribute("z", transition->m_mc.z);
372  }
373  if (transition->m_immediate) {
374  transitionElement->SetAttribute("immediate", true);
375  } else {
376  transitionElement->SetAttribute("immediate", false);
377  }
378  cellElement->LinkEndChild(transitionElement);
379  }
380  cellcacheElement->LinkEndChild(cellElement);
381  }
382  }
383  cellcachesElement->LinkEndChild(cellcacheElement);
384  }
385  typedef std::vector<Camera*> CameraContainer;
386  CameraContainer cameras = map.getCameras();
387  for (CameraContainer::iterator iter = cameras.begin(); iter != cameras.end(); ++iter)
388  {
389  if ((*iter)->getLocationRef().getMap()->getId() == map.getId())
390  {
391  TiXmlElement* cameraElement = new TiXmlElement("camera");
392 
393  cameraElement->SetAttribute("id", (*iter)->getId());
394  cameraElement->SetAttribute("ref_layer_id", (*iter)->getLocation().getLayer()->getId());
395  cameraElement->SetDoubleAttribute("zoom", (*iter)->getZoom());
396  cameraElement->SetDoubleAttribute("tilt", (*iter)->getTilt());
397  cameraElement->SetDoubleAttribute("rotation", (*iter)->getRotation());
398  if ((*iter)->isZToYEnabled()) {
399  cameraElement->SetDoubleAttribute("ztoy", (*iter)->getZToY());
400  }
401 
402  Rect viewport = (*iter)->getViewPort();
403  std::ostringstream viewportString;
404  viewportString << viewport.x << ","
405  << viewport.y << ","
406  << viewport.w << ","
407  << viewport.h;
408 
409  cameraElement->SetAttribute("viewport", viewportString.str());
410 
411  Point p = (*iter)->getCellImageDimensions();
412  cameraElement->SetAttribute("ref_cell_width", p.x);
413  cameraElement->SetAttribute("ref_cell_height", p.y);
414 
415  std::vector<float> lightingColor = (*iter)->getLightingColor();
416  bool writeLightingColor = false;
417  for (uint32_t i=0; i < lightingColor.size(); ++i)
418  {
419  if (lightingColor[i] < 1.0)
420  {
421  writeLightingColor = true;
422  break;
423  }
424  }
425 
426  if (writeLightingColor)
427  {
428  std::ostringstream lightingColorString;
429  for (uint32_t i=0; i < lightingColor.size(); ++i)
430  {
431  if (i > 0)
432  {
433  lightingColorString << ",";
434  }
435 
436  lightingColorString << lightingColor[i];
437 
438  cameraElement->SetAttribute("light_color", lightingColorString.str());
439  }
440  }
441 
442  mapElement->LinkEndChild(cameraElement);
443  }
444  }
445 
446  // save the map xml file
447  doc.SaveFile(filename);
448  }
449 }
double getCost() const
Returns the cost.
Definition: object.cpp:193
double getCostMultiplier()
Returns the current cell cost.
Definition: cell.cpp:423
virtual void setAnimationSaver(const FIFE::AnimationSaverPtr &animationSaver)
allows setting which animation saver will be used to save animation files
Definition: mapsaver.cpp:64
Layer * m_layer
target layer
Definition: cell.h:85
const std::string & getNamespace() const
Definition: object.h:69
int32_t getStackPosition()
Gets current stack position of instance.
Definition: visual.cpp:140
T h
Height of the rectangle.
Definition: rect.h:93
Object class.
Definition: object.h:51
Instance visual contains data that is needed to visualize the instance on screen. ...
Definition: visual.h:111
double getSpeedMultiplier()
Returns the current cell speed.
Definition: cell.cpp:439
T x
The X Coordinate.
Definition: rect.h:84
AtlasSaverPtr m_atlasSaver
Definition: mapsaver.h:73
const std::string & getId() const
Definition: object.h:68
A CellCache is an abstract depiction of one or a few layers and contains additional information...
Definition: cellcache.h:111
ObjectSaverPtr m_objectSaver
Definition: mapsaver.h:71
virtual const std::string & getType() const =0
Type of cellgrid.
static Logger _log(LM_AUDIO)
bool isMultiPart() const
Gets if object is a part of a multi object.
Definition: object.cpp:223
bool defaultCost()
Returns if cell use default cost.
Definition: cell.cpp:415
virtual void setObjectSaver(const FIFE::ObjectSaverPtr &objectSaver)
allows setting which object saver will be used to save object files
Definition: mapsaver.cpp:59
const double getZShift() const
Get the cellgrid z shift.
Definition: cellgrid.h:164
const double getYScale() const
Get the cellgrid y-scaling.
Definition: cellgrid.h:198
Simple class to hold the data for transistions.
Definition: cell.h:82
virtual void setAtlasSaver(const FIFE::AtlasSaverPtr &atlasSaver)
allows setting which atlas saver will be used to save atlas files
Definition: mapsaver.cpp:69
const std::string & getCostId() const
Returns the cost id.
Definition: object.cpp:185
static bool Equal(T _val1, T _val2)
Definition: fife_math.h:286
double getDefaultSpeedMultiplier()
Gets default speed for this CellCache.
Definition: cellcache.cpp:1162
const std::set< Instance * > & getInstances()
Returns all instances on this cell.
Definition: cell.cpp:484
uint8_t CellTypeInfo
Definition: cell.h:65
std::list< std::string > getCosts()
Returns all registered cost ids.
Definition: cellcache.cpp:1013
CellTypeInfo getCellType()
Returns blocker type.
Definition: cell.cpp:476
const double getXScale() const
Get the cellgrid x-scaling.
Definition: cellgrid.h:193
bool existsCostForCell(const std::string &costId, Cell *cell)
Gets if cell is assigned to cost identifier.
Definition: cellcache.cpp:1097
const double getRotation() const
Get the cellgrid rotation.
Definition: cellgrid.h:216
const double getXShift() const
Get the cellgrid x shift.
Definition: cellgrid.h:138
std::vector< std::string > getCellAreas(Cell *cell)
Returns all areas of a cell.
Definition: cellcache.cpp:1467
A basic cell on a CellCache.
Definition: cell.h:136
T y
The Y Coordinate.
Definition: rect.h:87
uint8_t CellVisualEffect
Definition: cell.h:78
const std::string & getId() const
Get the identifier for this map.
Definition: map.h:103
CellVisualEffect getFoWType()
Returns the cell visual.
Definition: cell.cpp:383
const ModelCoordinate getLayerCoordinates() const
Returns the layer coordinates of this cell.
Definition: cell.cpp:496
uint8_t getCellStackPosition() const
Returns cell stack position.
Definition: object.cpp:173
const std::string & getId() const
Get the id of this layer.
Definition: layer.cpp:80
const std::list< Layer * > & getLayers() const
Get the layers on this map.
Definition: map.h:119
const std::vector< std::vector< Cell * > > & getCells()
Returns all cells of this CellCache.
Definition: cellcache.cpp:717
bool isSpecialCost() const
Gets if object uses special cost.
Definition: object.cpp:177
const double getYShift() const
Get the cellgrid y shift.
Definition: cellgrid.h:151
double getCost(const std::string &costId)
Returns the cost value for the given id.
Definition: cellcache.cpp:997
virtual void save(const Map &map, const std::string &filename, const std::vector< std::string > &importFiles)
responsible for saving the map resource used to save map files
Definition: mapsaver.cpp:73
TransitionInfo * getTransition()
Returns the transition.
Definition: cell.cpp:566
A container of Layer(s).
Definition: map.h:87
const std::set< Cell * > & getNarrowCells()
Returns narrow cells.
Definition: cellcache.cpp:1374
unsigned int uint32_t
Definition: core.h:40
double getDefaultCostMultiplier()
Gets default cost for this CellCache.
Definition: cellcache.cpp:1154
MapSaver()
constructor
Definition: mapsaver.cpp:48
const std::vector< Camera * > & getCameras() const
Get a list containing all cameras.
Definition: map.cpp:291
~MapSaver()
destructor
Definition: mapsaver.cpp:54
bool defaultSpeed()
Returns if cell use default speed.
Definition: cell.cpp:431
T w
Width of the rectangle.
Definition: rect.h:90
bool m_immediate
use immediate
Definition: cell.h:93
bool isSearchNarrowCells()
Gets if narrow cells should be searched automatic.
Definition: cellcache.cpp:1394
AnimationSaverPtr m_animationSaver
Definition: mapsaver.h:72
ModelCoordinate m_mc
target coordinates
Definition: cell.h:89