Tileson  1.3.0
A helpful json parser for Tiled maps
Map.hpp
Go to the documentation of this file.
1 //
2 // Created by robin on 22.03.2020.
3 //
4 
5 #ifndef TILESON_MAP_HPP
6 #define TILESON_MAP_HPP
7 
8 #include "../objects/Color.hpp"
9 #include "../objects/Vector2.hpp"
10 //#include "../external/json.hpp"
11 #include "../interfaces/IJson.hpp"
12 #include "../json/NlohmannJson.hpp"
13 #include "../json/PicoJson.hpp"
14 //#include "../json/Gason.hpp" //Unsupported
15 #include "../json/Json11.hpp"
16 
17 #include "Layer.hpp"
18 #include "Tileset.hpp"
19 
20 #include "../common/Enums.hpp"
21 
22 namespace tson
23 {
24  class Map
25  {
26  public:
27  inline Map() = default;
28  inline Map(ParseStatus status, std::string description);
29  inline explicit Map(IJson &json, tson::DecompressorContainer *decompressors);
30  inline bool parse(IJson &json, tson::DecompressorContainer *decompressors);
31 
32  [[nodiscard]] inline const Colori &getBackgroundColor() const;
33  [[nodiscard]] inline const Vector2i &getSize() const;
34  [[nodiscard]] inline int getHexsideLength() const;
35  [[nodiscard]] inline bool isInfinite() const;
36  [[nodiscard]] inline int getNextLayerId() const;
37  [[nodiscard]] inline int getNextObjectId() const;
38  [[nodiscard]] inline const std::string &getOrientation() const;
39  [[nodiscard]] inline const std::string &getRenderOrder() const;
40  [[nodiscard]] inline const std::string &getStaggerAxis() const;
41  [[nodiscard]] inline const std::string &getStaggerIndex() const;
42  [[nodiscard]] inline const std::string &getTiledVersion() const;
43  [[nodiscard]] inline const Vector2i &getTileSize() const;
44  [[nodiscard]] inline const std::string &getType() const;
45  //[[nodiscard]] inline int getVersion() const; //Removed - Tileson v1.3.0
46 
47  [[nodiscard]] inline std::vector<tson::Layer> &getLayers();
48  [[nodiscard]] inline PropertyCollection &getProperties();
49  [[nodiscard]] inline std::vector<tson::Tileset> &getTilesets();
50 
51  [[nodiscard]] inline ParseStatus getStatus() const;
52  [[nodiscard]] inline const std::string &getStatusMessage() const;
53  [[nodiscard]] inline const std::map<uint32_t, tson::Tile *> &getTileMap() const;
54 
55  inline Layer * getLayer(const std::string &name);
56  inline Tileset * getTileset(const std::string &name);
57 
58  template <typename T>
59  inline T get(const std::string &name);
60  inline tson::Property * getProp(const std::string &name);
61 
62  //v1.2.0
63  [[nodiscard]] inline int getCompressionLevel() const;
65  inline Tileset * getTilesetByGid(uint32_t gid);
66 
67 
68  private:
69  inline bool createTilesetData(IJson &json);
70  inline void processData();
71 
72  Colori m_backgroundColor; ;
73  Vector2i m_size;
74  int m_hexsideLength {};
75  bool m_isInfinite {};
76  std::vector<tson::Layer> m_layers;
77  int m_nextLayerId {};
78  int m_nextObjectId {};
79  std::string m_orientation;
80  tson::PropertyCollection m_properties;
81  std::string m_renderOrder;
82  std::string m_staggerAxis;
83  std::string m_staggerIndex;
84  std::string m_tiledVersion;
85  Vector2i m_tileSize;
86  std::vector<tson::Tileset> m_tilesets;
87  std::string m_type;
88  //int m_version{}; /*! 'version': The JSON format version - Removed in Tileson v1.3.0*/
89 
90  ParseStatus m_status {ParseStatus::OK};
91  std::string m_statusMessage {"OK"};
92 
93  std::map<uint32_t, tson::Tile*> m_tileMap;
95  //v1.2.0
96  int m_compressionLevel {-1};
99  tson::DecompressorContainer * m_decompressors;
100  std::map<uint32_t, tson::Tile> m_flaggedTileMap;
101  };
102 
109  template<typename T>
110  T tson::Map::get(const std::string &name)
111  {
112  return m_properties.getValue<T>(name);
113  }
114 }
115 
121 tson::Map::Map(tson::ParseStatus status, std::string description) : m_status {status}, m_statusMessage { std::move(description) }
122 {
123 
124 }
125 
132 {
133  parse(json, decompressors);
134 }
135 
142 {
143  m_decompressors = decompressors;
144 
145  bool allFound = true;
146  if(json.count("compressionlevel") > 0)
147  m_compressionLevel = json["compressionlevel"].get<int>(); //Tiled 1.3 - Optional
148 
149  if(json.count("backgroundcolor") > 0) m_backgroundColor = Colori(json["backgroundcolor"].get<std::string>()); //Optional
150  if(json.count("width") > 0 && json.count("height") > 0 )
151  m_size = {json["width"].get<int>(), json["height"].get<int>()}; else allFound = false;
152  if(json.count("hexsidelength") > 0) m_hexsideLength = json["hexsidelength"].get<int>(); //Optional
153  if(json.count("infinite") > 0) m_isInfinite = json["infinite"].get<bool>(); //Optional
154  if(json.count("nextlayerid") > 0) m_nextLayerId = json["nextlayerid"].get<int>(); //Optional
155  if(json.count("nextobjectid") > 0) m_nextObjectId = json["nextobjectid"].get<int>(); else allFound = false;
156  if(json.count("orientation") > 0) m_orientation = json["orientation"].get<std::string>(); else allFound = false;
157  if(json.count("renderorder") > 0) m_renderOrder = json["renderorder"].get<std::string>(); //Optional
158  if(json.count("staggeraxis") > 0) m_staggerAxis = json["staggeraxis"].get<std::string>(); //Optional
159  if(json.count("staggerindex") > 0) m_staggerIndex = json["staggerindex"].get<std::string>(); //Optional
160  if(json.count("tiledversion") > 0) m_tiledVersion = json["tiledversion"].get<std::string>(); else allFound = false;
161  if(json.count("tilewidth") > 0 && json.count("tileheight") > 0 )
162  m_tileSize = {json["tilewidth"].get<int>(), json["tileheight"].get<int>()}; else allFound = false;
163  if(json.count("type") > 0) m_type = json["type"].get<std::string>(); //Optional
164 
165  //Removed - Changed from a float to string in Tiled v1.6, and old spec said int.
166  //Reason for removal is that it seems to have no real use, as TiledVersion is stored in another variable.
167  //if(json.count("version") > 0) m_version = json["version"].get<int>(); else allFound = false;
168 
169  //More advanced data
170  if(json.count("layers") > 0 && json["layers"].isArray())
171  {
172  auto &array = json.array("layers");
173  std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item)
174  {
175  m_layers.emplace_back(*item, this);
176  });
177  }
178 
179  if(json.count("properties") > 0 && json["properties"].isArray())
180  {
181  auto &array = json.array("properties");
182  std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item)
183  {
184  m_properties.add(*item);
185  });
186  }
187  if(!createTilesetData(json))
188  allFound = false;
189 
190  processData();
191 
192  return allFound;
193 }
194 
198 bool tson::Map::createTilesetData(IJson &json)
199 {
200  bool ok = true;
201  if(json.count("tilesets") > 0 && json["tilesets"].isArray())
202  {
203  //First created tileset objects
204  auto &tilesets = json.array("tilesets");
205  std::for_each(tilesets.begin(), tilesets.end(), [&](std::unique_ptr<IJson> &item)
206  {
207  m_tilesets.emplace_back();
208  });
209 
210  int i = 0;
211  //Then do the parsing
212  std::for_each(tilesets.begin(), tilesets.end(), [&](std::unique_ptr<IJson> &item)
213  {
214  item->directory(json.directory());
215  if(!m_tilesets[i].parse(*item, this))
216  ok = false;
217 
218  ++i;
219  });
220  }
221  return ok;
222 }
223 
227 void tson::Map::processData()
228 {
229  m_tileMap.clear();
230  for(auto &tileset : m_tilesets)
231  {
232  std::for_each(tileset.getTiles().begin(), tileset.getTiles().end(), [&](tson::Tile &tile) { m_tileMap[tile.getGid()] = &tile; });
233  }
234  std::for_each(m_layers.begin(), m_layers.end(), [&](tson::Layer &layer)
235  {
236  layer.assignTileMap(&m_tileMap);
237  layer.createTileData(m_size, m_isInfinite);
238  const std::set<uint32_t> &flaggedTiles = layer.getUniqueFlaggedTiles();
239  for(uint32_t ftile : flaggedTiles)
240  {
241  tson::Tile tile {ftile, layer.getMap()};
242  if(m_tileMap.count(tile.getGid()))
243  {
244  tson::Tile *originalTile = m_tileMap[tile.getGid()];
245  tile.addTilesetAndPerformCalculations(originalTile->getTileset());
246  tile.setProperties(originalTile->getProperties());
247  m_flaggedTileMap[ftile] = tile;
248  m_tileMap[ftile] = &m_flaggedTileMap[ftile];
249  }
250  }
251  layer.resolveFlaggedTiles();
252  });
253 }
254 
260 {
261  return m_backgroundColor;
262 }
263 
269 {
270  return m_size;
271 }
272 
278 {
279  return m_hexsideLength;
280 }
281 
287 {
288  return m_isInfinite;
289 }
290 
296 {
297  return m_nextLayerId;
298 }
299 
305 {
306  return m_nextObjectId;
307 }
308 
313 const std::string &tson::Map::getOrientation() const
314 {
315  return m_orientation;
316 }
317 
322 const std::string &tson::Map::getRenderOrder() const
323 {
324  return m_renderOrder;
325 }
326 
331 const std::string &tson::Map::getStaggerAxis() const
332 {
333  return m_staggerAxis;
334 }
335 
340 const std::string &tson::Map::getStaggerIndex() const
341 {
342  return m_staggerIndex;
343 }
344 
349 const std::string &tson::Map::getTiledVersion() const
350 {
351  return m_tiledVersion;
352 }
353 
359 {
360  return m_tileSize;
361 }
362 
367 const std::string &tson::Map::getType() const
368 {
369  return m_type;
370 }
371 
376 //int tson::Map::getVersion() const
377 //{
378 // return m_version;
379 //}
380 
385 std::vector<tson::Layer> &tson::Map::getLayers()
386 {
387  return m_layers;
388 }
389 
395 {
396  return m_properties;
397 }
398 
403 std::vector<tson::Tileset> &tson::Map::getTilesets()
404 {
405  return m_tilesets;
406 }
407 
408 tson::Layer *tson::Map::getLayer(const std::string &name)
409 {
410  auto result = std::find_if(m_layers.begin(), m_layers.end(), [&](const tson::Layer &item) { return item.getName() == name; });
411  if(result == m_layers.end())
412  return nullptr;
413 
414  return &result.operator*();
415 }
416 
423 tson::Tileset *tson::Map::getTileset(const std::string &name)
424 {
425  auto result = std::find_if(m_tilesets.begin(), m_tilesets.end(), [&](const tson::Tileset &item) {return item.getName() == name; });
426  if(result == m_tilesets.end())
427  return nullptr;
428 
429  return &result.operator*();
430 }
431 
439 {
440  auto result = std::find_if(m_tilesets.begin(), m_tilesets.end(), [&](const tson::Tileset &tileset)
441  {
442  int firstId = tileset.getFirstgid(); //First tile id of the tileset
443  int lastId = (firstId + tileset.getTileCount()) - 1;
444 
445  return (gid >= firstId && gid <= lastId);
446  });
447  if(result == m_tilesets.end())
448  return nullptr;
449 
450  return &result.operator*();
451 }
452 
458 tson::Property *tson::Map::getProp(const std::string &name)
459 {
460  if(m_properties.hasProperty(name))
461  return m_properties.getProperty(name);
462  return nullptr;
463 }
464 
466 {
467  return m_status;
468 }
469 
470 const std::string &tson::Map::getStatusMessage() const
471 {
472  return m_statusMessage;
473 }
474 
479 const std::map<uint32_t, tson::Tile *> &tson::Map::getTileMap() const
480 {
481  return m_tileMap;
482 }
483 
485 {
486  return m_decompressors;
487 }
488 
495 {
496  return m_compressionLevel;
497 }
498 
499 
500 
501 
502 #endif //TILESON_MAP_HPP
Definition: DecompressorContainer.hpp:16
Definition: IJson.hpp:11
T get(std::string_view key)
Definition: IJson.hpp:72
virtual bool isArray() const =0
virtual size_t count(std::string_view key) const =0
virtual std::vector< std::unique_ptr< IJson > > array()=0
Definition: Layer.hpp:26
void resolveFlaggedTiles()
Definition: Layer.hpp:617
Definition: Map.hpp:25
const Vector2i & getSize() const
Definition: Map.hpp:268
ParseStatus getStatus() const
Definition: Map.hpp:465
const std::string & getType() const
Definition: Map.hpp:367
std::vector< tson::Layer > & getLayers()
Definition: Map.hpp:385
const Vector2i & getTileSize() const
Definition: Map.hpp:358
Map()=default
const std::string & getRenderOrder() const
Definition: Map.hpp:322
const std::string & getOrientation() const
Definition: Map.hpp:313
int getCompressionLevel() const
Definition: Map.hpp:494
std::vector< tson::Tileset > & getTilesets()
Definition: Map.hpp:403
const std::string & getStaggerAxis() const
Definition: Map.hpp:331
Tileset * getTileset(const std::string &name)
Definition: Map.hpp:423
const std::string & getStaggerIndex() const
Definition: Map.hpp:340
T get(const std::string &name)
Definition: Map.hpp:110
tson::Property * getProp(const std::string &name)
Definition: Map.hpp:458
int getNextObjectId() const
Definition: Map.hpp:304
Tileset * getTilesetByGid(uint32_t gid)
Definition: Map.hpp:438
bool parse(IJson &json, tson::DecompressorContainer *decompressors)
Definition: Map.hpp:141
Layer * getLayer(const std::string &name)
Definition: Map.hpp:408
PropertyCollection & getProperties()
Definition: Map.hpp:394
const std::string & getTiledVersion() const
Definition: Map.hpp:349
const std::map< uint32_t, tson::Tile * > & getTileMap() const
Definition: Map.hpp:479
const Colori & getBackgroundColor() const
Definition: Map.hpp:259
int getNextLayerId() const
Definition: Map.hpp:295
int getHexsideLength() const
Definition: Map.hpp:277
DecompressorContainer * getDecompressors()
Definition: Map.hpp:484
bool isInfinite() const
Definition: Map.hpp:286
const std::string & getStatusMessage() const
Definition: Map.hpp:470
Definition: PropertyCollection.hpp:15
Definition: Property.hpp:21
Definition: Tile.hpp:22
Definition: Tileset.hpp:24
Definition: Base64.hpp:12
ParseStatus
Definition: Enums.hpp:43
Vector2< int > Vector2i
Definition: Vector2.hpp:51
Color< uint8_t > Colori
Definition: Color.hpp:89