Uranus  1.0.1.0
Uranus is a GameEngine written in C++
Loading...
Searching...
No Matches
Tileson.hpp
1
29
30#ifndef TILESON_TILESON_H
31#define TILESON_TILESON_H
32
33
34
36
37/* Copyright (c) 2013 Dropbox, Inc.
38 *
39 * Permission is hereby granted, free of charge, to any person obtaining a copy
40 * of this software and associated documentation files (the "Software"), to deal
41 * in the Software without restriction, including without limitation the rights
42 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43 * copies of the Software, and to permit persons to whom the Software is
44 * furnished to do so, subject to the following conditions:
45 *
46 * The above copyright notice and this permission notice shall be included in
47 * all copies or substantial portions of the Software.
48 *
49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55 * THE SOFTWARE.
56 */
57
58#pragma once
59
60#include <initializer_list>
61#include <map>
62#include <memory>
63#include <string>
64#include <vector>
65
66#define JSON11_IS_DEFINED
67
68#ifdef _MSC_VER
69 #if _MSC_VER <= 1800 // VS 2013
70 #ifndef noexcept
71 #define noexcept throw()
72 #endif
73
74 #ifndef snprintf
75 #define snprintf _snprintf_s
76 #endif
77 #endif
78#endif
79
80namespace json11 {
81
82 enum JsonParse {
83 STANDARD,
84 COMMENTS
85 };
86
87 class JsonValue;
88
89 class Json final {
90 public:
91 // Types
92 enum Type {
93 NUL,
94 NUMBER,
95 BOOL,
96 STRING,
97 ARRAY,
98 OBJECT
99 };
100
101 // Array and object typedefs
102 typedef std::vector<Json> array;
103 typedef std::map<std::string, Json> object;
104
105 // Constructors for the various types of JSON value.
106 inline Json() noexcept; // NUL
107 inline Json(std::nullptr_t) noexcept; // NUL
108 inline Json(double value); // NUMBER
109 inline Json(int value); // NUMBER
110 inline Json(bool value); // BOOL
111 inline Json(const std::string &value); // STRING
112 inline Json(std::string &&value); // STRING
113 inline Json(const char *value); // STRING
114 inline Json(const array &values); // ARRAY
115 inline Json(array &&values); // ARRAY
116 inline Json(const object &values); // OBJECT
117 inline Json(object &&values); // OBJECT
118
119 // Implicit constructor: anything with a to_json() function.
120 template<class T, class = decltype(&T::to_json)>
121 inline Json(const T &t) : Json(t.to_json())
122 {}
123
124 // Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
125 template<class M, typename std::enable_if<std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value &&
126 std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value,
127 int>::type = 0>
128 inline Json(const M &m) : Json(object(m.begin(), m.end()))
129 {}
130
131 // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
132 template<class V, typename std::enable_if<std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value, int>::type = 0>
133 inline Json(const V &v) : Json(array(v.begin(), v.end()))
134 {}
135
136 // This prevents Json(some_pointer) from accidentally producing a bool. Use
137 // Json(bool(some_pointer)) if that behavior is desired.
138 Json(void *) = delete;
139
140 // Accessors
141 inline Type type() const;
142
143 inline bool is_null() const { return type() == NUL; }
144
145 inline bool is_number() const { return type() == NUMBER; }
146
147 inline bool is_bool() const { return type() == BOOL; }
148
149 inline bool is_string() const { return type() == STRING; }
150
151 inline bool is_array() const { return type() == ARRAY; }
152
153 inline bool is_object() const { return type() == OBJECT; }
154
155 // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
156 // distinguish between integer and non-integer numbers - number_value() and int_value()
157 // can both be applied to a NUMBER-typed object.
158 inline double number_value() const;
159 inline int int_value() const;
160
161 // Return the enclosed value if this is a boolean, false otherwise.
162 inline bool bool_value() const;
163 // Return the enclosed string if this is a string, "" otherwise.
164 inline const std::string &string_value() const;
165 // Return the enclosed std::vector if this is an array, or an empty vector otherwise.
166 inline const array &array_items() const;
167 // Return the enclosed std::map if this is an object, or an empty map otherwise.
168 inline const object &object_items() const;
169
170 // Return a reference to arr[i] if this is an array, Json() otherwise.
171 inline const Json &operator[](size_t i) const;
172 // Return a reference to obj[key] if this is an object, Json() otherwise.
173 inline const Json &operator[](const std::string &key) const;
174
175 // Serialize.
176 inline void dump(std::string &out) const;
177
178 inline std::string dump() const
179 {
180 std::string out;
181 dump(out);
182 return out;
183 }
184
185 // Parse. If parse fails, return Json() and assign an error message to err.
186 static inline Json parse(const std::string &in, std::string &err, JsonParse strategy = JsonParse::STANDARD);
187
188 static inline Json parse(const char *in, std::string &err, JsonParse strategy = JsonParse::STANDARD)
189 {
190 if (in) {
191 return parse(std::string(in), err, strategy);
192 } else {
193 err = "null input";
194 return nullptr;
195 }
196 }
197
198 // Parse multiple objects, concatenated or separated by whitespace
199 static inline std::vector<Json> parse_multi(
200 const std::string &in, std::string::size_type &parser_stop_pos, std::string &err, JsonParse strategy = JsonParse::STANDARD);
201
202 static inline std::vector<Json> parse_multi(const std::string &in, std::string &err, JsonParse strategy = JsonParse::STANDARD)
203 {
204 std::string::size_type parser_stop_pos;
205 return parse_multi(in, parser_stop_pos, err, strategy);
206 }
207
208 inline bool operator==(const Json &rhs) const;
209 inline bool operator<(const Json &rhs) const;
210
211 inline bool operator!=(const Json &rhs) const { return !(*this == rhs); }
212
213 inline bool operator<=(const Json &rhs) const { return !(rhs < *this); }
214
215 inline bool operator>(const Json &rhs) const { return (rhs < *this); }
216
217 inline bool operator>=(const Json &rhs) const { return !(*this < rhs); }
218
219 /* has_shape(types, err)
220 *
221 * Return true if this is a JSON object and, for each item in types, has a field of
222 * the given type. If not, return false and set err to a descriptive message.
223 */
224 typedef std::initializer_list<std::pair<std::string, Type>> shape;
225 inline bool has_shape(const shape &types, std::string &err) const;
226
227 private:
228 std::shared_ptr<JsonValue> m_ptr;
229 };
230
231 // Internal class hierarchy - JsonValue objects are not exposed to users of this API.
232 class JsonValue {
233 protected:
234 friend class Json;
235 friend class JsonInt;
236 friend class JsonDouble;
237 virtual Json::Type type() const = 0;
238 virtual bool equals(const JsonValue *other) const = 0;
239 virtual bool less(const JsonValue *other) const = 0;
240 virtual void dump(std::string &out) const = 0;
241 virtual double number_value() const;
242 virtual int int_value() const;
243 virtual bool bool_value() const;
244 virtual const std::string &string_value() const;
245 virtual const Json::array &array_items() const;
246 virtual const Json &operator[](size_t i) const;
247 virtual const Json::object &object_items() const;
248 virtual const Json &operator[](const std::string &key) const;
249
250 virtual ~JsonValue() {}
251 };
252
253} // namespace json11
254
255
257#include <cassert>
258#include <cmath>
259#include <cstdio>
260#include <cstdlib>
261#include <limits>
262
263namespace json11 {
264
265 static const int max_depth = 200;
266
267 using std::initializer_list;
268 using std::make_shared;
269 using std::map;
270 using std::move;
271 using std::string;
272 using std::vector;
273
274 /* Helper for representing null - just a do-nothing struct, plus comparison
275 * operators so the helpers in JsonValue work. We can't use nullptr_t because
276 * it may not be orderable.
277 */
278 struct NullStruct {
279 bool operator==(NullStruct) const { return true; }
280
281 bool operator<(NullStruct) const { return false; }
282 };
283
284 /* * * * * * * * * * * * * * * * * * * *
285 * Serialization
286 */
287
288 static void dump(NullStruct, string &out)
289 {
290 out += "null";
291 }
292
293 static void dump(double value, string &out)
294 {
295 if (std::isfinite(value)) {
296 char buf[32];
297 snprintf(buf, sizeof buf, "%.17g", value);
298 out += buf;
299 } else {
300 out += "null";
301 }
302 }
303
304 static void dump(int value, string &out)
305 {
306 char buf[32];
307 snprintf(buf, sizeof buf, "%d", value);
308 out += buf;
309 }
310
311 static void dump(bool value, string &out)
312 {
313 out += value ? "true" : "false";
314 }
315
316 static void dump(const string &value, string &out)
317 {
318 out += '"';
319 for (size_t i = 0; i < value.length(); i++) {
320 const char ch = value[i];
321 if (ch == '\\') {
322 out += "\\\\";
323 } else if (ch == '"') {
324 out += "\\\"";
325 } else if (ch == '\b') {
326 out += "\\b";
327 } else if (ch == '\f') {
328 out += "\\f";
329 } else if (ch == '\n') {
330 out += "\\n";
331 } else if (ch == '\r') {
332 out += "\\r";
333 } else if (ch == '\t') {
334 out += "\\t";
335 } else if (static_cast<uint8_t>(ch) <= 0x1f) {
336 char buf[8];
337 snprintf(buf, sizeof buf, "\\u%04x", ch);
338 out += buf;
339 } else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i + 1]) == 0x80 && static_cast<uint8_t>(value[i + 2]) == 0xa8) {
340 out += "\\u2028";
341 i += 2;
342 } else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i + 1]) == 0x80 && static_cast<uint8_t>(value[i + 2]) == 0xa9) {
343 out += "\\u2029";
344 i += 2;
345 } else {
346 out += ch;
347 }
348 }
349 out += '"';
350 }
351
352 static void dump(const Json::array &values, string &out)
353 {
354 bool first = true;
355 out += "[";
356 for (const auto &value : values) {
357 if (!first) out += ", ";
358 value.dump(out);
359 first = false;
360 }
361 out += "]";
362 }
363
364 static void dump(const Json::object &values, string &out)
365 {
366 bool first = true;
367 out += "{";
368 for (const auto &kv : values) {
369 if (!first) out += ", ";
370 dump(kv.first, out);
371 out += ": ";
372 kv.second.dump(out);
373 first = false;
374 }
375 out += "}";
376 }
377
378 void Json::dump(string &out) const
379 {
380 m_ptr->dump(out);
381 }
382
383 /* * * * * * * * * * * * * * * * * * * *
384 * Value wrappers
385 */
386
387 template<Json::Type tag, typename T>
388 class Value : public JsonValue {
389 protected:
390 // Constructors
391 explicit Value(const T &value) : m_value(value) {}
392
393 explicit Value(T &&value) : m_value(move(value)) {}
394
395 // Get type tag
396 Json::Type type() const override { return tag; }
397
398 // Comparisons
399 bool equals(const JsonValue *other) const override { return m_value == static_cast<const Value<tag, T> *>(other)->m_value; }
400
401 bool less(const JsonValue *other) const override { return m_value < static_cast<const Value<tag, T> *>(other)->m_value; }
402
403 const T m_value;
404
405 void dump(string &out) const override { json11::dump(m_value, out); }
406 };
407
408 class JsonDouble final : public Value<Json::NUMBER, double> {
409 double number_value() const override { return m_value; }
410
411 int int_value() const override { return static_cast<int>(m_value); }
412
413 bool equals(const JsonValue *other) const override { return m_value == other->number_value(); }
414
415 bool less(const JsonValue *other) const override { return m_value < other->number_value(); }
416
417 public:
418 explicit JsonDouble(double value) : Value(value) {}
419 };
420
421 class JsonInt final : public Value<Json::NUMBER, int> {
422 double number_value() const override { return m_value; }
423
424 int int_value() const override { return m_value; }
425
426 bool equals(const JsonValue *other) const override { return m_value == other->number_value(); }
427
428 bool less(const JsonValue *other) const override { return m_value < other->number_value(); }
429
430 public:
431 explicit JsonInt(int value) : Value(value) {}
432 };
433
434 class JsonBoolean final : public Value<Json::BOOL, bool> {
435 bool bool_value() const override { return m_value; }
436
437 public:
438 explicit JsonBoolean(bool value) : Value(value) {}
439 };
440
441 class JsonString final : public Value<Json::STRING, string> {
442 const string &string_value() const override { return m_value; }
443
444 public:
445 explicit JsonString(const string &value) : Value(value) {}
446
447 explicit JsonString(string &&value) : Value(move(value)) {}
448 };
449
450 class JsonArray final : public Value<Json::ARRAY, Json::array> {
451 const Json::array &array_items() const override { return m_value; }
452
453 const Json &operator[](size_t i) const override;
454
455 public:
456 explicit JsonArray(const Json::array &value) : Value(value) {}
457
458 explicit JsonArray(Json::array &&value) : Value(move(value)) {}
459 };
460
461 class JsonObject final : public Value<Json::OBJECT, Json::object> {
462 const Json::object &object_items() const override { return m_value; }
463
464 const Json &operator[](const string &key) const override;
465
466 public:
467 explicit JsonObject(const Json::object &value) : Value(value) {}
468
469 explicit JsonObject(Json::object &&value) : Value(move(value)) {}
470 };
471
472 class JsonNull final : public Value<Json::NUL, NullStruct> {
473 public:
474 JsonNull() : Value({}) {}
475 };
476
477 /* * * * * * * * * * * * * * * * * * * *
478 * Static globals - static-init-safe
479 */
480 struct Statics {
481 const std::shared_ptr<JsonValue> null = make_shared<JsonNull>();
482 const std::shared_ptr<JsonValue> t = make_shared<JsonBoolean>(true);
483 const std::shared_ptr<JsonValue> f = make_shared<JsonBoolean>(false);
484 const string empty_string;
485 const vector<Json> empty_vector;
486 const map<string, Json> empty_map;
487
488 Statics() {}
489 };
490
491 static const Statics &statics()
492 {
493 static const Statics s {};
494 return s;
495 }
496
497 static const Json &static_null()
498 {
499 // This has to be separate, not in Statics, because Json() accesses statics().null.
500 static const Json json_null;
501 return json_null;
502 }
503
504 /* * * * * * * * * * * * * * * * * * * *
505 * Constructors
506 */
507
508 Json::Json() noexcept : m_ptr(statics().null) {}
509
510 Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {}
511
512 Json::Json(double value) : m_ptr(make_shared<JsonDouble>(value)) {}
513
514 Json::Json(int value) : m_ptr(make_shared<JsonInt>(value)) {}
515
516 Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {}
517
518 Json::Json(const string &value) : m_ptr(make_shared<JsonString>(value)) {}
519
520 Json::Json(string &&value) : m_ptr(make_shared<JsonString>(move(value))) {}
521
522 Json::Json(const char *value) : m_ptr(make_shared<JsonString>(value)) {}
523
524 Json::Json(const Json::array &values) : m_ptr(make_shared<JsonArray>(values)) {}
525
526 Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(move(values))) {}
527
528 Json::Json(const Json::object &values) : m_ptr(make_shared<JsonObject>(values)) {}
529
530 Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(move(values))) {}
531
532 /* * * * * * * * * * * * * * * * * * * *
533 * Accessors
534 */
535
536 inline Json::Type Json::type() const
537 {
538 return m_ptr->type();
539 }
540
541 inline double Json::number_value() const
542 {
543 return m_ptr->number_value();
544 }
545
546 inline int Json::int_value() const
547 {
548 return m_ptr->int_value();
549 }
550
551 inline bool Json::bool_value() const
552 {
553 return m_ptr->bool_value();
554 }
555
556 inline const string &Json::string_value() const
557 {
558 return m_ptr->string_value();
559 }
560
561 inline const vector<Json> &Json::array_items() const
562 {
563 return m_ptr->array_items();
564 }
565
566 inline const map<string, Json> &Json::object_items() const
567 {
568 return m_ptr->object_items();
569 }
570
571 inline const Json &Json::operator[](size_t i) const
572 {
573 return (*m_ptr)[i];
574 }
575
576 inline const Json &Json::operator[](const string &key) const
577 {
578 return (*m_ptr)[key];
579 }
580
581 inline double JsonValue::number_value() const
582 {
583 return 0;
584 }
585
586 inline int JsonValue::int_value() const
587 {
588 return 0;
589 }
590
591 inline bool JsonValue::bool_value() const
592 {
593 return false;
594 }
595
596 inline const string &JsonValue::string_value() const
597 {
598 return statics().empty_string;
599 }
600
601 inline const vector<Json> &JsonValue::array_items() const
602 {
603 return statics().empty_vector;
604 }
605
606 inline const map<string, Json> &JsonValue::object_items() const
607 {
608 return statics().empty_map;
609 }
610
611 inline const Json &JsonValue::operator[](size_t) const
612 {
613 return static_null();
614 }
615
616 inline const Json &JsonValue::operator[](const string &) const
617 {
618 return static_null();
619 }
620
621 inline const Json &JsonObject::operator[](const string &key) const
622 {
623 auto iter = m_value.find(key);
624 return (iter == m_value.end()) ? static_null() : iter->second;
625 }
626
627 inline const Json &JsonArray::operator[](size_t i) const
628 {
629 if (i >= m_value.size())
630 return static_null();
631 else
632 return m_value[i];
633 }
634
635 /* * * * * * * * * * * * * * * * * * * *
636 * Comparison
637 */
638
639 bool Json::operator==(const Json &other) const
640 {
641 if (m_ptr == other.m_ptr) return true;
642 if (m_ptr->type() != other.m_ptr->type()) return false;
643
644 return m_ptr->equals(other.m_ptr.get());
645 }
646
647 bool Json::operator<(const Json &other) const
648 {
649 if (m_ptr == other.m_ptr) return false;
650 if (m_ptr->type() != other.m_ptr->type()) return m_ptr->type() < other.m_ptr->type();
651
652 return m_ptr->less(other.m_ptr.get());
653 }
654
655 /* * * * * * * * * * * * * * * * * * * *
656 * Parsing
657 */
658
659 /* esc(c)
660 *
661 * Format char c suitable for printing in an error message.
662 */
663 static inline string esc(char c)
664 {
665 char buf[12];
666 if (static_cast<uint8_t>(c) >= 0x20 && static_cast<uint8_t>(c) <= 0x7f) {
667 snprintf(buf, sizeof buf, "'%c' (%d)", c, c);
668 } else {
669 snprintf(buf, sizeof buf, "(%d)", c);
670 }
671 return string(buf);
672 }
673
674 static inline bool in_range(long x, long lower, long upper)
675 {
676 return (x >= lower && x <= upper);
677 }
678
679 namespace {
680 /* JsonParser
681 *
682 * Object that tracks all state of an in-progress parse.
683 */
684 struct JsonParser final {
685 /* State
686 */
687 const string &str;
688 size_t i;
689 string &err;
690 bool failed;
691 const JsonParse strategy;
692
693 /* fail(msg, err_ret = Json())
694 *
695 * Mark this parse as failed.
696 */
697 Json fail(string &&msg) { return fail(move(msg), Json()); }
698
699 template<typename T>
700 T fail(string &&msg, const T err_ret)
701 {
702 if (!failed) err = std::move(msg);
703 failed = true;
704 return err_ret;
705 }
706
707 /* consume_whitespace()
708 *
709 * Advance until the current character is non-whitespace.
710 */
711 void consume_whitespace()
712 {
713 while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t')
714 i++;
715 }
716
717 /* consume_comment()
718 *
719 * Advance comments (c-style inline and multiline).
720 */
721 bool consume_comment()
722 {
723 bool comment_found = false;
724 if (str[i] == '/') {
725 i++;
726 if (i == str.size()) return fail("unexpected end of input after start of comment", false);
727 if (str[i] == '/') { // inline comment
728 i++;
729 // advance until next line, or end of input
730 while (i < str.size() && str[i] != '\n') {
731 i++;
732 }
733 comment_found = true;
734 } else if (str[i] == '*') { // multiline comment
735 i++;
736 if (i > str.size() - 2) return fail("unexpected end of input inside multi-line comment", false);
737 // advance until closing tokens
738 while (!(str[i] == '*' && str[i + 1] == '/')) {
739 i++;
740 if (i > str.size() - 2) return fail("unexpected end of input inside multi-line comment", false);
741 }
742 i += 2;
743 comment_found = true;
744 } else
745 return fail("malformed comment", false);
746 }
747 return comment_found;
748 }
749
750 /* consume_garbage()
751 *
752 * Advance until the current character is non-whitespace and non-comment.
753 */
754 void consume_garbage()
755 {
756 consume_whitespace();
757 if (strategy == JsonParse::COMMENTS) {
758 bool comment_found = false;
759 do {
760 comment_found = consume_comment();
761 if (failed) return;
762 consume_whitespace();
763 } while (comment_found);
764 }
765 }
766
767 /* get_next_token()
768 *
769 * Return the next non-whitespace character. If the end of the input is reached,
770 * flag an error and return 0.
771 */
772 char get_next_token()
773 {
774 consume_garbage();
775 if (failed) return static_cast<char>(0);
776 if (i == str.size()) return fail("unexpected end of input", static_cast<char>(0));
777
778 return str[i++];
779 }
780
781 /* encode_utf8(pt, out)
782 *
783 * Encode pt as UTF-8 and add it to out.
784 */
785 void encode_utf8(long pt, string &out)
786 {
787 if (pt < 0) return;
788
789 if (pt < 0x80) {
790 out += static_cast<char>(pt);
791 } else if (pt < 0x800) {
792 out += static_cast<char>((pt >> 6) | 0xC0);
793 out += static_cast<char>((pt & 0x3F) | 0x80);
794 } else if (pt < 0x10000) {
795 out += static_cast<char>((pt >> 12) | 0xE0);
796 out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80);
797 out += static_cast<char>((pt & 0x3F) | 0x80);
798 } else {
799 out += static_cast<char>((pt >> 18) | 0xF0);
800 out += static_cast<char>(((pt >> 12) & 0x3F) | 0x80);
801 out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80);
802 out += static_cast<char>((pt & 0x3F) | 0x80);
803 }
804 }
805
806 /* parse_string()
807 *
808 * Parse a string, starting at the current position.
809 */
810 string parse_string()
811 {
812 string out;
813 long last_escaped_codepoint = -1;
814 while (true) {
815 if (i == str.size()) return fail("unexpected end of input in string", "");
816
817 char ch = str[i++];
818
819 if (ch == '"') {
820 encode_utf8(last_escaped_codepoint, out);
821 return out;
822 }
823
824 if (in_range(ch, 0, 0x1f)) return fail("unescaped " + esc(ch) + " in string", "");
825
826 // The usual case: non-escaped characters
827 if (ch != '\\') {
828 encode_utf8(last_escaped_codepoint, out);
829 last_escaped_codepoint = -1;
830 out += ch;
831 continue;
832 }
833
834 // Handle escapes
835 if (i == str.size()) return fail("unexpected end of input in string", "");
836
837 ch = str[i++];
838
839 if (ch == 'u') {
840 // Extract 4-byte escape sequence
841 string esc = str.substr(i, 4);
842 // Explicitly check length of the substring. The following loop
843 // relies on std::string returning the terminating NUL when
844 // accessing str[length]. Checking here reduces brittleness.
845 if (esc.length() < 4) {
846 return fail("bad \\u escape: " + esc, "");
847 }
848 for (size_t j = 0; j < 4; j++) {
849 if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F') && !in_range(esc[j], '0', '9'))
850 return fail("bad \\u escape: " + esc, "");
851 }
852
853 long codepoint = strtol(esc.data(), nullptr, 16);
854
855 // JSON specifies that characters outside the BMP shall be encoded as a pair
856 // of 4-hex-digit \u escapes encoding their surrogate pair components. Check
857 // whether we're in the middle of such a beast: the previous codepoint was an
858 // escaped lead (high) surrogate, and this is a trail (low) surrogate.
859 if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF) && in_range(codepoint, 0xDC00, 0xDFFF)) {
860 // Reassemble the two surrogate pairs into one astral-plane character, per
861 // the UTF-16 algorithm.
862 encode_utf8((((last_escaped_codepoint - 0xD800) << 10) | (codepoint - 0xDC00)) + 0x10000, out);
863 last_escaped_codepoint = -1;
864 } else {
865 encode_utf8(last_escaped_codepoint, out);
866 last_escaped_codepoint = codepoint;
867 }
868
869 i += 4;
870 continue;
871 }
872
873 encode_utf8(last_escaped_codepoint, out);
874 last_escaped_codepoint = -1;
875
876 if (ch == 'b') {
877 out += '\b';
878 } else if (ch == 'f') {
879 out += '\f';
880 } else if (ch == 'n') {
881 out += '\n';
882 } else if (ch == 'r') {
883 out += '\r';
884 } else if (ch == 't') {
885 out += '\t';
886 } else if (ch == '"' || ch == '\\' || ch == '/') {
887 out += ch;
888 } else {
889 return fail("invalid escape character " + esc(ch), "");
890 }
891 }
892 }
893
894 /* parse_number()
895 *
896 * Parse a double.
897 */
898 Json parse_number()
899 {
900 size_t start_pos = i;
901
902 if (str[i] == '-') i++;
903
904 // Integer part
905 if (str[i] == '0') {
906 i++;
907 if (in_range(str[i], '0', '9')) return fail("leading 0s not permitted in numbers");
908 } else if (in_range(str[i], '1', '9')) {
909 i++;
910 while (in_range(str[i], '0', '9'))
911 i++;
912 } else {
913 return fail("invalid " + esc(str[i]) + " in number");
914 }
915
916 if (str[i] != '.' && str[i] != 'e' && str[i] != 'E' && (i - start_pos) <= static_cast<size_t>(std::numeric_limits<int>::digits10)) {
917 return std::atoi(str.c_str() + start_pos);
918 }
919
920 // Decimal part
921 if (str[i] == '.') {
922 i++;
923 if (!in_range(str[i], '0', '9')) return fail("at least one digit required in fractional part");
924
925 while (in_range(str[i], '0', '9'))
926 i++;
927 }
928
929 // Exponent part
930 if (str[i] == 'e' || str[i] == 'E') {
931 i++;
932
933 if (str[i] == '+' || str[i] == '-') i++;
934
935 if (!in_range(str[i], '0', '9')) return fail("at least one digit required in exponent");
936
937 while (in_range(str[i], '0', '9'))
938 i++;
939 }
940
941 return std::strtod(str.c_str() + start_pos, nullptr);
942 }
943
944 /* expect(str, res)
945 *
946 * Expect that 'str' starts at the character that was just read. If it does, advance
947 * the input and return res. If not, flag an error.
948 */
949 Json expect(const string &expected, Json res)
950 {
951 assert(i != 0);
952 i--;
953 if (str.compare(i, expected.length(), expected) == 0) {
954 i += expected.length();
955 return res;
956 } else {
957 return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length()));
958 }
959 }
960
961 /* parse_json()
962 *
963 * Parse a JSON object.
964 */
965 Json parse_json(int depth)
966 {
967 if (depth > max_depth) {
968 return fail("exceeded maximum nesting depth");
969 }
970
971 char ch = get_next_token();
972 if (failed) return Json();
973
974 if (ch == '-' || (ch >= '0' && ch <= '9')) {
975 i--;
976 return parse_number();
977 }
978
979 if (ch == 't') return expect("true", true);
980
981 if (ch == 'f') return expect("false", false);
982
983 if (ch == 'n') return expect("null", Json());
984
985 if (ch == '"') return parse_string();
986
987 if (ch == '{') {
988 map<string, Json> data;
989 ch = get_next_token();
990 if (ch == '}') return data;
991
992 while (1) {
993 if (ch != '"') return fail("expected '\"' in object, got " + esc(ch));
994
995 string key = parse_string();
996 if (failed) return Json();
997
998 ch = get_next_token();
999 if (ch != ':') return fail("expected ':' in object, got " + esc(ch));
1000
1001 data[std::move(key)] = parse_json(depth + 1);
1002 if (failed) return Json();
1003
1004 ch = get_next_token();
1005 if (ch == '}') break;
1006 if (ch != ',') return fail("expected ',' in object, got " + esc(ch));
1007
1008 ch = get_next_token();
1009 }
1010 return data;
1011 }
1012
1013 if (ch == '[') {
1014 vector<Json> data;
1015 ch = get_next_token();
1016 if (ch == ']') return data;
1017
1018 while (1) {
1019 i--;
1020 data.push_back(parse_json(depth + 1));
1021 if (failed) return Json();
1022
1023 ch = get_next_token();
1024 if (ch == ']') break;
1025 if (ch != ',') return fail("expected ',' in list, got " + esc(ch));
1026
1027 ch = get_next_token();
1028 (void) ch;
1029 }
1030 return data;
1031 }
1032
1033 return fail("expected value, got " + esc(ch));
1034 }
1035 };
1036 } // namespace
1037
1038 Json Json::parse(const string &in, string &err, JsonParse strategy)
1039 {
1040 JsonParser parser {in, 0, err, false, strategy};
1041 Json result = parser.parse_json(0);
1042
1043 // Check for any trailing garbage
1044 parser.consume_garbage();
1045 if (parser.failed) return Json();
1046 if (parser.i != in.size() &&
1047 ((parser.i + 1) != in.size() &&
1048 in[parser.i] != 0)) // RBP: If there is only 1 character diff, it is probably just a terminating zero from a memory read.
1049 {
1050 return parser.fail("unexpected trailing " + esc(in[parser.i]));
1051 }
1052 return result;
1053 }
1054
1055 // Documented in json11.hpp
1056 vector<Json> Json::parse_multi(const string &in, std::string::size_type &parser_stop_pos, string &err, JsonParse strategy)
1057 {
1058 JsonParser parser {in, 0, err, false, strategy};
1059 parser_stop_pos = 0;
1060 vector<Json> json_vec;
1061 while (parser.i != in.size() && !parser.failed) {
1062 json_vec.push_back(parser.parse_json(0));
1063 if (parser.failed) break;
1064
1065 // Check for another object
1066 parser.consume_garbage();
1067 if (parser.failed) break;
1068 parser_stop_pos = parser.i;
1069 }
1070 return json_vec;
1071 }
1072
1073 /* * * * * * * * * * * * * * * * * * * *
1074 * Shape-checking
1075 */
1076
1077 bool Json::has_shape(const shape &types, string &err) const
1078 {
1079 if (!is_object()) {
1080 err = "expected JSON object, got " + dump();
1081 return false;
1082 }
1083
1084 const auto &obj_items = object_items();
1085 for (auto &item : types) {
1086 const auto it = obj_items.find(item.first);
1087 if (it == obj_items.cend() || it->second.type() != item.second) {
1088 err = "bad type for " + item.first + " in " + dump();
1089 return false;
1090 }
1091 }
1092
1093 return true;
1094 }
1095
1096} // namespace json11
1097
1098
1100
1102
1103//
1104// Created by robin on 22.03.2020.
1105//
1106
1107#ifndef TILESON_TILESON_PARSER_HPP
1108 #define TILESON_TILESON_PARSER_HPP
1109
1110 // RBP: FS-namespace is defined in tileson_parser now!
1111 #if _MSC_VER && !__INTEL_COMPILER
1112 #include <filesystem>
1113namespace fs = std::filesystem;
1114 #elif __MINGW64__
1115 #if __MINGW64_VERSION_MAJOR > 6
1116 #include <filesystem>
1117namespace fs = std::filesystem;
1118 #else
1119 #include <experimental/filesystem>
1120namespace fs = std::experimental::filesystem;
1121 #endif
1122 #elif __clang__
1123 #if __clang_major__ < 8
1124 #include <experimental/filesystem>
1125namespace fs = std::experimental::filesystem;
1126 #else
1127 #include <filesystem>
1128namespace fs = std::filesystem;
1129 #endif
1130 #else // Linux
1131 #if __GNUC__ < 8 // GCC major version less than 8
1132 #include <experimental/filesystem>
1133namespace fs = std::experimental::filesystem;
1134 #else
1135 #include <filesystem>
1136namespace fs = std::filesystem;
1137 #endif
1138 #endif
1139
1140 #include <fstream>
1141 #include <memory>
1142 #include <sstream>
1143
1144
1145 //
1146 // Created by robin on 31.07.2020.
1147 //
1148
1149 #ifndef TILESON_TOOLS_HPP
1150 #define TILESON_TOOLS_HPP
1151
1152 #include <cstdint>
1153 #include <string_view>
1154 #include <vector>
1155
1156namespace tson {
1157 class Tools {
1158 public:
1159 Tools() = delete;
1160 ~Tools() = delete;
1161 inline static std::vector<uint8_t> Base64DecodedStringToBytes(std::string_view str);
1162 inline static std::vector<uint32_t> BytesToUnsignedInts(const std::vector<uint8_t> &bytes);
1163 inline static std::vector<std::string> SplitString(const std::string &s, char delim);
1164 inline static bool Equal(float a, float b, float precision = 8192.f);
1165
1166 private:
1167 template<typename Out>
1168 static void split(const std::string &s, char delim, Out result)
1169 {
1170 std::stringstream ss;
1171 ss.str(s);
1172 std::string item;
1173
1174 while (std::getline(ss, item, delim)) {
1175 *(result++) = item;
1176 }
1177 }
1178 };
1179
1185 std::vector<uint8_t> Tools::Base64DecodedStringToBytes(std::string_view str)
1186 {
1187 std::vector<uint8_t> bytes;
1188 for (size_t i = 0; i < str.size(); ++i) {
1189 uint8_t u8 = static_cast<uint8_t>(str[i]);
1190 bytes.push_back(u8);
1191 }
1192 return bytes;
1193 }
1194
1200 std::vector<uint32_t> Tools::BytesToUnsignedInts(const std::vector<uint8_t> &bytes)
1201 {
1202 std::vector<uint32_t> uints;
1203 std::vector<uint8_t> toConvert;
1204 // uint32_t size8 = (compressed[55] << 24) | (compressed[56] << 16) | (compressed[57] << 8) | compressed[58]; //Should be 66000
1205
1206 for (size_t i = 0; i < bytes.size(); ++i) {
1207 toConvert.push_back(bytes[i]);
1208 if (toConvert.size() == 4) {
1209 uint32_t u32 = (toConvert[3] << 24) | (toConvert[2] << 16) | (toConvert[1] << 8) | toConvert[0];
1210 uints.push_back(u32);
1211 toConvert.clear();
1212 }
1213 }
1214
1215 return uints;
1216 }
1217
1218 std::vector<std::string> Tools::SplitString(const std::string &s, char delim)
1219 {
1220 std::vector<std::string> elems;
1221 split(s, delim, std::back_inserter(elems));
1222 return elems;
1223 }
1224
1231 bool Tools::Equal(float a, float b, float precision)
1232 {
1233 float threshold = 1.f / precision;
1234 float diff = fabsf(a - b);
1235 return diff <= threshold;
1236 }
1237} // namespace tson
1238
1239 #endif // TILESON_TOOLS_HPP
1240
1241
1243
1244 //
1245 // Created by robin on 29.07.2020.
1246 // The Base64 decoding logic is heavily based on: https://github.com/ReneNyffenegger/cpp-base64
1247 //
1248
1249 #ifndef TILESON_BASE64DECOMPRESSOR_HPP
1250 #define TILESON_BASE64DECOMPRESSOR_HPP
1251
1252
1253 //
1254 // Created by robin on 29.07.2020.
1255 //
1256
1257 #ifndef TILESON_IDECOMPRESSOR_HPP
1258 #define TILESON_IDECOMPRESSOR_HPP
1259
1260 #include <string_view>
1261
1262namespace tson {
1263 template<class TIn, class TOut>
1265 public:
1277 [[nodiscard]]
1278 virtual const std::string &name() const = 0;
1279
1285 virtual TOut decompress(const TIn &input) = 0;
1286
1292 virtual TOut decompressFile(const fs::path &path) = 0;
1293
1299 virtual TOut decompress(const void *data, size_t size) = 0;
1300
1304 virtual ~IDecompressor() = default;
1305 };
1306} // namespace tson
1307
1308 #endif // TILESON_IDECOMPRESSOR_HPP
1309
1310
1312 #include <string>
1313
1314namespace tson {
1315 class Base64Decompressor : public IDecompressor<std::string_view, std::string> {
1316 public:
1317 [[nodiscard]]
1318 inline const std::string &name() const override;
1319
1320 inline std::string decompress(const std::string_view &s) override;
1321
1322 inline std::string decompressFile(const fs::path &path) override;
1323 inline std::string decompress(const void *data, size_t size) override;
1324
1325 private:
1326 inline unsigned int pos_of_char(const unsigned char chr);
1327 inline static const std::string NAME = "base64";
1328 };
1329
1330 const std::string &Base64Decompressor::name() const
1331 {
1332 return NAME;
1333 }
1334
1335 std::string Base64Decompressor::decompress(const std::string_view &s)
1336 {
1337 size_t length_of_string = s.length();
1338 if (!length_of_string) return std::string("");
1339
1340 size_t in_len = length_of_string;
1341 size_t pos = 0;
1342
1343 //
1344 // The approximate length (bytes) of the decoded string might be one ore
1345 // two bytes smaller, depending on the amount of trailing equal signs
1346 // in the encoded string. This approximation is needed to reserve
1347 // enough space in the string to be returned.
1348 //
1349 size_t approx_length_of_decoded_string = length_of_string / 4 * 3;
1350 std::string ret;
1351 ret.reserve(approx_length_of_decoded_string);
1352
1353 while (pos < in_len) {
1354 unsigned int pos_of_char_1 = pos_of_char(s[pos + 1]);
1355
1356 ret.push_back(static_cast<std::string::value_type>(((pos_of_char(s[pos + 0])) << 2) + ((pos_of_char_1 & 0x30) >> 4)));
1357
1358 if (s[pos + 2] != '=' && s[pos + 2] != '.') { // accept URL-safe base 64 strings, too, so check for '.' also.
1359
1360 unsigned int pos_of_char_2 = pos_of_char(s[pos + 2]);
1361 ret.push_back(static_cast<std::string::value_type>(((pos_of_char_1 & 0x0f) << 4) + ((pos_of_char_2 & 0x3c) >> 2)));
1362
1363 if (s[pos + 3] != '=' && s[pos + 3] != '.') {
1364 ret.push_back(static_cast<std::string::value_type>(((pos_of_char_2 & 0x03) << 6) + pos_of_char(s[pos + 3])));
1365 }
1366 }
1367
1368 pos += 4;
1369 }
1370
1371 return ret;
1372 }
1373
1374 unsigned int Base64Decompressor::pos_of_char(const unsigned char chr)
1375 {
1376 //
1377 // Return the position of chr within base64_encode()
1378 //
1379
1380 if (chr >= 'A' && chr <= 'Z')
1381 return chr - 'A';
1382 else if (chr >= 'a' && chr <= 'z')
1383 return chr - 'a' + ('Z' - 'A') + 1;
1384 else if (chr >= '0' && chr <= '9')
1385 return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2;
1386 else if (chr == '+' || chr == '-')
1387 return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters (
1388 else if (chr == '/' || chr == '_')
1389 return 63; // Ditto for '/' and '_'
1390
1391 throw "If input is correct, this line should never be reached.";
1392 }
1393
1399 std::string Base64Decompressor::decompressFile(const fs::path &)
1400 {
1401 return std::string();
1402 }
1403
1409 std::string Base64Decompressor::decompress(const void *, size_t)
1410 {
1411 return std::string();
1412 }
1413} // namespace tson
1414
1415 #endif // TILESON_BASE64DECOMPRESSOR_HPP
1416
1417
1419
1420 //
1421 // Created by robin on 16.01.2021.
1422 //
1423 // #include "../../extras/pocketlzma.hpp"
1424 #ifdef POCKETLZMA_POCKETLZMA_H
1425
1426 #ifndef TILESON_LZMA_HPP
1427 #define TILESON_LZMA_HPP
1428
1429namespace tson {
1430 class Lzma : public IDecompressor<std::vector<uint8_t>, std::vector<uint8_t>> {
1431 public:
1432 inline const std::string &name() const override { return NAME; }
1433
1434 inline std::vector<uint8_t> decompress(const std::vector<uint8_t> &input) override
1435 {
1436 std::vector<uint8_t> out;
1437
1438 plz::PocketLzma p;
1439 plz::StatusCode status = p.decompress(input, out);
1440
1441 if (status != plz::StatusCode::Ok) return std::vector<uint8_t>();
1442
1443 return out;
1444 }
1445
1446 inline std::vector<uint8_t> decompressFile(const fs::path &path) override
1447 {
1448 std::vector<uint8_t> in;
1449 std::vector<uint8_t> out;
1450
1451 plz::PocketLzma p;
1452 plz::FileStatus fileStatus = plz::File::FromFile(path.generic_string(), in);
1453 if (fileStatus.status() != plz::FileStatus::Code::Ok) return std::vector<uint8_t>();
1454
1455 plz::StatusCode status = p.decompress(in, out);
1456
1457 if (status != plz::StatusCode::Ok) return std::vector<uint8_t>();
1458
1459 return out;
1460 }
1461
1462 inline std::vector<uint8_t> decompress(const void *data, size_t size) override
1463 {
1464 std::vector<uint8_t> out;
1465
1466 plz::PocketLzma p;
1467 plz::StatusCode status = p.decompress((uint8_t *) data, size, out);
1468
1469 if (status != plz::StatusCode::Ok) return std::vector<uint8_t>();
1470
1471 return out;
1472 }
1473
1474 private:
1475 inline static const std::string NAME {"lzma"};
1476 };
1477} // namespace tson
1478
1479 #endif // TILESON_LZMA_HPP
1480
1481 #endif
1482
1484
1485 //
1486 // Created by robin on 30.07.2020.
1487 //
1488
1489 #ifndef TILESON_DECOMPRESSORCONTAINER_HPP
1490 #define TILESON_DECOMPRESSORCONTAINER_HPP
1491
1492 #include <functional>
1493 #include <memory>
1494 #include <string_view>
1495 #include <vector>
1496
1497namespace tson {
1499 public:
1500 inline DecompressorContainer() = default;
1501 template<typename T, typename... Args>
1502 inline void add(Args &&...args);
1503 inline void remove(std::string_view name);
1504 inline bool contains(std::string_view name) const;
1505 inline bool empty() const;
1506 inline size_t size() const;
1507 inline void clear();
1508
1509 inline IDecompressor<std::string_view, std::string> *get(std::string_view name);
1510
1511 private:
1512 // Key: name,
1513 std::vector<std::unique_ptr<IDecompressor<std::string_view, std::string>>> m_decompressors;
1514 };
1515
1516 template<typename T, typename... Args>
1517 void DecompressorContainer::add(Args &&...args)
1518 {
1519 m_decompressors.emplace_back(new T(args...));
1520 }
1521
1527 bool DecompressorContainer::contains(std::string_view name) const
1528 {
1529 auto iter = std::find_if(m_decompressors.begin(), m_decompressors.end(), [&](const auto &item) { return item->name() == name; });
1530
1531 return iter != m_decompressors.end();
1532 }
1533
1538 void DecompressorContainer::remove(std::string_view name)
1539 {
1540 auto iter = std::remove_if(m_decompressors.begin(), m_decompressors.end(), [&](const auto &item) { return item->name() == name; });
1541 m_decompressors.erase(iter);
1542 }
1543
1544 size_t DecompressorContainer::size() const
1545 {
1546 return m_decompressors.size();
1547 }
1548
1555 {
1556 auto iter = std::find_if(m_decompressors.begin(), m_decompressors.end(), [&](const auto &item) { return item->name() == name; });
1557
1558 return (iter != m_decompressors.end()) ? iter->get() : nullptr;
1559 }
1560
1566 {
1567 return m_decompressors.empty();
1568 }
1569
1574 {
1575 m_decompressors.clear();
1576 }
1577} // namespace tson
1578 #endif // TILESON_DECOMPRESSORCONTAINER_HPP
1579
1580
1582
1583 //
1584 // Created by robin on 22.03.2020.
1585 //
1586
1587 #ifndef TILESON_MEMORYSTREAM_HPP
1588 #define TILESON_MEMORYSTREAM_HPP
1589
1590
1591 //
1592 // Created by robin on 22.03.2020.
1593 //
1594
1595 #ifndef TILESON_MEMORYBUFFER_HPP
1596 #define TILESON_MEMORYBUFFER_HPP
1597
1598 #include <iostream>
1599
1600namespace tson {
1601 class MemoryBuffer : public std::basic_streambuf<char> {
1602 public:
1603 MemoryBuffer(const uint8_t *p, size_t l) { setg((char *) p, (char *) p, (char *) p + l); }
1604 };
1605} // namespace tson
1606
1607 #endif // TILESON_MEMORYBUFFER_HPP
1608
1609
1611namespace tson {
1612 class MemoryStream : public std::istream {
1613 public:
1614 MemoryStream(const uint8_t *p, size_t l) : std::istream(&m_buffer), m_buffer(p, l) { rdbuf(&m_buffer); }
1615
1616 private:
1617 MemoryBuffer m_buffer;
1618 };
1619} // namespace tson
1620
1621 #endif // TILESON_MEMORYSTREAM_HPP
1622
1623
1625
1626 //
1627 // Created by robin on 22.03.2020.
1628 //
1629
1630 #ifndef TILESON_MAP_HPP
1631 #define TILESON_MAP_HPP
1632
1633
1634 //
1635 // Created by robin on 09.08.2019.
1636 //
1637
1638 #ifndef TILESON_COLOR_HPP
1639 #define TILESON_COLOR_HPP
1640
1641 #include <cstdint>
1642 #include <string>
1643 #include <type_traits>
1644
1645namespace tson {
1646
1647 template<typename T>
1648 class Color {
1649 public:
1655 inline explicit Color(const std::string &color) { parseHexString(color); }
1656
1657 inline Color(T red, T green, T blue, T alpha);
1658
1659 inline Color()
1660 {
1661 r = g = b = 0;
1662 a = 255;
1663 }
1664
1665 inline bool operator==(const Color &rhs) const;
1666 inline bool operator==(const std::string &rhs) const;
1667 inline bool operator!=(const Color &rhs) const;
1668
1671
1673 T r;
1675 T g;
1677 T b;
1679 T a;
1680
1681 private:
1682 void parseHexString(const std::string &color)
1683 {
1684 if constexpr (std::is_same<T, float>::value) {
1685 if (color.size() == 9) {
1686 a = (float) std::stoi(color.substr(1, 2), nullptr, 16) / 255;
1687 r = (float) std::stoi(color.substr(3, 2), nullptr, 16) / 255;
1688 g = (float) std::stoi(color.substr(5, 2), nullptr, 16) / 255;
1689 b = (float) std::stoi(color.substr(7, 2), nullptr, 16) / 255;
1690 } else if (color.size() == 7) {
1691 r = (float) std::stoi(color.substr(1, 2), nullptr, 16) / 255;
1692 g = (float) std::stoi(color.substr(3, 2), nullptr, 16) / 255;
1693 b = (float) std::stoi(color.substr(5, 2), nullptr, 16) / 255;
1694 a = 1.f;
1695 }
1696 } else if constexpr (std::is_same<T, uint8_t>::value) {
1697 if (color.size() == 9) {
1698 a = static_cast<uint8_t>(std::stoi(color.substr(1, 2), nullptr, 16));
1699 r = static_cast<uint8_t>(std::stoi(color.substr(3, 2), nullptr, 16));
1700 g = static_cast<uint8_t>(std::stoi(color.substr(5, 2), nullptr, 16));
1701 b = static_cast<uint8_t>(std::stoi(color.substr(7, 2), nullptr, 16));
1702 } else if (color.size() == 7) {
1703 r = static_cast<uint8_t>(std::stoi(color.substr(1, 2), nullptr, 16));
1704 g = static_cast<uint8_t>(std::stoi(color.substr(3, 2), nullptr, 16));
1705 b = static_cast<uint8_t>(std::stoi(color.substr(5, 2), nullptr, 16));
1706 a = 255;
1707 }
1708 }
1709 }
1710 };
1711
1712 typedef Color<uint8_t> Colori;
1713 typedef Color<float> Colorf;
1714
1721 template<typename T>
1723 {
1724 if constexpr (std::is_same<T, float>::value)
1725 *this;
1726 else
1727 return tson::Colorf((float) r / 255, (float) g / 255, (float) b / 255, (float) a / 255);
1728 }
1729
1736 template<typename T>
1738 {
1739 if constexpr (std::is_same<T, float>::value)
1740 return tson::Colori(
1741 static_cast<std::uint8_t>((float) r * 255), static_cast<std::uint8_t>((float) g * 255), static_cast<std::uint8_t>((float) b * 255),
1742 static_cast<std::uint8_t>((float) a * 255));
1743 else
1744 *this;
1745 }
1746
1755 template<typename T>
1756 Color<T>::Color(T red, T green, T blue, T alpha)
1757 {
1758 r = red;
1759 g = green;
1760 b = blue;
1761 a = alpha;
1762 }
1763
1764 template<typename T>
1765 bool Color<T>::operator==(const std::string &rhs) const
1766 {
1767 Color other {rhs};
1768 return *this == other;
1769 }
1770
1771 template<typename T>
1772 bool Color<T>::operator==(const Color &rhs) const
1773 {
1774 return r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a;
1775 }
1776
1777 template<typename T>
1778 bool Color<T>::operator!=(const Color &rhs) const
1779 {
1780 return !(rhs == *this);
1781 }
1782
1783} // namespace tson
1784
1785 #endif // TILESON_COLOR_HPP
1786
1787
1789
1790 //
1791 // Created by robin on 31.07.2019.
1792 //
1793
1794 #ifndef TILESON_VECTOR2_HPP
1795 #define TILESON_VECTOR2_HPP
1796
1797namespace tson {
1798 template<typename T>
1799 class Vector2 {
1800 public:
1801 inline Vector2(T xPos, T yPos);
1802
1803 inline Vector2() { x = y = 0; }
1804
1805 inline bool operator==(const Vector2 &rhs) const;
1806 inline bool operator!=(const Vector2 &rhs) const;
1807
1808 T x;
1809 T y;
1810 };
1811
1818 template<typename T>
1819 Vector2<T>::Vector2(T xPos, T yPos)
1820 {
1821 x = xPos;
1822 y = yPos;
1823 }
1824
1825 template<typename T>
1826 bool Vector2<T>::operator==(const Vector2 &rhs) const
1827 {
1828 return x == rhs.x && y == rhs.y;
1829 }
1830
1831 template<typename T>
1832 bool Vector2<T>::operator!=(const Vector2 &rhs) const
1833 {
1834 return !(rhs == *this);
1835 }
1836
1837 typedef Vector2<int> Vector2i;
1838 typedef Vector2<float> Vector2f;
1839} // namespace tson
1840
1841 #endif // TILESON_VECTOR2_HPP
1842
1843
1845 // #include "../external/json.hpp"
1846
1847
1848 //
1849 // Created by robin on 06.01.2021.
1850 //
1851
1852 #ifndef TILESON_IJSON_HPP
1853 #define TILESON_IJSON_HPP
1854
1855namespace tson {
1856 class IJson {
1857 public:
1858 virtual IJson &operator[](std::string_view key) = 0;
1859 virtual IJson &at(std::string_view key) = 0;
1860 virtual IJson &at(size_t pos) = 0;
1865 [[nodiscard]]
1866 virtual std::vector<std::unique_ptr<IJson>> array() = 0;
1867 [[nodiscard]]
1868 virtual std::vector<std::unique_ptr<IJson>> &array(std::string_view key) = 0;
1874 [[nodiscard]]
1875 virtual size_t size() const = 0;
1876 [[nodiscard]]
1877 virtual bool parse(const fs::path &path) = 0;
1878 [[nodiscard]]
1879 virtual bool parse(const void *data, size_t size) = 0;
1880
1881 template<typename T>
1882 [[nodiscard]]
1883 T get(std::string_view key);
1884 template<typename T>
1885 [[nodiscard]]
1886 T get();
1887 [[nodiscard]]
1888 virtual size_t count(std::string_view key) const = 0;
1889 [[nodiscard]]
1890 virtual bool any(std::string_view key) const = 0;
1891 [[nodiscard]]
1892 virtual bool isArray() const = 0;
1893 [[nodiscard]]
1894 virtual bool isObject() const = 0;
1895 [[nodiscard]]
1896 virtual bool isNull() const = 0;
1897
1903 [[nodiscard]]
1904 virtual fs::path directory() const = 0;
1905 virtual void directory(const fs::path &directory) = 0;
1906
1910 virtual ~IJson() = default;
1911
1912 protected:
1913 [[nodiscard]]
1914 virtual int32_t getInt32(std::string_view key) = 0;
1915 [[nodiscard]]
1916 virtual uint32_t getUInt32(std::string_view key) = 0;
1917 [[nodiscard]]
1918 virtual int64_t getInt64(std::string_view key) = 0;
1919 [[nodiscard]]
1920 virtual uint64_t getUInt64(std::string_view key) = 0;
1921 [[nodiscard]]
1922 virtual double getDouble(std::string_view key) = 0;
1923 [[nodiscard]]
1924 virtual float getFloat(std::string_view key) = 0;
1925 [[nodiscard]]
1926 virtual std::string getString(std::string_view key) = 0;
1927 [[nodiscard]]
1928 virtual bool getBool(std::string_view key) = 0;
1929
1930 [[nodiscard]]
1931 virtual int32_t getInt32() = 0;
1932 [[nodiscard]]
1933 virtual uint32_t getUInt32() = 0;
1934 [[nodiscard]]
1935 virtual int64_t getInt64() = 0;
1936 [[nodiscard]]
1937 virtual uint64_t getUInt64() = 0;
1938 [[nodiscard]]
1939 virtual double getDouble() = 0;
1940 [[nodiscard]]
1941 virtual float getFloat() = 0;
1942 [[nodiscard]]
1943 virtual std::string getString() = 0;
1944 [[nodiscard]]
1945 virtual bool getBool() = 0;
1946 };
1947
1948 template<typename T>
1949 T IJson::get(std::string_view key)
1950 {
1951 if constexpr (std::is_same<T, double>::value) return getDouble(key);
1952 if constexpr (std::is_same<T, float>::value)
1953 return getFloat(key);
1954 else if constexpr (std::is_same<T, int32_t>::value)
1955 return getInt32(key);
1956 else if constexpr (std::is_same<T, uint32_t>::value)
1957 return getUInt32(key);
1958 else if constexpr (std::is_same<T, int64_t>::value)
1959 return getInt64(key);
1960 else if constexpr (std::is_same<T, uint64_t>::value)
1961 return getUInt64(key);
1962 else if constexpr (std::is_same<T, std::string>::value)
1963 return getString(key);
1964 else if constexpr (std::is_same<T, bool>::value)
1965 return getBool(key);
1966 else
1967 return nullptr;
1968 }
1969
1970 template<typename T>
1971 T IJson::get()
1972 {
1973 if constexpr (std::is_same<T, double>::value) return getDouble();
1974 if constexpr (std::is_same<T, float>::value)
1975 return getFloat();
1976 else if constexpr (std::is_same<T, int32_t>::value)
1977 return getInt32();
1978 else if constexpr (std::is_same<T, uint32_t>::value)
1979 return getUInt32();
1980 else if constexpr (std::is_same<T, int64_t>::value)
1981 return getInt64();
1982 else if constexpr (std::is_same<T, uint64_t>::value)
1983 return getUInt64();
1984 else if constexpr (std::is_same<T, std::string>::value)
1985 return getString();
1986 else if constexpr (std::is_same<T, bool>::value)
1987 return getBool();
1988 else
1989 return nullptr;
1990 }
1991
1992} // namespace tson
1993
1994 #endif // TILESON_IJSON_HPP
1995
1996
1998
1999 //
2000 // Created by robin on 08.01.2021.
2001 //
2002
2003 #ifdef INCLUDE_NLOHMANN_JSON_HPP_
2004
2005 #ifndef TILESON_NLOHMANNJSON_HPP
2006 #define TILESON_NLOHMANNJSON_HPP
2007
2008namespace tson {
2009 class NlohmannJson : public tson::IJson {
2010 public:
2011 inline NlohmannJson() = default;
2012
2013 IJson &operator[](std::string_view key) override
2014 {
2015 if (m_arrayCache.count(key.data()) == 0) m_arrayCache[key.data()] = std::make_unique<NlohmannJson>(&m_json->operator[](key.data())); //.front());
2016
2017 return *m_arrayCache[key.data()].get();
2018 }
2019
2020 inline explicit NlohmannJson(nlohmann::json *json) : m_json {json} {}
2021
2022 inline IJson &at(std::string_view key) override
2023 {
2024 if (m_arrayCache.count(key.data()) == 0) m_arrayCache[key.data()] = std::make_unique<NlohmannJson>(&m_json->operator[](key.data())); //.front());
2025
2026 return *m_arrayCache[key.data()].get();
2027 }
2028
2029 inline IJson &at(size_t pos) override
2030 {
2031 if (m_arrayPosCache.count(pos) == 0) m_arrayPosCache[pos] = std::make_unique<NlohmannJson>(&m_json->at(pos));
2032
2033 return *m_arrayPosCache[pos];
2034 }
2035
2036 std::vector<std::unique_ptr<IJson>> array() override
2037 {
2038 std::vector<std::unique_ptr<IJson>> vec;
2039 for (auto &item : *m_json) {
2040 nlohmann::json *ptr = &item;
2041 vec.emplace_back(std::make_unique<NlohmannJson>(ptr));
2042 }
2043
2044 return vec;
2045 }
2046
2047 inline std::vector<std::unique_ptr<IJson>> &array(std::string_view key) override
2048 {
2049 if (m_arrayListDataCache.count(key.data()) == 0) {
2050 if (m_json->count(key.data()) > 0 && m_json->operator[](key.data()).is_array()) {
2051 std::for_each(m_json->operator[](key.data()).begin(), m_json->operator[](key.data()).end(), [&](nlohmann::json &item) {
2052 nlohmann::json *ptr = &item;
2053 m_arrayListDataCache[key.data()].emplace_back(std::make_unique<NlohmannJson>(ptr));
2054 });
2055 }
2056 }
2057
2058 return m_arrayListDataCache[key.data()];
2059 }
2060
2061 [[nodiscard]]
2062 inline size_t size() const override
2063 {
2064 return m_json->size();
2065 }
2066
2067 inline bool parse(const fs::path &path) override
2068 {
2069 clearCache();
2070 m_data = nullptr;
2071 m_json = nullptr;
2072 if (fs::exists(path) && fs::is_regular_file(path)) {
2073 m_path = path.parent_path();
2074 m_data = std::make_unique<nlohmann::json>();
2075 std::ifstream i(path.generic_string());
2076 try {
2077 i >> *m_data;
2078 m_json = m_data.get();
2079 } catch (const nlohmann::json::parse_error &error) {
2080 std::string message = "Parse error: ";
2081 message += std::string(error.what());
2082 message += std::string("\n");
2083 std::cerr << message;
2084 return false;
2085 }
2086 return true;
2087 }
2088 return false;
2089 }
2090
2091 inline bool parse(const void *data, size_t size) override
2092 {
2093 clearCache();
2094 m_json = nullptr;
2095 m_data = std::make_unique<nlohmann::json>();
2096 tson::MemoryStream mem {(uint8_t *) data, size};
2097 try {
2098 mem >> *m_data;
2099 m_json = m_data.get();
2100 } catch (const nlohmann::json::parse_error &error) {
2101 std::string message = "Parse error: ";
2102 message += std::string(error.what());
2103 message += std::string("\n");
2104 std::cerr << message;
2105 return false;
2106 }
2107 return true;
2108 }
2109
2110 [[nodiscard]]
2111 inline size_t count(std::string_view key) const override
2112 {
2113 return m_json->count(key);
2114 }
2115
2116 [[nodiscard]]
2117 inline bool any(std::string_view key) const override
2118 {
2119 return count(key) > 0;
2120 }
2121
2122 [[nodiscard]]
2123 inline bool isArray() const override
2124 {
2125 return m_json->is_array();
2126 }
2127
2128 [[nodiscard]]
2129 inline bool isObject() const override
2130 {
2131 return m_json->is_object();
2132 }
2133
2134 [[nodiscard]]
2135 inline bool isNull() const override
2136 {
2137 return m_json->is_null();
2138 }
2139
2140 fs::path directory() const override { return m_path; }
2141
2142 void directory(const fs::path &directory) override { m_path = directory; }
2143
2144 protected:
2145 [[nodiscard]]
2146 inline int32_t getInt32(std::string_view key) override
2147 {
2148 return m_json->operator[](key.data()).get<int32_t>();
2149 }
2150
2151 [[nodiscard]]
2152 inline uint32_t getUInt32(std::string_view key) override
2153 {
2154 return m_json->operator[](key.data()).get<uint32_t>();
2155 }
2156
2157 [[nodiscard]]
2158 inline int64_t getInt64(std::string_view key) override
2159 {
2160 return m_json->operator[](key.data()).get<int64_t>();
2161 }
2162
2163 [[nodiscard]]
2164 inline uint64_t getUInt64(std::string_view key) override
2165 {
2166 return m_json->operator[](key.data()).get<uint64_t>();
2167 }
2168
2169 [[nodiscard]]
2170 inline double getDouble(std::string_view key) override
2171 {
2172 return m_json->operator[](key.data()).get<double>();
2173 }
2174
2175 [[nodiscard]]
2176 inline std::string getString(std::string_view key) override
2177 {
2178 return m_json->operator[](key.data()).get<std::string>();
2179 }
2180
2181 [[nodiscard]]
2182 inline bool getBool(std::string_view key) override
2183 {
2184 return m_json->operator[](key.data()).get<bool>();
2185 }
2186
2187 [[nodiscard]]
2188 float getFloat(std::string_view key) override
2189 {
2190 return m_json->operator[](key.data()).get<float>();
2191 }
2192
2193 [[nodiscard]]
2194 inline int32_t getInt32() override
2195 {
2196 return m_json->get<int32_t>();
2197 }
2198
2199 [[nodiscard]]
2200 inline uint32_t getUInt32() override
2201 {
2202 return m_json->get<uint32_t>();
2203 }
2204
2205 [[nodiscard]]
2206 inline int64_t getInt64() override
2207 {
2208 return m_json->get<int64_t>();
2209 }
2210
2211 [[nodiscard]]
2212 inline uint64_t getUInt64() override
2213 {
2214 return m_json->get<uint64_t>();
2215 }
2216
2217 [[nodiscard]]
2218 inline double getDouble() override
2219 {
2220 return m_json->get<double>();
2221 }
2222
2223 [[nodiscard]]
2224 inline std::string getString() override
2225 {
2226 return m_json->get<std::string>();
2227 }
2228
2229 [[nodiscard]]
2230 inline bool getBool() override
2231 {
2232 return m_json->get<bool>();
2233 }
2234
2235 [[nodiscard]]
2236 float getFloat() override
2237 {
2238 return m_json->get<float>();
2239 }
2240
2241 private:
2242 inline void clearCache()
2243 {
2244 m_arrayCache.clear();
2245 m_arrayPosCache.clear();
2246 m_arrayListDataCache.clear();
2247 }
2248
2249 nlohmann::json *m_json = nullptr;
2250 std::unique_ptr<nlohmann::json> m_data = nullptr; // Only used if this is the owner json!
2251 fs::path m_path;
2252
2253 // Cache!
2254 std::map<std::string, std::unique_ptr<IJson>> m_arrayCache;
2255 std::map<size_t, std::unique_ptr<IJson>> m_arrayPosCache;
2256 std::map<std::string, std::vector<std::unique_ptr<IJson>>> m_arrayListDataCache;
2257 };
2258} // namespace tson
2259 #endif // TILESON_NLOHMANNJSON_HPP
2260
2261 #endif // INCLUDE_NLOHMANN_JSON_HPP_
2262
2264
2265 //
2266 // Created by robin on 11.01.2021.
2267 //
2268
2269 #ifdef picojson_h
2270 #ifndef TILESON_PICOJSON_HPP
2271 #define TILESON_PICOJSON_HPP
2272
2273namespace tson {
2274 class PicoJson : public tson::IJson {
2275 public:
2276 inline PicoJson() = default;
2277
2278 IJson &operator[](std::string_view key) override
2279 {
2280 if (m_arrayCache.count(key.data()) == 0) {
2281 if (m_json->is<picojson::object>()) {
2282 picojson::object &o = m_json->get<picojson::object>();
2283 m_arrayCache[key.data()] = std::make_unique<PicoJson>(&o[key.data()]);
2284 }
2285 }
2286
2287 return *m_arrayCache[key.data()].get();
2288 }
2289
2290 inline explicit PicoJson(picojson::value *json) : m_json {json} {}
2291
2292 inline IJson &at(std::string_view key) override
2293 {
2294 if (m_arrayCache.count(key.data()) == 0) {
2295 if (m_json->is<picojson::object>()) {
2296 picojson::object &o = m_json->get<picojson::object>();
2297 m_arrayCache[key.data()] = std::make_unique<PicoJson>(&o[key.data()]);
2298 }
2299 }
2300 return *m_arrayCache[key.data()].get();
2301 }
2302
2303 inline IJson &at(size_t pos) override
2304 {
2305 if (m_arrayPosCache.count(pos) == 0) {
2306 picojson::array &a = m_json->get<picojson::array>();
2307 m_arrayPosCache[pos] = std::make_unique<PicoJson>(&a.at(pos));
2308 }
2309
2310 return *m_arrayPosCache[pos];
2311 }
2312
2313 std::vector<std::unique_ptr<IJson>> array() override
2314 {
2315 std::vector<std::unique_ptr<IJson>> vec;
2316 if (m_json->is<picojson::array>()) {
2317 picojson::array &a = m_json->get<picojson::array>();
2318 for (auto &item : a) {
2319 picojson::value *ptr = &item;
2320 vec.emplace_back(std::make_unique<PicoJson>(ptr));
2321 }
2322 }
2323
2324 return vec;
2325 }
2326
2327 inline std::vector<std::unique_ptr<IJson>> &array(std::string_view key) override
2328 {
2329 if (m_arrayListDataCache.count(key.data()) == 0) {
2330 if (count(key.data()) > 0) {
2331 if (isObject()) {
2332 picojson::object &obj = m_json->get<picojson::object>();
2333 picojson::value &v = obj.at(key.data());
2334 bool isArray = v.is<picojson::array>();
2335 if (isArray) {
2336 picojson::array &a = v.get<picojson::array>();
2337
2338 std::for_each(a.begin(), a.end(), [&](picojson::value &item) {
2339 picojson::value *ptr = &item;
2340 m_arrayListDataCache[key.data()].emplace_back(std::make_unique<PicoJson>(ptr));
2341 });
2342 }
2343 }
2344 }
2345 }
2346
2347 return m_arrayListDataCache[key.data()];
2348 }
2349
2350 [[nodiscard]]
2351 inline size_t size() const override
2352 {
2353 if (m_json->is<picojson::object>()) {
2354 picojson::object obj = m_json->get<picojson::object>();
2355 return obj.size();
2356 }
2357 return 0;
2358 }
2359
2360 inline bool parse(const fs::path &path) override
2361 {
2362 clearCache();
2363 m_data = nullptr;
2364 m_json = nullptr;
2365 if (fs::exists(path) && fs::is_regular_file(path)) {
2366 m_path = path.parent_path();
2367 m_data = std::make_unique<picojson::value>();
2368 std::ifstream i(path.generic_string());
2369 try {
2370 std::string error = picojson::parse(*m_data, i);
2371 if (!error.empty()) {
2372 std::cerr << "PicoJson parse error: " << error << "\n";
2373 return false;
2374 }
2375 // i >> *m_data;
2376 m_json = m_data.get();
2377 } catch (const std::exception &error) {
2378 std::string message = "Parse error: ";
2379 message += std::string(error.what());
2380 message += std::string("\n");
2381 std::cerr << message;
2382 return false;
2383 }
2384 return true;
2385 }
2386 return false;
2387 }
2388
2389 inline bool parse(const void *data, size_t size) override
2390 {
2391 clearCache();
2392 m_json = nullptr;
2393 m_data = std::make_unique<picojson::value>();
2394 tson::MemoryStream mem {(uint8_t *) data, size};
2395 try {
2396 std::string error = picojson::parse(*m_data, mem);
2397 if (!error.empty()) {
2398 std::cerr << "PicoJson parse error: " << error << "\n";
2399 return false;
2400 }
2401 // mem >> *m_data;
2402 m_json = m_data.get();
2403 } catch (const std::exception &error) {
2404 std::string message = "Parse error: ";
2405 message += std::string(error.what());
2406 message += std::string("\n");
2407 std::cerr << message;
2408 return false;
2409 }
2410 return true;
2411 }
2412
2413 [[nodiscard]]
2414 inline size_t count(std::string_view key) const override
2415 {
2416 if (isObject()) {
2417 picojson::object obj = m_json->get<picojson::object>();
2418 return obj.count(key.data());
2419 }
2420
2421 return m_json->contains(key.data()) ? 1 : 0;
2422 }
2423
2424 [[nodiscard]]
2425 inline bool any(std::string_view key) const override
2426 {
2427 return count(key) > 0;
2428 }
2429
2430 [[nodiscard]]
2431 inline bool isArray() const override
2432 {
2433 return m_json->is<picojson::array>();
2434 }
2435
2436 [[nodiscard]]
2437 inline bool isObject() const override
2438 {
2439 return m_json->is<picojson::object>();
2440 }
2441
2442 [[nodiscard]]
2443 inline bool isNull() const override
2444 {
2445 return m_json->is<picojson::null>();
2446 }
2447
2448 fs::path directory() const override { return m_path; }
2449
2450 void directory(const fs::path &directory) override { m_path = directory; }
2451
2452 protected:
2453 [[nodiscard]]
2454 inline int32_t getInt32(std::string_view key) override
2455 {
2456 picojson::object obj = m_json->get<picojson::object>();
2457 return static_cast<int32_t>(getDouble(key));
2458 }
2459
2460 [[nodiscard]]
2461 inline uint32_t getUInt32(std::string_view key) override
2462 {
2463 picojson::object obj = m_json->get<picojson::object>();
2464 return static_cast<uint32_t>(getDouble(key));
2465 }
2466
2467 [[nodiscard]]
2468 inline int64_t getInt64(std::string_view key) override
2469 {
2470 picojson::object obj = m_json->get<picojson::object>();
2471 return static_cast<int64_t>(getDouble(key));
2472 }
2473
2474 [[nodiscard]]
2475 inline uint64_t getUInt64(std::string_view key) override
2476 {
2477 picojson::object obj = m_json->get<picojson::object>();
2478 return static_cast<uint64_t>(getDouble(key));
2479 }
2480
2481 [[nodiscard]]
2482 inline double getDouble(std::string_view key) override
2483 {
2484 picojson::object obj = m_json->get<picojson::object>();
2485 return obj[key.data()].get<double>();
2486 }
2487
2488 [[nodiscard]]
2489 inline std::string getString(std::string_view key) override
2490 {
2491 picojson::object obj = m_json->get<picojson::object>();
2492 return obj[key.data()].get<std::string>();
2493 }
2494
2495 [[nodiscard]]
2496 inline bool getBool(std::string_view key) override
2497 {
2498 picojson::object obj = m_json->get<picojson::object>();
2499 return obj[key.data()].get<bool>();
2500 }
2501
2502 [[nodiscard]]
2503 float getFloat(std::string_view key) override
2504 {
2505 picojson::object obj = m_json->get<picojson::object>();
2506 return static_cast<float>(getDouble(key));
2507 }
2508
2509 [[nodiscard]]
2510 inline int32_t getInt32() override
2511 {
2512 return static_cast<int32_t>(getDouble());
2513 }
2514
2515 [[nodiscard]]
2516 inline uint32_t getUInt32() override
2517 {
2518 return static_cast<uint32_t>(getDouble());
2519 }
2520
2521 [[nodiscard]]
2522 inline int64_t getInt64() override
2523 {
2524 return static_cast<int64_t>(getDouble());
2525 }
2526
2527 [[nodiscard]]
2528 inline uint64_t getUInt64() override
2529 {
2530 return static_cast<uint64_t>(getDouble());
2531 }
2532
2533 [[nodiscard]]
2534 inline double getDouble() override
2535 {
2536 return m_json->get<double>();
2537 }
2538
2539 [[nodiscard]]
2540 inline std::string getString() override
2541 {
2542 return m_json->get<std::string>();
2543 }
2544
2545 [[nodiscard]]
2546 inline bool getBool() override
2547 {
2548 return m_json->get<bool>();
2549 }
2550
2551 [[nodiscard]]
2552 float getFloat() override
2553 {
2554 return static_cast<float>(getDouble());
2555 }
2556
2557 private:
2558 inline void clearCache()
2559 {
2560 m_arrayCache.clear();
2561 m_arrayPosCache.clear();
2562 m_arrayListDataCache.clear();
2563 }
2564
2565 picojson::value *m_json = nullptr;
2566 std::unique_ptr<picojson::value> m_data = nullptr; // Only used if this is the owner json!
2567 fs::path m_path;
2568
2569 // Cache!
2570 std::map<std::string, std::unique_ptr<IJson>> m_arrayCache;
2571 std::map<size_t, std::unique_ptr<IJson>> m_arrayPosCache;
2572 std::map<std::string, std::vector<std::unique_ptr<IJson>>> m_arrayListDataCache;
2573 };
2574} // namespace tson
2575 #endif // TILESON_PICOJSON_HPP
2576 #endif
2577
2578
2580 // #include "../json/Gason.hpp" //Unsupported
2581
2582
2583 //
2584 // Created by robin on 16.01.2021.
2585 //
2586
2587 #ifndef TILESON_JSON11_HPP
2588 #define TILESON_JSON11_HPP
2589
2590namespace tson {
2591 class Json11 : public tson::IJson {
2592 public:
2593 inline Json11() = default;
2594
2595 IJson &operator[](std::string_view key) override
2596 {
2597 if (m_arrayCache.count(key.data()) == 0) {
2598 if (m_json->is_object()) {
2599 m_arrayCache[key.data()] = std::make_unique<Json11>(m_json->operator[](key.data()));
2600 }
2601 }
2602
2603 return *m_arrayCache[key.data()].get();
2604 }
2605
2606 inline explicit Json11(const json11::Json &json) : m_json {&json} {}
2607
2608 inline IJson &at(std::string_view key) override
2609 {
2610 if (m_arrayCache.count(key.data()) == 0) {
2611 if (m_json->is_object()) {
2612 m_arrayCache[key.data()] = std::make_unique<Json11>(m_json->operator[](key.data()));
2613 }
2614 }
2615 return *m_arrayCache[key.data()].get();
2616 }
2617
2618 inline IJson &at(size_t pos) override
2619 {
2620 if (m_arrayPosCache.count(pos) == 0) {
2621 const std::vector<json11::Json> &a = m_json->array_items();
2622 m_arrayPosCache[pos] = std::make_unique<Json11>(a.at(pos));
2623 }
2624
2625 return *m_arrayPosCache[pos];
2626 }
2627
2628 std::vector<std::unique_ptr<IJson>> array() override
2629 {
2630 std::vector<std::unique_ptr<IJson>> vec;
2631 if (m_json->is_array()) {
2632 for (const json11::Json &item : m_json->array_items()) {
2633 vec.emplace_back(std::make_unique<Json11>(item));
2634 }
2635 }
2636
2637 return vec;
2638 }
2639
2640 inline std::vector<std::unique_ptr<IJson>> &array(std::string_view key) override
2641 {
2642 if (m_arrayListDataCache.count(key.data()) == 0) {
2643 if (count(key.data()) > 0) {
2644 if (isObject()) {
2645 const json11::Json &v = m_json->operator[](key.data());
2646 if (v.is_array()) {
2647 for (const json11::Json &item : v.array_items()) {
2648 m_arrayListDataCache[key.data()].emplace_back(std::make_unique<Json11>(item));
2649 }
2650 }
2651 }
2652 }
2653 }
2654
2655 return m_arrayListDataCache[key.data()];
2656 }
2657
2658 [[nodiscard]]
2659 inline size_t size() const override
2660 {
2661 if (m_json->is_object())
2662 return m_json->object_items().size();
2663 else if (m_json->is_array())
2664 return m_json->array_items().size();
2665
2666 return 0;
2667 }
2668
2669 inline bool parse(const fs::path &path) override
2670 {
2671 clearCache();
2672 m_data = nullptr;
2673 m_json = nullptr;
2674 if (fs::exists(path) && fs::is_regular_file(path)) {
2675 std::ifstream file(path.generic_string());
2676 std::string str;
2677 m_path = path.parent_path();
2678
2679 file.seekg(0, std::ios::end);
2680 str.reserve(static_cast<size_t>(file.tellg()));
2681 file.seekg(0, std::ios::beg);
2682
2683 str.assign((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
2684
2685 m_data = std::make_unique<json11::Json>();
2686
2687 try {
2688 std::string strError;
2689 *m_data = json11::Json::parse(str, strError);
2690 if (!strError.empty()) {
2691 std::cerr << strError << "\n";
2692 return false;
2693 }
2694 m_json = m_data.get();
2695 } catch (const std::exception &error) {
2696 std::string message = "Json11 parse error: ";
2697 message += std::string(error.what());
2698 message += std::string("\n");
2699 std::cerr << message;
2700 return false;
2701 }
2702 return true;
2703 }
2704 return false;
2705 }
2706
2707 inline bool parse(const void *data, size_t size) override
2708 {
2709 clearCache();
2710 m_json = nullptr;
2711 std::string str;
2712
2713 str.reserve(size);
2714
2715 tson::MemoryStream mem {(uint8_t *) data, size};
2716
2717 str.assign((std::istreambuf_iterator<char>(mem)), std::istreambuf_iterator<char>());
2718
2719 m_data = std::make_unique<json11::Json>();
2720
2721 try {
2722 std::string strError;
2723
2724 *m_data = json11::Json::parse(str, strError);
2725 if (!strError.empty()) {
2726 std::cout << strError << "\n";
2727 return false;
2728 }
2729 m_json = m_data.get();
2730 } catch (const std::exception &error) {
2731 std::string message = "Json11 parse error: ";
2732 message += std::string(error.what());
2733 message += std::string("\n");
2734 std::cerr << message;
2735 return false;
2736 }
2737 return true;
2738 }
2739
2740 [[nodiscard]]
2741 inline size_t count(std::string_view key) const override
2742 {
2743 if (isObject()) {
2744 // const json11::Json &j = m_json->operator[](key.data());
2745 // size_t s1 = j.object_items().size();
2746 return m_json->object_items().count(key.data());
2747 }
2748
2749 return 0;
2750 }
2751
2752 [[nodiscard]]
2753 inline bool any(std::string_view key) const override
2754 {
2755 return count(key) > 0;
2756 }
2757
2758 [[nodiscard]]
2759 inline bool isArray() const override
2760 {
2761 return m_json->is_array();
2762 }
2763
2764 [[nodiscard]]
2765 inline bool isObject() const override
2766 {
2767 return m_json->is_object();
2768 }
2769
2770 [[nodiscard]]
2771 inline bool isNull() const override
2772 {
2773 return m_json->is_null();
2774 }
2775
2776 fs::path directory() const override { return m_path; }
2777
2778 void directory(const fs::path &directory) override { m_path = directory; }
2779
2780 protected:
2781 [[nodiscard]]
2782 inline int32_t getInt32(std::string_view key) override
2783 {
2784 return static_cast<int32_t>(getDouble(key));
2785 }
2786
2787 [[nodiscard]]
2788 inline uint32_t getUInt32(std::string_view key) override
2789 {
2790 return static_cast<uint32_t>(getDouble(key));
2791 }
2792
2793 [[nodiscard]]
2794 inline int64_t getInt64(std::string_view key) override
2795 {
2796 return static_cast<int64_t>(getDouble(key));
2797 }
2798
2799 [[nodiscard]]
2800 inline uint64_t getUInt64(std::string_view key) override
2801 {
2802 return static_cast<uint64_t>(getDouble(key));
2803 }
2804
2805 [[nodiscard]]
2806 inline double getDouble(std::string_view key) override
2807 {
2808 return m_json->operator[](key.data()).number_value();
2809 }
2810
2811 [[nodiscard]]
2812 inline std::string getString(std::string_view key) override
2813 {
2814 return m_json->operator[](key.data()).string_value(); // .get<std::string>();
2815 }
2816
2817 [[nodiscard]]
2818 inline bool getBool(std::string_view key) override
2819 {
2820 return m_json->operator[](key.data()).bool_value();
2821 }
2822
2823 [[nodiscard]]
2824 float getFloat(std::string_view key) override
2825 {
2826 return static_cast<float>(getDouble(key));
2827 }
2828
2829 [[nodiscard]]
2830 inline int32_t getInt32() override
2831 {
2832 return static_cast<int32_t>(getDouble());
2833 }
2834
2835 [[nodiscard]]
2836 inline uint32_t getUInt32() override
2837 {
2838 return static_cast<uint32_t>(getDouble());
2839 }
2840
2841 [[nodiscard]]
2842 inline int64_t getInt64() override
2843 {
2844 return static_cast<int64_t>(getDouble());
2845 }
2846
2847 [[nodiscard]]
2848 inline uint64_t getUInt64() override
2849 {
2850 return static_cast<uint64_t>(getDouble());
2851 }
2852
2853 [[nodiscard]]
2854 inline double getDouble() override
2855 {
2856 return m_json->number_value();
2857 }
2858
2859 [[nodiscard]]
2860 inline std::string getString() override
2861 {
2862 return m_json->string_value();
2863 }
2864
2865 [[nodiscard]]
2866 inline bool getBool() override
2867 {
2868 return m_json->bool_value();
2869 }
2870
2871 [[nodiscard]]
2872 float getFloat() override
2873 {
2874 return static_cast<float>(getDouble());
2875 }
2876
2877 private:
2878 inline void clearCache()
2879 {
2880 m_arrayCache.clear();
2881 m_arrayPosCache.clear();
2882 m_arrayListDataCache.clear();
2883 }
2884
2885 // Owner values
2886 std::unique_ptr<json11::Json> m_data = nullptr; // Only used if this is the owner json!
2887
2888 const json11::Json *m_json = nullptr;
2889 fs::path m_path;
2890
2891 // Cache!
2892 std::map<std::string, std::unique_ptr<IJson>> m_arrayCache;
2893 std::map<size_t, std::unique_ptr<IJson>> m_arrayPosCache;
2894 std::map<std::string, std::vector<std::unique_ptr<IJson>>> m_arrayListDataCache;
2895 };
2896} // namespace tson
2897
2898 #endif // TILESON_JSON11_HPP
2899
2900
2902
2903 //
2904 // Created by robin on 22.03.2020.
2905 //
2906
2907 #ifndef TILESON_LAYER_HPP
2908 #define TILESON_LAYER_HPP
2909
2910 #include <set>
2911 // #include "../external/json.hpp"
2912
2913
2914 //
2915 // Created by robin on 22.03.2020.
2916 //
2917
2918 #ifndef TILESON_CHUNK_HPP
2919 #define TILESON_CHUNK_HPP
2920
2921// #include "../external/json.hpp"
2922
2923namespace tson {
2924 class Chunk {
2925 public:
2926 inline Chunk() = default;
2927 inline explicit Chunk(IJson &json);
2928 inline bool parse(IJson &json);
2929
2930 [[nodiscard]]
2931 inline const std::vector<int> &getData() const;
2932 [[nodiscard]]
2933 inline const std::string &getBase64Data() const;
2934 [[nodiscard]]
2935 inline const Vector2i &getSize() const;
2936 [[nodiscard]]
2937 inline const Vector2i &getPosition() const;
2938
2939 private:
2940 std::vector<int> m_data;
2941 std::string m_base64Data;
2944 };
2945} // namespace tson
2946
2947 #endif // TILESON_CHUNK_HPP
2948
2953tson::Chunk::Chunk(IJson &json)
2954{
2955 parse(json);
2956}
2957
2964{
2965 bool allFound = true;
2966
2967 if (json.count("width") > 0 && json.count("height") > 0)
2968 m_size = {json["width"].get<int>(), json["height"].get<int>()};
2969 else
2970 allFound = false;
2971 if (json.count("x") > 0 && json.count("y") > 0)
2972 m_position = {json["x"].get<int>(), json["y"].get<int>()};
2973 else
2974 allFound = false;
2975
2976 // Handle DATA (Optional)
2977 if (json.count("data") > 0) {
2978 if (json["data"].isArray()) {
2979 auto &data = json.array("data");
2980 std::for_each(data.begin(), data.end(), [&](std::unique_ptr<IJson> &item) { m_data.push_back(item->get<int>()); });
2981 } else
2982 m_base64Data = json["data"].get<std::string>();
2983 }
2984
2985 return allFound;
2986}
2987
2992const std::vector<int> &tson::Chunk::getData() const
2993{
2994 return m_data;
2995}
2996
3001const std::string &tson::Chunk::getBase64Data() const
3002{
3003 return m_base64Data;
3004}
3005
3011{
3012 return m_size;
3013}
3014
3020{
3021 return m_position;
3022}
3023
3024
3026
3027 //
3028 // Created by robin on 22.03.2020.
3029 //
3030
3031 #ifndef TILESON_OBJECT_HPP
3032 #define TILESON_OBJECT_HPP
3033
3034 // #include "../external/json.hpp"
3035
3036
3037 //
3038 // Created by robin on 22.03.2020.
3039 //
3040
3041 #ifndef TILESON_PROPERTYCOLLECTION_HPP
3042 #define TILESON_PROPERTYCOLLECTION_HPP
3043
3044
3045 //
3046 // Created by robin on 22.03.2020.
3047 //
3048
3049 #ifndef TILESON_PROPERTY_HPP
3050 #define TILESON_PROPERTY_HPP
3051
3052 // #include "../../TilesonConfig.h"
3053
3054 // #if USE_CPP17_FILESYSTEM
3055
3056 #include <any>
3057 #include <string>
3058
3059
3060 //
3061 // Created by robin on 22.03.2020.
3062 //
3063
3064 #ifndef TILESON_ENUMS_HPP
3065 #define TILESON_ENUMS_HPP
3066 #include <cstdint>
3067
3068
3069 //
3070 // Created by robin on 08.11.2020.
3071 //
3072
3073 #ifndef TILESON_ENUMBITFLAGS_HPP
3074 #define TILESON_ENUMBITFLAGS_HPP
3075
3076 #include <iostream>
3077 #include <type_traits>
3078
3079 #define TILESON_ENABLE_BITMASK_OPERATORS(x) \
3080 namespace tson { \
3081 ENABLE_BITMASK_OPERATORS(x) \
3082 }
3083
3084namespace tson {
3085 #define ENABLE_BITMASK_OPERATORS(x) \
3086 template<> \
3087 struct EnableBitMaskOperators<x> { \
3088 static const bool enable = true; \
3089 };
3090
3091 template<typename Enum>
3093 static const bool enable = false;
3094 };
3095
3096 template<typename Enum>
3097 typename std::enable_if<EnableBitMaskOperators<Enum>::enable, Enum>::type operator|(Enum lhs, Enum rhs)
3098 {
3099 static_assert(std::is_enum<Enum>::value, "template parameter is not an enum type");
3100
3101 using underlying = typename std::underlying_type<Enum>::type;
3102
3103 return static_cast<Enum>(static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
3104 }
3105
3106 // Permissions operator &(Permissions lhs, Permissions rhs)
3107 template<typename Enum>
3108 typename std::enable_if<EnableBitMaskOperators<Enum>::enable, Enum>::type operator&(Enum lhs, Enum rhs)
3109 {
3110 static_assert(std::is_enum<Enum>::value, "template parameter is not an enum type");
3111
3112 using underlying = typename std::underlying_type<Enum>::type;
3113
3114 return static_cast<Enum>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
3115 }
3116
3117 // Permissions operator ^(Permissions lhs, Permissions rhs)
3118 template<typename Enum>
3119 typename std::enable_if<EnableBitMaskOperators<Enum>::enable, Enum>::type operator^(Enum lhs, Enum rhs)
3120 {
3121 static_assert(std::is_enum<Enum>::value, "template parameter is not an enum type");
3122
3123 using underlying = typename std::underlying_type<Enum>::type;
3124
3125 return static_cast<Enum>(static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs));
3126 }
3127
3128 // Permissions operator ~(Permissions rhs)
3129 template<typename Enum>
3130 typename std::enable_if<EnableBitMaskOperators<Enum>::enable, Enum>::type operator~(Enum rhs)
3131 {
3132 static_assert(std::is_enum<Enum>::value, "template parameter is not an enum type");
3133
3134 using underlying = typename std::underlying_type<Enum>::type;
3135
3136 return static_cast<Enum>(~static_cast<underlying>(rhs));
3137 }
3138
3139 // Permissions& operator |=(Permissions &lhs, Permissions rhs)
3140 template<typename Enum>
3141 typename std::enable_if<EnableBitMaskOperators<Enum>::enable, Enum>::type &operator|=(Enum &lhs, Enum rhs)
3142 {
3143 static_assert(std::is_enum<Enum>::value, "template parameter is not an enum type");
3144
3145 using underlying = typename std::underlying_type<Enum>::type;
3146
3147 lhs = static_cast<Enum>(static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
3148
3149 return lhs;
3150 }
3151
3152 // Permissions& operator &=(Permissions &lhs, Permissions rhs)
3153 template<typename Enum>
3154 typename std::enable_if<EnableBitMaskOperators<Enum>::enable, Enum>::type &operator&=(Enum &lhs, Enum rhs)
3155 {
3156 static_assert(std::is_enum<Enum>::value, "template parameter is not an enum type");
3157
3158 using underlying = typename std::underlying_type<Enum>::type;
3159
3160 lhs = static_cast<Enum>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
3161
3162 return lhs;
3163 }
3164
3165 // Permissions& operator ^=(Permissions &lhs, Permissions rhs)
3166 template<typename Enum>
3167 typename std::enable_if<EnableBitMaskOperators<Enum>::enable, Enum>::type &operator^=(Enum &lhs, Enum rhs)
3168 {
3169 static_assert(std::is_enum<Enum>::value, "template parameter is not an enum type");
3170
3171 using underlying = typename std::underlying_type<Enum>::type;
3172
3173 lhs = static_cast<Enum>(static_cast<underlying>(lhs) ^ static_cast<underlying>(rhs));
3174
3175 return lhs;
3176 }
3177} // namespace tson
3178
3179 #endif // TILESON_ENUMBITFLAGS_HPP
3180
3181
3183namespace tson {
3187 enum class Type : uint8_t {
3188 Undefined = 0,
3189 Color = 1,
3190 File = 2,
3191 Int = 3,
3192 Boolean = 4,
3193 Float = 5,
3194 String = 6,
3195 Class = 7,
3196 Enum = 8,
3197 Object = 9
3198 };
3199
3204 enum class LayerType : uint8_t {
3205 Undefined = 0,
3206 TileLayer = 1,
3207 ObjectGroup = 2,
3208 ImageLayer = 3,
3209 Group = 4
3210 };
3211
3215 enum class ParseStatus : uint8_t {
3216 OK = 0, // OK unless otherwise stated
3217 FileNotFound = 1,
3218 ParseError = 2,
3219 MissingData = 3,
3220 DecompressionError = 4
3221 };
3222
3226 enum class ObjectType : uint8_t {
3227 Undefined = 0,
3228 Object = 1,
3229 Ellipse = 2,
3230 Rectangle = 3,
3231 Point = 4,
3232 Polygon = 5,
3233 Polyline = 6,
3234 Text = 7,
3235 Template = 8
3236 };
3237
3238 static constexpr uint32_t FLIPPED_HORIZONTALLY_FLAG = 0x80000000;
3239 static constexpr uint32_t FLIPPED_VERTICALLY_FLAG = 0x40000000;
3240 static constexpr uint32_t FLIPPED_DIAGONALLY_FLAG = 0x20000000;
3244 enum class TileFlipFlags : uint32_t {
3245 None = 0,
3246 Diagonally = FLIPPED_DIAGONALLY_FLAG,
3247 Vertically = FLIPPED_VERTICALLY_FLAG,
3248 Horizontally = FLIPPED_HORIZONTALLY_FLAG
3249 };
3250
3254 enum class ObjectAlignment : uint8_t {
3255 Unspecified = 0, // unspecified
3256 TopLeft = 1, // topleft
3257 Top = 2, // top
3258 TopRight = 3, // topright
3259 Left = 4, // left
3260 Center = 5, // center
3261 Right = 6, // right
3262 BottomLeft = 7, // bottomleft
3263 Bottom = 8, // bottom
3264 BottomRight = 9 // bottomright
3265 };
3266
3270 enum class TextAlignment : uint8_t {
3271 Unresolved = 0,
3272 Left = 1, // left
3273 Center = 2, // center
3274 Right = 3, // right
3275 Justify = 4, // justify
3276 Top = 5, // top
3277 Bottom = 6 // bottom
3278 };
3279
3283 enum class TileRenderSize : uint8_t {
3284 Undefined = 0,
3285 Tile = 1, // tile (default)
3286 Grid = 2 // grid
3287 };
3288
3292 enum class FillMode : uint8_t {
3293 Undefined = 0,
3294 Stretch = 1, // stretch (default)
3295 PreserveAspectFit = 2 // preserve-aspect-fit
3296 };
3297
3298 enum class EnumStorageType : uint8_t {
3299 Unspecified = 0,
3300 Int = 1,
3301 String = 2
3302 };
3303
3304 ENABLE_BITMASK_OPERATORS(TileFlipFlags)
3305} // namespace tson
3306
3307 #endif // TILESON_ENUMS_HPP
3308
3309
3311// #include "../external/json.hpp"
3312
3313namespace tson {
3314 class Project;
3315
3316 class Property {
3317 public:
3318 // enum class Type : uint8_t
3319 //{
3320 // Undefined = 0,
3321 // Color = 1, /*! color */
3322 // File = 2, /*! file */
3323 // Int = 3, /*! int */
3324 // Boolean = 4, /*! bool */
3325 // Float = 5, /*! float */
3326 // String = 6 /*! string */
3327 // };
3328
3329 inline Property();
3330 inline explicit Property(IJson &json, tson::Project *project = nullptr);
3331 inline Property(std::string name, std::any value, Type type);
3332
3333 inline void setValue(const std::any &value);
3334 inline void setStrValue(const std::string &value);
3335 inline void setName(const std::string &name);
3336
3337 [[nodiscard]]
3338 inline const std::type_info &getValueType() const;
3339 inline std::string getValueTypeInfo();
3340 [[nodiscard]]
3341 inline const std::any &getValue() const;
3342 template<typename T>
3343 inline T getValue() const;
3344 [[nodiscard]]
3345 inline const std::string &getName() const;
3346 [[nodiscard]]
3347 inline Type getType() const;
3348 [[nodiscard]]
3349 inline const std::string &getPropertyType() const;
3350
3351 // Became public in v1.4.0
3352 inline void setValueByType(IJson &json); // Definition in tileson_forward.hpp
3353
3354 protected:
3355 inline void setTypeByString(const std::string &str);
3356
3357 tson::Project *m_project = nullptr; // Used for resolving 'enum' and 'class' objects
3358 Type m_type = Type::Undefined;
3359 std::string m_name {};
3360 std::string m_propertyType {};
3361 std::any m_value; // Using std::any to assign any type
3362 };
3363
3364 template<typename T>
3365 T Property::getValue() const
3366 {
3367 bool isCorrectType = (m_value.type() == typeid(T));
3368
3369 if (isCorrectType) {
3370 T value = std::any_cast<T>(m_value);
3371 return value;
3372 } else {
3373 static T defaultValue;
3374 return defaultValue;
3375 }
3376 }
3377} // namespace tson
3378
3379tson::Property::Property() : m_name {"unnamed"} {}
3380
3381tson::Property::Property(IJson &json, tson::Project *project) : m_project {project}
3382{
3383 m_name = json["name"].get<std::string>();
3384 if (json.count("propertytype") > 0)
3385 m_propertyType = json["propertytype"].get<std::string>();
3386 else if (json.count("propertyType") > 0) // Somehow Tiled's class objects uses propertyType with 'T'.
3387 m_propertyType = json["propertyType"].get<std::string>();
3388
3389 setTypeByString(json["type"].get<std::string>());
3390 setValueByType(json["value"]);
3391}
3392
3393tson::Property::Property(std::string name, std::any value, Type type) : m_type {type}, m_name {move(name)}, m_value {move(value)} {}
3394
3395void tson::Property::setValue(const std::any &value)
3396{
3397 m_value = value;
3398}
3399
3406void tson::Property::setStrValue(const std::string &value)
3407{
3408 m_value = value;
3409}
3410
3411const std::any &tson::Property::getValue() const
3412{
3413 return m_value;
3414}
3415
3416void tson::Property::setName(const std::string &name)
3417{
3418 m_name = name;
3419}
3420
3421const std::string &tson::Property::getName() const
3422{
3423 return m_name;
3424}
3425
3433const std::type_info &tson::Property::getValueType() const
3434{
3435 return m_value.type();
3436}
3437
3447{
3448 return m_value.type().name();
3449}
3450
3451tson::Type tson::Property::getType() const
3452{
3453 return m_type;
3454}
3455
3456void tson::Property::setTypeByString(const std::string &str)
3457{
3458 if (str == "color")
3459 m_type = tson::Type::Color;
3460 else if (str == "file")
3461 m_type = tson::Type::File;
3462 else if (str == "int")
3463 m_type = tson::Type::Int;
3464 else if (str == "bool")
3465 m_type = tson::Type::Boolean;
3466 else if (str == "float")
3467 m_type = tson::Type::Float;
3468 else if (str == "string")
3469 m_type = tson::Type::String;
3470 else if (str == "class")
3471 m_type = tson::Type::Class;
3472 else if (str == "object")
3473 m_type = tson::Type::Object;
3474 else
3475 m_type = tson::Type::Undefined;
3476}
3477
3478const std::string &tson::Property::getPropertyType() const
3479{
3480 return m_propertyType;
3481}
3482
3483 #endif // TILESON_PROPERTY_HPP
3484
3485
3487 // #include "../external/json.hpp"
3488 #include <map>
3489
3490namespace tson {
3492 public:
3493 inline PropertyCollection() = default;
3494
3495 inline explicit PropertyCollection(std::string id);
3496
3497 inline tson::Property *add(const tson::Property &property);
3498 inline tson::Property *add(IJson &json, tson::Project *project = nullptr);
3499 inline tson::Property *add(const std::string &name, const std::any &value, tson::Type type);
3500
3501 inline void remove(const std::string &name);
3502
3503 inline void setValue(const std::string &name, const std::any &value);
3504 inline void setProperty(const std::string &name, const tson::Property &value);
3505 inline void setId(const std::string &id);
3506
3507 inline bool hasProperty(const std::string &name);
3508 inline tson::Property *getProperty(const std::string &name);
3509 inline std::map<std::string, Property> &getProperties();
3510 inline std::vector<Property *> get();
3511 template<typename T>
3512 inline T getValue(const std::string &name);
3513 [[nodiscard]]
3514 inline const std::string &getId() const;
3515 [[nodiscard]]
3516 inline size_t getSize() const;
3517
3518 protected:
3519 std::string m_id;
3520 std::map<std::string, tson::Property> m_properties;
3521 };
3522} // namespace tson
3523
3524template<typename T>
3525T tson::PropertyCollection::getValue(const std::string &name)
3526{
3527 static T defaultT;
3528 return (m_properties.count(name) > 0) ? m_properties[name].getValue<T>() : defaultT;
3529}
3530
3531tson::PropertyCollection::PropertyCollection(std::string id) : m_id {std::move(id)} {}
3532
3533tson::Property *tson::PropertyCollection::add(const tson::Property &property)
3534{
3535 m_properties[property.getName()] = property;
3536 return &m_properties[property.getName()];
3537}
3538
3539tson::Property *tson::PropertyCollection::add(IJson &json, tson::Project *project)
3540{
3541 tson::Property property = tson::Property(json, project);
3542 std::string name = property.getName();
3543 m_properties[name] = std::move(property);
3544 return &m_properties[name];
3545}
3546
3547tson::Property *tson::PropertyCollection::add(const std::string &name, const std::any &value, tson::Type type)
3548{
3549 m_properties[name] = {name, value, type};
3550 return &m_properties[name];
3551}
3552
3553void tson::PropertyCollection::remove(const std::string &name)
3554{
3555 m_properties.erase(name);
3556}
3557
3564void tson::PropertyCollection::setValue(const std::string &name, const std::any &value)
3565{
3566 if (m_properties.count(name) > 0) m_properties[name].setValue(value);
3567}
3568
3574void tson::PropertyCollection::setProperty(const std::string &name, const tson::Property &value)
3575{
3576 m_properties[name] = value;
3577}
3578
3579void tson::PropertyCollection::setId(const std::string &id)
3580{
3581 m_id = id;
3582}
3583
3584bool tson::PropertyCollection::hasProperty(const std::string &name)
3585{
3586 return m_properties.count(name) > 0;
3587}
3588
3589tson::Property *tson::PropertyCollection::getProperty(const std::string &name)
3590{
3591 return (m_properties.count(name) > 0) ? &m_properties[name] : nullptr;
3592}
3593
3594std::map<std::string, tson::Property> &tson::PropertyCollection::getProperties()
3595{
3596 return m_properties;
3597}
3598
3603std::vector<tson::Property *> tson::PropertyCollection::get()
3604{
3605 std::vector<tson::Property *> props;
3606 for (auto &i : m_properties)
3607 props.emplace_back(&i.second);
3608
3609 return props;
3610}
3611
3612const std::string &tson::PropertyCollection::getId() const
3613{
3614 return m_id;
3615}
3616
3617size_t tson::PropertyCollection::getSize() const
3618{
3619 return m_properties.size();
3620}
3621
3622 #endif // TILESON_PROPERTYCOLLECTION_HPP
3623
3624
3626
3627 //
3628 // Created by robin on 05.08.2019.
3629 //
3630
3631 #ifndef TILESON_TEXT_HPP
3632 #define TILESON_TEXT_HPP
3633
3634 #include <string>
3635
3636namespace tson {
3637 class Text {
3638 public:
3639 inline Text() = default;
3640
3646 // inline Text(std::string _text, bool _wrap, tson::Colori _color) : text {std::move(_text)}, wrap {_wrap}, color {_color} {};
3647 inline explicit Text(IJson &json)
3648 {
3649 bool hasColor = json.count("color") > 0;
3650 tson::Color c = (hasColor) ? tson::Colori(json["color"].get<std::string>()) : tson::Colori();
3651 color = c;
3652 text = (json.count("text") > 0) ? json["text"].get<std::string>() : "";
3653 wrap = (json.count("wrap") > 0) ? json["wrap"].get<bool>() : false;
3654
3655 // Previously missing properties
3656 bold = (json.count("bold") > 0) ? json["bold"].get<bool>() : false;
3657 fontFamily = (json.count("fontfamily") > 0) ? json["fontfamily"].get<std::string>() : "sans-serif";
3658 horizontalAlignment = (json.count("halign") > 0) ? resolveTextAlignmentByString(json["halign"].get<std::string>()) : TextAlignment::Left;
3659 italic = (json.count("italic") > 0) ? json["italic"].get<bool>() : false;
3660 kerning = (json.count("kerning") > 0) ? json["kerning"].get<bool>() : true;
3661 pixelSize = (json.count("pixelsize") > 0) ? json["pixelsize"].get<int32_t>() : 16;
3662 strikeout = (json.count("strikeout") > 0) ? json["strikeout"].get<bool>() : false;
3663 underline = (json.count("underline") > 0) ? json["underline"].get<bool>() : false;
3664 verticalAlignment = (json.count("valign") > 0) ? resolveTextAlignmentByString(json["valign"].get<std::string>()) : TextAlignment::Top;
3665 };
3666
3667 // Just make it simple
3668 std::string text {};
3669 tson::Colori color {};
3670 bool wrap {};
3671
3672 // Previously missing properties
3673 bool bold {false};
3674 std::string fontFamily {"sans-serif"};
3675 TextAlignment horizontalAlignment {TextAlignment::Left};
3676 bool italic {false};
3677 bool kerning {true};
3678 int pixelSize {16};
3679 bool strikeout {false};
3680 bool underline {false};
3681 TextAlignment verticalAlignment {TextAlignment::Top};
3682
3683 private:
3684 [[nodiscard]]
3685 TextAlignment resolveTextAlignmentByString(const std::string &str) const
3686 {
3687 if (str == "left") return TextAlignment::Left;
3688 if (str == "center") return TextAlignment::Center;
3689 if (str == "right") return TextAlignment::Right;
3690 if (str == "justify") return TextAlignment::Justify;
3691 if (str == "top") return TextAlignment::Top;
3692 if (str == "bottom") return TextAlignment::Bottom;
3693
3694 return TextAlignment::Unresolved;
3695 }
3696 };
3697} // namespace tson
3698
3699 #endif // TILESON_TEXT_HPP
3700
3701
3703 #include <optional>
3704
3705namespace tson {
3706 class TiledClass;
3707 class Map;
3708
3709 class Object {
3710 public:
3711 // enum class Type : uint8_t
3712 //{
3713 // Undefined = 0,
3714 // Object = 1,
3715 // Ellipse = 2,
3716 // Rectangle = 3,
3717 // Point = 4,
3718 // Polygon = 5,
3719 // Polyline = 6,
3720 // Text = 7,
3721 // Template = 8
3722 // };
3723
3724 inline Object() = default;
3725 inline explicit Object(IJson &json, tson::Map *map);
3726 inline bool parse(IJson &json, tson::Map *map);
3727
3728 [[nodiscard]]
3729 inline ObjectType getObjectType() const;
3730 [[nodiscard]]
3731 inline bool isEllipse() const;
3732 [[nodiscard]]
3733 inline uint32_t getGid() const;
3734 [[nodiscard]]
3735 inline const Vector2i &getSize() const;
3736 [[nodiscard]]
3737 inline int getId() const;
3738 [[nodiscard]]
3739 inline const std::string &getName() const;
3740 [[nodiscard]]
3741 inline bool isPoint() const;
3742 [[nodiscard]]
3743 inline float getRotation() const;
3744 [[nodiscard]]
3745 inline const std::string &getTemplate() const;
3746 [[nodiscard]]
3747 inline const std::string &getType() const;
3748 [[nodiscard]]
3749 inline const std::string &getClassType() const;
3750 [[nodiscard]]
3751 inline tson::TiledClass *getClass();
3752 [[nodiscard]]
3753 inline bool isVisible() const;
3754 [[nodiscard]]
3755 inline const Vector2i &getPosition() const;
3756
3757 [[nodiscard]]
3758 inline const std::vector<tson::Vector2i> &getPolygons() const;
3759 [[nodiscard]]
3760 inline const std::vector<tson::Vector2i> &getPolylines() const;
3761 [[nodiscard]]
3763 [[nodiscard]]
3764 inline const Text &getText() const;
3765
3766 template<typename T>
3767 inline T get(const std::string &name);
3768 inline tson::Property *getProp(const std::string &name);
3769
3770 // v1.2.0-stuff
3771 [[nodiscard]]
3772 inline TileFlipFlags getFlipFlags() const;
3773 inline bool hasFlipFlags(TileFlipFlags flags);
3774
3775 private:
3776 inline void setObjectTypeByJson(IJson &json);
3777
3778 ObjectType m_objectType = ObjectType::Undefined;
3779 bool m_ellipse {};
3780 uint32_t m_gid {};
3782 int m_id {};
3783 std::string m_name;
3784 bool m_point {};
3785 std::vector<tson::Vector2i> m_polygon;
3786 std::vector<tson::Vector2i> m_polyline;
3788 float m_rotation {};
3789 std::string m_template;
3791 std::string m_type;
3792 bool m_visible {};
3795 // v1.2.0-stuff
3796 tson::TileFlipFlags m_flipFlags = TileFlipFlags::None;
3798 tson::Map *m_map {nullptr};
3799 std::shared_ptr<tson::TiledClass> m_class {};
3800 };
3801
3808 template<typename T>
3809 T tson::Object::get(const std::string &name)
3810 {
3811 return m_properties.getValue<T>(name);
3812 }
3813} // namespace tson
3814
3819tson::Object::Object(IJson &json, tson::Map *map)
3820{
3821 parse(json, map);
3822}
3823
3831{
3832 m_map = map;
3833 bool allFound = true;
3834
3835 if (json.count("ellipse") > 0) m_ellipse = json["ellipse"].get<bool>(); // Optional
3836 if (json.count("gid") > 0) {
3837 uint32_t gid = json["gid"].get<uint32_t>(); // Optional
3838 if (gid & FLIPPED_HORIZONTALLY_FLAG) m_flipFlags |= TileFlipFlags::Horizontally;
3839 if (gid & FLIPPED_VERTICALLY_FLAG) m_flipFlags |= TileFlipFlags::Vertically;
3840 if (gid & FLIPPED_DIAGONALLY_FLAG) m_flipFlags |= TileFlipFlags::Diagonally;
3841
3842 // Clear flags
3843 gid &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG);
3844
3845 m_gid = gid;
3846 }
3847 if (json.count("id") > 0)
3848 m_id = json["id"].get<int>();
3849 else
3850 allFound = false;
3851 if (json.count("name") > 0)
3852 m_name = json["name"].get<std::string>();
3853 else
3854 allFound = false;
3855 if (json.count("point") > 0) m_point = json["point"].get<bool>(); // Optional
3856 if (json.count("rotation") > 0)
3857 m_rotation = json["rotation"].get<float>();
3858 else
3859 allFound = false;
3860 if (json.count("template") > 0) m_template = json["template"].get<std::string>(); // Optional
3861
3862 if (json.count("type") > 0)
3863 m_type = json["type"].get<std::string>();
3864 else if (json.count("class") > 0)
3865 m_type = json["class"].get<std::string>(); // Tiled v1.9 renamed 'type' to 'class'
3866 else
3867 allFound = false;
3868
3869 if (json.count("visible") > 0)
3870 m_visible = json["visible"].get<bool>();
3871 else
3872 allFound = false;
3873
3874 if (json.count("width") > 0 && json.count("height") > 0)
3875 m_size = {json["width"].get<int>(), json["height"].get<int>()};
3876 else
3877 allFound = false;
3878 if (json.count("x") > 0 && json.count("y") > 0)
3879 m_position = {json["x"].get<int>(), json["y"].get<int>()};
3880 else
3881 allFound = false;
3882
3883 if (json.count("text") > 0) {
3884 // Old logic
3885 // bool hasColor = json["text"].count("color") > 0;
3886 // tson::Color c = (hasColor) ? tson::Colori(json["text"]["color"].get<std::string>()) : tson::Colori();
3887 // m_text = {json["text"]["text"].get<std::string>(), json["text"]["wrap"].get<bool>(), c}; //Optional
3888 m_text = tson::Text(json["text"]);
3889 //
3890 }
3891
3892 setObjectTypeByJson(json);
3893
3894 if (m_objectType == ObjectType::Template) allFound = true; // Just accept anything with this type
3895
3896 // More advanced data
3897 if (json.count("polygon") > 0 && json["polygon"].isArray()) {
3898 auto &polygon = json.array("polygon");
3899 std::for_each(polygon.begin(), polygon.end(), [&](std::unique_ptr<IJson> &item) {
3900 IJson &j = *item;
3901 m_polygon.emplace_back(j["x"].get<int>(), j["y"].get<int>());
3902 });
3903 }
3904
3905 if (json.count("polyline") > 0 && json["polyline"].isArray()) {
3906 auto &polyline = json.array("polyline");
3907 std::for_each(polyline.begin(), polyline.end(), [&](std::unique_ptr<IJson> &item) {
3908 IJson &j = *item;
3909 m_polyline.emplace_back(j["x"].get<int>(), j["y"].get<int>());
3910 });
3911 }
3912
3913 if (json.count("properties") > 0 && json["properties"].isArray()) {
3914 auto &properties = json.array("properties");
3915 std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr<IJson> &item) { m_properties.add(*item); });
3916 }
3917
3918 return allFound;
3919}
3920
3926{
3927 m_objectType = ObjectType::Undefined;
3928 if (m_ellipse)
3929 m_objectType = ObjectType::Ellipse;
3930 else if (m_point)
3931 m_objectType = ObjectType::Point;
3932 else if (json.count("polygon") > 0)
3933 m_objectType = ObjectType::Polygon;
3934 else if (json.count("polyline") > 0)
3935 m_objectType = ObjectType::Polyline;
3936 else if (json.count("text") > 0)
3937 m_objectType = ObjectType::Text;
3938 else if (json.count("gid") > 0)
3939 m_objectType = ObjectType::Object;
3940 else if (json.count("template") > 0)
3941 m_objectType = ObjectType::Template;
3942 else
3943 m_objectType = ObjectType::Rectangle;
3944}
3945
3951tson::ObjectType tson::Object::getObjectType() const
3952{
3953 return m_objectType;
3954}
3955
3961{
3962 return m_ellipse;
3963}
3964
3969uint32_t tson::Object::getGid() const
3970{
3971 return m_gid;
3972}
3973
3979{
3980 return m_size;
3981}
3982
3988{
3989 return m_id;
3990}
3991
3996const std::string &tson::Object::getName() const
3997{
3998 return m_name;
3999}
4000
4006{
4007 return m_point;
4008}
4009
4015{
4016 return m_rotation;
4017}
4018
4023const std::string &tson::Object::getTemplate() const
4024{
4025 return m_template;
4026}
4027
4033const std::string &tson::Object::getType() const
4034{
4035 return m_type;
4036}
4037
4043const std::string &tson::Object::getClassType() const
4044{
4045 return m_type;
4046}
4047
4053{
4054 return m_visible;
4055}
4056
4062{
4063 return m_position;
4064}
4065
4071const std::vector<tson::Vector2i> &tson::Object::getPolygons() const
4072{
4073 return m_polygon;
4074}
4075
4081const std::vector<tson::Vector2i> &tson::Object::getPolylines() const
4082{
4083 return m_polyline;
4084}
4085
4091{
4092 return m_properties;
4093}
4094
4100{
4101 return m_text;
4102}
4103
4109tson::Property *tson::Object::getProp(const std::string &name)
4110{
4111 if (m_properties.hasProperty(name)) return m_properties.getProperty(name);
4112 return nullptr;
4113}
4114
4119tson::TileFlipFlags tson::Object::getFlipFlags() const
4120{
4121 return m_flipFlags;
4122}
4123
4132bool tson::Object::hasFlipFlags(TileFlipFlags flags)
4133{
4134 return ((m_flipFlags & flags) == flags) ? true : false;
4135}
4136
4137 #endif // TILESON_OBJECT_HPP
4138
4139
4141
4142 //
4143 // Created by robin on 26.07.2020.
4144 //
4145
4146 #ifndef TILESON_TILEOBJECT_HPP
4147 #define TILESON_TILEOBJECT_HPP
4148
4149
4150 //
4151 // Created by robin on 24.07.2020.
4152 //
4153
4154 #ifndef TILESON_RECT_HPP
4155 #define TILESON_RECT_HPP
4156
4157namespace tson {
4158 class Rect {
4159 public:
4160 inline Rect() = default;
4161 inline Rect(int x_, int y_, int width_, int height_);
4162
4163 inline bool operator==(const Rect &rhs) const;
4164 inline bool operator!=(const Rect &rhs) const;
4165
4166 int x {};
4167 int y {};
4168 int width {};
4169 int height {};
4170 };
4171
4172 Rect::Rect(int x_, int y_, int width_, int height_)
4173 {
4174 x = x_;
4175 y = y_;
4176 width = width_;
4177 height = height_;
4178 }
4179
4180 bool Rect::operator==(const Rect &rhs) const
4181 {
4182 return x == rhs.x && y == rhs.y && width == rhs.width && height == rhs.height;
4183 }
4184
4185 bool Rect::operator!=(const Rect &rhs) const
4186 {
4187 return !(rhs == *this);
4188 }
4189} // namespace tson
4190
4191 #endif // TILESON_RECT_HPP
4192
4193
4195namespace tson {
4196 class Tile;
4197
4199 public:
4200 inline TileObject() = default;
4201 inline TileObject(const std::tuple<int, int> &posInTileUnits, tson::Tile *tile);
4202
4203 inline void initialize(const std::tuple<int, int> &posInTileUnits, tson::Tile *tile); // Defined in tileson_forward.hpp
4204
4205 inline Tile *getTile();
4206 inline const Vector2i &getPositionInTileUnits() const;
4207 inline const Vector2f &getPosition() const;
4208 inline const tson::Rect &getDrawingRect() const; // Defined in tileson_forward.hpp
4209
4210 private:
4211 tson::Tile *m_tile;
4212 tson::Vector2i m_posInTileUnits;
4213 tson::Vector2f m_position;
4214 };
4215
4216 TileObject::TileObject(const std::tuple<int, int> &posInTileUnits, tson::Tile *tile)
4217 {
4218 initialize(posInTileUnits, tile);
4219 }
4220
4226 {
4227 return m_tile;
4228 }
4229
4235 {
4236 return m_posInTileUnits;
4237 }
4238
4244 {
4245 return m_position;
4246 }
4247} // namespace tson
4248
4249 #endif // TILESON_TILEOBJECT_HPP
4250
4251
4253
4254 //
4255 // Created by robin on 13.11.2020.
4256 //
4257
4258 #ifndef TILESON_FLAGGEDTILE_HPP
4259 #define TILESON_FLAGGEDTILE_HPP
4260
4261namespace tson {
4263 public:
4264 FlaggedTile(size_t x_, size_t y_, uint32_t id_, uint32_t tileId_) : x {x_}, y {y_}, id {id_}, tileId {tileId_} {}
4265
4266 size_t x;
4267 size_t y;
4269 uint32_t id;
4271 uint32_t tileId;
4272 };
4273} // namespace tson
4274 #endif // TILESON_FLAGGEDTILE_HPP
4275
4276
4278namespace tson {
4279 class Tile;
4280 class Map;
4281
4282 class Layer {
4283 public:
4284 inline Layer() = default;
4285 inline Layer(IJson &json, tson::Map *map);
4286 inline bool parse(IJson &json, tson::Map *map); // Defined in tileson_forward
4287
4288 [[nodiscard]]
4289 inline const std::string &getCompression() const;
4290 [[nodiscard]]
4291 inline const std::vector<uint32_t> &getData() const;
4292 [[nodiscard]]
4293 inline const std::string &getBase64Data() const;
4294 [[nodiscard]]
4295 inline const std::string &getDrawOrder() const;
4296 [[nodiscard]]
4297 inline const std::string &getEncoding() const;
4298 [[nodiscard]]
4299 inline int getId() const;
4300 [[nodiscard]]
4301 inline const std::string &getImage() const;
4302 [[nodiscard]]
4303 inline const std::string &getName() const;
4304 [[nodiscard]]
4305 inline const Vector2f &getOffset() const;
4306 [[nodiscard]]
4307 inline float getOpacity() const;
4308 [[nodiscard]]
4309 inline const Vector2i &getSize() const;
4310 [[nodiscard]]
4311 inline const Colori &getTransparentColor() const;
4312 [[nodiscard]]
4313 inline const Vector2f &getParallax() const;
4314 [[nodiscard]]
4315 inline bool hasRepeatX() const;
4316 [[nodiscard]]
4317 inline bool hasRepeatY() const;
4318
4319 [[nodiscard]]
4320 inline LayerType getType() const;
4321 [[nodiscard]]
4322 inline const std::string &getClassType() const;
4323 [[nodiscard]]
4324 inline tson::TiledClass *getClass();
4326 [[nodiscard]]
4327 inline const std::string &getTypeStr() const;
4328 [[nodiscard]]
4329 inline bool isVisible() const;
4330 [[nodiscard]]
4331 inline int getX() const;
4332 [[nodiscard]]
4333 inline int getY() const;
4334
4335 [[nodiscard]]
4336 inline std::vector<tson::Chunk> &getChunks();
4337 [[nodiscard]]
4338 inline std::vector<tson::Layer> &getLayers();
4339 [[nodiscard]]
4340 inline std::vector<tson::Object> &getObjects();
4341 [[nodiscard]]
4343
4344 inline tson::Object *getObj(int id);
4345 inline tson::Object *firstObj(const std::string &name);
4346 inline std::vector<tson::Object> getObjectsByName(const std::string &name);
4347 inline std::vector<tson::Object> getObjectsByType(tson::ObjectType type);
4348
4349 template<typename T>
4350 inline T get(const std::string &name);
4351 inline tson::Property *getProp(const std::string &name);
4352
4353 inline void assignTileMap(std::map<uint32_t, tson::Tile *> *tileMap);
4354 inline void createTileData(const Vector2i &mapSize, bool isInfiniteMap);
4355
4356 [[nodiscard]]
4357 inline const std::map<std::tuple<int, int>, tson::Tile *> &getTileData() const;
4358 inline tson::Tile *getTileData(int x, int y);
4359
4360 // v1.2.0-stuff
4361 [[nodiscard]]
4362 inline const Colori &getTintColor() const;
4363 [[nodiscard]]
4364 inline tson::Map *getMap() const;
4365
4366 [[nodiscard]]
4367 inline std::map<std::tuple<int, int>, tson::TileObject> &getTileObjects();
4368 inline tson::TileObject *getTileObject(int x, int y);
4369 [[nodiscard]]
4370 inline const std::set<uint32_t> &getUniqueFlaggedTiles() const;
4371 inline void resolveFlaggedTiles();
4372
4373 private:
4374 inline void setTypeByString();
4375
4376 std::vector<tson::Chunk> m_chunks;
4377 std::string m_compression;
4378 std::vector<uint32_t> m_data;
4380 std::string m_base64Data;
4382 std::string m_drawOrder;
4383 std::string m_encoding;
4384 int m_id {};
4385 std::string m_image;
4386 std::vector<tson::Layer> m_layers;
4387 std::string m_name;
4388 std::vector<tson::Object> m_objects;
4391 float m_opacity {};
4396 std::string m_typeStr;
4397 LayerType m_type {LayerType::Undefined};
4398 bool m_visible {};
4399 int m_x {};
4400 int m_y {};
4403 bool m_repeatX {};
4404 bool m_repeatY {};
4406 std::map<uint32_t, tson::Tile *> *m_tileMap;
4407 std::map<std::tuple<int, int>, tson::Tile *> m_tileData;
4409 // v1.2.0-stuff
4412 inline void decompressData();
4413 inline void queueFlaggedTile(size_t x, size_t y, uint32_t id);
4416 std::map<std::tuple<int, int>, tson::TileObject> m_tileObjects;
4417 std::set<uint32_t> m_uniqueFlaggedTiles;
4418 std::vector<tson::FlaggedTile> m_flaggedTiles;
4419
4420 std::string m_classType {};
4421 std::shared_ptr<tson::TiledClass> m_class {};
4422 };
4423
4430 template<typename T>
4431 T Layer::get(const std::string &name)
4432 {
4433 return m_properties.getValue<T>(name);
4434 }
4435} // namespace tson
4436
4441tson::Layer::Layer(IJson &json, tson::Map *map)
4442{
4443 parse(json, map);
4444}
4445
4446void tson::Layer::queueFlaggedTile(size_t x, size_t y, uint32_t id)
4447{
4448 uint32_t tileId = id;
4449 tileId &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG);
4450 m_uniqueFlaggedTiles.insert(id);
4451 m_flaggedTiles.emplace_back(x, y, id, tileId);
4452}
4453
4459std::vector<tson::Object> tson::Layer::getObjectsByName(const std::string &name)
4460{
4461 std::vector<tson::Object> found;
4462
4463 std::copy_if(m_objects.begin(), m_objects.end(), std::back_inserter(found), [&](const tson::Object &item) { return item.getName() == name; });
4464
4465 return found;
4466}
4467
4473std::vector<tson::Object> tson::Layer::getObjectsByType(tson::ObjectType type)
4474{
4475 std::vector<tson::Object> found;
4476
4477 std::copy_if(m_objects.begin(), m_objects.end(), std::back_inserter(found), [&](const tson::Object &item) { return item.getObjectType() == type; });
4478
4479 return found;
4480}
4481
4487tson::Object *tson::Layer::firstObj(const std::string &name)
4488{
4489 auto result = std::find_if(m_objects.begin(), m_objects.end(), [&](const tson::Object &obj) { return obj.getName() == name; });
4490 if (result == m_objects.end()) return nullptr;
4491
4492 return &result.operator*();
4493}
4494
4501{
4502 auto result = std::find_if(m_objects.begin(), m_objects.end(), [&](const tson::Object &obj) { return obj.getId() == id; });
4503 if (result == m_objects.end()) return nullptr;
4504
4505 return &result.operator*();
4506}
4507
4513{
4514 if (m_typeStr == "tilelayer")
4515 m_type = LayerType::TileLayer;
4516 else if (m_typeStr == "objectgroup")
4517 m_type = LayerType::ObjectGroup;
4518 else if (m_typeStr == "imagelayer")
4519 m_type = LayerType::ImageLayer;
4520 else if (m_typeStr == "group")
4521 m_type = LayerType::Group;
4522 else
4523 m_type = LayerType::Undefined;
4524}
4525
4530const std::string &tson::Layer::getCompression() const
4531{
4532 return m_compression;
4533}
4534
4539const std::vector<uint32_t> &tson::Layer::getData() const
4540{
4541 return m_data;
4542}
4543
4548const std::string &tson::Layer::getBase64Data() const
4549{
4550 return m_base64Data;
4551}
4552
4557const std::string &tson::Layer::getDrawOrder() const
4558{
4559 return m_drawOrder;
4560}
4561
4566const std::string &tson::Layer::getEncoding() const
4567{
4568 return m_encoding;
4569}
4570
4576{
4577 return m_id;
4578}
4579
4584const std::string &tson::Layer::getImage() const
4585{
4586 return m_image;
4587}
4588
4593const std::string &tson::Layer::getName() const
4594{
4595 return m_name;
4596}
4597
4603{
4604 return m_offset;
4605}
4606
4612{
4613 return m_opacity;
4614}
4615
4622{
4623 return m_size;
4624}
4625
4631{
4632 return m_transparentColor;
4633}
4634
4639const std::string &tson::Layer::getTypeStr() const
4640{
4641 return m_typeStr;
4642}
4643
4649{
4650 return m_visible;
4651}
4652
4658{
4659 return m_x;
4660}
4661
4667{
4668 return m_y;
4669}
4670
4675std::vector<tson::Chunk> &tson::Layer::getChunks()
4676{
4677 return m_chunks;
4678}
4679
4684std::vector<tson::Layer> &tson::Layer::getLayers()
4685{
4686 return m_layers;
4687}
4688
4693std::vector<tson::Object> &tson::Layer::getObjects()
4694{
4695 return m_objects;
4696}
4697
4703{
4704 return m_properties;
4705}
4706
4712tson::Property *tson::Layer::getProp(const std::string &name)
4713{
4714 if (m_properties.hasProperty(name)) return m_properties.getProperty(name);
4715 return nullptr;
4716}
4717
4722tson::LayerType tson::Layer::getType() const
4723{
4724 return m_type;
4725}
4726
4731void tson::Layer::assignTileMap(std::map<uint32_t, tson::Tile *> *tileMap)
4732{
4733 m_tileMap = tileMap;
4734}
4735
4746const std::map<std::tuple<int, int>, tson::Tile *> &tson::Layer::getTileData() const
4747{
4748 return m_tileData;
4749}
4750
4764{
4765 return (m_tileData.count({x, y}) > 0) ? m_tileData[{x, y}] : nullptr;
4766}
4767
4773{
4774 return m_map;
4775}
4776
4784void tson::Layer::createTileData(const Vector2i &mapSize, bool isInfiniteMap)
4785{
4786 size_t x = 0;
4787 size_t y = 0;
4788 if (!isInfiniteMap) {
4789 std::for_each(m_data.begin(), m_data.end(), [&](uint32_t tileId) {
4790 if (static_cast<int>(x) == mapSize.x) {
4791 ++y;
4792 x = 0;
4793 }
4794
4795 if (tileId > 0 && m_tileMap->count(tileId) > 0) {
4796 m_tileData[{static_cast<int>(x), static_cast<int>(y)}] = m_tileMap->at(tileId);
4797 m_tileObjects[{static_cast<int>(x), static_cast<int>(y)}] = {
4798 {static_cast<int>(x), static_cast<int>(y)}, m_tileData[{static_cast<int>(x), static_cast<int>(y)}]};
4799 } else if (tileId > 0 && m_tileMap->count(tileId) == 0) // Tile with flip flags!
4800 {
4801 queueFlaggedTile(x, y, tileId);
4802 }
4803 x++;
4804 });
4805 }
4806}
4807
4808std::map<std::tuple<int, int>, tson::TileObject> &tson::Layer::getTileObjects()
4809{
4810 return m_tileObjects;
4811}
4812
4813tson::TileObject *tson::Layer::getTileObject(int x, int y)
4814{
4815 return (m_tileObjects.count({x, y}) > 0) ? &m_tileObjects[{x, y}] : nullptr;
4816}
4817
4818const std::set<uint32_t> &tson::Layer::getUniqueFlaggedTiles() const
4819{
4820 return m_uniqueFlaggedTiles;
4821}
4822
4823void tson::Layer::resolveFlaggedTiles()
4824{
4825 std::for_each(m_flaggedTiles.begin(), m_flaggedTiles.end(), [&](const tson::FlaggedTile &tile) {
4826 if (tile.id > 0 && m_tileMap->count(tile.id) > 0) {
4827 m_tileData[{static_cast<int>(tile.x), static_cast<int>(tile.y)}] = m_tileMap->at(tile.id);
4828 m_tileObjects[{static_cast<int>(tile.x), static_cast<int>(tile.y)}] = {
4829 {static_cast<int>(tile.x), static_cast<int>(tile.y)}, m_tileData[{static_cast<int>(tile.x), static_cast<int>(tile.y)}]};
4830 }
4831 });
4832}
4833
4840{
4841 return m_tintColor;
4842}
4843
4850{
4851 return m_parallax;
4852}
4853
4860{
4861 return m_repeatX;
4862}
4863
4870{
4871 return m_repeatY;
4872}
4873
4874const std::string &tson::Layer::getClassType() const
4875{
4876 return m_classType;
4877}
4878
4879 #endif // TILESON_LAYER_HPP
4880
4881
4883
4884 //
4885 // Created by robin on 22.03.2020.
4886 //
4887
4888 #ifndef TILESON_TILESET_HPP
4889 #define TILESON_TILESET_HPP
4890
4891 // #include "../external/json.hpp"
4892
4893
4894 //
4895 // Created by robin on 04.04.2021.
4896 //
4897
4898 #ifndef TILESON_TRANSFORMATIONS_HPP
4899 #define TILESON_TRANSFORMATIONS_HPP
4900
4901namespace tson {
4903 public:
4904 inline Transformations() = default;
4905 inline explicit Transformations(IJson &json);
4906 inline bool parse(IJson &json);
4907
4908 inline bool allowHflip() const;
4909 inline bool allowPreferuntransformed() const;
4910 inline bool allowRotation() const;
4911 inline bool allowVflip() const;
4912
4913 private:
4914 bool m_hflip {};
4917 bool m_rotate {};
4918 bool m_vflip {};
4919 };
4920
4921 Transformations::Transformations(IJson &json)
4922 {
4923 parse(json);
4924 }
4925
4926 bool Transformations::parse(IJson &json)
4927 {
4928 if (json.count("hflip") > 0) m_hflip = json["hflip"].get<bool>(); // Optional
4929 if (json.count("preferuntransformed") > 0) m_preferuntransformed = json["preferuntransformed"].get<bool>(); // Optional
4930 if (json.count("rotate") > 0) m_rotate = json["rotate"].get<bool>(); // Optional
4931 if (json.count("vflip") > 0) m_vflip = json["vflip"].get<bool>(); // Optional
4932
4933 return true;
4934 }
4935
4941 {
4942 return m_hflip;
4943 }
4944
4951 {
4952 return m_preferuntransformed;
4953 }
4954
4960 {
4961 return m_rotate;
4962 }
4963
4969 {
4970 return m_vflip;
4971 }
4972} // namespace tson
4973
4974 #endif // TILESON_TRANSFORMATIONS_HPP
4975
4976
4978
4979 //
4980 // Created by robin on 22.03.2020.
4981 //
4982
4983 #ifndef TILESON_WANGSET_HPP
4984 #define TILESON_WANGSET_HPP
4985
4986 // #include "../external/json.hpp"
4987
4988
4989 //
4990 // Created by robin on 22.03.2020.
4991 //
4992
4993 #ifndef TILESON_WANGCOLOR_HPP
4994 #define TILESON_WANGCOLOR_HPP
4995
4996// #include "../external/json.hpp"
4997
4998namespace tson {
5000 public:
5001 inline WangColor() = default;
5002 inline explicit WangColor(IJson &json, tson::Map *map);
5003 inline bool parse(IJson &json, tson::Map *map);
5004
5005 [[nodiscard]]
5006 inline const Colori &getColor() const;
5007 [[nodiscard]]
5008 inline const std::string &getName() const;
5009 [[nodiscard]]
5010 inline float getProbability() const;
5011 [[nodiscard]]
5012 inline int getTile() const;
5013
5015 template<typename T>
5016 inline T get(const std::string &name);
5017 inline tson::Property *getProp(const std::string &name);
5018
5019 [[nodiscard]]
5020 inline const std::string &getClassType() const;
5021 [[nodiscard]]
5022 inline tson::TiledClass *getClass();
5024 private:
5026 std::string m_name;
5027 float m_probability {};
5028 int m_tile {};
5030 // New in Tiled v1.5
5033 std::string m_classType {};
5034 std::shared_ptr<tson::TiledClass> m_class {};
5035 };
5036} // namespace tson
5037
5038tson::WangColor::WangColor(IJson &json, tson::Map *map)
5039{
5040 parse(json, map);
5041}
5042
5043bool tson::WangColor::parse(IJson &json, tson::Map *map)
5044{
5045 m_map = map;
5046 bool allFound = true;
5047
5048 if (json.count("color") > 0)
5049 m_color = tson::Colori(json["color"].get<std::string>());
5050 else
5051 allFound = false;
5052 if (json.count("name") > 0)
5053 m_name = json["name"].get<std::string>();
5054 else
5055 allFound = false;
5056 if (json.count("probability") > 0)
5057 m_probability = json["probability"].get<float>();
5058 else
5059 allFound = false;
5060 if (json.count("tile") > 0)
5061 m_tile = json["tile"].get<int>();
5062 else
5063 allFound = false;
5064 if (json.count("class") > 0) m_classType = json["class"].get<std::string>(); // Optional
5065
5066 if (json.count("properties") > 0 && json["properties"].isArray()) {
5067 auto &properties = json.array("properties");
5068 std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr<IJson> &item) { m_properties.add(*item); });
5069 }
5070
5071 return allFound;
5072}
5073
5079{
5080 return m_color;
5081}
5082
5087const std::string &tson::WangColor::getName() const
5088{
5089 return m_name;
5090}
5091
5097{
5098 return m_probability;
5099}
5100
5106{
5107 return m_tile;
5108}
5109
5116{
5117 return m_properties;
5118}
5119
5126template<typename T>
5127T tson::WangColor::get(const std::string &name)
5128{
5129 return m_properties.getValue<T>(name);
5130}
5131
5138{
5139 if (m_properties.hasProperty(name)) return m_properties.getProperty(name);
5140
5141 return nullptr;
5142}
5143
5144const std::string &tson::WangColor::getClassType() const
5145{
5146 return m_classType;
5147}
5148
5149 #endif // TILESON_WANGCOLOR_HPP
5150
5151
5153
5154 //
5155 // Created by robin on 22.03.2020.
5156 //
5157
5158 #ifndef TILESON_WANGTILE_HPP
5159 #define TILESON_WANGTILE_HPP
5160
5161// #include "../external/json.hpp"
5162
5163namespace tson {
5164 class WangTile {
5165 public:
5166 inline WangTile() = default;
5167 inline explicit WangTile(IJson &json);
5168 inline bool parse(IJson &json);
5169
5170 [[nodiscard]]
5171 inline bool hasDFlip() const;
5172 [[nodiscard]]
5173 inline bool hasHFlip() const;
5174 [[nodiscard]]
5175 inline uint32_t getTileid() const;
5176 [[nodiscard]]
5177 inline bool hasVFlip() const;
5178
5179 [[nodiscard]]
5180 inline const std::vector<uint32_t> &getWangIds() const;
5181
5182 private:
5183 bool m_dflip {};
5184 bool m_hflip {};
5185 uint32_t m_tileid {};
5186 bool m_vflip {};
5187 std::vector<uint32_t> m_wangId;
5188 };
5189} // namespace tson
5190
5191tson::WangTile::WangTile(IJson &json)
5192{
5193 parse(json);
5194}
5195
5202{
5203 bool allFound = true;
5204
5205 if (json.count("dflip") > 0) m_dflip = json["dflip"].get<bool>(); // Removed in Tiled v1.5 and is now optional
5206 if (json.count("hflip") > 0) m_hflip = json["hflip"].get<bool>(); // Removed in Tiled v1.5 and is now optional
5207 if (json.count("vflip") > 0) m_vflip = json["vflip"].get<bool>(); // Removed in Tiled v1.5 and is now optional
5208
5209 if (json.count("tileid") > 0)
5210 m_tileid = json["tileid"].get<uint32_t>();
5211 else
5212 allFound = false;
5213 if (json.count("wangid") > 0 && json["wangid"].isArray()) {
5214 auto &wangid = json.array("wangid");
5215 std::for_each(wangid.begin(), wangid.end(), [&](std::unique_ptr<IJson> &item) { m_wangId.emplace_back(item->get<uint32_t>()); });
5216 }
5217
5218 return allFound;
5219}
5220
5228{
5229 return m_dflip;
5230}
5231
5239{
5240 return m_hflip;
5241}
5242
5248{
5249 return m_tileid;
5250}
5251
5259{
5260 return m_vflip;
5261}
5262
5267const std::vector<uint32_t> &tson::WangTile::getWangIds() const
5268{
5269 return m_wangId;
5270}
5271
5272 #endif // TILESON_WANGTILE_HPP
5273
5274
5276namespace tson {
5277 class WangSet {
5278 public:
5279 inline WangSet() = default;
5280 inline explicit WangSet(IJson &json, tson::Map *map);
5281 inline bool parse(IJson &json, tson::Map *map);
5282
5283 [[nodiscard]]
5284 inline const std::string &getName() const;
5285 [[nodiscard]]
5286 inline int getTile() const;
5287
5288 [[nodiscard]]
5289 inline const std::vector<tson::WangTile> &getWangTiles() const;
5290 [[nodiscard]]
5291 inline const std::vector<tson::WangColor> &getCornerColors() const;
5292 [[nodiscard]]
5293 inline const std::vector<tson::WangColor> &getEdgeColors() const;
5294
5295 inline tson::WangColor *getColor(const std::string &name);
5296 inline const std::vector<tson::WangColor> &getColors() const;
5298
5299 template<typename T>
5300 inline T get(const std::string &name);
5301 inline tson::Property *getProp(const std::string &name);
5302
5303 [[nodiscard]]
5304 inline const std::string &getClassType() const;
5305 [[nodiscard]]
5306 inline tson::TiledClass *getClass();
5308 private:
5309 inline bool parseTiled15Props(IJson &json);
5310
5311 std::string m_name;
5312 int m_tile {};
5313 std::vector<tson::WangTile> m_wangTiles;
5314 std::vector<tson::WangColor> m_cornerColors;
5315 std::vector<tson::WangColor> m_edgeColors;
5318 // Tiled v1.5
5319 std::vector<tson::WangColor> m_colors;
5322 std::string m_classType {};
5323 std::shared_ptr<tson::TiledClass> m_class {};
5324 };
5325
5332 template<typename T>
5333 T tson::WangSet::get(const std::string &name)
5334 {
5335 return m_properties.getValue<T>(name);
5336 }
5337} // namespace tson
5338
5339tson::WangSet::WangSet(IJson &json, tson::Map *map)
5340{
5341 parse(json, map);
5342}
5343
5344bool tson::WangSet::parse(IJson &json, tson::Map *map)
5345{
5346 m_map = map;
5347 bool allFound = true;
5348
5349 if (json.count("tile") > 0)
5350 m_tile = json["tile"].get<int>();
5351 else
5352 allFound = false;
5353 if (json.count("name") > 0)
5354 m_name = json["name"].get<std::string>();
5355 else
5356 allFound = false;
5357
5358 // More advanced data
5359 if (json.count("wangtiles") > 0 && json["wangtiles"].isArray()) {
5360 auto &wangtiles = json.array("wangtiles");
5361 std::for_each(wangtiles.begin(), wangtiles.end(), [&](std::unique_ptr<IJson> &item) { m_wangTiles.emplace_back(*item); });
5362 }
5363 if (json.count("cornercolors") > 0 && json["cornercolors"].isArray()) {
5364 auto &cornercolors = json.array("cornercolors");
5365 std::for_each(cornercolors.begin(), cornercolors.end(), [&](std::unique_ptr<IJson> &item) { m_cornerColors.emplace_back(*item, m_map); });
5366 }
5367 if (json.count("edgecolors") > 0 && json["edgecolors"].isArray()) {
5368 auto &edgecolors = json.array("edgecolors");
5369 std::for_each(edgecolors.begin(), edgecolors.end(), [&](std::unique_ptr<IJson> &item) { m_edgeColors.emplace_back(*item, m_map); });
5370 }
5371 if (json.count("properties") > 0 && json["properties"].isArray()) {
5372 auto &properties = json.array("properties");
5373 std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr<IJson> &item) { m_properties.add(*item); });
5374 }
5375
5376 if (json.count("class") > 0) m_classType = json["class"].get<std::string>(); // Optional
5377
5378 if (!parseTiled15Props(json)) allFound = false;
5379
5380 return allFound;
5381}
5382
5390{
5391 if (json.count("colors") > 0 && json["colors"].isArray()) {
5392 auto &colors = json.array("colors");
5393 std::for_each(colors.begin(), colors.end(), [&](std::unique_ptr<IJson> &item) { m_colors.emplace_back(*item, m_map); });
5394 }
5395 return true;
5396}
5397
5402const std::string &tson::WangSet::getName() const
5403{
5404 return m_name;
5405}
5406
5412{
5413 return m_tile;
5414}
5415
5420const std::vector<tson::WangTile> &tson::WangSet::getWangTiles() const
5421{
5422 return m_wangTiles;
5423}
5424
5429const std::vector<tson::WangColor> &tson::WangSet::getCornerColors() const
5430{
5431 return m_cornerColors;
5432}
5433
5438const std::vector<tson::WangColor> &tson::WangSet::getEdgeColors() const
5439{
5440 return m_edgeColors;
5441}
5442
5448{
5449 return m_properties;
5450}
5451
5458{
5459 if (m_properties.hasProperty(name)) return m_properties.getProperty(name);
5460
5461 return nullptr;
5462}
5463
5468const std::vector<tson::WangColor> &tson::WangSet::getColors() const
5469{
5470 return m_colors;
5471}
5472
5481{
5482 auto color = std::find_if(m_colors.begin(), m_colors.end(), [&](const auto &c) { return c.getName() == name; });
5483
5484 if (color != m_colors.end()) return &color.operator*();
5485
5486 return nullptr;
5487}
5488
5489const std::string &tson::WangSet::getClassType() const
5490{
5491 return m_classType;
5492}
5493
5494 #endif // TILESON_WANGSET_HPP
5495
5496
5498
5499 //
5500 // Created by robin on 22.03.2020.
5501 //
5502
5503 #ifndef TILESON_TILE_HPP
5504 #define TILESON_TILE_HPP
5505
5506 // #include "../external/json.hpp"
5507
5508
5509 //
5510 // Created by robin on 22.03.2020.
5511 //
5512
5513 #ifndef TILESON_FRAME_HPP
5514 #define TILESON_FRAME_HPP
5515
5516// #include "../external/json.hpp"
5517
5518namespace tson {
5519 class Frame {
5520 public:
5521 inline Frame() = default;
5522 inline Frame(int duration, uint32_t tileId);
5523 inline explicit Frame(IJson &json);
5524
5525 inline bool parse(IJson &json);
5526
5527 [[nodiscard]]
5528 inline int getDuration() const;
5529 [[nodiscard]]
5530 inline uint32_t getTileId() const;
5531
5532 private:
5533 int m_duration {};
5534 uint32_t m_tileId {};
5535 };
5536} // namespace tson
5537
5543tson::Frame::Frame(int duration, uint32_t tileId) : m_duration {duration}, m_tileId {tileId} {}
5544
5549tson::Frame::Frame(IJson &json)
5550{
5551 parse(json);
5552}
5553
5560{
5561 bool allFound = true;
5562
5563 if (json.count("duration") > 0)
5564 m_duration = json["duration"].get<int>();
5565 else
5566 allFound = false;
5567 if (json.count("tileid") > 0)
5568 m_tileId = json["tileid"].get<uint32_t>() + 1;
5569 else
5570 allFound = false;
5571
5572 return allFound;
5573}
5574
5580{
5581 return m_duration;
5582}
5583
5589{
5590 return m_tileId;
5591}
5592
5593 #endif // TILESON_FRAME_HPP
5594
5595
5597
5598 //
5599 // Created by robin on 21.05.2021.
5600 //
5601
5602 #ifndef TILESON_ANIMATION_HPP
5603 #define TILESON_ANIMATION_HPP
5604
5605namespace tson {
5607 public:
5608 inline Animation() = default;
5609 inline Animation(const std::vector<tson::Frame> &frames) : m_frames {frames} {};
5610
5611 inline void update(float timeDeltaMs);
5612 inline void reset();
5613
5614 inline void setFrames(const std::vector<tson::Frame> &frames);
5615 inline void setCurrentFrame(uint32_t currentFrame);
5616 inline void setTimeDelta(float timeDelta);
5617
5618 inline const std::vector<tson::Frame> &getFrames() const;
5619 inline const tson::Frame *getCurrentFrame() const;
5620 inline uint32_t getCurrentFrameNumber() const;
5621 inline uint32_t getCurrentTileId() const;
5622 inline float getTimeDelta() const;
5623
5624 inline bool any() const;
5625 inline size_t size() const;
5626
5627 private:
5628 inline int nextFrame();
5629 std::vector<tson::Frame> m_frames;
5630 uint32_t m_currentFrame {0};
5631 float m_timeDelta {0};
5632 };
5633
5634 const std::vector<tson::Frame> &Animation::getFrames() const
5635 {
5636 return m_frames;
5637 }
5638
5643 {
5644 m_currentFrame = 0;
5645 m_timeDelta = 0.f;
5646 }
5647
5653 {
5654 return (m_frames.size() == 0 || m_currentFrame >= m_frames.size()) ? nullptr : &m_frames.at(m_currentFrame);
5655 }
5656
5657 size_t Animation::size() const
5658 {
5659 return m_frames.size();
5660 }
5661
5666 void Animation::update(float timeDeltaMs)
5667 {
5668 const tson::Frame *frame = getCurrentFrame();
5669 if (frame != nullptr) {
5670 m_timeDelta += timeDeltaMs;
5671 if (m_timeDelta >= frame->getDuration()) {
5672 m_timeDelta = static_cast<float>((int32_t) m_timeDelta % frame->getDuration());
5673 m_currentFrame = nextFrame();
5674 }
5675 }
5676 }
5677
5678 int Animation::nextFrame()
5679 {
5680 return (m_currentFrame + 1 >= m_frames.size()) ? 0 : m_currentFrame + 1;
5681 }
5682
5683 float Animation::getTimeDelta() const
5684 {
5685 return m_timeDelta;
5686 }
5687
5688 uint32_t Animation::getCurrentFrameNumber() const
5689 {
5690 return m_currentFrame;
5691 }
5692
5693 uint32_t Animation::getCurrentTileId() const
5694 {
5695 return (getCurrentFrame() != nullptr) ? getCurrentFrame()->getTileId() : 0;
5696 }
5697
5698 void Animation::setFrames(const std::vector<tson::Frame> &frames)
5699 {
5700 m_frames = frames;
5701 }
5702
5703 void Animation::setCurrentFrame(uint32_t currentFrame)
5704 {
5705 m_currentFrame = currentFrame;
5706 }
5707
5708 void Animation::setTimeDelta(float timeDelta)
5709 {
5710 m_timeDelta = timeDelta;
5711 }
5712
5717 bool Animation::any() const
5718 {
5719 return m_frames.size() > 0;
5720 }
5721} // namespace tson
5722
5723 #endif // TILESON_ANIMATION_HPP
5724
5725
5727namespace tson {
5728 class Tileset;
5729 class TiledClass;
5730
5731 class Tile {
5732 public:
5733 inline Tile() = default;
5734 inline Tile(IJson &json, tson::Tileset *tileset, tson::Map *map);
5735 inline Tile(uint32_t id, tson::Tileset *tileset, tson::Map *map);
5736 inline Tile(uint32_t id, tson::Map *map); // v1.2.0
5737 inline bool parse(IJson &json, tson::Tileset *tileset, tson::Map *map);
5738 inline bool parseId(IJson &json);
5739
5740 [[nodiscard]]
5741 inline uint32_t getId() const;
5742 [[nodiscard]]
5743 inline const fs::path &getImage() const;
5744 [[nodiscard]]
5745 inline const Vector2i &getImageSize() const;
5746 [[nodiscard]]
5747 inline const std::string &getType() const;
5748 [[nodiscard]]
5749 inline const std::string &getClassType() const;
5750 [[nodiscard]]
5751 inline tson::TiledClass *getClass();
5753 //[[nodiscard]] inline const std::vector<tson::Frame> &getAnimation() const;
5754 [[nodiscard]]
5755 inline tson::Animation &getAnimation();
5756 [[nodiscard]]
5757 inline Layer &getObjectgroup();
5758 [[nodiscard]]
5760 [[nodiscard]]
5761 inline const std::vector<int> &getTerrain() const;
5762
5763 template<typename T>
5764 inline T get(const std::string &name);
5765 inline tson::Property *getProp(const std::string &name);
5766
5767 // v1.2.0-stuff
5768 inline void setProperties(const tson::PropertyCollection &properties);
5769
5770 [[nodiscard]]
5771 inline tson::Tileset *getTileset() const;
5772 [[nodiscard]]
5773 inline tson::Map *getMap() const;
5774 [[nodiscard]]
5775 inline const tson::Rect &getDrawingRect() const;
5776 [[nodiscard]]
5777 inline const Rect &getSubRectangle() const;
5778
5779 inline const tson::Vector2f getPosition(const std::tuple<int, int> &tileDataPos);
5780 inline const tson::Vector2i getPositionInTileUnits(const std::tuple<int, int> &tileDataPos);
5781 [[nodiscard]]
5782 inline const tson::Vector2i getTileSize() const;
5784 [[nodiscard]]
5785 inline TileFlipFlags getFlipFlags() const;
5786 inline bool hasFlipFlags(TileFlipFlags flags);
5787 [[nodiscard]]
5788 inline uint32_t getGid() const;
5789
5790 inline void addTilesetAndPerformCalculations(tson::Tileset *tileset); // v1.2.0
5791
5792 private:
5793 tson::Animation m_animation {};
5794 uint32_t m_id {};
5796 fs::path m_image;
5801 std::vector<int> m_terrain;
5802 std::string m_type;
5804 // v1.2.0-stuff
5805 uint32_t m_gid {};
5810 tson::TileFlipFlags m_flipFlags = TileFlipFlags::None;
5811 inline void performDataCalculations();
5812 inline void manageFlipFlagsByIdThenRemoveFlags(uint32_t &id);
5813 friend class Layer;
5814 std::shared_ptr<tson::TiledClass> m_class {};
5815 };
5816
5823 template<typename T>
5824 T tson::Tile::get(const std::string &name)
5825 {
5826 return m_properties.getValue<T>(name);
5827 }
5828} // namespace tson
5829
5830tson::Tile::Tile(IJson &json, tson::Tileset *tileset, tson::Map *map)
5831{
5832 parse(json, tileset, map);
5833}
5834
5839tson::Tile::Tile(uint32_t id, tson::Tileset *tileset, tson::Map *map) : m_id {id}, m_gid {id}
5840{
5841 m_tileset = tileset;
5842 m_map = map;
5845}
5846
5851tson::Tile::Tile(uint32_t id, tson::Map *map) : m_id {id}, m_gid {id}
5852{
5853 m_map = map;
5855}
5856
5862{
5863 m_tileset = tileset;
5864 performDataCalculations();
5865}
5866
5873{
5874 m_tileset = tileset;
5875 m_map = map;
5876
5877 if (json.count("image") > 0) m_image = fs::path(json["image"].get<std::string>()); // Optional
5878
5879 bool allFound = parseId(json);
5880
5881 if (json.count("type") > 0)
5882 m_type = json["type"].get<std::string>(); // Optional
5883 else if (json.count("class") > 0)
5884 m_type = json["class"].get<std::string>(); // Tiled v1.9 renamed 'type' to 'class'
5885
5886 if (json.count("objectgroup") > 0) m_objectgroup = tson::Layer(json["objectgroup"], m_map); // Optional
5887
5888 if (json.count("imagewidth") > 0 && json.count("imageheight") > 0)
5889 m_imageSize = {json["imagewidth"].get<int>(), json["imageheight"].get<int>()}; // Optional
5890
5891 m_subRect = {0, 0, m_imageSize.x, m_imageSize.y};
5892 if (json.count("x") > 0) m_subRect.x = json["x"].get<int>(); // Optional
5893 if (json.count("y") > 0) m_subRect.y = json["y"].get<int>(); // Optional
5894 if (json.count("width") > 0) m_subRect.width = json["width"].get<int>(); // Optional
5895 if (json.count("height") > 0) m_subRect.height = json["height"].get<int>(); // Optional
5896
5897 // More advanced data
5898 if (json.count("animation") > 0 && json["animation"].isArray()) {
5899 auto &animation = json.array("animation");
5900 std::vector<tson::Frame> frames;
5901 std::for_each(animation.begin(), animation.end(), [&](std::unique_ptr<IJson> &item) { frames.emplace_back(*item); });
5902 if (frames.size() > 0) {
5903 m_animation.setFrames(frames);
5904 }
5905 }
5906 if (json.count("terrain") > 0 && json["terrain"].isArray()) {
5907 auto &terrain = json.array("terrain");
5908 std::for_each(terrain.begin(), terrain.end(), [&](std::unique_ptr<IJson> &item) { m_terrain.emplace_back(item->get<int>()); });
5909 }
5910
5911 if (json.count("properties") > 0 && json["properties"].isArray()) {
5912 auto &properties = json.array("properties");
5913 std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr<IJson> &item) { m_properties.add(*item); });
5914 }
5915
5916 performDataCalculations();
5917
5918 return allFound;
5919}
5920
5925uint32_t tson::Tile::getId() const
5926{
5927 return m_id;
5928}
5929
5935const fs::path &tson::Tile::getImage() const
5936{
5937 return m_image;
5938}
5939
5945{
5946 return m_imageSize;
5947}
5948
5954const std::string &tson::Tile::getType() const
5955{
5956 return m_type;
5957}
5958
5964const std::string &tson::Tile::getClassType() const
5965{
5966 return m_type;
5967}
5968
5974{
5975 return m_animation;
5976}
5977
5983{
5984 return m_objectgroup;
5985}
5986
5992{
5993 return m_properties;
5994}
5995
6000const std::vector<int> &tson::Tile::getTerrain() const
6001{
6002 return m_terrain;
6003}
6004
6010tson::Property *tson::Tile::getProp(const std::string &name)
6011{
6012 if (m_properties.hasProperty(name)) return m_properties.getProperty(name);
6013
6014 return nullptr;
6015}
6016
6022{
6023 return m_tileset;
6024}
6025
6031{
6032 return m_map;
6033}
6034
6040{
6041 return m_drawingRect;
6042}
6043
6054const tson::Vector2i tson::Tile::getPositionInTileUnits(const std::tuple<int, int> &tileDataPos)
6055{
6056 return {std::get<0>(tileDataPos), std::get<1>(tileDataPos)};
6057}
6058
6060{
6061 if (id & FLIPPED_HORIZONTALLY_FLAG) m_flipFlags |= TileFlipFlags::Horizontally;
6062 if (id & FLIPPED_VERTICALLY_FLAG) m_flipFlags |= TileFlipFlags::Vertically;
6063 if (id & FLIPPED_DIAGONALLY_FLAG) m_flipFlags |= TileFlipFlags::Diagonally;
6064
6065 id &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG);
6066}
6067
6068tson::TileFlipFlags tson::Tile::getFlipFlags() const
6069{
6070 return m_flipFlags;
6071}
6072
6081bool tson::Tile::hasFlipFlags(tson::TileFlipFlags flags)
6082{
6083 return ((m_flipFlags & flags) == flags) ? true : false;
6084}
6085
6086uint32_t tson::Tile::getGid() const
6087{
6088 return m_gid;
6089}
6090
6091void tson::Tile::setProperties(const tson::PropertyCollection &properties)
6092{
6093 m_properties = properties;
6094}
6095
6101{
6102 return m_subRect;
6103}
6104
6105 #endif // TILESON_TILE_HPP
6106
6107
6109
6110 //
6111 // Created by robin on 22.03.2020.
6112 //
6113
6114 #ifndef TILESON_TERRAIN_HPP
6115 #define TILESON_TERRAIN_HPP
6116
6117// #include "../external/json.hpp"
6118
6119namespace tson {
6120 class Terrain {
6121 public:
6122 inline Terrain() = default;
6123 inline Terrain(std::string name, int tile);
6124 inline explicit Terrain(IJson &json);
6125
6126 inline bool parse(IJson &json);
6127
6128 [[nodiscard]]
6129 inline const std::string &getName() const;
6130 [[nodiscard]]
6131 inline int getTile() const;
6132 [[nodiscard]]
6134
6135 template<typename T>
6136 inline T get(const std::string &name);
6137 inline tson::Property *getProp(const std::string &name);
6138
6139 private:
6140 std::string m_name;
6141 int m_tile {};
6143 };
6144
6151 template<typename T>
6152 T tson::Terrain::get(const std::string &name)
6153 {
6154 return m_properties.getValue<T>(name);
6155 }
6156} // namespace tson
6157
6158tson::Terrain::Terrain(std::string name, int tile) : m_name {std::move(name)}, m_tile {tile} {}
6159
6160tson::Terrain::Terrain(IJson &json)
6161{
6162 parse(json);
6163}
6164
6165bool tson::Terrain::parse(IJson &json)
6166{
6167 bool allFound = true;
6168
6169 if (json.count("name") > 0)
6170 m_name = json["name"].get<std::string>();
6171 else
6172 allFound = false;
6173 if (json.count("tile") > 0)
6174 m_tile = json["tile"].get<int>();
6175 else
6176 allFound = false;
6177
6178 if (json.count("properties") > 0 && json["properties"].isArray()) {
6179 auto &properties = json.array("properties");
6180 std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr<IJson> &item) { m_properties.add(*item); });
6181 }
6182
6183 return allFound;
6184}
6185
6190const std::string &tson::Terrain::getName() const
6191{
6192 return m_name;
6193}
6194
6200{
6201 return m_tile;
6202}
6203
6209{
6210 return m_properties;
6211}
6212
6219{
6220 if (m_properties.hasProperty(name)) return m_properties.getProperty(name);
6221 return nullptr;
6222}
6223
6224 #endif // TILESON_TERRAIN_HPP
6225
6226
6228
6229 //
6230 // Created by robin on 22.03.2020.
6231 //
6232
6233 #ifndef TILESON_GRID_HPP
6234 #define TILESON_GRID_HPP
6235
6236 #include <string>
6237
6238// #include "../external/json.hpp"
6239
6240namespace tson {
6241 class Grid {
6242 public:
6243 inline Grid() = default;
6244 inline explicit Grid(IJson &json);
6245
6246 inline bool parse(IJson &json);
6247
6248 [[nodiscard]]
6249 inline const std::string &getOrientation() const;
6250 [[nodiscard]]
6251 inline const Vector2i &getSize() const;
6252
6253 private:
6254 std::string m_orientation;
6256 };
6257} // namespace tson
6258
6263tson::Grid::Grid(IJson &json)
6264{
6265 parse(json);
6266}
6267
6274{
6275 bool allFound = true;
6276
6277 if (json.count("orientation") > 0) m_orientation = json["orientation"].get<std::string>(); // Optional
6278
6279 if (json.count("width") > 0 && json.count("height") > 0)
6280 m_size = {json["width"].get<int>(), json["height"].get<int>()};
6281 else
6282 allFound = false;
6283
6284 return allFound;
6285}
6286
6291const std::string &tson::Grid::getOrientation() const
6292{
6293 return m_orientation;
6294}
6295
6301{
6302 return m_size;
6303}
6304
6305 #endif // TILESON_GRID_HPP
6306
6307
6309 #include <functional>
6310
6311namespace tson {
6312 class Map;
6313
6314 class Tileset {
6315 public:
6316 inline Tileset() = default;
6317 inline explicit Tileset(IJson &json, tson::Map *map);
6318 inline bool parse(IJson &json, tson::Map *map);
6319
6320 [[nodiscard]]
6321 inline int getColumns() const;
6322 [[nodiscard]]
6323 inline int getFirstgid() const;
6324
6325 [[nodiscard]]
6326 inline const fs::path &getImagePath() const;
6327 [[nodiscard]]
6328 inline const fs::path &getImage() const;
6329 [[nodiscard]]
6330 inline const Vector2i &getImageSize() const;
6331 [[nodiscard]]
6332 inline int getMargin() const;
6333 [[nodiscard]]
6334 inline const std::string &getName() const;
6335 [[nodiscard]]
6336 inline int getSpacing() const;
6337 [[nodiscard]]
6338 inline int getTileCount() const;
6339 [[nodiscard]]
6340 inline const Vector2i &getTileSize() const;
6341 [[nodiscard]]
6342 inline const Colori &getTransparentColor() const;
6343 [[nodiscard]]
6344 inline const std::string &getType() const;
6345 [[nodiscard]]
6346 inline const std::string &getClassType() const;
6347 [[nodiscard]]
6348 inline tson::TiledClass *getClass();
6349 [[nodiscard]]
6350 inline std::vector<tson::Tile> &getTiles();
6351 [[nodiscard]]
6352 inline const std::vector<tson::WangSet> &getWangsets() const;
6353 [[nodiscard]]
6355 [[nodiscard]]
6356 inline const std::vector<tson::Terrain> &getTerrains() const;
6357 [[nodiscard]]
6358 inline const Vector2i &getTileOffset() const;
6359 [[nodiscard]]
6360 inline const Grid &getGrid() const;
6361 [[nodiscard]]
6362 inline TileRenderSize getTileRenderSize() const;
6363 [[nodiscard]]
6364 inline FillMode getFillMode() const;
6365
6366 inline tson::Tile *getTile(uint32_t id);
6367 inline tson::Terrain *getTerrain(const std::string &name);
6368
6369 template<typename T>
6370 inline T get(const std::string &name);
6371 inline tson::Property *getProp(const std::string &name);
6372
6373 // v1.2.0-stuff
6374 [[nodiscard]]
6375 inline tson::Map *getMap() const;
6376 [[nodiscard]]
6377 inline ObjectAlignment getObjectAlignment() const;
6378
6379 inline static tson::ObjectAlignment StringToAlignment(std::string_view str);
6380
6381 // v1.3.0
6382 inline tson::Vector2i getMarginSpacingOffset(const tson::Vector2i &posInTileUnits);
6383 inline tson::WangSet *getWangset(const std::string &name);
6384 inline const Transformations &getTransformations() const;
6385
6386 #ifndef TSON_TEST_ENABLED
6387 private:
6388 #endif
6389 inline void generateMissingTiles();
6390
6391 int m_columns {};
6392 int m_firstgid {};
6394 fs::path m_image;
6397 int m_margin {};
6398 std::string m_name;
6399 int m_spacing {};
6403 std::string m_type;
6405 std::vector<tson::Tile> m_tiles;
6406 std::vector<tson::WangSet> m_wangsets;
6409 std::vector<tson::Terrain> m_terrains;
6414 // v1.2.0-stuff
6415 tson::ObjectAlignment m_objectAlignment {tson::ObjectAlignment::Unspecified};
6418 // v1.3.0-stuff
6419 fs::path m_source {};
6420 fs::path m_path {};
6424 // v1.4.0-stuff
6425 TileRenderSize
6428 FillMode m_fillMode {};
6432 std::string m_classType {};
6433 std::shared_ptr<tson::TiledClass> m_class {};
6434 };
6435
6442 template<typename T>
6443 T tson::Tileset::get(const std::string &name)
6444 {
6445 return m_properties.getValue<T>(name);
6446 }
6447} // namespace tson
6448
6449tson::Tileset::Tileset(IJson &json, tson::Map *map)
6450{
6451 parse(json, map);
6452}
6453
6454bool tson::Tileset::parse(IJson &json, tson::Map *map)
6455{
6456 m_map = map;
6457 bool allFound = true;
6458
6459 if (json.count("firstgid") > 0)
6460 m_firstgid = json["firstgid"].get<int>();
6461 else
6462 allFound = false;
6463
6464 // Tileset is stored in external file if 'source' exists
6465 if (json.count("source") > 0) {
6466 if (!allFound) return allFound;
6467
6468 std::string sourceStr = json["source"].get<std::string>();
6469 m_source = fs::path(sourceStr);
6470 m_path = json.directory() / m_source;
6471
6472 if (!json.parse(m_path)) return false;
6473 }
6474
6475 if (json.count("columns") > 0)
6476 m_columns = json["columns"].get<int>();
6477 else
6478 allFound = false;
6479
6480 if (json.count("image") > 0)
6481 m_image = fs::path(json["image"].get<std::string>());
6482 else
6483 allFound = false;
6484
6485 if (json.count("margin") > 0)
6486 m_margin = json["margin"].get<int>();
6487 else
6488 allFound = false;
6489 if (json.count("name") > 0)
6490 m_name = json["name"].get<std::string>();
6491 else
6492 allFound = false;
6493 if (json.count("spacing") > 0)
6494 m_spacing = json["spacing"].get<int>();
6495 else
6496 allFound = false;
6497 if (json.count("tilecount") > 0)
6498 m_tileCount = json["tilecount"].get<int>();
6499 else
6500 allFound = false;
6501 if (json.count("transparentcolor") > 0) m_transparentColor = tson::Colori(json["transparentcolor"].get<std::string>()); // Optional
6502 if (json.count("type") > 0) m_type = json["type"].get<std::string>();
6503 if (json.count("grid") > 0) m_grid = tson::Grid(json["grid"]);
6504 if (json.count("class") > 0) m_classType = json["class"].get<std::string>(); // Optional
6505
6506 if (json.count("imagewidth") > 0 && json.count("imageheight") > 0)
6507 m_imageSize = {json["imagewidth"].get<int>(), json["imageheight"].get<int>()};
6508 else
6509 allFound = false;
6510 if (json.count("tilewidth") > 0 && json.count("tileheight") > 0)
6511 m_tileSize = {json["tilewidth"].get<int>(), json["tileheight"].get<int>()};
6512 else
6513 allFound = false;
6514 if (json.count("tileoffset") > 0) m_tileOffset = {json["tileoffset"]["x"].get<int>(), json["tileoffset"]["y"].get<int>()};
6515
6516 if (json.count("tilerendersize") > 0) {
6517 std::string tileRenderStr = json["tilerendersize"].get<std::string>();
6518 if (tileRenderStr == "tile")
6519 m_tileRenderSize = TileRenderSize::Tile;
6520 else if (tileRenderStr == "grid")
6521 m_tileRenderSize = TileRenderSize::Grid;
6522 }
6523
6524 if (json.count("fillmode") > 0) {
6525 std::string fillmode = json["fillmode"].get<std::string>();
6526 if (fillmode == "stretch")
6527 m_fillMode = FillMode::Stretch;
6528 else if (fillmode == "preserve-aspect-fit")
6529 m_fillMode = FillMode::PreserveAspectFit;
6530 }
6531
6532 // More advanced data
6533 if (json.count("wangsets") > 0 && json["wangsets"].isArray()) {
6534 auto &wangsets = json.array("wangsets");
6535 std::for_each(wangsets.begin(), wangsets.end(), [&](std::unique_ptr<IJson> &item) { m_wangsets.emplace_back(*item, m_map); });
6536 }
6537 if (json.count("tiles") > 0 && json["tiles"].isArray()) {
6538 auto &tiles = json.array("tiles");
6539 std::for_each(tiles.begin(), tiles.end(), [&](std::unique_ptr<IJson> &item) { m_tiles.emplace_back(*item, this, m_map); });
6540 }
6541 if (json.count("terrains") > 0 && json["terrains"].isArray()) {
6542 auto &terrains = json.array("terrains");
6543 std::for_each(terrains.begin(), terrains.end(), [&](std::unique_ptr<IJson> &item) { m_terrains.emplace_back(*item); });
6544 }
6545
6546 if (json.count("properties") > 0 && json["properties"].isArray()) {
6547 auto &properties = json.array("properties");
6548 std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr<IJson> &item) { m_properties.add(*item); });
6549 }
6550
6551 if (json.count("objectalignment") > 0) {
6552 std::string alignment = json["objectalignment"].get<std::string>();
6553 m_objectAlignment = StringToAlignment(alignment);
6554 }
6555
6556 if (json.count("transformations") > 0) {
6557 m_transformations.parse(json["transformations"]);
6558 }
6559
6560 generateMissingTiles();
6561
6562 return allFound;
6563}
6564
6570{
6571 return m_columns;
6572}
6573
6579{
6580 return m_firstgid;
6581}
6582
6588const fs::path &tson::Tileset::getImagePath() const
6589{
6590 return m_image;
6591}
6592
6598{
6599 return m_imageSize;
6600}
6601
6607{
6608 return m_margin;
6609}
6610
6615const std::string &tson::Tileset::getName() const
6616{
6617 return m_name;
6618}
6619
6625{
6626 return m_spacing;
6627}
6628
6634{
6635 return m_tileCount;
6636}
6637
6643{
6644 return m_tileSize;
6645}
6646
6652{
6653 return m_transparentColor;
6654}
6655
6660const std::string &tson::Tileset::getType() const
6661{
6662 return m_type;
6663}
6664
6670const fs::path &tson::Tileset::getImage() const
6671{
6672 return m_image;
6673}
6674
6679std::vector<tson::Tile> &tson::Tileset::getTiles()
6680{
6681 return m_tiles;
6682}
6683
6688const std::vector<tson::WangSet> &tson::Tileset::getWangsets() const
6689{
6690 return m_wangsets;
6691}
6692
6698{
6699 return m_properties;
6700}
6701
6706const std::vector<tson::Terrain> &tson::Tileset::getTerrains() const
6707{
6708 return m_terrains;
6709}
6710
6716{
6717 return m_tileOffset;
6718}
6719
6726{
6727 return m_grid;
6728}
6729
6737{
6738 auto result = std::find_if(m_tiles.begin(), m_tiles.end(), [&](const tson::Tile &item) { return item.getId() == id; });
6739 if (result == m_tiles.end()) return nullptr;
6740
6741 return &result.operator*();
6742}
6743
6750{
6751 auto result = std::find_if(m_terrains.begin(), m_terrains.end(), [&](const tson::Terrain &item) { return item.getName() == name; });
6752 if (result == m_terrains.end()) return nullptr;
6753
6754 return &result.operator*();
6755}
6756
6763{
6764 if (m_properties.hasProperty(name)) return m_properties.getProperty(name);
6765
6766 return nullptr;
6767}
6768
6773{
6774 std::vector<uint32_t> tileIds;
6775 for (auto &tile : m_tiles)
6776 tileIds.push_back(tile.getId());
6777
6778 for (uint32_t i = m_firstgid; i < m_firstgid + (uint32_t) m_tileCount; ++i) {
6779 if (std::count(tileIds.begin(), tileIds.end(), i) == 0) {
6780 m_tiles.emplace_back(Tile(i, this, m_map));
6781 }
6782 }
6783}
6784
6790{
6791 return m_map;
6792}
6793
6799tson::ObjectAlignment tson::Tileset::StringToAlignment(std::string_view str)
6800{
6801 if (str == "unspecified")
6802 return tson::ObjectAlignment::Unspecified;
6803 else if (str == "topleft")
6804 return tson::ObjectAlignment::TopLeft;
6805 else if (str == "top")
6806 return tson::ObjectAlignment::Top;
6807 else if (str == "topright")
6808 return tson::ObjectAlignment::TopRight;
6809 else if (str == "left")
6810 return tson::ObjectAlignment::Left;
6811 else if (str == "center")
6812 return tson::ObjectAlignment::Center;
6813 else if (str == "right")
6814 return tson::ObjectAlignment::Right;
6815 else if (str == "bottomleft")
6816 return tson::ObjectAlignment::BottomLeft;
6817 else if (str == "bottom")
6818 return tson::ObjectAlignment::Bottom;
6819 else if (str == "bottomright")
6820 return tson::ObjectAlignment::BottomRight;
6821 else
6822 return tson::ObjectAlignment::Unspecified;
6823}
6824
6825tson::ObjectAlignment tson::Tileset::getObjectAlignment() const
6826{
6827 return m_objectAlignment;
6828}
6829
6838{
6839 if (m_margin == 0 && m_spacing == 0) return {0, 0};
6840
6841 tson::Vector2i offset {(posInTileUnits.x * m_spacing) + m_margin, (posInTileUnits.y * m_spacing) + m_margin};
6842 return offset;
6843}
6844
6851{
6852 auto wangset = std::find_if(m_wangsets.begin(), m_wangsets.end(), [&](const auto &w) { return w.getName() == name; });
6853
6854 if (wangset != m_wangsets.end()) return &wangset.operator*();
6855
6856 return nullptr;
6857}
6858
6866{
6867 return m_transformations;
6868}
6869
6870tson::TileRenderSize tson::Tileset::getTileRenderSize() const
6871{
6872 return m_tileRenderSize;
6873}
6874
6875tson::FillMode tson::Tileset::getFillMode() const
6876{
6877 return m_fillMode;
6878}
6879
6880const std::string &tson::Tileset::getClassType() const
6881{
6882 return m_classType;
6883}
6884
6885 #endif // TILESON_TILESET_HPP
6886
6888namespace tson {
6889 class Map {
6890 public:
6891 inline Map() = default;
6892 inline Map(ParseStatus status, std::string description);
6893 inline explicit Map(IJson &json, tson::DecompressorContainer *decompressors, tson::Project *project);
6894 inline bool parse(IJson &json, tson::DecompressorContainer *decompressors, tson::Project *project);
6895
6896 [[nodiscard]]
6897 inline const Colori &getBackgroundColor() const;
6898 [[nodiscard]]
6899 inline const Vector2i &getSize() const;
6900 [[nodiscard]]
6901 inline int getHexsideLength() const;
6902 [[nodiscard]]
6903 inline bool isInfinite() const;
6904 [[nodiscard]]
6905 inline int getNextLayerId() const;
6906 [[nodiscard]]
6907 inline int getNextObjectId() const;
6908 [[nodiscard]]
6909 inline const std::string &getOrientation() const;
6910 [[nodiscard]]
6911 inline const std::string &getRenderOrder() const;
6912 [[nodiscard]]
6913 inline const std::string &getStaggerAxis() const;
6914 [[nodiscard]]
6915 inline const std::string &getStaggerIndex() const;
6916 [[nodiscard]]
6917 inline const std::string &getTiledVersion() const;
6918 [[nodiscard]]
6919 inline const Vector2i &getTileSize() const;
6920 [[nodiscard]]
6921 inline const std::string &getType() const;
6922 [[nodiscard]]
6923 inline const std::string &getClassType() const;
6924 [[nodiscard]]
6925 inline tson::TiledClass *getClass();
6926 [[nodiscard]]
6927 inline const Vector2f &getParallaxOrigin() const;
6928 //[[nodiscard]] inline int getVersion() const; //Removed - Tileson v1.3.0
6929
6930 [[nodiscard]]
6931 inline std::vector<tson::Layer> &getLayers();
6932 [[nodiscard]]
6934 [[nodiscard]]
6935 inline std::vector<tson::Tileset> &getTilesets();
6936
6937 [[nodiscard]]
6938 inline ParseStatus getStatus() const;
6939 [[nodiscard]]
6940 inline const std::string &getStatusMessage() const;
6941 [[nodiscard]]
6942 inline const std::map<uint32_t, tson::Tile *> &getTileMap() const;
6943
6944 inline Layer *getLayer(const std::string &name);
6945 inline Tileset *getTileset(const std::string &name);
6946
6947 template<typename T>
6948 inline T get(const std::string &name);
6949 inline tson::Property *getProp(const std::string &name);
6950
6951 // v1.2.0
6952 [[nodiscard]]
6953 inline int getCompressionLevel() const;
6954 inline DecompressorContainer *getDecompressors();
6955 inline Project *getProject();
6956 inline Tileset *getTilesetByGid(uint32_t gid);
6957
6958 private:
6959 inline bool createTilesetData(IJson &json);
6960 inline void processData();
6961
6962 Colori m_backgroundColor;
6963 ;
6967 std::vector<tson::Layer> m_layers;
6970 std::string m_orientation;
6972 std::string m_renderOrder;
6973 std::string m_staggerAxis;
6974 std::string m_staggerIndex;
6975 std::string m_tiledVersion;
6977 std::vector<tson::Tileset> m_tilesets;
6978 std::string m_type;
6980 // int m_version{}; /*! 'version': The JSON format version - Removed in Tileson v1.3.0*/
6981
6982 ParseStatus m_status {ParseStatus::OK};
6983 std::string m_statusMessage {"OK"};
6984
6985 std::map<uint32_t, tson::Tile *> m_tileMap {};
6987 // v1.2.0
6992 tson::Project *m_project {nullptr};
6993 std::map<uint32_t, tson::Tile> m_flaggedTileMap {};
6995 std::string m_classType {};
6996 std::shared_ptr<tson::TiledClass> m_class {};
6997 };
6998
7005 template<typename T>
7006 T tson::Map::get(const std::string &name)
7007 {
7008 return m_properties.getValue<T>(name);
7009 }
7010} // namespace tson
7011
7017tson::Map::Map(tson::ParseStatus status, std::string description) : m_status {status}, m_statusMessage {std::move(description)} {}
7018
7024tson::Map::Map(IJson &json, tson::DecompressorContainer *decompressors, tson::Project *project)
7025{
7026 parse(json, decompressors, project);
7027}
7028
7035{
7036 m_decompressors = decompressors;
7037 m_project = project;
7038
7039 bool allFound = true;
7040 if (json.count("compressionlevel") > 0) m_compressionLevel = json["compressionlevel"].get<int>(); // Tiled 1.3 - Optional
7041
7042 if (json.count("backgroundcolor") > 0) m_backgroundColor = Colori(json["backgroundcolor"].get<std::string>()); // Optional
7043 if (json.count("width") > 0 && json.count("height") > 0)
7044 m_size = {json["width"].get<int>(), json["height"].get<int>()};
7045 else
7046 allFound = false;
7047 if (json.count("hexsidelength") > 0) m_hexsideLength = json["hexsidelength"].get<int>(); // Optional
7048 if (json.count("infinite") > 0) m_isInfinite = json["infinite"].get<bool>(); // Optional
7049 if (json.count("nextlayerid") > 0) m_nextLayerId = json["nextlayerid"].get<int>(); // Optional
7050 if (json.count("nextobjectid") > 0)
7051 m_nextObjectId = json["nextobjectid"].get<int>();
7052 else
7053 allFound = false;
7054 if (json.count("orientation") > 0)
7055 m_orientation = json["orientation"].get<std::string>();
7056 else
7057 allFound = false;
7058 if (json.count("renderorder") > 0) m_renderOrder = json["renderorder"].get<std::string>(); // Optional
7059 if (json.count("staggeraxis") > 0) m_staggerAxis = json["staggeraxis"].get<std::string>(); // Optional
7060 if (json.count("staggerindex") > 0) m_staggerIndex = json["staggerindex"].get<std::string>(); // Optional
7061 if (json.count("tiledversion") > 0)
7062 m_tiledVersion = json["tiledversion"].get<std::string>();
7063 else
7064 allFound = false;
7065 if (json.count("tilewidth") > 0 && json.count("tileheight") > 0)
7066 m_tileSize = {json["tilewidth"].get<int>(), json["tileheight"].get<int>()};
7067 else
7068 allFound = false;
7069 if (json.count("type") > 0) m_type = json["type"].get<std::string>(); // Optional
7070 if (json.count("class") > 0) m_classType = json["class"].get<std::string>(); // Optional
7071
7072 // Removed - Changed from a float to string in Tiled v1.6, and old spec said int.
7073 // Reason for removal is that it seems to have no real use, as TiledVersion is stored in another variable.
7074 // if(json.count("version") > 0) m_version = json["version"].get<int>(); else allFound = false;
7075
7076 // More advanced data
7077 if (json.count("layers") > 0 && json["layers"].isArray()) {
7078 auto &array = json.array("layers");
7079 std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item) { m_layers.emplace_back(*item, this); });
7080 }
7081
7082 if (json.count("properties") > 0 && json["properties"].isArray()) {
7083 auto &array = json.array("properties");
7084 std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item) { m_properties.add(*item, m_project); });
7085 }
7086
7087 tson::Vector2f parallaxOrigin {0.f, 0.f};
7088 if (json.count("parallaxoriginx") > 0) parallaxOrigin.x = json["parallaxoriginx"].get<float>();
7089 if (json.count("parallaxoriginy") > 0) parallaxOrigin.y = json["parallaxoriginy"].get<float>();
7090
7091 m_parallaxOrigin = parallaxOrigin;
7092
7093 if (!createTilesetData(json)) allFound = false;
7094
7095 processData();
7096
7097 return allFound;
7098}
7099
7104{
7105 bool ok = true;
7106 if (json.count("tilesets") > 0 && json["tilesets"].isArray()) {
7107 // First created tileset objects
7108 auto &tilesets = json.array("tilesets");
7109 std::for_each(tilesets.begin(), tilesets.end(), [&](std::unique_ptr<IJson> &) { m_tilesets.emplace_back(); });
7110
7111 int i = 0;
7112 // Then do the parsing
7113 std::for_each(tilesets.begin(), tilesets.end(), [&](std::unique_ptr<IJson> &item) {
7114 item->directory(json.directory());
7115 if (!m_tilesets[i].parse(*item, this)) ok = false;
7116
7117 ++i;
7118 });
7119 }
7120 return ok;
7121}
7122
7127{
7128 m_tileMap.clear();
7129 for (auto &tileset : m_tilesets) {
7130 std::set<std::uint32_t> usedIds;
7131 for (auto &tile : tileset.getTiles()) {
7132 if (usedIds.count(tile.getGid()) != 0) {
7133 continue;
7134 }
7135 usedIds.insert(tile.getGid());
7136 m_tileMap[tile.getGid()] = &tile;
7137 }
7138 }
7139 std::for_each(m_layers.begin(), m_layers.end(), [&](tson::Layer &layer) {
7140 layer.assignTileMap(&m_tileMap);
7141 layer.createTileData(m_size, m_isInfinite);
7142 const std::set<uint32_t> &flaggedTiles = layer.getUniqueFlaggedTiles();
7143 for (uint32_t ftile : flaggedTiles) {
7144 tson::Tile tile {ftile, layer.getMap()};
7145 if (m_tileMap.count(tile.getGid())) {
7146 tson::Tile *originalTile = m_tileMap[tile.getGid()];
7147 tile.addTilesetAndPerformCalculations(originalTile->getTileset());
7148 tile.setProperties(originalTile->getProperties());
7149 m_flaggedTileMap[ftile] = tile;
7150 m_tileMap[ftile] = &m_flaggedTileMap[ftile];
7151 }
7152 }
7153 layer.resolveFlaggedTiles();
7154 });
7155}
7156
7162{
7163 return m_backgroundColor;
7164}
7165
7171{
7172 return m_size;
7173}
7174
7180{
7181 return m_hexsideLength;
7182}
7183
7189{
7190 return m_isInfinite;
7191}
7192
7198{
7199 return m_nextLayerId;
7200}
7201
7207{
7208 return m_nextObjectId;
7209}
7210
7215const std::string &tson::Map::getOrientation() const
7216{
7217 return m_orientation;
7218}
7219
7224const std::string &tson::Map::getRenderOrder() const
7225{
7226 return m_renderOrder;
7227}
7228
7233const std::string &tson::Map::getStaggerAxis() const
7234{
7235 return m_staggerAxis;
7236}
7237
7242const std::string &tson::Map::getStaggerIndex() const
7243{
7244 return m_staggerIndex;
7245}
7246
7251const std::string &tson::Map::getTiledVersion() const
7252{
7253 return m_tiledVersion;
7254}
7255
7261{
7262 return m_tileSize;
7263}
7264
7269const std::string &tson::Map::getType() const
7270{
7271 return m_type;
7272}
7273
7278// int tson::Map::getVersion() const
7279//{
7280// return m_version;
7281// }
7282
7287std::vector<tson::Layer> &tson::Map::getLayers()
7288{
7289 return m_layers;
7290}
7291
7297{
7298 return m_properties;
7299}
7300
7305std::vector<tson::Tileset> &tson::Map::getTilesets()
7306{
7307 return m_tilesets;
7308}
7309
7310tson::Layer *tson::Map::getLayer(const std::string &name)
7311{
7312 auto result = std::find_if(m_layers.begin(), m_layers.end(), [&](const tson::Layer &item) { return item.getName() == name; });
7313 if (result == m_layers.end()) return nullptr;
7314
7315 return &result.operator*();
7316}
7317
7324tson::Tileset *tson::Map::getTileset(const std::string &name)
7325{
7326 auto result = std::find_if(m_tilesets.begin(), m_tilesets.end(), [&](const tson::Tileset &item) { return item.getName() == name; });
7327 if (result == m_tilesets.end()) return nullptr;
7328
7329 return &result.operator*();
7330}
7331
7339{
7340 auto result = std::find_if(m_tilesets.begin(), m_tilesets.end(), [&](const tson::Tileset &tileset) {
7341 auto const firstId = static_cast<uint32_t>(tileset.getFirstgid()); // First tile id of the tileset
7342 auto const lastId = static_cast<uint32_t>((firstId + tileset.getTileCount()) - 1);
7343
7344 return (gid >= firstId && gid <= lastId);
7345 });
7346 if (result == m_tilesets.end()) return nullptr;
7347
7348 return &result.operator*();
7349}
7350
7356tson::Property *tson::Map::getProp(const std::string &name)
7357{
7358 if (m_properties.hasProperty(name)) return m_properties.getProperty(name);
7359 return nullptr;
7360}
7361
7362tson::ParseStatus tson::Map::getStatus() const
7363{
7364 return m_status;
7365}
7366
7367const std::string &tson::Map::getStatusMessage() const
7368{
7369 return m_statusMessage;
7370}
7371
7376const std::map<uint32_t, tson::Tile *> &tson::Map::getTileMap() const
7377{
7378 return m_tileMap;
7379}
7380
7381tson::DecompressorContainer *tson::Map::getDecompressors()
7382{
7383 return m_decompressors;
7384}
7385
7392{
7393 return m_compressionLevel;
7394}
7395
7402{
7403 return m_parallaxOrigin;
7404}
7405
7406tson::Project *tson::Map::getProject()
7407{
7408 return m_project;
7409}
7410
7411const std::string &tson::Map::getClassType() const
7412{
7413 return m_classType;
7414}
7415
7416 #endif // TILESON_MAP_HPP
7417
7418
7420
7421 //
7422 // Created by robin on 06.06.22.
7423 //
7424
7425 #ifndef TILESON_TILEDENUM_HPP
7426 #define TILESON_TILEDENUM_HPP
7427
7428namespace tson {
7430 public:
7431 inline explicit EnumDefinition(IJson &json);
7432 inline uint32_t getValue(const std::string &str);
7433 inline std::string getValue(uint32_t num);
7434 inline std::vector<std::string> getValues(uint32_t num);
7435 inline bool exists(const std::string &str);
7436 inline bool exists(uint32_t num);
7437
7438 [[nodiscard]]
7439 inline uint32_t getId() const;
7440 [[nodiscard]]
7441 inline uint32_t getMaxValue() const;
7442 [[nodiscard]]
7443 inline const std::string &getName() const;
7444 [[nodiscard]]
7445 inline EnumStorageType getStorageType() const;
7446 [[nodiscard]]
7447 inline bool hasValuesAsFlags() const;
7448
7449 private:
7450 inline bool hasFlag(uint32_t value, uint32_t flag) const;
7451 uint32_t m_id {};
7452 uint32_t m_maxValue {};
7453 std::string m_name {};
7454 std::map<uint32_t, std::string> m_values {};
7455 bool m_valuesAsFlags {false};
7456 EnumStorageType m_storageType {EnumStorageType::Unspecified};
7457 };
7458
7459 EnumDefinition::EnumDefinition(IJson &json)
7460 {
7461 m_id = json.get<uint32_t>("id");
7462 m_name = json.get<std::string>("name");
7463 std::string type = json.get<std::string>("storageType");
7464 m_storageType = (type == "int") ? EnumStorageType::Int : (type == "string") ? EnumStorageType::String : EnumStorageType::Unspecified;
7465 m_valuesAsFlags = json.get<bool>("valuesAsFlags");
7466
7467 if (json.count("values") > 0 && json["values"].isArray()) {
7468 m_values[0] = "None";
7469 uint32_t valueCounter = (m_valuesAsFlags) ? 1 : 0;
7470 uint8_t flagBit = 1;
7471 auto &array = json.array("values");
7472 std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item) {
7473 std::string v = item->get<std::string>();
7474 m_values[valueCounter] = v;
7475 if (m_valuesAsFlags) {
7476 valueCounter = 1 << flagBit;
7477 ++flagBit;
7478 } else {
7479 ++valueCounter;
7480 }
7481 });
7482
7483 m_maxValue = valueCounter;
7484 }
7485 }
7486
7487 uint32_t EnumDefinition::getValue(const std::string &str)
7488 {
7489 auto result = std::find_if(m_values.begin(), m_values.end(), [&](const std::pair<uint32_t, std::string> &pair) { return pair.second == str; });
7490
7491 if (result != m_values.end()) return result->first;
7492
7493 return 0;
7494 }
7495
7496 std::string EnumDefinition::getValue(uint32_t num)
7497 {
7498 return (m_values.count(num) > 0) ? m_values[num] : "";
7499 }
7500
7501 bool EnumDefinition::hasValuesAsFlags() const
7502 {
7503 return m_valuesAsFlags;
7504 }
7505
7506 bool EnumDefinition::exists(const std::string &str)
7507 {
7508 auto result = std::find_if(m_values.begin(), m_values.end(), [&](const std::pair<uint32_t, std::string> &pair) { return pair.second == str; });
7509
7510 if (result != m_values.end()) return true;
7511
7512 return false;
7513 }
7514
7515 bool EnumDefinition::exists(uint32_t num)
7516 {
7517 return (m_values.count(num) > 0);
7518 }
7519
7520 uint32_t EnumDefinition::getId() const
7521 {
7522 return m_id;
7523 }
7524
7525 const std::string &EnumDefinition::getName() const
7526 {
7527 return m_name;
7528 }
7529
7530 EnumStorageType EnumDefinition::getStorageType() const
7531 {
7532 return m_storageType;
7533 }
7534
7535 uint32_t EnumDefinition::getMaxValue() const
7536 {
7537 return m_maxValue;
7538 }
7539
7540 std::vector<std::string> EnumDefinition::getValues(uint32_t num)
7541 {
7542 std::vector<std::string> values;
7543 if (m_valuesAsFlags) {
7544 uint32_t flag = 0;
7545 uint32_t i = 0;
7546 while (flag < m_maxValue) {
7547 flag = 1 << i;
7548 ++i;
7549 if (m_values.count(flag) > 0 && hasFlag(num, flag)) {
7550 values.emplace_back(m_values[flag]);
7551 }
7552 }
7553 } else {
7554 std::string v = getValue(num);
7555 if (!v.empty()) values.emplace_back();
7556 }
7557
7558 return values;
7559 }
7560
7561 bool EnumDefinition::hasFlag(uint32_t value, uint32_t flag) const
7562 {
7563 return ((value & flag) == flag);
7564 }
7565
7567 public:
7568 inline EnumValue() = default;
7569 inline EnumValue(uint32_t value, EnumDefinition *definition);
7570 inline EnumValue(const std::string &value, EnumDefinition *definition);
7571
7572 [[nodiscard]]
7573 inline uint32_t getValue() const;
7574 inline std::string getValueName() const;
7575 [[nodiscard]]
7576 inline std::vector<std::string> getValueNames() const;
7577 [[nodiscard]]
7578 inline EnumDefinition *getDefinition() const;
7579
7580 inline bool hasFlagValue(uint32_t flag) const;
7581 template<typename T>
7582 inline bool hasFlag(T flags) const;
7583 inline bool hasAnyFlagValue(uint32_t flags) const;
7584 template<typename T>
7585 inline bool hasAnyFlag(T flags) const;
7586 [[nodiscard]]
7587 inline bool containsValueName(const std::string &value) const;
7588
7589 private:
7590 uint32_t m_value {0};
7591 EnumDefinition *m_definition = nullptr;
7592 };
7593
7594 EnumValue::EnumValue(uint32_t value, EnumDefinition *definition) : m_value {value}, m_definition {definition} {}
7595
7596 EnumValue::EnumValue(const std::string &value, EnumDefinition *definition) : m_definition {definition}
7597 {
7598 if (!value.empty() && definition != nullptr) {
7599 std::vector<std::string> values = Tools::SplitString(value, ',');
7600 for (auto &item : values) {
7601 uint32_t v = definition->getValue(item);
7602 m_value |= v;
7603 }
7604 }
7605 }
7606
7613 bool EnumValue::hasFlagValue(uint32_t flags) const
7614 {
7615 if (m_definition->hasValuesAsFlags()) return ((m_value & flags) == flags) ? true : false;
7616
7617 return m_value == flags;
7618 }
7619
7626 bool EnumValue::hasAnyFlagValue(uint32_t flags) const
7627 {
7628 if (m_definition->hasValuesAsFlags()) return ((m_value & flags) != 0);
7629
7630 return m_value == flags;
7631 }
7632
7633 uint32_t EnumValue::getValue() const
7634 {
7635 return m_value;
7636 }
7637
7644 std::string EnumValue::getValueName() const
7645 {
7646 return (m_definition == nullptr) ? "" : m_definition->getValue(m_value);
7647 }
7648
7656 template<typename T>
7657 bool EnumValue::hasFlag(T flags) const
7658 {
7659 return hasFlagValue(static_cast<uint32_t>(flags));
7660 }
7661
7669 template<typename T>
7670 bool EnumValue::hasAnyFlag(T flags) const
7671 {
7672 return hasAnyFlagValue(static_cast<uint32_t>(flags));
7673 }
7674
7675 EnumDefinition *EnumValue::getDefinition() const
7676 {
7677 return m_definition;
7678 }
7679
7680 std::vector<std::string> EnumValue::getValueNames() const
7681 {
7682 return (m_definition == nullptr) ? std::vector<std::string>() : m_definition->getValues(m_value);
7683 }
7684
7690 bool EnumValue::containsValueName(const std::string &value) const
7691 {
7692 if (m_definition != nullptr) {
7693 if (m_definition->hasValuesAsFlags()) {
7694 std::vector<std::string> values = m_definition->getValues(m_value);
7695 auto it = std::find(values.begin(), values.end(), value);
7696 return it != values.end();
7697 }
7698 return m_definition->getValue(value) == m_value;
7699 }
7700 return false;
7701 }
7702} // namespace tson
7703
7704 #endif // TILESON_TILEDENUM_HPP
7705
7706
7708
7709 //
7710 // Created by robin on 06.06.22.
7711 //
7712
7713 #ifndef TILESON_TILEDCLASS_HPP
7714 #define TILESON_TILEDCLASS_HPP
7715
7716namespace tson {
7718 public:
7719 inline explicit TiledClass() = default;
7720 inline explicit TiledClass(IJson &json, tson::Project *project = nullptr);
7721
7722 [[nodiscard]]
7723 inline uint32_t getId() const;
7724 [[nodiscard]]
7725 inline const std::string &getName() const;
7726 [[nodiscard]]
7727 inline const std::string &getType() const;
7728 [[nodiscard]]
7729 inline const PropertyCollection &getMembers() const;
7730 inline void update(IJson &json);
7731 inline void update(PropertyCollection &properties);
7732
7733 template<typename T>
7734 inline T get(const std::string &name);
7735 inline tson::Property *getMember(const std::string &name);
7736
7737 private:
7738 uint32_t m_id {};
7739 std::string m_name {};
7740 std::string m_type {};
7741 PropertyCollection m_members {};
7742 };
7743
7744 TiledClass::TiledClass(IJson &json, tson::Project *project)
7745 {
7746 if (json.count("id") > 0) m_id = json["id"].get<uint32_t>();
7747
7748 if (json.count("name") > 0) m_name = json["name"].get<std::string>();
7749 if (json.count("type") > 0) m_type = json["type"].get<std::string>();
7750
7751 if (json.count("members") > 0 && json["members"].isArray()) {
7752 auto &array = json.array("members");
7753 std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item) { m_members.add(*item, project); });
7754 }
7755 }
7756
7757 uint32_t TiledClass::getId() const
7758 {
7759 return m_id;
7760 }
7761
7762 const std::string &TiledClass::getName() const
7763 {
7764 return m_name;
7765 }
7766
7767 const std::string &TiledClass::getType() const
7768 {
7769 return m_type;
7770 }
7771
7772 const PropertyCollection &TiledClass::getMembers() const
7773 {
7774 return m_members;
7775 }
7776
7777 template<typename T>
7778 T TiledClass::get(const std::string &name)
7779 {
7780 return m_members.getValue<T>(name);
7781 }
7782
7783 tson::Property *TiledClass::getMember(const std::string &name)
7784 {
7785 if (m_members.hasProperty(name)) return m_members.getProperty(name);
7786 return nullptr;
7787 }
7788
7794 {
7795 for (Property *property : m_members.get()) {
7796 if (json.any(property->getName())) {
7797 property->setValueByType(json[property->getName()]);
7798 }
7799 }
7800 }
7801
7802 void TiledClass::update(PropertyCollection &properties)
7803 {
7804 std::vector<Property *> toUpdate;
7805 for (Property *member : m_members.get()) {
7806 if (properties.hasProperty(member->getName())) {
7807 Property *property = properties.getProperty(member->getName());
7808 if (member->getType() == property->getType()) {
7809 toUpdate.push_back(property);
7810 }
7811 }
7812 }
7813
7814 std::for_each(toUpdate.begin(), toUpdate.end(), [&](Property *p) { m_members.setProperty(p->getName(), *p); });
7815 }
7816} // namespace tson
7817
7818 #endif // TILESON_TILEDCLASS_HPP
7819
7820
7822
7823 //
7824 // Created by robin on 01.08.2020.
7825 //
7826
7827 #ifndef TILESON_PROJECT_HPP
7828 #define TILESON_PROJECT_HPP
7829
7830 #include <fstream>
7831 #include <memory>
7832 #include <sstream>
7833
7834
7835 //
7836 // Created by robin on 01.08.2020.
7837 //
7838
7839 #ifndef TILESON_WORLD_HPP
7840 #define TILESON_WORLD_HPP
7841
7842
7843 //
7844 // Created by robin on 01.08.2020.
7845 //
7846
7847 #ifndef TILESON_WORLDMAPDATA_HPP
7848 #define TILESON_WORLDMAPDATA_HPP
7849
7850namespace tson {
7852 public:
7853 inline WorldMapData(const fs::path &folder_, IJson &json);
7854 inline void parse(const fs::path &folder_, IJson &json);
7855 // inline WorldMapData(fs::path folder_, std::string fileName_) : folder {std::move(folder_)}, fileName {fileName_}
7856 //{
7857 // path = folder / fileName;
7858 // }
7859
7860 fs::path folder;
7861 fs::path path;
7862 std::string fileName;
7863 tson::Vector2i size;
7864 tson::Vector2i position;
7865 };
7866
7867 WorldMapData::WorldMapData(const fs::path &folder_, IJson &json)
7868 {
7869 parse(folder_, json);
7870 }
7871
7872 void WorldMapData::parse(const fs::path &folder_, IJson &json)
7873 {
7874 folder = folder_;
7875 if (json.count("fileName") > 0) fileName = json["fileName"].get<std::string>();
7876 if (json.count("height") > 0) size = {json["width"].get<int>(), json["height"].get<int>()};
7877 if (json.count("x") > 0) position = {json["x"].get<int>(), json["y"].get<int>()};
7878
7879 path = (!fileName.empty()) ? folder / fileName : folder;
7880 }
7881} // namespace tson
7882
7883 #endif // TILESON_WORLDMAPDATA_HPP
7884
7886 #include <memory>
7887
7888namespace tson {
7889 class Tileson;
7890
7891 class World {
7892 public:
7893 #ifdef JSON11_IS_DEFINED
7894 inline explicit World(std::unique_ptr<tson::IJson> jsonParser = std::make_unique<tson::Json11>()) : m_json {std::move(jsonParser)} {}
7895
7896 inline explicit World(const fs::path &path, std::unique_ptr<tson::IJson> jsonParser = std::make_unique<tson::Json11>());
7897 #else
7898 inline explicit World(std::unique_ptr<tson::IJson> jsonParser) : m_json {std::move(jsonParser)} {}
7899
7900 inline explicit World(const fs::path &path, std::unique_ptr<tson::IJson> jsonParser);
7901 #endif
7902 inline bool parse(const fs::path &path);
7903 inline std::size_t loadMaps(tson::Tileson *parser); // tileson_forward.hpp
7904 inline bool contains(std::string_view filename);
7905 inline const WorldMapData *get(std::string_view filename) const;
7906
7907 [[nodiscard]]
7908 inline const fs::path &getPath() const;
7909 [[nodiscard]]
7910 inline const fs::path &getFolder() const;
7911 [[nodiscard]]
7912 inline const std::vector<WorldMapData> &getMapData() const;
7913 [[nodiscard]]
7914 inline bool onlyShowAdjacentMaps() const;
7915 [[nodiscard]]
7916 inline const std::string &getType() const;
7917 [[nodiscard]]
7918 inline const std::vector<std::unique_ptr<tson::Map>> &getMaps() const;
7919
7920 private:
7921 inline void parseJson(IJson &json);
7922
7923 std::unique_ptr<IJson> m_json = nullptr;
7924 fs::path m_path;
7925 fs::path m_folder;
7926 std::vector<WorldMapData> m_mapData;
7927 std::vector<std::unique_ptr<tson::Map>> m_maps;
7928 bool m_onlyShowAdjacentMaps;
7929 std::string m_type;
7930 };
7931
7932 World::World(const fs::path &path, std::unique_ptr<tson::IJson> jsonParser) : m_json {std::move(jsonParser)}
7933 {
7934 parse(path);
7935 }
7936
7937 bool World::parse(const fs::path &path)
7938 {
7939 m_path = path;
7940 m_folder = m_path.parent_path();
7941
7942 if (!m_json->parse(path)) return false;
7943
7944 parseJson(*m_json);
7945 return true;
7946 }
7947
7948 const fs::path &World::getPath() const
7949 {
7950 return m_path;
7951 }
7952
7953 const std::vector<WorldMapData> &World::getMapData() const
7954 {
7955 return m_mapData;
7956 }
7957
7958 bool World::onlyShowAdjacentMaps() const
7959 {
7960 return m_onlyShowAdjacentMaps;
7961 }
7962
7963 const std::string &World::getType() const
7964 {
7965 return m_type;
7966 }
7967
7968 void World::parseJson(IJson &json)
7969 {
7970 if (json.count("onlyShowAdjacentMaps") > 0) m_onlyShowAdjacentMaps = json["onlyShowAdjacentMaps"].get<bool>();
7971 if (json.count("type") > 0) m_type = json["type"].get<std::string>();
7972
7973 if (json["maps"].isArray()) {
7974 auto &maps = json.array("maps");
7975 std::for_each(maps.begin(), maps.end(), [&](std::unique_ptr<IJson> &item) { m_mapData.emplace_back(m_folder, *item); });
7976 }
7977 }
7978
7979 const fs::path &World::getFolder() const
7980 {
7981 return m_folder;
7982 }
7983
7990 bool World::contains(std::string_view filename)
7991 {
7992 // Note: might be moved to std::ranges from C++20.
7993 return std::any_of(m_mapData.begin(), m_mapData.end(), [&](const auto &item) { return item.fileName == filename; });
7994 }
7995
8001 const WorldMapData *World::get(std::string_view filename) const
8002 {
8003 auto iter = std::find_if(m_mapData.begin(), m_mapData.end(), [&](const auto &item) { return item.fileName == filename; });
8004 return (iter == m_mapData.end()) ? nullptr : iter.operator->();
8005 }
8006
8013 const std::vector<std::unique_ptr<tson::Map>> &World::getMaps() const
8014 {
8015 return m_maps;
8016 }
8017
8018} // namespace tson
8019
8020 #endif // TILESON_WORLD_HPP
8021
8022
8024
8025 //
8026 // Created by robin on 01.08.22.
8027 //
8028
8029 #ifndef TILESON_PROJECTPROPERTYTYPES_HPP
8030 #define TILESON_PROJECTPROPERTYTYPES_HPP
8031
8032namespace tson {
8034 public:
8035 inline ProjectPropertyTypes() = default;
8036 inline bool parse(IJson &json, tson::Project *project);
8037
8038 inline const std::vector<tson::EnumDefinition> &getEnums() const;
8039 inline const std::vector<tson::TiledClass> &getClasses() const;
8040 [[nodiscard]]
8041 inline tson::EnumDefinition *getEnumDefinition(std::string_view name);
8042 [[nodiscard]]
8043 inline tson::TiledClass *getClass(std::string_view name);
8044 inline bool isUnhandledContentFound() const;
8045
8046 private:
8047 std::vector<tson::EnumDefinition> m_enums;
8048 std::vector<tson::TiledClass> m_classes;
8049 bool m_unhandledContentFound {false};
8050 };
8051
8052 bool ProjectPropertyTypes::parse(IJson &json, tson::Project *project)
8053 {
8054 m_enums.clear();
8055 m_classes.clear();
8056 m_unhandledContentFound = false;
8057
8058 if (json.count("propertyTypes") > 0 && json["propertyTypes"].isArray()) {
8059 auto &array = json.array("propertyTypes");
8060 std::vector<tson::IJson *> classes; // Classes must be handled after enums
8061 std::vector<tson::IJson *> other; // Unhandled stuff - just to keep track if something is missing...
8062 std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item) {
8063 IJson &j = *item;
8064 if (j.count("type") > 0) {
8065 std::string t = j["type"].get<std::string>();
8066 if (t == "enum") {
8067 m_enums.emplace_back(j); // Can be resolved directly
8068 } else if (t == "class") {
8069 classes.push_back(item.get()); // Must be resolved later
8070 } else
8071 other.push_back(item.get()); // Only used to set flag for whether unhandled content was found.
8072 }
8073 });
8074
8075 std::for_each(classes.begin(), classes.end(), [&](IJson *item) { m_classes.emplace_back(*item, project); });
8076
8077 if (!other.empty()) m_unhandledContentFound = true;
8078 }
8079 return false;
8080 }
8081
8082 const std::vector<tson::EnumDefinition> &ProjectPropertyTypes::getEnums() const
8083 {
8084 return m_enums;
8085 }
8086
8087 const std::vector<tson::TiledClass> &ProjectPropertyTypes::getClasses() const
8088 {
8089 return m_classes;
8090 }
8091
8092 bool ProjectPropertyTypes::isUnhandledContentFound() const
8093 {
8094 return m_unhandledContentFound;
8095 }
8096
8097 tson::EnumDefinition *ProjectPropertyTypes::getEnumDefinition(std::string_view name)
8098 {
8099 auto it = std::find_if(m_enums.begin(), m_enums.end(), [&](const EnumDefinition &def) { return def.getName() == name; });
8100
8101 if (it != m_enums.end()) return &it.operator*();
8102
8103 return nullptr;
8104 }
8105
8106 tson::TiledClass *ProjectPropertyTypes::getClass(std::string_view name)
8107 {
8108 auto it = std::find_if(m_classes.begin(), m_classes.end(), [&](const TiledClass &def) { return def.getName() == name; });
8109
8110 if (it != m_classes.end()) return &it.operator*();
8111
8112 return nullptr;
8113 }
8114} // namespace tson
8115
8116 #endif // TILESON_PROJECTPROPERTYTYPES_HPP
8117
8118
8120
8121 //
8122 // Created by robin on 01.08.2020.
8123 //
8124
8125 #ifndef TILESON_PROJECTFOLDER_HPP
8126 #define TILESON_PROJECTFOLDER_HPP
8127
8128namespace tson {
8130 public:
8131 inline ProjectFolder(const fs::path &path);
8132
8133 inline const fs::path &getPath() const;
8134 inline bool hasWorldFile() const;
8135 inline const std::vector<ProjectFolder> &getSubFolders() const;
8136 inline const std::vector<fs::path> &getFiles() const;
8137 inline const World &getWorld() const;
8138
8139 private:
8140 inline void loadData();
8141 fs::path m_path;
8142 bool m_hasWorldFile;
8143 tson::World m_world;
8144 std::vector<ProjectFolder> m_subFolders;
8145 std::vector<fs::path> m_files;
8146 };
8147
8148 ProjectFolder::ProjectFolder(const fs::path &path) : m_path {path}
8149 {
8150 loadData();
8151 }
8152
8153 void ProjectFolder::loadData()
8154 {
8155 m_hasWorldFile = false;
8156 m_subFolders.clear();
8157 m_files.clear();
8158 // Search and see if there is a World file .world file
8159 fs::path worldPath;
8160 for (const auto &entry : fs::directory_iterator(m_path)) {
8161 if (fs::is_regular_file(entry.path())) {
8162 if (entry.path().extension() == ".world") {
8163 m_hasWorldFile = true;
8164 worldPath = entry.path();
8165 }
8166 }
8167 }
8168
8169 if (m_hasWorldFile) m_world.parse(worldPath);
8170
8171 for (const auto &entry : fs::directory_iterator(m_path)) {
8172 if (fs::is_directory(entry.path()))
8173 m_subFolders.emplace_back(entry.path()); //.loadData(); - loadData() is called in the constructor, so don't call again.
8174 else if (fs::is_regular_file(entry.path())) {
8175 if (m_hasWorldFile && m_world.contains(entry.path().filename().generic_string()))
8176 m_files.emplace_back(entry.path());
8177 else if (!m_hasWorldFile)
8178 m_files.emplace_back(entry.path());
8179 }
8180 }
8181 }
8182
8183 const fs::path &ProjectFolder::getPath() const
8184 {
8185 return m_path;
8186 }
8187
8188 bool ProjectFolder::hasWorldFile() const
8189 {
8190 return m_hasWorldFile;
8191 }
8192
8193 const std::vector<ProjectFolder> &ProjectFolder::getSubFolders() const
8194 {
8195 return m_subFolders;
8196 }
8197
8198 const std::vector<fs::path> &ProjectFolder::getFiles() const
8199 {
8200 return m_files;
8201 }
8202
8208 {
8209 return m_world;
8210 }
8211} // namespace tson
8212
8213 #endif // TILESON_PROJECTFOLDER_HPP
8214
8216
8217 //
8218 // Created by robin on 01.08.2020.
8219 //
8220
8221 #ifndef TILESON_PROJECTDATA_HPP
8222 #define TILESON_PROJECTDATA_HPP
8223
8224namespace tson {
8226 public:
8227 ProjectData() = default;
8228 std::string automappingRulesFile;
8229 std::vector<std::string> commands;
8230 std::string extensionsPath;
8231 std::vector<std::string> folders;
8232 std::string objectTypesFile;
8233 ProjectPropertyTypes projectPropertyTypes;
8234
8235 // Tileson specific
8236 fs::path basePath;
8237 std::vector<tson::ProjectFolder> folderPaths;
8238 };
8239} // namespace tson
8240
8241 #endif // TILESON_PROJECTDATA_HPP
8242
8244namespace tson {
8245 class Project {
8246 public:
8247 #ifdef JSON11_IS_DEFINED
8248 inline explicit Project(std::unique_ptr<tson::IJson> jsonParser = std::make_unique<tson::Json11>()) : m_json {std::move(jsonParser)} {}
8249
8250 inline explicit Project(const fs::path &path, std::unique_ptr<tson::IJson> jsonParser = std::make_unique<tson::Json11>());
8251 #else
8252 inline explicit Project(std::unique_ptr<tson::IJson> jsonParser) : m_json {std::move(jsonParser)} {}
8253
8254 inline explicit Project(const fs::path &path, std::unique_ptr<tson::IJson> jsonParser);
8255 #endif
8256 inline bool parse(const fs::path &path);
8257 inline void parse();
8258
8259 [[nodiscard]]
8260 inline const ProjectData &getData() const;
8261 [[nodiscard]]
8262 inline const fs::path &getPath() const;
8263 [[nodiscard]]
8264 inline const std::vector<ProjectFolder> &getFolders() const;
8265 [[nodiscard]]
8266 inline tson::EnumDefinition *getEnumDefinition(std::string_view name);
8267 [[nodiscard]]
8268 inline tson::TiledClass *getClass(std::string_view name);
8269
8270 private:
8271 inline void parseJson(IJson &json);
8272 fs::path m_path;
8273 std::vector<ProjectFolder> m_folders;
8274 ProjectData m_data;
8275 std::unique_ptr<IJson> m_json = nullptr;
8276 };
8277
8278 Project::Project(const fs::path &path, std::unique_ptr<tson::IJson> jsonParser) : m_json {std::move(jsonParser)}
8279 {
8280 parse(path);
8281 }
8282
8283 bool Project::parse(const fs::path &path)
8284 {
8285 m_path = path;
8286 std::ifstream i(m_path.generic_string());
8287
8288 try {
8289 if (!m_json->parse(path)) return false;
8290 } catch (const std::exception &error) {
8291 std::string message = "Parse error: ";
8292 message += std::string(error.what());
8293 message += std::string("\n");
8294 return false;
8295 }
8296 parseJson(*m_json);
8297 return true;
8298 }
8299
8300 const ProjectData &Project::getData() const
8301 {
8302 return m_data;
8303 }
8304
8305 void Project::parseJson(IJson &json)
8306 {
8307 m_data.basePath = (m_path.empty()) ? fs::path() : m_path.parent_path(); // The directory of the project file
8308
8309 // Make sure these property types are read before any map is, so they can be resolved.
8310 if (json.count("propertyTypes") > 0) {
8311 m_data.projectPropertyTypes.parse(json, this);
8312 }
8313
8314 if (json.count("automappingRulesFile") > 0) m_data.automappingRulesFile = json["automappingRulesFile"].get<std::string>();
8315 if (json.count("commands") > 0) {
8316 m_data.commands.clear();
8317 auto &commands = json.array("commands");
8318 std::for_each(commands.begin(), commands.end(), [&](std::unique_ptr<IJson> &item) { m_data.commands.emplace_back(item->get<std::string>()); });
8319 }
8320 if (json.count("extensionsPath") > 0) m_data.extensionsPath = json["extensionsPath"].get<std::string>();
8321 if (json.count("folders") > 0) {
8322 m_data.folders.clear();
8323 m_data.folderPaths.clear();
8324 auto &folders = json.array("folders");
8325 std::for_each(folders.begin(), folders.end(), [&](std::unique_ptr<IJson> &item) {
8326 std::string folder = item->get<std::string>();
8327 m_data.folders.emplace_back(folder);
8328 m_data.folderPaths.emplace_back(m_data.basePath / folder);
8329 m_folders.emplace_back(m_data.basePath / folder);
8330 });
8331 }
8332 if (json.count("objectTypesFile") > 0) m_data.objectTypesFile = json["objectTypesFile"].get<std::string>();
8333 }
8334
8335 const fs::path &Project::getPath() const
8336 {
8337 return m_path;
8338 }
8339
8340 const std::vector<ProjectFolder> &Project::getFolders() const
8341 {
8342 return m_folders;
8343 }
8344
8345 tson::EnumDefinition *Project::getEnumDefinition(std::string_view name)
8346 {
8347 return m_data.projectPropertyTypes.getEnumDefinition(name);
8348 }
8349
8350 tson::TiledClass *Project::getClass(std::string_view name)
8351 {
8352 return m_data.projectPropertyTypes.getClass(name);
8353 }
8354
8360 {
8361 parseJson(*m_json);
8362 }
8363
8364} // namespace tson
8365
8366 #endif // TILESON_PROJECT_HPP
8367
8368
8370namespace tson {
8371 class Tileson {
8372 public:
8373 #ifdef JSON11_IS_DEFINED
8374 inline explicit Tileson(std::unique_ptr<tson::IJson> jsonParser = std::make_unique<tson::Json11>(), bool includeBase64Decoder = true);
8375 inline explicit Tileson(
8376 tson::Project *project, std::unique_ptr<tson::IJson> jsonParser = std::make_unique<tson::Json11>(), bool includeBase64Decoder = true);
8377 #else
8378 inline explicit Tileson(std::unique_ptr<tson::IJson> jsonParser, bool includeBase64Decoder = true);
8379 inline explicit Tileson(tson::Project *project, std::unique_ptr<tson::IJson> jsonParser, bool includeBase64Decoder = true);
8380 #endif
8381
8382 inline std::unique_ptr<tson::Map> parse(
8383 const fs::path &path, std::unique_ptr<IDecompressor<std::vector<uint8_t>, std::vector<uint8_t>>> decompressor = nullptr);
8384 inline std::unique_ptr<tson::Map> parse(
8385 const void *data, size_t size, std::unique_ptr<IDecompressor<std::vector<uint8_t>, std::vector<uint8_t>>> decompressor = nullptr);
8387
8388 private:
8389 inline std::unique_ptr<tson::Map> parseJson();
8390 std::unique_ptr<tson::IJson> m_json;
8391 tson::DecompressorContainer m_decompressors;
8392 tson::Project *m_project {nullptr};
8393 };
8394} // namespace tson
8395
8401tson::Tileson::Tileson(std::unique_ptr<tson::IJson> jsonParser, bool includeBase64Decoder) : m_json {std::move(jsonParser)}
8402{
8403 if (includeBase64Decoder) m_decompressors.add<Base64Decompressor>();
8404}
8405
8406tson::Tileson::Tileson(tson::Project *project, std::unique_ptr<tson::IJson> jsonParser, bool includeBase64Decoder) : m_json {std::move(jsonParser)}
8407{
8408 m_project = project;
8409 if (includeBase64Decoder) m_decompressors.add<Base64Decompressor>();
8410}
8411
8417std::unique_ptr<tson::Map> tson::Tileson::parse(const fs::path &path, std::unique_ptr<IDecompressor<std::vector<uint8_t>, std::vector<uint8_t>>> decompressor)
8418{
8419 bool result = false;
8420
8421 if (decompressor != nullptr) {
8422 std::vector<uint8_t> decompressed = decompressor->decompressFile(path);
8423 result = (decompressed.empty()) ? false : true;
8424 if (!result) return std::make_unique<tson::Map>(tson::ParseStatus::DecompressionError, "Error during decompression");
8425
8426 result = m_json->parse(&decompressed[0], decompressed.size());
8427
8428 if (result) return parseJson();
8429 } else if (m_json->parse(path)) {
8430 return parseJson();
8431 }
8432
8433 std::string msg = "File not found: ";
8434 msg += std::string(path.generic_string());
8435 return std::make_unique<tson::Map>(tson::ParseStatus::FileNotFound, msg);
8436}
8437
8444std::unique_ptr<tson::Map> tson::Tileson::parse(
8445 const void *data, size_t size, std::unique_ptr<IDecompressor<std::vector<uint8_t>, std::vector<uint8_t>>> decompressor)
8446{
8447 bool result = false;
8448
8449 if (decompressor != nullptr) {
8450 std::vector<uint8_t> decompressed = decompressor->decompress(data, size);
8451 result = (decompressed.empty()) ? false : true;
8452 if (!result) return std::make_unique<tson::Map>(tson::ParseStatus::DecompressionError, "Error during decompression");
8453 result = m_json->parse(&decompressed[0], decompressed.size());
8454 } else
8455 result = m_json->parse(data, size);
8456
8457 if (!result) return std::make_unique<tson::Map>(tson::ParseStatus::ParseError, "Memory error");
8458
8459 return parseJson();
8460}
8461
8467std::unique_ptr<tson::Map> tson::Tileson::parseJson()
8468{
8469 std::unique_ptr<tson::Map> map = std::make_unique<tson::Map>();
8470
8471 if (map->parse(*m_json, &m_decompressors, m_project)) return map;
8472
8473 return std::make_unique<tson::Map>(tson::ParseStatus::MissingData, "Missing map data...");
8474}
8475
8484{
8485 return &m_decompressors;
8486}
8487
8488#endif // TILESON_TILESON_PARSER_HPP
8489
8490
8492
8493//
8494// Created by robin on 25.07.2020.
8495//
8496
8497#ifndef TILESON_TILESON_FORWARD_HPP
8498 #define TILESON_TILESON_FORWARD_HPP
8499
8510// M a p . h p p
8511// ----------------
8512
8514{
8515 if (m_class == nullptr) {
8516 TiledClass *baseClass = (m_project != nullptr) ? m_project->getClass(m_classType) : nullptr;
8517 if (baseClass != nullptr) {
8518 m_class = std::make_shared<TiledClass>(*baseClass);
8519 m_class->update(m_properties);
8520 }
8521 }
8522 return (m_class != nullptr) ? m_class.get() : nullptr;
8523}
8524
8525// T i l e . h p p
8526// ---------------------
8527
8533{
8534 if (m_map != nullptr)
8535 return m_map->getTileSize();
8536 else
8537 return {0, 0};
8538}
8539
8540bool tson::Tile::parseId(IJson &json)
8541{
8542 if (json.count("id") > 0) {
8543 m_id = json["id"].get<uint32_t>() + 1;
8544 if (m_tileset != nullptr)
8545 m_gid = m_tileset->getFirstgid() + m_id - 1;
8546 else
8547 m_gid = m_id;
8548 manageFlipFlagsByIdThenRemoveFlags(m_gid);
8549 return true;
8550 }
8551 return false;
8552}
8553
8559{
8560 if (m_tileset == nullptr || m_map == nullptr) return;
8561
8562 int firstId = m_tileset->getFirstgid(); // First tile id of the tileset
8563 int columns = m_tileset->getColumns();
8564 int rows = m_tileset->getTileCount() / columns;
8565 int lastId = (m_tileset->getFirstgid() + m_tileset->getTileCount()) - 1;
8566
8567 int const gid = static_cast<int>(getGid());
8568 if (gid >= firstId && gid <= lastId) {
8569 int const baseTilePosition = (gid - firstId);
8570
8571 int const tileModX = (baseTilePosition % columns);
8572 int const currentRow = (baseTilePosition / columns);
8573 int const offsetX = (tileModX != 0) ? ((tileModX) *m_map->getTileSize().x) : (0 * m_map->getTileSize().x);
8574 int const offsetY = (currentRow < rows - 1) ? (currentRow * m_map->getTileSize().y) : ((rows - 1) * m_map->getTileSize().y);
8575
8576 tson::Vector2i spacing = m_tileset->getMarginSpacingOffset({tileModX, currentRow});
8577 m_drawingRect = {offsetX + spacing.x, offsetY + spacing.y, m_map->getTileSize().x, m_map->getTileSize().y};
8578 } else
8579 m_drawingRect = {0, 0, 0, 0};
8580}
8581
8586const tson::Vector2f tson::Tile::getPosition(const std::tuple<int, int> &tileDataPos)
8587{
8588 return {((float) std::get<0>(tileDataPos)) * m_drawingRect.width, ((float) std::get<1>(tileDataPos)) * m_drawingRect.height};
8589}
8590
8597{
8598 if (m_class == nullptr) {
8599 TiledClass *baseClass = (m_map != nullptr && m_map->getProject() != nullptr) ? m_map->getProject()->getClass(m_type) : nullptr;
8600 if (baseClass != nullptr) {
8601 m_class = std::make_shared<TiledClass>(*baseClass);
8602 m_class->update(m_properties);
8603 }
8604 }
8605 return (m_class != nullptr) ? m_class.get() : nullptr;
8606}
8607
8608// T i l e s e t . h p p
8609// ------------------------
8610
8611tson::TiledClass *tson::Tileset::getClass()
8612{
8613 if (m_class == nullptr) {
8614 TiledClass *baseClass = (m_map != nullptr && m_map->getProject() != nullptr) ? m_map->getProject()->getClass(m_classType) : nullptr;
8615 if (baseClass != nullptr) {
8616 m_class = std::make_shared<TiledClass>(*baseClass);
8617 m_class->update(m_properties);
8618 }
8619 }
8620 return (m_class != nullptr) ? m_class.get() : nullptr;
8621}
8622
8623// T i l e O b j e c t . h p p
8624// ---------------------
8625
8632void tson::TileObject::initialize(const std::tuple<int, int> &posInTileUnits, tson::Tile *tile)
8633{
8634 m_tile = tile;
8635 m_posInTileUnits = tile->getPositionInTileUnits(posInTileUnits);
8636 m_position = tile->getPosition(posInTileUnits);
8637}
8638
8639const tson::Rect &tson::TileObject::getDrawingRect() const
8640{
8641 return m_tile->getDrawingRect();
8642}
8643
8644// L a y e r . h p p
8645// -------------------
8646
8651{
8652 tson::DecompressorContainer *container = m_map->getDecompressors();
8653 if (container->empty()) return;
8654
8655 if (m_encoding.empty() && m_compression.empty()) return;
8656
8657 std::string data = m_base64Data;
8658 bool hasBeenDecoded = false;
8659 if (!m_encoding.empty() && container->contains(m_encoding)) {
8660 data = container->get(m_encoding)->decompress(data);
8661 hasBeenDecoded = true;
8662 }
8663
8664 if (!m_compression.empty() && container->contains(m_compression)) {
8665 data = container->get(m_compression)->decompress(data);
8666 }
8667
8668 if (hasBeenDecoded) {
8669 std::vector<uint8_t> bytes = tson::Tools::Base64DecodedStringToBytes(data);
8670 m_data = tson::Tools::BytesToUnsignedInts(bytes);
8671 }
8672}
8673
8680{
8681 m_map = map;
8682
8683 bool allFound = true;
8684 if (json.count("tintcolor") > 0) m_tintColor = tson::Colori(json["tintcolor"].get<std::string>()); // Optional
8685 if (json.count("compression") > 0) m_compression = json["compression"].get<std::string>(); // Optional
8686 if (json.count("draworder") > 0) m_drawOrder = json["draworder"].get<std::string>(); // Optional
8687 if (json.count("encoding") > 0) m_encoding = json["encoding"].get<std::string>(); // Optional
8688 if (json.count("id") > 0) m_id = json["id"].get<int>(); // Optional
8689 if (json.count("image") > 0) m_image = json["image"].get<std::string>(); // Optional
8690 if (json.count("name") > 0)
8691 m_name = json["name"].get<std::string>();
8692 else
8693 allFound = false;
8694 if (json.count("offsetx") > 0 && json.count("offsety") > 0) m_offset = {json["offsetx"].get<float>(), json["offsety"].get<float>()}; // Optional
8695 if (json.count("opacity") > 0)
8696 m_opacity = json["opacity"].get<float>();
8697 else
8698 allFound = false;
8699 if (json.count("width") > 0 && json.count("height") > 0)
8700 m_size = {json["width"].get<int>(), json["height"].get<int>()}; // else allFound = false; - Not mandatory for all layers!
8701 if (json.count("transparentcolor") > 0) m_transparentColor = tson::Colori(json["transparentcolor"].get<std::string>()); // Optional
8702 if (json.count("type") > 0)
8703 m_typeStr = json["type"].get<std::string>();
8704 else
8705 allFound = false;
8706 if (json.count("class") > 0) m_classType = json["class"].get<std::string>(); // Optional
8707 if (json.count("visible") > 0)
8708 m_visible = json["visible"].get<bool>();
8709 else
8710 allFound = false;
8711 if (json.count("x") > 0)
8712 m_x = json["x"].get<int>();
8713 else
8714 allFound = false;
8715 if (json.count("y") > 0)
8716 m_y = json["y"].get<int>();
8717 else
8718 allFound = false;
8719 if (json.count("repeatx") > 0) m_repeatX = json["repeatx"].get<bool>(); // Optional
8720 if (json.count("repeaty") > 0) m_repeatY = json["repeaty"].get<bool>(); // Optional
8721
8722 tson::Vector2f parallax {1.f, 1.f};
8723 if (json.count("parallaxx") > 0) parallax.x = json["parallaxx"].get<float>();
8724 if (json.count("parallaxy") > 0) parallax.y = json["parallaxy"].get<float>();
8725
8726 m_parallax = parallax;
8727
8728 // Handle DATA (Optional)
8729 if (json.count("data") > 0) {
8730 if (json["data"].isArray()) {
8731 auto &array = json.array("data");
8732 std::for_each(array.begin(), array.end(), [&](std::unique_ptr<IJson> &item) { m_data.push_back(item->get<uint32_t>()); });
8733 } else {
8734 m_base64Data = json["data"].get<std::string>();
8735 decompressData();
8736 }
8737 }
8738
8739 // More advanced data
8740 if (json.count("chunks") > 0 && json["chunks"].isArray()) {
8741 auto &chunks = json.array("chunks");
8742 std::for_each(chunks.begin(), chunks.end(), [&](std::unique_ptr<IJson> &item) { m_chunks.emplace_back(*item); });
8743 }
8744 if (json.count("layers") > 0 && json["layers"].isArray()) {
8745 auto &layers = json.array("layers");
8746 std::for_each(layers.begin(), layers.end(), [&](std::unique_ptr<IJson> &item) { m_layers.emplace_back(*item, m_map); });
8747 }
8748 if (json.count("objects") > 0 && json["objects"].isArray()) {
8749 auto &objects = json.array("objects");
8750 std::for_each(objects.begin(), objects.end(), [&](std::unique_ptr<IJson> &item) { m_objects.emplace_back(*item, m_map); });
8751 }
8752 if (json.count("properties") > 0 && json["properties"].isArray()) {
8753 auto &properties = json.array("properties");
8754 tson::Project *project = (m_map != nullptr) ? m_map->getProject() : nullptr;
8755 std::for_each(properties.begin(), properties.end(), [&](std::unique_ptr<IJson> &item) { m_properties.add(*item, project); });
8756 }
8757
8758 setTypeByString();
8759
8760 return allFound;
8761}
8762
8763tson::TiledClass *tson::Layer::getClass()
8764{
8765 if (m_class == nullptr) {
8766 TiledClass *baseClass = (m_map != nullptr && m_map->getProject() != nullptr) ? m_map->getProject()->getClass(m_classType) : nullptr;
8767 if (baseClass != nullptr) {
8768 m_class = std::make_shared<TiledClass>(*baseClass);
8769 m_class->update(m_properties);
8770 }
8771 }
8772 return (m_class != nullptr) ? m_class.get() : nullptr;
8773}
8774
8775// O b j e c t . h p p
8776// --------------------
8777
8778// W a n g s e t . h p p
8779// ----------------------
8780tson::TiledClass *tson::WangSet::getClass()
8781{
8782 if (m_class == nullptr) {
8783 TiledClass *baseClass = (m_map != nullptr && m_map->getProject() != nullptr) ? m_map->getProject()->getClass(m_classType) : nullptr;
8784 if (baseClass != nullptr) {
8785 m_class = std::make_shared<TiledClass>(*baseClass);
8786 m_class->update(m_properties);
8787 }
8788 }
8789 return (m_class != nullptr) ? m_class.get() : nullptr;
8790}
8791
8792// W a n g c o l o r . h p p
8793// ----------------------
8794tson::TiledClass *tson::WangColor::getClass()
8795{
8796 if (m_class == nullptr) {
8797 TiledClass *baseClass = (m_map != nullptr && m_map->getProject() != nullptr) ? m_map->getProject()->getClass(m_classType) : nullptr;
8798 if (baseClass != nullptr) {
8799 m_class = std::make_shared<TiledClass>(*baseClass);
8800 m_class->update(m_properties);
8801 }
8802 }
8803 return (m_class != nullptr) ? m_class.get() : nullptr;
8804}
8805
8812{
8813 if (m_class == nullptr) {
8814 TiledClass *baseClass = (m_map != nullptr && m_map->getProject() != nullptr) ? m_map->getProject()->getClass(m_type) : nullptr;
8815 if (baseClass != nullptr) {
8816 m_class = std::make_shared<TiledClass>(*baseClass);
8817 m_class->update(m_properties);
8818 }
8819 }
8820 return (m_class != nullptr) ? m_class.get() : nullptr;
8821}
8822
8823// W o r l d . h p p
8824// ------------------
8825
8833{
8834 m_maps.clear();
8835 std::for_each(m_mapData.begin(), m_mapData.end(), [&](const tson::WorldMapData &data) {
8836 if (fs::exists(data.path)) {
8837 std::unique_ptr<tson::Map> map = parser->parse(data.path);
8838 m_maps.push_back(std::move(map));
8839 }
8840 });
8841
8842 return m_maps.size();
8843}
8844
8845// P r o p e r t y . h p p
8846// ------------------
8847void tson::Property::setValueByType(IJson &json)
8848{
8849 switch (m_type) {
8850 case Type::Color: m_value = Colori(json.get<std::string>()); break;
8851
8852 case Type::File: m_value = fs::path(json.get<std::string>()); break;
8853
8854 case Type::Int:
8855 if (!m_propertyType.empty()) {
8856 m_type = Type::Enum;
8857 tson::EnumDefinition *def = (m_project != nullptr) ? m_project->getEnumDefinition(m_propertyType) : nullptr;
8858 if (def != nullptr) {
8859 uint32_t v = json.get<uint32_t>();
8860 m_value = tson::EnumValue(v, def);
8861 } else
8862 m_value = tson::EnumValue();
8863 } else
8864 m_value = json.get<int>();
8865
8866 break;
8867
8868 case Type::Boolean: m_value = json.get<bool>(); break;
8869
8870 case Type::Float: m_value = json.get<float>(); break;
8871
8872 case Type::String:
8873 if (!m_propertyType.empty()) {
8874 m_type = Type::Enum;
8875 tson::EnumDefinition *def = (m_project != nullptr) ? m_project->getEnumDefinition(m_propertyType) : nullptr;
8876 if (def != nullptr) {
8877 std::string v = json.get<std::string>();
8878 m_value = tson::EnumValue(v, def);
8879 } else
8880 m_value = tson::EnumValue();
8881 } else
8882 setStrValue(json.get<std::string>());
8883
8884 break;
8885
8886 case Type::Class: {
8887 tson::TiledClass *baseClass = (m_project != nullptr) ? m_project->getClass(m_propertyType) : nullptr;
8888 if (baseClass != nullptr) {
8889 tson::TiledClass c = *baseClass;
8890 c.update(json);
8891 m_value = c;
8892 }
8893 } break;
8894
8895 case Type::Object: m_value = json.get<uint32_t>(); break;
8896 default: setStrValue(json.get<std::string>()); break;
8897 }
8898}
8899
8900#endif // TILESON_TILESON_FORWARD_HPP
8901
8902
8904#endif // TILESON_TILESON_H
Definition: Tileson.hpp:450
Definition: Tileson.hpp:434
Definition: Tileson.hpp:408
Definition: Tileson.hpp:89
Definition: Tileson.hpp:421
Definition: Tileson.hpp:472
Definition: Tileson.hpp:461
Definition: Tileson.hpp:441
Definition: Tileson.hpp:232
Definition: Tileson.hpp:388
Definition: Tileson.hpp:5606
const tson::Frame * getCurrentFrame() const
Definition: Tileson.hpp:5652
void update(float timeDeltaMs)
Definition: Tileson.hpp:5666
void reset()
Definition: Tileson.hpp:5642
bool any() const
Definition: Tileson.hpp:5717
Definition: Tileson.hpp:1315
std::string decompressFile(const fs::path &path) override
Definition: Tileson.hpp:1399
std::string decompress(const std::string_view &s) override
Definition: Tileson.hpp:1335
const std::string & name() const override
Definition: Tileson.hpp:1330
Definition: Tileson.hpp:2924
const Vector2i & getSize() const
Definition: Tileson.hpp:3010
const std::string & getBase64Data() const
Definition: Tileson.hpp:3001
const std::vector< int > & getData() const
Definition: Tileson.hpp:2992
std::string m_base64Data
Definition: Tileson.hpp:2941
tson::Vector2i m_size
Definition: Tileson.hpp:2942
bool parse(IJson &json)
Definition: Tileson.hpp:2963
const Vector2i & getPosition() const
Definition: Tileson.hpp:3019
tson::Vector2i m_position
Definition: Tileson.hpp:2943
Definition: Tileson.hpp:1648
Color< uint8_t > asInt()
Definition: Tileson.hpp:1737
Color< float > asFloat()
Definition: Tileson.hpp:1722
Color(T red, T green, T blue, T alpha)
Definition: Tileson.hpp:1756
T a
Definition: Tileson.hpp:1679
T b
Definition: Tileson.hpp:1677
T g
Definition: Tileson.hpp:1675
T r
Definition: Tileson.hpp:1673
Definition: Tileson.hpp:1498
bool contains(std::string_view name) const
Definition: Tileson.hpp:1527
void remove(std::string_view name)
Definition: Tileson.hpp:1538
bool empty() const
Definition: Tileson.hpp:1565
IDecompressor< std::string_view, std::string > * get(std::string_view name)
Definition: Tileson.hpp:1554
void clear()
Definition: Tileson.hpp:1573
Definition: Tileson.hpp:7429
Definition: Tileson.hpp:7566
bool hasFlagValue(uint32_t flag) const
Definition: Tileson.hpp:7613
bool hasAnyFlagValue(uint32_t flags) const
Definition: Tileson.hpp:7626
bool containsValueName(const std::string &value) const
Definition: Tileson.hpp:7690
bool hasFlag(T flags) const
Definition: Tileson.hpp:7657
bool hasAnyFlag(T flags) const
Definition: Tileson.hpp:7670
std::string getValueName() const
Definition: Tileson.hpp:7644
Definition: Tileson.hpp:4262
uint32_t tileId
Definition: Tileson.hpp:4271
uint32_t id
Definition: Tileson.hpp:4269
Definition: Tileson.hpp:5519
int getDuration() const
Definition: Tileson.hpp:5579
uint32_t m_tileId
Definition: Tileson.hpp:5534
uint32_t getTileId() const
Definition: Tileson.hpp:5588
bool parse(IJson &json)
Definition: Tileson.hpp:5559
Definition: Tileson.hpp:6241
bool parse(IJson &json)
Definition: Tileson.hpp:6273
const Vector2i & getSize() const
Definition: Tileson.hpp:6300
tson::Vector2i m_size
Definition: Tileson.hpp:6255
const std::string & getOrientation() const
Definition: Tileson.hpp:6291
Definition: Tileson.hpp:1264
virtual TOut decompressFile(const fs::path &path)=0
virtual TOut decompress(const TIn &input)=0
virtual const std::string & name() const =0
virtual TOut decompress(const void *data, size_t size)=0
virtual ~IDecompressor()=default
Definition: Tileson.hpp:1856
virtual ~IJson()=default
virtual fs::path directory() const =0
virtual size_t size() const =0
virtual std::vector< std::unique_ptr< IJson > > array()=0
Definition: Tileson.hpp:2591
fs::path directory() const override
Definition: Tileson.hpp:2776
std::vector< std::unique_ptr< IJson > > array() override
Definition: Tileson.hpp:2628
size_t size() const override
Definition: Tileson.hpp:2659
Definition: Tileson.hpp:4282
std::vector< tson::Object > getObjectsByType(tson::ObjectType type)
Definition: Tileson.hpp:4473
const std::map< std::tuple< int, int >, tson::Tile * > & getTileData() const
Definition: Tileson.hpp:4746
std::vector< tson::Layer > & getLayers()
Definition: Tileson.hpp:4684
void createTileData(const Vector2i &mapSize, bool isInfiniteMap)
Definition: Tileson.hpp:4784
bool m_visible
Definition: Tileson.hpp:4398
const std::string & getBase64Data() const
Definition: Tileson.hpp:4548
PropertyCollection & getProperties()
Definition: Tileson.hpp:4702
tson::Object * firstObj(const std::string &name)
Definition: Tileson.hpp:4487
void assignTileMap(std::map< uint32_t, tson::Tile * > *tileMap)
Definition: Tileson.hpp:4731
int m_id
Definition: Tileson.hpp:4384
int getId() const
Definition: Tileson.hpp:4575
bool hasRepeatY() const
Definition: Tileson.hpp:4869
std::string m_compression
Definition: Tileson.hpp:4377
tson::Vector2i m_size
Definition: Tileson.hpp:4393
tson::Object * getObj(int id)
Definition: Tileson.hpp:4500
std::string m_base64Data
Definition: Tileson.hpp:4380
void queueFlaggedTile(size_t x, size_t y, uint32_t id)
Definition: Tileson.hpp:4446
const std::string & getName() const
Definition: Tileson.hpp:4593
bool parse(IJson &json, tson::Map *map)
Definition: Tileson.hpp:8679
LayerType getType() const
Definition: Tileson.hpp:4722
std::string m_image
Definition: Tileson.hpp:4385
std::vector< uint32_t > m_data
Definition: Tileson.hpp:4378
bool m_repeatY
Definition: Tileson.hpp:4404
tson::Vector2f m_parallax
Definition: Tileson.hpp:4401
LayerType m_type
Definition: Tileson.hpp:4397
const Vector2i & getSize() const
Definition: Tileson.hpp:4621
T get(const std::string &name)
Definition: Tileson.hpp:4431
std::string m_name
Definition: Tileson.hpp:4387
std::vector< tson::Layer > m_layers
Definition: Tileson.hpp:4386
void setTypeByString()
Definition: Tileson.hpp:4512
std::string m_typeStr
Definition: Tileson.hpp:4396
std::vector< tson::Chunk > & getChunks()
Definition: Tileson.hpp:4675
tson::Map * getMap() const
Definition: Tileson.hpp:4772
std::string m_drawOrder
Definition: Tileson.hpp:4382
tson::Vector2f m_offset
Definition: Tileson.hpp:4389
std::string m_encoding
Definition: Tileson.hpp:4383
const std::string & getEncoding() const
Definition: Tileson.hpp:4566
float getOpacity() const
Definition: Tileson.hpp:4611
const std::vector< uint32_t > & getData() const
Definition: Tileson.hpp:4539
const std::string & getCompression() const
Definition: Tileson.hpp:4530
bool hasRepeatX() const
Definition: Tileson.hpp:4859
tson::Map * m_map
Definition: Tileson.hpp:4415
int m_y
Definition: Tileson.hpp:4400
const Vector2f & getOffset() const
Definition: Tileson.hpp:4602
tson::Property * getProp(const std::string &name)
Definition: Tileson.hpp:4712
int m_x
Definition: Tileson.hpp:4399
bool isVisible() const
Definition: Tileson.hpp:4648
bool m_repeatX
Definition: Tileson.hpp:4403
const std::string & getTypeStr() const
Definition: Tileson.hpp:4639
const Colori & getTransparentColor() const
Definition: Tileson.hpp:4630
std::shared_ptr< tson::TiledClass > m_class
Definition: Tileson.hpp:4421
std::map< uint32_t, tson::Tile * > * m_tileMap
Definition: Tileson.hpp:4406
tson::PropertyCollection m_properties
Definition: Tileson.hpp:4392
const Colori & getTintColor() const
Definition: Tileson.hpp:4839
const std::string & getImage() const
Definition: Tileson.hpp:4584
const Vector2f & getParallax() const
Definition: Tileson.hpp:4849
std::vector< tson::Object > & getObjects()
Definition: Tileson.hpp:4693
float m_opacity
Definition: Tileson.hpp:4391
tson::Colori m_tintColor
Definition: Tileson.hpp:4410
std::vector< tson::Object > m_objects
Definition: Tileson.hpp:4388
void decompressData()
Definition: Tileson.hpp:8650
int getX() const
Definition: Tileson.hpp:4657
const std::string & getDrawOrder() const
Definition: Tileson.hpp:4557
std::map< std::tuple< int, int >, tson::TileObject > m_tileObjects
Definition: Tileson.hpp:4416
std::vector< tson::Object > getObjectsByName(const std::string &name)
Definition: Tileson.hpp:4459
int getY() const
Definition: Tileson.hpp:4666
tson::Colori m_transparentColor
Definition: Tileson.hpp:4395
Definition: Tileson.hpp:6889
Vector2i m_tileSize
Definition: Tileson.hpp:6976
const Vector2i & getSize() const
Definition: Tileson.hpp:7170
std::string m_staggerAxis
Definition: Tileson.hpp:6973
std::string m_renderOrder
Definition: Tileson.hpp:6972
std::string m_type
Definition: Tileson.hpp:6978
int m_nextObjectId
Definition: Tileson.hpp:6969
tson::Vector2f m_parallaxOrigin
Definition: Tileson.hpp:6979
std::string m_tiledVersion
Definition: Tileson.hpp:6975
Vector2i m_size
Definition: Tileson.hpp:6964
const std::string & getType() const
Definition: Tileson.hpp:7269
std::vector< tson::Layer > & getLayers()
Definition: Tileson.hpp:7287
void processData()
Definition: Tileson.hpp:7126
const Vector2i & getTileSize() const
Definition: Tileson.hpp:7260
std::string m_orientation
Definition: Tileson.hpp:6970
const std::string & getRenderOrder() const
Definition: Tileson.hpp:7224
const std::string & getOrientation() const
Definition: Tileson.hpp:7215
int getCompressionLevel() const
Definition: Tileson.hpp:7391
std::vector< tson::Tileset > & getTilesets()
Definition: Tileson.hpp:7305
const std::string & getStaggerAxis() const
Definition: Tileson.hpp:7233
tson::PropertyCollection m_properties
Definition: Tileson.hpp:6971
Tileset * getTileset(const std::string &name)
Definition: Tileson.hpp:7324
const std::string & getStaggerIndex() const
Definition: Tileson.hpp:7242
std::shared_ptr< tson::TiledClass > m_class
Definition: Tileson.hpp:6996
std::vector< tson::Tileset > m_tilesets
Definition: Tileson.hpp:6977
T get(const std::string &name)
Definition: Tileson.hpp:7006
tson::Property * getProp(const std::string &name)
Definition: Tileson.hpp:7356
const Vector2f & getParallaxOrigin() const
Definition: Tileson.hpp:7401
int getNextObjectId() const
Definition: Tileson.hpp:7206
int m_nextLayerId
Definition: Tileson.hpp:6968
std::vector< tson::Layer > m_layers
Definition: Tileson.hpp:6967
int m_hexsideLength
Definition: Tileson.hpp:6965
bool parse(IJson &json, tson::DecompressorContainer *decompressors, tson::Project *project)
Definition: Tileson.hpp:7034
Tileset * getTilesetByGid(uint32_t gid)
Definition: Tileson.hpp:7338
ParseStatus m_status
Definition: Tileson.hpp:6982
int m_compressionLevel
Definition: Tileson.hpp:6988
std::string m_staggerIndex
Definition: Tileson.hpp:6974
PropertyCollection & getProperties()
Definition: Tileson.hpp:7296
const std::string & getTiledVersion() const
Definition: Tileson.hpp:7251
const std::map< uint32_t, tson::Tile * > & getTileMap() const
Definition: Tileson.hpp:7376
tson::DecompressorContainer * m_decompressors
Definition: Tileson.hpp:6991
const Colori & getBackgroundColor() const
Definition: Tileson.hpp:7161
std::string m_classType
Definition: Tileson.hpp:6995
int getNextLayerId() const
Definition: Tileson.hpp:7197
bool createTilesetData(IJson &json)
Definition: Tileson.hpp:7103
tson::TiledClass * getClass()
Definition: Tileson.hpp:8513
int getHexsideLength() const
Definition: Tileson.hpp:7179
bool m_isInfinite
Definition: Tileson.hpp:6966
bool isInfinite() const
Definition: Tileson.hpp:7188
Definition: Tileson.hpp:1601
Definition: Tileson.hpp:1612
Definition: Tileson.hpp:3709
const std::string & getTemplate() const
Definition: Tileson.hpp:4023
const std::string & getClassType() const
Definition: Tileson.hpp:4043
std::string m_type
Definition: Tileson.hpp:3791
tson::TileFlipFlags m_flipFlags
Definition: Tileson.hpp:3796
bool hasFlipFlags(TileFlipFlags flags)
Definition: Tileson.hpp:4132
T get(const std::string &name)
Definition: Tileson.hpp:3809
const std::string & getName() const
Definition: Tileson.hpp:3996
TileFlipFlags getFlipFlags() const
Definition: Tileson.hpp:4119
const std::vector< tson::Vector2i > & getPolygons() const
Definition: Tileson.hpp:4071
float m_rotation
Definition: Tileson.hpp:3788
int m_id
Definition: Tileson.hpp:3782
tson::Vector2i m_position
Definition: Tileson.hpp:3793
tson::Property * getProp(const std::string &name)
Definition: Tileson.hpp:4109
const std::string & getType() const
Definition: Tileson.hpp:4033
std::string m_name
Definition: Tileson.hpp:3783
uint32_t m_gid
Definition: Tileson.hpp:3780
float getRotation() const
Definition: Tileson.hpp:4014
const std::vector< tson::Vector2i > & getPolylines() const
Definition: Tileson.hpp:4081
const Vector2i & getPosition() const
Definition: Tileson.hpp:4061
bool m_ellipse
Definition: Tileson.hpp:3779
bool parse(IJson &json, tson::Map *map)
Definition: Tileson.hpp:3830
std::string m_template
Definition: Tileson.hpp:3789
tson::Text m_text
Definition: Tileson.hpp:3790
const Vector2i & getSize() const
Definition: Tileson.hpp:3978
std::vector< tson::Vector2i > m_polyline
Definition: Tileson.hpp:3786
ObjectType getObjectType() const
Definition: Tileson.hpp:3951
bool isVisible() const
Definition: Tileson.hpp:4052
uint32_t getGid() const
Definition: Tileson.hpp:3969
tson::TiledClass * getClass()
Definition: Tileson.hpp:8811
tson::PropertyCollection m_properties
Definition: Tileson.hpp:3787
tson::Map * m_map
Definition: Tileson.hpp:3798
std::vector< tson::Vector2i > m_polygon
Definition: Tileson.hpp:3785
const Text & getText() const
Definition: Tileson.hpp:4099
bool isEllipse() const
Definition: Tileson.hpp:3960
bool m_point
Definition: Tileson.hpp:3784
int getId() const
Definition: Tileson.hpp:3987
bool m_visible
Definition: Tileson.hpp:3792
tson::Vector2i m_size
Definition: Tileson.hpp:3781
PropertyCollection & getProperties()
Definition: Tileson.hpp:4090
void setObjectTypeByJson(IJson &json)
Definition: Tileson.hpp:3925
bool isPoint() const
Definition: Tileson.hpp:4005
Definition: Tileson.hpp:8225
Definition: Tileson.hpp:8129
const World & getWorld() const
Definition: Tileson.hpp:8207
Definition: Tileson.hpp:8245
void parse()
Definition: Tileson.hpp:8359
Definition: Tileson.hpp:8033
Definition: Tileson.hpp:3491
void setProperty(const std::string &name, const tson::Property &value)
Definition: Tileson.hpp:3574
std::vector< Property * > get()
Definition: Tileson.hpp:3603
void setValue(const std::string &name, const std::any &value)
Definition: Tileson.hpp:3564
Definition: Tileson.hpp:3316
std::string getValueTypeInfo()
Definition: Tileson.hpp:3446
const std::type_info & getValueType() const
Definition: Tileson.hpp:3433
void setStrValue(const std::string &value)
Definition: Tileson.hpp:3406
Definition: Tileson.hpp:4158
Definition: Tileson.hpp:6120
PropertyCollection & getProperties()
Definition: Tileson.hpp:6208
tson::Property * getProp(const std::string &name)
Definition: Tileson.hpp:6218
int m_tile
Definition: Tileson.hpp:6141
T get(const std::string &name)
Definition: Tileson.hpp:6152
tson::PropertyCollection m_properties
Definition: Tileson.hpp:6142
const std::string & getName() const
Definition: Tileson.hpp:6190
int getTile() const
Definition: Tileson.hpp:6199
Definition: Tileson.hpp:3637
Text(IJson &json)
Definition: Tileson.hpp:3647
Definition: Tileson.hpp:5731
const fs::path & getImage() const
Definition: Tileson.hpp:5935
uint32_t m_gid
Definition: Tileson.hpp:5805
TileFlipFlags getFlipFlags() const
Definition: Tileson.hpp:6068
const Rect & getSubRectangle() const
Definition: Tileson.hpp:6100
tson::Vector2i m_imageSize
Definition: Tileson.hpp:5798
fs::path m_image
Definition: Tileson.hpp:5796
tson::Map * m_map
Definition: Tileson.hpp:5807
const tson::Vector2f getPosition(const std::tuple< int, int > &tileDataPos)
Definition: Tileson.hpp:8586
uint32_t m_id
Definition: Tileson.hpp:5794
const std::string & getType() const
Definition: Tileson.hpp:5954
std::vector< int > m_terrain
Definition: Tileson.hpp:5801
tson::Rect m_subRect
Definition: Tileson.hpp:5809
const std::vector< int > & getTerrain() const
Definition: Tileson.hpp:6000
PropertyCollection & getProperties()
Definition: Tileson.hpp:5991
const tson::Vector2i getTileSize() const
Definition: Tileson.hpp:8532
tson::Property * getProp(const std::string &name)
Definition: Tileson.hpp:6010
bool hasFlipFlags(TileFlipFlags flags)
Definition: Tileson.hpp:6081
const Vector2i & getImageSize() const
Definition: Tileson.hpp:5944
tson::PropertyCollection m_properties
Definition: Tileson.hpp:5800
void performDataCalculations()
Definition: Tileson.hpp:8558
bool parse(IJson &json, tson::Tileset *tileset, tson::Map *map)
Definition: Tileson.hpp:5872
Layer & getObjectgroup()
Definition: Tileson.hpp:5982
tson::Rect m_drawingRect
Definition: Tileson.hpp:5808
const std::string & getClassType() const
Definition: Tileson.hpp:5964
tson::Layer m_objectgroup
Definition: Tileson.hpp:5799
tson::Tileset * getTileset() const
Definition: Tileson.hpp:6021
const tson::Vector2i getPositionInTileUnits(const std::tuple< int, int > &tileDataPos)
Definition: Tileson.hpp:6054
tson::Animation & getAnimation()
Definition: Tileson.hpp:5973
std::string m_type
Definition: Tileson.hpp:5802
void addTilesetAndPerformCalculations(tson::Tileset *tileset)
Definition: Tileson.hpp:5861
tson::Map * getMap() const
Definition: Tileson.hpp:6030
void manageFlipFlagsByIdThenRemoveFlags(uint32_t &id)
Definition: Tileson.hpp:6059
tson::TileFlipFlags m_flipFlags
Definition: Tileson.hpp:5810
uint32_t getId() const
Definition: Tileson.hpp:5925
tson::Tileset * m_tileset
Definition: Tileson.hpp:5806
tson::TiledClass * getClass()
Definition: Tileson.hpp:8596
T get(const std::string &name)
Definition: Tileson.hpp:5824
const tson::Rect & getDrawingRect() const
Definition: Tileson.hpp:6039
Definition: Tileson.hpp:4198
const Vector2i & getPositionInTileUnits() const
Definition: Tileson.hpp:4234
Tile * getTile()
Definition: Tileson.hpp:4225
void initialize(const std::tuple< int, int > &posInTileUnits, tson::Tile *tile)
Definition: Tileson.hpp:8632
const Vector2f & getPosition() const
Definition: Tileson.hpp:4243
Definition: Tileson.hpp:7717
void update(IJson &json)
Definition: Tileson.hpp:7793
Definition: Tileson.hpp:6314
const std::string & getType() const
Definition: Tileson.hpp:6660
const std::vector< tson::Terrain > & getTerrains() const
Definition: Tileson.hpp:6706
int m_tileCount
Definition: Tileson.hpp:6400
const Vector2i & getImageSize() const
Definition: Tileson.hpp:6597
FillMode m_fillMode
Definition: Tileson.hpp:6428
tson::Vector2i m_tileSize
Definition: Tileson.hpp:6401
static tson::ObjectAlignment StringToAlignment(std::string_view str)
Definition: Tileson.hpp:6799
Transformations m_transformations
Definition: Tileson.hpp:6421
fs::path m_path
Definition: Tileson.hpp:6420
std::string m_type
Definition: Tileson.hpp:6403
std::string m_classType
Definition: Tileson.hpp:6432
const fs::path & getImage() const
Definition: Tileson.hpp:6670
int getSpacing() const
Definition: Tileson.hpp:6624
const Grid & getGrid() const
Definition: Tileson.hpp:6725
const Vector2i & getTileOffset() const
Definition: Tileson.hpp:6715
int getMargin() const
Definition: Tileson.hpp:6606
tson::Map * m_map
Definition: Tileson.hpp:6416
tson::Vector2i m_tileOffset
Definition: Tileson.hpp:6410
const fs::path & getImagePath() const
Definition: Tileson.hpp:6588
T get(const std::string &name)
Definition: Tileson.hpp:6443
tson::Colori m_transparentColor
Definition: Tileson.hpp:6402
std::vector< tson::Terrain > m_terrains
Definition: Tileson.hpp:6409
std::string m_name
Definition: Tileson.hpp:6398
const Vector2i & getTileSize() const
Definition: Tileson.hpp:6642
tson::Vector2i m_imageSize
Definition: Tileson.hpp:6396
tson::Property * getProp(const std::string &name)
Definition: Tileson.hpp:6762
tson::Map * getMap() const
Definition: Tileson.hpp:6789
const Transformations & getTransformations() const
Definition: Tileson.hpp:6865
std::vector< tson::Tile > m_tiles
Definition: Tileson.hpp:6405
int getFirstgid() const
Definition: Tileson.hpp:6578
tson::Grid m_grid
Definition: Tileson.hpp:6411
fs::path m_image
Definition: Tileson.hpp:6394
int getTileCount() const
Definition: Tileson.hpp:6633
TileRenderSize m_tileRenderSize
Definition: Tileson.hpp:6426
void generateMissingTiles()
Definition: Tileson.hpp:6772
tson::Tile * getTile(uint32_t id)
Definition: Tileson.hpp:6736
tson::PropertyCollection m_properties
Definition: Tileson.hpp:6407
std::vector< tson::WangSet > m_wangsets
Definition: Tileson.hpp:6406
fs::path m_source
Definition: Tileson.hpp:6419
PropertyCollection & getProperties()
Definition: Tileson.hpp:6697
const std::vector< tson::WangSet > & getWangsets() const
Definition: Tileson.hpp:6688
int getColumns() const
Definition: Tileson.hpp:6569
int m_spacing
Definition: Tileson.hpp:6399
int m_firstgid
Definition: Tileson.hpp:6392
const Colori & getTransparentColor() const
Definition: Tileson.hpp:6651
tson::ObjectAlignment m_objectAlignment
Definition: Tileson.hpp:6415
const std::string & getName() const
Definition: Tileson.hpp:6615
std::vector< tson::Tile > & getTiles()
Definition: Tileson.hpp:6679
std::shared_ptr< tson::TiledClass > m_class
Definition: Tileson.hpp:6433
tson::Terrain * getTerrain(const std::string &name)
Definition: Tileson.hpp:6749
int m_margin
Definition: Tileson.hpp:6397
tson::WangSet * getWangset(const std::string &name)
Definition: Tileson.hpp:6850
tson::Vector2i getMarginSpacingOffset(const tson::Vector2i &posInTileUnits)
Definition: Tileson.hpp:6837
Definition: Tileson.hpp:8371
Tileson(std::unique_ptr< tson::IJson > jsonParser=std::make_unique< tson::Json11 >(), bool includeBase64Decoder=true)
Definition: Tileson.hpp:8401
tson::DecompressorContainer * decompressors()
Definition: Tileson.hpp:8483
std::unique_ptr< tson::Map > parseJson()
Definition: Tileson.hpp:8467
std::unique_ptr< tson::Map > parse(const fs::path &path, std::unique_ptr< IDecompressor< std::vector< uint8_t >, std::vector< uint8_t > > > decompressor=nullptr)
Definition: Tileson.hpp:8417
Definition: Tileson.hpp:1157
static bool Equal(float a, float b, float precision=8192.f)
Definition: Tileson.hpp:1231
static std::vector< uint8_t > Base64DecodedStringToBytes(std::string_view str)
Definition: Tileson.hpp:1185
static std::vector< uint32_t > BytesToUnsignedInts(const std::vector< uint8_t > &bytes)
Definition: Tileson.hpp:1200
Definition: Tileson.hpp:4902
bool m_rotate
Definition: Tileson.hpp:4917
bool allowVflip() const
Definition: Tileson.hpp:4968
bool m_preferuntransformed
Definition: Tileson.hpp:4915
bool allowRotation() const
Definition: Tileson.hpp:4959
bool allowHflip() const
Definition: Tileson.hpp:4940
bool m_vflip
Definition: Tileson.hpp:4918
bool allowPreferuntransformed() const
Definition: Tileson.hpp:4950
Definition: Tileson.hpp:1799
Vector2(T xPos, T yPos)
Definition: Tileson.hpp:1819
Definition: Tileson.hpp:4999
tson::Property * getProp(const std::string &name)
Definition: Tileson.hpp:5137
float getProbability() const
Definition: Tileson.hpp:5096
T get(const std::string &name)
Definition: Tileson.hpp:5127
std::shared_ptr< tson::TiledClass > m_class
Definition: Tileson.hpp:5034
tson::Map * m_map
Definition: Tileson.hpp:5032
const std::string & getName() const
Definition: Tileson.hpp:5087
float m_probability
Definition: Tileson.hpp:5027
int m_tile
Definition: Tileson.hpp:5028
std::string m_name
Definition: Tileson.hpp:5026
tson::Colori m_color
Definition: Tileson.hpp:5025
PropertyCollection & getProperties()
Definition: Tileson.hpp:5115
const Colori & getColor() const
Definition: Tileson.hpp:5078
int getTile() const
Definition: Tileson.hpp:5105
tson::PropertyCollection m_properties
Definition: Tileson.hpp:5031
Definition: Tileson.hpp:5277
const std::vector< tson::WangColor > & getColors() const
Definition: Tileson.hpp:5468
int getTile() const
Definition: Tileson.hpp:5411
tson::Map * m_map
Definition: Tileson.hpp:5321
bool parseTiled15Props(IJson &json)
Definition: Tileson.hpp:5389
std::vector< tson::WangColor > m_edgeColors
Definition: Tileson.hpp:5315
std::vector< tson::WangTile > m_wangTiles
Definition: Tileson.hpp:5313
std::vector< tson::WangColor > m_colors
Definition: Tileson.hpp:5319
PropertyCollection & getProperties()
Definition: Tileson.hpp:5447
std::vector< tson::WangColor > m_cornerColors
Definition: Tileson.hpp:5314
const std::vector< tson::WangTile > & getWangTiles() const
Definition: Tileson.hpp:5420
const std::string & getName() const
Definition: Tileson.hpp:5402
const std::vector< tson::WangColor > & getEdgeColors() const
Definition: Tileson.hpp:5438
tson::WangColor * getColor(const std::string &name)
Definition: Tileson.hpp:5480
std::shared_ptr< tson::TiledClass > m_class
Definition: Tileson.hpp:5323
int m_tile
Definition: Tileson.hpp:5312
tson::PropertyCollection m_properties
Definition: Tileson.hpp:5316
const std::vector< tson::WangColor > & getCornerColors() const
Definition: Tileson.hpp:5429
tson::Property * getProp(const std::string &name)
Definition: Tileson.hpp:5457
T get(const std::string &name)
Definition: Tileson.hpp:5333
Definition: Tileson.hpp:5164
std::vector< uint32_t > m_wangId
Definition: Tileson.hpp:5187
bool hasHFlip() const
Definition: Tileson.hpp:5238
uint32_t m_tileid
Definition: Tileson.hpp:5185
bool hasDFlip() const
Definition: Tileson.hpp:5227
bool m_hflip
Definition: Tileson.hpp:5184
uint32_t getTileid() const
Definition: Tileson.hpp:5247
bool parse(IJson &json)
Definition: Tileson.hpp:5201
bool hasVFlip() const
Definition: Tileson.hpp:5258
const std::vector< uint32_t > & getWangIds() const
Definition: Tileson.hpp:5267
bool m_vflip
Definition: Tileson.hpp:5186
Definition: Tileson.hpp:7891
const WorldMapData * get(std::string_view filename) const
Definition: Tileson.hpp:8001
std::size_t loadMaps(tson::Tileson *parser)
Definition: Tileson.hpp:8832
const std::vector< std::unique_ptr< tson::Map > > & getMaps() const
Definition: Tileson.hpp:8013
bool contains(std::string_view filename)
Definition: Tileson.hpp:7990
Definition: Tileson.hpp:7851
Definition: Tileson.hpp:278
Definition: Tileson.hpp:480
Definition: Tileson.hpp:3092