diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.cs b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.cs new file mode 100644 index 0000000..82dfd29 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.cs @@ -0,0 +1,242 @@ +using System.Numerics; + +namespace DotTiled.Tests; + +public partial class TestData +{ + public static Map MapOverrideObjectBug(string fileExt) => new Map + { + Class = "", + 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 = 8, + NextObjectID = 8, + Tilesets = [ + new Tileset + { + Version = "1.10", + TiledVersion = "1.11.0", + FirstGID = 1, + Name = "tileset", + TileWidth = 32, + TileHeight = 32, + TileCount = 24, + Columns = 8, + Source = $"tileset.{(fileExt == "tmx" ? "tsx" : "tsj")}", + Image = new Image + { + Format = ImageFormat.Png, + Source = "tileset.png", + Width = 256, + Height = 96, + } + } + ], + Layers = [ + new Group + { + ID = 2, + Name = "Root", + Layers = [ + new ObjectLayer + { + ID = 3, + Name = "Objects", + Objects = [ + new RectangleObject + { + ID = 1, + Name = "Object 1", + X = 25.6667f, + Y = 28.6667f, + Width = 31.3333f, + Height = 31.3333f + }, + new PointObject + { + ID = 3, + Name = "P1", + X = 117.667f, + Y = 48.6667f + }, + new EllipseObject + { + ID = 4, + Name = "Circle1", + X = 77f, + Y = 72.3333f, + Width = 34.6667f, + Height = 34.6667f + }, + new PolygonObject + { + ID = 5, + Name = "Poly", + X = 20.6667f, + Y = 114.667f, + Points = [ + new Vector2(0, 0), + new Vector2(104,20), + new Vector2(35.6667f, 32.3333f) + ], + Template = fileExt == "tmx" ? "poly.tx" : "poly.tj", + Properties = [ + new StringProperty { Name = "templateprop", Value = "helo there" } + ] + }, + new TileObject + { + ID = 6, + Name = "TileObj", + GID = 7, + X = -35, + Y = 110.333f, + Width = 64, + Height = 146 + }, + new RectangleObject + { + ID = 7, + Name = "", + Template = fileExt == "tmx" ? "random.tx" : "random.tj", + Type = "randomclass", + X = 134.552f, + Y = 113.638f + } + ] + }, + new Group + { + ID = 5, + Name = "Sub", + Layers = [ + new TileLayer + { + ID = 7, + Name = "Tile 3", + 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 + ]) + } + }, + new TileLayer + { + ID = 6, + Name = "Tile 2", + Width = 5, + Height = 5, + Data = new Data + { + Encoding = DataEncoding.Csv, + GlobalTileIDs = new Optional([ + 0, 15, 15, 0, 0, + 0, 15, 15, 0, 0, + 0, 15, 15, 15, 0, + 15, 15, 15, 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 + ]) + } + } + ] + }, + new ImageLayer + { + ID = 4, + Name = "ImageLayer", + Image = new Image + { + Format = ImageFormat.Png, + Source = "tileset.png", + Width = fileExt == "tmx" ? 256u : 0, // Currently, json format does not + Height = fileExt == "tmx" ? 96u : 0 // include image dimensions in image layer https://github.com/mapeditor/tiled/issues/4028 + }, + RepeatX = true + }, + new TileLayer + { + ID = 1, + Name = "Tile Layer 1", + Width = 5, + Height = 5, + Data = new Data + { + Encoding = DataEncoding.Csv, + GlobalTileIDs = new Optional([ + 1, 1, 1, 1, 1, + 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 + ]) + } + } + ] + } + ] + }; + + public static IReadOnlyCollection MapOverrideObjectBugCustomTypeDefinitions() => [ + new CustomClassDefinition + { + Name = "TestClass", + UseAs = CustomClassUseAs.Map, + Members = [ + new BoolProperty + { + Name = "classbool", + Value = true + }, + new StringProperty + { + Name = "classstring", + Value = "Hello there default value" + } + ] + }, + new CustomClassDefinition + { + Name = "randomclass" + } + ]; +} diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.tmj b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.tmj new file mode 100644 index 0000000..ba67083 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.tmj @@ -0,0 +1,171 @@ +{ "compressionlevel":-1, + "height":5, + "infinite":false, + "layers":[ + { + "id":2, + "layers":[ + { + "draworder":"topdown", + "id":3, + "name":"Objects", + "objects":[ + { + "height":31.3333, + "id":1, + "name":"Object 1", + "rotation":0, + "type":"", + "visible":true, + "width":31.3333, + "x":25.6667, + "y":28.6667 + }, + { + "height":0, + "id":3, + "name":"P1", + "point":true, + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":117.667, + "y":48.6667 + }, + { + "ellipse":true, + "height":34.6667, + "id":4, + "name":"Circle1", + "rotation":0, + "type":"", + "visible":true, + "width":34.6667, + "x":77, + "y":72.3333 + }, + { + "id":5, + "template":"poly.tj", + "x":20.6667, + "y":114.667 + }, + { + "gid":7, + "height":146, + "id":6, + "name":"TileObj", + "rotation":0, + "type":"", + "visible":true, + "width":64, + "x":-35, + "y":110.333 + }, + + { + "id":7, + "template":"random.tj", + "type":"randomclass", + "x":134.551764025448, + "y":113.637941006362 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }, + { + "id":5, + "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":7, + "name":"Tile 3", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":5, + "x":0, + "y":0 + }, + { + "data":[0, 15, 15, 0, 0, + 0, 15, 15, 0, 0, + 0, 15, 15, 15, 0, + 15, 15, 15, 0, 0, + 0, 0, 0, 0, 0], + "height":5, + "id":6, + "name":"Tile 2", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":5, + "x":0, + "y":0 + }], + "name":"Sub", + "opacity":1, + "type":"group", + "visible":true, + "x":0, + "y":0 + }, + { + "id":4, + "image":"tileset.png", + "name":"ImageLayer", + "opacity":1, + "repeatx":true, + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 + }, + { + "data":[1, 1, 1, 1, 1, + 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 + }], + "name":"Root", + "opacity":1, + "type":"group", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":8, + "nextobjectid":8, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.11.0", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset.tsj" + }], + "tilewidth":32, + "type":"map", + "version":"1.10", + "width":5 +} \ No newline at end of file diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.tmx b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.tmx new file mode 100644 index 0000000..08f2657 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/map-override-object-bug.tmx @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + +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 + + + + +0,15,15,0,0, +0,15,15,0,0, +0,15,15,15,0, +15,15,15,0,0, +0,0,0,0,0 + + + + + + + + +1,1,1,1,1, +0,0,0,0,0, +0,0,0,0,0, +0,0,0,0,0, +0,0,0,0,0 + + + + diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/poly.tj b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/poly.tj new file mode 100644 index 0000000..f23c7d9 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/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/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/poly.tx b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/poly.tx new file mode 100644 index 0000000..a0a2457 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/poly.tx @@ -0,0 +1,9 @@ + + diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/random.tj b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/random.tj new file mode 100644 index 0000000..09b8393 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/random.tj @@ -0,0 +1,12 @@ +{ "object": + { + "height":0, + "id":7, + "name":"", + "rotation":0, + "type":"randomclass", + "visible":true, + "width":0 + }, + "type":"template" +} \ No newline at end of file diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/random.tx b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/random.tx new file mode 100644 index 0000000..d6b44ee --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/random.tx @@ -0,0 +1,4 @@ + + diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.png b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.png new file mode 100644 index 0000000..97c1fb3 Binary files /dev/null and b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.png differ diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.tsj b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.tsj new file mode 100644 index 0000000..820e88f --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.tsj @@ -0,0 +1,14 @@ +{ "columns":8, + "image":"tileset.png", + "imageheight":96, + "imagewidth":256, + "margin":0, + "name":"tileset", + "spacing":0, + "tilecount":24, + "tiledversion":"1.11.0", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":"1.10" +} \ No newline at end of file diff --git a/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.tsx b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.tsx new file mode 100644 index 0000000..d730182 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/map-override-object-bug/tileset.tsx @@ -0,0 +1,4 @@ + + + + diff --git a/src/DotTiled.Tests/UnitTests/Serialization/TestData.cs b/src/DotTiled.Tests/UnitTests/Serialization/TestData.cs index b59622e..28358b3 100644 --- a/src/DotTiled.Tests/UnitTests/Serialization/TestData.cs +++ b/src/DotTiled.Tests/UnitTests/Serialization/TestData.cs @@ -46,5 +46,6 @@ public static partial class TestData [GetMapPath("map-with-deep-props"), (string f) => MapWithDeepProps(), MapWithDeepPropsCustomTypeDefinitions()], [GetMapPath("map-with-class"), (string f) => MapWithClass(), MapWithClassCustomTypeDefinitions()], [GetMapPath("map-with-class-and-props"), (string f) => MapWithClassAndProps(), MapWithClassAndPropsCustomTypeDefinitions()], + [GetMapPath("map-override-object-bug"), (string f) => MapOverrideObjectBug(f), MapOverrideObjectBugCustomTypeDefinitions()], ]; } diff --git a/src/DotTiled/Serialization/Tmx/TmxReaderBase.ObjectLayer.cs b/src/DotTiled/Serialization/Tmx/TmxReaderBase.ObjectLayer.cs index 7553d21..b2e0c56 100644 --- a/src/DotTiled/Serialization/Tmx/TmxReaderBase.ObjectLayer.cs +++ b/src/DotTiled/Serialization/Tmx/TmxReaderBase.ObjectLayer.cs @@ -148,19 +148,20 @@ public abstract partial class TmxReaderBase if (obj is null) return foundObject; + 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).ToList(); + obj.Template = foundObject.Template; + if (obj.GetType() != foundObject.GetType()) { - 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).ToList(); - obj.Template = foundObject.Template; return obj; } @@ -231,6 +232,13 @@ public abstract partial class TmxReaderBase return obj; } + internal static RectangleObject OverrideObject(RectangleObject obj, RectangleObject foundObject) + { + obj.Width = foundObject.Width; + obj.Height = foundObject.Height; + return obj; + } + internal TextObject ReadTextObject() { // Attributes