Merge pull request #26 from dcronqvist/resolve-class

Resolve properties from specified classes
This commit is contained in:
dcronqvist 2024-09-05 20:46:28 +02:00 committed by GitHub
commit 2b05ab9a72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 328 additions and 30 deletions

View file

@ -41,5 +41,7 @@ public static partial class TestData
["Serialization/TestData/Map/map_external_tileset_wangset/map-external-tileset-wangset", (string f) => MapExternalTilesetWangset(f), Array.Empty<ICustomTypeDefinition>()],
["Serialization/TestData/Map/map_with_many_layers/map-with-many-layers", (string f) => MapWithManyLayers(f), Array.Empty<ICustomTypeDefinition>()],
["Serialization/TestData/Map/map_with_deep_props/map-with-deep-props", (string f) => MapWithDeepProps(), MapWithDeepPropsCustomTypeDefinitions()],
["Serialization/TestData/Map/map_with_class/map-with-class", (string f) => MapWithClass(), MapWithClassCustomTypeDefinitions()],
["Serialization/TestData/Map/map_with_class_and_props/map-with-class-and-props", (string f) => MapWithClassAndProps(), MapWithClassAndPropsCustomTypeDefinitions()],
];
}

View file

@ -0,0 +1,83 @@
namespace DotTiled.Tests;
public partial class TestData
{
public static Map MapWithClassAndProps() => new Map
{
Class = "TestClass",
Orientation = MapOrientation.Orthogonal,
Width = 5,
Height = 5,
TileWidth = 32,
TileHeight = 32,
Infinite = false,
ParallaxOriginX = 0,
ParallaxOriginY = 0,
RenderOrder = RenderOrder.RightDown,
CompressionLevel = -1,
BackgroundColor = new Color { R = 0, G = 0, B = 0, A = 0 },
Version = "1.10",
TiledVersion = "1.11.0",
NextLayerID = 2,
NextObjectID = 1,
Layers = [
new TileLayer
{
ID = 1,
Name = "Tile Layer 1",
Width = 5,
Height = 5,
Data = new Data
{
Encoding = DataEncoding.Csv,
GlobalTileIDs = new Optional<uint[]>([
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
]),
FlippingFlags = new Optional<FlippingFlags[]>([
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None
])
}
}
],
Properties = [
new BoolProperty
{
Name = "classbool",
Value = true
},
new StringProperty
{
Name = "classstring",
Value = "I am not default value"
}
]
};
public static IReadOnlyCollection<ICustomTypeDefinition> MapWithClassAndPropsCustomTypeDefinitions() => [
new CustomClassDefinition
{
Name = "TestClass",
UseAs = CustomClassUseAs.Map,
Members = [
new BoolProperty
{
Name = "classbool",
Value = true
},
new StringProperty
{
Name = "classstring",
Value = "Hello there default value"
}
]
},
];
}

View file

@ -0,0 +1,39 @@
{ "class":"TestClass",
"compressionlevel":-1,
"height":5,
"infinite":false,
"layers":[
{
"data":[0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0],
"height":5,
"id":1,
"name":"Tile Layer 1",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":5,
"x":0,
"y":0
}],
"nextlayerid":2,
"nextobjectid":1,
"orientation":"orthogonal",
"properties":[
{
"name":"classstring",
"type":"string",
"value":"I am not default value"
}],
"renderorder":"right-down",
"tiledversion":"1.11.0",
"tileheight":32,
"tilesets":[],
"tilewidth":32,
"type":"map",
"version":"1.10",
"width":5
}

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.0" class="TestClass" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
<properties>
<property name="classstring" value="I am not default value"/>
</properties>
<layer id="1" name="Tile Layer 1" width="5" height="5">
<data encoding="csv">
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
</data>
</layer>
</map>

View file

@ -0,0 +1,83 @@
namespace DotTiled.Tests;
public partial class TestData
{
public static Map MapWithClass() => new Map
{
Class = "TestClass",
Orientation = MapOrientation.Orthogonal,
Width = 5,
Height = 5,
TileWidth = 32,
TileHeight = 32,
Infinite = false,
ParallaxOriginX = 0,
ParallaxOriginY = 0,
RenderOrder = RenderOrder.RightDown,
CompressionLevel = -1,
BackgroundColor = new Color { R = 0, G = 0, B = 0, A = 0 },
Version = "1.10",
TiledVersion = "1.11.0",
NextLayerID = 2,
NextObjectID = 1,
Layers = [
new TileLayer
{
ID = 1,
Name = "Tile Layer 1",
Width = 5,
Height = 5,
Data = new Data
{
Encoding = DataEncoding.Csv,
GlobalTileIDs = new Optional<uint[]>([
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
]),
FlippingFlags = new Optional<FlippingFlags[]>([
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None,
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None
])
}
}
],
Properties = [
new BoolProperty
{
Name = "classbool",
Value = true
},
new StringProperty
{
Name = "classstring",
Value = "Hello there default value"
}
]
};
public static IReadOnlyCollection<ICustomTypeDefinition> MapWithClassCustomTypeDefinitions() => [
new CustomClassDefinition
{
Name = "TestClass",
UseAs = CustomClassUseAs.Map,
Members = [
new BoolProperty
{
Name = "classbool",
Value = true
},
new StringProperty
{
Name = "classstring",
Value = "Hello there default value"
}
]
},
];
}

