Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
TiledStructures.h
Go to the documentation of this file.
1/*
2 * TiledStructures.h - Data structures mirroring Tiled MapEditor JSON format
3 *
4 * Complete representation of Tiled .tmj/.tsj file formats including:
5 * - Maps (orthogonal, isometric, infinite, chunked)
6 * - Layers (tilelayer, objectgroup, imagelayer, group)
7 * - Objects (rectangle, ellipse, point, polygon, polyline)
8 * - Tilesets (embedded, external, image-based, collection)
9 * - Properties (custom properties of all types)
10 * - Parallax scrolling support
11 */
12
13#pragma once
14
15#include <string>
16#include <vector>
17#include <map>
18#include <memory>
19#include <cstdint>
20#include <functional>
21#include <ostream> // For std::ostream
22
23namespace Olympe {
24namespace Tiled {
25
26 // Flip flags for tile data (used by structures below)
27 constexpr uint32_t FLIPPED_HORIZONTALLY_FLAG = 0x80000000;
28 constexpr uint32_t FLIPPED_VERTICALLY_FLAG = 0x40000000;
29 constexpr uint32_t FLIPPED_DIAGONALLY_FLAG = 0x20000000;
30 constexpr uint32_t TILE_ID_MASK = 0x1FFFFFFF;
31
32 // Forward declarations
33 struct TiledProperty;
34 struct TiledChunk;
35 struct TiledLayer;
36 struct TiledObject;
37 struct TiledTile;
38 struct TiledTileset;
39 struct TiledMap;
40
41 // Property value types
42 enum class PropertyType
43 {
44 String,
45 Int,
46 Float,
47 Bool,
48 Color,
49 File,
50 Object
51 };
52
53 // Property structure
55 {
56 std::string name;
58 std::string stringValue;
62
65 };
66
67 // Layer navigation/collision properties
68 // Used to control how tile layers are processed for navigation and collision maps
70 {
71 bool hasNavigationProperties; // true if layer has any nav/col properties
72 bool isTilesetWalkable; // true = non-empty tiles are walkable, false = they are obstacles
73 bool useTilesetBorder; // true = empty tiles adjacent to non-empty are borders (obstacles)
74
77 };
78
79 // Helper function to parse layer navigation/collision properties
80 inline LayerProperties ParseLayerProperties(const std::map<std::string, TiledProperty>& properties)
81 {
83
84 // Check for isTilesetWalkable property
85 auto walkableIt = properties.find("isTilesetWalkable");
86 if (walkableIt != properties.end() && walkableIt->second.type == PropertyType::Bool)
87 {
89 props.isTilesetWalkable = walkableIt->second.boolValue;
90 }
91
92 // Check for useTilesetBorder property
93 auto borderIt = properties.find("useTilesetBorder");
94 if (borderIt != properties.end() && borderIt->second.type == PropertyType::Bool)
95 {
96 props.hasNavigationProperties = true;
97 props.useTilesetBorder = borderIt->second.boolValue;
98 }
99
100 return props;
101 }
102
103 // Chunk for infinite maps
105 {
106 int x; // Chunk X position (in tiles)
107 int y; // Chunk Y position (in tiles)
108 int width; // Chunk width (in tiles)
109 int height; // Chunk height (in tiles)
110 std::vector<uint32_t> data; // Tile IDs (with flip flags)
111
113 : x(0), y(0), width(0), height(0) {}
114 };
115
116 // Layer types
117 enum class LayerType
118 {
119 TileLayer,
122 Group
123 };
124
125 // Object types for object layers
126 enum class ObjectType
127 {
128 Rectangle,
129 Ellipse,
130 Point,
131 Polygon,
132 Polyline,
133 Text
134 };
135
136 // Point for polygons/polylines
137 struct Point
138 {
139 float x;
140 float y;
141
142 Point() : x(0.0f), y(0.0f) {}
143 Point(float x_, float y_) : x(x_), y(y_) {}
144 };
145
146 // Object in object layer
148 {
149 int id;
150 std::string name;
151 std::string type;
153 float x;
154 float y;
155 float width;
156 float height;
157 float rotation;
158 int gid; // Tile ID for tile objects
160 std::vector<Point> polygon;
161 std::vector<Point> polyline;
162 std::string text;
163 std::map<std::string, TiledProperty> properties;
164
167 x(0.0f), y(0.0f), width(0.0f), height(0.0f),
168 rotation(0.0f), gid(0), visible(true) {}
169 };
170
171 // Layer structure
173 {
174 int id;
175 std::string name;
178 float opacity;
179 float offsetx;
180 float offsety;
181 float parallaxx; // Parallax scroll factor X (1.0 = normal)
182 float parallaxy; // Parallax scroll factor Y (1.0 = normal)
183 int tintcolor; // ARGB color
184
185 // Tile layer data
186 int width;
188 int startx; // Starting X tile position offset (for infinite maps)
189 int starty; // Starting Y tile position offset (for infinite maps)
190 std::vector<uint32_t> data; // Tile IDs (for finite maps)
191 std::vector<TiledChunk> chunks; // Chunks (for infinite maps)
192 std::string encoding; // "csv", "base64"
193 std::string compression; // "gzip", "zlib", "" (none)
194
195 // Object layer data
196 std::vector<TiledObject> objects;
197
198 // Image layer data
199 std::string image;
202
203 // Group layer data
204 std::vector<std::shared_ptr<TiledLayer>> layers;
205
206 // Properties
207 std::map<std::string, TiledProperty> properties;
208
211 opacity(1.0f), offsetx(0.0f), offsety(0.0f),
212 parallaxx(1.0f), parallaxy(1.0f), tintcolor(0xFFFFFFFF),
213 width(0), height(0), startx(0), starty(0),
215 };
216
217 // Individual tile in tileset (for tile-specific properties)
219 {
220 int id; // Local tile ID (0-based)
221 std::string image; // For collection of images tilesets
224 std::string type; // Tile type/class
225 std::map<std::string, TiledProperty> properties;
226
228 : id(0), imagewidth(0), imageheight(0) {}
229 };
230
231 // Tileset structure
233 {
234 int firstgid; // First global tile ID
235 int lastgid; // Last global tile ID (calculated from firstgid + tilecount - 1)
236 std::string name;
237 std::string source; // External tileset file path (.tsx or .tsj)
238
239 // For embedded or loaded external tilesets
246
247 // ====================================================================
248 // CRITICAL: Global tile offset from tileset definition
249 // Parsed from .tsx <tileoffset> or .tsj "tileoffset" property
250 // ALL tiles in this tileset inherit these values
251 // ====================================================================
254
255 std::string image; // Single image file (for image-based tilesets)
258 std::string transparentcolor;
259
260 // Collection of images tileset
261 std::vector<TiledTile> tiles;
262
263 // Properties
264 std::map<std::string, TiledProperty> properties;
265
266 // Constructor with explicit default values
271
272 // Calculate lastgid from tileset parameters
274 {
275 if (tilecount > 0) {
276 lastgid = firstgid + tilecount - 1;
277 } else if (imagewidth > 0 && imageheight > 0 && tilewidth > 0 && tileheight > 0) {
278 // Calculate from image dimensions
279 int cols = (imagewidth - margin * 2 + spacing) / (tilewidth + spacing);
280 int rows = (imageheight - margin * 2 + spacing) / (tileheight + spacing);
281 int calculatedTilecount = cols * rows;
283 } else {
285 }
286 }
287
288 // Check if a GID belongs to this tileset
289 bool ContainsGid(uint32_t gid) const
290 {
292 return cleanGid >= static_cast<uint32_t>(firstgid) &&
293 cleanGid <= static_cast<uint32_t>(lastgid);
294 }
295
296 // Get local tile ID from global ID
297 int GetLocalId(uint32_t gid) const
298 {
300 return static_cast<int>(cleanGid) - firstgid;
301 }
302
303 // Get tile coordinates in atlas (for image-based tilesets)
304 void GetTileCoords(uint32_t gid, int& tileX, int& tileY) const
305 {
306 int localId = GetLocalId(gid);
307 if (columns > 0) {
308 tileX = localId % columns;
309 tileY = localId / columns;
310 } else {
311 tileX = 0;
312 tileY = 0;
313 }
314 }
315 };
316
317 // Map orientations
318 enum class MapOrientation
319 {
321 Isometric,
322 Staggered,
324 };
325
326 // Stream operator for MapOrientation (for logging)
327 inline std::ostream& operator<<(std::ostream& os, MapOrientation orientation)
328 {
329 switch (orientation)
330 {
331 case MapOrientation::Orthogonal: return os << "Orthogonal";
332 case MapOrientation::Isometric: return os << "Isometric";
333 case MapOrientation::Staggered: return os << "Staggered";
334 case MapOrientation::Hexagonal: return os << "Hexagonal";
335 default: return os << "Unknown";
336 }
337 }
338
339 // Render order
340 enum class RenderOrder
341 {
342 RightDown,
343 RightUp,
344 LeftDown,
345 LeftUp
346 };
347
348 // Main map structure
349 struct TiledMap
350 {
351 int version; // Tiled version
352 std::string tiledversion;
353 std::string type; // "map"
357
358 int width; // Map width in tiles
359 int height; // Map height in tiles
360 int tilewidth; // Tile width in pixels
361 int tileheight; // Tile height in pixels
362
363 bool infinite; // Whether map uses chunks
364
365 std::string backgroundcolor;
368
369 std::vector<std::shared_ptr<TiledLayer>> layers;
370 std::vector<TiledTileset> tilesets;
371 std::map<std::string, TiledProperty> properties;
372
378
379 // GID resolver: Find tileset for a given GID
380 // Returns pointer to tileset or nullptr if not found
382 {
384 if (cleanGid == 0) return nullptr; // GID 0 is empty tile
385
386 // Tilesets are stored in order, find the one containing this GID
387 for (const auto& tileset : tilesets) {
388 if (tileset.ContainsGid(cleanGid)) {
389 return &tileset;
390 }
391 }
392 return nullptr;
393 }
394
395 // Non-const version
397 {
399 if (cleanGid == 0) return nullptr; // GID 0 is empty tile
400
401 // Tilesets are stored in order, find the one containing this GID
402 for (auto& tileset : tilesets) {
403 if (tileset.ContainsGid(cleanGid)) {
404 return &tileset;
405 }
406 }
407 return nullptr;
408 }
409
410 // Helper to initialize all tilesets lastgid values
412 {
413 for (auto& tileset : tilesets) {
414 tileset.CalculateLastGid();
415 }
416 }
417 };
418
419 // Resolved GID information
421 {
422 const TiledTileset* tileset; // Pointer to tileset (nullptr if not found)
423 int localId; // Local tile ID within tileset
424 int tileX; // X coordinate in atlas
425 int tileY; // Y coordinate in atlas
426 bool flipH; // Horizontal flip flag
427 bool flipV; // Vertical flip flag
428 bool flipD; // Diagonal flip flag
429
433
434 bool IsValid() const { return tileset != nullptr && localId >= 0; }
435 };
436
437 // Helper to extract tile ID and flip flags
439 {
440 return gid & TILE_ID_MASK;
441 }
442
444 {
445 return (gid & FLIPPED_HORIZONTALLY_FLAG) != 0;
446 }
447
449 {
450 return (gid & FLIPPED_VERTICALLY_FLAG) != 0;
451 }
452
454 {
455 return (gid & FLIPPED_DIAGONALLY_FLAG) != 0;
456 }
457
458 // Comprehensive GID resolver
459 // Resolves a GID to its tileset, local ID, and atlas coordinates
461 {
463
464 // Extract flip flags
466 result.flipV = IsFlippedVertically(gid);
467 result.flipD = IsFlippedDiagonally(gid);
468
469 // Clean GID
471
472 // GID 0 is empty tile
473 if (cleanGid == 0) {
474 return result;
475 }
476
477 // Find tileset
478 result.tileset = map.FindTilesetForGid(cleanGid);
479 if (result.tileset == nullptr) {
480 return result;
481 }
482
483 // Calculate local ID and atlas coordinates
484 result.localId = result.tileset->GetLocalId(cleanGid);
485 result.tileset->GetTileCoords(cleanGid, result.tileX, result.tileY);
486
487 return result;
488 }
489
490 // Helper to get all image paths from a map (for preloading validation)
491 // Returns a vector of image file paths from all tilesets and image layers
492 // NOTE: The runtime must ensure these images are loaded before rendering
493 inline std::vector<std::string> GetAllImagePaths(const TiledMap& map)
494 {
495 std::vector<std::string> imagePaths;
496
497 // Collect tileset images
498 for (const auto& tileset : map.tilesets) {
499 // Main tileset image
500 if (!tileset.image.empty()) {
501 imagePaths.push_back(tileset.image);
502 }
503
504 // Collection tileset individual images
505 for (const auto& tile : tileset.tiles) {
506 if (!tile.image.empty()) {
507 imagePaths.push_back(tile.image);
508 }
509 }
510 }
511
512 // Collect image layer paths (recursive)
513 std::function<void(const std::shared_ptr<TiledLayer>&)> processLayer;
514 processLayer = [&](const std::shared_ptr<TiledLayer>& layer) {
515 if (!layer) return;
516
517 if (layer->type == LayerType::ImageLayer && !layer->image.empty()) {
518 imagePaths.push_back(layer->image);
519 }
520
521 // Recursively process group layers
522 if (layer->type == LayerType::Group) {
523 for (const auto& childLayer : layer->layers) {
525 }
526 }
527 };
528
529 for (const auto& layer : map.layers) {
530 processLayer(layer);
531 }
532
533 return imagePaths;
534 }
535
536} // namespace Tiled
537} // namespace Olymp
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
LayerProperties ParseLayerProperties(const std::map< std::string, TiledProperty > &properties)
std::ostream & operator<<(std::ostream &os, MapOrientation orientation)
bool IsFlippedDiagonally(uint32_t gid)
ResolvedGid ResolveGid(const TiledMap &map, uint32_t gid)
constexpr uint32_t FLIPPED_HORIZONTALLY_FLAG
bool IsFlippedVertically(uint32_t gid)
bool IsFlippedHorizontally(uint32_t gid)
constexpr uint32_t FLIPPED_VERTICALLY_FLAG
uint32_t GetTileId(uint32_t gid)
std::vector< std::string > GetAllImagePaths(const TiledMap &map)
constexpr uint32_t FLIPPED_DIAGONALLY_FLAG
constexpr uint32_t TILE_ID_MASK
Point(float x_, float y_)
const TiledTileset * tileset
std::vector< uint32_t > data
std::vector< TiledObject > objects
std::vector< uint32_t > data
std::map< std::string, TiledProperty > properties
std::vector< TiledChunk > chunks
std::vector< std::shared_ptr< TiledLayer > > layers
const TiledTileset * FindTilesetForGid(uint32_t gid) const
std::vector< TiledTileset > tilesets
std::vector< std::shared_ptr< TiledLayer > > layers
TiledTileset * FindTilesetForGid(uint32_t gid)
std::map< std::string, TiledProperty > properties
std::vector< Point > polyline
std::map< std::string, TiledProperty > properties
std::vector< Point > polygon
std::map< std::string, TiledProperty > properties
void GetTileCoords(uint32_t gid, int &tileX, int &tileY) const
std::vector< TiledTile > tiles
std::map< std::string, TiledProperty > properties
int GetLocalId(uint32_t gid) const
bool ContainsGid(uint32_t gid) const