mirror of
https://github.com/dcronqvist/DotTiled.git
synced 2025-02-05 17:02:49 +02:00
Add object Templates to Model and TmxSerializer
This commit is contained in:
parent
5193ab5b61
commit
0f6db5254d
16 changed files with 631 additions and 44 deletions
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- TmxSerializer test data -->
|
<!-- TmxSerializer test data -->
|
||||||
<EmbeddedResource Include="TmxSerializer/TestData/**/*.tmx" />
|
<EmbeddedResource Include="TmxSerializer/TestData/**/*" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
94
DotTiled.Tests/TmxSerializer/TestData/Map/map-with-group.cs
Normal file
94
DotTiled.Tests/TmxSerializer/TestData/Map/map-with-group.cs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
namespace DotTiled.Tests;
|
||||||
|
|
||||||
|
public partial class TmxSerializerMapTests
|
||||||
|
{
|
||||||
|
private static Map MapWithGroup() => new Map
|
||||||
|
{
|
||||||
|
Version = "1.10",
|
||||||
|
TiledVersion = "1.11.0",
|
||||||
|
Orientation = MapOrientation.Orthogonal,
|
||||||
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
Width = 5,
|
||||||
|
Height = 5,
|
||||||
|
TileWidth = 32,
|
||||||
|
TileHeight = 32,
|
||||||
|
Infinite = false,
|
||||||
|
NextLayerID = 5,
|
||||||
|
NextObjectID = 2,
|
||||||
|
Layers = [
|
||||||
|
new TileLayer
|
||||||
|
{
|
||||||
|
ID = 4,
|
||||||
|
Name = "Tile Layer 2",
|
||||||
|
Width = 5,
|
||||||
|
Height = 5,
|
||||||
|
Data = new Data
|
||||||
|
{
|
||||||
|
Encoding = DataEncoding.Csv,
|
||||||
|
GlobalTileIDs = [
|
||||||
|
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 = [
|
||||||
|
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 Group
|
||||||
|
{
|
||||||
|
ID = 3,
|
||||||
|
Name = "Group 1",
|
||||||
|
Layers = [
|
||||||
|
new TileLayer
|
||||||
|
{
|
||||||
|
ID = 1,
|
||||||
|
Name = "Tile Layer 1",
|
||||||
|
Width = 5,
|
||||||
|
Height = 5,
|
||||||
|
Data = new Data
|
||||||
|
{
|
||||||
|
Encoding = DataEncoding.Csv,
|
||||||
|
GlobalTileIDs = [
|
||||||
|
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 = [
|
||||||
|
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 ObjectLayer
|
||||||
|
{
|
||||||
|
ID = 2,
|
||||||
|
Name = "Object Layer 1",
|
||||||
|
Objects = [
|
||||||
|
new RectangleObject
|
||||||
|
{
|
||||||
|
ID = 1,
|
||||||
|
Name = "Name",
|
||||||
|
X = 35.5f,
|
||||||
|
Y = 26,
|
||||||
|
Width = 64.5f,
|
||||||
|
Height = 64.5f,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
26
DotTiled.Tests/TmxSerializer/TestData/Map/map-with-group.tmx
Normal file
26
DotTiled.Tests/TmxSerializer/TestData/Map/map-with-group.tmx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="5" nextobjectid="2">
|
||||||
|
<layer id="4" name="Tile Layer 2" 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>
|
||||||
|
<group id="3" name="Group 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>
|
||||||
|
<objectgroup id="2" name="Object Layer 1">
|
||||||
|
<object id="1" name="Name" x="35.5" y="26" width="64.5" height="64.5"/>
|
||||||
|
</objectgroup>
|
||||||
|
</group>
|
||||||
|
</map>
|
|
@ -0,0 +1,125 @@
|
||||||
|
namespace DotTiled.Tests;
|
||||||
|
|
||||||
|
public partial class TmxSerializerMapTests
|
||||||
|
{
|
||||||
|
private static Map MapWithObjectTemplate() => new Map
|
||||||
|
{
|
||||||
|
Version = "1.10",
|
||||||
|
TiledVersion = "1.11.0",
|
||||||
|
Orientation = MapOrientation.Orthogonal,
|
||||||
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
Width = 5,
|
||||||
|
Height = 5,
|
||||||
|
TileWidth = 32,
|
||||||
|
TileHeight = 32,
|
||||||
|
Infinite = false,
|
||||||
|
NextLayerID = 3,
|
||||||
|
NextObjectID = 3,
|
||||||
|
Layers = [
|
||||||
|
new TileLayer
|
||||||
|
{
|
||||||
|
ID = 1,
|
||||||
|
Name = "Tile Layer 1",
|
||||||
|
Width = 5,
|
||||||
|
Height = 5,
|
||||||
|
Data = new Data
|
||||||
|
{
|
||||||
|
Encoding = DataEncoding.Csv,
|
||||||
|
GlobalTileIDs = [
|
||||||
|
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 = [
|
||||||
|
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 ObjectLayer
|
||||||
|
{
|
||||||
|
ID = 2,
|
||||||
|
Name = "Object Layer 1",
|
||||||
|
Objects = [
|
||||||
|
new RectangleObject
|
||||||
|
{
|
||||||
|
ID = 1,
|
||||||
|
Template = "map-with-object-template.tx",
|
||||||
|
Name = "Thingy 2",
|
||||||
|
X = 94.5749f,
|
||||||
|
Y = 33.6842f,
|
||||||
|
Width = 37.0156f,
|
||||||
|
Height = 37.0156f,
|
||||||
|
Properties = new Dictionary<string, IProperty>
|
||||||
|
{
|
||||||
|
["Bool"] = new BoolProperty { Name = "Bool", Value = true },
|
||||||
|
["TestClassInTemplate"] = new ClassProperty
|
||||||
|
{
|
||||||
|
Name = "TestClassInTemplate",
|
||||||
|
PropertyType = "TestClass",
|
||||||
|
Properties = new Dictionary<string, IProperty>
|
||||||
|
{
|
||||||
|
["Amount"] = new FloatProperty { Name = "Amount", Value = 37 },
|
||||||
|
["Name"] = new StringProperty { Name = "Name", Value = "I am here" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new RectangleObject
|
||||||
|
{
|
||||||
|
ID = 2,
|
||||||
|
Template = "map-with-object-template.tx",
|
||||||
|
Name = "Thingy",
|
||||||
|
X = 29.7976f,
|
||||||
|
Y = 33.8693f,
|
||||||
|
Width = 37.0156f,
|
||||||
|
Height = 37.0156f,
|
||||||
|
Properties = new Dictionary<string, IProperty>
|
||||||
|
{
|
||||||
|
["Bool"] = new BoolProperty { Name = "Bool", Value = true },
|
||||||
|
["TestClassInTemplate"] = new ClassProperty
|
||||||
|
{
|
||||||
|
Name = "TestClassInTemplate",
|
||||||
|
PropertyType = "TestClass",
|
||||||
|
Properties = new Dictionary<string, IProperty>
|
||||||
|
{
|
||||||
|
["Amount"] = new FloatProperty { Name = "Amount", Value = 4.2f },
|
||||||
|
["Name"] = new StringProperty { Name = "Name", Value = "Hello there" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new RectangleObject
|
||||||
|
{
|
||||||
|
ID = 3,
|
||||||
|
Template = "map-with-object-template.tx",
|
||||||
|
Name = "Thingy 3",
|
||||||
|
X = 5,
|
||||||
|
Y = 5,
|
||||||
|
Width = 37.0156f,
|
||||||
|
Height = 37.0156f,
|
||||||
|
Properties = new Dictionary<string, IProperty>
|
||||||
|
{
|
||||||
|
["Bool"] = new BoolProperty { Name = "Bool", Value = true },
|
||||||
|
["TestClassInTemplate"] = new ClassProperty
|
||||||
|
{
|
||||||
|
Name = "TestClassInTemplate",
|
||||||
|
PropertyType = "TestClass",
|
||||||
|
Properties = new Dictionary<string, IProperty>
|
||||||
|
{
|
||||||
|
["Amount"] = new FloatProperty { Name = "Amount", Value = 4.2f },
|
||||||
|
["Name"] = new StringProperty { Name = "Name", Value = "I am here 3" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="5" height="5" tilewidth="32" tileheight="32" infinite="0" nextlayerid="3" nextobjectid="3">
|
||||||
|
<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>
|
||||||
|
<objectgroup id="2" name="Object Layer 1">
|
||||||
|
<object id="1" template="map-with-object-template.tx" name="Thingy 2" x="94.5749" y="33.6842">
|
||||||
|
<properties>
|
||||||
|
<property name="Bool" type="bool" value="true"/>
|
||||||
|
<property name="TestClassInTemplate" type="class" propertytype="TestClass">
|
||||||
|
<properties>
|
||||||
|
<property name="Amount" type="float" value="37"/>
|
||||||
|
<property name="Name" value="I am here"/>
|
||||||
|
</properties>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
</object>
|
||||||
|
<object id="2" template="map-with-object-template.tx" x="29.7976" y="33.8693"/>
|
||||||
|
<object id="3" template="map-with-object-template.tx" name="Thingy 3" x="5" y="5">
|
||||||
|
<properties>
|
||||||
|
<property name="TestClassInTemplate" type="class" propertytype="TestClass">
|
||||||
|
<properties>
|
||||||
|
<property name="Name" value="I am here 3"/>
|
||||||
|
</properties>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
</object>
|
||||||
|
</objectgroup>
|
||||||
|
</map>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<template>
|
||||||
|
<object name="Thingy" width="37.0156" height="37.0156">
|
||||||
|
<properties>
|
||||||
|
<property name="Bool" type="bool" value="true"/>
|
||||||
|
<property name="TestClassInTemplate" type="class" propertytype="TestClass">
|
||||||
|
<properties>
|
||||||
|
<property name="Amount" type="float" value="4.2"/>
|
||||||
|
<property name="Name" value="Hello there"/>
|
||||||
|
</properties>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
|
</object>
|
||||||
|
</template>
|
|
@ -15,8 +15,6 @@ public partial class TmxSerializerLayerTests
|
||||||
Assert.Equal(expected.ID, actual.ID);
|
Assert.Equal(expected.ID, actual.ID);
|
||||||
Assert.Equal(expected.Name, actual.Name);
|
Assert.Equal(expected.Name, actual.Name);
|
||||||
Assert.Equal(expected.Class, actual.Class);
|
Assert.Equal(expected.Class, actual.Class);
|
||||||
Assert.Equal(expected.X, actual.X);
|
|
||||||
Assert.Equal(expected.Y, actual.Y);
|
|
||||||
Assert.Equal(expected.Opacity, actual.Opacity);
|
Assert.Equal(expected.Opacity, actual.Opacity);
|
||||||
Assert.Equal(expected.Visible, actual.Visible);
|
Assert.Equal(expected.Visible, actual.Visible);
|
||||||
Assert.Equal(expected.TintColor, actual.TintColor);
|
Assert.Equal(expected.TintColor, actual.TintColor);
|
||||||
|
@ -34,6 +32,8 @@ public partial class TmxSerializerLayerTests
|
||||||
// Attributes
|
// Attributes
|
||||||
Assert.Equal(expected.Width, actual.Width);
|
Assert.Equal(expected.Width, actual.Width);
|
||||||
Assert.Equal(expected.Height, actual.Height);
|
Assert.Equal(expected.Height, actual.Height);
|
||||||
|
Assert.Equal(expected.X, actual.X);
|
||||||
|
Assert.Equal(expected.Y, actual.Y);
|
||||||
|
|
||||||
Assert.NotNull(actual.Data);
|
Assert.NotNull(actual.Data);
|
||||||
TmxSerializerDataTests.AssertData(actual.Data, expected.Data);
|
TmxSerializerDataTests.AssertData(actual.Data, expected.Data);
|
||||||
|
@ -43,6 +43,8 @@ public partial class TmxSerializerLayerTests
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
Assert.Equal(expected.DrawOrder, actual.DrawOrder);
|
Assert.Equal(expected.DrawOrder, actual.DrawOrder);
|
||||||
|
Assert.Equal(expected.X, actual.X);
|
||||||
|
Assert.Equal(expected.Y, actual.Y);
|
||||||
|
|
||||||
Assert.NotNull(actual.Objects);
|
Assert.NotNull(actual.Objects);
|
||||||
Assert.Equal(expected.Objects.Count, actual.Objects.Count);
|
Assert.Equal(expected.Objects.Count, actual.Objects.Count);
|
||||||
|
@ -55,8 +57,19 @@ public partial class TmxSerializerLayerTests
|
||||||
// Attributes
|
// Attributes
|
||||||
Assert.Equal(expected.RepeatX, actual.RepeatX);
|
Assert.Equal(expected.RepeatX, actual.RepeatX);
|
||||||
Assert.Equal(expected.RepeatY, actual.RepeatY);
|
Assert.Equal(expected.RepeatY, actual.RepeatY);
|
||||||
|
Assert.Equal(expected.X, actual.X);
|
||||||
|
Assert.Equal(expected.Y, actual.Y);
|
||||||
|
|
||||||
Assert.NotNull(actual.Image);
|
Assert.NotNull(actual.Image);
|
||||||
TmxSerializerImageTests.AssertImage(actual.Image, expected.Image);
|
TmxSerializerImageTests.AssertImage(actual.Image, expected.Image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AssertLayer(Group actual, Group expected)
|
||||||
|
{
|
||||||
|
// Attributes
|
||||||
|
Assert.NotNull(actual.Layers);
|
||||||
|
Assert.Equal(expected.Layers.Count, actual.Layers.Count);
|
||||||
|
for (var i = 0; i < expected.Layers.Count; i++)
|
||||||
|
AssertLayer(actual.Layers[i], expected.Layers[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,13 +50,18 @@ public partial class TmxSerializerMapTests
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(DeserializeMap_ValidXmlNoExternalTilesets_ReturnsMapWithoutThrowing_Data))]
|
[MemberData(nameof(DeserializeMap_ValidXmlNoExternalTilesets_ReturnsMapWithoutThrowing_Data))]
|
||||||
public void DeserializeMap_ValidXmlNoExternalTilesets_ReturnsMapThatEqualsExpected(string testDataFile, Map expectedMap)
|
public void DeserializeMapFromXmlReader_ValidXmlNoExternalTilesets_ReturnsMapThatEqualsExpected(string testDataFile, Map expectedMap)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
using var reader = TmxSerializerTestData.GetReaderFor(testDataFile);
|
using var reader = TmxSerializerTestData.GetReaderFor(testDataFile);
|
||||||
var testDataFileText = TmxSerializerTestData.GetRawStringFor(testDataFile);
|
var testDataFileText = TmxSerializerTestData.GetRawStringFor(testDataFile);
|
||||||
Func<string, Tileset> externalTilesetResolver = (string s) => throw new NotSupportedException("External tilesets are not supported in this test");
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver = (TmxSerializer serializer, string s) =>
|
||||||
var tmxSerializer = new TmxSerializer(externalTilesetResolver);
|
throw new NotSupportedException("External tilesets are not supported in this test");
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
throw new NotSupportedException("External templates are not supported in this test");
|
||||||
|
var tmxSerializer = new TmxSerializer(
|
||||||
|
externalTilesetResolver,
|
||||||
|
externalTemplateResolver);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var map = tmxSerializer.DeserializeMap(reader);
|
var map = tmxSerializer.DeserializeMap(reader);
|
||||||
|
@ -68,5 +73,153 @@ public partial class TmxSerializerMapTests
|
||||||
|
|
||||||
Assert.NotNull(raw);
|
Assert.NotNull(raw);
|
||||||
AssertMap(raw, expectedMap);
|
AssertMap(raw, expectedMap);
|
||||||
|
|
||||||
|
AssertMap(map, raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(DeserializeMap_ValidXmlNoExternalTilesets_ReturnsMapWithoutThrowing_Data))]
|
||||||
|
public void DeserializeMapFromString_ValidXmlNoExternalTilesets_ReturnsMapThatEqualsExpected(string testDataFile, Map expectedMap)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testDataFileText = TmxSerializerTestData.GetRawStringFor(testDataFile);
|
||||||
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
throw new NotSupportedException("External tilesets are not supported in this test");
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
throw new NotSupportedException("External templates are not supported in this test");
|
||||||
|
var tmxSerializer = new TmxSerializer(
|
||||||
|
externalTilesetResolver,
|
||||||
|
externalTemplateResolver);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var raw = tmxSerializer.DeserializeMap(testDataFileText);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(raw);
|
||||||
|
AssertMap(raw, expectedMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(DeserializeMap_ValidXmlNoExternalTilesets_ReturnsMapWithoutThrowing_Data))]
|
||||||
|
public void DeserializeMapFromStringFromXmlReader_ValidXmlNoExternalTilesets_Equal(string testDataFile, Map expectedMap)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var reader = TmxSerializerTestData.GetReaderFor(testDataFile);
|
||||||
|
var testDataFileText = TmxSerializerTestData.GetRawStringFor(testDataFile);
|
||||||
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
throw new NotSupportedException("External tilesets are not supported in this test");
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
throw new NotSupportedException("External templates are not supported in this test");
|
||||||
|
var tmxSerializer = new TmxSerializer(
|
||||||
|
externalTilesetResolver,
|
||||||
|
externalTemplateResolver);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var map = tmxSerializer.DeserializeMap(reader);
|
||||||
|
var raw = tmxSerializer.DeserializeMap(testDataFileText);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(map);
|
||||||
|
Assert.NotNull(raw);
|
||||||
|
|
||||||
|
AssertMap(map, raw);
|
||||||
|
AssertMap(map, expectedMap);
|
||||||
|
AssertMap(raw, expectedMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> DeserializeMap_ValidXmlExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected_Data =>
|
||||||
|
[
|
||||||
|
["TmxSerializer.TestData.Map.map-with-object-template.tmx", MapWithObjectTemplate()],
|
||||||
|
["TmxSerializer.TestData.Map.map-with-group.tmx", MapWithGroup()],
|
||||||
|
];
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(DeserializeMap_ValidXmlExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected_Data))]
|
||||||
|
public void DeserializeMapFromXmlReader_ValidXmlExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected(string testDataFile, Map expectedMap)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var reader = TmxSerializerTestData.GetReaderFor(testDataFile);
|
||||||
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
{
|
||||||
|
using var tilesetReader = TmxSerializerTestData.GetReaderFor($"TmxSerializer.TestData.Tileset.{s}");
|
||||||
|
return serializer.DeserializeTileset(tilesetReader);
|
||||||
|
};
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
{
|
||||||
|
using var templateReader = TmxSerializerTestData.GetReaderFor($"TmxSerializer.TestData.Template.{s}");
|
||||||
|
return serializer.DeserializeTemplate(templateReader);
|
||||||
|
};
|
||||||
|
var tmxSerializer = new TmxSerializer(
|
||||||
|
externalTilesetResolver,
|
||||||
|
externalTemplateResolver);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var map = tmxSerializer.DeserializeMap(reader);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(map);
|
||||||
|
AssertMap(map, expectedMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(DeserializeMap_ValidXmlExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected_Data))]
|
||||||
|
public void DeserializeMapFromString_ValidXmlExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected(string testDataFile, Map expectedMap)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var testDataFileText = TmxSerializerTestData.GetRawStringFor(testDataFile);
|
||||||
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
{
|
||||||
|
using var tilesetReader = TmxSerializerTestData.GetReaderFor($"TmxSerializer.TestData.Tileset.{s}");
|
||||||
|
return serializer.DeserializeTileset(tilesetReader);
|
||||||
|
};
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
{
|
||||||
|
using var templateReader = TmxSerializerTestData.GetReaderFor($"TmxSerializer.TestData.Template.{s}");
|
||||||
|
return serializer.DeserializeTemplate(templateReader);
|
||||||
|
};
|
||||||
|
var tmxSerializer = new TmxSerializer(
|
||||||
|
externalTilesetResolver,
|
||||||
|
externalTemplateResolver);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var map = tmxSerializer.DeserializeMap(testDataFileText);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(map);
|
||||||
|
AssertMap(map, expectedMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(DeserializeMap_ValidXmlExternalTilesetsAndTemplates_ReturnsMapThatEqualsExpected_Data))]
|
||||||
|
public void DeserializeMapFromStringFromXmlReader_ValidXmlExternalTilesetsAndTemplates_Equal(string testDataFile, Map expectedMap)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var reader = TmxSerializerTestData.GetReaderFor(testDataFile);
|
||||||
|
var testDataFileText = TmxSerializerTestData.GetRawStringFor(testDataFile);
|
||||||
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
{
|
||||||
|
using var tilesetReader = TmxSerializerTestData.GetReaderFor($"TmxSerializer.TestData.Tileset.{s}");
|
||||||
|
return serializer.DeserializeTileset(tilesetReader);
|
||||||
|
};
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver = (TmxSerializer serializer, string s) =>
|
||||||
|
{
|
||||||
|
using var templateReader = TmxSerializerTestData.GetReaderFor($"TmxSerializer.TestData.Template.{s}");
|
||||||
|
return serializer.DeserializeTemplate(templateReader);
|
||||||
|
};
|
||||||
|
var tmxSerializer = new TmxSerializer(
|
||||||
|
externalTilesetResolver,
|
||||||
|
externalTemplateResolver);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var map = tmxSerializer.DeserializeMap(reader);
|
||||||
|
var raw = tmxSerializer.DeserializeMap(testDataFileText);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(map);
|
||||||
|
Assert.NotNull(raw);
|
||||||
|
|
||||||
|
AssertMap(map, raw);
|
||||||
|
AssertMap(map, expectedMap);
|
||||||
|
AssertMap(raw, expectedMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,11 @@ public class TmxSerializerTests
|
||||||
public void TmxSerializerConstructor_ExternalTilesetResolverIsNull_ThrowsArgumentNullException()
|
public void TmxSerializerConstructor_ExternalTilesetResolverIsNull_ThrowsArgumentNullException()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
Func<string, Tileset> externalTilesetResolver = null!;
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver = null!;
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver = null!;
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
Action act = () => _ = new TmxSerializer(externalTilesetResolver);
|
Action act = () => _ = new TmxSerializer(externalTilesetResolver, externalTemplateResolver);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Throws<ArgumentNullException>(act);
|
Assert.Throws<ArgumentNullException>(act);
|
||||||
|
@ -19,10 +20,11 @@ public class TmxSerializerTests
|
||||||
public void TmxSerializerConstructor_ExternalTilesetResolverIsNotNull_DoesNotThrow()
|
public void TmxSerializerConstructor_ExternalTilesetResolverIsNotNull_DoesNotThrow()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
Func<string, Tileset> externalTilesetResolver = _ => new Tileset();
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver = (_, _) => new Tileset();
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver = (_, _) => new Template { Object = new RectangleObject { } };
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var tmxSerializer = new TmxSerializer(externalTilesetResolver);
|
var tmxSerializer = new TmxSerializer(externalTilesetResolver, externalTemplateResolver);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(tmxSerializer);
|
Assert.NotNull(tmxSerializer);
|
||||||
|
|
|
@ -15,8 +15,8 @@ public class ObjectLayer : BaseLayer
|
||||||
public uint Y { get; set; } = 0;
|
public uint Y { get; set; } = 0;
|
||||||
public uint? Width { get; set; }
|
public uint? Width { get; set; }
|
||||||
public uint? Height { get; set; }
|
public uint? Height { get; set; }
|
||||||
public required Color? Color { get; set; }
|
public Color? Color { get; set; }
|
||||||
public required DrawOrder DrawOrder { get; set; } = DrawOrder.TopDown;
|
public DrawOrder DrawOrder { get; set; } = DrawOrder.TopDown;
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
public required List<Object> Objects { get; set; }
|
public required List<Object> Objects { get; set; }
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace DotTiled;
|
||||||
public abstract class Object
|
public abstract class Object
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
public required uint ID { get; set; }
|
public uint? ID { get; set; }
|
||||||
public string Name { get; set; } = "";
|
public string Name { get; set; } = "";
|
||||||
public string Type { get; set; } = "";
|
public string Type { get; set; } = "";
|
||||||
public float X { get; set; } = 0f;
|
public float X { get; set; } = 0f;
|
||||||
|
|
8
DotTiled/Model/Template.cs
Normal file
8
DotTiled/Model/Template.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace DotTiled;
|
||||||
|
|
||||||
|
public class Template
|
||||||
|
{
|
||||||
|
// At most one of (if the template is a tile object)
|
||||||
|
public Tileset? Tileset { get; set; }
|
||||||
|
public required Object Object { get; set; }
|
||||||
|
}
|
|
@ -13,5 +13,14 @@ public partial class TmxSerializer
|
||||||
|
|
||||||
field = value;
|
field = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetAtMostOnceUsingCounter<T>(ref T? field, T value, string fieldName, ref int counter)
|
||||||
|
{
|
||||||
|
if (counter > 0)
|
||||||
|
throw new InvalidOperationException($"{fieldName} already set");
|
||||||
|
|
||||||
|
field = value;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,30 +71,63 @@ public partial class TmxSerializer
|
||||||
private Object ReadObject(XmlReader reader)
|
private Object ReadObject(XmlReader reader)
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var id = reader.GetRequiredAttributeParseable<uint>("id");
|
|
||||||
var name = reader.GetOptionalAttribute("name") ?? "";
|
|
||||||
var type = reader.GetOptionalAttribute("type") ?? "";
|
|
||||||
var x = reader.GetOptionalAttributeParseable<float>("x") ?? 0f;
|
|
||||||
var y = reader.GetOptionalAttributeParseable<float>("y") ?? 0f;
|
|
||||||
var width = reader.GetOptionalAttributeParseable<float>("width") ?? 0f;
|
|
||||||
var height = reader.GetOptionalAttributeParseable<float>("height") ?? 0f;
|
|
||||||
var rotation = reader.GetOptionalAttributeParseable<float>("rotation") ?? 0f;
|
|
||||||
var gid = reader.GetOptionalAttributeParseable<uint>("gid");
|
|
||||||
var visible = reader.GetOptionalAttributeParseable<bool>("visible") ?? true;
|
|
||||||
var template = reader.GetOptionalAttribute("template");
|
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<string, IProperty>? propertiesDefault = null;
|
||||||
|
|
||||||
|
// Perform template copy first
|
||||||
|
if (template is not null)
|
||||||
|
{
|
||||||
|
var resolvedTemplate = _externalTemplateResolver(this, template);
|
||||||
|
var templObj = resolvedTemplate.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;
|
||||||
|
gidDefault = templObj.GID;
|
||||||
|
visibleDefault = templObj.Visible;
|
||||||
|
propertiesDefault = templObj.Properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = reader.GetOptionalAttributeParseable<uint>("id") ?? idDefault;
|
||||||
|
var name = reader.GetOptionalAttribute("name") ?? nameDefault;
|
||||||
|
var type = reader.GetOptionalAttribute("type") ?? typeDefault;
|
||||||
|
var x = reader.GetOptionalAttributeParseable<float>("x") ?? xDefault;
|
||||||
|
var y = reader.GetOptionalAttributeParseable<float>("y") ?? yDefault;
|
||||||
|
var width = reader.GetOptionalAttributeParseable<float>("width") ?? widthDefault;
|
||||||
|
var height = reader.GetOptionalAttributeParseable<float>("height") ?? heightDefault;
|
||||||
|
var rotation = reader.GetOptionalAttributeParseable<float>("rotation") ?? rotationDefault;
|
||||||
|
var gid = reader.GetOptionalAttributeParseable<uint>("gid") ?? gidDefault;
|
||||||
|
var visible = reader.GetOptionalAttributeParseable<bool>("visible") ?? visibleDefault;
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
Object? obj = null;
|
Object? obj = null;
|
||||||
Dictionary<string, IProperty>? properties = null;
|
int propertiesCounter = 0;
|
||||||
|
Dictionary<string, IProperty>? properties = propertiesDefault;
|
||||||
|
|
||||||
reader.ProcessChildren("object", (r, elementName) => elementName switch
|
reader.ProcessChildren("object", (r, elementName) => elementName switch
|
||||||
{
|
{
|
||||||
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(r), "Properties"),
|
"properties" => () => Helpers.SetAtMostOnceUsingCounter(ref properties, MergeProperties(properties, ReadProperties(r)), "Properties", ref propertiesCounter),
|
||||||
"ellipse" => () => Helpers.SetAtMostOnce(ref obj, ReadEllipseObject(r, id), "Object marker"),
|
"ellipse" => () => Helpers.SetAtMostOnce(ref obj, ReadEllipseObject(r), "Object marker"),
|
||||||
"point" => () => Helpers.SetAtMostOnce(ref obj, ReadPointObject(r, id), "Object marker"),
|
"point" => () => Helpers.SetAtMostOnce(ref obj, ReadPointObject(r), "Object marker"),
|
||||||
"polygon" => () => Helpers.SetAtMostOnce(ref obj, ReadPolygonObject(r, id), "Object marker"),
|
"polygon" => () => Helpers.SetAtMostOnce(ref obj, ReadPolygonObject(r), "Object marker"),
|
||||||
"polyline" => () => Helpers.SetAtMostOnce(ref obj, ReadPolylineObject(r, id), "Object marker"),
|
"polyline" => () => Helpers.SetAtMostOnce(ref obj, ReadPolylineObject(r), "Object marker"),
|
||||||
"text" => () => Helpers.SetAtMostOnce(ref obj, ReadTextObject(r, id), "Object marker"),
|
"text" => () => Helpers.SetAtMostOnce(ref obj, ReadTextObject(r), "Object marker"),
|
||||||
_ => throw new Exception($"Unknown object marker '{elementName}'")
|
_ => throw new Exception($"Unknown object marker '{elementName}'")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -119,19 +152,51 @@ public partial class TmxSerializer
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private EllipseObject ReadEllipseObject(XmlReader reader, uint id)
|
private Dictionary<string, IProperty> MergeProperties(Dictionary<string, IProperty>? baseProperties, Dictionary<string, IProperty> overrideProperties)
|
||||||
{
|
{
|
||||||
reader.Skip();
|
if (baseProperties is null)
|
||||||
return new EllipseObject { ID = id };
|
return overrideProperties ?? new Dictionary<string, IProperty>();
|
||||||
|
|
||||||
|
if (overrideProperties is null)
|
||||||
|
return baseProperties;
|
||||||
|
|
||||||
|
var result = new Dictionary<string, IProperty>(baseProperties);
|
||||||
|
foreach (var (key, value) in overrideProperties)
|
||||||
|
{
|
||||||
|
if (!result.TryGetValue(key, out var baseProp))
|
||||||
|
{
|
||||||
|
result[key] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value is ClassProperty classProp)
|
||||||
|
{
|
||||||
|
((ClassProperty)baseProp).Properties = MergeProperties(((ClassProperty)baseProp).Properties, classProp.Properties);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PointObject ReadPointObject(XmlReader reader, uint id)
|
return result;
|
||||||
{
|
|
||||||
reader.Skip();
|
|
||||||
return new PointObject { ID = id };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PolygonObject ReadPolygonObject(XmlReader reader, uint id)
|
private EllipseObject ReadEllipseObject(XmlReader reader)
|
||||||
|
{
|
||||||
|
reader.Skip();
|
||||||
|
return new EllipseObject { };
|
||||||
|
}
|
||||||
|
|
||||||
|
private PointObject ReadPointObject(XmlReader reader)
|
||||||
|
{
|
||||||
|
reader.Skip();
|
||||||
|
return new PointObject { };
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolygonObject ReadPolygonObject(XmlReader reader)
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var points = reader.GetRequiredAttributeParseable<List<Vector2>>("points", s =>
|
var points = reader.GetRequiredAttributeParseable<List<Vector2>>("points", s =>
|
||||||
|
@ -146,10 +211,10 @@ public partial class TmxSerializer
|
||||||
});
|
});
|
||||||
|
|
||||||
reader.ReadStartElement("polygon");
|
reader.ReadStartElement("polygon");
|
||||||
return new PolygonObject { ID = id, Points = points };
|
return new PolygonObject { Points = points };
|
||||||
}
|
}
|
||||||
|
|
||||||
private PolylineObject ReadPolylineObject(XmlReader reader, uint id)
|
private PolylineObject ReadPolylineObject(XmlReader reader)
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var points = reader.GetRequiredAttributeParseable<List<Vector2>>("points", s =>
|
var points = reader.GetRequiredAttributeParseable<List<Vector2>>("points", s =>
|
||||||
|
@ -164,10 +229,10 @@ public partial class TmxSerializer
|
||||||
});
|
});
|
||||||
|
|
||||||
reader.ReadStartElement("polyline");
|
reader.ReadStartElement("polyline");
|
||||||
return new PolylineObject { ID = id, Points = points };
|
return new PolylineObject { Points = points };
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextObject ReadTextObject(XmlReader reader, uint id)
|
private TextObject ReadTextObject(XmlReader reader)
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var fontFamily = reader.GetOptionalAttribute("fontfamily") ?? "sans-serif";
|
var fontFamily = reader.GetOptionalAttribute("fontfamily") ?? "sans-serif";
|
||||||
|
@ -200,7 +265,6 @@ public partial class TmxSerializer
|
||||||
|
|
||||||
return new TextObject
|
return new TextObject
|
||||||
{
|
{
|
||||||
ID = id,
|
|
||||||
FontFamily = fontFamily,
|
FontFamily = fontFamily,
|
||||||
PixelSize = pixelSize,
|
PixelSize = pixelSize,
|
||||||
Wrap = wrap,
|
Wrap = wrap,
|
||||||
|
@ -215,4 +279,31 @@ public partial class TmxSerializer
|
||||||
Text = text
|
Text = text
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Template ReadTemplate(XmlReader reader)
|
||||||
|
{
|
||||||
|
// No attributes
|
||||||
|
|
||||||
|
// At most one of
|
||||||
|
Tileset? tileset = null;
|
||||||
|
|
||||||
|
// Should contain exactly one of
|
||||||
|
Object? obj = null;
|
||||||
|
|
||||||
|
reader.ProcessChildren("template", (r, elementName) => elementName switch
|
||||||
|
{
|
||||||
|
"tileset" => () => Helpers.SetAtMostOnce(ref tileset, ReadTileset(r), "Tileset"),
|
||||||
|
"object" => () => Helpers.SetAtMostOnce(ref obj, ReadObject(r), "Object"),
|
||||||
|
_ => r.Skip
|
||||||
|
});
|
||||||
|
|
||||||
|
if (obj is null)
|
||||||
|
throw new NotSupportedException("Template must contain exactly one object");
|
||||||
|
|
||||||
|
return new Template
|
||||||
|
{
|
||||||
|
Tileset = tileset,
|
||||||
|
Object = obj
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public partial class TmxSerializer
|
||||||
// Check if tileset is referring to external file
|
// Check if tileset is referring to external file
|
||||||
if (source is not null)
|
if (source is not null)
|
||||||
{
|
{
|
||||||
var resolvedTileset = _externalTilesetResolver(source);
|
var resolvedTileset = _externalTilesetResolver(this, source);
|
||||||
resolvedTileset.FirstGID = firstGID;
|
resolvedTileset.FirstGID = firstGID;
|
||||||
resolvedTileset.Source = null;
|
resolvedTileset.Source = null;
|
||||||
return resolvedTileset;
|
return resolvedTileset;
|
||||||
|
|
|
@ -6,11 +6,16 @@ namespace DotTiled;
|
||||||
|
|
||||||
public partial class TmxSerializer
|
public partial class TmxSerializer
|
||||||
{
|
{
|
||||||
private readonly Func<string, Tileset> _externalTilesetResolver;
|
private readonly Func<TmxSerializer, string, Tileset> _externalTilesetResolver;
|
||||||
|
private readonly Func<TmxSerializer, string, Template> _externalTemplateResolver;
|
||||||
|
|
||||||
public TmxSerializer(Func<string, Tileset> externalTilesetResolver)
|
public TmxSerializer(
|
||||||
|
Func<TmxSerializer, string, Tileset> externalTilesetResolver,
|
||||||
|
Func<TmxSerializer, string, Template> externalTemplateResolver
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_externalTilesetResolver = externalTilesetResolver ?? throw new ArgumentNullException(nameof(externalTilesetResolver));
|
_externalTilesetResolver = externalTilesetResolver ?? throw new ArgumentNullException(nameof(externalTilesetResolver));
|
||||||
|
_externalTemplateResolver = externalTemplateResolver ?? throw new ArgumentNullException(nameof(externalTemplateResolver));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map DeserializeMap(XmlReader reader)
|
public Map DeserializeMap(XmlReader reader)
|
||||||
|
@ -25,4 +30,16 @@ public partial class TmxSerializer
|
||||||
using var reader = XmlReader.Create(stringReader);
|
using var reader = XmlReader.Create(stringReader);
|
||||||
return DeserializeMap(reader);
|
return DeserializeMap(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tileset DeserializeTileset(XmlReader reader)
|
||||||
|
{
|
||||||
|
reader.ReadToFollowing("tileset");
|
||||||
|
return ReadTileset(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Template DeserializeTemplate(XmlReader reader)
|
||||||
|
{
|
||||||
|
reader.ReadToFollowing("template");
|
||||||
|
return ReadTemplate(reader);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue