From aecd97bd7d1f72c4a81454e6739ed35095208614 Mon Sep 17 00:00:00 2001 From: Daniel Cronqvist Date: Wed, 14 Aug 2024 20:29:55 +0200 Subject: [PATCH] More tests --- DotTiled.Tests/Assert/AssertObject.cs | 2 + .../map-with-many-layers.cs | 7 +- .../map-with-many-layers.tmj | 44 ++---- .../map-with-many-layers.tmx | 4 +- .../TestData/Map/map-with-many-layers/poly.tj | 31 ++++ .../TestData/Map/map-with-many-layers/poly.tx | 9 ++ DotTiled/Serialization/Helpers.cs | 2 +- DotTiled/Serialization/Tmx/Tmx.ObjectLayer.cs | 148 ++++++++++++------ 8 files changed, 159 insertions(+), 88 deletions(-) create mode 100644 DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/poly.tj create mode 100644 DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/poly.tx diff --git a/DotTiled.Tests/Assert/AssertObject.cs b/DotTiled.Tests/Assert/AssertObject.cs index bd303f9..6c586bb 100644 --- a/DotTiled.Tests/Assert/AssertObject.cs +++ b/DotTiled.Tests/Assert/AssertObject.cs @@ -17,6 +17,8 @@ public static partial class DotTiledAssert AssertEqual(expected.Template, actual.Template, nameof(Object.Template)); AssertProperties(expected.Properties, actual.Properties); + + Assert.True(expected.GetType() == actual.GetType(), $"Expected object type {expected.GetType()} but got {actual.GetType()}"); AssertObject((dynamic)expected, (dynamic)actual); } diff --git a/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.cs b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.cs index 8ef6ce5..2ef98d0 100644 --- a/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.cs +++ b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.cs @@ -92,7 +92,12 @@ public partial class TestData new Vector2(0, 0), new Vector2(104,20), new Vector2(35.6667f, 32.3333f) - ] + ], + Template = fileExt == "tmx" ? "poly.tx" : "poly.tj", + Properties = new Dictionary + { + ["templateprop"] = new StringProperty { Name = "templateprop", Value = "helo there" } + } }, new TileObject { diff --git a/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.tmj b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.tmj index 16561f4..9e9f669 100644 --- a/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.tmj +++ b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.tmj @@ -11,15 +11,15 @@ "name":"Objects", "objects":[ { - "height":31.3333333333333, + "height":31.3333, "id":1, "name":"Object 1", "rotation":0, "type":"", "visible":true, - "width":31.3333333333333, - "x":25.6666666666667, - "y":28.6666666666667 + "width":31.3333, + "x":25.6667, + "y":28.6667 }, { "height":0, @@ -30,44 +30,26 @@ "type":"", "visible":true, "width":0, - "x":117.666666666667, - "y":48.6666666666667 + "x":117.667, + "y":48.6667 }, { "ellipse":true, - "height":34.6666666666667, + "height":34.6667, "id":4, "name":"Circle1", "rotation":0, "type":"", "visible":true, - "width":34.6666666666667, + "width":34.6667, "x":77, - "y":72.3333333333333 + "y":72.3333 }, { - "height":0, "id":5, - "name":"Poly", - "polygon":[ - { - "x":0, - "y":0 - }, - { - "x":104, - "y":20 - }, - { - "x":35.6666666666667, - "y":32.3333333333333 - }], - "rotation":0, - "type":"", - "visible":true, - "width":0, - "x":20.6666666666667, - "y":114.666666666667 + "template":"poly.tj", + "x":20.6667, + "y":114.667 }, { "gid":7, @@ -79,7 +61,7 @@ "visible":true, "width":64, "x":-35, - "y":110.333333333333 + "y":110.333 }], "opacity":1, "type":"objectgroup", diff --git a/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.tmx b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.tmx index 34cd91c..5888069 100644 --- a/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.tmx +++ b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/map-with-many-layers.tmx @@ -10,9 +10,7 @@ - - - + diff --git a/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/poly.tj b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/poly.tj new file mode 100644 index 0000000..f23c7d9 --- /dev/null +++ b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/poly.tj @@ -0,0 +1,31 @@ +{ "object": + { + "height":0, + "id":5, + "name":"Poly", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":104, + "y":20 + }, + { + "x":35.6667, + "y":32.3333 + }], + "properties":[ + { + "name":"templateprop", + "type":"string", + "value":"helo there" + }], + "rotation":0, + "type":"", + "visible":true, + "width":0 + }, + "type":"template" +} \ No newline at end of file diff --git a/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/poly.tx b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/poly.tx new file mode 100644 index 0000000..a0a2457 --- /dev/null +++ b/DotTiled.Tests/Serialization/TestData/Map/map-with-many-layers/poly.tx @@ -0,0 +1,9 @@ + + diff --git a/DotTiled/Serialization/Helpers.cs b/DotTiled/Serialization/Helpers.cs index 905cb9f..2e36124 100644 --- a/DotTiled/Serialization/Helpers.cs +++ b/DotTiled/Serialization/Helpers.cs @@ -72,7 +72,7 @@ internal static partial class Helpers }; } - internal static Dictionary MergeProperties(Dictionary? baseProperties, Dictionary overrideProperties) + internal static Dictionary MergeProperties(Dictionary? baseProperties, Dictionary? overrideProperties) { if (baseProperties is null) return overrideProperties ?? new Dictionary(); diff --git a/DotTiled/Serialization/Tmx/Tmx.ObjectLayer.cs b/DotTiled/Serialization/Tmx/Tmx.ObjectLayer.cs index fa80805..4d70b91 100644 --- a/DotTiled/Serialization/Tmx/Tmx.ObjectLayer.cs +++ b/DotTiled/Serialization/Tmx/Tmx.ObjectLayer.cs @@ -78,36 +78,21 @@ internal partial class Tmx { // Attributes var template = reader.GetOptionalAttribute("template"); - - uint? idDefault = null; - string nameDefault = ""; - string typeDefault = ""; - float xDefault = 0f; - float yDefault = 0f; - float widthDefault = 0f; - float heightDefault = 0f; - float rotationDefault = 0f; - uint? gidDefault = null; - bool visibleDefault = true; - Dictionary? propertiesDefault = null; - - // Perform template copy first + Object? obj = null; if (template is not null) - { - var resolvedTemplate = externalTemplateResolver(template); - var templObj = resolvedTemplate.Object; + obj = externalTemplateResolver(template).Object; - idDefault = templObj.ID; - nameDefault = templObj.Name; - typeDefault = templObj.Type; - xDefault = templObj.X; - yDefault = templObj.Y; - widthDefault = templObj.Width; - heightDefault = templObj.Height; - rotationDefault = templObj.Rotation; - visibleDefault = templObj.Visible; - propertiesDefault = templObj.Properties; - } + uint? idDefault = obj?.ID ?? null; + string nameDefault = obj?.Name ?? ""; + string typeDefault = obj?.Type ?? ""; + float xDefault = obj?.X ?? 0f; + float yDefault = obj?.Y ?? 0f; + float widthDefault = obj?.Width ?? 0f; + float heightDefault = obj?.Height ?? 0f; + float rotationDefault = obj?.Rotation ?? 0f; + uint? gidDefault = obj is TileObject tileObj ? tileObj.GID : null; + bool visibleDefault = obj?.Visible ?? true; + Dictionary? propertiesDefault = obj?.Properties ?? null; var id = reader.GetOptionalAttributeParseable("id") ?? idDefault; var name = reader.GetOptionalAttribute("name") ?? nameDefault; @@ -121,46 +106,66 @@ internal partial class Tmx var visible = reader.GetOptionalAttributeParseable("visible") ?? visibleDefault; // Elements - Object? obj = null; + Object? foundObject = null; int propertiesCounter = 0; Dictionary? properties = propertiesDefault; reader.ProcessChildren("object", (r, elementName) => elementName switch { "properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, Helpers.MergeProperties(properties, ReadProperties(r, customTypeDefinitions)), "Properties", ref propertiesCounter), - "ellipse" => () => Helpers.SetAtMostOnce(ref obj, ReadEllipseObject(r), "Object marker"), - "point" => () => Helpers.SetAtMostOnce(ref obj, ReadPointObject(r), "Object marker"), - "polygon" => () => Helpers.SetAtMostOnce(ref obj, ReadPolygonObject(r), "Object marker"), - "polyline" => () => Helpers.SetAtMostOnce(ref obj, ReadPolylineObject(r), "Object marker"), - "text" => () => Helpers.SetAtMostOnce(ref obj, ReadTextObject(r), "Object marker"), + "ellipse" => () => Helpers.SetAtMostOnce(ref foundObject, ReadEllipseObject(r), "Object marker"), + "point" => () => Helpers.SetAtMostOnce(ref foundObject, ReadPointObject(r), "Object marker"), + "polygon" => () => Helpers.SetAtMostOnce(ref foundObject, ReadPolygonObject(r), "Object marker"), + "polyline" => () => Helpers.SetAtMostOnce(ref foundObject, ReadPolylineObject(r), "Object marker"), + "text" => () => Helpers.SetAtMostOnce(ref foundObject, ReadTextObject(r), "Object marker"), _ => throw new Exception($"Unknown object marker '{elementName}'") }); - if (gid is not null) + if (foundObject is null) { - obj = new TileObject { ID = id, GID = gid.Value }; - reader.Skip(); + if (gid is not null) + foundObject = new TileObject { ID = id, GID = gid.Value }; + else + foundObject = new RectangleObject { ID = id }; } + foundObject.ID = id; + foundObject.Name = name; + foundObject.Type = type; + foundObject.X = x; + foundObject.Y = y; + foundObject.Width = width; + foundObject.Height = height; + foundObject.Rotation = rotation; + foundObject.Visible = visible; + foundObject.Properties = properties; + foundObject.Template = template; + + return OverrideObject(obj, foundObject); + } + + internal static Object OverrideObject(Object? obj, Object foundObject) + { if (obj is null) + return foundObject; + + if (obj.GetType() != foundObject.GetType()) { - obj = new RectangleObject { ID = id }; - reader.Skip(); + obj.ID = foundObject.ID; + obj.Name = foundObject.Name; + obj.Type = foundObject.Type; + obj.X = foundObject.X; + obj.Y = foundObject.Y; + obj.Width = foundObject.Width; + obj.Height = foundObject.Height; + obj.Rotation = foundObject.Rotation; + obj.Visible = foundObject.Visible; + obj.Properties = Helpers.MergeProperties(obj.Properties, foundObject.Properties); + obj.Template = foundObject.Template; + return obj; } - obj.ID = id; - obj.Name = name; - obj.Type = type; - obj.X = x; - obj.Y = y; - obj.Width = width; - obj.Height = height; - obj.Rotation = rotation; - obj.Visible = visible; - obj.Template = template; - obj.Properties = properties; - - return obj; + return OverrideObject((dynamic)obj, (dynamic)foundObject); } internal static EllipseObject ReadEllipseObject(XmlReader reader) @@ -169,12 +174,16 @@ internal partial class Tmx return new EllipseObject { }; } + internal static EllipseObject OverrideObject(EllipseObject obj, EllipseObject foundObject) => obj; + internal static PointObject ReadPointObject(XmlReader reader) { reader.Skip(); return new PointObject { }; } + internal static PointObject OverrideObject(PointObject obj, PointObject foundObject) => obj; + internal static PolygonObject ReadPolygonObject(XmlReader reader) { // Attributes @@ -193,6 +202,12 @@ internal partial class Tmx return new PolygonObject { Points = points }; } + internal static PolygonObject OverrideObject(PolygonObject obj, PolygonObject foundObject) + { + obj.Points = foundObject.Points; + return obj; + } + internal static PolylineObject ReadPolylineObject(XmlReader reader) { // Attributes @@ -211,6 +226,12 @@ internal partial class Tmx return new PolylineObject { Points = points }; } + internal static PolylineObject OverrideObject(PolylineObject obj, PolylineObject foundObject) + { + obj.Points = foundObject.Points; + return obj; + } + internal static TextObject ReadTextObject(XmlReader reader) { // Attributes @@ -259,6 +280,29 @@ internal partial class Tmx }; } + internal static TextObject OverrideObject(TextObject obj, TextObject foundObject) + { + obj.FontFamily = foundObject.FontFamily; + obj.PixelSize = foundObject.PixelSize; + obj.Wrap = foundObject.Wrap; + obj.Color = foundObject.Color; + obj.Bold = foundObject.Bold; + obj.Italic = foundObject.Italic; + obj.Underline = foundObject.Underline; + obj.Strikeout = foundObject.Strikeout; + obj.Kerning = foundObject.Kerning; + obj.HorizontalAlignment = foundObject.HorizontalAlignment; + obj.VerticalAlignment = foundObject.VerticalAlignment; + obj.Text = foundObject.Text; + return obj; + } + + internal static TileObject OverrideObject(TileObject obj, TileObject foundObject) + { + obj.GID = foundObject.GID; + return obj; + } + internal static Template ReadTemplate( XmlReader reader, Func externalTilesetResolver,