#pragma once #include "StarDungeonGenerator.hpp" #include "StarJson.hpp" #include "StarLexicalCast.hpp" #include "StarLruCache.hpp" #include "StarSet.hpp" namespace Star { STAR_CLASS(TilesetDatabase); namespace Tiled { STAR_CLASS(Tile); STAR_CLASS(Tileset); extern EnumMap const LayerNames; // Tiled properties are all String values (due to its original format being // XML). This class wraps and converts the String properties into more useful // types, parsing them as Json for instance. class Properties { public: Properties(); Properties(Json const& json); Json toJson() const; // Returns a new properties set where this properties object overrides // the properties parameter. Properties inherit(Json const& properties) const; Properties inherit(Properties const& properties) const; bool contains(String const& name) const; template T get(String const& name) const; template Maybe opt(String const& name) const; template void set(String const& name, T const& value); private: Json m_properties; }; class Tile : public Dungeon::Tile { public: Tile(Properties const& properties, TileLayer layer, bool flipX = false); Properties properties; }; class Tileset { public: Tileset(Json const& json); TileConstPtr const& getTile(size_t id, TileLayer layer) const; size_t size() const; private: List const& tiles(TileLayer layer) const; List m_tilesBack, m_tilesFront; }; } class TilesetDatabase { public: TilesetDatabase(); Tiled::TilesetConstPtr get(String const& path) const; private: static Tiled::TilesetConstPtr readTileset(String const& path); mutable Mutex m_cacheMutex; mutable HashLruCache m_tilesetCache; }; namespace Tiled { template struct PropertyConverter { static T to(String const& propertyValue) { return lexicalCast(propertyValue); } static String from(T const& propertyValue) { return toString(propertyValue); } }; template <> struct PropertyConverter { static Json to(String const& propertyValue); static String from(Json const& propertyValue); }; template <> struct PropertyConverter { static String to(String const& propertyValue); static String from(String const& propertyValue); }; template T getProperty(Json const& properties, String const& propertyName) { return PropertyConverter::to(properties.get(propertyName).toString()); } template Maybe optProperty(Json const& properties, String const& propertyName) { if (Maybe propertyValue = properties.optString(propertyName)) return PropertyConverter::to(*propertyValue); return {}; } template Json setProperty(Json const& properties, String const& propertyName, T const& propertyValue) { return properties.set(propertyName, PropertyConverter::from(propertyValue)); } template T Properties::get(String const& name) const { return getProperty(m_properties, name); } template Maybe Properties::opt(String const& name) const { return optProperty(m_properties, name); } template void Properties::set(String const& name, T const& propertyValue) { m_properties = setProperty(m_properties, name, propertyValue); } } }