diff --git a/src/DotTiled.Tests/Serialization/TestData.cs b/src/DotTiled.Tests/Serialization/TestData.cs index 3e58e6d..582bd70 100644 --- a/src/DotTiled.Tests/Serialization/TestData.cs +++ b/src/DotTiled.Tests/Serialization/TestData.cs @@ -42,5 +42,6 @@ public static partial class TestData ["Serialization/TestData/Map/map_with_many_layers/map-with-many-layers", (string f) => MapWithManyLayers(f), Array.Empty()], ["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()], ]; } diff --git a/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class-and-props/map-with-class-and-props.cs b/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class-and-props/map-with-class-and-props.cs new file mode 100644 index 0000000..8cbd6bd --- /dev/null +++ b/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class-and-props/map-with-class-and-props.cs @@ -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([ + 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.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 MapWithClassAndPropsCustomTypeDefinitions() => [ + new CustomClassDefinition + { + Name = "TestClass", + UseAs = CustomClassUseAs.Map, + Members = [ + new BoolProperty + { + Name = "classbool", + Value = true + }, + new StringProperty + { + Name = "classstring", + Value = "Hello there default value" + } + ] + }, + ]; +} diff --git a/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class-and-props/map-with-class-and-props.tmj b/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class-and-props/map-with-class-and-props.tmj new file mode 100644 index 0000000..d60afe3 --- /dev/null +++ b/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class-and-props/map-with-class-and-props.tmj @@ -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 +} \ No newline at end of file diff --git a/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class/map-with-class.cs b/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class/map-with-class.cs index 80d50a5..ef98d02 100644 --- a/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class/map-with-class.cs +++ b/src/DotTiled.Tests/Serialization/TestData/Map/map-with-class/map-with-class.cs @@ -55,7 +55,7 @@ public partial class TestData }, new StringProperty { - Name = "stringbool", + Name = "classstring", Value = "Hello there default value" } ] @@ -74,7 +74,7 @@ public partial class TestData }, new StringProperty { - Name = "stringbool", + Name = "classstring", Value = "Hello there default value" } ] diff --git a/src/DotTiled/Serialization/Tmj/TmjReaderBase.Map.cs b/src/DotTiled/Serialization/Tmj/TmjReaderBase.Map.cs index 8779dde..caecb7e 100644 --- a/src/DotTiled/Serialization/Tmj/TmjReaderBase.Map.cs +++ b/src/DotTiled/Serialization/Tmj/TmjReaderBase.Map.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Text.Json; namespace DotTiled.Serialization.Tmj; @@ -53,8 +52,7 @@ public abstract partial class TmjReaderBase var nextObjectID = element.GetRequiredProperty("nextobjectid"); var infinite = element.GetOptionalProperty("infinite").GetValueOr(false); - var classProps = Helpers.ResolveClassProperties(@class, _customTypeResolver); - var properties = Helpers.MergeProperties(element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]), classProps).ToList(); + var properties = ResolveAndMergeProperties(@class, element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([])); List layers = element.GetOptionalPropertyCustom>("layers", e => e.GetValueAsList(el => ReadLayer(el))).GetValueOr([]); List tilesets = element.GetOptionalPropertyCustom>("tilesets", e => e.GetValueAsList(el => ReadTileset(el, version, tiledVersion))).GetValueOr([]); diff --git a/src/DotTiled/Serialization/Tmj/TmjReaderBase.cs b/src/DotTiled/Serialization/Tmj/TmjReaderBase.cs index f36ca88..f32100a 100644 --- a/src/DotTiled/Serialization/Tmj/TmjReaderBase.cs +++ b/src/DotTiled/Serialization/Tmj/TmjReaderBase.cs @@ -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 ResolveAndMergeProperties(string className, List readProperties) + { + var classProps = Helpers.ResolveClassProperties(className, _customTypeResolver); + return Helpers.MergeProperties(classProps, readProperties).ToList(); + } + /// protected virtual void Dispose(bool disposing) { diff --git a/src/DotTiled/Serialization/Tmx/TmxReaderBase.Map.cs b/src/DotTiled/Serialization/Tmx/TmxReaderBase.Map.cs index a16b715..ed3a492 100644 --- a/src/DotTiled/Serialization/Tmx/TmxReaderBase.Map.cs +++ b/src/DotTiled/Serialization/Tmx/TmxReaderBase.Map.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; namespace DotTiled.Serialization.Tmx; @@ -56,6 +57,7 @@ public abstract partial class TmxReaderBase var infinite = _reader.GetOptionalAttributeParseable("infinite").GetValueOr(0) == 1; // At most one of + var propertiesCounter = 0; List properties = Helpers.ResolveClassProperties(@class, _customTypeResolver); // Any number of @@ -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()),