From 7ca19713215e62fbdbd9d327d90e728deee37d02 Mon Sep 17 00:00:00 2001 From: Daniel Cronqvist Date: Sun, 25 Aug 2024 00:16:59 +0200 Subject: [PATCH] A first attempt at documentation for properties --- docs/docs/accessing-properties.md | 96 +++++++++++++++++++++++++- docs/images/monster-spawner-class.png | Bin 0 -> 17831 bytes 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 docs/images/monster-spawner-class.png diff --git a/docs/docs/accessing-properties.md b/docs/docs/accessing-properties.md index 0269b88..04e1846 100644 --- a/docs/docs/accessing-properties.md +++ b/docs/docs/accessing-properties.md @@ -1 +1,95 @@ -# Accessing properties \ No newline at end of file +# Accessing properties + +[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 custom properties implement the interface in some way. Below is an exhaustive list of all classes that can contain custom properties: + +- + - + - + - + - +- (allows for recursive property objects) +- (used to define custom Tiled property types) +- + - + - + - + - + - + - + - +- +- +- +- + +### How to access properties + +To access the properties on one of the classes listed above, you will make use of the interface. + +In situations where you know that a property must exist, and you simply want to retrieve it, you can use the method like so: + +```csharp +var map = LoadMap(); +var propertyValue = map.GetProperty("boolPropertyInMap").Value; +``` + +If you are unsure whether a property exists, or you want to provide some kind of default behaviour if the property is not present, you can instead use the method like so: + +```csharp +var map = LoadMap(); +if (map.TryGetProperty("boolPropertyInMap", out var property)) +{ + // Do something with existing property + var propertyValue = property.Value; +} +else +{ + // Do something if property does not exist +} +``` + +### 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: + +- `bool` - +- `color` - +- `float` - +- `file` - +- `int` - +- `object` - +- `string` - + +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). + +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 + +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. + +For example, if you have a `class` property in Tiled that looks like this: + +![MonsterSpawner class in Tiled UI](../images/monster-spawner-class.png) + +The equivalent definition in DotTiled would look like the following: + +```csharp +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 = "" } + ] +}; +``` \ No newline at end of file diff --git a/docs/images/monster-spawner-class.png b/docs/images/monster-spawner-class.png new file mode 100644 index 0000000000000000000000000000000000000000..c3b5ef410d3649cd504f7f4ab564ac5b2b7b3134 GIT binary patch literal 17831 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 literal 0 HcmV?d00001