From eda3fbe308070d40a32d04c0d0518fdb74441fd3 Mon Sep 17 00:00:00 2001 From: Daniel Cronqvist Date: Sun, 25 Aug 2024 00:37:28 +0200 Subject: [PATCH] More docs --- docs/docs/accessing-properties.md | 36 +++++++++++++++++++++--------- docs/images/resolve-types.png | Bin 0 -> 19541 bytes 2 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 docs/images/resolve-types.png diff --git a/docs/docs/accessing-properties.md b/docs/docs/accessing-properties.md index 04e1846..59fcfea 100644 --- a/docs/docs/accessing-properties.md +++ b/docs/docs/accessing-properties.md @@ -2,7 +2,7 @@ [Tiled facilitates a very flexible way to store custom data in your maps using properties](https://doc.mapeditor.org/en/stable/manual/custom-properties/#custom-properties). Accessing these properties is a common task when working with Tiled maps in your game since it will allow you to fully utilize the strengths of Tiled, such as customizing the behavior of your game objects or setting up the initial state of your game world. -### All classes that can contain properties +## All classes that can contain properties All classes that can contain custom properties implement the interface in some way. Below is an exhaustive list of all classes that can contain custom properties: @@ -26,7 +26,7 @@ All classes that can contain custom properties implement the interface - -### How to access properties +## How to access properties To access the properties on one of the classes listed above, you will make use of the interface. @@ -52,7 +52,9 @@ else } ``` -### All types of properties +For both methods, you can replace `BoolProperty` with any of the property types that Tiled supports. You can find a list of all property types and their corresponding classes in the [next section](#all-types-of-properties). + +## All types of properties Tiled supports a variety of property types, which are represented in the DotTiled library as classes that implement the interface. Below is a list of all property types that Tiled supports and their corresponding classes in DotTiled: @@ -66,11 +68,11 @@ Tiled supports a variety of property types, which are represented in the DotTile In addition to these primitive property types, [Tiled also supports more complex property types](https://doc.mapeditor.org/en/stable/manual/custom-properties/#custom-types). These custom property types are defined in Tiled according to the linked documentation, and to work with them in DotTiled, you *must* define their equivalences as a collection of . This collection of definitions shall then be passed to the corresponding reader when loading a map, tileset, or template. -Whenever DotTiled encounters a property that is of type `class` in a Tiled file, it will attempt to find the corresponding definition, and if it does not find one, it will throw an exception. However, if it does find the definition, it will use that definition to know the default values of the properties of that class, and then override those defaults with the values found in the Tiled file. More information about these `class` properties can be found in [the next section](#class-properties). +Whenever DotTiled encounters a property that is of type `class` in a Tiled file, it will attempt to find the corresponding definition, and if it does not find one, it will throw an exception. However, if it does find the definition, it will use that definition to know the default values of the properties of that class, and then override those defaults with the values found in the Tiled file when populating a instance. More information about these `class` properties can be found in [the next section](#class-properties). Finally, Tiled also allows you to define custom property types that work as enums. These custom property types are just parsed and retrieved as their corresponding storage type. So for a custom property type that is defined as an enum where the values are stored as strings, DotTiled will just parse those as . Similarly, if the values are stored as integers, DotTiled will parse those as . -### Class properties +## Class properties As mentioned, Tiled supports `class` properties which allow you to create hierarchical structures of properties. DotTiled supports this feature through the class. For all your custom `class` types in Tiled, you must create an equivalent and pass it to the corresponding reader when loading a map, tileset, or template. @@ -86,10 +88,24 @@ var monsterSpawnerDefinition = new CustomClassDefinition Name = "MonsterSpawner", UseAs = CustomClassUseAs.All, // Not really validated by DotTiled Members = [ // Make sure that the default values match the Tiled UI - new BoolProperty { Name = "enabled", Value = true }, - new IntProperty { Name = "maxSpawnAmount", Value = 10 }, - new IntProperty { Name = "minSpawnAmount", Value = 0 }, - new StringProperty { Name = "monsterNames", Value = "" } + new BoolProperty { Name = "enabled", Value = true }, + new IntProperty { Name = "maxSpawnAmount", Value = 10 }, + new IntProperty { Name = "minSpawnAmount", Value = 0 }, + new StringProperty { Name = "monsterNames", Value = "" } ] }; -``` \ No newline at end of file +``` + +### Resolve object types and properties automatically + +If you don't want to have to rely on creating an equivalent definition for every `class` property that you may be using in your Tiled maps, you can check the `Resolve object types and properties` checkbox in `Edit > Preferences > General | Export Options` in Tiled. + +![Resolve object types and properties](../images/resolve-types.png) + +This will make sure that all properties, even those that do not differ from their default values, are included in the exported map, tileset, or template file. This will allow DotTiled to resolve the properties of the `class` property without needing an equivalent definition. However, you *must* enable a similar configuration flag in DotTiled when loading the map, tileset, or template to make sure that DotTiled knows to not throw an exception when it encounters a `class` property without an equivalent definition. + +### [Future] Automatically map custom property `class` types to C# classes + +In the future, DotTiled will support automatically mapping custom property `class` types to C# classes. This will allow you to define a C# class that matches the structure of the `class` property in Tiled, and DotTiled will automatically map the properties of the `class` property to the properties of the C# class. This will make working with `class` properties much easier and more intuitive. + +The idea is to expand on the interface with a method like `GetMappedProperty(string propertyName)`, where `T` is a class that matches the structure of the `class` property in Tiled. \ No newline at end of file diff --git a/docs/images/resolve-types.png b/docs/images/resolve-types.png new file mode 100644 index 0000000000000000000000000000000000000000..ea66d43618f89214acd5428815ca152ec1cf5f2d GIT binary patch literal 19541 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 NlvRCR_S7u!e*rjBFwFn} literal 0 HcmV?d00001