View file

@ -0,0 +1,33 @@
{ "class":"TestClass",
"compressionlevel":-1,
"height":5,
"infinite":false,
"layers":[
{
"data":[0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0],
"height":5,
"id":1,
"name":"Tile Layer 1",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":5,
"x":0,
"y":0
}],
"nextlayerid":2,
"nextobjectid":1,
"orientation":"orthogonal",
"renderorder":"right-down",
"tiledversion":"1.11.0",
"tileheight":32,
"tilesets":[],
"tilewidth":32,
"type":"map",
"version":"1.10",
"width":5
}

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.0" class="TestClass" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
<layer id="1" name="Tile Layer 1" width="5" height="5">
<data encoding="csv">
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0
</data>
</layer>
</map>

View file

@ -86,6 +86,18 @@ internal static partial class Helpers
};
}
internal static List<IProperty> ResolveClassProperties(string className, Func<string, ICustomTypeDefinition> customTypeResolver)
{
if (string.IsNullOrWhiteSpace(className))
return null;
var customType = customTypeResolver(className) ?? throw new InvalidOperationException($"Could not resolve custom type '{className}'.");
if (customType is not CustomClassDefinition ccd)
throw new InvalidOperationException($"Custom type '{className}' is not a class.");
return CreateInstanceOfCustomClass(ccd, customTypeResolver);
}
internal static List<IProperty> CreateInstanceOfCustomClass(
CustomClassDefinition customClassDefinition,
Func<string, ICustomTypeDefinition> customTypeResolver)

View file

@ -17,7 +17,7 @@ public abstract partial class TmjReaderBase
var offsetY = element.GetOptionalProperty<float>("offsety").GetValueOr(0.0f);
var parallaxX = element.GetOptionalProperty<float>("parallaxx").GetValueOr(1.0f);
var parallaxY = element.GetOptionalProperty<float>("parallaxy").GetValueOr(1.0f);
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
var layers = element.GetOptionalPropertyCustom<List<BaseLayer>>("layers", e => e.GetValueAsList<BaseLayer>(ReadLayer)).GetValueOr([]);
return new Group

View file

@ -16,7 +16,7 @@ public abstract partial class TmjReaderBase
var offsetY = element.GetOptionalProperty<float>("offsety").GetValueOr(0.0f);
var parallaxX = element.GetOptionalProperty<float>("parallaxx").GetValueOr(1.0f);
var parallaxY = element.GetOptionalProperty<float>("parallaxy").GetValueOr(1.0f);
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
var image = element.GetRequiredProperty<string>("image");
var repeatX = element.GetOptionalProperty<bool>("repeatx").GetValueOr(false);

View file

@ -52,7 +52,7 @@ public abstract partial class TmjReaderBase
var nextObjectID = element.GetRequiredProperty<uint>("nextobjectid");
var infinite = element.GetOptionalProperty<bool>("infinite").GetValueOr(false);
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
List<BaseLayer> layers = element.GetOptionalPropertyCustom<List<BaseLayer>>("layers", e => e.GetValueAsList<BaseLayer>(el => ReadLayer(el))).GetValueOr([]);
List<Tileset> tilesets = element.GetOptionalPropertyCustom<List<Tileset>>("tilesets", e => e.GetValueAsList<Tileset>(el => ReadTileset(el, version, tiledVersion))).GetValueOr([]);

View file

@ -19,7 +19,7 @@ public abstract partial class TmjReaderBase
var offsetY = element.GetOptionalProperty<float>("offsety").GetValueOr(0.0f);
var parallaxX = element.GetOptionalProperty<float>("parallaxx").GetValueOr(1.0f);
var parallaxY = element.GetOptionalProperty<float>("parallaxy").GetValueOr(1.0f);
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
var x = element.GetOptionalProperty<uint>("x").GetValueOr(0);
var y = element.GetOptionalProperty<uint>("y").GetValueOr(0);

View file

