Tileson 1.4.0
A helpful json parser for Tiled maps
Loading...
Searching...
No Matches
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 <functional>
9
10#include "../objects/Color.hpp"
11#include "../objects/Vector2.hpp"
12//#include "../external/json.hpp"
13#include "../interfaces/IJson.hpp"
14#include "../json/NlohmannJson.hpp"
15#include "../json/PicoJson.hpp"
16//#include "../json/Gason.hpp" //Unsupported
17#include "../json/Json11.hpp"
18
19#include "Layer.hpp"
20#include "Tileset.hpp"
21
22#include "../common/Enums.hpp"
23
24namespace tson
25{
26 using LinkedFileParser = std::function<std::unique_ptr<IJson>(std::string relativePath)>;
27 class Object;
28 class Map
29 {
30 friend class Object;
31 public:
32 inline Map() = default;
33 inline Map(ParseStatus status, std::string description);
34 inline explicit Map(IJson &json, tson::DecompressorContainer *decompressors, tson::Project *project, tson::LinkedFileParser linkedFileParser = nullptr);
35 inline bool parse(IJson &json, tson::DecompressorContainer *decompressors, tson::Project *project, tson::LinkedFileParser linkedFileParser = nullptr);
36
37 [[nodiscard]] inline const Colori &getBackgroundColor() const;
38 [[nodiscard]] inline const Vector2i &getSize() const;
39 [[nodiscard]] inline int getHexsideLength() const;
40 [[nodiscard]] inline bool isInfinite() const;
41 [[nodiscard]] inline int getNextLayerId() const;
42 [[nodiscard]] inline int getNextObjectId() const;
43 [[nodiscard]] inline const std::string &getOrientation() const;
44 [[nodiscard]] inline const std::string &getRenderOrder() const;
45 [[nodiscard]] inline const std::string &getStaggerAxis() const;
46 [[nodiscard]] inline const std::string &getStaggerIndex() const;
47 [[nodiscard]] inline const std::string &getTiledVersion() const;
48 [[nodiscard]] inline const Vector2i &getTileSize() const;
49 [[nodiscard]] inline const std::string &getType() const;
50 [[nodiscard]] inline const std::string &getClassType() const;
51 [[nodiscard]] inline tson::TiledClass *getClass();
52 [[nodiscard]] inline const Vector2f &getParallaxOrigin() const;
53 //[[nodiscard]] inline int getVersion() const; //Removed - Tileson v1.3.0
54
55 [[nodiscard]] inline std::vector<tson::Layer> &getLayers();
56 [[nodiscard]] inline PropertyCollection &getProperties();
57 [[nodiscard]] inline std::vector<tson::Tileset> &getTilesets();
58
59 [[nodiscard]] inline ParseStatus getStatus() const;
60 [[nodiscard]] inline const std::string &getStatusMessage() const;
61 [[nodiscard]] inline const std::map<uint32_t, tson::Tile *> &getTileMap() const;
62
63 inline Layer * getLayer(const std::string &name);
64 inline Tileset * getTileset(const std::string &name);
65
66 template <typename T>
67 inline T get(const std::string &name);
68 inline tson::Property * getProp(const std::string &name);
69
70 //v1.2.0
71 [[nodiscard]] inline int getCompressionLevel() const;
73 inline Project * getProject();
74 inline Tileset * getTilesetByGid(uint32_t gid);
75
76
77 private:
78 inline IJson* parseLinkedFile(const std::string& path);
79 inline bool createTilesetData(IJson &json);
80 inline void processData();
81
82 Colori m_backgroundColor; ;
83 Vector2i m_size;
84 int m_hexsideLength {};
85 bool m_isInfinite {};
86 std::vector<tson::Layer> m_layers;
87 int m_nextLayerId {};
88 int m_nextObjectId {};
89 std::string m_orientation;
90 tson::PropertyCollection m_properties;
91 std::string m_renderOrder;
92 std::string m_staggerAxis;
93 std::string m_staggerIndex;
94 std::string m_tiledVersion;
95 Vector2i m_tileSize;
96 std::vector<tson::Tileset> m_tilesets;
97 std::string m_type;
98 tson::Vector2f m_parallaxOrigin;
99 //int m_version{}; /*! 'version': The JSON format version - Removed in Tileson v1.3.0*/
100
101 ParseStatus m_status {ParseStatus::OK};
102 std::string m_statusMessage {"OK"};
103
104 std::map<uint32_t, tson::Tile*> m_tileMap{};
106 //v1.2.0
107 int m_compressionLevel {-1};
110 tson::DecompressorContainer * m_decompressors {nullptr};
111 tson::Project * m_project {nullptr};
112 std::map<uint32_t, tson::Tile> m_flaggedTileMap{};
114 std::string m_classType{};
115 std::shared_ptr<tson::TiledClass> m_class {};
116
117 tson::LinkedFileParser m_linkedFileParser;
118 std::map<std::string, std::unique_ptr<IJson>> m_linkedFiles;
119 };
120
127 template<typename T>
128 T tson::Map::get(const std::string &name)
129 {
130 return m_properties.getValue<T>(name);
131 }
132}
133
139tson::Map::Map(tson::ParseStatus status, std::string description) : m_status {status}, m_statusMessage { std::move(description) }
140{
141
142}
143
151{
152 parse(json, decompressors, project, linkedFileParser);
153}
154
161bool tson::Map::parse(IJson &json, tson::DecompressorContainer *decompressors, tson::Project *project, tson::LinkedFileParser linkedFileParser)
162{
163 m_decompressors = decompressors;
164 m_project = project;
165 m_linkedFileParser = linkedFileParser;
166
167 if(!m_linkedFileParser)
168 { // build a default linked file parser out of processing relative paths to
169 // the main json's location.
170 m_linkedFileParser = [&json](std::string relativePath) -> std::unique_ptr<IJson>
171 {
172 if(json.directory().empty())
173 return nullptr;
174
175 std::unique_ptr<IJson> linkedFileJson = json.create();
176 bool parseOk = linkedFileJson->parse(json.directory() / relativePath);
177 if(parseOk)
178 return linkedFileJson;
179 else
180 return nullptr;
181 };
182 }
183
184 bool allFound = true;
185 if(json.count("compressionlevel") > 0)
186 m_compressionLevel = json["compressionlevel"].get<int>(); //Tiled 1.3 - Optional
187
188 if(json.count("backgroundcolor") > 0) m_backgroundColor = Colori(json["backgroundcolor"].get<std::string>()); //Optional
189 if(json.count("width") > 0 && json.count("height") > 0 )
190 m_size = {json["width"].get<int>(), json["height"].get<int>()}; else allFound = false;
191 if(json.count("hexsidelength") > 0) m_hexsideLength = json["hexsidelength"].get<int>(); //Optional
192 if(json.count("infinite") > 0) m_isInfinite = json["infinite"].get<bool>(); //Optional
193 if(json.count("nextlayerid") > 0) m_nextLayerId = json["nextlayerid"].get<int>(); //Optional
194 if(json.count("nextobjectid") > 0) m_nextObjectId = json["nextobjectid"].get<int>(); else allFound = false;
195 if(json.count("orientation") > 0) m_orientation = json["orientation"].get<std::string>(); else allFound = false;
196 if(json.count("renderorder") > 0) m_renderOrder = json["renderorder"].get<std::string>(); //Optional
197 if(json.count("staggeraxis") > 0) m_staggerAxis = json["staggeraxis"].get<std::string>(); //Optional
198 if(json.count("staggerindex") > 0) m_staggerIndex = json["staggerindex"].get<std::string>(); //Optional
199 if(json.count("tiledversion") > 0) m_tiledVersion = json["tiledversion"].get<std::string>(); else allFound = false;
200 if(json.count("tilewidth") > 0 && json.count("tileheight") > 0 )
201 m_tileSize = {json["tilewidth"].get<int>(), json["tileheight"].get<int>()}; else allFound = false;
202 if(json.count("type") > 0) m_type = json["type"].get<std::string>(); //Optional
203 if(json.count("class") > 0) m_classType = json["class"].get<std::string>(); //Optional
204
205 //Removed - Changed from a float to string in Tiled v1.6, and old spec said int.
206 //Reason for removal is that it seems to have no real use, as TiledVersion is stored in another variable.
207 //if(json.count("version") > 0) m_version = json["version"].get<int>(); else allFound = false;
208
209 //More advanced data
210 if(json.count("layers") > 0 && json["layers"].isArray())
211 {
212 auto &array = json.array("layers");
213 std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item)
214 {
215 m_layers.emplace_back(*item, this);
216 });
217 }
218
219 if(json.count("properties") > 0 && json["properties"].isArray())
220 {
221 auto &array = json.array("properties");
222 std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item)
223 {
224 m_properties.add(*item, m_project);
225 });
226 }
227
228 tson::Vector2f parallaxOrigin {0.f, 0.f};
229 if(json.count("parallaxoriginx") > 0)
230 parallaxOrigin.x = json["parallaxoriginx"].get<float>();
231 if(json.count("parallaxoriginy") > 0)
232 parallaxOrigin.y = json["parallaxoriginy"].get<float>();
233
234 m_parallaxOrigin = parallaxOrigin;
235
236 if(!createTilesetData(json))
237 allFound = false;
238
239 processData();
240
241 m_linkedFiles.clear(); // close all open linked json files
242
243 return allFound;
244}
245
251tson::IJson* tson::Map::parseLinkedFile(const std::string& relativePath)
252{
253 auto it = m_linkedFiles.find(relativePath);
254 if(it == m_linkedFiles.end())
255 {
256 if (!m_linkedFileParser) return nullptr;
257 std::unique_ptr<IJson> linkedFileJson = m_linkedFileParser(relativePath);
258 if(!linkedFileJson)
259 return nullptr;
260
261 auto result = m_linkedFiles.emplace(relativePath, std::move(linkedFileJson));
262 return result.first->second.get();
263 }
264 else return it->second.get();
265}
266
270bool tson::Map::createTilesetData(IJson &json)
271{
272 bool ok = true;
273 if(json.count("tilesets") > 0 && json["tilesets"].isArray())
274 {
275 //First created tileset objects
276 auto &tilesets = json.array("tilesets");
277 std::for_each(tilesets.begin(), tilesets.end(), [&](std::unique_ptr<IJson> &)
278 {
279 m_tilesets.emplace_back();
280 });
281
282 int i = 0;
283 //Then do the parsing
284 std::for_each(tilesets.begin(), tilesets.end(), [&](std::unique_ptr<IJson> &item)
285 {
286 item->directory(json.directory());
287 if(!m_tilesets[i].parse(*item, this))
288 ok = false;
289
290 ++i;
291 });
292 }
293 return ok;
294}
295
299void tson::Map::processData()
300{
301 m_tileMap.clear();
302 for(auto &tileset : m_tilesets)
303 {
304 std::set<std::uint32_t> usedIds;
305 for(auto& tile : tileset.getTiles())
306 {
307 if (usedIds.count(tile.getGid()) != 0)
308 {
309 continue;
310 }
311 usedIds.insert(tile.getGid());
312 m_tileMap[tile.getGid()] = &tile;
313 }
314 }
315 std::for_each(m_layers.begin(), m_layers.end(), [&](tson::Layer &layer)
316 {
317 layer.assignTileMap(&m_tileMap);
318 layer.createTileData(m_size, m_isInfinite);
319 const std::set<uint32_t> &flaggedTiles = layer.getUniqueFlaggedTiles();
320 for(uint32_t ftile : flaggedTiles)
321 {
322 tson::Tile tile {ftile, layer.getMap()};
323 if(m_tileMap.count(tile.getGid()))
324 {
325 tson::Tile *originalTile = m_tileMap[tile.getGid()];
326 tile.addTilesetAndPerformCalculations(originalTile->getTileset());
327 tile.setProperties(originalTile->getProperties());
328 m_flaggedTileMap[ftile] = tile;
329 m_tileMap[ftile] = &m_flaggedTileMap[ftile];
330 }
331 }
332 layer.resolveFlaggedTiles();
333 });
334}
335
341{
342 return m_backgroundColor;
343}
344
350{
351 return m_size;
352}
353
359{
360 return m_hexsideLength;
361}
362
368{
369 return m_isInfinite;
370}
371
377{
378 return m_nextLayerId;
379}
380
386{
387 return m_nextObjectId;
388}
389
394const std::string &tson::Map::getOrientation() const
395{
396 return m_orientation;
397}
398
403const std::string &tson::Map::getRenderOrder() const
404{
405 return m_renderOrder;
406}
407
412const std::string &tson::Map::getStaggerAxis() const
413{
414 return m_staggerAxis;
415}
416
421const std::string &tson::Map::getStaggerIndex() const
422{
423 return m_staggerIndex;
424}
425
430const std::string &tson::Map::getTiledVersion() const
431{
432 return m_tiledVersion;
433}
434
440{
441 return m_tileSize;
442}
443
448const std::string &tson::Map::getType() const
449{
450 return m_type;
451}
452
457//int tson::Map::getVersion() const
458//{
459// return m_version;
460//}
461
466std::vector<tson::Layer> &tson::Map::getLayers()
467{
468 return m_layers;
469}
470
476{
477 return m_properties;
478}
479
484std::vector<tson::Tileset> &tson::Map::getTilesets()
485{
486 return m_tilesets;
487}
488
489tson::Layer *tson::Map::getLayer(const std::string &name)
490{
491 auto result = std::find_if(m_layers.begin(), m_layers.end(), [&](const tson::Layer &item) { return item.getName() == name; });
492 if(result == m_layers.end())
493 return nullptr;
494
495 return &result.operator*();
496}
497
504tson::Tileset *tson::Map::getTileset(const std::string &name)
505{
506 auto result = std::find_if(m_tilesets.begin(), m_tilesets.end(), [&](const tson::Tileset &item) {return item.getName() == name; });
507 if(result == m_tilesets.end())
508 return nullptr;
509
510 return &result.operator*();
511}
512
520{
521 auto result = std::find_if(m_tilesets.begin(), m_tilesets.end(), [&](const tson::Tileset &tileset)
522 {
523 auto const firstId = static_cast<uint32_t>(tileset.getFirstgid()); //First tile id of the tileset
524 auto const lastId = static_cast<uint32_t>((firstId + tileset.getTileCount()) - 1);
525
526 return (gid >= firstId && gid <= lastId);
527 });
528 if(result == m_tilesets.end())
529 return nullptr;
530
531 return &result.operator*();
532}
533
539tson::Property *tson::Map::getProp(const std::string &name)
540{
541 if(m_properties.hasProperty(name))
542 return m_properties.getProperty(name);
543 return nullptr;
544}
545
547{
548 return m_status;
549}
550
551const std::string &tson::Map::getStatusMessage() const
552{
553 return m_statusMessage;
554}
555
560const std::map<uint32_t, tson::Tile *> &tson::Map::getTileMap() const
561{
562 return m_tileMap;
563}
564
566{
567 return m_decompressors;
568}
569
576{
577 return m_compressionLevel;
578}
579
586{
587 return m_parallaxOrigin;
588}
589
591{
592 return m_project;
593}
594
595const std::string &tson::Map::getClassType() const
596{
597 return m_classType;
598}
599
600
601#endif //TILESON_MAP_HPP
Definition DecompressorContainer.hpp:16
Definition IJson.hpp:11
virtual std::unique_ptr< IJson > create()=0
T get(std::string_view key)
Definition IJson.hpp:82
virtual bool isArray() const =0
virtual fs::path directory() 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:547
Definition Map.hpp:29
const Vector2i & getSize() const
Definition Map.hpp:349
ParseStatus getStatus() const
Definition Map.hpp:546
const std::string & getType() const
Definition Map.hpp:448
std::vector< tson::Layer > & getLayers()
Definition Map.hpp:466
const Vector2i & getTileSize() const
Definition Map.hpp:439
Map()=default
const std::string & getRenderOrder() const
Definition Map.hpp:403
const std::string & getOrientation() const
Definition Map.hpp:394
bool parse(IJson &json, tson::DecompressorContainer *decompressors, tson::Project *project, tson::LinkedFileParser linkedFileParser=nullptr)
Definition Map.hpp:161
int getCompressionLevel() const
Definition Map.hpp:575
std::vector< tson::Tileset > & getTilesets()
Definition Map.hpp:484
const std::string & getStaggerAxis() const
Definition Map.hpp:412
Tileset * getTileset(const std::string &name)
Definition Map.hpp:504
const std::string & getStaggerIndex() const
Definition Map.hpp:421
T get(const std::string &name)
Definition Map.hpp:128
tson::Property * getProp(const std::string &name)
Definition Map.hpp:539
const Vector2f & getParallaxOrigin() const
Definition Map.hpp:585
int getNextObjectId() const
Definition Map.hpp:385
Tileset * getTilesetByGid(uint32_t gid)
Definition Map.hpp:519
Layer * getLayer(const std::string &name)
Definition Map.hpp:489
PropertyCollection & getProperties()
Definition Map.hpp:475
const std::string & getTiledVersion() const
Definition Map.hpp:430
const std::map< uint32_t, tson::Tile * > & getTileMap() const
Definition Map.hpp:560
const Colori & getBackgroundColor() const
Definition Map.hpp:340
const std::string & getClassType() const
Definition Map.hpp:595
int getNextLayerId() const
Definition Map.hpp:376
tson::TiledClass * getClass()
Definition tileson_forward.hpp:20
int getHexsideLength() const
Definition Map.hpp:358
DecompressorContainer * getDecompressors()
Definition Map.hpp:565
Project * getProject()
Definition Map.hpp:590
bool isInfinite() const
Definition Map.hpp:367
const std::string & getStatusMessage() const
Definition Map.hpp:551
Definition Object.hpp:21
Definition Project.hpp:20
Definition PropertyCollection.hpp:15
Definition Property.hpp:23
Definition TiledClass.hpp:11
Definition Tileset.hpp:24
T x
Definition Vector2.hpp:21
Definition Base64.hpp:12
std::function< std::unique_ptr< IJson >(std::string relativePath)> LinkedFileParser
Definition Map.hpp:26
ParseStatus
Definition Enums.hpp:46
Vector2< int > Vector2i
Definition Vector2.hpp:51
Color< uint8_t > Colori
Definition Color.hpp:89