From a475b843e7d37f128ce30140d193f0312aa70c9c Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 2 Feb 2021 15:36:09 -0500 Subject: Using tmxlite instead of Tileson --- .gitmodules | 3 + CMakeLists.txt | 8 +- res/map1.json | 53 - res/map1.tmx | 11 + res/map1_tiles.png | Bin 0 -> 22418 bytes src/game.h | 12 +- src/main.cpp | 5 +- src/map.cpp | 46 + src/map.h | 41 + src/renderer.cpp | 67 +- src/renderer.h | 5 +- src/vector.h | 4 + vendor/tileson.hpp | 7391 ---------------------------------------------------- vendor/tmxlite | 1 + 14 files changed, 160 insertions(+), 7487 deletions(-) create mode 100644 .gitmodules delete mode 100644 res/map1.json create mode 100644 res/map1.tmx create mode 100644 res/map1_tiles.png create mode 100644 src/map.cpp create mode 100644 src/map.h delete mode 100644 vendor/tileson.hpp create mode 160000 vendor/tmxlite diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8fd23f6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vendor/tmxlite"] + path = vendor/tmxlite + url = https://github.com/fallahn/tmxlite diff --git a/CMakeLists.txt b/CMakeLists.txt index 443fe86..45c838c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required (VERSION 3.1) project (tanetane) set(CMAKE_BUILD_TYPE Debug) -set(CMAKE_C_COMPILER /usr/local/bin/gcc-10) -set(CMAKE_CXX_COMPILER /usr/local/bin/g++-10) + +add_subdirectory(vendor/tmxlite/tmxlite) # Set directory to look for package helpers. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${tanetane_SOURCE_DIR}/cmake") @@ -15,13 +15,14 @@ find_package(SDL2_Image REQUIRED) set(ALL_LIBS ${SDL2_LIBRARY} ${SDL2_IMAGE_LIBRARIES} + tmxlite ) include_directories( ${SDL2_INCLUDE_DIR} ${SDL2_IMAGE_INCLUDE_DIRS} src - vendor + vendor/tmxlite/tmxlite/include ) link_directories( @@ -34,6 +35,7 @@ add_executable(tanetane src/sprite.cpp src/party.cpp src/game.cpp + src/map.cpp ) set_property(TARGET tanetane PROPERTY CXX_STANDARD 17) diff --git a/res/map1.json b/res/map1.json deleted file mode 100644 index b5b3d1a..0000000 --- a/res/map1.json +++ /dev/null @@ -1,53 +0,0 @@ -{ "compressionlevel":-1, - "height":32, - "infinite":false, - "layers":[ - { - "data":[55, 55, 55, 55, 55, 55, 56, 57, 58, 58, 2147483704, 2147483703, 2147483707, 2147483708, 2147483709, 2147483703, 55, 55, 55, 55, 55, 55, 55, 62, 63, 2147483711, 2147483710, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 58, 58, 2147483712, 55, 55, 55, 55, 55, 61, 60, 59, 55, 55, 65, 66, 58, 58, 58, 2147483714, 2147483715, 2147483716, 2147483717, 2147483718, 71, 2147483712, 55, 61, 60, 59, 55, 55, 56, 57, 2147483705, 2147483704, 55, 55, 55, 55, 55, 55, 61, 60, 59, 55, 55, 65, 66, 58, 58, 58, 72, 2147483719, 55, 55, 55, 70, 69, 68, 67, 73, 58, 74, 58, 58, 58, 58, 2147483706, 2147483723, 2147483724, 2147483725, 2147483706, 2147483705, 2147483719, 70, 69, 68, 67, 73, 66, 58, 58, 58, 2147483713, 55, 55, 65, 73, 2147483713, 70, 69, 68, 67, 73, 58, 58, 58, 58, 58, 58, 58, 2147483712, 65, 73, 77, 76, 75, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 77, 76, 75, 58, 58, 58, 58, 58, 58, 58, 2147483719, 2147483724, 58, 58, 58, 77, 76, 75, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 80, 81, 82, 83, 84, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 85, 86, 2147483735, 2147483735, 2147483735, 2147483735, 2147483734, 2147483733, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 88, 89, 90, 91, 92, 79, 79, 2147483732, 2147483731, 2147483730, 2147483729, 2147483728, 79, 79, 79, 79, 79, 79, 79, 85, 86, 2147483735, 2147483735, 2147483735, 2147483735, 2147483735, 2147483735, 2147483735, 2147483735, 93, 94, 2147483743, 2147483743, 2147483743, 2147483743, 2147483742, 2147483741, 2147483735, 87, 2147483734, 2147483733, 79, 79, 79, 2147483735, 2147483735, 2147483744, 2147483733, 97, 98, 99, 100, 101, 101, 79, 2147483740, 2147483739, 2147483738, 2147483737, 2147483736, 79, 79, 79, 85, 86, 87, 87, 93, 94, 2147483743, 2147483743, 2147483743, 102, 103, 104, 105, 106, 106, 107, 106, 108, 2147483757, 2147483756, 2147483755, 2147483758, 2147483743, 95, 2147483742, 2147483741, 2147483735, 2147483735, 2147483735, 2147483743, 2147483743, 2147483759, 2147483741, 2147483760, 2147483761, 2147483727, 2147483727, 79, 79, 79, 2147483749, 2147483748, 2147483747, 2147483746, 2147483745, 79, 85, 112, 93, 94, 95, 95, 95, 106, 106, 106, 106, 114, 114, 114, 114, 106, 106, 108, 109, 115, 116, 2147483763, 2147483757, 109, 109, 2147483756, 2147483755, 2147483758, 2147483743, 2147483743, 2147483743, 2147483765, 2147483765, 118, 2147483758, 2147483767, 2147483768, 2147483735, 2147483734, 2147483733, 2147483769, 2147483770, 123, 122, 121, 85, 86, 2147483735, 93, 94, 95, 107, 106, 106, 106, 106, 106, 106, 106, 106, 2147483772, 2147483772, 106, 108, 109, 115, 116, 116, 116, 116, 116, 116, 116, 2147483763, 2147483756, 106, 106, 106, 106, 2147483765, 118, 2147483754, 2147483754, 2147483754, 2147483773, 126, 2147483742, 2147483741, 2147483775, 2147483776, 129, 128, 127, 93, 130, 130, 95, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 131, 132, 109, 115, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 2147483763, 2147483756, 106, 106, 106, 133, 130, 118, 134, 106, 106, 106, 2147483755, 2147483758, 2147483783, 136, 2147483784, 2147483784, 135, 110, 107, 118, 106, 106, 106, 106, 106, 108, 2147483757, 109, 2147483757, 109, 2147483757, 109, 115, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 2147483763, 109, 137, 137, 138, 2147483756, 106, 106, 106, 2147483754, 108, 2147483756, 106, 106, 2147483784, 2147483784, 2147483784, 2147483784, 133, 130, 118, 134, 106, 106, 106, 108, 115, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 139, 140, 2147483756, 106, 108, 115, 2147483763, 137, 2147483756, 2147483784, 2147483784, 2147483784, 2147483784, 108, 2147483757, 109, 138, 141, 142, 109, 115, 116, 116, 116, 116, 116, 116, 116, 2147483764, 2147483764, 2147483764, 116, 116, 116, 116, 116, 116, 116, 116, 2147483791, 2147483792, 143, 116, 145, 138, 141, 142, 138, 116, 146, 139, 140, 147, 116, 116, 148, 2147483763, 2147483756, 106, 106, 108, 115, 116, 116, 116, 139, 138, 141, 142, 116, 2147483764, 2147483764, 2147483764, 2147483764, 2147483764, 2147483764, 2147483764, 2147483764, 2147483764, 2147483764, 2147483764, 146, 139, 140, 142, 2147483791, 2147483792, 2147483797, 150, 149, 151, 152, 2147483764, 116, 151, 116, 138, 141, 116, 116, 116, 116, 116, 116, 116, 2147483763, 2147483757, 109, 115, 116, 148, 146, 139, 140, 147, 2147483764, 2147483764, 2147483764, 2147483764, 102, 103, 104, 105, 2147483764, 2147483764, 2147483764, 2147483764, 146, 139, 140, 142, 2147483791, 151, 152, 150, 150, 151, 152, 150, 149, 143, 116, 151, 138, 138, 141, 116, 116, 138, 141, 141, 141, 116, 153, 154, 116, 116, 155, 116, 116, 2147483791, 143, 138, 141, 142, 102, 103, 104, 156, 157, 103, 104, 105, 146, 139, 140, 142, 148, 2147483791, 2147483792, 150, 158, 159, 160, 161, 158, 151, 152, 161, 143, 151, 116, 138, 141, 138, 141, 138, 141, 162, 162, 162, 143, 116, 153, 154, 163, 2147483791, 144, 2147483797, 149, 2147483792, 145, 138, 141, 142, 1073741988, 3221225637, 3221225638, 167, 143, 139, 140, 2147483764, 2147483791, 144, 2147483792, 2147483797, 2147483816, 151, 152, 169, 170, 151, 152, 150, 150, 151, 152, 151, 116, 116, 116, 138, 141, 2147483797, 158, 151, 152, 161, 149, 143, 116, 116, 2147483791, 2147483797, 150, 150, 158, 151, 152, 161, 158, 151, 152, 161, 3221225640, 1073741988, 149, 139, 140, 2147483792, 2147483797, 150, 150, 2147483816, 2147483814, 167, 167, 167, 167, 167, 167, 150, 150, 151, 151, 151, 116, 116, 2147483791, 2147483792, 2147483797, 151, 152, 150, 150, 150, 171, 172, 2147483792, 144, 2147483820, 2147483819, 150, 173, 174, 175, 158, 151, 152, 161, 150, 150, 176, 177, 178, 159, 160, 179, 180, 181, 2147483816, 2147483814, 102, 103, 104, 105, 102, 103, 104, 103, 152, 151, 152, 151, 116, 2147483791, 2147483797, 151, 152, 139, 150, 151, 152, 182, 150, 150, 150, 150, 150, 150, 150, 183, 184, 185, 150, 150, 150, 150, 150, 150, 150, 150, 186, 169, 170, 187, 150, 150, 2147483814, 167, 167, 188, 102, 103, 104, 105, 102, 103, 152, 150, 158, 151, 2147483792, 2147483797, 150, 150, 158, 151, 152, 161, 152, 189, 190, 150, 189, 190, 150, 150, 150, 191, 192, 193, 150, 150, 150, 189, 190, 150, 150, 150, 150, 1073741995, 1073741996, 194, 194, 151, 152, 167, 1073742019, 1073742019, 3221225638, 188, 167, 167, 167, 167, 158, 151, 152, 161, 150, 150, 158, 151, 152, 161, 158, 151, 152, 161, 189, 190, 150, 196, 1073741995, 1073741996, 194, 2147483842, 3221225644, 3221225643, 2147483816, 2147483845, 197, 168, 150, 2147483816, 2147483845, 150, 150, 150, 198, 3221225671, 1073742024, 3221225672, 151, 151, 152, 150, 3221225640, 1073742019, 1073741988, 1073742019, 158, 151, 152, 161, 201, 202, 150, 151, 152, 164, 195, 195, 203, 196, 150, 2147483816, 204, 195, 168, 150, 205, 198, 153, 154, 2147483846, 2147483853, 205, 194, 167, 166, 195, 2147483814, 1073741990, 151, 152, 103, 104, 3221225678, 207, 151, 152, 151, 152, 150, 189, 190, 158, 151, 152, 161, 150, 150, 2147483856, 209, 151, 167, 167, 103, 104, 167, 204, 195, 204, 2147483814, 167, 210, 211, 168, 198, 2147483802, 2147483801, 2147483860, 2147483860, 2147483846, 138, 141, 142, 167, 3221225638, 188, 167, 151, 152, 103, 104, 103, 104, 103, 104, 151, 152, 161, 150, 150, 150, 150, 150, 2147483816, 195, 195, 2147483861, 214, 150, 151, 152, 167, 167, 103, 104, 215, 157, 103, 104, 105, 167, 167, 2147483860, 2147483860, 148, 2147483860, 2147483860, 2147483860, 2147483860, 2147483860, 2147483860, 2147483860, 2147483848, 2147483854, 166, 167, 167, 103, 104, 103, 104, 151, 152, 161, 150, 2147483798, 2147483798, 2147483864, 2147483865, 2147483798, 2147483816, 2147483814, 167, 167, 218, 214, 150, 150, 158, 151, 152, 103, 104, 1073741988, 3221225637, 3221225638, 1073741991, 167, 167, 139, 140, 1073742024, 1073742023, 146, 139, 219, 220, 221, 222, 140, 147, 2147483847, 102, 103, 104, 105, 158, 151, 152, 103, 104, 138, 138, 2147483798, 2147483871, 2147483872, 2147483873, 2147483874, 3221225640, 3221225638, 151, 152, 151, 152, 150, 151, 152, 161, 150, 138, 141, 3221225622, 3221225622, 3221225640, 3221225638, 139, 140, 151, 152, 207, 1073742030, 1073742023, 2147483860, 227, 228, 229, 230, 163, 3221225671, 103, 167, 167, 102, 103, 104, 105, 146, 139, 140, 138, 104, 138, 104, 150, 150, 150, 150, 3221225640, 138, 151, 152, 2147483860, 151, 139, 140, 150, 3221225622, 3221225622, 3221225622, 103, 104, 3221225622, 3221225640, 151, 152, 139, 207, 103, 104, 1073742030, 3221225670, 2147483792, 144, 143, 3221225671, 1073742055, 3221225678, 103, 104, 103, 167, 167, 167, 138, 141, 1073742023, 116, 138, 141, 103, 104, 151, 152, 150, 150, 151, 152, 150, 150, 151, 150, 151, 152, 139, 140, 138, 141, 139, 140, 103, 104, 3221225622, 139, 151, 152, 139, 140, 103, 104, 168, 2147483816, 103, 104, 167, 167, 138, 141, 138, 141, 167, 116, 116, 116, 116, 116, 103, 104, 138, 141, 2147483853, 150, 151, 152, 150, 150, 151, 152, 150, 150, 150, 205, 138, 141, 116, 116, 138, 141, 139, 140, 138, 141, 2147483853, 150, 151, 141, 139, 139, 166, 2147483814, 103, 104, 103, 104, 138, 141, 138, 141, 138, 141, 138, 141, 103, 104, 138, 141, 116, 116, 2147483846, 232, 232, 2147483853, 151, 152, 150, 150, 150, 150, 205, 198, 116, 116, 116, 116, 116, 116, 138, 141, 116, 116, 2147483846, 194, 198, 116, 138, 141, 200, 231, 138, 141, 138, 141, 138, 141, 116, 116, 138, 141, 116, 116, 138, 141, 116, 116, 116, 116, 116, 116, 116, 2147483846, 2147483853, 150, 150, 150, 150], - "height":32, - "id":1, - "name":"Layer 1", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":48, - "x":0, - "y":0 - }, - { - "data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 6, 7, 8, 9, 4, 5, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 10, 7, 11, 9, 4, 5, 2, 3, 6, 7, 8, 12, 6, 7, 8, 9, 4, 5, 2, 3, 6, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 1, 1, 13, 14, 15, 12, 6, 7, 15, 9, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 9, 6, 7, 8, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 10, 7, 8, 9, 4, 5, 16, 17, 6, 7, 11, 18, 19, 20, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 21, 22, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 6, 7, 8, 12, 6, 7, 8, 9, 10, 7, 8, 12, 6, 23, 24, 17, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 8, 9, 4, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 9, 25, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 6, 7, 11, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 17, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 8, 18, 27, 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 14, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 6, 23, 2, 29, 21, 22, 1, 1, 1, 1, 1, 1, 1, 1, 30, 31, 19, 20, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 8, 9, 25, 32, 8, 9, 4, 5, 1, 1, 1, 1, 1, 1, 1, 1, 24, 17, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 18, 19, 14, 6, 7, 11, 18, 19, 14, 11, 26, 1, 1, 1, 1, 1, 1, 1, 1, 13, 20, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 33, 18, 19, 14, 8, 12, 6, 7, 8, 12, 6, 23, 24, 17, 8, 12, 6, 23, 24, 17, 6, 34, 1, 1, 1, 1, 1, 1, 1, 1, 30, 31, 19, 20, 8, 12, 6, 7, 33, 18, 19, 20, 8, 12, 6, 7, 33, 18, 27, 28, 24, 17, 6, 7, 8, 12, 6, 7, 8, 9, 25, 32, 6, 7, 8, 9, 25, 32, 8, 9, 4, 5, 1, 1, 1, 1, 1, 1, 1, 1, 24, 17, 6, 7, 8, 12, 6, 23, 30, 31, 19, 20, 33, 18, 27, 28, 1, 1, 13, 20, 33, 18, 19, 14, 33, 18, 19, 14, 8, 12, 8, 12, 6, 7, 8, 12, 6, 7, 11, 26, 1, 1, 1, 1, 1, 1, 1, 1, 13, 20, 8, 12, 6, 7, 33, 35, 1, 29, 36, 37, 38, 39, 4, 5, 1, 1, 16, 17, 6, 23, 24, 17, 6, 23, 24, 17, 6, 7, 6, 7, 8, 12, 6, 7, 11, 18, 27, 28, 1, 1, 1, 1, 1, 1, 1, 1, 30, 31, 19, 20, 33, 18, 27, 28, 40, 41, 19, 20, 33, 18, 42, 35, 1, 1, 13, 20, 8, 9, 25, 32, 8, 9, 25, 32, 8, 12, 8, 12, 6, 7, 8, 12, 6, 23, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 31, 27, 28, 1, 1, 30, 31, 43, 31, 27, 44, 27, 28, 1, 1, 30, 31, 19, 20, 33, 18, 19, 20, 8, 12, 6, 32, 6, 7, 8, 12, 6, 7, 8, 9, 4, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 31, 27, 28, 24, 17, 6, 32, 33, 18, 8, 12, 6, 7, 11, 18, 19, 14, 11, 26, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 1, 1, 1, 1, 1, 29, 6, 32, 33, 18, 27, 28, 6, 7, 11, 18, 27, 28, 45, 31, 27, 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 29, 4, 5, 1, 1, 1, 1, 29, 4, 5, 1, 1, 13, 14, 15, 9, 4, 5, 1, 1, 40, 46, 33, 18, 27, 28, 1, 1, 8, 12, 6, 23, 1, 1, 1, 1, 1, 29, 21, 22, 1, 1, 1, 1, 1, 1, 1, 40, 46, 11, 26, 1, 1, 1, 40, 46, 8, 9, 4, 5, 16, 17, 6, 7, 11, 26, 1, 1, 30, 31, 27, 28, 1, 1, 1, 1, 6, 7, 8, 9, 4, 22, 1, 1, 40, 46, 47, 35, 1, 1, 1, 1, 1, 1, 29, 36, 37, 38, 39, 4, 22, 1, 16, 17, 6, 7, 8, 9, 10, 7, 11, 18, 27, 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 12, 6, 7, 8, 9, 4, 5, 45, 48, 49, 50, 2, 3, 4, 5, 1, 40, 46, 19, 20, 33, 18, 42, 35, 1, 13, 14, 8, 12, 6, 7, 8, 12, 6, 23, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 11, 18, 19, 14, 11, 26, 1, 1, 2, 3, 25, 7, 42, 26, 1, 30, 31, 43, 31, 27, 44, 27, 28, 1, 30, 31, 19, 14, 8, 12, 6, 7, 8, 9, 4, 5, 1, 1, 2147483699, 1, 2, 3, 6, 7, 8, 52, 8, 12, 6, 23, 24, 17, 6, 34, 1, 1, 13, 14, 8, 12, 6, 34, 1, 53, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 30, 31, 19, 14, 11, 18, 19, 14, 15, 9, 4, 5, 2147483702, 1, 13, 14, 8, 12, 6, 7, 6, 7, 8, 9, 25, 32, 8, 9, 4, 5, 16, 17, 6, 7, 8, 9, 4, 5, 1, 1, 1, 1, 1, 1, 13, 14, 8, 9, 4, 5, 16, 17, 6, 23, 24, 17, 6, 7, 15, 9, 4, 5, 16, 17, 6, 7, 8, 12, 8, 12, 6, 7, 8, 12, 6, 7, 8, 9, 10, 7, 8, 12, 6, 7, 8, 9, 4, 5, 2, 3, 4, 5, 16, 17, 6, 7, 8, 9, 10, 32, 8, 9, 25, 7, 15, 12, 6, 7, 15, 9, 25, 32, 8, 12, 6, 7, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 42, 26, 13, 14, 8, 9, 25, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 34, 16, 17, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 9, 25, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12, 6, 7, 8, 12], - "height":32, - "id":1, - "name":"Layer 0", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":48, - "x":0, - "y":0 - }], - "nextlayerid":2, - "nextobjectid":1, - "orientation":"orthogonal", - "renderorder":"right-down", - "tiledversion":"1.4.3", - "tileheight":16, - "tilesets":[ - { - "columns":10, - "firstgid":1, - "image":"..\/tools\/sprite_dumper\/build\/tiles.png", - "imageheight":384, - "imagewidth":160, - "margin":0, - "name":"fromRom", - "spacing":0, - "tilecount":240, - "tileheight":16, - "tilewidth":16 - }], - "tilewidth":16, - "type":"map", - "version":1.4, - "width":48 -} \ No newline at end of file diff --git a/res/map1.tmx b/res/map1.tmx new file mode 100644 index 0000000..ceae330 --- /dev/null +++ b/res/map1.tmx @@ -0,0 +1,11 @@ + + + + + + 55,55,55,55,55,55,56,57,58,58,2147483704,2147483703,2147483707,2147483708,2147483709,2147483703,55,55,55,55,55,55,55,62,63,2147483711,2147483710,55,55,55,55,55,55,55,55,55,55,55,55,56,58,58,2147483712,55,55,55,55,55,61,60,59,55,55,65,66,58,58,58,2147483714,2147483715,2147483716,2147483717,2147483718,71,2147483712,55,61,60,59,55,55,56,57,2147483705,2147483704,55,55,55,55,55,55,61,60,59,55,55,65,66,58,58,58,72,2147483719,55,55,55,70,69,68,67,73,58,74,58,58,58,58,2147483706,2147483723,2147483724,2147483725,2147483706,2147483705,2147483719,70,69,68,67,73,66,58,58,58,2147483713,55,55,65,73,2147483713,70,69,68,67,73,58,58,58,58,58,58,58,2147483712,65,73,77,76,75,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,77,76,75,58,58,58,58,58,58,58,2147483719,2147483724,58,58,58,77,76,75,58,58,58,58,58,58,58,58,58,58,58,58,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,79,79,79,79,80,81,82,83,84,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,85,86,2147483735,2147483735,2147483735,2147483735,2147483734,2147483733,79,79,79,79,79,79,79,79,79,79,79,88,89,90,91,92,79,79,2147483732,2147483731,2147483730,2147483729,2147483728,79,79,79,79,79,79,79,85,86,2147483735,2147483735,2147483735,2147483735,2147483735,2147483735,2147483735,2147483735,93,94,2147483743,2147483743,2147483743,2147483743,2147483742,2147483741,2147483735,87,2147483734,2147483733,79,79,79,2147483735,2147483735,2147483744,2147483733,97,98,99,100,101,101,79,2147483740,2147483739,2147483738,2147483737,2147483736,79,79,79,85,86,87,87,93,94,2147483743,2147483743,2147483743,102,103,104,105,106,106,107,106,108,2147483757,2147483756,2147483755,2147483758,2147483743,95,2147483742,2147483741,2147483735,2147483735,2147483735,2147483743,2147483743,2147483759,2147483741,2147483760,2147483761,2147483727,2147483727,79,79,79,2147483749,2147483748,2147483747,2147483746,2147483745,79,85,112,93,94,95,95,95,106,106,106,106,114,114,114,114,106,106,108,109,115,116,2147483763,2147483757,109,109,2147483756,2147483755,2147483758,2147483743,2147483743,2147483743,2147483765,2147483765,118,2147483758,2147483767,2147483768,2147483735,2147483734,2147483733,2147483769,2147483770,123,122,121,85,86,2147483735,93,94,95,107,106,106,106,106,106,106,106,106,2147483772,2147483772,106,108,109,115,116,116,116,116,116,116,116,2147483763,2147483756,106,106,106,106,2147483765,118,2147483754,2147483754,2147483754,2147483773,126,2147483742,2147483741,2147483775,2147483776,129,128,127,93,130,130,95,106,106,106,106,106,106,106,106,106,106,106,131,132,109,115,116,116,116,116,116,116,116,116,116,116,2147483763,2147483756,106,106,106,133,130,118,134,106,106,106,2147483755,2147483758,2147483783,136,2147483784,2147483784,135,110,107,118,106,106,106,106,106,108,2147483757,109,2147483757,109,2147483757,109,115,116,116,116,116,116,116,116,116,116,116,116,116,116,116,2147483763,109,137,137,138,2147483756,106,106,106,2147483754,108,2147483756,106,106,2147483784,2147483784,2147483784,2147483784,133,130,118,134,106,106,106,108,115,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,139,140,2147483756,106,108,115,2147483763,137,2147483756,2147483784,2147483784,2147483784,2147483784,108,2147483757,109,138,141,142,109,115,116,116,116,116,116,116,116,2147483764,2147483764,2147483764,116,116,116,116,116,116,116,116,2147483791,2147483792,143,116,145,138,141,142,138,116,146,139,140,147,116,116,148,2147483763,2147483756,106,106,108,115,116,116,116,139,138,141,142,116,2147483764,2147483764,2147483764,2147483764,2147483764,2147483764,2147483764,2147483764,2147483764,2147483764,2147483764,146,139,140,142,2147483791,2147483792,2147483797,150,149,151,152,2147483764,116,151,116,138,141,116,116,116,116,116,116,116,2147483763,2147483757,109,115,116,148,146,139,140,147,2147483764,2147483764,2147483764,2147483764,102,103,104,105,2147483764,2147483764,2147483764,2147483764,146,139,140,142,2147483791,151,152,150,150,151,152,150,149,143,116,151,138,138,141,116,116,138,141,141,141,116,153,154,116,116,155,116,116,2147483791,143,138,141,142,102,103,104,156,157,103,104,105,146,139,140,142,148,2147483791,2147483792,150,158,159,160,161,158,151,152,161,143,151,116,138,141,138,141,138,141,162,162,162,143,116,153,154,163,2147483791,144,2147483797,149,2147483792,145,138,141,142,1073741988,3221225637,3221225638,167,143,139,140,2147483764,2147483791,144,2147483792,2147483797,2147483816,151,152,169,170,151,152,150,150,151,152,151,116,116,116,138,141,2147483797,158,151,152,161,149,143,116,116,2147483791,2147483797,150,150,158,151,152,161,158,151,152,161,3221225640,1073741988,149,139,140,2147483792,2147483797,150,150,2147483816,2147483814,167,167,167,167,167,167,150,150,151,151,151,116,116,2147483791,2147483792,2147483797,151,152,150,150,150,171,172,2147483792,144,2147483820,2147483819,150,173,174,175,158,151,152,161,150,150,176,177,178,159,160,179,180,181,2147483816,2147483814,102,103,104,105,102,103,104,103,152,151,152,151,116,2147483791,2147483797,151,152,139,150,151,152,182,150,150,150,150,150,150,150,183,184,185,150,150,150,150,150,150,150,150,186,169,170,187,150,150,2147483814,167,167,188,102,103,104,105,102,103,152,150,158,151,2147483792,2147483797,150,150,158,151,152,161,152,189,190,150,189,190,150,150,150,191,192,193,150,150,150,189,190,150,150,150,150,1073741995,1073741996,194,194,151,152,167,1073742019,1073742019,3221225638,188,167,167,167,167,158,151,152,161,150,150,158,151,152,161,158,151,152,161,189,190,150,196,1073741995,1073741996,194,2147483842,3221225644,3221225643,2147483816,2147483845,197,168,150,2147483816,2147483845,150,150,150,198,3221225671,1073742024,3221225672,151,151,152,150,3221225640,1073742019,1073741988,1073742019,158,151,152,161,201,202,150,151,152,164,195,195,203,196,150,2147483816,204,195,168,150,205,198,153,154,2147483846,2147483853,205,194,167,166,195,2147483814,1073741990,151,152,103,104,3221225678,207,151,152,151,152,150,189,190,158,151,152,161,150,150,2147483856,209,151,167,167,103,104,167,204,195,204,2147483814,167,210,211,168,198,2147483802,2147483801,2147483860,2147483860,2147483846,138,141,142,167,3221225638,188,167,151,152,103,104,103,104,103,104,151,152,161,150,150,150,150,150,2147483816,195,195,2147483861,214,150,151,152,167,167,103,104,215,157,103,104,105,167,167,2147483860,2147483860,148,2147483860,2147483860,2147483860,2147483860,2147483860,2147483860,2147483860,2147483848,2147483854,166,167,167,103,104,103,104,151,152,161,150,2147483798,2147483798,2147483864,2147483865,2147483798,2147483816,2147483814,167,167,218,214,150,150,158,151,152,103,104,1073741988,3221225637,3221225638,1073741991,167,167,139,140,1073742024,1073742023,146,139,219,220,221,222,140,147,2147483847,102,103,104,105,158,151,152,103,104,138,138,2147483798,2147483871,2147483872,2147483873,2147483874,3221225640,3221225638,151,152,151,152,150,151,152,161,150,138,141,3221225622,3221225622,3221225640,3221225638,139,140,151,152,207,1073742030,1073742023,2147483860,227,228,229,230,163,3221225671,103,167,167,102,103,104,105,146,139,140,138,104,138,104,150,150,150,150,3221225640,138,151,152,2147483860,151,139,140,150,3221225622,3221225622,3221225622,103,104,3221225622,3221225640,151,152,139,207,103,104,1073742030,3221225670,2147483792,144,143,3221225671,1073742055,3221225678,103,104,103,167,167,167,138,141,1073742023,116,138,141,103,104,151,152,150,150,151,152,150,150,151,150,151,152,139,140,138,141,139,140,103,104,3221225622,139,151,152,139,140,103,104,168,2147483816,103,104,167,167,138,141,138,141,167,116,116,116,116,116,103,104,138,141,2147483853,150,151,152,150,150,151,152,150,150,150,205,138,141,116,116,138,141,139,140,138,141,2147483853,150,151,141,139,139,166,2147483814,103,104,103,104,138,141,138,141,138,141,138,141,103,104,138,141,116,116,2147483846,232,232,2147483853,151,152,150,150,150,150,205,198,116,116,116,116,116,116,138,141,116,116,2147483846,194,198,116,138,141,200,231,138,141,138,141,138,141,116,116,138,141,116,116,138,141,116,116,116,116,116,116,116,2147483846,2147483853,150,150,150,150 + + + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,5,1,1,1,1,2,3,6,7,8,9,4,5,1,1,1,1,2,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,10,7,11,9,4,5,2,3,6,7,8,12,6,7,8,9,4,5,2,3,6,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,5,1,1,13,14,15,12,6,7,15,9,6,7,8,12,6,7,8,12,6,7,8,9,6,7,8,12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,10,7,8,9,4,5,16,17,6,7,11,18,19,20,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,21,22,1,1,1,1,1,1,1,1,1,1,1,1,2,3,6,7,8,12,6,7,8,9,10,7,8,12,6,23,24,17,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,8,9,4,5,1,1,1,1,1,1,1,1,1,1,13,14,8,12,6,7,8,12,6,7,8,12,6,7,8,9,25,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,6,7,11,26,1,1,1,1,1,1,1,1,1,1,16,17,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,8,18,27,28,1,1,1,1,1,1,1,1,1,1,13,14,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,6,23,2,29,21,22,1,1,1,1,1,1,1,1,30,31,19,20,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,8,9,25,32,8,9,4,5,1,1,1,1,1,1,1,1,24,17,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,18,19,14,6,7,11,18,19,14,11,26,1,1,1,1,1,1,1,1,13,20,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,33,18,19,14,8,12,6,7,8,12,6,23,24,17,8,12,6,23,24,17,6,34,1,1,1,1,1,1,1,1,30,31,19,20,8,12,6,7,33,18,19,20,8,12,6,7,33,18,27,28,24,17,6,7,8,12,6,7,8,9,25,32,6,7,8,9,25,32,8,9,4,5,1,1,1,1,1,1,1,1,24,17,6,7,8,12,6,23,30,31,19,20,33,18,27,28,1,1,13,20,33,18,19,14,33,18,19,14,8,12,8,12,6,7,8,12,6,7,11,26,1,1,1,1,1,1,1,1,13,20,8,12,6,7,33,35,1,29,36,37,38,39,4,5,1,1,16,17,6,23,24,17,6,23,24,17,6,7,6,7,8,12,6,7,11,18,27,28,1,1,1,1,1,1,1,1,30,31,19,20,33,18,27,28,40,41,19,20,33,18,42,35,1,1,13,20,8,9,25,32,8,9,25,32,8,12,8,12,6,7,8,12,6,23,1,1,1,1,1,1,1,1,1,1,1,1,30,31,27,28,1,1,30,31,43,31,27,44,27,28,1,1,30,31,19,20,33,18,19,20,8,12,6,32,6,7,8,12,6,7,8,9,4,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,30,31,27,28,24,17,6,32,33,18,8,12,6,7,11,18,19,14,11,26,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,5,1,1,1,1,1,29,6,32,33,18,27,28,6,7,11,18,27,28,45,31,27,28,1,1,1,1,1,1,1,1,1,1,29,4,5,1,1,1,1,29,4,5,1,1,13,14,15,9,4,5,1,1,40,46,33,18,27,28,1,1,8,12,6,23,1,1,1,1,1,29,21,22,1,1,1,1,1,1,1,40,46,11,26,1,1,1,40,46,8,9,4,5,16,17,6,7,11,26,1,1,30,31,27,28,1,1,1,1,6,7,8,9,4,22,1,1,40,46,47,35,1,1,1,1,1,1,29,36,37,38,39,4,22,1,16,17,6,7,8,9,10,7,11,18,27,28,1,1,1,1,1,1,1,1,1,1,8,12,6,7,8,9,4,5,45,48,49,50,2,3,4,5,1,40,46,19,20,33,18,42,35,1,13,14,8,12,6,7,8,12,6,23,1,1,1,1,1,1,1,1,2,3,4,5,6,7,11,18,19,14,11,26,1,1,2,3,25,7,42,26,1,30,31,43,31,27,44,27,28,1,30,31,19,14,8,12,6,7,8,9,4,5,1,1,2147483699,1,2,3,6,7,8,52,8,12,6,23,24,17,6,34,1,1,13,14,8,12,6,34,1,53,1,1,1,1,1,1,2,3,4,5,30,31,19,14,11,18,19,14,15,9,4,5,2147483702,1,13,14,8,12,6,7,6,7,8,9,25,32,8,9,4,5,16,17,6,7,8,9,4,5,1,1,1,1,1,1,13,14,8,9,4,5,16,17,6,23,24,17,6,7,15,9,4,5,16,17,6,7,8,12,8,12,6,7,8,12,6,7,8,9,10,7,8,12,6,7,8,9,4,5,2,3,4,5,16,17,6,7,8,9,10,32,8,9,25,7,15,12,6,7,15,9,25,32,8,12,6,7,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,42,26,13,14,8,9,25,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,34,16,17,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,9,25,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12,6,7,8,12 + + diff --git a/res/map1_tiles.png b/res/map1_tiles.png new file mode 100644 index 0000000..1f6d7b9 Binary files /dev/null and b/res/map1_tiles.png differ diff --git a/src/game.h b/src/game.h index e5976b1..2c1680a 100644 --- a/src/game.h +++ b/src/game.h @@ -4,8 +4,9 @@ #include #include #include -#include +#include #include "sprite.h" +#include "map.h" struct Input { bool left = false; @@ -55,18 +56,15 @@ public: } } - void loadMapFromFile(std::string_view filename) { - tson::Tileson t; - map_ = t.parse(fs::path(filename)); - } + void setMap(std::unique_ptr map) { map_ = std::move(map); } - tson::Map* getMap() const { return map_.get(); } + const Map& getMap() const { return *map_; } private: std::vector sprites_; std::set> spritesByY_; - std::unique_ptr map_; + std::unique_ptr map_; }; #endif /* end of include guard: GAME_H_E6F1396E */ diff --git a/src/main.cpp b/src/main.cpp index df0bfff..587ae15 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,14 +1,17 @@ #include +#include #include "renderer.h" #include "game.h" #include "party.h" #include "timer.h" +#include "map.h" void loop(Renderer& renderer) { Game game; Input keystate; - game.loadMapFromFile("../res/map1.json"); + auto map = std::make_unique("../res/map1.tmx", renderer); + game.setMap(std::move(map)); int lucasSprite = game.addSprite(Sprite("../res/lucas_anim.txt", renderer)); int kumaSprite = game.addSprite(Sprite("../res/kuma_anim.txt", renderer)); diff --git a/src/map.cpp b/src/map.cpp new file mode 100644 index 0000000..a60cbba --- /dev/null +++ b/src/map.cpp @@ -0,0 +1,46 @@ +#include "map.h" +#include +#include +#include +#include +#include "renderer.h" + +Map::Map(std::string_view filename, Renderer& renderer) { + tmx::Map mapfile; + if (!mapfile.load(filename.data())) { + throw std::invalid_argument("Could not find map file: " + std::string(filename)); + } + + const tmx::Vector2u& mapSize = mapfile.getTileCount(); + mapSize_.x() = mapSize.x; + mapSize_.y() = mapSize.y; + + const tmx::Vector2u& tileSize = mapfile.getTileSize(); + tileSize_.x() = tileSize.x; + tileSize_.y() = tileSize.y; + + int firstGID = 0; + // There should only be one tileset. + for (const tmx::Tileset& tileset : mapfile.getTilesets()) { + firstGID = tileset.getFirstGID(); + tilesetTextureId_ = renderer.loadImageFromFile(tileset.getImagePath()); + tilesetColumns_ = tileset.getColumnCount(); + } + + for (const auto& layer : mapfile.getLayers()) { + if (layer->getType() == tmx::Layer::Type::Tile) { + const auto& tileLayer = layer->getLayerAs(); + + std::vector tilesToStore; + + for (const auto& maptile : tileLayer.getTiles()) { + tilesToStore.push_back(Tile { + .id = maptile.ID - firstGID, + .flipHorizontal = (maptile.flipFlags & tmx::TileLayer::Horizontal) != 0, + .flipVertical = (maptile.flipFlags & tmx::TileLayer::Vertical) != 0 }); + } + + layers_.push_back(std::move(tilesToStore)); + } + } +} diff --git a/src/map.h b/src/map.h new file mode 100644 index 0000000..1031996 --- /dev/null +++ b/src/map.h @@ -0,0 +1,41 @@ +#ifndef MAP_H_D95D6D47 +#define MAP_H_D95D6D47 + +#include +#include +#include "renderer.h" +#include "vector.h" + +class Renderer; + +struct Tile { + unsigned int id = 0; + bool flipHorizontal = false; + bool flipVertical = false; +}; + +class Map { +public: + + Map(std::string_view filename, Renderer& renderer); + + const vec2i& getMapSize() const { return mapSize_; } + + const vec2i& getTileSize() const { return tileSize_; } + + const std::vector>& getLayers() const { return layers_; } + + int getTilesetTextureId() const { return tilesetTextureId_; } + + int getTilesetColumns() const { return tilesetColumns_; } + +private: + + vec2i mapSize_; + vec2i tileSize_; + std::vector> layers_; + int tilesetTextureId_; + int tilesetColumns_; +}; + +#endif /* end of include guard: MAP_H_D95D6D47 */ diff --git a/src/renderer.cpp b/src/renderer.cpp index 45b9045..9d20fee 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -1,6 +1,7 @@ #include "renderer.h" #include "consts.h" #include "game.h" +#include "map.h" Renderer::Renderer() { win_ = window_ptr( @@ -29,14 +30,16 @@ Renderer::Renderer() { } } -texture_ptr Renderer::renderMapLayer(const tson::Layer& layer) { +texture_ptr Renderer::renderMapLayer(const Map& map, int layer) { + vec2i mapBounds = map.getMapSize() * map.getTileSize(); + texture_ptr canvas( SDL_CreateTexture( ren_.get(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, - layer.getMap()->getSize().x * layer.getMap()->getTileSize().x, - layer.getMap()->getSize().y * layer.getMap()->getTileSize().y)); + mapBounds.w(), + mapBounds.h())); SDL_SetTextureBlendMode(canvas.get(), SDL_BLENDMODE_BLEND); @@ -45,38 +48,44 @@ texture_ptr Renderer::renderMapLayer(const tson::Layer& layer) { SDL_SetRenderDrawColor(ren_.get(), 255, 255, 255, 0); SDL_RenderClear(ren_.get()); - for (auto& [pos, tileObject] : layer.getTileObjects()) { - int x = tileObject.getPosition().x; - int y = tileObject.getPosition().y; - tson::Rect tileDestRect = tileObject.getDrawingRect(); - SDL_Rect srcRect { tileDestRect.x, tileDestRect.y, tileDestRect.width, tileDestRect.height }; - SDL_Rect destRect { - x, y, tileObject.getTile()->getTileSize().x, tileObject.getTile()->getTileSize().y }; - - SDL_RendererFlip flip = SDL_FLIP_NONE; - if (tileObject.getTile()->hasFlipFlags(tson::TileFlipFlags::Horizontally | tson::TileFlipFlags::Vertically)) { - flip = static_cast(SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL); - } else if (tileObject.getTile()->hasFlipFlags(tson::TileFlipFlags::Horizontally)) { - flip = SDL_FLIP_HORIZONTAL; - } else if (tileObject.getTile()->hasFlipFlags(tson::TileFlipFlags::Vertically)) { - flip = SDL_FLIP_VERTICAL; + const std::vector& tiles = map.getLayers().at(layer); + for (int y = 0; y < map.getMapSize().h(); y++) { + for (int x = 0; x < map.getMapSize().w(); x++) { + const Tile& tile = tiles.at(x + y * map.getMapSize().w()); + + SDL_Rect srcRect { + static_cast((tile.id % map.getTilesetColumns()) * map.getTileSize().w()), + static_cast((tile.id / map.getTilesetColumns()) * map.getTileSize().h()), + map.getTileSize().w(), + map.getTileSize().h() }; + + SDL_Rect destRect { + x * map.getTileSize().w(), + y * map.getTileSize().h(), + map.getTileSize().w(), + map.getTileSize().h() }; + + SDL_RendererFlip flip = SDL_FLIP_NONE; + if (tile.flipHorizontal && tile.flipVertical) { + flip = static_cast(SDL_FLIP_HORIZONTAL | SDL_FLIP_VERTICAL); + } else if (tile.flipHorizontal) { + flip = SDL_FLIP_HORIZONTAL; + } else if (tile.flipVertical) { + flip = SDL_FLIP_VERTICAL; + } + SDL_RenderCopyEx(ren_.get(), textures_[map.getTilesetTextureId()].get(), &srcRect, &destRect, 0, nullptr, flip); } - SDL_RenderCopyEx(ren_.get(), textures_[tilesetTexId_].get(), &srcRect, &destRect, 0, nullptr, flip); } return canvas; } void Renderer::render(Game& game) { - if (tilesetTexId_ == -1) { - tilesetTexId_ = loadImageFromFile(game.getMap()->getTileset("fromRom")->getImage().c_str()); - } - if (!renLay1_) { - renLay1_ = renderMapLayer(*game.getMap()->getLayer("Layer 1")); + renLay1_ = renderMapLayer(game.getMap(), 0); } if (!renLay0_) { - renLay0_ = renderMapLayer(*game.getMap()->getLayer("Layer 0")); + renLay0_ = renderMapLayer(game.getMap(), 1); } texture_ptr canvas( @@ -91,15 +100,15 @@ void Renderer::render(Game& game) { throw sdl_error(); } - - SDL_SetRenderTarget(ren_.get(), canvas.get()); SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(ren_.get(), 255, 255, 255, 255); SDL_RenderClear(ren_.get()); + vec2i mapBounds = game.getMap().getMapSize() * game.getMap().getTileSize(); + { - SDL_Rect dest { -80, -80, game.getMap()->getSize().x * game.getMap()->getTileSize().x, game.getMap()->getSize().y * game.getMap()->getTileSize().y }; + SDL_Rect dest { -80, -80, mapBounds.w(), mapBounds.h() }; SDL_RenderCopy(ren_.get(), renLay1_.get(), nullptr, &dest); } @@ -111,7 +120,7 @@ void Renderer::render(Game& game) { } { - SDL_Rect dest { -80, -80, game.getMap()->getSize().x * game.getMap()->getTileSize().x, game.getMap()->getSize().y * game.getMap()->getTileSize().y }; + SDL_Rect dest { -80, -80, mapBounds.w(), mapBounds.h() }; SDL_RenderCopy(ren_.get(), renLay0_.get(), nullptr, &dest); } diff --git a/src/renderer.h b/src/renderer.h index 9573d8c..f952ab3 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -7,9 +7,9 @@ #include #include #include -#include class Game; +class Map; class sdl_error : public std::logic_error { public: @@ -122,7 +122,7 @@ public: private: - texture_ptr renderMapLayer(const tson::Layer& layer); + texture_ptr renderMapLayer(const Map& map, int layer); sdl_wrapper sdl_; img_wrapper img_; @@ -130,7 +130,6 @@ private: renderer_ptr ren_; std::vector textures_; - int tilesetTexId_ = -1; texture_ptr renLay0_; texture_ptr renLay1_; }; diff --git a/src/vector.h b/src/vector.h index bf38bb2..d54fdbb 100644 --- a/src/vector.h +++ b/src/vector.h @@ -91,6 +91,10 @@ public: return *this; } + vec2 operator*(const vec2& other) const { + return vec2(x() * other.x(), y() * other.y()); + } + bool operator==(const vec2& other) const { return std::tie(x(), other.x()) == std::tie(y(), other.y()); } diff --git a/vendor/tileson.hpp b/vendor/tileson.hpp deleted file mode 100644 index f8545ed..0000000 --- a/vendor/tileson.hpp +++ /dev/null @@ -1,7391 +0,0 @@ -/// -/// T I L E S O N V E R S I O N 1 . 3 . 0 -/// ------------------------------------------------ -/// BSD 2-Clause License -/// -/// Copyright (c) 2020, Robin Berg Pettersen -/// All rights reserved. -/// -/// Redistribution and use in source and binary forms, with or without -/// modification, are permitted provided that the following conditions are met: -/// -/// 1. Redistributions of source code must retain the above copyright notice, this -/// list of conditions and the following disclaimer. -/// -/// 2. Redistributions in binary form must reproduce the above copyright notice, -/// this list of conditions and the following disclaimer in the documentation -/// and/or other materials provided with the distribution. -/// -/// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -/// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -/// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -/// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -/// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -/// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -/// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -/// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -/// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -/// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef TILESON_TILESON_H -#define TILESON_TILESON_H - - -/*** Start of inlined file: json11.hpp ***/ -/*** Start of inlined file: json11.cpp ***/ - -/*** Start of inlined file: json11.hpp ***/ -/* Copyright (c) 2013 Dropbox, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#define JSON11_IS_DEFINED - -#ifdef _MSC_VER -#if _MSC_VER <= 1800 // VS 2013 - #ifndef noexcept - #define noexcept throw() - #endif - - #ifndef snprintf - #define snprintf _snprintf_s - #endif - #endif -#endif - -namespace json11 { - - enum JsonParse { - STANDARD, COMMENTS - }; - - class JsonValue; - - class Json final { - public: - // Types - enum Type { - NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT - }; - - // Array and object typedefs - typedef std::vector array; - typedef std::map object; - - // Constructors for the various types of JSON value. - inline Json() noexcept; // NUL - inline Json(std::nullptr_t) noexcept; // NUL - inline Json(double value); // NUMBER - inline Json(int value); // NUMBER - inline Json(bool value); // BOOL - inline Json(const std::string &value); // STRING - inline Json(std::string &&value); // STRING - inline Json(const char * value); // STRING - inline Json(const array &values); // ARRAY - inline Json(array &&values); // ARRAY - inline Json(const object &values); // OBJECT - inline Json(object &&values); // OBJECT - - // Implicit constructor: anything with a to_json() function. - template - inline Json(const T & t) : Json(t.to_json()) {} - - // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) - template ().begin()->first)>::value - && std::is_constructible().begin()->second)>::value, - int>::type = 0> - inline Json(const M & m) : Json(object(m.begin(), m.end())) {} - - // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc) - template ().begin())>::value, - int>::type = 0> - inline Json(const V & v) : Json(array(v.begin(), v.end())) {} - - // This prevents Json(some_pointer) from accidentally producing a bool. Use - // Json(bool(some_pointer)) if that behavior is desired. - Json(void *) = delete; - - // Accessors - inline Type type() const; - - inline bool is_null() const { return type() == NUL; } - inline bool is_number() const { return type() == NUMBER; } - inline bool is_bool() const { return type() == BOOL; } - inline bool is_string() const { return type() == STRING; } - inline bool is_array() const { return type() == ARRAY; } - inline bool is_object() const { return type() == OBJECT; } - - // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not - // distinguish between integer and non-integer numbers - number_value() and int_value() - // can both be applied to a NUMBER-typed object. - inline double number_value() const; - inline int int_value() const; - - // Return the enclosed value if this is a boolean, false otherwise. - inline bool bool_value() const; - // Return the enclosed string if this is a string, "" otherwise. - inline const std::string &string_value() const; - // Return the enclosed std::vector if this is an array, or an empty vector otherwise. - inline const array &array_items() const; - // Return the enclosed std::map if this is an object, or an empty map otherwise. - inline const object &object_items() const; - - // Return a reference to arr[i] if this is an array, Json() otherwise. - inline const Json & operator[](size_t i) const; - // Return a reference to obj[key] if this is an object, Json() otherwise. - inline const Json & operator[](const std::string &key) const; - - // Serialize. - inline void dump(std::string &out) const; - inline std::string dump() const { - std::string out; - dump(out); - return out; - } - - // Parse. If parse fails, return Json() and assign an error message to err. - static inline Json parse(const std::string & in, - std::string & err, - JsonParse strategy = JsonParse::STANDARD); - static inline Json parse(const char * in, - std::string & err, - JsonParse strategy = JsonParse::STANDARD) { - if (in) { - return parse(std::string(in), err, strategy); - } else { - err = "null input"; - return nullptr; - } - } - // Parse multiple objects, concatenated or separated by whitespace - static inline std::vector parse_multi( - const std::string & in, - std::string::size_type & parser_stop_pos, - std::string & err, - JsonParse strategy = JsonParse::STANDARD); - - static inline std::vector parse_multi( - const std::string & in, - std::string & err, - JsonParse strategy = JsonParse::STANDARD) { - std::string::size_type parser_stop_pos; - return parse_multi(in, parser_stop_pos, err, strategy); - } - - inline bool operator== (const Json &rhs) const; - inline bool operator< (const Json &rhs) const; - inline bool operator!= (const Json &rhs) const { return !(*this == rhs); } - inline bool operator<= (const Json &rhs) const { return !(rhs < *this); } - inline bool operator> (const Json &rhs) const { return (rhs < *this); } - inline bool operator>= (const Json &rhs) const { return !(*this < rhs); } - - /* has_shape(types, err) - * - * Return true if this is a JSON object and, for each item in types, has a field of - * the given type. If not, return false and set err to a descriptive message. - */ - typedef std::initializer_list> shape; - inline bool has_shape(const shape & types, std::string & err) const; - - private: - std::shared_ptr m_ptr; - }; - -// Internal class hierarchy - JsonValue objects are not exposed to users of this API. - class JsonValue { - protected: - friend class Json; - friend class JsonInt; - friend class JsonDouble; - virtual Json::Type type() const = 0; - virtual bool equals(const JsonValue * other) const = 0; - virtual bool less(const JsonValue * other) const = 0; - virtual void dump(std::string &out) const = 0; - virtual double number_value() const; - virtual int int_value() const; - virtual bool bool_value() const; - virtual const std::string &string_value() const; - virtual const Json::array &array_items() const; - virtual const Json &operator[](size_t i) const; - virtual const Json::object &object_items() const; - virtual const Json &operator[](const std::string &key) const; - virtual ~JsonValue() {} - }; - -} // namespace json11 - -/*** End of inlined file: json11.hpp ***/ - -#include -#include -#include -#include -#include - -namespace json11 { - - static const int max_depth = 200; - - using std::string; - using std::vector; - using std::map; - using std::make_shared; - using std::initializer_list; - using std::move; - -/* Helper for representing null - just a do-nothing struct, plus comparison - * operators so the helpers in JsonValue work. We can't use nullptr_t because - * it may not be orderable. - */ - struct NullStruct { - bool operator==(NullStruct) const { return true; } - bool operator<(NullStruct) const { return false; } - }; - -/* * * * * * * * * * * * * * * * * * * * - * Serialization - */ - - static void dump(NullStruct, string &out) { - out += "null"; - } - - static void dump(double value, string &out) { - if (std::isfinite(value)) { - char buf[32]; - snprintf(buf, sizeof buf, "%.17g", value); - out += buf; - } else { - out += "null"; - } - } - - static void dump(int value, string &out) { - char buf[32]; - snprintf(buf, sizeof buf, "%d", value); - out += buf; - } - - static void dump(bool value, string &out) { - out += value ? "true" : "false"; - } - - static void dump(const string &value, string &out) { - out += '"'; - for (size_t i = 0; i < value.length(); i++) { - const char ch = value[i]; - if (ch == '\\') { - out += "\\\\"; - } else if (ch == '"') { - out += "\\\""; - } else if (ch == '\b') { - out += "\\b"; - } else if (ch == '\f') { - out += "\\f"; - } else if (ch == '\n') { - out += "\\n"; - } else if (ch == '\r') { - out += "\\r"; - } else if (ch == '\t') { - out += "\\t"; - } else if (static_cast(ch) <= 0x1f) { - char buf[8]; - snprintf(buf, sizeof buf, "\\u%04x", ch); - out += buf; - } else if (static_cast(ch) == 0xe2 && static_cast(value[i+1]) == 0x80 - && static_cast(value[i+2]) == 0xa8) { - out += "\\u2028"; - i += 2; - } else if (static_cast(ch) == 0xe2 && static_cast(value[i+1]) == 0x80 - && static_cast(value[i+2]) == 0xa9) { - out += "\\u2029"; - i += 2; - } else { - out += ch; - } - } - out += '"'; - } - - static void dump(const Json::array &values, string &out) { - bool first = true; - out += "["; - for (const auto &value : values) { - if (!first) - out += ", "; - value.dump(out); - first = false; - } - out += "]"; - } - - static void dump(const Json::object &values, string &out) { - bool first = true; - out += "{"; - for (const auto &kv : values) { - if (!first) - out += ", "; - dump(kv.first, out); - out += ": "; - kv.second.dump(out); - first = false; - } - out += "}"; - } - - void Json::dump(string &out) const { - m_ptr->dump(out); - } - -/* * * * * * * * * * * * * * * * * * * * - * Value wrappers - */ - - template - class Value : public JsonValue { - protected: - - // Constructors - explicit Value(const T &value) : m_value(value) {} - explicit Value(T &&value) : m_value(move(value)) {} - - // Get type tag - Json::Type type() const override { - return tag; - } - - // Comparisons - bool equals(const JsonValue * other) const override { - return m_value == static_cast *>(other)->m_value; - } - bool less(const JsonValue * other) const override { - return m_value < static_cast *>(other)->m_value; - } - - const T m_value; - void dump(string &out) const override { json11::dump(m_value, out); } - }; - - class JsonDouble final : public Value { - double number_value() const override { return m_value; } - int int_value() const override { return static_cast(m_value); } - bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } - bool less(const JsonValue * other) const override { return m_value < other->number_value(); } - public: - explicit JsonDouble(double value) : Value(value) {} - }; - - class JsonInt final : public Value { - double number_value() const override { return m_value; } - int int_value() const override { return m_value; } - bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } - bool less(const JsonValue * other) const override { return m_value < other->number_value(); } - public: - explicit JsonInt(int value) : Value(value) {} - }; - - class JsonBoolean final : public Value { - bool bool_value() const override { return m_value; } - public: - explicit JsonBoolean(bool value) : Value(value) {} - }; - - class JsonString final : public Value { - const string &string_value() const override { return m_value; } - public: - explicit JsonString(const string &value) : Value(value) {} - explicit JsonString(string &&value) : Value(move(value)) {} - }; - - class JsonArray final : public Value { - const Json::array &array_items() const override { return m_value; } - const Json & operator[](size_t i) const override; - public: - explicit JsonArray(const Json::array &value) : Value(value) {} - explicit JsonArray(Json::array &&value) : Value(move(value)) {} - }; - - class JsonObject final : public Value { - const Json::object &object_items() const override { return m_value; } - const Json & operator[](const string &key) const override; - public: - explicit JsonObject(const Json::object &value) : Value(value) {} - explicit JsonObject(Json::object &&value) : Value(move(value)) {} - }; - - class JsonNull final : public Value { - public: - JsonNull() : Value({}) {} - }; - -/* * * * * * * * * * * * * * * * * * * * - * Static globals - static-init-safe - */ - struct Statics { - const std::shared_ptr null = make_shared(); - const std::shared_ptr t = make_shared(true); - const std::shared_ptr f = make_shared(false); - const string empty_string; - const vector empty_vector; - const map empty_map; - Statics() {} - }; - - static const Statics & statics() { - static const Statics s {}; - return s; - } - - static const Json & static_null() { - // This has to be separate, not in Statics, because Json() accesses statics().null. - static const Json json_null; - return json_null; - } - -/* * * * * * * * * * * * * * * * * * * * - * Constructors - */ - - Json::Json() noexcept : m_ptr(statics().null) {} - Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {} - Json::Json(double value) : m_ptr(make_shared(value)) {} - Json::Json(int value) : m_ptr(make_shared(value)) {} - Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {} - Json::Json(const string &value) : m_ptr(make_shared(value)) {} - Json::Json(string &&value) : m_ptr(make_shared(move(value))) {} - Json::Json(const char * value) : m_ptr(make_shared(value)) {} - Json::Json(const Json::array &values) : m_ptr(make_shared(values)) {} - Json::Json(Json::array &&values) : m_ptr(make_shared(move(values))) {} - Json::Json(const Json::object &values) : m_ptr(make_shared(values)) {} - Json::Json(Json::object &&values) : m_ptr(make_shared(move(values))) {} - -/* * * * * * * * * * * * * * * * * * * * - * Accessors - */ - - inline Json::Type Json::type() const { return m_ptr->type(); } - inline double Json::number_value() const { return m_ptr->number_value(); } - inline int Json::int_value() const { return m_ptr->int_value(); } - inline bool Json::bool_value() const { return m_ptr->bool_value(); } - inline const string & Json::string_value() const { return m_ptr->string_value(); } - inline const vector & Json::array_items() const { return m_ptr->array_items(); } - inline const map & Json::object_items() const { return m_ptr->object_items(); } - inline const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; } - inline const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; } - - inline double JsonValue::number_value() const { return 0; } - inline int JsonValue::int_value() const { return 0; } - inline bool JsonValue::bool_value() const { return false; } - inline const string & JsonValue::string_value() const { return statics().empty_string; } - inline const vector & JsonValue::array_items() const { return statics().empty_vector; } - inline const map & JsonValue::object_items() const { return statics().empty_map; } - inline const Json & JsonValue::operator[] (size_t) const { return static_null(); } - inline const Json & JsonValue::operator[] (const string &) const { return static_null(); } - - inline const Json & JsonObject::operator[] (const string &key) const { - auto iter = m_value.find(key); - return (iter == m_value.end()) ? static_null() : iter->second; - } - inline const Json & JsonArray::operator[] (size_t i) const { - if (i >= m_value.size()) return static_null(); - else return m_value[i]; - } - -/* * * * * * * * * * * * * * * * * * * * - * Comparison - */ - - bool Json::operator== (const Json &other) const { - if (m_ptr == other.m_ptr) - return true; - if (m_ptr->type() != other.m_ptr->type()) - return false; - - return m_ptr->equals(other.m_ptr.get()); - } - - bool Json::operator< (const Json &other) const { - if (m_ptr == other.m_ptr) - return false; - if (m_ptr->type() != other.m_ptr->type()) - return m_ptr->type() < other.m_ptr->type(); - - return m_ptr->less(other.m_ptr.get()); - } - -/* * * * * * * * * * * * * * * * * * * * - * Parsing - */ - -/* esc(c) - * - * Format char c suitable for printing in an error message. - */ - static inline string esc(char c) { - char buf[12]; - if (static_cast(c) >= 0x20 && static_cast(c) <= 0x7f) { - snprintf(buf, sizeof buf, "'%c' (%d)", c, c); - } else { - snprintf(buf, sizeof buf, "(%d)", c); - } - return string(buf); - } - - static inline bool in_range(long x, long lower, long upper) { - return (x >= lower && x <= upper); - } - - namespace { -/* JsonParser - * - * Object that tracks all state of an in-progress parse. - */ - struct JsonParser final { - - /* State - */ - const string &str; - size_t i; - string &err; - bool failed; - const JsonParse strategy; - - /* fail(msg, err_ret = Json()) - * - * Mark this parse as failed. - */ - Json fail(string &&msg) { - return fail(move(msg), Json()); - } - - template - T fail(string &&msg, const T err_ret) { - if (!failed) - err = std::move(msg); - failed = true; - return err_ret; - } - - /* consume_whitespace() - * - * Advance until the current character is non-whitespace. - */ - void consume_whitespace() { - while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t') - i++; - } - - /* consume_comment() - * - * Advance comments (c-style inline and multiline). - */ - bool consume_comment() { - bool comment_found = false; - if (str[i] == '/') { - i++; - if (i == str.size()) - return fail("unexpected end of input after start of comment", false); - if (str[i] == '/') { // inline comment - i++; - // advance until next line, or end of input - while (i < str.size() && str[i] != '\n') { - i++; - } - comment_found = true; - } - else if (str[i] == '*') { // multiline comment - i++; - if (i > str.size()-2) - return fail("unexpected end of input inside multi-line comment", false); - // advance until closing tokens - while (!(str[i] == '*' && str[i+1] == '/')) { - i++; - if (i > str.size()-2) - return fail( - "unexpected end of input inside multi-line comment", false); - } - i += 2; - comment_found = true; - } - else - return fail("malformed comment", false); - } - return comment_found; - } - - /* consume_garbage() - * - * Advance until the current character is non-whitespace and non-comment. - */ - void consume_garbage() { - consume_whitespace(); - if(strategy == JsonParse::COMMENTS) { - bool comment_found = false; - do { - comment_found = consume_comment(); - if (failed) return; - consume_whitespace(); - } - while(comment_found); - } - } - - /* get_next_token() - * - * Return the next non-whitespace character. If the end of the input is reached, - * flag an error and return 0. - */ - char get_next_token() { - consume_garbage(); - if (failed) return static_cast(0); - if (i == str.size()) - return fail("unexpected end of input", static_cast(0)); - - return str[i++]; - } - - /* encode_utf8(pt, out) - * - * Encode pt as UTF-8 and add it to out. - */ - void encode_utf8(long pt, string & out) { - if (pt < 0) - return; - - if (pt < 0x80) { - out += static_cast(pt); - } else if (pt < 0x800) { - out += static_cast((pt >> 6) | 0xC0); - out += static_cast((pt & 0x3F) | 0x80); - } else if (pt < 0x10000) { - out += static_cast((pt >> 12) | 0xE0); - out += static_cast(((pt >> 6) & 0x3F) | 0x80); - out += static_cast((pt & 0x3F) | 0x80); - } else { - out += static_cast((pt >> 18) | 0xF0); - out += static_cast(((pt >> 12) & 0x3F) | 0x80); - out += static_cast(((pt >> 6) & 0x3F) | 0x80); - out += static_cast((pt & 0x3F) | 0x80); - } - } - - /* parse_string() - * - * Parse a string, starting at the current position. - */ - string parse_string() { - string out; - long last_escaped_codepoint = -1; - while (true) { - if (i == str.size()) - return fail("unexpected end of input in string", ""); - - char ch = str[i++]; - - if (ch == '"') { - encode_utf8(last_escaped_codepoint, out); - return out; - } - - if (in_range(ch, 0, 0x1f)) - return fail("unescaped " + esc(ch) + " in string", ""); - - // The usual case: non-escaped characters - if (ch != '\\') { - encode_utf8(last_escaped_codepoint, out); - last_escaped_codepoint = -1; - out += ch; - continue; - } - - // Handle escapes - if (i == str.size()) - return fail("unexpected end of input in string", ""); - - ch = str[i++]; - - if (ch == 'u') { - // Extract 4-byte escape sequence - string esc = str.substr(i, 4); - // Explicitly check length of the substring. The following loop - // relies on std::string returning the terminating NUL when - // accessing str[length]. Checking here reduces brittleness. - if (esc.length() < 4) { - return fail("bad \\u escape: " + esc, ""); - } - for (size_t j = 0; j < 4; j++) { - if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F') - && !in_range(esc[j], '0', '9')) - return fail("bad \\u escape: " + esc, ""); - } - - long codepoint = strtol(esc.data(), nullptr, 16); - - // JSON specifies that characters outside the BMP shall be encoded as a pair - // of 4-hex-digit \u escapes encoding their surrogate pair components. Check - // whether we're in the middle of such a beast: the previous codepoint was an - // escaped lead (high) surrogate, and this is a trail (low) surrogate. - if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF) - && in_range(codepoint, 0xDC00, 0xDFFF)) { - // Reassemble the two surrogate pairs into one astral-plane character, per - // the UTF-16 algorithm. - encode_utf8((((last_escaped_codepoint - 0xD800) << 10) - | (codepoint - 0xDC00)) + 0x10000, out); - last_escaped_codepoint = -1; - } else { - encode_utf8(last_escaped_codepoint, out); - last_escaped_codepoint = codepoint; - } - - i += 4; - continue; - } - - encode_utf8(last_escaped_codepoint, out); - last_escaped_codepoint = -1; - - if (ch == 'b') { - out += '\b'; - } else if (ch == 'f') { - out += '\f'; - } else if (ch == 'n') { - out += '\n'; - } else if (ch == 'r') { - out += '\r'; - } else if (ch == 't') { - out += '\t'; - } else if (ch == '"' || ch == '\\' || ch == '/') { - out += ch; - } else { - return fail("invalid escape character " + esc(ch), ""); - } - } - } - - /* parse_number() - * - * Parse a double. - */ - Json parse_number() { - size_t start_pos = i; - - if (str[i] == '-') - i++; - - // Integer part - if (str[i] == '0') { - i++; - if (in_range(str[i], '0', '9')) - return fail("leading 0s not permitted in numbers"); - } else if (in_range(str[i], '1', '9')) { - i++; - while (in_range(str[i], '0', '9')) - i++; - } else { - return fail("invalid " + esc(str[i]) + " in number"); - } - - if (str[i] != '.' && str[i] != 'e' && str[i] != 'E' - && (i - start_pos) <= static_cast(std::numeric_limits::digits10)) { - return std::atoi(str.c_str() + start_pos); - } - - // Decimal part - if (str[i] == '.') { - i++; - if (!in_range(str[i], '0', '9')) - return fail("at least one digit required in fractional part"); - - while (in_range(str[i], '0', '9')) - i++; - } - - // Exponent part - if (str[i] == 'e' || str[i] == 'E') { - i++; - - if (str[i] == '+' || str[i] == '-') - i++; - - if (!in_range(str[i], '0', '9')) - return fail("at least one digit required in exponent"); - - while (in_range(str[i], '0', '9')) - i++; - } - - return std::strtod(str.c_str() + start_pos, nullptr); - } - - /* expect(str, res) - * - * Expect that 'str' starts at the character that was just read. If it does, advance - * the input and return res. If not, flag an error. - */ - Json expect(const string &expected, Json res) { - assert(i != 0); - i--; - if (str.compare(i, expected.length(), expected) == 0) { - i += expected.length(); - return res; - } else { - return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length())); - } - } - - /* parse_json() - * - * Parse a JSON object. - */ - Json parse_json(int depth) { - if (depth > max_depth) { - return fail("exceeded maximum nesting depth"); - } - - char ch = get_next_token(); - if (failed) - return Json(); - - if (ch == '-' || (ch >= '0' && ch <= '9')) { - i--; - return parse_number(); - } - - if (ch == 't') - return expect("true", true); - - if (ch == 'f') - return expect("false", false); - - if (ch == 'n') - return expect("null", Json()); - - if (ch == '"') - return parse_string(); - - if (ch == '{') { - map data; - ch = get_next_token(); - if (ch == '}') - return data; - - while (1) { - if (ch != '"') - return fail("expected '\"' in object, got " + esc(ch)); - - string key = parse_string(); - if (failed) - return Json(); - - ch = get_next_token(); - if (ch != ':') - return fail("expected ':' in object, got " + esc(ch)); - - data[std::move(key)] = parse_json(depth + 1); - if (failed) - return Json(); - - ch = get_next_token(); - if (ch == '}') - break; - if (ch != ',') - return fail("expected ',' in object, got " + esc(ch)); - - ch = get_next_token(); - } - return data; - } - - if (ch == '[') { - vector data; - ch = get_next_token(); - if (ch == ']') - return data; - - while (1) { - i--; - data.push_back(parse_json(depth + 1)); - if (failed) - return Json(); - - ch = get_next_token(); - if (ch == ']') - break; - if (ch != ',') - return fail("expected ',' in list, got " + esc(ch)); - - ch = get_next_token(); - (void)ch; - } - return data; - } - - return fail("expected value, got " + esc(ch)); - } - }; - }//namespace { - - Json Json::parse(const string &in, string &err, JsonParse strategy) { - JsonParser parser { in, 0, err, false, strategy }; - Json result = parser.parse_json(0); - - // Check for any trailing garbage - parser.consume_garbage(); - if (parser.failed) - return Json(); - if (parser.i != in.size() && - ((parser.i + 1) != in.size() && in[parser.i] != 0)) //RBP: If there is only 1 character diff, it is probably just a terminating zero from a memory read. - { - return parser.fail("unexpected trailing " + esc(in[parser.i])); - } - return result; - } - -// Documented in json11.hpp - vector Json::parse_multi(const string &in, - std::string::size_type &parser_stop_pos, - string &err, - JsonParse strategy) { - JsonParser parser { in, 0, err, false, strategy }; - parser_stop_pos = 0; - vector json_vec; - while (parser.i != in.size() && !parser.failed) { - json_vec.push_back(parser.parse_json(0)); - if (parser.failed) - break; - - // Check for another object - parser.consume_garbage(); - if (parser.failed) - break; - parser_stop_pos = parser.i; - } - return json_vec; - } - -/* * * * * * * * * * * * * * * * * * * * - * Shape-checking - */ - - bool Json::has_shape(const shape & types, string & err) const { - if (!is_object()) { - err = "expected JSON object, got " + dump(); - return false; - } - - const auto& obj_items = object_items(); - for (auto & item : types) { - const auto it = obj_items.find(item.first); - if (it == obj_items.cend() || it->second.type() != item.second) { - err = "bad type for " + item.first + " in " + dump(); - return false; - } - } - - return true; - } - -} // namespace json11 - -/*** End of inlined file: json11.cpp ***/ - -/*** End of inlined file: json11.hpp ***/ - - -/*** Start of inlined file: tileson_parser.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_TILESON_PARSER_HPP -#define TILESON_TILESON_PARSER_HPP - -//RBP: FS-namespace is defined in tileson_parser now! -#if _MSC_VER && !__INTEL_COMPILER - #include - namespace fs = std::filesystem; -#elif __MINGW64__ - #if __MINGW64_VERSION_MAJOR > 6 - #include - namespace fs = std::filesystem; - #else - #include - namespace fs = std::experimental::filesystem; - #endif -#elif __clang__ - #if __clang_major__ < 8 - #include - namespace fs = std::experimental::filesystem; - #else - #include - namespace fs = std::filesystem; - #endif -#else //Linux - #if __GNUC__ < 8 //GCC major version less than 8 - #include - namespace fs = std::experimental::filesystem; - #else - #include - namespace fs = std::filesystem; - #endif -#endif - -#include -#include -#include - - -/*** Start of inlined file: Tools.hpp ***/ -// -// Created by robin on 31.07.2020. -// - -#ifndef TILESON_TOOLS_HPP -#define TILESON_TOOLS_HPP - -#include -#include -#include -namespace tson -{ - class Tools - { - - public: - Tools() = delete; - ~Tools() = delete; - inline static std::vector Base64DecodedStringToBytes(std::string_view str); - inline static std::vector BytesToUnsignedInts(const std::vector &bytes); - //inline static std::vector BytesToInts(const std::vector &bytes); - }; - - /*! - * When you have decoded a Base64 string, you'll get a string representing bytes. This function turns them into actual bytes. - * @param str - * @return - */ - std::vector Tools::Base64DecodedStringToBytes(std::string_view str) - { - std::vector bytes; - for(size_t i = 0; i < str.size(); ++i) - { - uint8_t u8 = static_cast(str[i]); - bytes.push_back(u8); - } - return bytes; - } - - /*! - * Converts bytes into unsigned int values. The bytes are converted in the Little Endian byte order to fit Tiled's specs. - * @param bytes A vector of bytes. - * @return Bytes converted to unsigned ints - */ - std::vector Tools::BytesToUnsignedInts(const std::vector &bytes) - { - std::vector uints; - std::vector toConvert; - //uint32_t size8 = (compressed[55] << 24) | (compressed[56] << 16) | (compressed[57] << 8) | compressed[58]; //Should be 66000 - - for(size_t i = 0; i < bytes.size(); ++i) - { - toConvert.push_back(bytes[i]); - if(toConvert.size() == 4) - { - uint32_t u32 = (toConvert[3] << 24) | (toConvert[2] << 16) | (toConvert[1] << 8) | toConvert[0]; - uints.push_back(u32); - toConvert.clear(); - } - } - - return uints; - } - - /*! - * While the Tiled specification uses unsigned ints for their tiles, Tileson uses regular ints. - * This may be changed in the future, but should in reality never really become an issue. - * - * Update 2020-11-09: This will cause problems when tiles has flip flags! - * - * int differences: - * int max: 2147483647 - * uint max: 4294967295 - * - * @param bytes A vector of bytes. - * @return Bytes converted to ints - */ - /*std::vector Tools::BytesToInts(const std::vector &bytes) - { - std::vector ints; - std::vector toConvert; - //uint32_t size8 = (compressed[55] << 24) | (compressed[56] << 16) | (compressed[57] << 8) | compressed[58]; //Should be 66000 - - for(size_t i = 0; i < bytes.size(); ++i) - { - toConvert.push_back(bytes[i]); - if(toConvert.size() == 4) - { - uint32_t u32 = (toConvert[3] << 24) | (toConvert[2] << 16) | (toConvert[1] << 8) | toConvert[0]; - ints.push_back(u32); - toConvert.clear(); - } - } - - return ints; - }*/ -} - -#endif //TILESON_TOOLS_HPP - -/*** End of inlined file: Tools.hpp ***/ - - -/*** Start of inlined file: Base64Decompressor.hpp ***/ -// -// Created by robin on 29.07.2020. -// The Base64 decoding logic is heavily based on: https://github.com/ReneNyffenegger/cpp-base64 -// - -#ifndef TILESON_BASE64DECOMPRESSOR_HPP -#define TILESON_BASE64DECOMPRESSOR_HPP - - -/*** Start of inlined file: IDecompressor.hpp ***/ -// -// Created by robin on 29.07.2020. -// - -#ifndef TILESON_IDECOMPRESSOR_HPP -#define TILESON_IDECOMPRESSOR_HPP - -#include - -namespace tson -{ - template - class IDecompressor - { - public: - /*! - * If the name matches with 'compression' or 'encoding' the decompress() function will - * be called automatically for the actual Layer. Encoding-related matching is handled first! - * - * Known values: - * - * compression: zlib, gzip, zstd (since Tiled 1.3) or empty (default) (tilelayer only). - * encoding: csv (default) or base64 (tilelayer only). - * - * @return - */ - [[nodiscard]] virtual const std::string &name() const = 0; - - /*! - * Used primarily for Tiled related decompression. - * @param input Input data - * @return Decompressed data - */ - virtual TOut decompress(const TIn &input) = 0; - - /*! - * Used for whole file decompression. Not related to Tiled - * @param path - * @return - */ - virtual TOut decompressFile(const fs::path &path) = 0; - - /*! - * Used for whole file decompression. Not related to Tiled - * @param path - * @return - */ - virtual TOut decompress(const void *data, size_t size) = 0; - }; -} - -#endif //TILESON_IDECOMPRESSOR_HPP - -/*** End of inlined file: IDecompressor.hpp ***/ - -#include - -namespace tson -{ - class Base64Decompressor : public IDecompressor - { - public: - [[nodiscard]] inline const std::string &name() const override; - - inline std::string decompress(const std::string_view &s) override; - - inline std::string decompressFile(const fs::path &path) override; - inline std::string decompress(const void *data, size_t size) override; - - private: - inline unsigned int pos_of_char(const unsigned char chr); - inline static const std::string NAME = "base64"; - }; - - const std::string &Base64Decompressor::name() const - { - return NAME; - } - - std::string Base64Decompressor::decompress(const std::string_view &s) - { - - size_t length_of_string = s.length(); - if (!length_of_string) return std::string(""); - - size_t in_len = length_of_string; - size_t pos = 0; - - // - // The approximate length (bytes) of the decoded string might be one ore - // two bytes smaller, depending on the amount of trailing equal signs - // in the encoded string. This approximation is needed to reserve - // enough space in the string to be returned. - // - size_t approx_length_of_decoded_string = length_of_string / 4 * 3; - std::string ret; - ret.reserve(approx_length_of_decoded_string); - - while (pos < in_len) { - - unsigned int pos_of_char_1 = pos_of_char(s[pos+1] ); - - ret.push_back(static_cast( ( (pos_of_char(s[pos+0]) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4))); - - if (s[pos+2] != '=' && s[pos+2] != '.') { // accept URL-safe base 64 strings, too, so check for '.' also. - - unsigned int pos_of_char_2 = pos_of_char(s[pos+2] ); - ret.push_back(static_cast( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2))); - - if (s[pos+3] != '=' && s[pos+3] != '.') { - ret.push_back(static_cast( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(s[pos+3]) )); - } - } - - pos += 4; - } - - return ret; - } - - unsigned int Base64Decompressor::pos_of_char(const unsigned char chr) - { - // - // Return the position of chr within base64_encode() - // - - if (chr >= 'A' && chr <= 'Z') return chr - 'A'; - else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1; - else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2; - else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters ( - else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_' - - throw "If input is correct, this line should never be reached."; - } - - /*! - * UNUSED! Does nothing - * @param path - * @return - */ - std::string Base64Decompressor::decompressFile(const fs::path &path) - { - return std::string(); - } - - /*! - * UNUSED! Does nothing - * @param path - * @return - */ - std::string Base64Decompressor::decompress(const void *data, size_t size) - { - return std::string(); - } -} - -#endif //TILESON_BASE64DECOMPRESSOR_HPP - -/*** End of inlined file: Base64Decompressor.hpp ***/ - - -/*** Start of inlined file: Lzma.hpp ***/ -// -// Created by robin on 16.01.2021. -// -//#include "../../extras/pocketlzma.hpp" -#ifdef POCKETLZMA_POCKETLZMA_H - -#ifndef TILESON_LZMA_HPP -#define TILESON_LZMA_HPP - -namespace tson -{ - class Lzma : public IDecompressor, std::vector> - { - public: - inline const std::string &name() const override - { - return NAME; - } - - inline std::vector decompress(const std::vector &input) override - { - std::vector out; - - plz::PocketLzma p; - plz::StatusCode status = p.decompress(input, out); - - if(status != plz::StatusCode::Ok) - return std::vector(); - - return out; - } - - inline std::vector decompressFile(const fs::path &path) override - { - std::vector in; - std::vector out; - - plz::PocketLzma p; - plz::FileStatus fileStatus = plz::File::FromFile(path.u8string(), in); - if(fileStatus.status() != plz::FileStatus::Code::Ok) - return std::vector(); - - plz::StatusCode status = p.decompress(in, out); - - if(status != plz::StatusCode::Ok) - return std::vector(); - - return out; - } - - inline std::vector decompress(const void *data, size_t size) override - { - std::vector out; - - plz::PocketLzma p; - plz::StatusCode status = p.decompress((uint8_t*) data, size, out); - - if(status != plz::StatusCode::Ok) - return std::vector(); - - return out; - } - - private: - inline static const std::string NAME {"lzma"}; - }; -} - -#endif //TILESON_LZMA_HPP - -#endif -/*** End of inlined file: Lzma.hpp ***/ - - -/*** Start of inlined file: DecompressorContainer.hpp ***/ -// -// Created by robin on 30.07.2020. -// - -#ifndef TILESON_DECOMPRESSORCONTAINER_HPP -#define TILESON_DECOMPRESSORCONTAINER_HPP - -#include -#include -#include -#include -namespace tson -{ - class DecompressorContainer - { - public: - inline DecompressorContainer() = default; - template - inline void add(Args &&... args); - inline void remove(std::string_view name); - inline bool contains(std::string_view name) const; - inline bool empty() const; - inline size_t size() const; - inline void clear(); - - inline IDecompressor *get(std::string_view name); - private: - //Key: name, - std::vector>> m_decompressors; - }; - - template - void DecompressorContainer::add(Args &&... args) - { - m_decompressors.emplace_back(new T(args...)); - } - - /*! - * - * @param name The name of the decompressor to check whether exists. - * @return Whether a decompressor with the given name exists or not. - */ - bool DecompressorContainer::contains(std::string_view name) const - { - auto iter = std::find_if(m_decompressors.begin(), m_decompressors.end(), [&](const auto &item) - { - return item->name() == name; - }); - - return iter != m_decompressors.end(); - } - - /*! - * Removed an element with the given name. - * @param name The name of the decompressor - */ - void DecompressorContainer::remove(std::string_view name) - { - auto iter = std::remove_if(m_decompressors.begin(), m_decompressors.end(), [&](const auto &item) - { - return item->name() == name; - }); - m_decompressors.erase(iter); - } - - size_t DecompressorContainer::size() const - { - return m_decompressors.size(); - } - - /*! - * - * @param name The name of the container - * @return An ICompressor pointer if it exists. nullptr otherwise. - */ - IDecompressor *DecompressorContainer::get(std::string_view name) - { - auto iter = std::find_if(m_decompressors.begin(), m_decompressors.end(), [&](const auto &item) - { - return item->name() == name; - }); - - return (iter != m_decompressors.end()) ? iter->get() : nullptr; - } - - /*! - * Check if container is empty - * @return Whether or not the container is empty - */ - bool DecompressorContainer::empty() const - { - return m_decompressors.empty(); - } - - /*! - * Clears all IDecompressor elements in the container - */ - void DecompressorContainer::clear() - { - m_decompressors.clear(); - } -} -#endif //TILESON_DECOMPRESSORCONTAINER_HPP - -/*** End of inlined file: DecompressorContainer.hpp ***/ - - -/*** Start of inlined file: MemoryStream.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_MEMORYSTREAM_HPP -#define TILESON_MEMORYSTREAM_HPP - - -/*** Start of inlined file: MemoryBuffer.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_MEMORYBUFFER_HPP -#define TILESON_MEMORYBUFFER_HPP - -#include - -namespace tson -{ - class MemoryBuffer : public std::basic_streambuf { - public: - MemoryBuffer(const uint8_t *p, size_t l) { - setg((char*)p, (char*)p, (char*)p + l); - } - }; -} - -#endif //TILESON_MEMORYBUFFER_HPP - -/*** End of inlined file: MemoryBuffer.hpp ***/ - -namespace tson -{ - class MemoryStream : public std::istream { - public: - MemoryStream(const uint8_t *p, size_t l) : - std::istream(&m_buffer), - m_buffer(p, l) { - rdbuf(&m_buffer); - } - - private: - MemoryBuffer m_buffer; - }; -} - -#endif //TILESON_MEMORYSTREAM_HPP - -/*** End of inlined file: MemoryStream.hpp ***/ - - -/*** Start of inlined file: Map.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_MAP_HPP -#define TILESON_MAP_HPP - - -/*** Start of inlined file: Color.hpp ***/ -// -// Created by robin on 09.08.2019. -// - -#ifndef TILESON_COLOR_HPP -#define TILESON_COLOR_HPP - -#include -#include -#include - -namespace tson -{ - - template - class Color - { - - public: - /*! - * Parses color from Tiled's own color format, which is #aarrggbb in hex format or optionally #rrggbb. - * @param color Color in "#rrggbbaa" hex format. - * @example "#ffaa07ff" and "#aa07ff". In cases where alpha is not a value, it is set to 255. - */ - inline explicit Color(const std::string &color) - { - parseHexString(color); - } - inline Color(T red, T green, T blue, T alpha); - inline Color() { r = g = b = 0; a = 255; } - - inline bool operator==(const Color &rhs) const; - inline bool operator==(const std::string &rhs) const; - inline bool operator!=(const Color &rhs) const; - - inline Color asFloat(); - inline Color asInt(); - - /*! Red */ - T r; - /*! Green */ - T g; - /*! Blue */ - T b; - /*! Alpha */ - T a; - - private: - void parseHexString(const std::string &color) - { - if constexpr (std::is_same::value) - { - if (color.size() == 9) - { - a = (float) std::stoi(color.substr(1, 2), nullptr, 16) / 255; - r = (float) std::stoi(color.substr(3, 2), nullptr, 16) / 255; - g = (float) std::stoi(color.substr(5, 2), nullptr, 16) / 255; - b = (float) std::stoi(color.substr(7, 2), nullptr, 16) / 255; - } - else if (color.size() == 7) - { - r = (float) std::stoi(color.substr(1, 2), nullptr, 16) / 255; - g = (float) std::stoi(color.substr(3, 2), nullptr, 16) / 255; - b = (float) std::stoi(color.substr(5, 2), nullptr, 16) / 255; - a = 1.f; - } - } - else - { - if (color.size() == 9) - { - a = std::stoi(color.substr(1, 2), nullptr, 16); - r = std::stoi(color.substr(3, 2), nullptr, 16); - g = std::stoi(color.substr(5, 2), nullptr, 16); - b = std::stoi(color.substr(7, 2), nullptr, 16); - } - else if (color.size() == 7) - { - r = std::stoi(color.substr(1, 2), nullptr, 16); - g = std::stoi(color.substr(3, 2), nullptr, 16); - b = std::stoi(color.substr(5, 2), nullptr, 16); - a = 255; - } - } - } - - }; - - typedef Color Colori; - typedef Color Colorf; - - /*! - * Gets the Color as a float. Only useful if the template related to the current color is NOT float - * @tparam T The template type - * @return If the T type is float, the value will be returned as a copy of itself. Else: All values will be divided by 255 - * before returning. - */ - template - tson::Colorf Color::asFloat() - { - if constexpr (std::is_same::value) - *this; - else - return tson::Colorf((float) r / 255, (float) g / 255, (float) b / 255, (float) a / 255); - } - - /*! - * Gets the Color as an 32-bit variable, where each channel is 8-bit. - * Only useful if the template related to the current color is NOT already 8-bit int - * @tparam T The template type - * @return If the T type is float, the value of each channel will be multiplied by 255. Else: The value will be returned as a copy of itself. - */ - template - tson::Colori Color::asInt() - { - if constexpr (std::is_same::value) - return tson::Colori((float) r * 255, (float) g * 255, (float) b * 255, (float) a * 255); - else - *this; - } - - /*! - * Create a new color in rgba (red, green, blue, alpha) format - * @tparam T the template type for each channel. Usually uint8_t (8-bit int) or float. - * @param red Red channel - * @param green Green channel - * @param blue Blue channel - * @param alpha Alpha channel - */ - template - Color::Color(T red, T green, T blue, T alpha) - { - r = red; - g = green; - b = blue; - a = alpha; - } - - template - bool Color::operator==(const std::string &rhs) const { - Color other {rhs}; - return *this == other; - } - - template - bool Color::operator==(const Color &rhs) const - { - return r == rhs.r && - g == rhs.g && - b == rhs.b && - a == rhs.a; - } - - template - bool Color::operator!=(const Color &rhs) const - { - return !(rhs == *this); - } - -} - -#endif //TILESON_COLOR_HPP - -/*** End of inlined file: Color.hpp ***/ - - -/*** Start of inlined file: Vector2.hpp ***/ -// -// Created by robin on 31.07.2019. -// - -#ifndef TILESON_VECTOR2_HPP -#define TILESON_VECTOR2_HPP - -namespace tson -{ - template - class Vector2 - { - - public: - inline Vector2(T xPos, T yPos); - inline Vector2() { x = y = 0; } - - inline bool operator==(const Vector2 &rhs) const; - inline bool operator!=(const Vector2 &rhs) const; - - T x; - T y; - }; - - /*! - * - * @tparam T template type - * @param xPos x-position - * @param yPos y-position - */ - template - Vector2::Vector2(T xPos, T yPos) - { - x = xPos; - y = yPos; - } - - template - bool Vector2::operator==(const Vector2 &rhs) const - { - return x == rhs.x && - y == rhs.y; - } - - template - bool Vector2::operator!=(const Vector2 &rhs) const - { - return !(rhs == *this); - } - - typedef Vector2 Vector2i; - typedef Vector2 Vector2f; -} - -#endif //TILESON_VECTOR2_HPP - -/*** End of inlined file: Vector2.hpp ***/ - -//#include "../external/json.hpp" - -/*** Start of inlined file: IJson.hpp ***/ -// -// Created by robin on 06.01.2021. -// - -#ifndef TILESON_IJSON_HPP -#define TILESON_IJSON_HPP - -namespace tson -{ - class IJson - { - public: - - virtual IJson& operator[](std::string_view key) = 0; - virtual IJson &at(std::string_view key) = 0; - virtual IJson &at(size_t pos) = 0; - /*! - * If current json object is an array, this will get all elements of it! - * @return An array - */ - [[nodiscard]] virtual std::vector> array() = 0; - [[nodiscard]] virtual std::vector> &array(std::string_view key) = 0; - /*! - * Get the size of an object. This will be equal to the number of - * variables an object contains. - * @return - */ - [[nodiscard]] virtual size_t size() const = 0; - [[nodiscard]] virtual bool parse(const fs::path &path) = 0; - [[nodiscard]] virtual bool parse(const void *data, size_t size) = 0; - - template - [[nodiscard]] T get(std::string_view key); - template - [[nodiscard]] T get(); - [[nodiscard]] virtual size_t count(std::string_view key) const = 0; - [[nodiscard]] virtual bool any(std::string_view key) const = 0; - [[nodiscard]] virtual bool isArray() const = 0; - [[nodiscard]] virtual bool isObject() const = 0; - [[nodiscard]] virtual bool isNull() const = 0; - - protected: - [[nodiscard]] virtual int32_t getInt32(std::string_view key) = 0; - [[nodiscard]] virtual uint32_t getUInt32(std::string_view key) = 0; - [[nodiscard]] virtual int64_t getInt64(std::string_view key) = 0; - [[nodiscard]] virtual uint64_t getUInt64(std::string_view key) = 0; - [[nodiscard]] virtual double getDouble(std::string_view key) = 0; - [[nodiscard]] virtual float getFloat(std::string_view key) = 0; - [[nodiscard]] virtual std::string getString(std::string_view key) = 0; - [[nodiscard]] virtual bool getBool(std::string_view key) = 0; - - [[nodiscard]] virtual int32_t getInt32() = 0; - [[nodiscard]] virtual uint32_t getUInt32() = 0; - [[nodiscard]] virtual int64_t getInt64() = 0; - [[nodiscard]] virtual uint64_t getUInt64() = 0; - [[nodiscard]] virtual double getDouble() = 0; - [[nodiscard]] virtual float getFloat() = 0; - [[nodiscard]] virtual std::string getString() = 0; - [[nodiscard]] virtual bool getBool() = 0; - }; - - template - T IJson::get(std::string_view key) - { - if constexpr (std::is_same::value) - return getDouble(key); - if constexpr (std::is_same::value) - return getFloat(key); - else if constexpr (std::is_same::value) - return getInt32(key); - else if constexpr (std::is_same::value) - return getUInt32(key); - else if constexpr (std::is_same::value) - return getInt64(key); - else if constexpr (std::is_same::value) - return getUInt64(key); - else if constexpr (std::is_same::value) - return getString(key); - else if constexpr (std::is_same::value) - return getBool(key); - else - return nullptr; - } - - template - T IJson::get() - { - if constexpr (std::is_same::value) - return getDouble(); - if constexpr (std::is_same::value) - return getFloat(); - else if constexpr (std::is_same::value) - return getInt32(); - else if constexpr (std::is_same::value) - return getUInt32(); - else if constexpr (std::is_same::value) - return getInt64(); - else if constexpr (std::is_same::value) - return getUInt64(); - else if constexpr (std::is_same::value) - return getString(); - else if constexpr (std::is_same::value) - return getBool(); - else - return nullptr; - } - -} - -#endif //TILESON_IJSON_HPP - -/*** End of inlined file: IJson.hpp ***/ - - - -/*** Start of inlined file: NlohmannJson.hpp ***/ -// -// Created by robin on 08.01.2021. -// - -#ifdef INCLUDE_NLOHMANN_JSON_HPP_ - -#ifndef TILESON_NLOHMANNJSON_HPP -#define TILESON_NLOHMANNJSON_HPP - -namespace tson -{ - class NlohmannJson : public tson::IJson - { - public: - inline NlohmannJson() = default; - - IJson &operator[](std::string_view key) override - { - if(m_arrayCache.count(key.data()) == 0) - m_arrayCache[key.data()] = std::make_unique(&m_json->operator[](key.data()));//.front()); - - return *m_arrayCache[key.data()].get(); - } - - inline explicit NlohmannJson(nlohmann::json *json) : m_json {json} - { - - } - - inline IJson& at(std::string_view key) override - { - if(m_arrayCache.count(key.data()) == 0) - m_arrayCache[key.data()] = std::make_unique(&m_json->operator[](key.data()));//.front()); - - return *m_arrayCache[key.data()].get(); - } - - inline IJson& at(size_t pos) override - { - if(m_arrayPosCache.count(pos) == 0) - m_arrayPosCache[pos] = std::make_unique(&m_json->at(pos)); - - return *m_arrayPosCache[pos]; - } - - std::vector> array() override - { - std::vector> vec; - for(auto &item : *m_json) - { - nlohmann::json *ptr = &item; - vec.emplace_back(std::make_unique(ptr)); - } - - return vec; - } - - inline std::vector> &array(std::string_view key) override - { - if(m_arrayListDataCache.count(key.data()) == 0) - { - if (m_json->count(key.data()) > 0 && m_json->operator[](key.data()).is_array()) - { - std::for_each(m_json->operator[](key.data()).begin(), m_json->operator[](key.data()).end(), [&](nlohmann::json &item) - { - nlohmann::json *ptr = &item; - m_arrayListDataCache[key.data()].emplace_back(std::make_unique(ptr)); - }); - } - } - - return m_arrayListDataCache[key.data()]; - } - - [[nodiscard]] inline size_t size() const override - { - return m_json->size(); - } - - inline bool parse(const fs::path &path) override - { - clearCache(); - m_data = nullptr; - m_json = nullptr; - if (fs::exists(path) && fs::is_regular_file(path)) - { - m_data = std::make_unique(); - std::ifstream i(path.u8string()); - try - { - i >> *m_data; - m_json = m_data.get(); - } - catch (const nlohmann::json::parse_error &error) - { - std::string message = "Parse error: "; - message += std::string(error.what()); - message += std::string("\n"); - std::cerr << message; - return false; - } - return true; - } - return false; - } - - inline bool parse(const void *data, size_t size) override - { - clearCache(); - m_json = nullptr; - m_data = std::make_unique(); - tson::MemoryStream mem{(uint8_t *) data, size}; - try - { - mem >> *m_data; - m_json = m_data.get(); - } - catch (const nlohmann::json::parse_error &error) - { - std::string message = "Parse error: "; - message += std::string(error.what()); - message += std::string("\n"); - std::cerr << message; - return false; - } - return true; - } - - [[nodiscard]] inline size_t count(std::string_view key) const override - { - return m_json->count(key); - } - - [[nodiscard]] inline bool any(std::string_view key) const override - { - return count(key) > 0; - } - - [[nodiscard]] inline bool isArray() const override - { - return m_json->is_array(); - } - - [[nodiscard]] inline bool isObject() const override - { - return m_json->is_object(); - } - - [[nodiscard]] inline bool isNull() const override - { - return m_json->is_null(); - } - - protected: - [[nodiscard]] inline int32_t getInt32(std::string_view key) override - { - return m_json->operator[](key.data()).get(); - } - - [[nodiscard]] inline uint32_t getUInt32(std::string_view key) override - { - return m_json->operator[](key.data()).get(); - } - - [[nodiscard]] inline int64_t getInt64(std::string_view key) override - { - return m_json->operator[](key.data()).get(); - } - - [[nodiscard]] inline uint64_t getUInt64(std::string_view key) override - { - return m_json->operator[](key.data()).get(); - } - - [[nodiscard]] inline double getDouble(std::string_view key) override - { - return m_json->operator[](key.data()).get(); - } - - [[nodiscard]] inline std::string getString(std::string_view key) override - { - return m_json->operator[](key.data()).get(); - } - - [[nodiscard]] inline bool getBool(std::string_view key) override - { - return m_json->operator[](key.data()).get(); - } - - [[nodiscard]] float getFloat(std::string_view key) override - { - return m_json->operator[](key.data()).get(); - } - - [[nodiscard]] inline int32_t getInt32() override - { - return m_json->get(); - } - - [[nodiscard]] inline uint32_t getUInt32() override - { - return m_json->get(); - } - - [[nodiscard]] inline int64_t getInt64() override - { - return m_json->get(); - } - - [[nodiscard]] inline uint64_t getUInt64() override - { - return m_json->get(); - } - - [[nodiscard]] inline double getDouble() override - { - return m_json->get(); - } - - [[nodiscard]] inline std::string getString() override - { - return m_json->get(); - } - - [[nodiscard]] inline bool getBool() override - { - return m_json->get(); - } - - [[nodiscard]] float getFloat() override - { - return m_json->get(); - } - - private: - inline void clearCache() - { - m_arrayCache.clear(); - m_arrayPosCache.clear(); - m_arrayListDataCache.clear(); - } - - nlohmann::json *m_json = nullptr; - std::unique_ptr m_data = nullptr; //Only used if this is the owner json! - - //Cache! - std::map> m_arrayCache; - std::map> m_arrayPosCache; - std::map>> m_arrayListDataCache; - - }; -} -#endif //TILESON_NLOHMANNJSON_HPP - -#endif //INCLUDE_NLOHMANN_JSON_HPP_ -/*** End of inlined file: NlohmannJson.hpp ***/ - - -/*** Start of inlined file: PicoJson.hpp ***/ -// -// Created by robin on 11.01.2021. -// - -#ifdef picojson_h -#ifndef TILESON_PICOJSON_HPP -#define TILESON_PICOJSON_HPP - -namespace tson -{ - class PicoJson : public tson::IJson - { - public: - inline PicoJson() = default; - - IJson &operator[](std::string_view key) override - { - if(m_arrayCache.count(key.data()) == 0) - { - if(m_json->is()) - { - picojson::object &o = m_json->get(); - m_arrayCache[key.data()] = std::make_unique(&o[key.data()]); - } - } - - return *m_arrayCache[key.data()].get(); - } - - inline explicit PicoJson(picojson::value *json) : m_json {json} - { - - } - - inline IJson& at(std::string_view key) override - { - if(m_arrayCache.count(key.data()) == 0) - { - if(m_json->is()) - { - picojson::object &o = m_json->get(); - m_arrayCache[key.data()] = std::make_unique(&o[key.data()]); - } - } - return *m_arrayCache[key.data()].get(); - } - - inline IJson& at(size_t pos) override - { - if(m_arrayPosCache.count(pos) == 0) - { - picojson::array &a = m_json->get(); - m_arrayPosCache[pos] = std::make_unique(&a.at(pos)); - } - - return *m_arrayPosCache[pos]; - } - - std::vector> array() override - { - std::vector> vec; - if(m_json->is()) - { - picojson::array &a = m_json->get(); - for (auto &item : a) - { - picojson::value *ptr = &item; - vec.emplace_back(std::make_unique(ptr)); - } - } - - return vec; - } - - inline std::vector> &array(std::string_view key) override - { - if(m_arrayListDataCache.count(key.data()) == 0) - { - if(count(key.data()) > 0) - { - if (isObject()) - { - picojson::object &obj = m_json->get(); - picojson::value &v = obj.at(key.data()); - bool isArray = v.is(); - if (isArray) - { - picojson::array &a = v.get(); - - std::for_each(a.begin(), a.end(), [&](picojson::value &item) - { - picojson::value *ptr = &item; - m_arrayListDataCache[key.data()].emplace_back(std::make_unique(ptr)); - }); - } - } - } - } - - return m_arrayListDataCache[key.data()]; - } - - [[nodiscard]] inline size_t size() const override - { - if (m_json->is()) - { - picojson::object obj = m_json->get(); - return obj.size(); - } - return 0; - } - - inline bool parse(const fs::path &path) override - { - clearCache(); - m_data = nullptr; - m_json = nullptr; - if (fs::exists(path) && fs::is_regular_file(path)) - { - m_data = std::make_unique(); - std::ifstream i(path.u8string()); - try - { - std::string error = picojson::parse(*m_data, i); - if(!error.empty()) - { - std::cerr << "PicoJson parse error: " << error << "\n"; - return false; - } - //i >> *m_data; - m_json = m_data.get(); - } - catch (const std::exception &error) - { - std::string message = "Parse error: "; - message += std::string(error.what()); - message += std::string("\n"); - std::cerr << message; - return false; - } - return true; - } - return false; - } - - inline bool parse(const void *data, size_t size) override - { - clearCache(); - m_json = nullptr; - m_data = std::make_unique(); - tson::MemoryStream mem{(uint8_t *) data, size}; - try - { - std::string error = picojson::parse(*m_data, mem); - if(!error.empty()) - { - std::cerr << "PicoJson parse error: " << error << "\n"; - return false; - } - //mem >> *m_data; - m_json = m_data.get(); - } - catch (const std::exception &error) - { - std::string message = "Parse error: "; - message += std::string(error.what()); - message += std::string("\n"); - std::cerr << message; - return false; - } - return true; - } - - [[nodiscard]] inline size_t count(std::string_view key) const override - { - if (isObject()) - { - picojson::object obj = m_json->get(); - return obj.count(key.data()); - } - - return m_json->contains(key.data()) ? 1 : 0; - } - - [[nodiscard]] inline bool any(std::string_view key) const override - { - return count(key) > 0; - } - - [[nodiscard]] inline bool isArray() const override - { - return m_json->is(); - } - - [[nodiscard]] inline bool isObject() const override - { - return m_json->is(); - } - - [[nodiscard]] inline bool isNull() const override - { - return m_json->is(); - } - - protected: - [[nodiscard]] inline int32_t getInt32(std::string_view key) override - { - picojson::object obj = m_json->get(); - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline uint32_t getUInt32(std::string_view key) override - { - picojson::object obj = m_json->get(); - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline int64_t getInt64(std::string_view key) override - { - picojson::object obj = m_json->get(); - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline uint64_t getUInt64(std::string_view key) override - { - picojson::object obj = m_json->get(); - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline double getDouble(std::string_view key) override - { - picojson::object obj = m_json->get(); - return obj[key.data()].get(); - } - - [[nodiscard]] inline std::string getString(std::string_view key) override - { - picojson::object obj = m_json->get(); - return obj[key.data()].get(); - } - - [[nodiscard]] inline bool getBool(std::string_view key) override - { - picojson::object obj = m_json->get(); - return obj[key.data()].get(); - } - - [[nodiscard]] float getFloat(std::string_view key) override - { - picojson::object obj = m_json->get(); - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline int32_t getInt32() override - { - return static_cast(getDouble()); - } - - [[nodiscard]] inline uint32_t getUInt32() override - { - return static_cast(getDouble()); - } - - [[nodiscard]] inline int64_t getInt64() override - { - return static_cast(getDouble()); - } - - [[nodiscard]] inline uint64_t getUInt64() override - { - return static_cast(getDouble()); - } - - [[nodiscard]] inline double getDouble() override - { - return m_json->get(); - } - - [[nodiscard]] inline std::string getString() override - { - return m_json->get(); - } - - [[nodiscard]] inline bool getBool() override - { - return m_json->get(); - } - - [[nodiscard]] float getFloat() override - { - return static_cast(getDouble()); - } - - private: - inline void clearCache() - { - m_arrayCache.clear(); - m_arrayPosCache.clear(); - m_arrayListDataCache.clear(); - } - - picojson::value *m_json = nullptr; - std::unique_ptr m_data = nullptr; //Only used if this is the owner json! - - //Cache! - std::map> m_arrayCache; - std::map> m_arrayPosCache; - std::map>> m_arrayListDataCache; - - }; -} -#endif //TILESON_PICOJSON_HPP -#endif - -/*** End of inlined file: PicoJson.hpp ***/ - -//#include "../json/Gason.hpp" //Unsupported - -/*** Start of inlined file: Json11.hpp ***/ -// -// Created by robin on 16.01.2021. -// - -#ifndef TILESON_JSON11_HPP -#define TILESON_JSON11_HPP - -namespace tson -{ - class Json11 : public tson::IJson - { - public: - inline Json11() = default; - - IJson &operator[](std::string_view key) override - { - if(m_arrayCache.count(key.data()) == 0) - { - if(m_json->is_object()) - { - m_arrayCache[key.data()] = std::make_unique(m_json->operator[](key.data())); - } - } - - return *m_arrayCache[key.data()].get(); - } - - inline explicit Json11(const json11::Json &json) : m_json {&json} - { - - } - - inline IJson& at(std::string_view key) override - { - if(m_arrayCache.count(key.data()) == 0) - { - if(m_json->is_object()) - { - m_arrayCache[key.data()] = std::make_unique(m_json->operator[](key.data())); - } - } - return *m_arrayCache[key.data()].get(); - } - - inline IJson& at(size_t pos) override - { - if(m_arrayPosCache.count(pos) == 0) - { - const std::vector &a = m_json->array_items(); - m_arrayPosCache[pos] = std::make_unique(a.at(pos)); - } - - return *m_arrayPosCache[pos]; - } - - std::vector> array() override - { - std::vector> vec; - if(m_json->is_array()) - { - for (const json11::Json &item : m_json->array_items()) - { - vec.emplace_back(std::make_unique(item)); - } - } - - return vec; - } - - inline std::vector> &array(std::string_view key) override - { - if(m_arrayListDataCache.count(key.data()) == 0) - { - if(count(key.data()) > 0) - { - if(isObject()) - { - const json11::Json &v = m_json->operator[](key.data()); - if(v.is_array()) - { - for (const json11::Json &item : v.array_items()) - { - m_arrayListDataCache[key.data()].emplace_back(std::make_unique(item)); - } - } - } - } - } - - return m_arrayListDataCache[key.data()]; - } - - [[nodiscard]] inline size_t size() const override - { - if(m_json->is_object()) - return m_json->object_items().size(); - else if(m_json->is_array()) - return m_json->array_items().size(); - - return 0; - } - - inline bool parse(const fs::path &path) override - { - clearCache(); - m_data = nullptr; - m_json = nullptr; - if (fs::exists(path) && fs::is_regular_file(path)) - { - std::ifstream file(path.u8string()); - std::string str; - - file.seekg(0, std::ios::end); - str.reserve(file.tellg()); - file.seekg(0, std::ios::beg); - - str.assign((std::istreambuf_iterator(file)), - std::istreambuf_iterator()); - - m_data = std::make_unique(); - - try - { - std::string strError; - *m_data = json11::Json::parse(str, strError); - if(!strError.empty()) - { - std::cerr << strError << "\n"; - return false; - } - m_json = m_data.get(); - } - catch (const std::exception &error) - { - std::string message = "Json11 parse error: "; - message += std::string(error.what()); - message += std::string("\n"); - std::cerr << message; - return false; - } - return true; - } - return false; - } - - inline bool parse(const void *data, size_t size) override - { - clearCache(); - m_json = nullptr; - std::string str; - - str.reserve(size); - - tson::MemoryStream mem{(uint8_t *) data, size}; - - str.assign((std::istreambuf_iterator(mem)), - std::istreambuf_iterator()); - - m_data = std::make_unique(); - - try - { - std::string strError; - - *m_data = json11::Json::parse(str, strError); - if(!strError.empty()) - { - std::cout << strError << "\n"; - return false; - } - m_json = m_data.get(); - } - catch (const std::exception &error) - { - std::string message = "Json11 parse error: "; - message += std::string(error.what()); - message += std::string("\n"); - std::cerr << message; - return false; - } - return true; - } - - [[nodiscard]] inline size_t count(std::string_view key) const override - { - if (isObject()) - { - //const json11::Json &j = m_json->operator[](key.data()); - //size_t s1 = j.object_items().size(); - return m_json->object_items().count(key.data()); - } - - return 0; - } - - [[nodiscard]] inline bool any(std::string_view key) const override - { - return count(key) > 0; - } - - [[nodiscard]] inline bool isArray() const override - { - return m_json->is_array(); - } - - [[nodiscard]] inline bool isObject() const override - { - return m_json->is_object(); - } - - [[nodiscard]] inline bool isNull() const override - { - return m_json->is_null(); - } - - protected: - [[nodiscard]] inline int32_t getInt32(std::string_view key) override - { - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline uint32_t getUInt32(std::string_view key) override - { - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline int64_t getInt64(std::string_view key) override - { - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline uint64_t getUInt64(std::string_view key) override - { - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline double getDouble(std::string_view key) override - { - return m_json->operator[](key.data()).number_value(); - } - - [[nodiscard]] inline std::string getString(std::string_view key) override - { - return m_json->operator[](key.data()).string_value(); // .get(); - } - - [[nodiscard]] inline bool getBool(std::string_view key) override - { - return m_json->operator[](key.data()).bool_value(); - } - - [[nodiscard]] float getFloat(std::string_view key) override - { - return static_cast(getDouble(key)); - } - - [[nodiscard]] inline int32_t getInt32() override - { - return static_cast(getDouble()); - } - - [[nodiscard]] inline uint32_t getUInt32() override - { - return static_cast(getDouble()); - } - - [[nodiscard]] inline int64_t getInt64() override - { - return static_cast(getDouble()); - } - - [[nodiscard]] inline uint64_t getUInt64() override - { - return static_cast(getDouble()); - } - - [[nodiscard]] inline double getDouble() override - { - return m_json->number_value(); - } - - [[nodiscard]] inline std::string getString() override - { - return m_json->string_value(); - } - - [[nodiscard]] inline bool getBool() override - { - return m_json->bool_value(); - } - - [[nodiscard]] float getFloat() override - { - return static_cast(getDouble()); - } - - private: - - inline void clearCache() - { - m_arrayCache.clear(); - m_arrayPosCache.clear(); - m_arrayListDataCache.clear(); - } - - //Owner values - char *m_endptr; - std::unique_ptr m_data = nullptr; //Only used if this is the owner json! - - const json11::Json *m_json = nullptr; - - //Cache! - std::map> m_arrayCache; - std::map> m_arrayPosCache; - std::map>> m_arrayListDataCache; - - }; -} - -#endif //TILESON_JSON11_HPP - -/*** End of inlined file: Json11.hpp ***/ - - - -/*** Start of inlined file: Layer.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_LAYER_HPP -#define TILESON_LAYER_HPP - -#include -//#include "../external/json.hpp" - - -/*** Start of inlined file: Chunk.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_CHUNK_HPP -#define TILESON_CHUNK_HPP - -//#include "../external/json.hpp" - -namespace tson -{ - class Chunk - { - public: - inline Chunk() = default; - inline explicit Chunk(IJson &json); - inline bool parse(IJson &json); - - [[nodiscard]] inline const std::vector &getData() const; - [[nodiscard]] inline const std::string &getBase64Data() const; - [[nodiscard]] inline const Vector2i &getSize() const; - [[nodiscard]] inline const Vector2i &getPosition() const; - - private: - std::vector m_data; /*! 'data' (when uint array): Array of unsigned int (GIDs) or base64-encoded data. tilelayer only. */ - std::string m_base64Data; /*! 'data' (when string): Array of unsigned int (GIDs) or base64-encoded data. */ - tson::Vector2i m_size; /*! x='width' (in tiles) and y='height' (in tiles): */ - tson::Vector2i m_position; /*! 'x' and 'y' position in tiles */ - }; -} - -#endif //TILESON_CHUNK_HPP - -/*! - * Parses 'chunk' data from Tiled json and stores the values in this class - * @param json json-data - */ -tson::Chunk::Chunk(IJson &json) -{ - parse(json); -} - -/*! - * Parses 'chunk' data from Tiled json and stores the values in this class - * @param json json-data - * @return true if all mandatory fields was found. false otherwise. - */ -bool tson::Chunk::parse(IJson &json) -{ - bool allFound = true; - - if(json.count("width") > 0 && json.count("height") > 0) - m_size = {json["width"].get(), json["height"].get()}; else allFound = false; - if(json.count("x") > 0 && json.count("y") > 0) - m_position = {json["x"].get(), json["y"].get()}; else allFound = false; - - //Handle DATA (Optional) - if(json.count("data") > 0) - { - if(json["data"].isArray()) - { - auto &data = json.array("data"); - std::for_each(data.begin(), data.end(), [&](std::unique_ptr &item) { m_data.push_back(item->get()); }); - } - else - m_base64Data = json["data"].get(); - } - - return allFound; -} - -/*! - * 'data' (when uint array): Array of unsigned int (GIDs) or base64-encoded data. tilelayer only. - * @return list of tile ids - */ -const std::vector &tson::Chunk::getData() const -{ - return m_data; -} - -/*! - * 'data' (when string): Array of unsigned int (GIDs) or base64-encoded data. - * @return base64 string - */ -const std::string &tson::Chunk::getBase64Data() const -{ - return m_base64Data; -} - -/*! - * x='width' (in tiles) and y='height' (in tiles). - * @return Size (x and y), containing the values from the fields 'width' and 'height' in Tiled - */ -const tson::Vector2i &tson::Chunk::getSize() const -{ - return m_size; -} - -/*! - * 'x' and 'y' position in tiles - * @return Position in int - */ -const tson::Vector2i &tson::Chunk::getPosition() const -{ - return m_position; -} -/*** End of inlined file: Chunk.hpp ***/ - - -/*** Start of inlined file: Object.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_OBJECT_HPP -#define TILESON_OBJECT_HPP - -//#include "../external/json.hpp" - - -/*** Start of inlined file: PropertyCollection.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_PROPERTYCOLLECTION_HPP -#define TILESON_PROPERTYCOLLECTION_HPP - - -/*** Start of inlined file: Property.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_PROPERTY_HPP -#define TILESON_PROPERTY_HPP - -//#include "../../TilesonConfig.h" - -//#if USE_CPP17_FILESYSTEM - -#include -#include - -/*** Start of inlined file: Enums.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_ENUMS_HPP -#define TILESON_ENUMS_HPP -#include - -/*** Start of inlined file: EnumBitflags.hpp ***/ -// -// Created by robin on 08.11.2020. -// - -#ifndef TILESON_ENUMBITFLAGS_HPP -#define TILESON_ENUMBITFLAGS_HPP - -#include -#include - -namespace tson -{ - #define ENABLE_BITMASK_OPERATORS(x) \ - template<> \ - struct EnableBitMaskOperators \ - { \ - static const bool enable = true; \ - }; - - template - struct EnableBitMaskOperators - { - static const bool enable = false; - }; - - template - typename std::enable_if::enable, Enum>::type - operator |(Enum lhs, Enum rhs) - { - static_assert(std::is_enum::value, - "template parameter is not an enum type"); - - using underlying = typename std::underlying_type::type; - - return static_cast ( - static_cast(lhs) | - static_cast(rhs) - ); - } - - //Permissions operator &(Permissions lhs, Permissions rhs) - template - typename std::enable_if::enable, Enum>::type - operator &(Enum lhs, Enum rhs) - { - static_assert(std::is_enum::value, - "template parameter is not an enum type"); - - using underlying = typename std::underlying_type::type; - - return static_cast ( - static_cast(lhs) & - static_cast(rhs) - ); - } - - //Permissions operator ^(Permissions lhs, Permissions rhs) - template - typename std::enable_if::enable, Enum>::type - operator ^(Enum lhs, Enum rhs) - { - static_assert(std::is_enum::value, - "template parameter is not an enum type"); - - using underlying = typename std::underlying_type::type; - - return static_cast ( - static_cast(lhs) ^ - static_cast(rhs) - ); - } - - //Permissions operator ~(Permissions rhs) - template - typename std::enable_if::enable, Enum>::type - operator ~(Enum rhs) - { - static_assert(std::is_enum::value, - "template parameter is not an enum type"); - - using underlying = typename std::underlying_type::type; - - return static_cast ( - ~static_cast(rhs) - ); - } - - //Permissions& operator |=(Permissions &lhs, Permissions rhs) - template - typename std::enable_if::enable, Enum>::type - &operator |=(Enum &lhs, Enum rhs) - { - static_assert(std::is_enum::value, - "template parameter is not an enum type"); - - using underlying = typename std::underlying_type::type; - - lhs = static_cast ( - static_cast(lhs) | - static_cast(rhs) - ); - - return lhs; - } - - //Permissions& operator &=(Permissions &lhs, Permissions rhs) - template - typename std::enable_if::enable, Enum>::type - &operator &=(Enum &lhs, Enum rhs) - { - static_assert(std::is_enum::value, - "template parameter is not an enum type"); - - using underlying = typename std::underlying_type::type; - - lhs = static_cast ( - static_cast(lhs) & - static_cast(rhs) - ); - - return lhs; - } - - //Permissions& operator ^=(Permissions &lhs, Permissions rhs) - template - typename std::enable_if::enable, Enum>::type - &operator ^=(Enum &lhs, Enum rhs) - { - static_assert(std::is_enum::value, - "template parameter is not an enum type"); - - using underlying = typename std::underlying_type::type; - - lhs = static_cast ( - static_cast(lhs) ^ - static_cast(rhs) - ); - - return lhs; - } -} - -#endif //TILESON_ENUMBITFLAGS_HPP - -/*** End of inlined file: EnumBitflags.hpp ***/ - - -namespace tson -{ - /*! - * Type used in Property.hpp - */ - enum class Type : uint8_t - { - Undefined = 0, - Color = 1, /*! color */ - File = 2, /*! file */ - Int = 3, /*! int */ - Boolean = 4, /*! bool */ - Float = 5, /*! float */ - String = 6 /*! string */ - }; - - /*! - * Layer.hpp - LayerType - * //'type': tilelayer, objectgroup, imagelayer or group - */ - enum class LayerType : uint8_t - { - Undefined = 0, - TileLayer = 1, - ObjectGroup = 2, - ImageLayer = 3, - Group = 4 - }; - - /*! - * Map.hpp - ParseStatus - */ - enum class ParseStatus : uint8_t - { - OK = 0, //OK unless otherwise stated - FileNotFound = 1, - ParseError = 2, - MissingData = 3, - DecompressionError = 4 - }; - - /*! - * Object.hpp - ObjectType - */ - enum class ObjectType : uint8_t - { - Undefined = 0, - Object = 1, - Ellipse = 2, - Rectangle = 3, - Point = 4, - Polygon = 5, - Polyline = 6, - Text = 7, - Template = 8 - }; - - static constexpr uint32_t FLIPPED_HORIZONTALLY_FLAG = 0x80000000; - static constexpr uint32_t FLIPPED_VERTICALLY_FLAG = 0x40000000; - static constexpr uint32_t FLIPPED_DIAGONALLY_FLAG = 0x20000000; - /*! - * Object.hpp - ObjectFlipFlags - */ - enum class TileFlipFlags : uint32_t - { - None = 0, - Diagonally = FLIPPED_DIAGONALLY_FLAG, - Vertically = FLIPPED_VERTICALLY_FLAG, - Horizontally = FLIPPED_HORIZONTALLY_FLAG - }; - - /*! - * Tileset.hpp - ObjectAlignment - */ - enum class ObjectAlignment : uint8_t - { - Unspecified = 0, //unspecified - TopLeft = 1, //topleft - Top = 2, //top - TopRight = 3, //topright - Left = 4, //left - Center = 5, //center - Right = 6, //right - BottomLeft = 7, //bottomleft - Bottom = 8, //bottom - BottomRight = 9 //bottomright - }; - - ENABLE_BITMASK_OPERATORS(TileFlipFlags) -} - -#endif //TILESON_ENUMS_HPP - -/*** End of inlined file: Enums.hpp ***/ - - -//#include "../external/json.hpp" - -namespace tson -{ - class Property - { - public: - - //enum class Type : uint8_t - //{ - // Undefined = 0, - // Color = 1, /*! color */ - // File = 2, /*! file */ - // Int = 3, /*! int */ - // Boolean = 4, /*! bool */ - // Float = 5, /*! float */ - // String = 6 /*! string */ - //}; - - inline Property(); - inline Property(IJson &json); - inline Property(std::string name, std::any value, Type type); - - inline void setValue(const std::any &value); - inline void setStrValue(const std::string &value); - inline void setName(const std::string &name); - - [[nodiscard]] inline const std::type_info& getValueType() const; - inline std::string getValueTypeInfo(); - [[nodiscard]]inline const std::any &getValue() const; - template - inline T getValue() const; - [[nodiscard]] inline const std::string &getName() const; - [[nodiscard]] inline Type getType() const; - - protected: - inline void setTypeByString(const std::string &str); - inline void setValueByType(IJson &json); - - Type m_type = Type::Undefined; - std::string m_name; - std::any m_value; //Using std::any to assign any type - }; - - template - T Property::getValue() const - { - bool isCorrectType = (m_value.type() == typeid(T)); - - if(isCorrectType) - { - T value = std::any_cast(m_value); - return value; - } - else - { - static T defaultValue; - return defaultValue; - } - } -} - -tson::Property::Property() : m_name {"unnamed"} -{ - -} - -tson::Property::Property(IJson &json) -{ - setTypeByString(json["type"].get()); - setValueByType(json["value"]); - m_name = json["name"].get(); -} - -tson::Property::Property(std::string name, std::any value, Type type) : m_name { move(name) }, m_value { move(value) }, m_type {type} -{ - -} - -void tson::Property::setValue(const std::any &value) -{ - m_value = value; -} - -/*! - * Sets the value specifically as string. - * When not specified as std::string, the default is that the value will be set as char * when adding a value like "test" - * This function is to make sure the value is added as string. - * @param value - */ -void tson::Property::setStrValue(const std::string &value) -{ - m_value = value; -} - -const std::any &tson::Property::getValue() const -{ - return m_value; -} - -void tson::Property::setName(const std::string &name) -{ - m_name = name; -} - -const std::string &tson::Property::getName() const -{ - return m_name; -} - -/*! - * Gets the value type as std::value_info. - * This can easily be compared to types like this: - * Check if int: getValueType() == typeid(int) - * @return - */ - -const std::type_info &tson::Property::getValueType() const -{ - return m_value.type(); -} - -/*! - * Gets the value type as std::string - * Examples of known types: - * "i" = int - * "f" = float - * "b" = bool - * @return - */ -std::string tson::Property::getValueTypeInfo() -{ - return m_value.type().name(); -} - -tson::Type tson::Property::getType() const -{ - return m_type; -} - -void tson::Property::setTypeByString(const std::string &str) -{ - if(str == "color") - m_type = tson::Type::Color; - else if(str == "file") - m_type = tson::Type::File; - else if(str == "int") - m_type = tson::Type::Int; - else if(str == "bool") - m_type = tson::Type::Boolean; - else if(str == "float") - m_type = tson::Type::Float; - else if(str == "string") - m_type = tson::Type::String; - else - m_type = tson::Type::Undefined; -} - -void tson::Property::setValueByType(IJson &json) -{ - switch(m_type) - { - case Type::Color: - m_value = Colori(json.get()); - break; - - case Type::File: - m_value = fs::path(json.get()); - break; - - case Type::Int: - m_value = json.get(); - break; - - case Type::Boolean: - m_value = json.get(); - break; - - case Type::Float: - m_value = json.get(); - break; - - case Type::String: - setStrValue(json.get()); - break; - - default: - setStrValue(json.get()); - break; - - } -} - -#endif //TILESON_PROPERTY_HPP - -/*** End of inlined file: Property.hpp ***/ - -//#include "../external/json.hpp" -#include - -namespace tson -{ - class PropertyCollection - { - public: - inline PropertyCollection() = default; - - inline explicit PropertyCollection(std::string id); - - inline tson::Property * add(const tson::Property &property); - inline tson::Property * add(IJson &json); - inline tson::Property * add(const std::string &name, const std::any &value, tson::Type type); - - inline void remove(const std::string &name); - - inline void setValue(const std::string &name, const std::any &value); - inline void setId(const std::string &id); - - inline bool hasProperty(const std::string &name); - inline tson::Property * getProperty(const std::string &name); - inline std::map &getProperties(); - inline std::vector get(); - template - inline T getValue(const std::string &name); - [[nodiscard]] inline const std::string &getId() const; - [[nodiscard]] inline size_t getSize() const; - - protected: - std::string m_id; - std::map m_properties; - }; -} - -template -T tson::PropertyCollection::getValue(const std::string &name) -{ - static T defaultT; - return (m_properties.count(name) > 0) ? m_properties[name].getValue() : defaultT; -} - -tson::PropertyCollection::PropertyCollection(std::string id) : m_id {std::move(id)} -{ - -} - -tson::Property *tson::PropertyCollection::add(const tson::Property &property) -{ - m_properties[property.getName()] = property; - return &m_properties[property.getName()]; -} - -tson::Property *tson::PropertyCollection::add(IJson &json) -{ - tson::Property property = tson::Property(json); - std::string name = property.getName(); - m_properties[name] = std::move(property); - return &m_properties[name]; -} - -tson::Property *tson::PropertyCollection::add(const std::string &name, const std::any &value, tson::Type type) -{ - m_properties[name] = {name, value, type}; - return &m_properties[name]; -} - -void tson::PropertyCollection::remove(const std::string &name) -{ - m_properties.erase(name); -} - -/*! - * Sets a value IF the property already exists. Does nothing otherwise. - * See add() for adding new properties - * @param name - * @param value - */ -void tson::PropertyCollection::setValue(const std::string &name, const std::any &value) -{ - if(m_properties.count(name) > 0) - m_properties[name].setValue(value); -} - -void tson::PropertyCollection::setId(const std::string &id) -{ - m_id = id; -} - -bool tson::PropertyCollection::hasProperty(const std::string &name) -{ - return m_properties.count(name) > 0; -} - -tson::Property *tson::PropertyCollection::getProperty(const std::string &name) -{ - return (m_properties.count(name) > 0) ? &m_properties[name] : nullptr; -} - -std::map &tson::PropertyCollection::getProperties() -{ - return m_properties; -} - -/*! - * Gets vector of pointers to all the existing properties - * @return - */ -std::vector tson::PropertyCollection::get() -{ - std::vector props; - for(auto &i : m_properties) - props.emplace_back(&i.second); - - return props; -} - -const std::string &tson::PropertyCollection::getId() const -{ - return m_id; -} - -size_t tson::PropertyCollection::getSize() const -{ - return m_properties.size(); -} - -#endif //TILESON_PROPERTYCOLLECTION_HPP - -/*** End of inlined file: PropertyCollection.hpp ***/ - - -/*** Start of inlined file: Text.hpp ***/ -// -// Created by robin on 05.08.2019. -// - -#ifndef TILESON_TEXT_HPP -#define TILESON_TEXT_HPP - -#include - -namespace tson -{ - class Text - { - public: - inline Text() = default; - /*! - * - * @param _text Text - * @param _wrap If the text is marked as wrapped - */ - inline Text(std::string _text, bool _wrap, tson::Colori _color) : text {std::move(_text)}, wrap {_wrap}, color {_color} {}; - //Just make it simple - std::string text; - tson::Colori color; - bool wrap{}; - }; -} - -#endif //TILESON_TEXT_HPP - -/*** End of inlined file: Text.hpp ***/ - -namespace tson -{ - class Object - { - public: - //enum class Type : uint8_t - //{ - // Undefined = 0, - // Object = 1, - // Ellipse = 2, - // Rectangle = 3, - // Point = 4, - // Polygon = 5, - // Polyline = 6, - // Text = 7, - // Template = 8 - //}; - - inline Object() = default; - inline explicit Object(IJson &json); - inline bool parse(IJson &json); - - [[nodiscard]] inline ObjectType getObjectType() const; - [[nodiscard]] inline bool isEllipse() const; - [[nodiscard]] inline uint32_t getGid() const; - [[nodiscard]] inline const Vector2i &getSize() const; - [[nodiscard]] inline int getId() const; - [[nodiscard]] inline const std::string &getName() const; - [[nodiscard]] inline bool isPoint() const; - [[nodiscard]] inline float getRotation() const; - [[nodiscard]] inline const std::string &getTemplate() const; - [[nodiscard]] inline const std::string &getType() const; - [[nodiscard]] inline bool isVisible() const; - [[nodiscard]] inline const Vector2i &getPosition() const; - - [[nodiscard]] inline const std::vector &getPolygons() const; - [[nodiscard]] inline const std::vector &getPolylines() const; - [[nodiscard]] inline PropertyCollection &getProperties(); - [[nodiscard]] inline const Text &getText() const; - - template - inline T get(const std::string &name); - inline tson::Property * getProp(const std::string &name); - - //v1.2.0-stuff - [[nodiscard]] inline TileFlipFlags getFlipFlags() const; - inline bool hasFlipFlags(TileFlipFlags flags); - - private: - inline void setObjectTypeByJson(IJson &json); - - ObjectType m_objectType = ObjectType::Undefined; /*! Says with object type this is */ - bool m_ellipse {}; /*! 'ellipse': Used to mark an object as an ellipse */ - uint32_t m_gid {}; /*! 'gid': GID, only if object comes from a Tilemap */ - tson::Vector2i m_size; /*! x = 'width' (Width in pixels), y = 'height' (Height in pixels). Ignored if using a gid.)*/ - int m_id{}; /*! 'id': Incremental id - unique across all objects */ - std::string m_name; /*! 'name': String assigned to name field in editor*/ - bool m_point {}; /*! 'point': Used to mark an object as a point */ - std::vector m_polygon; /*! 'polygon': A list of x,y coordinates in pixels */ - std::vector m_polyline; /*! 'polyline': A list of x,y coordinates in pixels */ - tson::PropertyCollection m_properties; /*! 'properties': A list of properties (name, value, type). */ - float m_rotation {}; /*! 'rotation': Angle in degrees clockwise */ - std::string m_template; /*! 'template': Reference to a template file, in case object is a template instance */ - tson::Text m_text; /*! first: 'text' second: 'wrap' */ - std::string m_type; /*! 'type': String assigned to type field in editor */ - bool m_visible {}; /*! 'visible': Whether object is shown in editor. */ - tson::Vector2i m_position; /*! 'x' and 'y': coordinate in pixels */ - - //v1.2.0-stuff - tson::TileFlipFlags m_flipFlags = TileFlipFlags::None; /*! Resolved using bit 32, 31 and 30 from gid */ - }; - - /*! - * A shortcut for getting a property. Alternative to getProperties().getValue("") - * @tparam T The template value - * @param name Name of the property - * @return The actual value, if it exists. Otherwise: The default value of the type. - */ - template - T tson::Object::get(const std::string &name) - { - return m_properties.getValue(name); - } -} - -/*! - * Parses a json Tiled object - * @param json - */ -tson::Object::Object(IJson &json) -{ - parse(json); -} - -/*! - * Parses a json Tiled object and autoamtically determines the object type based on the data presented. - * Call getObjectType() to see what object type it is. - * @param json - * @return true if all mandatory fields was found. false otherwise. - */ -bool tson::Object::parse(IJson &json) -{ - bool allFound = true; - - if(json.count("ellipse") > 0) m_ellipse = json["ellipse"].get(); //Optional - if(json.count("gid") > 0) - { - uint32_t gid = json["gid"].get(); //Optional - if (gid & FLIPPED_HORIZONTALLY_FLAG) m_flipFlags |= TileFlipFlags::Horizontally; - if (gid & FLIPPED_VERTICALLY_FLAG) m_flipFlags |= TileFlipFlags::Vertically; - if (gid & FLIPPED_DIAGONALLY_FLAG) m_flipFlags |= TileFlipFlags::Diagonally; - - // Clear flags - gid &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG); - - m_gid = gid; - } - if(json.count("id") > 0) m_id = json["id"].get(); else allFound = false; - if(json.count("name") > 0) m_name = json["name"].get(); else allFound = false; - if(json.count("point") > 0) m_point = json["point"].get(); //Optional - if(json.count("rotation") > 0) m_rotation = json["rotation"].get(); else allFound = false; - if(json.count("template") > 0) m_template = json["template"].get(); //Optional - if(json.count("type") > 0) m_type = json["type"].get(); else allFound = false; - if(json.count("visible") > 0) m_visible = json["visible"].get(); else allFound = false; - - if(json.count("width") > 0 && json.count("height") > 0) - m_size = {json["width"].get(), json["height"].get()}; else allFound = false; - if(json.count("x") > 0 && json.count("y") > 0) - m_position = {json["x"].get(), json["y"].get()}; else allFound = false; - - if(json.count("text") > 0) - { - bool hasColor = json["text"].count("color") > 0; - tson::Color c = (hasColor) ? tson::Colori(json["text"]["color"].get()) : tson::Colori(); - m_text = {json["text"]["text"].get(), json["text"]["wrap"].get(), c}; //Optional - } - - setObjectTypeByJson(json); - - if(m_objectType == ObjectType::Template) - allFound = true; //Just accept anything with this type - - //More advanced data - if(json.count("polygon") > 0 && json["polygon"].isArray()) - { - auto &polygon = json.array("polygon"); - std::for_each(polygon.begin(), polygon.end(),[&](std::unique_ptr &item) - { - IJson &j = *item; - m_polygon.emplace_back(j["x"].get(), j["y"].get()); - }); - - } - - if(json.count("polyline") > 0 && json["polyline"].isArray()) - { - auto &polyline = json.array("polyline"); - std::for_each(polyline.begin(), polyline.end(),[&](std::unique_ptr &item) - { - IJson &j = *item; - m_polyline.emplace_back(j["x"].get(), j["y"].get()); - }); - } - - if(json.count("properties") > 0 && json["properties"].isArray()) - { - auto &properties = json.array("properties"); - std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr &item) - { - m_properties.add(*item); - }); - } - - return allFound; -} - -/*! - * Sets an object type based on json data. - * @param json - */ -void tson::Object::setObjectTypeByJson(IJson &json) -{ - m_objectType = ObjectType::Undefined; - if(m_ellipse) - m_objectType = ObjectType::Ellipse; - else if(m_point) - m_objectType = ObjectType::Point; - else if(json.count("polygon") > 0) - m_objectType = ObjectType::Polygon; - else if(json.count("polyline") > 0) - m_objectType = ObjectType::Polyline; - else if(json.count("text") > 0) - m_objectType = ObjectType::Text; - else if(json.count("gid") > 0) - m_objectType = ObjectType::Object; - else if(json.count("template") > 0) - m_objectType = ObjectType::Template; - else - m_objectType = ObjectType::Rectangle; -} - -/*! - * Gets what type of object this is. - * @return - */ - -tson::ObjectType tson::Object::getObjectType() const -{ - return m_objectType; -} - -/*! - * 'ellipse': Used to mark an object as an ellipse - * @return - */ -bool tson::Object::isEllipse() const -{ - return m_ellipse; -} - -/*! - * 'gid': GID, only if object comes from a Tilemap - * @return - */ -uint32_t tson::Object::getGid() const -{ - return m_gid; -} - -/*! - * x = 'width' (Width in pixels), y = 'height' (Height in pixels). Ignored if using a gid.) - * @return - */ -const tson::Vector2i &tson::Object::getSize() const -{ - return m_size; -} - -/*! - * 'id': Incremental id - unique across all objects - * @return - */ -int tson::Object::getId() const -{ - return m_id; -} - -/*! - * 'name': String assigned to name field in editor - * @return - */ -const std::string &tson::Object::getName() const -{ - return m_name; -} - -/*! - * 'point': Used to mark an object as a point - * @return true if the object is of type point - */ -bool tson::Object::isPoint() const -{ - return m_point; -} - -/*! - * 'rotation': Angle in degrees clockwise - * @return - */ -float tson::Object::getRotation() const -{ - return m_rotation; -} - -/*! - * 'template': Reference to a template file, in case object is a template instance - * @return - */ -const std::string &tson::Object::getTemplate() const -{ - return m_template; -} - -/*! - * 'type': String assigned to type field in editor - * @return - */ -const std::string &tson::Object::getType() const -{ - return m_type; -} - -/*! - * 'visible': Whether object is shown in editor. - * @return - */ -bool tson::Object::isVisible() const -{ - return m_visible; -} - -/*! - * 'x' and 'y': coordinate in pixels - * @return - */ -const tson::Vector2i &tson::Object::getPosition() const -{ - return m_position; -} - -/*! - * 'polygon': A list of x,y coordinates in pixels. - * If this is a Polygon type, this function will return the points used to create it - * @return - */ -const std::vector &tson::Object::getPolygons() const -{ - return m_polygon; -} - -/*! - * 'polyline': A list of x,y coordinates in pixels - * If this is a Polyline type, this function will return the points used to create it - * @return - */ -const std::vector &tson::Object::getPolylines() const -{ - return m_polyline; -} - -/*! - * 'properties': A list of properties (name, value, type). - * @return - */ -tson::PropertyCollection &tson::Object::getProperties() -{ - return m_properties; -} - -/*! - * 'type': String assigned to type field in editor - * @return - */ -const tson::Text &tson::Object::getText() const -{ - return m_text; -} - -/*! - * Shortcut for getting a property object. Alternative to getProperties().getProperty(""); - * @param name Name of the property - * @return - */ -tson::Property *tson::Object::getProp(const std::string &name) -{ - if(m_properties.hasProperty(name)) - return m_properties.getProperty(name); - return nullptr; -} - -/*! - * Get all flip flags - * @return - */ -tson::TileFlipFlags tson::Object::getFlipFlags() const -{ - return m_flipFlags; -} - -/*! - * - * @param flags Which flags to check for. Several flags can be checked at once using the bitwise or operator. - * Example: - * hasFlipFlags(TileFlipFlags::Vertically | TileFlipFlags::Horizontally) - * - * @return true if the flag(s) specified are set - */ -bool tson::Object::hasFlipFlags(TileFlipFlags flags) -{ - return ((m_flipFlags & flags) == flags) ? true : false; -} - -#endif //TILESON_OBJECT_HPP - -/*** End of inlined file: Object.hpp ***/ - - -/*** Start of inlined file: TileObject.hpp ***/ -// -// Created by robin on 26.07.2020. -// - -#ifndef TILESON_TILEOBJECT_HPP -#define TILESON_TILEOBJECT_HPP - - -/*** Start of inlined file: Rect.hpp ***/ -// -// Created by robin on 24.07.2020. -// - -#ifndef TILESON_RECT_HPP -#define TILESON_RECT_HPP - -namespace tson -{ - class Rect - { - public: - - inline Rect(); - inline Rect(int x_, int y_, int width_, int height_); - - inline bool operator==(const Rect &rhs) const; - inline bool operator!=(const Rect &rhs) const; - - int x; - int y; - int width; - int height; - }; - - Rect::Rect() - { - - } - - Rect::Rect(int x_, int y_, int width_, int height_) - { - x = x_; - y = y_; - width = width_; - height = height_; - } - - bool Rect::operator==(const Rect &rhs) const - { - return x == rhs.x && - y == rhs.y && - width == rhs.width && - height == rhs.height; - } - - bool Rect::operator!=(const Rect &rhs) const - { - return !(rhs == *this); - } -} - -#endif //TILESON_RECT_HPP - -/*** End of inlined file: Rect.hpp ***/ - -namespace tson -{ - class Tile; - class TileObject - { - public: - inline TileObject() = default; - inline TileObject(const std::tuple &posInTileUnits, tson::Tile *tile); - - inline void initialize(const std::tuple &posInTileUnits, tson::Tile *tile); //Defined in tileson_forward.hpp - - inline Tile *getTile() const; - inline const Vector2i &getPositionInTileUnits() const; - inline const Vector2f &getPosition() const; - inline const tson::Rect &getDrawingRect() const; //Defined in tileson_forward.hpp - - private: - tson::Tile *m_tile; - tson::Vector2i m_posInTileUnits; - tson::Vector2f m_position; - - }; - - TileObject::TileObject(const std::tuple &posInTileUnits, tson::Tile *tile) - { - initialize(posInTileUnits, tile); - } - - /*! - * Get a pointer to the related tile - * @return - */ - Tile *TileObject::getTile() const - { - return m_tile; - } - - /*! - * Gets the position of the tile in tile units - * @return - */ - const Vector2i &TileObject::getPositionInTileUnits() const - { - return m_posInTileUnits; - } - - /*! - * Gets the position of the tile in pixels. - * @return - */ - const Vector2f &TileObject::getPosition() const - { - return m_position; - } -} - -#endif //TILESON_TILEOBJECT_HPP - -/*** End of inlined file: TileObject.hpp ***/ - - -/*** Start of inlined file: FlaggedTile.hpp ***/ -// -// Created by robin on 13.11.2020. -// - -#ifndef TILESON_FLAGGEDTILE_HPP -#define TILESON_FLAGGEDTILE_HPP - -namespace tson -{ - class FlaggedTile - { - - public: - FlaggedTile(size_t x_, size_t y_, uint32_t id_, uint32_t tileId_) : x {x_}, y {y_}, id {id_}, tileId {tileId_} - { - - } - size_t x; - size_t y; - /*! Full ID, including flag */ - uint32_t id; - /*! ID of the flagged tile */ - uint32_t tileId; - }; -} -#endif //TILESON_FLAGGEDTILE_HPP - -/*** End of inlined file: FlaggedTile.hpp ***/ - -namespace tson -{ - class Tile; - class Map; - - class Layer - { - public: - inline Layer() = default; - inline Layer(IJson &json, tson::Map *map); - inline bool parse(IJson &json, tson::Map *map); - - [[nodiscard]] inline const std::string &getCompression() const; - [[nodiscard]] inline const std::vector &getData() const; - [[nodiscard]] inline const std::string &getBase64Data() const; - [[nodiscard]] inline const std::string &getDrawOrder() const; - [[nodiscard]] inline const std::string &getEncoding() const; - [[nodiscard]] inline int getId() const; - [[nodiscard]] inline const std::string &getImage() const; - [[nodiscard]] inline const std::string &getName() const; - [[nodiscard]] inline const Vector2f &getOffset() const; - [[nodiscard]] inline float getOpacity() const; - [[nodiscard]] inline const Vector2i &getSize() const; - [[nodiscard]] inline const Colori &getTransparentcolor() const; - - [[nodiscard]] inline LayerType getType() const; - - [[nodiscard]] inline const std::string &getTypeStr() const; - [[nodiscard]] inline bool isVisible() const; - [[nodiscard]] inline int getX() const; - [[nodiscard]] inline int getY() const; - - [[nodiscard]] inline std::vector &getChunks(); - [[nodiscard]] inline std::vector &getLayers(); - [[nodiscard]] inline std::vector &getObjects(); - [[nodiscard]] inline PropertyCollection &getProperties(); - - inline tson::Object *getObj(int id); - inline tson::Object *firstObj(const std::string &name); - inline std::vector getObjectsByName(const std::string &name); - inline std::vector getObjectsByType(tson::ObjectType type); - - template - inline T get(const std::string &name); - inline tson::Property * getProp(const std::string &name); - - inline void assignTileMap(std::map *tileMap); - inline void createTileData(const Vector2i &mapSize, bool isInfiniteMap); - - [[nodiscard]] inline const std::map, tson::Tile *> &getTileData() const; - inline tson::Tile * getTileData(int x, int y); - - //v1.2.0-stuff - [[nodiscard]] inline const Colori &getTintColor() const; - [[nodiscard]] inline tson::Map *getMap() const; - - [[nodiscard]] inline const std::map, tson::TileObject> &getTileObjects() const; - inline tson::TileObject * getTileObject(int x, int y); - [[nodiscard]] inline const std::set &getUniqueFlaggedTiles() const; - inline void resolveFlaggedTiles(); - - private: - inline void setTypeByString(); - - std::vector m_chunks; /*! 'chunks': Array of chunks (optional). tilelayer only. */ - std::string m_compression; /*! 'compression': zlib, gzip or empty (default). tilelayer only. */ - std::vector m_data; /*! 'data' (when uint array): Array of unsigned int (GIDs) or base64-encoded - * data. tilelayer only. */ - std::string m_base64Data; /*! 'data' (when string): Array of unsigned int (GIDs) or base64-encoded - * data. tilelayer only. */ - std::string m_drawOrder; /*! 'draworder': topdown (default) or index. objectgroup only. */ - std::string m_encoding; /*! 'encoding': csv (default) or base64. tilelayer only. */ - int m_id{}; /*! 'id': Incremental id - unique across all layers */ - std::string m_image; /*! 'image': Image used by this layer. imagelayer only. */ - std::vector m_layers; /*! 'layers': Array of layers. group on */ - std::string m_name; /*! 'name': Name assigned to this layer */ - std::vector m_objects; /*! 'objects': Array of objects. objectgroup only. */ - tson::Vector2f m_offset; /*! 'offsetx' and 'offsety': Horizontal and Vertical layer offset in pixels - * (default: {0, 0}) */ - float m_opacity{}; /*! 'opacity': Value between 0 and 1 */ - tson::PropertyCollection m_properties; /*! 'properties': A list of properties (name, value, type). */ - tson::Vector2i m_size; /*! x = 'width': (Column count. Same as map width for fixed-size maps.) - y = 'height': Row count. Same as map height for fixed-size maps. */ - tson::Colori m_transparentcolor; /*! 'transparentcolor': Hex-formatted color (#RRGGBB) (optional, imagelayer only */ - std::string m_typeStr; /*! 'type': tilelayer, objectgroup, imagelayer or group */ - LayerType m_type {LayerType::Undefined}; /*! Layer type as enum*/ - bool m_visible{}; /*! 'visible': Whether layer is shown or hidden in editor */ - int m_x{}; /*! 'x': Horizontal layer offset in tiles. Always 0. */ - int m_y{}; /*! 'y': Vertical layer offset in tiles. Always 0. */ - - std::map *m_tileMap; - std::map, tson::Tile*> m_tileData; /*! Key: Tuple of x and y pos in tile units. */ - - //v1.2.0-stuff - tson::Colori m_tintcolor; /*! 'tintcolor': Hex-formatted color (#RRGGBB or #AARRGGBB) that is multiplied with - * any graphics drawn by this layer or any child layers (optional). */ - inline void decompressData(); /*! Defined in tileson_forward.hpp */ - inline void queueFlaggedTile(size_t x, size_t y, uint32_t id); /*! Queue a flagged tile */ - - tson::Map * m_map; /*! The map who owns this layer */ - std::map, tson::TileObject> m_tileObjects; - std::set m_uniqueFlaggedTiles; - std::vector m_flaggedTiles; - - }; - - /*! - * A shortcut for getting a property. Alternative to getProperties().getValue("") - * @tparam T The template value - * @param name Name of the property - * @return The actual value, if it exists. Otherwise: The default value of the type. - */ - template - T Layer::get(const std::string &name) - { - return m_properties.getValue(name); - } -} - -/*! - * Parses a Tiled layer from json - * @param json - */ -tson::Layer::Layer(IJson &json, tson::Map *map) -{ - parse(json, map); -} - -void tson::Layer::queueFlaggedTile(size_t x, size_t y, uint32_t id) -{ - uint32_t tileId = id; - tileId &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG); - m_uniqueFlaggedTiles.insert(id); - m_flaggedTiles.emplace_back(x, y, id, tileId); -} - -/*! - * Parses a Tiled layer from json - * @param json - * @return true if all mandatory fields was found. false otherwise. - */ -bool tson::Layer::parse(IJson &json, tson::Map *map) -{ - m_map = map; - - bool allFound = true; - if(json.count("tintcolor") > 0) m_tintcolor = tson::Colori(json["tintcolor"].get()); //Optional - if(json.count("compression") > 0) m_compression = json["compression"].get(); //Optional - if(json.count("draworder") > 0) m_drawOrder = json["draworder"].get(); //Optional - if(json.count("encoding") > 0) m_encoding = json["encoding"].get(); //Optional - if(json.count("id") > 0) m_id = json["id"].get(); //Optional - if(json.count("image") > 0) m_image = json["image"].get(); //Optional - if(json.count("name") > 0) m_name = json["name"].get(); else allFound = false; - if(json.count("offsetx") > 0 && json.count("offsety") > 0) - m_offset = {json["offsetx"].get(), json["offsety"].get()}; //Optional - if(json.count("opacity") > 0) m_opacity = json["opacity"].get(); else allFound = false; - if(json.count("width") > 0 && json.count("height") > 0) - m_size = {json["width"].get(), json["height"].get()}; //else allFound = false; - Not mandatory for all layers! - if(json.count("transparentcolor") > 0) m_transparentcolor = tson::Colori(json["transparentcolor"].get()); //Optional - if(json.count("type") > 0) m_typeStr = json["type"].get(); else allFound = false; - if(json.count("visible") > 0) m_visible = json["visible"].get(); else allFound = false; - if(json.count("x") > 0) m_x = json["x"].get(); else allFound = false; - if(json.count("y") > 0) m_y = json["y"].get(); else allFound = false; - - //Handle DATA (Optional) - if(json.count("data") > 0) - { - if(json["data"].isArray()) - { - auto &array = json.array("data"); - std::for_each(array.begin(), array.end(), [&](std::unique_ptr &item) { m_data.push_back(item->get()); }); - } - else - { - m_base64Data = json["data"].get(); - decompressData(); - } - } - - //More advanced data - if(json.count("chunks") > 0 && json["chunks"].isArray()) - { - auto &chunks = json.array("chunks"); - std::for_each(chunks.begin(), chunks.end(), [&](std::unique_ptr &item) { m_chunks.emplace_back(*item); }); - } - if(json.count("layers") > 0 && json["layers"].isArray()) - { - auto &layers = json.array("layers"); - std::for_each(layers.begin(), layers.end(), [&](std::unique_ptr &item) { m_layers.emplace_back(*item, m_map); }); - } - if(json.count("objects") > 0 && json["objects"].isArray()) - { - auto &objects = json.array("objects"); - std::for_each(objects.begin(), objects.end(), [&](std::unique_ptr &item) { m_objects.emplace_back(*item); }); - } - if(json.count("properties") > 0 && json["properties"].isArray()) - { - auto &properties = json.array("properties"); - std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr &item) { m_properties.add(*item); }); - } - - setTypeByString(); - - return allFound; -} - -/*! - * Copies all objects with a name that equals the parameter - * @param name Name of the objects to return - * @return All objects with a matching name - */ -std::vector tson::Layer::getObjectsByName(const std::string &name) -{ - std::vector found; - - std::copy_if(m_objects.begin(), m_objects.end(), std::back_inserter(found), [&](const tson::Object &item) - { - return item.getName() == name; - }); - - return found; -} - -/*! - * Copies all objects with a type that equals the parameter - * @param type LayerType of the objects to return - * @return All objects with a matching type - */ -std::vector tson::Layer::getObjectsByType(tson::ObjectType type) -{ - std::vector found; - - std::copy_if(m_objects.begin(), m_objects.end(), std::back_inserter(found), [&](const tson::Object &item) - { - return item.getObjectType() == type; - }); - - return found; -} - -/*! - * Returns the first object with the given name - * @param name Name of the object to find. - * @return A pointer to the object if found. nullptr otherwise. - */ -tson::Object *tson::Layer::firstObj(const std::string &name) -{ - auto result = std::find_if(m_objects.begin(), m_objects.end(), [&](const tson::Object &obj){return obj.getName() == name; }); - if(result == m_objects.end()) - return nullptr; - - return &result.operator*(); -} - -/*! - * Get an object by ID - * @param id Unique ID of the object - * @return A pointer to the object if found. nullptr otherwise. - */ -tson::Object *tson::Layer::getObj(int id) -{ - auto result = std::find_if(m_objects.begin(), m_objects.end(), [&](const tson::Object &obj){return obj.getId() == id; }); - if(result == m_objects.end()) - return nullptr; - - return &result.operator*(); -} - -/*! - * Set type by string - * tilelayer, objectgroup, imagelayer or group - */ -void tson::Layer::setTypeByString() -{ - if(m_typeStr == "tilelayer") m_type = LayerType::TileLayer; - else if(m_typeStr == "objectgroup") m_type = LayerType::ObjectGroup; - else if(m_typeStr == "imagelayer") m_type = LayerType::ImageLayer; - else if(m_typeStr == "group") m_type = LayerType::Group; - else m_type = LayerType::Undefined; -} - -/*! - * 'compression': zlib, gzip or empty (default). tilelayer only. - * @return - */ -const std::string &tson::Layer::getCompression() const -{ - return m_compression; -} - -/*! - * 'data' (when uint array): Array of unsigned int (GIDs) or base64-encoded data. tilelayer only. - * @return - */ -const std::vector &tson::Layer::getData() const -{ - return m_data; -} - -/*! - * 'data' (when string): Array of unsigned int (GIDs) or base64-encoded data. tilelayer only. - * @return - */ -const std::string &tson::Layer::getBase64Data() const -{ - return m_base64Data; -} - -/*! - * 'draworder': topdown (default) or index. objectgroup only. - * @return - */ -const std::string &tson::Layer::getDrawOrder() const -{ - return m_drawOrder; -} - -/*! - * 'encoding': csv (default) or base64. tilelayer only. - * @return - */ -const std::string &tson::Layer::getEncoding() const -{ - return m_encoding; -} - -/*! - * 'id': Incremental id - unique across all layers - * @return - */ -int tson::Layer::getId() const -{ - return m_id; -} - -/*! - * 'image': Image used by this layer. imagelayer only. - * @return - */ -const std::string &tson::Layer::getImage() const -{ - return m_image; -} - -/*! - * 'name': Name assigned to this layer - * @return - */ -const std::string &tson::Layer::getName() const -{ - return m_name; -} - -/*! - * 'offsetx' and 'offsety': Horizontal and Vertical layer offset in pixels (default: {0, 0}) - * @return - */ -const tson::Vector2f &tson::Layer::getOffset() const -{ - return m_offset; -} - -/*! - * 'opacity': Value between 0 and 1 - * @return - */ -float tson::Layer::getOpacity() const -{ - return m_opacity; -} - -/*! - * x = 'width': (Column count. Same as map width for fixed-size maps.) - * y = 'height': Row count. Same as map height for fixed-size maps. - * @return width and height as a single size - */ -const tson::Vector2i &tson::Layer::getSize() const -{ - return m_size; -} - -/*! - * 'transparentcolor': Color created from a hex color (#RRGGBB) (optional, imagelayer only) - * @return color as color object with rgba channel. - */ -const tson::Colori &tson::Layer::getTransparentcolor() const -{ - return m_transparentcolor; -} - -/*! - * 'type': tilelayer, objectgroup, imagelayer or group - * @return string with the object type - */ -const std::string &tson::Layer::getTypeStr() const -{ - return m_typeStr; -} - -/*! - * 'visible': Whether layer is shown or hidden in editor - * @return - */ -bool tson::Layer::isVisible() const -{ - return m_visible; -} - -/*! - * 'x': Horizontal layer offset in tiles. Always 0. - * @return x value (always 0 for layer) - */ -int tson::Layer::getX() const -{ - return m_x; -} - -/*! - * 'y': Horizontal layer offset in tiles. Always 0. - * @return y value (always 0 for layer) - */ -int tson::Layer::getY() const -{ - return m_y; -} - -/*! - * 'chunks': Array of chunks (optional). tilelayer only. - * @return - */ -std::vector &tson::Layer::getChunks() -{ - return m_chunks; -} - -/*! - * 'layers': Array of layers. group on - * @return - */ -std::vector &tson::Layer::getLayers() -{ - return m_layers; -} - -/*! - * 'objects': Array of objects. objectgroup only. - * @return - */ -std::vector &tson::Layer::getObjects() -{ - return m_objects; -} - -/*! - * 'properties': A list of properties (name, value, type). - * @return - */ -tson::PropertyCollection &tson::Layer::getProperties() -{ - return m_properties; -} - -/*! - * Shortcut for getting a property object. Alternative to getProperties().getProperty(""); - * @param name Name of the property - * @return - */ -tson::Property *tson::Layer::getProp(const std::string &name) -{ - if(m_properties.hasProperty(name)) - return m_properties.getProperty(name); - return nullptr; -} - -/*! - * Get layer type - * @return Layer type as enum - */ -tson::LayerType tson::Layer::getType() const -{ - return m_type; -} - -/*! - * Assigns a tilemap of pointers to existing tiles. - * @param tileMap The tilemap. key: tile id, value: pointer to Tile. - */ -void tson::Layer::assignTileMap(std::map *tileMap) -{ - m_tileMap = tileMap; -} - -/*! - * Get tile data as some kind of map with x and y position with pointers to existing tiles. - * Map only contains tiles that are not empty. x and y position is in tile units. - * - * Example of getting tile from the returned map: - * - * Tile *tile = tileData[{0, 4}]; - * - * @return A map that represents the data returned from getData() in a 2D map with Tile pointers. - */ -const std::map, tson::Tile *> &tson::Layer::getTileData() const -{ - return m_tileData; -} - -/*! - * A safe way to get tile data - * Get tile data as some kind of map with x and y position with pointers to existing tiles. - * Map only contains tiles that are not empty. x and y position is in tile units. - * - * Example of getting tile: - * Tile *tile = layer->getTileData(0, 4) - * - * @param x X position in tile units - * @param y Y position in tile units - * @return pointer to tile, if it exists. nullptr otherwise. - */ -tson::Tile *tson::Layer::getTileData(int x, int y) -{ - return (m_tileData.count({x, y}) > 0) ? m_tileData[{x,y}] : nullptr; -} - -/*! - * Used for getting the tson::Map who is the parent of this Layer. - * @return a pointer to the tson::Map where this layer is contained. - */ -tson::Map *tson::Layer::getMap() const -{ - return m_map; -} - -/*! - * - * This is only supported for non-infinite maps! - * - * @param mapSize The size of the map - * @param isInfiniteMap Whether or not the current map is infinte. - */ -void tson::Layer::createTileData(const Vector2i &mapSize, bool isInfiniteMap) -{ - size_t x = 0; - size_t y = 0; - if(!isInfiniteMap) - { - std::for_each(m_data.begin(), m_data.end(), [&](uint32_t tileId) - { - if (x == mapSize.x) - { - ++y; - x = 0; - } - - if (tileId > 0 && m_tileMap->count(tileId) > 0) - { - m_tileData[{x, y}] = m_tileMap->at(tileId); - m_tileObjects[{x, y}] = {{x, y}, m_tileData[{x, y}]}; - } - else if(tileId > 0 && m_tileMap->count(tileId) == 0) //Tile with flip flags! - { - queueFlaggedTile(x, y, tileId); - } - x++; - }); - - } -} - -const std::map, tson::TileObject> &tson::Layer::getTileObjects() const -{ - return m_tileObjects; -} - -tson::TileObject *tson::Layer::getTileObject(int x, int y) -{ - return (m_tileObjects.count({x, y}) > 0) ? &m_tileObjects[{x,y}] : nullptr; -} - -const std::set &tson::Layer::getUniqueFlaggedTiles() const -{ - return m_uniqueFlaggedTiles; -} - -void tson::Layer::resolveFlaggedTiles() -{ - std::for_each(m_flaggedTiles.begin(), m_flaggedTiles.end(), [&](const tson::FlaggedTile &tile) - { - if (tile.id > 0 && m_tileMap->count(tile.id) > 0) - { - m_tileData[{tile.x, tile.y}] = m_tileMap->at(tile.id); - m_tileObjects[{tile.x, tile.y}] = {{tile.x, tile.y}, m_tileData[{tile.x, tile.y}]}; - } - }); -} - -/*! - * 'tintcolor': Hex-formatted color (#RRGGBB or #AARRGGBB) that is multiplied with any graphics drawn by this layer or any child layers (optional). - * - * @return tintcolor - */ -const tson::Colori &tson::Layer::getTintColor() const -{ - return m_tintcolor; -} - -#endif //TILESON_LAYER_HPP - -/*** End of inlined file: Layer.hpp ***/ - - -/*** Start of inlined file: Tileset.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_TILESET_HPP -#define TILESON_TILESET_HPP - -//#include "../external/json.hpp" - - -/*** Start of inlined file: WangSet.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_WANGSET_HPP -#define TILESON_WANGSET_HPP - -//#include "../external/json.hpp" - -/*** Start of inlined file: WangColor.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_WANGCOLOR_HPP -#define TILESON_WANGCOLOR_HPP - -//#include "../external/json.hpp" - -namespace tson -{ - class WangColor - { - public: - inline WangColor() = default; - inline explicit WangColor(IJson &json); - inline bool parse(IJson &json); - - [[nodiscard]] inline const Colori &getColor() const; - [[nodiscard]] inline const std::string &getName() const; - [[nodiscard]] inline float getProbability() const; - [[nodiscard]] inline int getTile() const; - - private: - tson::Colori m_color; /*! 'color': Hex-formatted color (#RRGGBB or #AARRGGBB) */ - std::string m_name; /*! 'name': Name of the Wang color */ - float m_probability{}; /*! 'probability': Probability used when randomizing */ - int m_tile{}; /*! 'tile': Local ID of tile representing the Wang color */ - }; -} - -tson::WangColor::WangColor(IJson &json) -{ - parse(json); -} - -bool tson::WangColor::parse(IJson &json) -{ - bool allFound = true; - - if(json.count("color") > 0) m_color = tson::Colori(json["color"].get()); else allFound = false; - if(json.count("name") > 0) m_name = json["name"].get(); else allFound = false; - if(json.count("probability") > 0) m_probability = json["probability"].get(); else allFound = false; - if(json.count("tile") > 0) m_tile = json["tile"].get(); else allFound = false; - - return allFound; -} - -/*! - * 'color': Color object created from hex-formatted string (#RRGGBB or #AARRGGBB) - * @return - */ -const tson::Colori &tson::WangColor::getColor() const -{ - return m_color; -} - -/*! - * 'name': Name of the Wang color - * @return - */ -const std::string &tson::WangColor::getName() const -{ - return m_name; -} - -/*! - * 'probability': Probability used when randomizing - * @return - */ -float tson::WangColor::getProbability() const -{ - return m_probability; -} - -/*! - * 'tile': Local ID of tile representing the Wang color - * @return - */ -int tson::WangColor::getTile() const -{ - return m_tile; -} - -#endif //TILESON_WANGCOLOR_HPP - -/*** End of inlined file: WangColor.hpp ***/ - - - -/*** Start of inlined file: WangTile.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_WANGTILE_HPP -#define TILESON_WANGTILE_HPP - -//#include "../external/json.hpp" - -namespace tson -{ - class WangTile - { - public: - inline WangTile() = default; - inline explicit WangTile(IJson &json); - inline bool parse(IJson &json); - - [[nodiscard]] inline bool hasDFlip() const; - [[nodiscard]] inline bool hasHFlip() const; - [[nodiscard]] inline int getTileid() const; - [[nodiscard]] inline bool hasVFlip() const; - - [[nodiscard]] inline const std::vector &getWangIds() const; - - private: - bool m_dflip{}; /*! 'dflip': Tile is flipped diagonally */ - bool m_hflip{}; /*! 'hflip': Tile is flipped horizontally */ - int m_tileid{}; /*! 'tileid': Local ID of tile */ - bool m_vflip{}; /*! 'vflip': Tile is flipped vertically */ - std::vector m_wangId; /*! 'wangid': Array of Wang color indexes (uchar[8])*/ - }; -} - -tson::WangTile::WangTile(IJson &json) -{ - parse(json); -} - -/*! - * Parses a wang tile from Tiled json. - * @param json A Tiled json file - * @return true if all mandatory fields were found. False otherwise. - */ -bool tson::WangTile::parse(IJson &json) -{ - bool allFound = true; - - if(json.count("dflip") > 0) m_dflip = json["dflip"].get(); else allFound = false; - if(json.count("hflip") > 0) m_hflip = json["hflip"].get(); else allFound = false; - if(json.count("vflip") > 0) m_vflip = json["vflip"].get(); else allFound = false; - if(json.count("tileid") > 0) m_tileid = json["tileid"].get(); else allFound = false; - - if(json.count("wangid") > 0 && json["wangid"].isArray()) - { - auto &wangid = json.array("wangid"); - std::for_each(wangid.begin(), wangid.end(), [&](std::unique_ptr &item) { m_wangId.emplace_back(item->get()); }); - } - - return allFound; -} - -/*! - * 'dflip': Tile is flipped diagonally - * @return - */ -bool tson::WangTile::hasDFlip() const -{ - return m_dflip; -} - -/*! - * 'hflip': Tile is flipped horizontally - * @return - */ -bool tson::WangTile::hasHFlip() const -{ - return m_hflip; -} - -/*! - * 'tileid': Local ID of tile - * @return - */ -int tson::WangTile::getTileid() const -{ - return m_tileid; -} - -/*! - * 'vflip': Tile is flipped vertically - * @return - */ -bool tson::WangTile::hasVFlip() const -{ - return m_vflip; -} - -/*! - * 'wangid': Array of Wang color indexes (uchar[8]) - * @return - */ -const std::vector &tson::WangTile::getWangIds() const -{ - return m_wangId; -} - -#endif //TILESON_WANGTILE_HPP - -/*** End of inlined file: WangTile.hpp ***/ - -namespace tson -{ - class WangSet - { - public: - inline WangSet() = default; - inline explicit WangSet(IJson &json); - inline bool parse(IJson &json); - - [[nodiscard]] inline const std::string &getName() const; - [[nodiscard]] inline int getTile() const; - - [[nodiscard]] inline const std::vector &getWangTiles() const; - [[nodiscard]] inline const std::vector &getCornerColors() const; - [[nodiscard]] inline const std::vector &getEdgeColors() const; - - inline PropertyCollection &getProperties(); - - template - inline T get(const std::string &name); - inline tson::Property * getProp(const std::string &name); - - private: - std::string m_name; /*! 'name': Name of the Wang set */ - int m_tile{}; /*! 'tile': Local ID of tile representing the Wang set */ - std::vector m_wangTiles; /*! 'wangtiles': Array of Wang tiles */ - std::vector m_cornerColors; /*! 'cornercolors': Array of Wang colors */ - std::vector m_edgeColors; /*! 'edgecolors': Array of Wang colors */ - tson::PropertyCollection m_properties; /*! 'properties': A list of properties (name, value, type). */ - - }; - - /*! - * A shortcut for getting a property. Alternative to getProperties().getValue("") - * @tparam T The template value - * @param name Name of the property - * @return The actual value, if it exists. Otherwise: The default value of the type. - */ - template - T tson::WangSet::get(const std::string &name) - { - return m_properties.getValue(name); - } -} - -tson::WangSet::WangSet(IJson &json) -{ - parse(json); -} - -bool tson::WangSet::parse(IJson &json) -{ - bool allFound = true; - - if(json.count("tile") > 0) m_tile = json["tile"].get(); else allFound = false; - if(json.count("name") > 0) m_name = json["name"].get(); else allFound = false; - - //More advanced data - if(json.count("wangtiles") > 0 && json["wangtiles"].isArray()) - { - auto &wangtiles = json.array("wangtiles"); - std::for_each(wangtiles.begin(), wangtiles.end(), [&](std::unique_ptr &item) { m_wangTiles.emplace_back(*item); }); - } - if(json.count("cornercolors") > 0 && json["cornercolors"].isArray()) - { - auto &cornercolors = json.array("cornercolors"); - std::for_each(cornercolors.begin(), cornercolors.end(), [&](std::unique_ptr &item) { m_cornerColors.emplace_back(*item); }); - } - if(json.count("edgecolors") > 0 && json["edgecolors"].isArray()) - { - auto &edgecolors = json.array("edgecolors"); - std::for_each(edgecolors.begin(), edgecolors.end(), [&](std::unique_ptr &item) { m_edgeColors.emplace_back(*item); }); - } - if(json.count("properties") > 0 && json["properties"].isArray()) - { - auto &properties = json.array("properties"); - std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr &item) { m_properties.add(*item); }); - } - - return allFound; -} - -/*! - * 'name': Name of the Wang set - * @return - */ -const std::string &tson::WangSet::getName() const -{ - return m_name; -} - -/*! - * 'tile': Local ID of tile representing the Wang set - * @return - */ -int tson::WangSet::getTile() const -{ - return m_tile; -} - -/*! - * 'wangtiles': Array of Wang tiles - * @return - */ -const std::vector &tson::WangSet::getWangTiles() const -{ - return m_wangTiles; -} - -/*! - * 'cornercolors': Array of Wang colors - * @return - */ -const std::vector &tson::WangSet::getCornerColors() const -{ - return m_cornerColors; -} - -/*! - * 'edgecolors': Array of Wang colors - * @return - */ -const std::vector &tson::WangSet::getEdgeColors() const -{ - return m_edgeColors; -} - -/*! - * 'properties': A list of properties (name, value, type). - * @return - */ -tson::PropertyCollection &tson::WangSet::getProperties() -{ - return m_properties; -} - -/*! - * Shortcut for getting a property object. Alternative to getProperties().getProperty(""); - * @param name Name of the property - * @return - */ -tson::Property *tson::WangSet::getProp(const std::string &name) -{ - if(m_properties.hasProperty(name)) - return m_properties.getProperty(name); - - return nullptr; -} - -#endif //TILESON_WANGSET_HPP - -/*** End of inlined file: WangSet.hpp ***/ - - -/*** Start of inlined file: Tile.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_TILE_HPP -#define TILESON_TILE_HPP - -//#include "../external/json.hpp" - - -/*** Start of inlined file: Frame.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_FRAME_HPP -#define TILESON_FRAME_HPP - -//#include "../external/json.hpp" - -namespace tson -{ - class Frame - { - public: - inline Frame() = default; - inline Frame(int duration, int tileId); - inline explicit Frame(IJson &json); - - inline bool parse(IJson &json); - - [[nodiscard]] inline int getDuration() const; - [[nodiscard]] inline int getTileId() const; - - private: - int m_duration {}; /*! 'duration': Frame duration in milliseconds */ - int m_tileId {}; /*! 'tileid': Local tile ID representing this frame */ - }; -} - -/*! - * - * @param duration duration in milliseconds - * @param tileId TileId - */ -tson::Frame::Frame(int duration, int tileId) : m_duration {duration}, m_tileId {tileId} -{ - -} - -/*! - * Parses frame data from json - * @param json - */ -tson::Frame::Frame(IJson &json) -{ - parse(json); -} - -/*! - * Parses frame data from json - * @param json - * @return true if all mandatory fields was found. false otherwise. - */ -bool tson::Frame::parse(IJson &json) -{ - bool allFound = true; - - if(json.count("duration") > 0) m_duration = json["duration"].get(); else allFound = false; - if(json.count("tileid") > 0) m_tileId = json["tileid"].get(); else allFound = false; - - return allFound; -} - -/*! - * 'duration': Frame duration in milliseconds - * @return Duration in milliseconds - */ -int tson::Frame::getDuration() const -{ - return m_duration; -} - -/*! - * 'tileid': Local tile ID representing this frame - * @return tile id - */ -int tson::Frame::getTileId() const -{ - return m_tileId; -} - -#endif //TILESON_FRAME_HPP - -/*** End of inlined file: Frame.hpp ***/ - -namespace tson -{ - class Tileset; - - class Tile - { - public: - inline Tile() = default; - inline Tile(IJson &json, tson::Tileset *tileset, tson::Map *map); - inline Tile(uint32_t id, tson::Tileset *tileset, tson::Map *map); - inline Tile(uint32_t id, tson::Map *map); //v1.2.0 - inline bool parse(IJson &json, tson::Tileset *tileset, tson::Map *map); - inline bool parseId(IJson &json); - - [[nodiscard]] inline uint32_t getId() const; - - [[nodiscard]] inline const fs::path &getImage() const; - - [[nodiscard]] inline const Vector2i &getImageSize() const; - [[nodiscard]] inline const std::string &getType() const; - - [[nodiscard]] inline const std::vector &getAnimation() const; - [[nodiscard]] inline const Layer &getObjectgroup() const; - [[nodiscard]] inline PropertyCollection &getProperties(); - [[nodiscard]] inline const std::vector &getTerrain() const; - - template - inline T get(const std::string &name); - inline tson::Property * getProp(const std::string &name); - - //v1.2.0-stuff - inline void setProperties(const tson::PropertyCollection &properties); - - inline tson::Tileset * getTileset() const; - inline tson::Map * getMap() const; - inline const tson::Rect &getDrawingRect() const; - inline const tson::Vector2f getPosition(const std::tuple &tileDataPos); - inline const tson::Vector2i getPositionInTileUnits(const std::tuple &tileDataPos); - inline const tson::Vector2i getTileSize() const; /*! Declared in tileson_forward.hpp */ - - [[nodiscard]] inline TileFlipFlags getFlipFlags() const; - inline bool hasFlipFlags(TileFlipFlags flags); - [[nodiscard]] inline uint32_t getGid() const; - - inline void addTilesetAndPerformCalculations(tson::Tileset *tileset); //v1.2.0 - - private: - std::vector m_animation; /*! 'animation': Array of Frames */ - uint32_t m_id {}; /*! 'id': Local ID of the tile */ - - fs::path m_image; /*! 'image': Image representing this tile (optional)*/ - - tson::Vector2i m_imageSize; /*! x = 'imagewidth' and y = 'imageheight': in pixels */ - tson::Layer m_objectgroup; /*! 'objectgroup': Layer with type objectgroup (optional) */ - tson::PropertyCollection m_properties; /*! 'properties': A list of properties (name, value, type). */ - std::vector m_terrain; /*! 'terrain': Index of terrain for each corner of tile */ - std::string m_type; /*! 'type': The type of the tile (optional) */ - - //v1.2.0-stuff - uint32_t m_gid {}; /*! id without flip flags */ - tson::Tileset * m_tileset; /*! A pointer to the tileset where this Tile comes from */ - tson::Map * m_map; /*! A pointer to the map where this tile is contained */ - tson::Rect m_drawingRect; /*! A rect that shows which part of the tileset that is used for this tile */ - tson::TileFlipFlags m_flipFlags = TileFlipFlags::None; /*! Resolved using bit 32, 31 and 30 from gid */ - inline void performDataCalculations(); /*! Declared in tileson_forward.hpp - Calculate all the values used in the tile class. */ - inline void manageFlipFlagsByIdThenRemoveFlags(uint32_t &id); - friend class Layer; - }; - - /*! - * A shortcut for getting a property. Alternative to getProperties().getValue("") - * @tparam T The template value - * @param name Name of the property - * @return The actual value, if it exists. Otherwise: The default value of the type. - */ - template - T tson::Tile::get(const std::string &name) - { - return m_properties.getValue(name); - } -} - -tson::Tile::Tile(IJson &json, tson::Tileset *tileset, tson::Map *map) -{ - parse(json, tileset, map); -} - -/*! - * Used in cases where you have a tile without any property - * @param id - */ -tson::Tile::Tile(uint32_t id, tson::Tileset *tileset, tson::Map *map) : m_id {id}, m_gid {id} -{ - m_tileset = tileset; - m_map = map; - manageFlipFlagsByIdThenRemoveFlags(m_gid); - performDataCalculations(); -} - -/*! - * Used in cases where you have a FLIP FLAGGED tile - * @param id - */ -tson::Tile::Tile(uint32_t id, tson::Map *map) : m_id {id}, m_gid {id} -{ - m_map = map; - manageFlipFlagsByIdThenRemoveFlags(m_gid); -} - -/*! - * For flip flagged tiles, tilesets must be resolved later. - * @param tileset - */ -void tson::Tile::addTilesetAndPerformCalculations(tson::Tileset *tileset) -{ - m_tileset = tileset; - performDataCalculations(); -} - -/*! - * Parses a tile from a Tiled json. id on tile is store as id + 1 to match the references in data containers. - * @param json - * @return - */ -bool tson::Tile::parse(IJson &json, tson::Tileset *tileset, tson::Map *map) -{ - m_tileset = tileset; - m_map = map; - - if(json.count("image") > 0) m_image = fs::path(json["image"].get()); //Optional - - bool allFound = parseId(json); - - if(json.count("type") > 0) m_type = json["type"].get(); //Optional - if(json.count("objectgroup") > 0) m_objectgroup = tson::Layer(json["objectgroup"], m_map); //Optional - - if(json.count("imagewidth") > 0 && json.count("imageheight") > 0) - m_imageSize = {json["imagewidth"].get(), json["imageheight"].get()}; //Optional - - //More advanced data - if(json.count("animation") > 0 && json["animation"].isArray()) - { - auto &animation = json.array("animation"); - std::for_each(animation.begin(), animation.end(), [&](std::unique_ptr &item) { m_animation.emplace_back(*item); }); - } - if(json.count("terrain") > 0 && json["terrain"].isArray()) - { - auto &terrain = json.array("terrain"); - std::for_each(terrain.begin(), terrain.end(), [&](std::unique_ptr &item) { m_terrain.emplace_back(item->get()); }); - } - - if(json.count("properties") > 0 && json["properties"].isArray()) - { - auto &properties = json.array("properties"); - std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr &item) { m_properties.add(*item); }); - } - - performDataCalculations(); - - return allFound; -} - -/*! - * 'id': Local ID of the tile - * @return - */ -uint32_t tson::Tile::getId() const -{ - return m_id; -} - -/*! - * 'image': Image representing this tile (optional) - * @return - */ - -const fs::path &tson::Tile::getImage() const { return m_image; } - -/*! - * x = 'imagewidth' and y = 'imageheight': in pixels - * @return - */ -const tson::Vector2i &tson::Tile::getImageSize() const -{ - return m_imageSize; -} - -/*! - * 'type': The type of the tile (optional) - * @return - */ -const std::string &tson::Tile::getType() const -{ - return m_type; -} - -/*! - * 'animation': Array of Frames - * @return - */ -const std::vector &tson::Tile::getAnimation() const -{ - return m_animation; -} - -/*! - * 'objectgroup': Layer with type objectgroup (optional) - * @return - */ -const tson::Layer &tson::Tile::getObjectgroup() const -{ - return m_objectgroup; -} - -/*! - * 'properties': A list of properties (name, value, type). - * @return - */ -tson::PropertyCollection &tson::Tile::getProperties() -{ - return m_properties; -} - -/*! - * 'terrain': Index of terrain for each corner of tile - * @return - */ -const std::vector &tson::Tile::getTerrain() const -{ - return m_terrain; -} - -/*! - * Shortcut for getting a property object. Alternative to getProperties().getProperty(""); - * @param name Name of the property - * @return - */ -tson::Property *tson::Tile::getProp(const std::string &name) -{ - if(m_properties.hasProperty(name)) - return m_properties.getProperty(name); - - return nullptr; -} - -/*! - * Used for getting the tson::Tileset who is the parent of this Tile. - * @return a pointer to the tson::Tileset where this tile is contained. - */ -tson::Tileset *tson::Tile::getTileset() const -{ - return m_tileset; -} - -/*! - * Used for getting the tson::Map who is the parent of this Tile. - * @return a pointer to the tson::Map where this tile is contained. - */ -tson::Map *tson::Tile::getMap() const -{ - return m_map; -} - -/*! - * Get the information needed to draw the Tile based on its current tileset - * @return a tson::Rect containing the information needed to draw the tile. - */ -const tson::Rect &tson::Tile::getDrawingRect() const -{ - return m_drawingRect; -} - -/*! - * Helper function. - * - * Get the position of the tile in tile units. - * The size of each unit is determined by the tile size property of the map. - * Example: If the tile size is 16x16 in the map, a tile unit of [2, 4] would be [32, 64] in pixels. - * If you want the position in pixels: use getPosition() instead. - * - * @return Position of tile in tile units. - */ -const tson::Vector2i tson::Tile::getPositionInTileUnits(const std::tuple &tileDataPos) -{ - return {std::get<0>(tileDataPos), std::get<1>(tileDataPos)}; -} - -void tson::Tile::manageFlipFlagsByIdThenRemoveFlags(uint32_t &id) -{ - if (id & FLIPPED_HORIZONTALLY_FLAG) m_flipFlags |= TileFlipFlags::Horizontally; - if (id & FLIPPED_VERTICALLY_FLAG) m_flipFlags |= TileFlipFlags::Vertically; - if (id & FLIPPED_DIAGONALLY_FLAG) m_flipFlags |= TileFlipFlags::Diagonally; - - id &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG); -} - -tson::TileFlipFlags tson::Tile::getFlipFlags() const -{ - return m_flipFlags; -} - -/*! - * - * @param flags Which flags to check for. Several flags can be checked at once using the bitwise or operator. - * Example: - * hasFlipFlags(TileFlipFlags::Vertically | TileFlipFlags::Horizontally) - * - * @return true if the flag(s) specified are set - */ -bool tson::Tile::hasFlipFlags(tson::TileFlipFlags flags) -{ - return ((m_flipFlags & flags) == flags) ? true : false; -} - -uint32_t tson::Tile::getGid() const -{ - return m_gid; -} - -void tson::Tile::setProperties(const tson::PropertyCollection &properties) -{ - m_properties = properties; -} - -#endif //TILESON_TILE_HPP - -/*** End of inlined file: Tile.hpp ***/ - - -/*** Start of inlined file: Terrain.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_TERRAIN_HPP -#define TILESON_TERRAIN_HPP - -//#include "../external/json.hpp" - -namespace tson -{ - class Terrain - { - public: - inline Terrain() = default; - inline Terrain(std::string name, int tile); - inline explicit Terrain(IJson &json); - - inline bool parse(IJson &json); - - [[nodiscard]] inline const std::string &getName() const; - [[nodiscard]] inline int getTile() const; - [[nodiscard]] inline PropertyCollection &getProperties(); - - template - inline T get(const std::string &name); - inline tson::Property * getProp(const std::string &name); - - private: - std::string m_name; /*! 'name': Name of terrain */ - int m_tile {}; /*! 'tile': Local ID of tile representing terrain */ - tson::PropertyCollection m_properties; /*! 'properties': A list of properties (name, value, type). */ - }; - - /*! - * A shortcut for getting a property. Alternative to getProperties().getValue("") - * @tparam T The template value - * @param name Name of the property - * @return The actual value, if it exists. Otherwise: The default value of the type. - */ - template - T tson::Terrain::get(const std::string &name) - { - return m_properties.getValue(name); - } -} - -tson::Terrain::Terrain(std::string name, int tile) : m_name {std::move(name)}, m_tile {tile} -{ - -} - -tson::Terrain::Terrain(IJson &json) -{ - parse(json); -} - -bool tson::Terrain::parse(IJson &json) -{ - bool allFound = true; - - if(json.count("name") > 0) m_name = json["name"].get(); else allFound = false; - if(json.count("tile") > 0) m_tile = json["tile"].get(); else allFound = false; - - if(json.count("properties") > 0 && json["properties"].isArray()) - { - auto &properties = json.array("properties"); - std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr &item) { m_properties.add(*item); }); - } - - return allFound; -} - -/*! - * 'name': Name of terrain - * @return - */ -const std::string &tson::Terrain::getName() const -{ - return m_name; -} - -/*! - * 'tile': Local ID of tile representing terrain - * @return - */ -int tson::Terrain::getTile() const -{ - return m_tile; -} - -/*! - * 'properties': A list of properties (name, value, type). *Missing from the official Tiled documentation...* - * @return - */ -tson::PropertyCollection &tson::Terrain::getProperties() -{ - return m_properties; -} - -/*! - * Shortcut for getting a property object. Alternative to getProperties().getProperty(""); - * @param name Name of the property - * @return - */ -tson::Property *tson::Terrain::getProp(const std::string &name) -{ - if(m_properties.hasProperty(name)) - return m_properties.getProperty(name); - return nullptr; -} - -#endif //TILESON_TERRAIN_HPP - -/*** End of inlined file: Terrain.hpp ***/ - - -/*** Start of inlined file: Grid.hpp ***/ -// -// Created by robin on 22.03.2020. -// - -#ifndef TILESON_GRID_HPP -#define TILESON_GRID_HPP - -#include -//#include "../external/json.hpp" - -namespace tson -{ - class Grid - { - public: - inline Grid() = default; - inline explicit Grid(IJson &json); - - inline bool parse(IJson &json); - - [[nodiscard]] inline const std::string &getOrientation() const; - [[nodiscard]] inline const Vector2i &getSize() const; - - private: - std::string m_orientation; /*! 'orientation': Orientation of the grid for the tiles in this tileset (orthogonal or isometric) */ - tson::Vector2i m_size; /*! 'width' and 'height': Size. */ - }; -} - -/*! - * Parses Tiled grid data from json - * @param json - */ -tson::Grid::Grid(IJson &json) -{ - parse(json); -} - -/*! - * Parses Tiled grid data from json - * @param json - * @return true if all mandatory fields was found. false otherwise. - */ -bool tson::Grid::parse(IJson &json) -{ - bool allFound = true; - - if(json.count("orientation") > 0) m_orientation = json["orientation"].get(); //Optional - - if(json.count("width") > 0 && json.count("height") > 0) - m_size = {json["width"].get(), json["height"].get()}; else allFound = false; - - return allFound; -} - -/*! - * 'orientation': Orientation of the grid for the tiles in this tileset (orthogonal or isometric) - * @return orientation as string - */ -const std::string &tson::Grid::getOrientation() const -{ - return m_orientation; -} - -/*! - * 'width' and 'height': Size. - * @return size as int - */ -const tson::Vector2i &tson::Grid::getSize() const -{ - return m_size; -} - -#endif //TILESON_GRID_HPP - -/*** End of inlined file: Grid.hpp ***/ - -#include - -namespace tson -{ - class Map; - class Tileset - { - public: - inline Tileset() = default; - inline explicit Tileset(IJson &json, tson::Map *map); - inline bool parse(IJson &json, tson::Map *map); - - [[nodiscard]] inline int getColumns() const; - [[nodiscard]] inline int getFirstgid() const; - - [[nodiscard]] inline const fs::path &getImagePath() const; - [[nodiscard]] inline const fs::path &getImage() const; - - [[nodiscard]] inline const Vector2i &getImageSize() const; - [[nodiscard]] inline int getMargin() const; - [[nodiscard]] inline const std::string &getName() const; - [[nodiscard]] inline int getSpacing() const; - [[nodiscard]] inline int getTileCount() const; - [[nodiscard]] inline const Vector2i &getTileSize() const; - [[nodiscard]] inline const Colori &getTransparentColor() const; - - [[nodiscard]] inline const std::string &getType() const; - [[nodiscard]] inline std::vector &getTiles(); - [[nodiscard]] inline const std::vector &getWangsets() const; - [[nodiscard]] inline PropertyCollection &getProperties(); - [[nodiscard]] inline const std::vector &getTerrains() const; - [[nodiscard]] inline const Vector2i &getTileOffset() const; - [[nodiscard]] inline const Grid &getGrid() const; - - inline tson::Tile * getTile(int id); - inline tson::Terrain * getTerrain(const std::string &name); - - template - inline T get(const std::string &name); - inline tson::Property * getProp(const std::string &name); - - //v1.2.0-stuff - [[nodiscard]] inline tson::Map *getMap() const; - [[nodiscard]] inline ObjectAlignment getObjectAlignment() const; - - inline static tson::ObjectAlignment StringToAlignment(std::string_view str); - - private: - inline void generateMissingTiles(); - - int m_columns {}; /*! 'columns': The number of tile columns in the tileset */ - int m_firstgid {}; /*! 'firstgid': GID corresponding to the first tile in the set */ - - fs::path m_image; /*! 'image': Image used for tiles in this set */ - - tson::Vector2i m_imageSize; /*! x = 'imagewidth' and y = 'imageheight': in pixels */ - int m_margin {}; /*! 'margin': Buffer between image edge and first tile (pixels)*/ - std::string m_name; /*! 'name': Name given to this tileset */ - int m_spacing {}; /*! 'spacing': Spacing between adjacent tiles in image (pixels)*/ - int m_tileCount {}; /*! 'tilecount': The number of tiles in this tileset */ - tson::Vector2i m_tileSize; /*! x = 'tilewidth' and y = 'tileheight': Maximum size of tiles in this set */ - tson::Colori m_transparentColor; /*! 'transparentcolor': Hex-formatted color (#RRGGBB) (optional) */ - std::string m_type; /*! 'type': tileset (for tileset files, since 1.0) */ - - std::vector m_tiles; /*! 'tiles': Array of Tiles (optional) */ - std::vector m_wangsets; /*! 'wangsets':Array of Wang sets (since 1.1.5) */ - tson::PropertyCollection m_properties; /*! 'properties': A list of properties (name, value, type). */ - - std::vector m_terrains; /*! 'terrains': Array of Terrains (optional) */ - tson::Vector2i m_tileOffset; /*! 'x' and 'y': See (optional) */ - tson::Grid m_grid; /*! 'grid': This element is only used in case of isometric orientation, and determines - how tile overlays for terrain and collision information are rendered. */ - - //v1.2.0-stuff - tson::ObjectAlignment m_objectAlignment{tson::ObjectAlignment::Unspecified}; /*! 'objectalignment': Alignment to use for tile objects. Tiled 1.4.*/ - tson::Map * m_map; /*! The map who owns this tileset */ - }; - - /*! - * A shortcut for getting a property. Alternative to getProperties().getValue("") - * @tparam T The template value - * @param name Name of the property - * @return The actual value, if it exists. Otherwise: The default value of the type. - */ - template - T tson::Tileset::get(const std::string &name) - { - return m_properties.getValue(name); - } -} - -tson::Tileset::Tileset(IJson &json, tson::Map *map) -{ - parse(json, map); -} - -bool tson::Tileset::parse(IJson &json, tson::Map *map) -{ - m_map = map; - bool allFound = true; - - if(json.count("columns") > 0) m_columns = json["columns"].get(); else allFound = false; - if(json.count("firstgid") > 0) m_firstgid = json["firstgid"].get(); else allFound = false; - - if(json.count("image") > 0) m_image = fs::path(json["image"].get()); else allFound = false; - - if(json.count("margin") > 0) m_margin = json["margin"].get(); else allFound = false; - if(json.count("name") > 0) m_name = json["name"].get(); else allFound = false; - if(json.count("spacing") > 0) m_spacing = json["spacing"].get(); else allFound = false; - if(json.count("tilecount") > 0) m_tileCount = json["tilecount"].get(); else allFound = false; - if(json.count("transparentcolor") > 0) m_transparentColor = tson::Colori(json["transparentcolor"].get()); //Optional - if(json.count("type") > 0) m_type = json["type"].get(); - if(json.count("grid") > 0) m_grid = tson::Grid(json["grid"]); - - if(json.count("imagewidth") > 0 && json.count("imageheight") > 0) - m_imageSize = {json["imagewidth"].get(), json["imageheight"].get()}; else allFound = false; - if(json.count("tilewidth") > 0 && json.count("tileheight") > 0) - m_tileSize = {json["tilewidth"].get(), json["tileheight"].get()}; else allFound = false; - if(json.count("tileoffset") > 0) - m_tileOffset = {json["tileoffset"]["x"].get(), json["tileoffset"]["y"].get()}; - - //More advanced data - if(json.count("wangsets") > 0 && json["wangsets"].isArray()) - { - auto &wangsets = json.array("wangsets"); - std::for_each(wangsets.begin(), wangsets.end(), [&](std::unique_ptr &item) { m_wangsets.emplace_back(*item); }); - } - if(json.count("tiles") > 0 && json["tiles"].isArray()) - { - auto &tiles = json.array("tiles"); - std::for_each(tiles.begin(), tiles.end(), [&](std::unique_ptr &item) { m_tiles.emplace_back(*item, this, m_map); }); - } - if(json.count("terrains") > 0 && json["terrains"].isArray()) - { - auto &terrains = json.array("terrains"); - std::for_each(terrains.begin(), terrains.end(), [&](std::unique_ptr &item) { m_terrains.emplace_back(*item); }); - } - - if(json.count("properties") > 0 && json["properties"].isArray()) - { - auto &properties = json.array("properties"); - std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr &item) { m_properties.add(*item); }); - } - - if(json.count("objectalignment") > 0) - { - std::string alignment = json["objectalignment"].get(); - m_objectAlignment = StringToAlignment(alignment); - } - - generateMissingTiles(); - - return allFound; -} - -/*! - * 'columns': The number of tile columns in the tileset - * @return - */ -int tson::Tileset::getColumns() const -{ - return m_columns; -} - -/*! - * 'firstgid': GID corresponding to the first tile in the set - * @return - */ -int tson::Tileset::getFirstgid() const -{ - return m_firstgid; -} - -/*! - * 'image': Image used for tiles in this set - * @return - */ - -const fs::path &tson::Tileset::getImagePath() const { return m_image; } - -/*! - * x = 'imagewidth' and y = 'imageheight': in pixels - * @return - */ -const tson::Vector2i &tson::Tileset::getImageSize() const -{ - return m_imageSize; -} - -/*! - * 'margin': Buffer between image edge and first tile (pixels) - * @return - */ -int tson::Tileset::getMargin() const -{ - return m_margin; -} - -/*! - * 'name': Name given to this tileset - * @return - */ -const std::string &tson::Tileset::getName() const -{ - return m_name; -} - -/*! - * 'spacing': Spacing between adjacent tiles in image (pixels) - * @return - */ -int tson::Tileset::getSpacing() const -{ - return m_spacing; -} - -/*! - * 'tilecount': The number of tiles in this tileset - * @return - */ -int tson::Tileset::getTileCount() const -{ - return m_tileCount; -} - -/*! - * x = 'tilewidth' and y = 'tileheight': Maximum size of tiles in this set - * @return - */ -const tson::Vector2i &tson::Tileset::getTileSize() const -{ - return m_tileSize; -} - -/*! - * 'transparentcolor': Color object created by hex-formatted color (#RRGGBB) (optional) - * @return - */ -const tson::Colori &tson::Tileset::getTransparentColor() const -{ - return m_transparentColor; -} - -/*! - * 'type': tileset (for tileset files, since 1.0) - * @return - */ -const std::string &tson::Tileset::getType() const -{ - return m_type; -} - -/*! - * 'image': Image used for tiles in this set - * @return - */ - -const fs::path &tson::Tileset::getImage() const { return m_image; } - -/*! - * 'tiles': Array of Tiles (optional) - * @return - */ -std::vector &tson::Tileset::getTiles() -{ - return m_tiles; -} - -/*! - * 'wangsets':Array of Wang sets (since Tiled 1.1.5) - * @return - */ -const std::vector &tson::Tileset::getWangsets() const -{ - return m_wangsets; -} - -/*! - * 'properties': A list of properties (name, value, type). - * @return - */ -tson::PropertyCollection &tson::Tileset::getProperties() -{ - return m_properties; -} - -/*! - * 'terrains': Array of Terrains (optional) - * @return - */ -const std::vector &tson::Tileset::getTerrains() const -{ - return m_terrains; -} - -/*! - * 'x' and 'y': See (optional) - * @return - */ -const tson::Vector2i &tson::Tileset::getTileOffset() const -{ - return m_tileOffset; -} - -/*! - * 'grid': This element is only used in case of isometric orientation, and determines - * how tile overlays for terrain and collision information are rendered. - * @return - */ -const tson::Grid &tson::Tileset::getGrid() const -{ - return m_grid; -} - -/*! - * Gets a tile by ID (Tiled ID + 1) - * @param id The ID of the tile stored in Tiled map + 1. Example: If ID was stored in Tiled map as 0, the corresponding value in Tileson is 1. - * This is to make sure the IDs of tiles matches their references in containers. - * @return A pointer to the Tile if found. nullptr otherwise. - */ -tson::Tile *tson::Tileset::getTile(int id) -{ - auto result = std::find_if(m_tiles.begin(), m_tiles.end(), [&](const tson::Tile & item) { return item.getId() == id;}); - if(result == m_tiles.end()) - return nullptr; - - return &result.operator*(); -} - -/*! - * Get an existing Terrain object by name - * @param name - * @return A pointer to the Terrain if found. nullptr otherwise. - */ -tson::Terrain *tson::Tileset::getTerrain(const std::string &name) -{ - auto result = std::find_if(m_terrains.begin(), m_terrains.end(), [&](const tson::Terrain & item) { return item.getName() == name;}); - if(result == m_terrains.end()) - return nullptr; - - return &result.operator*(); -} - -/*! - * Shortcut for getting a property object. Alternative to getProperties().getProperty(""); - * @param name Name of the property - * @return - */ -tson::Property *tson::Tileset::getProp(const std::string &name) -{ - if(m_properties.hasProperty(name)) - return m_properties.getProperty(name); - - return nullptr; -} - -/*! - * Tiled only has tiles with a property stored in the map. This function makes sure even the ones with no properties will exist. - */ -void tson::Tileset::generateMissingTiles() -{ - std::vector tileIds; - for(auto &tile : m_tiles) - tileIds.push_back(tile.getId()); - - for(uint32_t i = m_firstgid; i < m_firstgid + m_tileCount; ++i) - { - if(std::count(tileIds.begin(), tileIds.end(), i) == 0) - { - m_tiles.emplace_back(Tile(i, this, m_map)); - } - } -} - -/*! - * Used for getting the tson::Map who is the parent of this Tileset. - * @return a pointer to the tson::Map where this tileset is contained. - */ -tson::Map *tson::Tileset::getMap() const -{ - return m_map; -} - -/*! - * - * @param str The string you want to convert - * @return Alignment enum based on the string from the input. - */ -tson::ObjectAlignment tson::Tileset::StringToAlignment(std::string_view str) -{ - if(str == "unspecified") return tson::ObjectAlignment::Unspecified; - else if(str == "topleft") return tson::ObjectAlignment::TopLeft; - else if(str == "top") return tson::ObjectAlignment::Top; - else if(str == "topright") return tson::ObjectAlignment::TopRight; - else if(str == "left") return tson::ObjectAlignment::Left; - else if(str == "center") return tson::ObjectAlignment::Center; - else if(str == "right") return tson::ObjectAlignment::Right; - else if(str == "bottomleft") return tson::ObjectAlignment::BottomLeft; - else if(str == "bottom") return tson::ObjectAlignment::Bottom; - else if(str == "bottomright") return tson::ObjectAlignment::BottomRight; - else - return tson::ObjectAlignment::Unspecified; -} - -tson::ObjectAlignment tson::Tileset::getObjectAlignment() const -{ - return m_objectAlignment; -} - -#endif //TILESON_TILESET_HPP -/*** End of inlined file: Tileset.hpp ***/ - -namespace tson -{ - class Map - { - public: - inline Map() = default; - inline Map(ParseStatus status, std::string description); - inline explicit Map(IJson &json, tson::DecompressorContainer *decompressors); - inline bool parse(IJson &json, tson::DecompressorContainer *decompressors); - - [[nodiscard]] inline const Colori &getBackgroundColor() const; - [[nodiscard]] inline const Vector2i &getSize() const; - [[nodiscard]] inline int getHexsideLength() const; - [[nodiscard]] inline bool isInfinite() const; - [[nodiscard]] inline int getNextLayerId() const; - [[nodiscard]] inline int getNextObjectId() const; - [[nodiscard]] inline const std::string &getOrientation() const; - [[nodiscard]] inline const std::string &getRenderOrder() const; - [[nodiscard]] inline const std::string &getStaggerAxis() const; - [[nodiscard]] inline const std::string &getStaggerIndex() const; - [[nodiscard]] inline const std::string &getTiledVersion() const; - [[nodiscard]] inline const Vector2i &getTileSize() const; - [[nodiscard]] inline const std::string &getType() const; - [[nodiscard]] inline int getVersion() const; - - [[nodiscard]] inline std::vector &getLayers(); - [[nodiscard]] inline PropertyCollection &getProperties(); - [[nodiscard]] inline std::vector &getTilesets(); - - [[nodiscard]] inline ParseStatus getStatus() const; - [[nodiscard]] inline const std::string &getStatusMessage() const; - [[nodiscard]] inline const std::map &getTileMap() const; - - inline Layer * getLayer(const std::string &name); - inline Tileset * getTileset(const std::string &name); - - template - inline T get(const std::string &name); - inline tson::Property * getProp(const std::string &name); - - //v1.2.0 - [[nodiscard]] inline int getCompressionLevel() const; - inline DecompressorContainer *getDecompressors(); - inline Tileset * getTilesetByGid(uint32_t gid); - - private: - inline void createTilesetData(IJson &json); - inline void processData(); - - Colori m_backgroundColor; /*! 'backgroundcolor': Hex-formatted color (#RRGGBB or #AARRGGBB) (optional)*/; - Vector2i m_size; /*! 'width' and 'height' of a Tiled map */ - int m_hexsideLength {}; /*! 'hexsidelength': Length of the side of a hex tile in pixels */ - bool m_isInfinite {}; /*! 'infinite': Whether the map has infinite dimensions*/ - std::vector m_layers; /*! 'layers': Array of layers. group on */ - int m_nextLayerId {}; /*! 'nextlayerid': Auto-increments for each layer */ - int m_nextObjectId {}; /*! 'nextobjectid': Auto-increments for each placed object */ - std::string m_orientation; /*! 'orientation': orthogonal, isometric, staggered or hexagonal */ - tson::PropertyCollection m_properties; /*! 'properties': A list of properties (name, value, type). */ - std::string m_renderOrder; /*! 'renderorder': Rendering direction (orthogonal maps only) */ - std::string m_staggerAxis; /*! 'staggeraxis': x or y (staggered / hexagonal maps only) */ - std::string m_staggerIndex; /*! 'staggerindex': odd or even (staggered / hexagonal maps only) */ - std::string m_tiledVersion; /*! 'tiledversion': The Tiled version used to save the file */ - Vector2i m_tileSize; /*! 'tilewidth': and 'tileheight' of a map */ - std::vector m_tilesets; /*! 'tilesets': Array of Tilesets */ - std::string m_type; /*! 'type': map (since 1.0) */ - int m_version{}; /*! 'version': The JSON format version*/ - - ParseStatus m_status {ParseStatus::OK}; - std::string m_statusMessage {"OK"}; - - std::map m_tileMap; /*! key: Tile ID. Value: Pointer to Tile*/ - - //v1.2.0 - int m_compressionLevel {-1}; /*! 'compressionlevel': The compression level to use for tile layer - * data (defaults to -1, which means to use the algorithm default) - * Introduced in Tiled 1.3*/ - tson::DecompressorContainer * m_decompressors; - std::map m_flaggedTileMap; /*! key: Tile ID. Value: Tile*/ - }; - - /*! - * A shortcut for getting a property. Alternative to getProperties().getValue("") - * @tparam T The template value - * @param name Name of the property - * @return The actual value, if it exists. Otherwise: The default value of the type. - */ - template - T tson::Map::get(const std::string &name) - { - return m_properties.getValue(name); - } -} - -/*! - * When errors have happened before the map starts parsing, just keep the statuses - * @param status The status - * @param description Description of the status - */ -tson::Map::Map(tson::ParseStatus status, std::string description) : m_status {status}, m_statusMessage { std::move(description) } -{ - -} - -/*! - * Parses a json of a Tiled map. - * @param json A json object with the format of Map - * @return true if all mandatory fields was found. false otherwise. - */ -tson::Map::Map(IJson &json, tson::DecompressorContainer *decompressors) -{ - parse(json, decompressors); -} - -/*! - * Parses a json of a Tiled map. - * @param json A json object with the format of Map - * @return true if all mandatory fields was found. false otherwise. - */ -bool tson::Map::parse(IJson &json, tson::DecompressorContainer *decompressors) -{ - m_decompressors = decompressors; - - bool allFound = true; - if(json.count("compressionlevel") > 0) - m_compressionLevel = json["compressionlevel"].get(); //Tiled 1.3 - Optional - - if(json.count("backgroundcolor") > 0) m_backgroundColor = Colori(json["backgroundcolor"].get()); //Optional - if(json.count("width") > 0 && json.count("height") > 0 ) - m_size = {json["width"].get(), json["height"].get()}; else allFound = false; - if(json.count("hexsidelength") > 0) m_hexsideLength = json["hexsidelength"].get(); //Optional - if(json.count("infinite") > 0) m_isInfinite = json["infinite"].get(); //Optional - if(json.count("nextlayerid") > 0) m_nextLayerId = json["nextlayerid"].get(); //Optional - if(json.count("nextobjectid") > 0) m_nextObjectId = json["nextobjectid"].get(); else allFound = false; - if(json.count("orientation") > 0) m_orientation = json["orientation"].get(); else allFound = false; - if(json.count("renderorder") > 0) m_renderOrder = json["renderorder"].get(); //Optional - if(json.count("staggeraxis") > 0) m_staggerAxis = json["staggeraxis"].get(); //Optional - if(json.count("staggerindex") > 0) m_staggerIndex = json["staggerindex"].get(); //Optional - if(json.count("tiledversion") > 0) m_tiledVersion = json["tiledversion"].get(); else allFound = false; - if(json.count("tilewidth") > 0 && json.count("tileheight") > 0 ) - m_tileSize = {json["tilewidth"].get(), json["tileheight"].get()}; else allFound = false; - if(json.count("type") > 0) m_type = json["type"].get(); //Optional - if(json.count("version") > 0) m_version = json["version"].get(); else allFound = false; - - //More advanced data - if(json.count("layers") > 0 && json["layers"].isArray()) - { - auto &array = json.array("layers"); - std::for_each(array.begin(), array.end(), [&](std::unique_ptr &item) - { - m_layers.emplace_back(*item, this); - }); - } - - if(json.count("properties") > 0 && json["properties"].isArray()) - { - auto &array = json.array("properties"); - std::for_each(array.begin(), array.end(), [&](std::unique_ptr &item) - { - m_properties.add(*item); - }); - } - createTilesetData(json); - processData(); - - return allFound; -} - -/*! - * Tileset data must be created in two steps to prevent malformed tson::Tileset pointers inside tson::Tile - */ -void tson::Map::createTilesetData(IJson &json) -{ - if(json.count("tilesets") > 0 && json["tilesets"].isArray()) - { - //First created tileset objects - auto &tilesets = json.array("tilesets"); - std::for_each(tilesets.begin(), tilesets.end(), [&](std::unique_ptr &item) - { - m_tilesets.emplace_back(); - }); - - int i = 0; - //Then do the parsing - std::for_each(tilesets.begin(), tilesets.end(), [&](std::unique_ptr &item) - { - m_tilesets[i].parse(*item, this); - ++i; - }); - } -} - -/*! - * Processes the parsed data and uses the data to create helpful objects, like tile maps. - */ -void tson::Map::processData() -{ - m_tileMap.clear(); - for(auto &tileset : m_tilesets) - { - std::for_each(tileset.getTiles().begin(), tileset.getTiles().end(), [&](tson::Tile &tile) { m_tileMap[tile.getGid()] = &tile; }); - } - std::for_each(m_layers.begin(), m_layers.end(), [&](tson::Layer &layer) - { - layer.assignTileMap(&m_tileMap); - layer.createTileData(m_size, m_isInfinite); - const std::set &flaggedTiles = layer.getUniqueFlaggedTiles(); - for(uint32_t ftile : flaggedTiles) - { - tson::Tile tile {ftile, layer.getMap()}; - if(m_tileMap.count(tile.getGid())) - { - tson::Tile *originalTile = m_tileMap[tile.getGid()]; - tile.addTilesetAndPerformCalculations(originalTile->getTileset()); - tile.setProperties(originalTile->getProperties()); - m_flaggedTileMap[ftile] = tile; - m_tileMap[ftile] = &m_flaggedTileMap[ftile]; - } - } - layer.resolveFlaggedTiles(); - }); -} - -/*! - * 'backgroundcolor': Color created from a hex-formatted color string (#RRGGBB or #AARRGGBB) (optional) - * @return string as color - */ -const tson::Colori &tson::Map::getBackgroundColor() const -{ - return m_backgroundColor; -} - -/*! - * 'width' and 'height' of a Tiled map - * @return - */ -const tson::Vector2 &tson::Map::getSize() const -{ - return m_size; -} - -/*! - * 'hexsidelength': Length of the side of a hex tile in pixels - * @return - */ -int tson::Map::getHexsideLength() const -{ - return m_hexsideLength; -} - -/*! - * 'infinite': Whether the map has infinite dimensions - * @return - */ -bool tson::Map::isInfinite() const -{ - return m_isInfinite; -} - -/*! - * 'nextlayerid': Auto-increments for each layer - * @return - */ -int tson::Map::getNextLayerId() const -{ - return m_nextLayerId; -} - -/*! - * 'nextobjectid': Auto-increments for each placed object - * @return - */ -int tson::Map::getNextObjectId() const -{ - return m_nextObjectId; -} - -/*! - * 'orientation': orthogonal, isometric, staggered or hexagonal - * @return - */ -const std::string &tson::Map::getOrientation() const -{ - return m_orientation; -} - -/*! - * 'renderorder': Rendering direction (orthogonal maps only) - * @return - */ -const std::string &tson::Map::getRenderOrder() const -{ - return m_renderOrder; -} - -/*! - * 'staggeraxis': x or y (staggered / hexagonal maps only) - * @return - */ -const std::string &tson::Map::getStaggerAxis() const -{ - return m_staggerAxis; -} - -/*! - * 'staggerindex': odd or even (staggered / hexagonal maps only) - * @return - */ -const std::string &tson::Map::getStaggerIndex() const -{ - return m_staggerIndex; -} - -/*! - * 'tiledversion': The Tiled version used to save the file - * @return - */ -const std::string &tson::Map::getTiledVersion() const -{ - return m_tiledVersion; -} - -/*! - * 'tilewidth': and 'tileheight' of a map - * @return - */ -const tson::Vector2 &tson::Map::getTileSize() const -{ - return m_tileSize; -} - -/*! - * 'type': map (since 1.0) - * @return - */ -const std::string &tson::Map::getType() const -{ - return m_type; -} - -/*! - * 'version': The JSON format version - * @return - */ -int tson::Map::getVersion() const -{ - return m_version; -} - -/*! - * 'layers': Array of layers. group on - * @return - */ -std::vector &tson::Map::getLayers() -{ - return m_layers; -} - -/*! - * 'properties': A list of properties (name, value, type). - * @return - */ -tson::PropertyCollection &tson::Map::getProperties() -{ - return m_properties; -} - -/*! - * 'tilesets': Array of Tilesets - * @return - */ -std::vector &tson::Map::getTilesets() -{ - return m_tilesets; -} - -tson::Layer *tson::Map::getLayer(const std::string &name) -{ - auto result = std::find_if(m_layers.begin(), m_layers.end(), [&](const tson::Layer &item) { return item.getName() == name; }); - if(result == m_layers.end()) - return nullptr; - - return &result.operator*(); -} - -/*! - * Gets a tileset by name - * - * @param name Name of the tileset - * @return tileset with the matching name - */ -tson::Tileset *tson::Map::getTileset(const std::string &name) -{ - auto result = std::find_if(m_tilesets.begin(), m_tilesets.end(), [&](const tson::Tileset &item) {return item.getName() == name; }); - if(result == m_tilesets.end()) - return nullptr; - - return &result.operator*(); -} - -/*! - * Gets a tileset by gid (graphical ID of a tile). These are always unique, no matter how many tilesets you have - * - * @param gid Graphical ID of a tile - * @return tileset related to the actual gid - */ -tson::Tileset *tson::Map::getTilesetByGid(uint32_t gid) -{ - auto result = std::find_if(m_tilesets.begin(), m_tilesets.end(), [&](const tson::Tileset &tileset) - { - int firstId = tileset.getFirstgid(); //First tile id of the tileset - int lastId = (firstId + tileset.getTileCount()) - 1; - - return (gid >= firstId && gid <= lastId); - }); - if(result == m_tilesets.end()) - return nullptr; - - return &result.operator*(); -} - -/*! - * Shortcut for getting a property object. Alternative to getProperties().getProperty(""); - * @param name Name of the property - * @return - */ -tson::Property *tson::Map::getProp(const std::string &name) -{ - if(m_properties.hasProperty(name)) - return m_properties.getProperty(name); - return nullptr; -} - -tson::ParseStatus tson::Map::getStatus() const -{ - return m_status; -} - -const std::string &tson::Map::getStatusMessage() const -{ - return m_statusMessage; -} - -/*! - * Get a tile map with pointers to every existing tile. - * @return - */ -const std::map &tson::Map::getTileMap() const -{ - return m_tileMap; -} - -tson::DecompressorContainer *tson::Map::getDecompressors() -{ - return m_decompressors; -} - -/*! - * 'compressionlevel': The compression level to use for tile layer data (defaults to -1, which means to use the algorithm default) - * - * @return The compression level - */ -int tson::Map::getCompressionLevel() const -{ - return m_compressionLevel; -} - -#endif //TILESON_MAP_HPP - -/*** End of inlined file: Map.hpp ***/ - - -/*** Start of inlined file: Project.hpp ***/ -// -// Created by robin on 01.08.2020. -// - -#ifndef TILESON_PROJECT_HPP -#define TILESON_PROJECT_HPP - -#include -#include -#include - -/*** Start of inlined file: World.hpp ***/ -// -// Created by robin on 01.08.2020. -// - -#ifndef TILESON_WORLD_HPP -#define TILESON_WORLD_HPP - - -/*** Start of inlined file: WorldMapData.hpp ***/ -// -// Created by robin on 01.08.2020. -// - -#ifndef TILESON_WORLDMAPDATA_HPP -#define TILESON_WORLDMAPDATA_HPP - -namespace tson -{ - class WorldMapData - { - public: - inline WorldMapData(const fs::path &folder_, IJson &json); - inline void parse(const fs::path &folder_, IJson &json); - //inline WorldMapData(fs::path folder_, std::string fileName_) : folder {std::move(folder_)}, fileName {fileName_} - //{ - // path = folder / fileName; - //} - - fs::path folder; - fs::path path; - std::string fileName; - tson::Vector2i size; - tson::Vector2i position; - }; - - WorldMapData::WorldMapData(const fs::path &folder_, IJson &json) - { - parse(folder_, json); - } - - void WorldMapData::parse(const fs::path &folder_, IJson &json) - { - folder = folder_; - if(json.count("fileName") > 0) fileName = json["fileName"].get(); - if(json.count("height") > 0) size = {json["width"].get(), json["height"].get()}; - if(json.count("x") > 0) position = {json["x"].get(), json["y"].get()}; - - path = (!fileName.empty()) ? folder / fileName : folder; - } -} - -#endif //TILESON_WORLDMAPDATA_HPP -/*** End of inlined file: WorldMapData.hpp ***/ - -#include -namespace tson -{ - class Tileson; - class World - { - public: - #ifdef JSON11_IS_DEFINED - inline explicit World(std::unique_ptr jsonParser = std::make_unique()) : m_json {std::move(jsonParser)} - { - } - - inline explicit World(const fs::path &path, std::unique_ptr jsonParser = std::make_unique()); - #else - inline explicit World(std::unique_ptr jsonParser) : m_json {std::move(jsonParser)} - { - } - - inline explicit World(const fs::path &path, std::unique_ptr jsonParser); - #endif - inline bool parse(const fs::path &path); - inline int loadMaps(tson::Tileson *parser); //tileson_forward.hpp - inline bool contains(std::string_view filename); - inline const WorldMapData *get(std::string_view filename) const; - - [[nodiscard]] inline const fs::path &getPath() const; - [[nodiscard]] inline const fs::path &getFolder() const; - [[nodiscard]] inline const std::vector &getMapData() const; - [[nodiscard]] inline bool onlyShowAdjacentMaps() const; - [[nodiscard]] inline const std::string &getType() const; - [[nodiscard]] inline const std::vector> &getMaps() const; - - private: - inline void parseJson(IJson &json); - - std::unique_ptr m_json = nullptr; - fs::path m_path; - fs::path m_folder; - std::vector m_mapData; - std::vector> m_maps; - bool m_onlyShowAdjacentMaps; - std::string m_type; - }; - - World::World(const fs::path &path, std::unique_ptr jsonParser) : m_json {std::move(jsonParser)} - { - parse(path); - } - - bool World::parse(const fs::path &path) - { - m_path = path; - m_folder = m_path.parent_path(); - - if(!m_json->parse(path)) - return false; - - parseJson(*m_json); - return true; - } - - const fs::path &World::getPath() const - { - return m_path; - } - - const std::vector &World::getMapData() const - { - return m_mapData; - } - - bool World::onlyShowAdjacentMaps() const - { - return m_onlyShowAdjacentMaps; - } - - const std::string &World::getType() const - { - return m_type; - } - - void World::parseJson(IJson &json) - { - if(json.count("onlyShowAdjacentMaps") > 0) m_onlyShowAdjacentMaps = json["onlyShowAdjacentMaps"].get(); - if(json.count("type") > 0) m_type = json["type"].get(); - - if(json["maps"].isArray()) - { - auto &maps = json.array("maps"); - std::for_each(maps.begin(), maps.end(), [&](std::unique_ptr &item) { m_mapData.emplace_back(m_folder, *item); }); - } - } - - const fs::path &World::getFolder() const - { - return m_folder; - } - - /*! - * Check if there is WorldMapData in the world that contains the current filename. - * Filename = . - * @param filename - * @return - */ - bool World::contains(std::string_view filename) - { - //Note: might be moved to std::ranges from C++20. - return std::any_of(m_mapData.begin(), m_mapData.end(), [&](const auto &item) { return item.fileName == filename; }); - } - - /*! - * Get a map by its filename - * @param filename Filename (including extension) - (example: file.json) - * @return pointer to WorldMapData or nullptr if not exists - */ - const WorldMapData * World::get(std::string_view filename) const - { - auto iter = std::find_if(m_mapData.begin(), m_mapData.end(), [&](const auto &item) { return item.fileName == filename; }); - return (iter == m_mapData.end()) ? nullptr : iter.operator->(); - } - - /*! - * Get all maps that have been loaded by loadMaps(). - * NOTE: This is untested, and was a last second addition to Tileson 1.2.0, as I had forgot about the loadMaps() functionality (also untested) - * If you find anything malfunctioning - please report. - * @return All maps loaded by loadMaps() - */ - const std::vector> &World::getMaps() const - { - return m_maps; - } - -} - -#endif //TILESON_WORLD_HPP -/*** End of inlined file: World.hpp ***/ - - - -/*** Start of inlined file: ProjectFolder.hpp ***/ -// -// Created by robin on 01.08.2020. -// - -#ifndef TILESON_PROJECTFOLDER_HPP -#define TILESON_PROJECTFOLDER_HPP - -namespace tson -{ - class ProjectFolder - { - public: - inline ProjectFolder(const fs::path &path); - - inline const fs::path &getPath() const; - inline bool hasWorldFile() const; - inline const std::vector &getSubFolders() const; - inline const std::vector &getFiles() const; - inline const World &getWorld() const; - - private: - inline void loadData(); - fs::path m_path; - bool m_hasWorldFile; - tson::World m_world; - std::vector m_subFolders; - std::vector m_files; - - }; - - ProjectFolder::ProjectFolder(const fs::path &path) : m_path {path} - { - loadData(); - } - - void ProjectFolder::loadData() - { - m_hasWorldFile = false; - m_subFolders.clear(); - m_files.clear(); - //Search and see if there is a World file .world file - fs::path worldPath; - for (const auto & entry : fs::directory_iterator(m_path)) - { - if(fs::is_regular_file(entry.path())) - { - if(entry.path().extension() == ".world") - { - m_hasWorldFile = true; - worldPath = entry.path(); - } - } - } - - if(m_hasWorldFile) - m_world.parse(worldPath); - - for (const auto & entry : fs::directory_iterator(m_path)) - { - if (fs::is_directory(entry.path())) - m_subFolders.emplace_back(entry.path());//.loadData(); - loadData() is called in the constructor, so don't call again. - else if (fs::is_regular_file(entry.path())) - { - if(m_hasWorldFile && m_world.contains(entry.path().filename().u8string())) - m_files.emplace_back(entry.path()); - else if(!m_hasWorldFile) - m_files.emplace_back(entry.path()); - } - } - - } - - const fs::path &ProjectFolder::getPath() const - { - return m_path; - } - - bool ProjectFolder::hasWorldFile() const - { - return m_hasWorldFile; - } - - const std::vector &ProjectFolder::getSubFolders() const - { - return m_subFolders; - } - - const std::vector &ProjectFolder::getFiles() const - { - return m_files; - } - - /*! - * Only gives useful data if hasWorldFile() is true! - * @return - */ - const World &ProjectFolder::getWorld() const - { - return m_world; - } -} - -#endif //TILESON_PROJECTFOLDER_HPP -/*** End of inlined file: ProjectFolder.hpp ***/ - - -/*** Start of inlined file: ProjectData.hpp ***/ -// -// Created by robin on 01.08.2020. -// - -#ifndef TILESON_PROJECTDATA_HPP -#define TILESON_PROJECTDATA_HPP - -namespace tson -{ - class ProjectData - { - public: - ProjectData() = default; - std::string automappingRulesFile; - std::vector commands; - std::string extensionsPath; - std::vector folders; - std::string objectTypesFile; - - //Tileson specific - fs::path basePath; - std::vector folderPaths; - }; -} - -#endif //TILESON_PROJECTDATA_HPP -/*** End of inlined file: ProjectData.hpp ***/ - -namespace tson -{ - class Project - { - public: - #ifdef JSON11_IS_DEFINED - inline explicit Project(std::unique_ptr jsonParser = std::make_unique()) : m_json {std::move(jsonParser)} - { - - } - inline explicit Project(const fs::path &path, std::unique_ptr jsonParser = std::make_unique()); - #else - inline explicit Project(std::unique_ptr jsonParser) : m_json {std::move(jsonParser)} - { - - } - inline explicit Project(const fs::path &path, std::unique_ptr jsonParser); - #endif - inline bool parse(const fs::path &path); - - [[nodiscard]] inline const ProjectData &getData() const; - [[nodiscard]] inline const fs::path &getPath() const; - [[nodiscard]] inline const std::vector &getFolders() const; - - private: - inline void parseJson(IJson &json); - fs::path m_path; - std::vector m_folders; - ProjectData m_data; - std::unique_ptr m_json = nullptr; - }; - - Project::Project(const fs::path &path, std::unique_ptr jsonParser) : m_json {std::move(jsonParser)} - { - parse(path); - } - - bool Project::parse(const fs::path &path) - { - m_path = path; - std::ifstream i(m_path.u8string()); - - try - { - if(!m_json->parse(path)) - return false; - } - catch(const std::exception &error) - { - std::string message = "Parse error: "; - message += std::string(error.what()); - message += std::string("\n"); - return false; - } - parseJson(*m_json); - return true; - } - - const ProjectData &Project::getData() const - { - return m_data; - } - - void Project::parseJson(IJson &json) - { - m_data.basePath = m_path.parent_path(); //The directory of the project file - - if(json.count("automappingRulesFile") > 0) m_data.automappingRulesFile = json["automappingRulesFile"].get(); - if(json.count("commands") > 0) - { - m_data.commands.clear(); - auto &commands = json.array("commands"); - std::for_each(commands.begin(), commands.end(), [&](std::unique_ptr &item) - { - m_data.commands.emplace_back(item->get()); - }); - } - if(json.count("extensionsPath") > 0) m_data.extensionsPath = json["extensionsPath"].get(); - if(json.count("folders") > 0) - { - m_data.folders.clear(); - m_data.folderPaths.clear(); - auto &folders = json.array("folders"); - std::for_each(folders.begin(), folders.end(), [&](std::unique_ptr &item) - { - std::string folder = item->get(); - m_data.folders.emplace_back(folder); - m_data.folderPaths.emplace_back(m_data.basePath / folder); - m_folders.emplace_back(m_data.basePath / folder); - }); - } - if(json.count("objectTypesFile") > 0) m_data.objectTypesFile = json["objectTypesFile"].get(); - - } - - const fs::path &Project::getPath() const - { - return m_path; - } - - const std::vector &Project::getFolders() const - { - return m_folders; - } - -} - -#endif //TILESON_PROJECT_HPP - -/*** End of inlined file: Project.hpp ***/ - -namespace tson -{ - class Tileson - { - public: - #ifdef JSON11_IS_DEFINED - inline explicit Tileson(std::unique_ptr jsonParser = std::make_unique(), bool includeBase64Decoder = true); - #else - inline explicit Tileson(std::unique_ptr jsonParser, bool includeBase64Decoder = true); - #endif - - inline std::unique_ptr parse(const fs::path &path, std::unique_ptr, std::vector>> decompressor = nullptr); - inline std::unique_ptr parse(const void * data, size_t size, std::unique_ptr, std::vector>> decompressor = nullptr); - inline tson::DecompressorContainer *decompressors(); - - private: - inline std::unique_ptr parseJson(); - std::unique_ptr m_json; - tson::DecompressorContainer m_decompressors; - }; -} - -/*! - * - * @param includeBase64Decoder Includes the base64-decoder from "Base64Decompressor.hpp" if true. - * Otherwise no other decompressors/decoders than whatever the user itself have added will be used. - */ -tson::Tileson::Tileson(std::unique_ptr jsonParser, bool includeBase64Decoder) : m_json {std::move(jsonParser)} -{ - if(includeBase64Decoder) - m_decompressors.add(); -} - -/*! - * Parses Tiled json map data by file - * @param path path to file - * @return parsed data as Map - */ -std::unique_ptr tson::Tileson::parse(const fs::path &path, std::unique_ptr, std::vector>> decompressor) -{ - - bool result = false; - - if(decompressor != nullptr) - { - std::vector decompressed = decompressor->decompressFile(path); - result = (decompressed.empty()) ? false : true; - if(!result) - return std::make_unique(tson::ParseStatus::DecompressionError, "Error during decompression"); - result = m_json->parse(&decompressed[0], decompressed.size()); - if(result) - return std::move(parseJson()); - } - else if(m_json->parse(path)) - { - return std::move(parseJson()); - } - - std::string msg = "File not found: "; - msg += std::string(path.u8string()); - return std::make_unique(tson::ParseStatus::FileNotFound, msg); -} - -/*! - * Parses Tiled json map data by memory - * @param data The data to parse - * @param size The size of the data to parse - * @return parsed data as Map - */ -std::unique_ptr tson::Tileson::parse(const void *data, size_t size, std::unique_ptr, std::vector>> decompressor) -{ - bool result = false; - - if(decompressor != nullptr) - { - std::vector decompressed = decompressor->decompress(data, size); - result = (decompressed.empty()) ? false : true; - if(!result) - return std::make_unique(tson::ParseStatus::DecompressionError, "Error during decompression"); - result = m_json->parse(&decompressed[0], decompressed.size()); - } - else - result = m_json->parse(data, size); - - if(!result) - return std::make_unique(tson::ParseStatus::ParseError, "Memory error"); - - return std::move(parseJson()); -} - -/*! - * Common parsing functionality for doing the json parsing - * @param json Tiled json to parse - * @return parsed data as Map - */ -std::unique_ptr tson::Tileson::parseJson() -{ - std::unique_ptr map = std::make_unique(); - - if(map->parse(*m_json, &m_decompressors)) - return std::move(map); - - return std::make_unique (tson::ParseStatus::MissingData, "Missing map data..."); -} - -/*! - * Gets the decompressor container used when something is either encoded or compressed (regardless: IDecompressor is used as base). - * These are used specifically for tile layers, and are connected by checking the name of the IDecompressor. If the name of a decompressor - * matches with an encoding or a compression, its decompress() function will be used. - * - * @return The container including all decompressors. - */ -tson::DecompressorContainer *tson::Tileson::decompressors() -{ - return &m_decompressors; -} - -#endif //TILESON_TILESON_PARSER_HPP - -/*** End of inlined file: tileson_parser.hpp ***/ - - -/*** Start of inlined file: tileson_forward.hpp ***/ -// -// Created by robin on 25.07.2020. -// - -#ifndef TILESON_TILESON_FORWARD_HPP -#define TILESON_TILESON_FORWARD_HPP -/*! - * T I L E S O N F O R W A R D D E C L A R A T I O N S - * ------------------------------------------------------- - * - * Due to cross-references we have forward declarations that cannot be resolved during the - * implementation, thus the implementations must be done later when the class definition itself is known. - * - * All those forward declarations can be found below. - */ - -// T i l e . h p p -// --------------------- - -/*! - * Really just a shortcut to retrieve the tile size from the map. - * @return TileSize based on the map property for tile size. - */ -const tson::Vector2i tson::Tile::getTileSize() const -{ - if(m_map != nullptr) - return m_map->getTileSize(); - else - return {0,0}; -} - -bool tson::Tile::parseId(IJson &json) -{ - if(json.count("id") > 0) - { - m_id = json["id"].get() + 1; - if (m_tileset != nullptr) - m_gid = m_tileset->getFirstgid() + m_id - 1; - else - m_gid = m_id; - manageFlipFlagsByIdThenRemoveFlags(m_gid); - return true; - } - return false; -} - -/*! - * Uses tson::Tileset and tson::Map data to calculate related values for tson::Tile. - * Added in v1.2.0 - */ -void tson::Tile::performDataCalculations() -{ - if(m_tileset == nullptr || m_map == nullptr) - return; - - int firstId = m_tileset->getFirstgid(); //First tile id of the tileset - int columns = m_tileset->getColumns(); - int rows = m_tileset->getTileCount() / columns; - int lastId = (m_tileset->getFirstgid() + m_tileset->getTileCount()) - 1; - - if (getGid() >= firstId && getGid() <= lastId) - { - int baseTilePosition = ((int)getGid() - firstId); - - int tileModX = (baseTilePosition % columns); - int currentRow = (baseTilePosition / columns); - int offsetX = (tileModX != 0) ? ((tileModX) * m_map->getTileSize().x) : (0 * m_map->getTileSize().x); - int offsetY = (currentRow < rows-1) ? (currentRow * m_map->getTileSize().y) : ((rows-1) * m_map->getTileSize().y); - - m_drawingRect = { offsetX, offsetY, m_map->getTileSize().x, m_map->getTileSize().y }; - } - else - m_drawingRect = {0, 0, 0, 0}; -} - -/*! - * Get the position of the tile in pixels based on the tile data position from the current layer. - * @return The position of the tile in Pixels - */ -const tson::Vector2f tson::Tile::getPosition(const std::tuple &tileDataPos) -{ - return {((float) std::get<0>(tileDataPos)) * m_drawingRect.width, ((float) std::get<1>(tileDataPos)) * m_drawingRect.height}; -} - -// T i l e O b j e c t . h p p -// --------------------- - -/*! - * In cases where the empty constructor is called, this must be called manually - * for this class to make sense - * @param posInTileUnits - * @param tile - */ -void tson::TileObject::initialize(const std::tuple &posInTileUnits, tson::Tile *tile) -{ - m_tile = tile; - m_posInTileUnits = tile->getPositionInTileUnits(posInTileUnits); - m_position = tile->getPosition(posInTileUnits); -} - -const tson::Rect &tson::TileObject::getDrawingRect() const -{ - return m_tile->getDrawingRect(); -} - -// L a y e r . h p p -// ------------------- - -/*! - * Decompresses data if there are matching decompressors - */ -void tson::Layer::decompressData() -{ - - tson::DecompressorContainer *container = m_map->getDecompressors(); - if(container->empty()) - return; - - if(m_encoding.empty() && m_compression.empty()) - return; - - std::string data = m_base64Data; - bool hasBeenDecoded = false; - if(!m_encoding.empty() && container->contains(m_encoding)) - { - data = container->get(m_encoding)->decompress(data); - hasBeenDecoded = true; - } - - if(!m_compression.empty() && container->contains(m_compression)) - { - data = container->get(m_compression)->decompress(data); - } - - if(hasBeenDecoded) - { - std::vector bytes = tson::Tools::Base64DecodedStringToBytes(data); - m_data = tson::Tools::BytesToUnsignedInts(bytes); - } -} - -// W o r l d . h p p -// ------------------ - -/*! - * Loads the actual maps based on the world data. - * @param parser A Tileson object used for parsing the maps of the world. - * @return How many maps who were parsed. Remember to call getStatus() for the actual map to find out if everything went okay. - */ - -int tson::World::loadMaps(tson::Tileson *parser) -{ - m_maps.clear(); - std::for_each(m_mapData.begin(), m_mapData.end(), [&](const tson::WorldMapData &data) - { - if(fs::exists(data.path)) - { - std::unique_ptr map = parser->parse(data.path); - m_maps.push_back(std::move(map)); - } - }); - - return m_maps.size(); -} - -#endif //TILESON_TILESON_FORWARD_HPP - -/*** End of inlined file: tileson_forward.hpp ***/ - -#endif //TILESON_TILESON_H - diff --git a/vendor/tmxlite b/vendor/tmxlite new file mode 160000 index 0000000..796be88 --- /dev/null +++ b/vendor/tmxlite @@ -0,0 +1 @@ +Subproject commit 796be88be0a44cebf355529a4bcb3531e67acee3 -- cgit 1.4.1