@ -30,7 +30,7 @@ public abstract partial class TmjReaderBase
var opacity = element.GetOptionalProperty<float>("opacity").GetValueOr(1.0f);
var parallaxx = element.GetOptionalProperty<float>("parallaxx").GetValueOr(1.0f);
var parallaxy = element.GetOptionalProperty<float>("parallaxy").GetValueOr(1.0f);
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
var repeatX = element.GetOptionalProperty<bool>("repeatx").GetValueOr(false);
var repeatY = element.GetOptionalProperty<bool>("repeaty").GetValueOr(false);
var startX = element.GetOptionalProperty<int>("startx").GetValueOr(0);

View file

@ -40,7 +40,7 @@ public abstract partial class TmjReaderBase
"bottomright" => ObjectAlignment.BottomRight,
_ => throw new JsonException($"Unknown object alignment '{s}'")
}).GetValueOr(ObjectAlignment.Unspecified);
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
var source = element.GetOptionalProperty<string>("source");
var spacing = element.GetOptionalProperty<uint>("spacing");
var tileCount = element.GetOptionalProperty<uint>("tilecount");
@ -166,8 +166,8 @@ public abstract partial class TmjReaderBase
var height = e.GetOptionalProperty<uint>("height").GetValueOr(imageHeight.GetValueOr(0));
var objectGroup = e.GetOptionalPropertyCustom<ObjectLayer>("objectgroup", e => ReadObjectLayer(e));
var probability = e.GetOptionalProperty<float>("probability").GetValueOr(0.0f);
var properties = e.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var type = e.GetOptionalProperty<string>("type").GetValueOr("");
var properties = ResolveAndMergeProperties(type, e.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
Optional<Image> imageModel = image.HasValue ? new Image
{
@ -207,17 +207,17 @@ public abstract partial class TmjReaderBase
internal Wangset ReadWangset(JsonElement element)
{
var @clalss = element.GetOptionalProperty<string>("class").GetValueOr("");
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
var colors = element.GetOptionalPropertyCustom<List<WangColor>>("colors", e => e.GetValueAsList<WangColor>(el => ReadWangColor(el))).GetValueOr([]);
var name = element.GetRequiredProperty<string>("name");
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
var tile = element.GetOptionalProperty<int>("tile").GetValueOr(0);
var type = element.GetOptionalProperty<string>("type").GetValueOr("");
var wangTiles = element.GetOptionalPropertyCustom<List<WangTile>>("wangtiles", e => e.GetValueAsList<WangTile>(ReadWangTile)).GetValueOr([]);
return new Wangset
{
Class = @clalss,
Class = @class,
WangColors = colors,
Name = name,
Properties = properties,
@ -232,7 +232,7 @@ public abstract partial class TmjReaderBase
var color = element.GetRequiredPropertyParseable<Color>("color");
var name = element.GetRequiredProperty<string>("name");
var probability = element.GetOptionalProperty<float>("probability").GetValueOr(1.0f);
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]));
var tile = element.GetOptionalProperty<int>("tile").GetValueOr(0);
return new WangColor

View file

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace DotTiled.Serialization.Tmj;
@ -40,6 +42,12 @@ public abstract partial class TmjReaderBase : IDisposable
_customTypeResolver = customTypeResolver ?? throw new ArgumentNullException(nameof(customTypeResolver));
}
private List<IProperty> ResolveAndMergeProperties(string className, List<IProperty> readProperties)
{
var classProps = Helpers.ResolveClassProperties(className, _customTypeResolver);
return Helpers.MergeProperties(classProps, readProperties).ToList();
}
/// <inheritdoc/>
protected virtual void Dispose(bool disposing)
{

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace DotTiled.Serialization.Tmx;
@ -56,7 +57,8 @@ public abstract partial class TmxReaderBase
var infinite = _reader.GetOptionalAttributeParseable<uint>("infinite").GetValueOr(0) == 1;
// At most one of
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(@class, _customTypeResolver);
// Any number of
List<BaseLayer> layers = [];
@ -64,7 +66,7 @@ public abstract partial class TmxReaderBase
_reader.ProcessChildren("map", (r, elementName) => elementName switch
{
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
"tileset" => () => tilesets.Add(ReadTileset(version, tiledVersion)),
"layer" => () => layers.Add(ReadTileLayer(infinite)),
"objectgroup" => () => layers.Add(ReadObjectLayer()),

View file

@ -34,12 +34,13 @@ public abstract partial class TmxReaderBase
}).GetValueOr(DrawOrder.TopDown);
// Elements
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(@class, _customTypeResolver);
List<DotTiled.Object> objects = [];
_reader.ProcessChildren("objectgroup", (r, elementName) => elementName switch
{
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
"object" => () => objects.Add(ReadObject()),
_ => r.Skip
});
@ -101,7 +102,7 @@ public abstract partial class TmxReaderBase
// Elements
DotTiled.Object foundObject = null;
int propertiesCounter = 0;
List<IProperty> properties = propertiesDefault;
List<IProperty> properties = Helpers.ResolveClassProperties(type, _customTypeResolver) ?? propertiesDefault;
_reader.ProcessChildren("object", (r, elementName) => elementName switch
{

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
namespace DotTiled.Serialization.Tmx;
@ -21,13 +22,14 @@ public abstract partial class TmxReaderBase
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx").GetValueOr(1.0f);
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy").GetValueOr(1.0f);
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(@class, _customTypeResolver);
Data data = null;
_reader.ProcessChildren("layer", (r, elementName) => elementName switch
{
"data" => () => Helpers.SetAtMostOnce(ref data, ReadData(dataUsesChunks), "Data"),
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
_ => r.Skip
});
@ -69,13 +71,14 @@ public abstract partial class TmxReaderBase
var repeatX = _reader.GetOptionalAttributeParseable<uint>("repeatx").GetValueOr(0) == 1;
var repeatY = _reader.GetOptionalAttributeParseable<uint>("repeaty").GetValueOr(0) == 1;
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(@class, _customTypeResolver);
Image image = null;
_reader.ProcessChildren("imagelayer", (r, elementName) => elementName switch
{
"image" => () => Helpers.SetAtMostOnce(ref image, ReadImage(), "Image"),
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
_ => r.Skip
});
@ -113,12 +116,13 @@ public abstract partial class TmxReaderBase
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx").GetValueOr(1f);
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy").GetValueOr(1f);
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(@class, _customTypeResolver);
List<BaseLayer> layers = [];
_reader.ProcessChildren("group", (r, elementName) => elementName switch
{
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
"layer" => () => layers.Add(ReadTileLayer(false)),
"objectgroup" => () => layers.Add(ReadObjectLayer()),
"imagelayer" => () => layers.Add(ReadImageLayer()),

View file

@ -68,7 +68,8 @@ public abstract partial class TmxReaderBase
Image image = null;
TileOffset tileOffset = null;
Grid grid = null;
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(@class, _customTypeResolver);
List<Wangset> wangsets = null;
Transformations transformations = null;
List<Tile> tiles = [];
@ -78,7 +79,7 @@ public abstract partial class TmxReaderBase
"image" => () => Helpers.SetAtMostOnce(ref image, ReadImage(), "Image"),
"tileoffset" => () => Helpers.SetAtMostOnce(ref tileOffset, ReadTileOffset(), "TileOffset"),
"grid" => () => Helpers.SetAtMostOnce(ref grid, ReadGrid(), "Grid"),
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
"wangsets" => () => Helpers.SetAtMostOnce(ref wangsets, ReadWangsets(), "Wangsets"),
"transformations" => () => Helpers.SetAtMostOnce(ref transformations, ReadTransformations(), "Transformations"),
"tile" => () => tiles.Add(ReadTile()),
@ -197,14 +198,15 @@ public abstract partial class TmxReaderBase
var height = _reader.GetOptionalAttributeParseable<uint>("height");
// Elements
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(type, _customTypeResolver);
Image image = null;
ObjectLayer objectLayer = null;
List<Frame> animation = null;
_reader.ProcessChildren("tile", (r, elementName) => elementName switch
{
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
"image" => () => Helpers.SetAtMostOnce(ref image, ReadImage(), "Image"),
"objectgroup" => () => Helpers.SetAtMostOnce(ref objectLayer, ReadObjectLayer(), "ObjectLayer"),
"animation" => () => Helpers.SetAtMostOnce(ref animation, r.ReadList<Frame>("animation", "frame", (ar) =>
@ -243,13 +245,14 @@ public abstract partial class TmxReaderBase
var tile = _reader.GetRequiredAttributeParseable<int>("tile");
// Elements
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(@class, _customTypeResolver);
List<WangColor> wangColors = [];
List<WangTile> wangTiles = [];
_reader.ProcessChildren("wangset", (r, elementName) => elementName switch
{
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
"wangcolor" => () => wangColors.Add(ReadWangColor()),
"wangtile" => () => wangTiles.Add(ReadWangTile()),
_ => r.Skip
@ -279,11 +282,12 @@ public abstract partial class TmxReaderBase
var probability = _reader.GetOptionalAttributeParseable<float>("probability").GetValueOr(0f);
// Elements
List<IProperty> properties = null;
var propertiesCounter = 0;
List<IProperty> properties = Helpers.ResolveClassProperties(@class, _customTypeResolver);
_reader.ProcessChildren("wangcolor", (r, elementName) => elementName switch
{
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties()).ToList(), "Properties", ref propertiesCounter),
_ => r.Skip
});