mirror of
https://github.com/dcronqvist/DotTiled.git
synced 2025-02-05 17:02:49 +02:00
Merge pull request #22 from dcronqvist/optional
Use Optional<T> in model for explicit optionality for some properties
This commit is contained in:
commit
60e4adadb1
61 changed files with 1323 additions and 628 deletions
9
docs/docs/essentials/representation-model.md
Normal file
9
docs/docs/essentials/representation-model.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Representation model
|
||||||
|
|
||||||
|
Tiled map files contain various types of data, such as tilesets, layers, and object groups. The representation model is a way to represent this data in a structured way. By using the `.tmx` file format as inspiration, the representation model is a collection of classes which mimic the structure of a Tiled map file.
|
||||||
|
|
||||||
|
Certain properties throughout the representation model are marked as *optional* by being either wrapped in a <xref:DotTiled.Optional`1> or by having a set default value.
|
||||||
|
|
||||||
|
- Properties that make use of the [required](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/required) keyword must be present in the file, otherwise an error will be raised.
|
||||||
|
- Properties that have default values will use the default value if the property is not present in the file, and are not marked as required or optional since you must not provide a value for them.
|
||||||
|
- Properties that are wrapped in <xref:DotTiled.Optional`1> may or may not be present in the file, and have no default value.
|
|
@ -4,4 +4,5 @@
|
||||||
|
|
||||||
- name: Essentials
|
- name: Essentials
|
||||||
- href: essentials/loading-maps.md
|
- href: essentials/loading-maps.md
|
||||||
|
- href: essentials/representation-model.md
|
||||||
- href: essentials/custom-properties.md
|
- href: essentials/custom-properties.md
|
|
@ -2,7 +2,7 @@ namespace DotTiled.Tests;
|
||||||
|
|
||||||
public static partial class DotTiledAssert
|
public static partial class DotTiledAssert
|
||||||
{
|
{
|
||||||
internal static void AssertData(Data? expected, Data? actual)
|
internal static void AssertData(Data expected, Data actual)
|
||||||
{
|
{
|
||||||
if (expected is null)
|
if (expected is null)
|
||||||
{
|
{
|
||||||
|
@ -18,14 +18,7 @@ public static partial class DotTiledAssert
|
||||||
// Data
|
// Data
|
||||||
AssertEqual(expected.GlobalTileIDs, actual.GlobalTileIDs, nameof(Data.GlobalTileIDs));
|
AssertEqual(expected.GlobalTileIDs, actual.GlobalTileIDs, nameof(Data.GlobalTileIDs));
|
||||||
AssertEqual(expected.FlippingFlags, actual.FlippingFlags, nameof(Data.FlippingFlags));
|
AssertEqual(expected.FlippingFlags, actual.FlippingFlags, nameof(Data.FlippingFlags));
|
||||||
|
AssertOptionalsEqual(expected.Chunks, actual.Chunks, nameof(Data.Chunks), (a, b) => AssertListOrdered(a, b, nameof(Chunk), AssertChunk));
|
||||||
if (expected.Chunks is not null)
|
|
||||||
{
|
|
||||||
Assert.NotNull(actual.Chunks);
|
|
||||||
AssertEqual(expected.Chunks.Length, actual.Chunks.Length, "Chunks.Length");
|
|
||||||
for (var i = 0; i < expected.Chunks.Length; i++)
|
|
||||||
AssertChunk(expected.Chunks[i], actual.Chunks[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AssertChunk(Chunk expected, Chunk actual)
|
private static void AssertChunk(Chunk expected, Chunk actual)
|
||||||
|
|
|
@ -2,7 +2,7 @@ namespace DotTiled.Tests;
|
||||||
|
|
||||||
public static partial class DotTiledAssert
|
public static partial class DotTiledAssert
|
||||||
{
|
{
|
||||||
internal static void AssertImage(Image? expected, Image? actual)
|
internal static void AssertImage(Image expected, Image actual)
|
||||||
{
|
{
|
||||||
if (expected is null)
|
if (expected is null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@ namespace DotTiled.Tests;
|
||||||
|
|
||||||
public static partial class DotTiledAssert
|
public static partial class DotTiledAssert
|
||||||
{
|
{
|
||||||
internal static void AssertLayer(BaseLayer? expected, BaseLayer? actual)
|
internal static void AssertLayer(BaseLayer expected, BaseLayer actual)
|
||||||
{
|
{
|
||||||
if (expected is null)
|
if (expected is null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,68 @@ namespace DotTiled.Tests;
|
||||||
|
|
||||||
public static partial class DotTiledAssert
|
public static partial class DotTiledAssert
|
||||||
{
|
{
|
||||||
|
private static void AssertListOrdered<T>(IList<T> expected, IList<T> actual, string nameof, Action<T, T> assertEqual = null)
|
||||||
|
{
|
||||||
|
if (expected is null)
|
||||||
|
{
|
||||||
|
Assert.Null(actual);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.NotNull(actual);
|
||||||
|
AssertEqual(expected.Count, actual.Count, $"{nameof}.Count");
|
||||||
|
|
||||||
|
for (var i = 0; i < expected.Count; i++)
|
||||||
|
{
|
||||||
|
if (assertEqual is not null)
|
||||||
|
{
|
||||||
|
assertEqual(expected[i], actual[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AssertEqual(expected[i], actual[i], $"{nameof}[{i}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AssertOptionalsEqual<T>(
|
||||||
|
Optional<T> expected,
|
||||||
|
Optional<T> actual,
|
||||||
|
string nameof,
|
||||||
|
Action<T, T> assertEqual)
|
||||||
|
{
|
||||||
|
if (expected is null)
|
||||||
|
{
|
||||||
|
Assert.Null(actual);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expected.HasValue)
|
||||||
|
{
|
||||||
|
Assert.True(actual.HasValue, $"Expected {nameof} to have a value");
|
||||||
|
assertEqual(expected.Value, actual.Value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.False(actual.HasValue, $"Expected {nameof} to not have a value");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AssertEqual<T>(Optional<T> expected, Optional<T> actual, string nameof)
|
||||||
|
{
|
||||||
|
if (expected is null)
|
||||||
|
{
|
||||||
|
Assert.Null(actual);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expected.HasValue)
|
||||||
|
{
|
||||||
|
Assert.True(actual.HasValue, $"Expected {nameof} to have a value");
|
||||||
|
AssertEqual(expected.Value, actual.Value, nameof);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.False(actual.HasValue, $"Expected {nameof} to not have a value");
|
||||||
|
}
|
||||||
|
|
||||||
private static void AssertEqual<T>(T expected, T actual, string nameof)
|
private static void AssertEqual<T>(T expected, T actual, string nameof)
|
||||||
{
|
{
|
||||||
if (expected == null)
|
if (expected == null)
|
||||||
|
|
|
@ -2,7 +2,7 @@ namespace DotTiled.Tests;
|
||||||
|
|
||||||
public static partial class DotTiledAssert
|
public static partial class DotTiledAssert
|
||||||
{
|
{
|
||||||
internal static void AssertProperties(IList<IProperty>? expected, IList<IProperty>? actual)
|
internal static void AssertProperties(IList<IProperty> expected, IList<IProperty> actual)
|
||||||
{
|
{
|
||||||
if (expected is null)
|
if (expected is null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,6 @@ public static partial class DotTiledAssert
|
||||||
{
|
{
|
||||||
internal static void AssertTileset(Tileset expected, Tileset actual)
|
internal static void AssertTileset(Tileset expected, Tileset actual)
|
||||||
{
|
{
|
||||||
// Attributes
|
|
||||||
AssertEqual(expected.Version, actual.Version, nameof(Tileset.Version));
|
AssertEqual(expected.Version, actual.Version, nameof(Tileset.Version));
|
||||||
AssertEqual(expected.TiledVersion, actual.TiledVersion, nameof(Tileset.TiledVersion));
|
AssertEqual(expected.TiledVersion, actual.TiledVersion, nameof(Tileset.TiledVersion));
|
||||||
AssertEqual(expected.FirstGID, actual.FirstGID, nameof(Tileset.FirstGID));
|
AssertEqual(expected.FirstGID, actual.FirstGID, nameof(Tileset.FirstGID));
|
||||||
|
@ -21,29 +20,16 @@ public static partial class DotTiledAssert
|
||||||
AssertEqual(expected.RenderSize, actual.RenderSize, nameof(Tileset.RenderSize));
|
AssertEqual(expected.RenderSize, actual.RenderSize, nameof(Tileset.RenderSize));
|
||||||
AssertEqual(expected.FillMode, actual.FillMode, nameof(Tileset.FillMode));
|
AssertEqual(expected.FillMode, actual.FillMode, nameof(Tileset.FillMode));
|
||||||
|
|
||||||
// At most one of
|
AssertOptionalsEqual(expected.Image, actual.Image, nameof(Tileset.Image), AssertImage);
|
||||||
AssertImage(expected.Image, actual.Image);
|
AssertOptionalsEqual(expected.TileOffset, actual.TileOffset, nameof(Tileset.TileOffset), AssertTileOffset);
|
||||||
AssertTileOffset(expected.TileOffset, actual.TileOffset);
|
AssertOptionalsEqual(expected.Grid, actual.Grid, nameof(Tileset.Grid), AssertGrid);
|
||||||
AssertGrid(expected.Grid, actual.Grid);
|
|
||||||
AssertProperties(expected.Properties, actual.Properties);
|
AssertProperties(expected.Properties, actual.Properties);
|
||||||
// TODO: AssertTerrainTypes(actual.TerrainTypes, expected.TerrainTypes);
|
AssertListOrdered(expected.Wangsets, actual.Wangsets, nameof(Tileset.Wangsets), AssertWangset);
|
||||||
if (expected.Wangsets is not null)
|
AssertOptionalsEqual(expected.Transformations, actual.Transformations, nameof(Tileset.Transformations), AssertTransformations);
|
||||||
{
|
AssertListOrdered(expected.Tiles, actual.Tiles, nameof(Tileset.Tiles), AssertTile);
|
||||||
Assert.NotNull(actual.Wangsets);
|
|
||||||
AssertEqual(expected.Wangsets.Count, actual.Wangsets.Count, "Wangsets.Count");
|
|
||||||
for (var i = 0; i < expected.Wangsets.Count; i++)
|
|
||||||
AssertWangset(expected.Wangsets[i], actual.Wangsets[i]);
|
|
||||||
}
|
|
||||||
AssertTransformations(expected.Transformations, actual.Transformations);
|
|
||||||
|
|
||||||
// Any number of
|
|
||||||
Assert.NotNull(actual.Tiles);
|
|
||||||
AssertEqual(expected.Tiles.Count, actual.Tiles.Count, "Tiles.Count");
|
|
||||||
for (var i = 0; i < expected.Tiles.Count; i++)
|
|
||||||
AssertTile(expected.Tiles[i], actual.Tiles[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AssertTileOffset(TileOffset? expected, TileOffset? actual)
|
private static void AssertTileOffset(TileOffset expected, TileOffset actual)
|
||||||
{
|
{
|
||||||
if (expected is null)
|
if (expected is null)
|
||||||
{
|
{
|
||||||
|
@ -57,7 +43,7 @@ public static partial class DotTiledAssert
|
||||||
AssertEqual(expected.Y, actual.Y, nameof(TileOffset.Y));
|
AssertEqual(expected.Y, actual.Y, nameof(TileOffset.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AssertGrid(Grid? expected, Grid? actual)
|
private static void AssertGrid(Grid expected, Grid actual)
|
||||||
{
|
{
|
||||||
if (expected is null)
|
if (expected is null)
|
||||||
{
|
{
|
||||||
|
@ -74,27 +60,17 @@ public static partial class DotTiledAssert
|
||||||
|
|
||||||
private static void AssertWangset(Wangset expected, Wangset actual)
|
private static void AssertWangset(Wangset expected, Wangset actual)
|
||||||
{
|
{
|
||||||
// Attributes
|
|
||||||
AssertEqual(expected.Name, actual.Name, nameof(Wangset.Name));
|
AssertEqual(expected.Name, actual.Name, nameof(Wangset.Name));
|
||||||
AssertEqual(expected.Class, actual.Class, nameof(Wangset.Class));
|
AssertEqual(expected.Class, actual.Class, nameof(Wangset.Class));
|
||||||
AssertEqual(expected.Tile, actual.Tile, nameof(Wangset.Tile));
|
AssertEqual(expected.Tile, actual.Tile, nameof(Wangset.Tile));
|
||||||
|
|
||||||
// At most one of
|
|
||||||
AssertProperties(expected.Properties, actual.Properties);
|
AssertProperties(expected.Properties, actual.Properties);
|
||||||
if (expected.WangColors is not null)
|
AssertListOrdered(expected.WangColors, actual.WangColors, nameof(Wangset.WangColors), AssertWangColor);
|
||||||
{
|
AssertListOrdered(expected.WangTiles, actual.WangTiles, nameof(Wangset.WangTiles), AssertWangTile);
|
||||||
Assert.NotNull(actual.WangColors);
|
|
||||||
AssertEqual(expected.WangColors.Count, actual.WangColors.Count, "WangColors.Count");
|
|
||||||
for (var i = 0; i < expected.WangColors.Count; i++)
|
|
||||||
AssertWangColor(expected.WangColors[i], actual.WangColors[i]);
|
|
||||||
}
|
|
||||||
for (var i = 0; i < expected.WangTiles.Count; i++)
|
|
||||||
AssertWangTile(expected.WangTiles[i], actual.WangTiles[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AssertWangColor(WangColor expected, WangColor actual)
|
private static void AssertWangColor(WangColor expected, WangColor actual)
|
||||||
{
|
{
|
||||||
// Attributes
|
|
||||||
AssertEqual(expected.Name, actual.Name, nameof(WangColor.Name));
|
AssertEqual(expected.Name, actual.Name, nameof(WangColor.Name));
|
||||||
AssertEqual(expected.Class, actual.Class, nameof(WangColor.Class));
|
AssertEqual(expected.Class, actual.Class, nameof(WangColor.Class));
|
||||||
AssertEqual(expected.Color, actual.Color, nameof(WangColor.Color));
|
AssertEqual(expected.Color, actual.Color, nameof(WangColor.Color));
|
||||||
|
@ -106,12 +82,11 @@ public static partial class DotTiledAssert
|
||||||
|
|
||||||
private static void AssertWangTile(WangTile expected, WangTile actual)
|
private static void AssertWangTile(WangTile expected, WangTile actual)
|
||||||
{
|
{
|
||||||
// Attributes
|
|
||||||
AssertEqual(expected.TileID, actual.TileID, nameof(WangTile.TileID));
|
AssertEqual(expected.TileID, actual.TileID, nameof(WangTile.TileID));
|
||||||
AssertEqual(expected.WangID, actual.WangID, nameof(WangTile.WangID));
|
AssertEqual(expected.WangID, actual.WangID, nameof(WangTile.WangID));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AssertTransformations(Transformations? expected, Transformations? actual)
|
private static void AssertTransformations(Transformations expected, Transformations actual)
|
||||||
{
|
{
|
||||||
if (expected is null)
|
if (expected is null)
|
||||||
{
|
{
|
||||||
|
@ -119,7 +94,6 @@ public static partial class DotTiledAssert
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attributes
|
|
||||||
Assert.NotNull(actual);
|
Assert.NotNull(actual);
|
||||||
AssertEqual(expected.HFlip, actual.HFlip, nameof(Transformations.HFlip));
|
AssertEqual(expected.HFlip, actual.HFlip, nameof(Transformations.HFlip));
|
||||||
AssertEqual(expected.VFlip, actual.VFlip, nameof(Transformations.VFlip));
|
AssertEqual(expected.VFlip, actual.VFlip, nameof(Transformations.VFlip));
|
||||||
|
@ -129,7 +103,6 @@ public static partial class DotTiledAssert
|
||||||
|
|
||||||
private static void AssertTile(Tile expected, Tile actual)
|
private static void AssertTile(Tile expected, Tile actual)
|
||||||
{
|
{
|
||||||
// Attributes
|
|
||||||
AssertEqual(expected.ID, actual.ID, nameof(Tile.ID));
|
AssertEqual(expected.ID, actual.ID, nameof(Tile.ID));
|
||||||
AssertEqual(expected.Type, actual.Type, nameof(Tile.Type));
|
AssertEqual(expected.Type, actual.Type, nameof(Tile.Type));
|
||||||
AssertEqual(expected.Probability, actual.Probability, nameof(Tile.Probability));
|
AssertEqual(expected.Probability, actual.Probability, nameof(Tile.Probability));
|
||||||
|
@ -138,22 +111,14 @@ public static partial class DotTiledAssert
|
||||||
AssertEqual(expected.Width, actual.Width, nameof(Tile.Width));
|
AssertEqual(expected.Width, actual.Width, nameof(Tile.Width));
|
||||||
AssertEqual(expected.Height, actual.Height, nameof(Tile.Height));
|
AssertEqual(expected.Height, actual.Height, nameof(Tile.Height));
|
||||||
|
|
||||||
// Elements
|
|
||||||
AssertProperties(expected.Properties, actual.Properties);
|
AssertProperties(expected.Properties, actual.Properties);
|
||||||
AssertImage(expected.Image, actual.Image);
|
AssertOptionalsEqual(expected.Image, actual.Image, nameof(Tile.Image), AssertImage);
|
||||||
AssertLayer((BaseLayer?)expected.ObjectLayer, (BaseLayer?)actual.ObjectLayer);
|
AssertOptionalsEqual(expected.ObjectLayer, actual.ObjectLayer, nameof(Tile.ObjectLayer), (a, b) => AssertLayer((BaseLayer)a, (BaseLayer)b));
|
||||||
if (expected.Animation is not null)
|
AssertListOrdered(expected.Animation, actual.Animation, nameof(Tile.Animation), AssertFrame);
|
||||||
{
|
|
||||||
Assert.NotNull(actual.Animation);
|
|
||||||
AssertEqual(expected.Animation.Count, actual.Animation.Count, "Animation.Count");
|
|
||||||
for (var i = 0; i < expected.Animation.Count; i++)
|
|
||||||
AssertFrame(expected.Animation[i], actual.Animation[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AssertFrame(Frame expected, Frame actual)
|
private static void AssertFrame(Frame expected, Frame actual)
|
||||||
{
|
{
|
||||||
// Attributes
|
|
||||||
AssertEqual(expected.TileID, actual.TileID, nameof(Frame.TileID));
|
AssertEqual(expected.TileID, actual.TileID, nameof(Frame.TileID));
|
||||||
AssertEqual(expected.Duration, actual.Duration, nameof(Frame.Duration));
|
AssertEqual(expected.Duration, actual.Duration, nameof(Frame.Duration));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<IsTestProject>true</IsTestProject>
|
<IsTestProject>true</IsTestProject>
|
||||||
|
|
520
src/DotTiled.Tests/OptionalTests.cs
Normal file
520
src/DotTiled.Tests/OptionalTests.cs
Normal file
|
@ -0,0 +1,520 @@
|
||||||
|
namespace DotTiled.Tests;
|
||||||
|
|
||||||
|
// public class OptionalTests
|
||||||
|
// {
|
||||||
|
// [Fact]
|
||||||
|
// public void HasValue_WhenValueIsSet_ReturnsTrue()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act & Assert
|
||||||
|
// Assert.True(optional.HasValue);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void HasValue_WhenValueIsNotSet_ReturnsFalse()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>();
|
||||||
|
|
||||||
|
// // Act & Assert
|
||||||
|
// Assert.False(optional.HasValue);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void Value_WhenValueIsSet_ReturnsValue()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var value = optional.Value;
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.Equal(42, value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void Value_WhenValueIsNotSet_ThrowsInvalidOperationException()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>();
|
||||||
|
|
||||||
|
// // Act & Assert
|
||||||
|
// _ = Assert.Throws<InvalidOperationException>(() => optional.Value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void ImplicitConversionFromValue_CreatesOptionalWithValue()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// Optional<int> optional = 42;
|
||||||
|
|
||||||
|
// // Act & Assert
|
||||||
|
// Assert.True(optional.HasValue);
|
||||||
|
// Assert.Equal(42, optional.Value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void ImplicitConversionToValue_ReturnsValue()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// int value = optional;
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.Equal(42, value);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void ToString_WhenValueIsSet_ReturnsValueToString()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional.ToString();
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.Equal("42", result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void ToString_WhenValueIsNotSet_ReturnsEmpty()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>();
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional.ToString();
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.Equal("Empty", result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void Equals_WithObject_ReturnsTrueWhenValueIsEqual()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional.Equals(42);
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.True(result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void Equals_WithObject_ReturnsFalseWhenValueIsNotEqual()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional.Equals(43);
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.False(result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void Equals_WithObject_ReturnsFalseWhenValueIsNotSet()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>();
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional.Equals(42);
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.False(result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void Equals_WithOptional_ReturnsTrueWhenValueIsEqual()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional1 = new Optional<int>(42);
|
||||||
|
// var optional2 = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.True(result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void Equals_WithOptional_ReturnsFalseWhenValueIsNotEqual()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional1 = new Optional<int>(42);
|
||||||
|
// var optional2 = new Optional<int>(43);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.False(result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void Equals_WithOptional_ReturnsFalseWhenValueIsNotSet()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional1 = new Optional<int>();
|
||||||
|
// var optional2 = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.False(result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void GetHashCode_WhenValueIsSet_ReturnsValueHashCode()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>(42);
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional.GetHashCode();
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.Equal(42.GetHashCode(), result);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// [Fact]
|
||||||
|
// public void GetHashCode_WhenValueIsNotSet_ReturnsZero()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var optional = new Optional<int>();
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var result = optional.GetHashCode();
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.Equal(0, result);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
public class OptionalTests
|
||||||
|
{
|
||||||
|
// Constructor Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_WithNonNullValue_ShouldSetHasValueToTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string expectedValue = "test";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var optional = new Optional<string>(expectedValue);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(optional.HasValue);
|
||||||
|
Assert.Equal(expectedValue, optional.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_WithNullValue_ShouldSetHasValueToTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string expectedValue = null;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var optional = new Optional<string>(expectedValue);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(optional.HasValue);
|
||||||
|
Assert.Null(optional.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DefaultConstructor_ShouldSetHasValueToFalse()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var optional = new Optional<string>();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(optional.HasValue);
|
||||||
|
_ = Assert.Throws<InvalidOperationException>(() => optional.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implicit Conversion Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ImplicitConversion_FromValueToOptional_ShouldSetHasValueToTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int expectedValue = 5;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Optional<int> optional = expectedValue;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(optional.HasValue);
|
||||||
|
Assert.Equal(expectedValue, optional.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ImplicitConversion_FromOptionalToValue_ShouldReturnValue_WhenHasValueIsTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int expectedValue = 10;
|
||||||
|
var optional = new Optional<int>(expectedValue);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int value = optional;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ImplicitConversion_FromOptionalToValue_ShouldThrowException_WhenHasValueIsFalse()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional = new Optional<int>();
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
_ = Assert.Throws<InvalidOperationException>(() => { int value = optional; });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToString Method Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToString_WithValue_ShouldReturnValueToString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int expectedValue = 42;
|
||||||
|
var optional = new Optional<int>(expectedValue);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
string result = optional.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
#pragma warning disable CA1305 // Specify IFormatProvider
|
||||||
|
Assert.Equal(expectedValue.ToString(), result);
|
||||||
|
#pragma warning restore CA1305 // Specify IFormatProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ToString_WithoutValue_ShouldReturnEmpty()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var optional = new Optional<int>();
|
||||||
|
string result = optional.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("Empty", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equality Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equals_WithSameValue_ShouldReturnTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional1 = new Optional<int>(10);
|
||||||
|
var optional2 = new Optional<int>(10);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
bool areEqual = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(areEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equals_WithDifferentValues_ShouldReturnFalse()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional1 = new Optional<int>(10);
|
||||||
|
var optional2 = new Optional<int>(20);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
bool areEqual = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(areEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equals_WithNull_ShouldReturnFalse()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional = new Optional<string>("test");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
bool areEqual = optional.Equals(null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(areEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equals_WithEmptyOptional_ShouldReturnTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional1 = new Optional<string>();
|
||||||
|
var optional2 = new Optional<string>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
bool areEqual = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(areEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equals_WithSameReferenceTypeValue_ShouldReturnTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var value = new object();
|
||||||
|
var optional1 = new Optional<object>(value);
|
||||||
|
var optional2 = new Optional<object>(value);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
bool areEqual = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(areEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Equals_WithDifferentReferenceTypeValues_ShouldReturnFalse()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional1 = new Optional<object>(new object());
|
||||||
|
var optional2 = new Optional<object>(new object());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
bool areEqual = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(areEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHashCode Method Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetHashCode_WithValue_ShouldReturnValueHashCode()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int value = 42;
|
||||||
|
var optional = new Optional<int>(value);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int hashCode = optional.GetHashCode();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(value.GetHashCode(), hashCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetHashCode_WithoutValue_ShouldReturnZero()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var optional = new Optional<int>();
|
||||||
|
int hashCode = optional.GetHashCode();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(0, hashCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exception Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Value_WhenHasValueIsFalse_ShouldThrowInvalidOperationException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional = new Optional<string>();
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
_ = Assert.Throws<InvalidOperationException>(() => optional.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ImplicitConversion_WhenHasValueIsFalse_ShouldThrowInvalidOperationException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional = new Optional<int>();
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
_ = Assert.Throws<InvalidOperationException>(() => { int value = optional; });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edge Cases
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EmptyOptionalEquality_ShouldReturnTrue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var optional1 = new Optional<int>();
|
||||||
|
var optional2 = new Optional<int>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
bool areEqual = optional1.Equals(optional2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(areEqual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special Scenarios
|
||||||
|
|
||||||
|
public struct CustomStruct
|
||||||
|
{
|
||||||
|
public int X { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OptionalWithCustomStruct_ShouldBehaveCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var structValue = new CustomStruct { X = 10 };
|
||||||
|
var optional = new Optional<CustomStruct>(structValue);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
CustomStruct value = optional.Value;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(optional.HasValue);
|
||||||
|
Assert.Equal(structValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OptionalWithNullableInt_ShouldBehaveCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int? nullableValue = 5;
|
||||||
|
var optional = new Optional<int?>(nullableValue);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int? value = optional.Value;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(optional.HasValue);
|
||||||
|
Assert.Equal(nullableValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OptionalWithNullNullableInt_ShouldBehaveCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
int? nullableValue = null;
|
||||||
|
var optional = new Optional<int?>(nullableValue);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
int? value = optional.Value;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(optional.HasValue);
|
||||||
|
Assert.Null(value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,9 +11,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 32,
|
TileHeight = 32,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -33,22 +30,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
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,
|
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 = 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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 32,
|
TileHeight = 32,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -97,22 +94,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
GlobalTileIDs = [
|
|
||||||
0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0,
|
||||||
1, 0, 0, 0, 0,
|
1, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0,
|
||||||
0, 2, 0, 0, 0
|
0, 2, 0, 0, 0
|
||||||
],
|
]),
|
||||||
FlippingFlags = [
|
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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 24,
|
TileWidth = 24,
|
||||||
TileHeight = 24,
|
TileHeight = 24,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -56,7 +53,59 @@ public partial class TestData
|
||||||
Source = "tileset.png",
|
Source = "tileset.png",
|
||||||
Width = 256,
|
Width = 256,
|
||||||
Height = 96,
|
Height = 96,
|
||||||
}
|
},
|
||||||
|
Wangsets = [
|
||||||
|
new Wangset
|
||||||
|
{
|
||||||
|
Name = "test-terrain",
|
||||||
|
Tile = -1,
|
||||||
|
WangColors = [
|
||||||
|
new WangColor
|
||||||
|
{
|
||||||
|
Name = "Water",
|
||||||
|
Color = Color.Parse("#ff0000", CultureInfo.InvariantCulture),
|
||||||
|
Tile = 0,
|
||||||
|
Probability = 1
|
||||||
|
},
|
||||||
|
new WangColor
|
||||||
|
{
|
||||||
|
Name = "Grass",
|
||||||
|
Color = Color.Parse("#00ff00", CultureInfo.InvariantCulture),
|
||||||
|
Tile = -1,
|
||||||
|
Probability = 1
|
||||||
|
},
|
||||||
|
new WangColor
|
||||||
|
{
|
||||||
|
Name = "Stone",
|
||||||
|
Color = Color.Parse("#0000ff", CultureInfo.InvariantCulture),
|
||||||
|
Tile = 29,
|
||||||
|
Probability = 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
WangTiles = [
|
||||||
|
new WangTile
|
||||||
|
{
|
||||||
|
TileID = 0,
|
||||||
|
WangID = [1,1,0,0,0,1,1,1]
|
||||||
|
},
|
||||||
|
new WangTile
|
||||||
|
{
|
||||||
|
TileID = 1,
|
||||||
|
WangID = [1,1,1,1,0,0,0,1]
|
||||||
|
},
|
||||||
|
new WangTile
|
||||||
|
{
|
||||||
|
TileID = 10,
|
||||||
|
WangID = [0,0,0,1,1,1,1,1]
|
||||||
|
},
|
||||||
|
new WangTile
|
||||||
|
{
|
||||||
|
TileID = 11,
|
||||||
|
WangID = [0,1,1,1,1,1,0,0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
Layers = [
|
Layers = [
|
||||||
|
@ -69,22 +118,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
GlobalTileIDs = [
|
|
||||||
2, 2, 12, 11, 0,
|
2, 2, 12, 11, 0,
|
||||||
1, 12, 1, 11, 0,
|
1, 12, 1, 11, 0,
|
||||||
2, 1, 0, 1, 0,
|
2, 1, 0, 1, 0,
|
||||||
12, 11, 12, 2, 0,
|
12, 11, 12, 2, 0,
|
||||||
0, 0, 0, 0, 0
|
0, 0, 0, 0, 0
|
||||||
],
|
]),
|
||||||
FlippingFlags = [
|
FlippingFlags = new Optional<FlippingFlags[]>([
|
||||||
FlippingFlags.FlippedHorizontally, FlippingFlags.None, FlippingFlags.FlippedHorizontally, FlippingFlags.FlippedHorizontally, FlippingFlags.None,
|
FlippingFlags.FlippedHorizontally, FlippingFlags.None, FlippingFlags.FlippedHorizontally, FlippingFlags.FlippedHorizontally, FlippingFlags.None,
|
||||||
FlippingFlags.FlippedVertically, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically | FlippingFlags.FlippedHorizontally, FlippingFlags.None,
|
FlippingFlags.FlippedVertically, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically | FlippingFlags.FlippedHorizontally, FlippingFlags.None,
|
||||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically | FlippingFlags.FlippedHorizontally, FlippingFlags.None,
|
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically | FlippingFlags.FlippedHorizontally, FlippingFlags.None,
|
||||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedHorizontally, FlippingFlags.None,
|
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedHorizontally, FlippingFlags.None,
|
||||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None
|
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 16,
|
TileHeight = 16,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -35,22 +32,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
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,
|
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 = 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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 32,
|
TileHeight = 32,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -35,22 +32,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
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,
|
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 = 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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 32,
|
TileHeight = 32,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -35,22 +32,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
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,
|
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 = 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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 32,
|
TileHeight = 32,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -28,6 +25,8 @@ public partial class TestData
|
||||||
Tilesets = [
|
Tilesets = [
|
||||||
new Tileset
|
new Tileset
|
||||||
{
|
{
|
||||||
|
Version = "1.10",
|
||||||
|
TiledVersion = "1.11.0",
|
||||||
FirstGID = 1,
|
FirstGID = 1,
|
||||||
Name = "tileset",
|
Name = "tileset",
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
|
@ -53,22 +52,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
GlobalTileIDs = [
|
|
||||||
1, 1, 0, 0, 7,
|
1, 1, 0, 0, 7,
|
||||||
1, 1, 0, 0, 7,
|
1, 1, 0, 0, 7,
|
||||||
0, 0, 0, 0, 7,
|
0, 0, 0, 0, 7,
|
||||||
9, 10, 0, 0, 7,
|
9, 10, 0, 0, 7,
|
||||||
17, 18, 0, 0, 0
|
17, 18, 0, 0, 0
|
||||||
],
|
]),
|
||||||
FlippingFlags = [
|
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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 32,
|
TileHeight = 32,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -56,22 +53,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
GlobalTileIDs = [
|
|
||||||
1, 1, 0, 0, 7,
|
1, 1, 0, 0, 7,
|
||||||
1, 1, 0, 0, 7,
|
1, 1, 0, 0, 7,
|
||||||
0, 0, 1, 0, 7,
|
0, 0, 1, 0, 7,
|
||||||
0, 0, 0, 1, 7,
|
0, 0, 0, 1, 7,
|
||||||
21, 21, 21, 21, 1
|
21, 21, 21, 21, 1
|
||||||
],
|
]),
|
||||||
FlippingFlags = [
|
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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 32,
|
TileHeight = 32,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -56,22 +53,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
GlobalTileIDs = [
|
|
||||||
1, 1, 0, 0, 7,
|
1, 1, 0, 0, 7,
|
||||||
1, 1, 0, 0, 7,
|
1, 1, 0, 0, 7,
|
||||||
0, 0, 1, 0, 7,
|
0, 0, 1, 0, 7,
|
||||||
0, 0, 0, 1, 7,
|
0, 0, 0, 1, 7,
|
||||||
21, 21, 21, 21, 1
|
21, 21, 21, 21, 1
|
||||||
],
|
]),
|
||||||
FlippingFlags = [
|
FlippingFlags = new Optional<FlippingFlags[]>([
|
||||||
FlippingFlags.None, FlippingFlags.FlippedDiagonally | FlippingFlags.FlippedHorizontally, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically,
|
FlippingFlags.None, FlippingFlags.FlippedDiagonally | FlippingFlags.FlippedHorizontally, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically,
|
||||||
FlippingFlags.FlippedDiagonally | FlippingFlags.FlippedVertically, FlippingFlags.FlippedVertically | FlippingFlags.FlippedHorizontally, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically,
|
FlippingFlags.FlippedDiagonally | FlippingFlags.FlippedVertically, FlippingFlags.FlippedVertically | FlippingFlags.FlippedHorizontally, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically,
|
||||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically,
|
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically,
|
||||||
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically,
|
FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.FlippedVertically,
|
||||||
FlippingFlags.FlippedHorizontally, FlippingFlags.FlippedHorizontally, FlippingFlags.FlippedHorizontally, FlippingFlags.FlippedHorizontally, FlippingFlags.None
|
FlippingFlags.FlippedHorizontally, FlippingFlags.FlippedHorizontally, FlippingFlags.FlippedHorizontally, FlippingFlags.FlippedHorizontally, FlippingFlags.None
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,9 +13,6 @@ public partial class TestData
|
||||||
TileWidth = 32,
|
TileWidth = 32,
|
||||||
TileHeight = 32,
|
TileHeight = 32,
|
||||||
Infinite = false,
|
Infinite = false,
|
||||||
HexSideLength = null,
|
|
||||||
StaggerAxis = null,
|
|
||||||
StaggerIndex = null,
|
|
||||||
ParallaxOriginX = 0,
|
ParallaxOriginX = 0,
|
||||||
ParallaxOriginY = 0,
|
ParallaxOriginY = 0,
|
||||||
RenderOrder = RenderOrder.RightDown,
|
RenderOrder = RenderOrder.RightDown,
|
||||||
|
@ -124,22 +121,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
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,
|
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 = 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,
|
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
|
new TileLayer
|
||||||
|
@ -151,22 +146,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
GlobalTileIDs = [
|
|
||||||
0, 15, 15, 0, 0,
|
0, 15, 15, 0, 0,
|
||||||
0, 15, 15, 0, 0,
|
0, 15, 15, 0, 0,
|
||||||
0, 15, 15, 15, 0,
|
0, 15, 15, 15, 0,
|
||||||
15, 15, 15, 0, 0,
|
15, 15, 15, 0, 0,
|
||||||
0, 0, 0, 0, 0
|
0, 0, 0, 0, 0
|
||||||
],
|
]),
|
||||||
FlippingFlags = [
|
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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -193,22 +186,20 @@ public partial class TestData
|
||||||
Data = new Data
|
Data = new Data
|
||||||
{
|
{
|
||||||
Encoding = DataEncoding.Csv,
|
Encoding = DataEncoding.Csv,
|
||||||
Chunks = null,
|
GlobalTileIDs = new Optional<uint[]>([
|
||||||
Compression = null,
|
|
||||||
GlobalTileIDs = [
|
|
||||||
1, 1, 1, 1, 1,
|
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,
|
||||||
0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0
|
0, 0, 0, 0, 0
|
||||||
],
|
]),
|
||||||
FlippingFlags = [
|
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,
|
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
|
||||||
]
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class Color : IParsable<Color>, IEquatable<Color>
|
||||||
/// <param name="provider">An object that supplies culture-specific information about the format of s.</param>
|
/// <param name="provider">An object that supplies culture-specific information about the format of s.</param>
|
||||||
/// <returns>The parsed <see cref="Color"/></returns>
|
/// <returns>The parsed <see cref="Color"/></returns>
|
||||||
/// <exception cref="FormatException">Thrown in case the provided string <paramref name="s"/> is not in a valid format.</exception>
|
/// <exception cref="FormatException">Thrown in case the provided string <paramref name="s"/> is not in a valid format.</exception>
|
||||||
public static Color Parse(string s, IFormatProvider? provider)
|
public static Color Parse(string s, IFormatProvider provider)
|
||||||
{
|
{
|
||||||
_ = TryParse(s, provider, out var result);
|
_ = TryParse(s, provider, out var result);
|
||||||
return result ?? throw new FormatException($"Invalid format for TiledColor: {s}");
|
return result ?? throw new FormatException($"Invalid format for TiledColor: {s}");
|
||||||
|
@ -52,8 +52,8 @@ public class Color : IParsable<Color>, IEquatable<Color>
|
||||||
/// <param name="result">When this method returns, contains the parsed <see cref="Color"/> or <c>null</c> on failure.</param>
|
/// <param name="result">When this method returns, contains the parsed <see cref="Color"/> or <c>null</c> on failure.</param>
|
||||||
/// <returns><c>true</c> if <paramref name="s"/> was successfully parsed; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if <paramref name="s"/> was successfully parsed; otherwise, <c>false</c>.</returns>
|
||||||
public static bool TryParse(
|
public static bool TryParse(
|
||||||
[NotNullWhen(true)] string? s,
|
[NotNullWhen(true)] string s,
|
||||||
IFormatProvider? provider,
|
IFormatProvider provider,
|
||||||
[MaybeNullWhen(false)] out Color result)
|
[MaybeNullWhen(false)] out Color result)
|
||||||
{
|
{
|
||||||
if (s is not null && !s.StartsWith('#'))
|
if (s is not null && !s.StartsWith('#'))
|
||||||
|
@ -90,7 +90,7 @@ public class Color : IParsable<Color>, IEquatable<Color>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool Equals(Color? other)
|
public bool Equals(Color other)
|
||||||
{
|
{
|
||||||
if (other is null)
|
if (other is null)
|
||||||
return false;
|
return false;
|
||||||
|
@ -99,7 +99,7 @@ public class Color : IParsable<Color>, IEquatable<Color>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override bool Equals(object? obj) => obj is Color other && Equals(other);
|
public override bool Equals(object obj) => obj is Color other && Equals(other);
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override int GetHashCode() => HashCode.Combine(R, G, B, A);
|
public override int GetHashCode() => HashCode.Combine(R, G, B, A);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ public abstract class BaseLayer : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A tint color that is multiplied with any tiles drawn by this layer.
|
/// A tint color that is multiplied with any tiles drawn by this layer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Color? TintColor { get; set; }
|
public Optional<Color> TintColor { get; set; } = Optional<Color>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Horizontal offset for this layer in pixels.
|
/// Horizontal offset for this layer in pixels.
|
||||||
|
|
|
@ -118,27 +118,27 @@ public class Data
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The encoding used to encode the tile layer data.
|
/// The encoding used to encode the tile layer data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataEncoding? Encoding { get; set; }
|
public Optional<DataEncoding> Encoding { get; set; } = Optional<DataEncoding>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The compression method used to compress the tile layer data.
|
/// The compression method used to compress the tile layer data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataCompression? Compression { get; set; }
|
public Optional<DataCompression> Compression { get; set; } = Optional<DataCompression>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The parsed tile layer data, as a list of tile GIDs.
|
/// The parsed tile layer data, as a list of tile GIDs.
|
||||||
/// To get an actual tile ID, you map it to a local tile ID using the correct tileset. Please refer to
|
/// To get an actual tile ID, you map it to a local tile ID using the correct tileset. Please refer to
|
||||||
/// <see href="https://doc.mapeditor.org/en/stable/reference/global-tile-ids/#mapping-a-gid-to-a-local-tile-id">the documentation on how to do this</see>.
|
/// <see href="https://doc.mapeditor.org/en/stable/reference/global-tile-ids/#mapping-a-gid-to-a-local-tile-id">the documentation on how to do this</see>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint[]? GlobalTileIDs { get; set; }
|
public Optional<uint[]> GlobalTileIDs { get; set; } = Optional<uint[]>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The parsed flipping flags for each tile in the layer. Appear in the same order as the tiles in the layer in <see cref="GlobalTileIDs"/>.
|
/// The parsed flipping flags for each tile in the layer. Appear in the same order as the tiles in the layer in <see cref="GlobalTileIDs"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FlippingFlags[]? FlippingFlags { get; set; }
|
public Optional<FlippingFlags[]> FlippingFlags { get; set; } = Optional<FlippingFlags[]>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If the map is infinite, it will instead contain a list of chunks.
|
/// If the map is infinite, it will instead contain a list of chunks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Chunk[]? Chunks { get; set; }
|
public Optional<Chunk[]> Chunks { get; set; } = Optional<Chunk[]>.Empty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,20 +13,20 @@ public class ImageLayer : BaseLayer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Y position of the image layer in pixels.
|
/// The Y position of the image layer in pixels.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint Y { get; set; } = 0;
|
public Optional<uint> Y { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the image drawn by this layer is repeated along the X axis.
|
/// Whether the image drawn by this layer is repeated along the X axis.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool RepeatX { get; set; } = false;
|
public Optional<bool> RepeatX { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the image drawn by this layer is repeated along the Y axis.
|
/// Whether the image drawn by this layer is repeated along the Y axis.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool RepeatY { get; set; } = false;
|
public Optional<bool> RepeatY { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The image to be drawn by this image layer.
|
/// The image to be drawn by this image layer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Image? Image { get; set; }
|
public Optional<Image> Image { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,17 +36,17 @@ public class ObjectLayer : BaseLayer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The width of the object layer in tiles. Meaningless.
|
/// The width of the object layer in tiles. Meaningless.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? Width { get; set; }
|
public uint Width { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The height of the object layer in tiles. Meaningless.
|
/// The height of the object layer in tiles. Meaningless.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? Height { get; set; }
|
public uint Height { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A color that is multiplied with any tile objects drawn by this layer.
|
/// A color that is multiplied with any tile objects drawn by this layer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Color? Color { get; set; }
|
public Optional<Color> Color { get; set; } = Optional<Color>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the objects are drawn according to the order of appearance (<see cref="DrawOrder.Index"/>) or sorted by their Y coordinate (<see cref="DrawOrder.TopDown"/>).
|
/// Whether the objects are drawn according to the order of appearance (<see cref="DrawOrder.Index"/>) or sorted by their Y coordinate (<see cref="DrawOrder.TopDown"/>).
|
||||||
|
|
|
@ -10,7 +10,7 @@ public abstract class Object : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unique ID of the objects. Each object that is placed on a map gets a unique ID. Even if an object was deleted, no object gets the same ID.
|
/// Unique ID of the objects. Each object that is placed on a map gets a unique ID. Even if an object was deleted, no object gets the same ID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? ID { get; set; }
|
public Optional<uint> ID { get; set; } = Optional<uint>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the object. An arbitrary string.
|
/// The name of the object. An arbitrary string.
|
||||||
|
@ -55,7 +55,7 @@ public abstract class Object : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A reference to a template file.
|
/// A reference to a template file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Template { get; set; }
|
public Optional<string> Template { get; set; } = Optional<string>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Object properties.
|
/// Object properties.
|
||||||
|
|
|
@ -28,5 +28,5 @@ public class TileLayer : BaseLayer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The tile layer data.
|
/// The tile layer data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Data? Data { get; set; }
|
public Optional<Data> Data { get; set; } = Optional<Data>.Empty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class Map : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Tiled version used to save the file.
|
/// The Tiled version used to save the file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public required string TiledVersion { get; set; }
|
public Optional<string> TiledVersion { get; set; } = Optional<string>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The class of this map.
|
/// The class of this map.
|
||||||
|
@ -146,17 +146,17 @@ public class Map : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Only for hexagonal maps. Determines the width or height (depending on the staggered axis) of the tile's edge, in pixels.
|
/// Only for hexagonal maps. Determines the width or height (depending on the staggered axis) of the tile's edge, in pixels.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? HexSideLength { get; set; }
|
public Optional<uint> HexSideLength { get; set; } = Optional<uint>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For staggered and hexagonal maps, determines which axis (X or Y) is staggered.
|
/// For staggered and hexagonal maps, determines which axis (X or Y) is staggered.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public StaggerAxis? StaggerAxis { get; set; }
|
public Optional<StaggerAxis> StaggerAxis { get; set; } = Optional<StaggerAxis>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// For staggered and hexagonal maps, determines whether the "even" or "odd" indexes along the staggered axis are shifted.
|
/// For staggered and hexagonal maps, determines whether the "even" or "odd" indexes along the staggered axis are shifted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public StaggerIndex? StaggerIndex { get; set; }
|
public Optional<StaggerIndex> StaggerIndex { get; set; } = Optional<StaggerIndex>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// X coordinate of the parallax origin in pixels.
|
/// X coordinate of the parallax origin in pixels.
|
||||||
|
|
132
src/DotTiled/Optional.cs
Normal file
132
src/DotTiled/Optional.cs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DotTiled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a value that may or may not be present.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of the optionally present value.</typeparam>
|
||||||
|
public class Optional<T>
|
||||||
|
{
|
||||||
|
private readonly T _value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the current <see cref="Optional{T}"/> object has a value.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasValue { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the current <see cref="Optional{T}"/> object if it has been set; otherwise, throws an exception.
|
||||||
|
/// </summary>
|
||||||
|
public T Value => HasValue ? _value : throw new InvalidOperationException("Value is not set");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Optional{T}"/> class with the specified value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to be set.</param>
|
||||||
|
public Optional(T value)
|
||||||
|
{
|
||||||
|
_value = value;
|
||||||
|
HasValue = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Optional{T}"/> class with no value.
|
||||||
|
/// </summary>
|
||||||
|
public Optional()
|
||||||
|
{
|
||||||
|
_value = default!;
|
||||||
|
HasValue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implicitly converts a value to an <see cref="Optional{T}"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The value to be converted.</param>
|
||||||
|
public static implicit operator Optional<T>(T value)
|
||||||
|
{
|
||||||
|
if (value is null)
|
||||||
|
return new();
|
||||||
|
|
||||||
|
return new(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implicitly converts an <see cref="Optional{T}"/> object to a value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="optional">The <see cref="Optional{T}"/> object to be converted.</param>
|
||||||
|
public static implicit operator T(Optional<T> optional)
|
||||||
|
{
|
||||||
|
return optional.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the specified <see cref="Optional{T}"/> objects are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left"></param>
|
||||||
|
/// <param name="right"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool operator ==(Optional<T> left, Optional<T> right)
|
||||||
|
{
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the specified <see cref="Optional{T}"/> objects are not equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="left"></param>
|
||||||
|
/// <param name="right"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool operator !=(Optional<T> left, Optional<T> right)
|
||||||
|
{
|
||||||
|
return !left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value of the current <see cref="Optional{T}"/> object if it has been set; otherwise, returns the specified default value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="defaultValue">The value to be returned if the current <see cref="Optional{T}"/> object has no value.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public T GetValueOr(T defaultValue) => HasValue ? _value : defaultValue;
|
||||||
|
|
||||||
|
public Optional<T> GetValueOrOptional(Optional<T> defaultValue) => HasValue ? this : defaultValue;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString() => HasValue ? _value.ToString() : "Empty";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is null)
|
||||||
|
{
|
||||||
|
return !HasValue;
|
||||||
|
}
|
||||||
|
else if (obj.GetType() == typeof(T))
|
||||||
|
{
|
||||||
|
return HasValue && _value.Equals(obj);
|
||||||
|
}
|
||||||
|
else if (obj is Optional<T> opt)
|
||||||
|
{
|
||||||
|
if (HasValue && opt.HasValue)
|
||||||
|
{
|
||||||
|
return Equals(opt.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return !HasValue && !opt.HasValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int GetHashCode() => HasValue ? _value!.GetHashCode() : 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an empty <see cref="Optional{T}"/> object.
|
||||||
|
/// </summary>
|
||||||
|
#pragma warning disable CA1000 // Do not declare static members on generic types
|
||||||
|
public static Optional<T> Empty => new();
|
||||||
|
#pragma warning restore CA1000 // Do not declare static members on generic types
|
||||||
|
}
|
|
@ -51,7 +51,7 @@ public class ClassProperty : IHasProperties, IProperty<IList<IProperty>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool TryGetProperty<T>(string name, [NotNullWhen(true)] out T? property) where T : IProperty
|
public bool TryGetProperty<T>(string name, [NotNullWhen(true)] out T property) where T : IProperty
|
||||||
{
|
{
|
||||||
if (Value.FirstOrDefault(_properties => _properties.Name == name) is T prop)
|
if (Value.FirstOrDefault(_properties => _properties.Name == name) is T prop)
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class CustomClassDefinition : HasPropertiesBase, ICustomTypeDefinition
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The color of the custom class inside the Tiled editor.
|
/// The color of the custom class inside the Tiled editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Color? Color { get; set; }
|
public Color Color { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the custom class should be drawn with a fill color.
|
/// Whether the custom class should be drawn with a fill color.
|
||||||
|
|
|
@ -22,7 +22,7 @@ public interface IHasProperties
|
||||||
/// <param name="name">The name of the property to get.</param>
|
/// <param name="name">The name of the property to get.</param>
|
||||||
/// <param name="property">The property with the specified name, if found.</param>
|
/// <param name="property">The property with the specified name, if found.</param>
|
||||||
/// <returns>True if a property with the specified name was found; otherwise, false.</returns>
|
/// <returns>True if a property with the specified name was found; otherwise, false.</returns>
|
||||||
bool TryGetProperty<T>(string name, out T? property) where T : IProperty;
|
bool TryGetProperty<T>(string name, out T property) where T : IProperty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a property of the specified type with the specified name.
|
/// Gets a property of the specified type with the specified name.
|
||||||
|
@ -57,7 +57,7 @@ public abstract class HasPropertiesBase : IHasProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public bool TryGetProperty<T>(string name, [NotNullWhen(true)] out T? property) where T : IProperty
|
public bool TryGetProperty<T>(string name, [NotNullWhen(true)] out T property) where T : IProperty
|
||||||
{
|
{
|
||||||
var properties = GetProperties();
|
var properties = GetProperties();
|
||||||
if (properties.FirstOrDefault(_properties => _properties.Name == name) is T prop)
|
if (properties.FirstOrDefault(_properties => _properties.Name == name) is T prop)
|
||||||
|
|
|
@ -8,6 +8,20 @@ namespace DotTiled.Serialization;
|
||||||
|
|
||||||
internal static partial class Helpers
|
internal static partial class Helpers
|
||||||
{
|
{
|
||||||
|
internal static Func<string, T> CreateMapper<T>(Func<string, Exception> noMatch, params (string, T)[] mappings)
|
||||||
|
{
|
||||||
|
return s =>
|
||||||
|
{
|
||||||
|
foreach (var (key, value) in mappings)
|
||||||
|
{
|
||||||
|
if (key == s)
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw noMatch(s);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
internal static uint[] ReadMemoryStreamAsInt32Array(Stream stream)
|
internal static uint[] ReadMemoryStreamAsInt32Array(Stream stream)
|
||||||
{
|
{
|
||||||
var finalValues = new List<uint>();
|
var finalValues = new List<uint>();
|
||||||
|
@ -92,7 +106,7 @@ internal static partial class Helpers
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static IList<IProperty> MergeProperties(IList<IProperty>? baseProperties, IList<IProperty>? overrideProperties)
|
internal static IList<IProperty> MergeProperties(IList<IProperty> baseProperties, IList<IProperty> overrideProperties)
|
||||||
{
|
{
|
||||||
if (baseProperties is null)
|
if (baseProperties is null)
|
||||||
return overrideProperties ?? [];
|
return overrideProperties ?? [];
|
||||||
|
@ -134,7 +148,7 @@ internal static partial class Helpers
|
||||||
properties[index] = property;
|
properties[index] = property;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetAtMostOnce<T>(ref T? field, T value, string fieldName)
|
internal static void SetAtMostOnce<T>(ref T field, T value, string fieldName)
|
||||||
{
|
{
|
||||||
if (field is not null)
|
if (field is not null)
|
||||||
throw new InvalidOperationException($"{fieldName} already set");
|
throw new InvalidOperationException($"{fieldName} already set");
|
||||||
|
@ -142,7 +156,7 @@ internal static partial class Helpers
|
||||||
field = value;
|
field = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetAtMostOnceUsingCounter<T>(ref T? field, T value, string fieldName, ref int counter)
|
internal static void SetAtMostOnceUsingCounter<T>(ref T field, T value, string fieldName, ref int counter)
|
||||||
{
|
{
|
||||||
if (counter > 0)
|
if (counter > 0)
|
||||||
throw new InvalidOperationException($"{fieldName} already set");
|
throw new InvalidOperationException($"{fieldName} already set");
|
||||||
|
|
|
@ -16,8 +16,8 @@ public class MapReader : IMapReader
|
||||||
private readonly Func<string, Template> _externalTemplateResolver;
|
private readonly Func<string, Template> _externalTemplateResolver;
|
||||||
private readonly Func<string, ICustomTypeDefinition> _customTypeResolver;
|
private readonly Func<string, ICustomTypeDefinition> _customTypeResolver;
|
||||||
|
|
||||||
private readonly StringReader? _mapStringReader;
|
private readonly StringReader _mapStringReader;
|
||||||
private readonly XmlReader? _xmlReader;
|
private readonly XmlReader _xmlReader;
|
||||||
private readonly IMapReader _mapReader;
|
private readonly IMapReader _mapReader;
|
||||||
private bool disposedValue;
|
private bool disposedValue;
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ public class TemplateReader : ITemplateReader
|
||||||
private readonly Func<string, Template> _externalTemplateResolver;
|
private readonly Func<string, Template> _externalTemplateResolver;
|
||||||
private readonly Func<string, ICustomTypeDefinition> _customTypeResolver;
|
private readonly Func<string, ICustomTypeDefinition> _customTypeResolver;
|
||||||
|
|
||||||
private readonly StringReader? _templateStringReader;
|
private readonly StringReader _templateStringReader;
|
||||||
private readonly XmlReader? _xmlReader;
|
private readonly XmlReader _xmlReader;
|
||||||
private readonly ITemplateReader _templateReader;
|
private readonly ITemplateReader _templateReader;
|
||||||
private bool disposedValue;
|
private bool disposedValue;
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ public class TilesetReader : ITilesetReader
|
||||||
private readonly Func<string, Template> _externalTemplateResolver;
|
private readonly Func<string, Template> _externalTemplateResolver;
|
||||||
private readonly Func<string, ICustomTypeDefinition> _customTypeResolver;
|
private readonly Func<string, ICustomTypeDefinition> _customTypeResolver;
|
||||||
|
|
||||||
private readonly StringReader? _tilesetStringReader;
|
private readonly StringReader _tilesetStringReader;
|
||||||
private readonly XmlReader? _xmlReader;
|
private readonly XmlReader _xmlReader;
|
||||||
private readonly ITilesetReader _tilesetReader;
|
private readonly ITilesetReader _tilesetReader;
|
||||||
private bool disposedValue;
|
private bool disposedValue;
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,13 @@ internal static class ExtensionsJsonElement
|
||||||
return property.GetValueAs<T>();
|
return property.GetValueAs<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static T GetOptionalProperty<T>(this JsonElement element, string propertyName, T defaultValue)
|
internal static Optional<T> GetOptionalProperty<T>(this JsonElement element, string propertyName)
|
||||||
{
|
{
|
||||||
if (!element.TryGetProperty(propertyName, out var property))
|
if (!element.TryGetProperty(propertyName, out var property))
|
||||||
return defaultValue;
|
return Optional<T>.Empty;
|
||||||
|
|
||||||
if (property.ValueKind == JsonValueKind.Null)
|
if (property.ValueKind == JsonValueKind.Null)
|
||||||
return defaultValue;
|
return Optional<T>.Empty;
|
||||||
|
|
||||||
return property.GetValueAs<T>();
|
return property.GetValueAs<T>();
|
||||||
}
|
}
|
||||||
|
@ -64,18 +64,18 @@ internal static class ExtensionsJsonElement
|
||||||
return parser(property.GetString()!);
|
return parser(property.GetString()!);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static T GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName, T defaultValue) where T : IParsable<T>
|
internal static Optional<T> GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName) where T : IParsable<T>
|
||||||
{
|
{
|
||||||
if (!element.TryGetProperty(propertyName, out var property))
|
if (!element.TryGetProperty(propertyName, out var property))
|
||||||
return defaultValue;
|
return Optional<T>.Empty;
|
||||||
|
|
||||||
return T.Parse(property.GetString()!, CultureInfo.InvariantCulture);
|
return T.Parse(property.GetString()!, CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static T GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName, Func<string, T> parser, T defaultValue)
|
internal static Optional<T> GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName, Func<string, T> parser)
|
||||||
{
|
{
|
||||||
if (!element.TryGetProperty(propertyName, out var property))
|
if (!element.TryGetProperty(propertyName, out var property))
|
||||||
return defaultValue;
|
return Optional<T>.Empty;
|
||||||
|
|
||||||
return parser(property.GetString()!);
|
return parser(property.GetString()!);
|
||||||
}
|
}
|
||||||
|
@ -88,10 +88,10 @@ internal static class ExtensionsJsonElement
|
||||||
return parser(property);
|
return parser(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static T GetOptionalPropertyCustom<T>(this JsonElement element, string propertyName, Func<JsonElement, T> parser, T defaultValue)
|
internal static Optional<T> GetOptionalPropertyCustom<T>(this JsonElement element, string propertyName, Func<JsonElement, T> parser)
|
||||||
{
|
{
|
||||||
if (!element.TryGetProperty(propertyName, out var property))
|
if (!element.TryGetProperty(propertyName, out var property))
|
||||||
return defaultValue;
|
return Optional<T>.Empty;
|
||||||
|
|
||||||
return parser(property);
|
return parser(property);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,18 @@ namespace DotTiled.Serialization.Tmj;
|
||||||
|
|
||||||
public abstract partial class TmjReaderBase
|
public abstract partial class TmjReaderBase
|
||||||
{
|
{
|
||||||
internal static Data ReadDataAsChunks(JsonElement element, DataCompression? compression, DataEncoding encoding)
|
internal static Data ReadDataAsChunks(JsonElement element, Optional<DataCompression> compression, DataEncoding encoding)
|
||||||
{
|
{
|
||||||
var chunks = element.GetValueAsList<Chunk>(e => ReadChunk(e, compression, encoding)).ToArray();
|
var chunks = element.GetValueAsList<Chunk>(e => ReadChunk(e, compression, encoding)).ToArray();
|
||||||
return new Data
|
return new Data
|
||||||
{
|
{
|
||||||
Chunks = chunks,
|
Chunks = chunks,
|
||||||
Compression = compression,
|
Compression = compression,
|
||||||
Encoding = encoding,
|
Encoding = encoding
|
||||||
FlippingFlags = null,
|
|
||||||
GlobalTileIDs = null
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Chunk ReadChunk(JsonElement element, DataCompression? compression, DataEncoding encoding)
|
internal static Chunk ReadChunk(JsonElement element, Optional<DataCompression> compression, DataEncoding encoding)
|
||||||
{
|
{
|
||||||
var data = ReadDataWithoutChunks(element, compression, encoding);
|
var data = ReadDataWithoutChunks(element, compression, encoding);
|
||||||
|
|
||||||
|
@ -34,33 +32,33 @@ public abstract partial class TmjReaderBase
|
||||||
Y = y,
|
Y = y,
|
||||||
Width = width,
|
Width = width,
|
||||||
Height = height,
|
Height = height,
|
||||||
GlobalTileIDs = data.GlobalTileIDs!,
|
GlobalTileIDs = data.GlobalTileIDs,
|
||||||
FlippingFlags = data.FlippingFlags!
|
FlippingFlags = data.FlippingFlags
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Data ReadDataWithoutChunks(JsonElement element, DataCompression? compression, DataEncoding encoding)
|
internal static Data ReadDataWithoutChunks(JsonElement element, Optional<DataCompression> compression, DataEncoding encoding)
|
||||||
{
|
{
|
||||||
if (encoding == DataEncoding.Csv)
|
if (encoding == DataEncoding.Csv)
|
||||||
{
|
{
|
||||||
// Array of uint
|
// Array of uint
|
||||||
var data = element.GetValueAsList<uint>(e => e.GetValueAs<uint>()).ToArray();
|
var data = element.GetValueAsList<uint>(e => e.GetValueAs<uint>()).ToArray();
|
||||||
var (globalTileIDs, flippingFlags) = Helpers.ReadAndClearFlippingFlagsFromGIDs(data);
|
var (globalTileIDs, flippingFlags) = Helpers.ReadAndClearFlippingFlagsFromGIDs(data);
|
||||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags, Chunks = null };
|
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags };
|
||||||
}
|
}
|
||||||
else if (encoding == DataEncoding.Base64)
|
else if (encoding == DataEncoding.Base64)
|
||||||
{
|
{
|
||||||
var base64Data = element.GetBytesFromBase64();
|
var base64Data = element.GetBytesFromBase64();
|
||||||
|
|
||||||
if (compression == null)
|
if (!compression.HasValue)
|
||||||
{
|
{
|
||||||
var data = Helpers.ReadBytesAsInt32Array(base64Data);
|
var data = Helpers.ReadBytesAsInt32Array(base64Data);
|
||||||
var (globalTileIDs, flippingFlags) = Helpers.ReadAndClearFlippingFlagsFromGIDs(data);
|
var (globalTileIDs, flippingFlags) = Helpers.ReadAndClearFlippingFlagsFromGIDs(data);
|
||||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags, Chunks = null };
|
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags };
|
||||||
}
|
}
|
||||||
|
|
||||||
using var stream = new MemoryStream(base64Data);
|
using var stream = new MemoryStream(base64Data);
|
||||||
var decompressed = compression switch
|
var decompressed = compression.Value switch
|
||||||
{
|
{
|
||||||
DataCompression.GZip => Helpers.DecompressGZip(stream),
|
DataCompression.GZip => Helpers.DecompressGZip(stream),
|
||||||
DataCompression.ZLib => Helpers.DecompressZLib(stream),
|
DataCompression.ZLib => Helpers.DecompressZLib(stream),
|
||||||
|
@ -70,7 +68,7 @@ public abstract partial class TmjReaderBase
|
||||||
|
|
||||||
{
|
{
|
||||||
var (globalTileIDs, flippingFlags) = Helpers.ReadAndClearFlippingFlagsFromGIDs(decompressed);
|
var (globalTileIDs, flippingFlags) = Helpers.ReadAndClearFlippingFlagsFromGIDs(decompressed);
|
||||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags, Chunks = null };
|
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace DotTiled.Serialization.Tmj;
|
namespace DotTiled.Serialization.Tmj;
|
||||||
|
@ -10,16 +9,16 @@ public abstract partial class TmjReaderBase
|
||||||
{
|
{
|
||||||
var id = element.GetRequiredProperty<uint>("id");
|
var id = element.GetRequiredProperty<uint>("id");
|
||||||
var name = element.GetRequiredProperty<string>("name");
|
var name = element.GetRequiredProperty<string>("name");
|
||||||
var @class = element.GetOptionalProperty<string>("class", "");
|
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||||
var opacity = element.GetOptionalProperty<float>("opacity", 1.0f);
|
var opacity = element.GetOptionalProperty<float>("opacity").GetValueOr(1.0f);
|
||||||
var visible = element.GetOptionalProperty<bool>("visible", true);
|
var visible = element.GetOptionalProperty<bool>("visible").GetValueOr(true);
|
||||||
var tintColor = element.GetOptionalPropertyParseable<Color?>("tintcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var tintColor = element.GetOptionalPropertyParseable<Color>("tintcolor");
|
||||||
var offsetX = element.GetOptionalProperty<float>("offsetx", 0.0f);
|
var offsetX = element.GetOptionalProperty<float>("offsetx").GetValueOr(0.0f);
|
||||||
var offsetY = element.GetOptionalProperty<float>("offsety", 0.0f);
|
var offsetY = element.GetOptionalProperty<float>("offsety").GetValueOr(0.0f);
|
||||||
var parallaxX = element.GetOptionalProperty<float>("parallaxx", 1.0f);
|
var parallaxX = element.GetOptionalProperty<float>("parallaxx").GetValueOr(1.0f);
|
||||||
var parallaxY = element.GetOptionalProperty<float>("parallaxy", 1.0f);
|
var parallaxY = element.GetOptionalProperty<float>("parallaxy").GetValueOr(1.0f);
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
var layers = element.GetOptionalPropertyCustom<List<BaseLayer>>("layers", e => e.GetValueAsList<BaseLayer>(ReadLayer), []);
|
var layers = element.GetOptionalPropertyCustom<List<BaseLayer>>("layers", e => e.GetValueAsList<BaseLayer>(ReadLayer)).GetValueOr([]);
|
||||||
|
|
||||||
return new Group
|
return new Group
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Globalization;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace DotTiled.Serialization.Tmj;
|
namespace DotTiled.Serialization.Tmj;
|
||||||
|
@ -9,22 +8,22 @@ public abstract partial class TmjReaderBase
|
||||||
{
|
{
|
||||||
var id = element.GetRequiredProperty<uint>("id");
|
var id = element.GetRequiredProperty<uint>("id");
|
||||||
var name = element.GetRequiredProperty<string>("name");
|
var name = element.GetRequiredProperty<string>("name");
|
||||||
var @class = element.GetOptionalProperty<string>("class", "");
|
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||||
var opacity = element.GetOptionalProperty<float>("opacity", 1.0f);
|
var opacity = element.GetOptionalProperty<float>("opacity").GetValueOr(1.0f);
|
||||||
var visible = element.GetOptionalProperty<bool>("visible", true);
|
var visible = element.GetOptionalProperty<bool>("visible").GetValueOr(true);
|
||||||
var tintColor = element.GetOptionalPropertyParseable<Color?>("tintcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var tintColor = element.GetOptionalPropertyParseable<Color>("tintcolor");
|
||||||
var offsetX = element.GetOptionalProperty<float>("offsetx", 0.0f);
|
var offsetX = element.GetOptionalProperty<float>("offsetx").GetValueOr(0.0f);
|
||||||
var offsetY = element.GetOptionalProperty<float>("offsety", 0.0f);
|
var offsetY = element.GetOptionalProperty<float>("offsety").GetValueOr(0.0f);
|
||||||
var parallaxX = element.GetOptionalProperty<float>("parallaxx", 1.0f);
|
var parallaxX = element.GetOptionalProperty<float>("parallaxx").GetValueOr(1.0f);
|
||||||
var parallaxY = element.GetOptionalProperty<float>("parallaxy", 1.0f);
|
var parallaxY = element.GetOptionalProperty<float>("parallaxy").GetValueOr(1.0f);
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
|
|
||||||
var image = element.GetRequiredProperty<string>("image");
|
var image = element.GetRequiredProperty<string>("image");
|
||||||
var repeatX = element.GetOptionalProperty<bool>("repeatx", false);
|
var repeatX = element.GetOptionalProperty<bool>("repeatx").GetValueOr(false);
|
||||||
var repeatY = element.GetOptionalProperty<bool>("repeaty", false);
|
var repeatY = element.GetOptionalProperty<bool>("repeaty").GetValueOr(false);
|
||||||
var transparentColor = element.GetOptionalPropertyParseable<Color?>("transparentcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var transparentColor = element.GetOptionalPropertyParseable<Color>("transparentcolor");
|
||||||
var x = element.GetOptionalProperty<uint>("x", 0);
|
var x = element.GetOptionalProperty<uint>("x").GetValueOr(0);
|
||||||
var y = element.GetOptionalProperty<uint>("y", 0);
|
var y = element.GetOptionalProperty<uint>("y").GetValueOr(0);
|
||||||
|
|
||||||
var imgModel = new Image
|
var imgModel = new Image
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,7 @@ public abstract partial class TmjReaderBase
|
||||||
{
|
{
|
||||||
var version = element.GetRequiredProperty<string>("version");
|
var version = element.GetRequiredProperty<string>("version");
|
||||||
var tiledVersion = element.GetRequiredProperty<string>("tiledversion");
|
var tiledVersion = element.GetRequiredProperty<string>("tiledversion");
|
||||||
string @class = element.GetOptionalProperty<string>("class", "");
|
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||||
var orientation = element.GetRequiredPropertyParseable<MapOrientation>("orientation", s => s switch
|
var orientation = element.GetRequiredPropertyParseable<MapOrientation>("orientation", s => s switch
|
||||||
{
|
{
|
||||||
"orthogonal" => MapOrientation.Orthogonal,
|
"orthogonal" => MapOrientation.Orthogonal,
|
||||||
|
@ -26,36 +26,36 @@ public abstract partial class TmjReaderBase
|
||||||
"left-down" => RenderOrder.LeftDown,
|
"left-down" => RenderOrder.LeftDown,
|
||||||
"left-up" => RenderOrder.LeftUp,
|
"left-up" => RenderOrder.LeftUp,
|
||||||
_ => throw new JsonException($"Unknown render order '{s}'")
|
_ => throw new JsonException($"Unknown render order '{s}'")
|
||||||
}, RenderOrder.RightDown);
|
}).GetValueOr(RenderOrder.RightDown);
|
||||||
var compressionLevel = element.GetOptionalProperty<int>("compressionlevel", -1);
|
var compressionLevel = element.GetOptionalProperty<int>("compressionlevel").GetValueOr(-1);
|
||||||
var width = element.GetRequiredProperty<uint>("width");
|
var width = element.GetRequiredProperty<uint>("width");
|
||||||
var height = element.GetRequiredProperty<uint>("height");
|
var height = element.GetRequiredProperty<uint>("height");
|
||||||
var tileWidth = element.GetRequiredProperty<uint>("tilewidth");
|
var tileWidth = element.GetRequiredProperty<uint>("tilewidth");
|
||||||
var tileHeight = element.GetRequiredProperty<uint>("tileheight");
|
var tileHeight = element.GetRequiredProperty<uint>("tileheight");
|
||||||
var hexSideLength = element.GetOptionalProperty<uint?>("hexsidelength", null);
|
var hexSideLength = element.GetOptionalProperty<uint>("hexsidelength");
|
||||||
var staggerAxis = element.GetOptionalPropertyParseable<StaggerAxis?>("staggeraxis", s => s switch
|
var staggerAxis = element.GetOptionalPropertyParseable<StaggerAxis>("staggeraxis", s => s switch
|
||||||
{
|
{
|
||||||
"x" => StaggerAxis.X,
|
"x" => StaggerAxis.X,
|
||||||
"y" => StaggerAxis.Y,
|
"y" => StaggerAxis.Y,
|
||||||
_ => throw new JsonException($"Unknown stagger axis '{s}'")
|
_ => throw new JsonException($"Unknown stagger axis '{s}'")
|
||||||
}, null);
|
});
|
||||||
var staggerIndex = element.GetOptionalPropertyParseable<StaggerIndex?>("staggerindex", s => s switch
|
var staggerIndex = element.GetOptionalPropertyParseable<StaggerIndex>("staggerindex", s => s switch
|
||||||
{
|
{
|
||||||
"odd" => StaggerIndex.Odd,
|
"odd" => StaggerIndex.Odd,
|
||||||
"even" => StaggerIndex.Even,
|
"even" => StaggerIndex.Even,
|
||||||
_ => throw new JsonException($"Unknown stagger index '{s}'")
|
_ => throw new JsonException($"Unknown stagger index '{s}'")
|
||||||
}, null);
|
});
|
||||||
var parallaxOriginX = element.GetOptionalProperty<float>("parallaxoriginx", 0.0f);
|
var parallaxOriginX = element.GetOptionalProperty<float>("parallaxoriginx").GetValueOr(0f);
|
||||||
var parallaxOriginY = element.GetOptionalProperty<float>("parallaxoriginy", 0.0f);
|
var parallaxOriginY = element.GetOptionalProperty<float>("parallaxoriginy").GetValueOr(0f);
|
||||||
var backgroundColor = element.GetOptionalPropertyParseable<Color>("backgroundcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), Color.Parse("#00000000", CultureInfo.InvariantCulture));
|
var backgroundColor = element.GetOptionalPropertyParseable<Color>("backgroundcolor").GetValueOr(Color.Parse("#00000000", CultureInfo.InvariantCulture));
|
||||||
var nextLayerID = element.GetRequiredProperty<uint>("nextlayerid");
|
var nextLayerID = element.GetRequiredProperty<uint>("nextlayerid");
|
||||||
var nextObjectID = element.GetRequiredProperty<uint>("nextobjectid");
|
var nextObjectID = element.GetRequiredProperty<uint>("nextobjectid");
|
||||||
var infinite = element.GetOptionalProperty<bool>("infinite", false);
|
var infinite = element.GetOptionalProperty<bool>("infinite").GetValueOr(false);
|
||||||
|
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
|
|
||||||
List<BaseLayer> layers = element.GetOptionalPropertyCustom<List<BaseLayer>>("layers", e => e.GetValueAsList<BaseLayer>(el => ReadLayer(el)), []);
|
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)), []);
|
List<Tileset> tilesets = element.GetOptionalPropertyCustom<List<Tileset>>("tilesets", e => e.GetValueAsList<Tileset>(el => ReadTileset(el, version, tiledVersion))).GetValueOr([]);
|
||||||
|
|
||||||
return new Map
|
return new Map
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,29 +11,29 @@ public abstract partial class TmjReaderBase
|
||||||
{
|
{
|
||||||
var id = element.GetRequiredProperty<uint>("id");
|
var id = element.GetRequiredProperty<uint>("id");
|
||||||
var name = element.GetRequiredProperty<string>("name");
|
var name = element.GetRequiredProperty<string>("name");
|
||||||
var @class = element.GetOptionalProperty<string>("class", "");
|
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||||
var opacity = element.GetOptionalProperty<float>("opacity", 1.0f);
|
var opacity = element.GetOptionalProperty<float>("opacity").GetValueOr(1.0f);
|
||||||
var visible = element.GetOptionalProperty<bool>("visible", true);
|
var visible = element.GetOptionalProperty<bool>("visible").GetValueOr(true);
|
||||||
var tintColor = element.GetOptionalPropertyParseable<Color?>("tintcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var tintColor = element.GetOptionalPropertyParseable<Color>("tintcolor");
|
||||||
var offsetX = element.GetOptionalProperty<float>("offsetx", 0.0f);
|
var offsetX = element.GetOptionalProperty<float>("offsetx").GetValueOr(0.0f);
|
||||||
var offsetY = element.GetOptionalProperty<float>("offsety", 0.0f);
|
var offsetY = element.GetOptionalProperty<float>("offsety").GetValueOr(0.0f);
|
||||||
var parallaxX = element.GetOptionalProperty<float>("parallaxx", 1.0f);
|
var parallaxX = element.GetOptionalProperty<float>("parallaxx").GetValueOr(1.0f);
|
||||||
var parallaxY = element.GetOptionalProperty<float>("parallaxy", 1.0f);
|
var parallaxY = element.GetOptionalProperty<float>("parallaxy").GetValueOr(1.0f);
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
|
|
||||||
var x = element.GetOptionalProperty<uint>("x", 0);
|
var x = element.GetOptionalProperty<uint>("x").GetValueOr(0);
|
||||||
var y = element.GetOptionalProperty<uint>("y", 0);
|
var y = element.GetOptionalProperty<uint>("y").GetValueOr(0);
|
||||||
var width = element.GetOptionalProperty<uint?>("width", null);
|
var width = element.GetOptionalProperty<uint>("width").GetValueOr(0);
|
||||||
var height = element.GetOptionalProperty<uint?>("height", null);
|
var height = element.GetOptionalProperty<uint>("height").GetValueOr(0);
|
||||||
var color = element.GetOptionalPropertyParseable<Color?>("color", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var color = element.GetOptionalPropertyParseable<Color>("color");
|
||||||
var drawOrder = element.GetOptionalPropertyParseable<DrawOrder>("draworder", s => s switch
|
var drawOrder = element.GetOptionalPropertyParseable<DrawOrder>("draworder", s => s switch
|
||||||
{
|
{
|
||||||
"topdown" => DrawOrder.TopDown,
|
"topdown" => DrawOrder.TopDown,
|
||||||
"index" => DrawOrder.Index,
|
"index" => DrawOrder.Index,
|
||||||
_ => throw new JsonException($"Unknown draw order '{s}'.")
|
_ => throw new JsonException($"Unknown draw order '{s}'.")
|
||||||
}, DrawOrder.TopDown);
|
}).GetValueOr(DrawOrder.TopDown);
|
||||||
|
|
||||||
var objects = element.GetOptionalPropertyCustom<List<DotTiled.Object>>("objects", e => e.GetValueAsList<DotTiled.Object>(el => ReadObject(el)), []);
|
var objects = element.GetOptionalPropertyCustom<List<DotTiled.Object>>("objects", e => e.GetValueAsList<DotTiled.Object>(el => ReadObject(el))).GetValueOr([]);
|
||||||
|
|
||||||
return new ObjectLayer
|
return new ObjectLayer
|
||||||
{
|
{
|
||||||
|
@ -60,7 +60,7 @@ public abstract partial class TmjReaderBase
|
||||||
|
|
||||||
internal DotTiled.Object ReadObject(JsonElement element)
|
internal DotTiled.Object ReadObject(JsonElement element)
|
||||||
{
|
{
|
||||||
uint? idDefault = null;
|
Optional<uint> idDefault = Optional<uint>.Empty;
|
||||||
string nameDefault = "";
|
string nameDefault = "";
|
||||||
string typeDefault = "";
|
string typeDefault = "";
|
||||||
float xDefault = 0f;
|
float xDefault = 0f;
|
||||||
|
@ -68,16 +68,16 @@ public abstract partial class TmjReaderBase
|
||||||
float widthDefault = 0f;
|
float widthDefault = 0f;
|
||||||
float heightDefault = 0f;
|
float heightDefault = 0f;
|
||||||
float rotationDefault = 0f;
|
float rotationDefault = 0f;
|
||||||
uint? gidDefault = null;
|
|
||||||
bool visibleDefault = true;
|
bool visibleDefault = true;
|
||||||
bool ellipseDefault = false;
|
bool ellipseDefault = false;
|
||||||
bool pointDefault = false;
|
bool pointDefault = false;
|
||||||
List<Vector2>? polygonDefault = null;
|
|
||||||
List<Vector2>? polylineDefault = null;
|
List<Vector2> polygonDefault = null;
|
||||||
|
List<Vector2> polylineDefault = null;
|
||||||
List<IProperty> propertiesDefault = [];
|
List<IProperty> propertiesDefault = [];
|
||||||
|
|
||||||
var template = element.GetOptionalProperty<string?>("template", null);
|
var template = element.GetOptionalProperty<string>("template");
|
||||||
if (template is not null)
|
if (template.HasValue)
|
||||||
{
|
{
|
||||||
var resolvedTemplate = _externalTemplateResolver(template);
|
var resolvedTemplate = _externalTemplateResolver(template);
|
||||||
var templObj = resolvedTemplate.Object;
|
var templObj = resolvedTemplate.Object;
|
||||||
|
@ -98,24 +98,24 @@ public abstract partial class TmjReaderBase
|
||||||
polylineDefault = (templObj is PolylineObject polylineObj) ? polylineObj.Points : null;
|
polylineDefault = (templObj is PolylineObject polylineObj) ? polylineObj.Points : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ellipse = element.GetOptionalProperty<bool>("ellipse", ellipseDefault);
|
var ellipse = element.GetOptionalProperty<bool>("ellipse").GetValueOr(ellipseDefault);
|
||||||
var gid = element.GetOptionalProperty<uint?>("gid", gidDefault);
|
var gid = element.GetOptionalProperty<uint>("gid");
|
||||||
var height = element.GetOptionalProperty<float>("height", heightDefault);
|
var height = element.GetOptionalProperty<float>("height").GetValueOr(heightDefault);
|
||||||
var id = element.GetOptionalProperty<uint?>("id", idDefault);
|
var id = element.GetOptionalProperty<uint>("id").GetValueOrOptional(idDefault);
|
||||||
var name = element.GetOptionalProperty<string>("name", nameDefault);
|
var name = element.GetOptionalProperty<string>("name").GetValueOr(nameDefault);
|
||||||
var point = element.GetOptionalProperty<bool>("point", pointDefault);
|
var point = element.GetOptionalProperty<bool>("point").GetValueOr(pointDefault);
|
||||||
var polygon = element.GetOptionalPropertyCustom<List<Vector2>?>("polygon", ReadPoints, polygonDefault);
|
var polygon = element.GetOptionalPropertyCustom<List<Vector2>>("polygon", ReadPoints).GetValueOr(polygonDefault);
|
||||||
var polyline = element.GetOptionalPropertyCustom<List<Vector2>?>("polyline", ReadPoints, polylineDefault);
|
var polyline = element.GetOptionalPropertyCustom<List<Vector2>>("polyline", ReadPoints).GetValueOr(polylineDefault);
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, propertiesDefault);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr(propertiesDefault);
|
||||||
var rotation = element.GetOptionalProperty<float>("rotation", rotationDefault);
|
var rotation = element.GetOptionalProperty<float>("rotation").GetValueOr(rotationDefault);
|
||||||
var text = element.GetOptionalPropertyCustom<TextObject?>("text", ReadText, null);
|
var text = element.GetOptionalPropertyCustom<TextObject>("text", ReadText);
|
||||||
var type = element.GetOptionalProperty<string>("type", typeDefault);
|
var type = element.GetOptionalProperty<string>("type").GetValueOr(typeDefault);
|
||||||
var visible = element.GetOptionalProperty<bool>("visible", visibleDefault);
|
var visible = element.GetOptionalProperty<bool>("visible").GetValueOr(visibleDefault);
|
||||||
var width = element.GetOptionalProperty<float>("width", widthDefault);
|
var width = element.GetOptionalProperty<float>("width").GetValueOr(widthDefault);
|
||||||
var x = element.GetOptionalProperty<float>("x", xDefault);
|
var x = element.GetOptionalProperty<float>("x").GetValueOr(xDefault);
|
||||||
var y = element.GetOptionalProperty<float>("y", yDefault);
|
var y = element.GetOptionalProperty<float>("y").GetValueOr(yDefault);
|
||||||
|
|
||||||
if (gid is not null)
|
if (gid.HasValue)
|
||||||
{
|
{
|
||||||
return new TileObject
|
return new TileObject
|
||||||
{
|
{
|
||||||
|
@ -208,19 +208,19 @@ public abstract partial class TmjReaderBase
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text is not null)
|
if (text.HasValue)
|
||||||
{
|
{
|
||||||
text.ID = id;
|
text.Value.ID = id;
|
||||||
text.Name = name;
|
text.Value.Name = name;
|
||||||
text.Type = type;
|
text.Value.Type = type;
|
||||||
text.X = x;
|
text.Value.X = x;
|
||||||
text.Y = y;
|
text.Value.Y = y;
|
||||||
text.Width = width;
|
text.Value.Width = width;
|
||||||
text.Height = height;
|
text.Value.Height = height;
|
||||||
text.Rotation = rotation;
|
text.Value.Rotation = rotation;
|
||||||
text.Visible = visible;
|
text.Value.Visible = visible;
|
||||||
text.Template = template;
|
text.Value.Template = template;
|
||||||
text.Properties = properties;
|
text.Value.Properties = properties;
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,30 +250,30 @@ public abstract partial class TmjReaderBase
|
||||||
|
|
||||||
internal static TextObject ReadText(JsonElement element)
|
internal static TextObject ReadText(JsonElement element)
|
||||||
{
|
{
|
||||||
var bold = element.GetOptionalProperty<bool>("bold", false);
|
var bold = element.GetOptionalProperty<bool>("bold").GetValueOr(false);
|
||||||
var color = element.GetOptionalPropertyParseable<Color>("color", s => Color.Parse(s, CultureInfo.InvariantCulture), Color.Parse("#00000000", CultureInfo.InvariantCulture));
|
var color = element.GetOptionalPropertyParseable<Color>("color").GetValueOr(Color.Parse("#00000000", CultureInfo.InvariantCulture));
|
||||||
var fontfamily = element.GetOptionalProperty<string>("fontfamily", "sans-serif");
|
var fontfamily = element.GetOptionalProperty<string>("fontfamily").GetValueOr("sans-serif");
|
||||||
var halign = element.GetOptionalPropertyParseable<TextHorizontalAlignment>("halign", s => s switch
|
var halign = element.GetOptionalPropertyParseable<TextHorizontalAlignment>("halign", s => s switch
|
||||||
{
|
{
|
||||||
"left" => TextHorizontalAlignment.Left,
|
"left" => TextHorizontalAlignment.Left,
|
||||||
"center" => TextHorizontalAlignment.Center,
|
"center" => TextHorizontalAlignment.Center,
|
||||||
"right" => TextHorizontalAlignment.Right,
|
"right" => TextHorizontalAlignment.Right,
|
||||||
_ => throw new JsonException($"Unknown horizontal alignment '{s}'.")
|
_ => throw new JsonException($"Unknown horizontal alignment '{s}'.")
|
||||||
}, TextHorizontalAlignment.Left);
|
}).GetValueOr(TextHorizontalAlignment.Left);
|
||||||
var italic = element.GetOptionalProperty<bool>("italic", false);
|
var italic = element.GetOptionalProperty<bool>("italic").GetValueOr(false);
|
||||||
var kerning = element.GetOptionalProperty<bool>("kerning", true);
|
var kerning = element.GetOptionalProperty<bool>("kerning").GetValueOr(true);
|
||||||
var pixelsize = element.GetOptionalProperty<int>("pixelsize", 16);
|
var pixelsize = element.GetOptionalProperty<int>("pixelsize").GetValueOr(16);
|
||||||
var strikeout = element.GetOptionalProperty<bool>("strikeout", false);
|
var strikeout = element.GetOptionalProperty<bool>("strikeout").GetValueOr(false);
|
||||||
var text = element.GetRequiredProperty<string>("text");
|
var text = element.GetRequiredProperty<string>("text");
|
||||||
var underline = element.GetOptionalProperty<bool>("underline", false);
|
var underline = element.GetOptionalProperty<bool>("underline").GetValueOr(false);
|
||||||
var valign = element.GetOptionalPropertyParseable<TextVerticalAlignment>("valign", s => s switch
|
var valign = element.GetOptionalPropertyParseable<TextVerticalAlignment>("valign", s => s switch
|
||||||
{
|
{
|
||||||
"top" => TextVerticalAlignment.Top,
|
"top" => TextVerticalAlignment.Top,
|
||||||
"center" => TextVerticalAlignment.Center,
|
"center" => TextVerticalAlignment.Center,
|
||||||
"bottom" => TextVerticalAlignment.Bottom,
|
"bottom" => TextVerticalAlignment.Bottom,
|
||||||
_ => throw new JsonException($"Unknown vertical alignment '{s}'.")
|
_ => throw new JsonException($"Unknown vertical alignment '{s}'.")
|
||||||
}, TextVerticalAlignment.Top);
|
}).GetValueOr(TextVerticalAlignment.Top);
|
||||||
var wrap = element.GetOptionalProperty<bool>("wrap", false);
|
var wrap = element.GetOptionalProperty<bool>("wrap").GetValueOr(false);
|
||||||
|
|
||||||
return new TextObject
|
return new TextObject
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,9 +22,9 @@ public abstract partial class TmjReaderBase
|
||||||
"object" => PropertyType.Object,
|
"object" => PropertyType.Object,
|
||||||
"class" => PropertyType.Class,
|
"class" => PropertyType.Class,
|
||||||
_ => throw new JsonException("Invalid property type")
|
_ => throw new JsonException("Invalid property type")
|
||||||
}, PropertyType.String);
|
}).GetValueOr(PropertyType.String);
|
||||||
var propertyType = e.GetOptionalProperty<string?>("propertytype", null);
|
var propertyType = e.GetOptionalProperty<string>("propertytype");
|
||||||
if (propertyType is not null)
|
if (propertyType.HasValue)
|
||||||
{
|
{
|
||||||
return ReadPropertyWithCustomType(e);
|
return ReadPropertyWithCustomType(e);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public abstract partial class TmjReaderBase
|
||||||
|
|
||||||
internal IProperty ReadPropertyWithCustomType(JsonElement element)
|
internal IProperty ReadPropertyWithCustomType(JsonElement element)
|
||||||
{
|
{
|
||||||
var isClass = element.GetOptionalProperty<string?>("type", null) == "class";
|
var isClass = element.GetOptionalProperty<string>("type") == "class";
|
||||||
if (isClass)
|
if (isClass)
|
||||||
{
|
{
|
||||||
return ReadClassProperty(element);
|
return ReadClassProperty(element);
|
||||||
|
@ -66,7 +66,7 @@ public abstract partial class TmjReaderBase
|
||||||
if (customTypeDef is CustomClassDefinition ccd)
|
if (customTypeDef is CustomClassDefinition ccd)
|
||||||
{
|
{
|
||||||
var propsInType = Helpers.CreateInstanceOfCustomClass(ccd, _customTypeResolver);
|
var propsInType = Helpers.CreateInstanceOfCustomClass(ccd, _customTypeResolver);
|
||||||
var props = element.GetOptionalPropertyCustom<List<IProperty>>("value", e => ReadPropertiesInsideClass(e, ccd), []);
|
var props = element.GetOptionalPropertyCustom<List<IProperty>>("value", e => ReadPropertiesInsideClass(e, ccd)).GetValueOr([]);
|
||||||
var mergedProps = Helpers.MergeProperties(propsInType, props);
|
var mergedProps = Helpers.MergeProperties(propsInType, props);
|
||||||
|
|
||||||
return new ClassProperty
|
return new ClassProperty
|
||||||
|
@ -120,7 +120,7 @@ public abstract partial class TmjReaderBase
|
||||||
"string" => PropertyType.String,
|
"string" => PropertyType.String,
|
||||||
"int" => PropertyType.Int,
|
"int" => PropertyType.Int,
|
||||||
_ => throw new JsonException("Invalid property type")
|
_ => throw new JsonException("Invalid property type")
|
||||||
}, PropertyType.String);
|
}).GetValueOr(PropertyType.String);
|
||||||
var customTypeDef = _customTypeResolver(propertyType);
|
var customTypeDef = _customTypeResolver(propertyType);
|
||||||
|
|
||||||
if (customTypeDef is not CustomEnumDefinition ced)
|
if (customTypeDef is not CustomEnumDefinition ced)
|
||||||
|
|
|
@ -7,7 +7,7 @@ public abstract partial class TmjReaderBase
|
||||||
internal Template ReadTemplate(JsonElement element)
|
internal Template ReadTemplate(JsonElement element)
|
||||||
{
|
{
|
||||||
var type = element.GetRequiredProperty<string>("type");
|
var type = element.GetRequiredProperty<string>("type");
|
||||||
var tileset = element.GetOptionalPropertyCustom<Tileset?>("tileset", ReadTileset, null);
|
var tileset = element.GetOptionalPropertyCustom<Tileset>("tileset", e => ReadTileset(e));
|
||||||
var @object = element.GetRequiredPropertyCustom<DotTiled.Object>("object", ReadObject);
|
var @object = element.GetRequiredPropertyCustom<DotTiled.Object>("object", ReadObject);
|
||||||
|
|
||||||
return new Template
|
return new Template
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
using System.Globalization;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace DotTiled.Serialization.Tmj;
|
namespace DotTiled.Serialization.Tmj;
|
||||||
|
@ -7,43 +6,43 @@ public abstract partial class TmjReaderBase
|
||||||
{
|
{
|
||||||
internal TileLayer ReadTileLayer(JsonElement element)
|
internal TileLayer ReadTileLayer(JsonElement element)
|
||||||
{
|
{
|
||||||
var compression = element.GetOptionalPropertyParseable<DataCompression?>("compression", s => s switch
|
|
||||||
{
|
|
||||||
"zlib" => DataCompression.ZLib,
|
|
||||||
"gzip" => DataCompression.GZip,
|
|
||||||
"" => null,
|
|
||||||
_ => throw new JsonException($"Unsupported compression '{s}'.")
|
|
||||||
}, null);
|
|
||||||
var encoding = element.GetOptionalPropertyParseable<DataEncoding>("encoding", s => s switch
|
var encoding = element.GetOptionalPropertyParseable<DataEncoding>("encoding", s => s switch
|
||||||
{
|
{
|
||||||
"csv" => DataEncoding.Csv,
|
"csv" => DataEncoding.Csv,
|
||||||
"base64" => DataEncoding.Base64,
|
"base64" => DataEncoding.Base64,
|
||||||
_ => throw new JsonException($"Unsupported encoding '{s}'.")
|
_ => throw new JsonException($"Unsupported encoding '{s}'.")
|
||||||
}, DataEncoding.Csv);
|
}).GetValueOr(DataEncoding.Csv);
|
||||||
var chunks = element.GetOptionalPropertyCustom<Data?>("chunks", e => ReadDataAsChunks(e, compression, encoding), null);
|
var compression = element.GetOptionalPropertyParseable<DataCompression>("compression", s => s switch
|
||||||
var @class = element.GetOptionalProperty<string>("class", "");
|
{
|
||||||
var data = element.GetOptionalPropertyCustom<Data?>("data", e => ReadDataWithoutChunks(e, compression, encoding), null);
|
"zlib" => DataCompression.ZLib,
|
||||||
|
"gzip" => DataCompression.GZip,
|
||||||
|
"" => Optional<DataCompression>.Empty,
|
||||||
|
_ => throw new JsonException($"Unsupported compression '{s}'.")
|
||||||
|
});
|
||||||
|
var chunks = element.GetOptionalPropertyCustom<Data>("chunks", e => ReadDataAsChunks(e, compression, encoding));
|
||||||
|
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||||
|
var data = element.GetOptionalPropertyCustom<Data>("data", e => ReadDataWithoutChunks(e, compression, encoding));
|
||||||
var height = element.GetRequiredProperty<uint>("height");
|
var height = element.GetRequiredProperty<uint>("height");
|
||||||
var id = element.GetRequiredProperty<uint>("id");
|
var id = element.GetRequiredProperty<uint>("id");
|
||||||
var name = element.GetRequiredProperty<string>("name");
|
var name = element.GetRequiredProperty<string>("name");
|
||||||
var offsetX = element.GetOptionalProperty<float>("offsetx", 0.0f);
|
var offsetX = element.GetOptionalProperty<float>("offsetx").GetValueOr(0.0f);
|
||||||
var offsetY = element.GetOptionalProperty<float>("offsety", 0.0f);
|
var offsetY = element.GetOptionalProperty<float>("offsety").GetValueOr(0.0f);
|
||||||
var opacity = element.GetOptionalProperty<float>("opacity", 1.0f);
|
var opacity = element.GetOptionalProperty<float>("opacity").GetValueOr(1.0f);
|
||||||
var parallaxx = element.GetOptionalProperty<float>("parallaxx", 1.0f);
|
var parallaxx = element.GetOptionalProperty<float>("parallaxx").GetValueOr(1.0f);
|
||||||
var parallaxy = element.GetOptionalProperty<float>("parallaxy", 1.0f);
|
var parallaxy = element.GetOptionalProperty<float>("parallaxy").GetValueOr(1.0f);
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
var repeatX = element.GetOptionalProperty<bool>("repeatx", false);
|
var repeatX = element.GetOptionalProperty<bool>("repeatx").GetValueOr(false);
|
||||||
var repeatY = element.GetOptionalProperty<bool>("repeaty", false);
|
var repeatY = element.GetOptionalProperty<bool>("repeaty").GetValueOr(false);
|
||||||
var startX = element.GetOptionalProperty<int>("startx", 0);
|
var startX = element.GetOptionalProperty<int>("startx").GetValueOr(0);
|
||||||
var startY = element.GetOptionalProperty<int>("starty", 0);
|
var startY = element.GetOptionalProperty<int>("starty").GetValueOr(0);
|
||||||
var tintColor = element.GetOptionalPropertyParseable<Color?>("tintcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var tintColor = element.GetOptionalPropertyParseable<Color>("tintcolor");
|
||||||
var transparentColor = element.GetOptionalPropertyParseable<Color?>("transparentcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var transparentColor = element.GetOptionalPropertyParseable<Color>("transparentcolor");
|
||||||
var visible = element.GetOptionalProperty<bool>("visible", true);
|
var visible = element.GetOptionalProperty<bool>("visible").GetValueOr(true);
|
||||||
var width = element.GetRequiredProperty<uint>("width");
|
var width = element.GetRequiredProperty<uint>("width");
|
||||||
var x = element.GetRequiredProperty<uint>("x");
|
var x = element.GetRequiredProperty<uint>("x");
|
||||||
var y = element.GetRequiredProperty<uint>("y");
|
var y = element.GetRequiredProperty<uint>("y");
|
||||||
|
|
||||||
if ((data ?? chunks) is null)
|
if (!data.HasValue && !chunks.HasValue)
|
||||||
throw new JsonException("Tile layer does not contain data.");
|
throw new JsonException("Tile layer does not contain data.");
|
||||||
|
|
||||||
return new TileLayer
|
return new TileLayer
|
||||||
|
|
|
@ -1,29 +1,31 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace DotTiled.Serialization.Tmj;
|
namespace DotTiled.Serialization.Tmj;
|
||||||
|
|
||||||
public abstract partial class TmjReaderBase
|
public abstract partial class TmjReaderBase
|
||||||
{
|
{
|
||||||
internal Tileset ReadTileset(JsonElement element)
|
internal Tileset ReadTileset(
|
||||||
|
JsonElement element,
|
||||||
|
Optional<string> parentVersion = null,
|
||||||
|
Optional<string> parentTiledVersion = null)
|
||||||
{
|
{
|
||||||
var backgroundColor = element.GetOptionalPropertyParseable<Color?>("backgroundcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var backgroundColor = element.GetOptionalPropertyParseable<Color>("backgroundcolor");
|
||||||
var @class = element.GetOptionalProperty<string>("class", "");
|
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||||
var columns = element.GetOptionalProperty<uint?>("columns", null);
|
var columns = element.GetOptionalProperty<uint>("columns");
|
||||||
var fillMode = element.GetOptionalPropertyParseable<FillMode>("fillmode", s => s switch
|
var fillMode = element.GetOptionalPropertyParseable<FillMode>("fillmode", s => s switch
|
||||||
{
|
{
|
||||||
"stretch" => FillMode.Stretch,
|
"stretch" => FillMode.Stretch,
|
||||||
"preserve-aspect-fit" => FillMode.PreserveAspectFit,
|
"preserve-aspect-fit" => FillMode.PreserveAspectFit,
|
||||||
_ => throw new JsonException($"Unknown fill mode '{s}'")
|
_ => throw new JsonException($"Unknown fill mode '{s}'")
|
||||||
}, FillMode.Stretch);
|
}).GetValueOr(FillMode.Stretch);
|
||||||
var firstGID = element.GetOptionalProperty<uint?>("firstgid", null);
|
var firstGID = element.GetOptionalProperty<uint>("firstgid");
|
||||||
var grid = element.GetOptionalPropertyCustom<Grid?>("grid", ReadGrid, null);
|
var grid = element.GetOptionalPropertyCustom<Grid>("grid", ReadGrid);
|
||||||
var image = element.GetOptionalProperty<string?>("image", null);
|
var image = element.GetOptionalProperty<string>("image");
|
||||||
var imageHeight = element.GetOptionalProperty<uint?>("imageheight", null);
|
var imageHeight = element.GetOptionalProperty<uint>("imageheight");
|
||||||
var imageWidth = element.GetOptionalProperty<uint?>("imagewidth", null);
|
var imageWidth = element.GetOptionalProperty<uint>("imagewidth");
|
||||||
var margin = element.GetOptionalProperty<uint?>("margin", null);
|
var margin = element.GetOptionalProperty<uint>("margin");
|
||||||
var name = element.GetOptionalProperty<string?>("name", null);
|
var name = element.GetOptionalProperty<string>("name");
|
||||||
var objectAlignment = element.GetOptionalPropertyParseable<ObjectAlignment>("objectalignment", s => s switch
|
var objectAlignment = element.GetOptionalPropertyParseable<ObjectAlignment>("objectalignment", s => s switch
|
||||||
{
|
{
|
||||||
"unspecified" => ObjectAlignment.Unspecified,
|
"unspecified" => ObjectAlignment.Unspecified,
|
||||||
|
@ -37,29 +39,29 @@ public abstract partial class TmjReaderBase
|
||||||
"bottom" => ObjectAlignment.Bottom,
|
"bottom" => ObjectAlignment.Bottom,
|
||||||
"bottomright" => ObjectAlignment.BottomRight,
|
"bottomright" => ObjectAlignment.BottomRight,
|
||||||
_ => throw new JsonException($"Unknown object alignment '{s}'")
|
_ => throw new JsonException($"Unknown object alignment '{s}'")
|
||||||
}, ObjectAlignment.Unspecified);
|
}).GetValueOr(ObjectAlignment.Unspecified);
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
var source = element.GetOptionalProperty<string?>("source", null);
|
var source = element.GetOptionalProperty<string>("source");
|
||||||
var spacing = element.GetOptionalProperty<uint?>("spacing", null);
|
var spacing = element.GetOptionalProperty<uint>("spacing");
|
||||||
var tileCount = element.GetOptionalProperty<uint?>("tilecount", null);
|
var tileCount = element.GetOptionalProperty<uint>("tilecount");
|
||||||
var tiledVersion = element.GetOptionalProperty<string?>("tiledversion", null);
|
var tiledVersion = element.GetOptionalProperty<string>("tiledversion").GetValueOrOptional(parentTiledVersion);
|
||||||
var tileHeight = element.GetOptionalProperty<uint?>("tileheight", null);
|
var tileHeight = element.GetOptionalProperty<uint>("tileheight");
|
||||||
var tileOffset = element.GetOptionalPropertyCustom<TileOffset?>("tileoffset", ReadTileOffset, null);
|
var tileOffset = element.GetOptionalPropertyCustom<TileOffset>("tileoffset", ReadTileOffset);
|
||||||
var tileRenderSize = element.GetOptionalPropertyParseable<TileRenderSize>("tilerendersize", s => s switch
|
var tileRenderSize = element.GetOptionalPropertyParseable<TileRenderSize>("tilerendersize", s => s switch
|
||||||
{
|
{
|
||||||
"tile" => TileRenderSize.Tile,
|
"tile" => TileRenderSize.Tile,
|
||||||
"grid" => TileRenderSize.Grid,
|
"grid" => TileRenderSize.Grid,
|
||||||
_ => throw new JsonException($"Unknown tile render size '{s}'")
|
_ => throw new JsonException($"Unknown tile render size '{s}'")
|
||||||
}, TileRenderSize.Tile);
|
}).GetValueOr(TileRenderSize.Tile);
|
||||||
var tiles = element.GetOptionalPropertyCustom<List<Tile>>("tiles", ReadTiles, []);
|
var tiles = element.GetOptionalPropertyCustom<List<Tile>>("tiles", ReadTiles).GetValueOr([]);
|
||||||
var tileWidth = element.GetOptionalProperty<uint?>("tilewidth", null);
|
var tileWidth = element.GetOptionalProperty<uint>("tilewidth");
|
||||||
var transparentColor = element.GetOptionalPropertyParseable<Color?>("transparentcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
var transparentColor = element.GetOptionalPropertyParseable<Color>("transparentcolor");
|
||||||
var type = element.GetOptionalProperty<string?>("type", null);
|
var type = element.GetOptionalProperty<string>("type");
|
||||||
var version = element.GetOptionalProperty<string?>("version", null);
|
var version = element.GetOptionalProperty<string>("version").GetValueOrOptional(parentVersion);
|
||||||
var transformations = element.GetOptionalPropertyCustom<Transformations?>("transformations", ReadTransformations, null);
|
var transformations = element.GetOptionalPropertyCustom<Transformations>("transformations", ReadTransformations);
|
||||||
var wangsets = element.GetOptionalPropertyCustom<List<Wangset>?>("wangsets", el => el.GetValueAsList<Wangset>(e => ReadWangset(e)), null);
|
var wangsets = element.GetOptionalPropertyCustom<List<Wangset>>("wangsets", el => el.GetValueAsList<Wangset>(e => ReadWangset(e))).GetValueOr([]);
|
||||||
|
|
||||||
if (source is not null)
|
if (source.HasValue)
|
||||||
{
|
{
|
||||||
var resolvedTileset = _externalTilesetResolver(source);
|
var resolvedTileset = _externalTilesetResolver(source);
|
||||||
resolvedTileset.FirstGID = firstGID;
|
resolvedTileset.FirstGID = firstGID;
|
||||||
|
@ -67,14 +69,14 @@ public abstract partial class TmjReaderBase
|
||||||
return resolvedTileset;
|
return resolvedTileset;
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageModel = image is not null ? new Image
|
Optional<Image> imageModel = image.HasValue ? new Image
|
||||||
{
|
{
|
||||||
Format = Helpers.ParseImageFormatFromSource(image),
|
Format = Helpers.ParseImageFormatFromSource(image),
|
||||||
Source = image,
|
Source = image,
|
||||||
Height = imageHeight,
|
Height = imageHeight,
|
||||||
Width = imageWidth,
|
Width = imageWidth,
|
||||||
TransparentColor = transparentColor
|
TransparentColor = transparentColor
|
||||||
} : null;
|
} : Optional<Image>.Empty;
|
||||||
|
|
||||||
return new Tileset
|
return new Tileset
|
||||||
{
|
{
|
||||||
|
@ -105,10 +107,10 @@ public abstract partial class TmjReaderBase
|
||||||
|
|
||||||
internal static Transformations ReadTransformations(JsonElement element)
|
internal static Transformations ReadTransformations(JsonElement element)
|
||||||
{
|
{
|
||||||
var hFlip = element.GetOptionalProperty<bool>("hflip", false);
|
var hFlip = element.GetOptionalProperty<bool>("hflip").GetValueOr(false);
|
||||||
var vFlip = element.GetOptionalProperty<bool>("vflip", false);
|
var vFlip = element.GetOptionalProperty<bool>("vflip").GetValueOr(false);
|
||||||
var rotate = element.GetOptionalProperty<bool>("rotate", false);
|
var rotate = element.GetOptionalProperty<bool>("rotate").GetValueOr(false);
|
||||||
var preferUntransformed = element.GetOptionalProperty<bool>("preferuntransformed", false);
|
var preferUntransformed = element.GetOptionalProperty<bool>("preferuntransformed").GetValueOr(false);
|
||||||
|
|
||||||
return new Transformations
|
return new Transformations
|
||||||
{
|
{
|
||||||
|
@ -126,7 +128,7 @@ public abstract partial class TmjReaderBase
|
||||||
"orthogonal" => GridOrientation.Orthogonal,
|
"orthogonal" => GridOrientation.Orthogonal,
|
||||||
"isometric" => GridOrientation.Isometric,
|
"isometric" => GridOrientation.Isometric,
|
||||||
_ => throw new JsonException($"Unknown grid orientation '{s}'")
|
_ => throw new JsonException($"Unknown grid orientation '{s}'")
|
||||||
}, GridOrientation.Orthogonal);
|
}).GetValueOr(GridOrientation.Orthogonal);
|
||||||
var height = element.GetRequiredProperty<uint>("height");
|
var height = element.GetRequiredProperty<uint>("height");
|
||||||
var width = element.GetRequiredProperty<uint>("width");
|
var width = element.GetRequiredProperty<uint>("width");
|
||||||
|
|
||||||
|
@ -153,28 +155,27 @@ public abstract partial class TmjReaderBase
|
||||||
internal List<Tile> ReadTiles(JsonElement element) =>
|
internal List<Tile> ReadTiles(JsonElement element) =>
|
||||||
element.GetValueAsList<Tile>(e =>
|
element.GetValueAsList<Tile>(e =>
|
||||||
{
|
{
|
||||||
var animation = e.GetOptionalPropertyCustom<List<Frame>?>("animation", e => e.GetValueAsList<Frame>(ReadFrame), null);
|
var animation = e.GetOptionalPropertyCustom<List<Frame>>("animation", e => e.GetValueAsList<Frame>(ReadFrame)).GetValueOr([]);
|
||||||
var id = e.GetRequiredProperty<uint>("id");
|
var id = e.GetRequiredProperty<uint>("id");
|
||||||
var image = e.GetOptionalProperty<string?>("image", null);
|
var image = e.GetOptionalProperty<string>("image");
|
||||||
var imageHeight = e.GetOptionalProperty<uint?>("imageheight", null);
|
var imageHeight = e.GetOptionalProperty<uint>("imageheight");
|
||||||
var imageWidth = e.GetOptionalProperty<uint?>("imagewidth", null);
|
var imageWidth = e.GetOptionalProperty<uint>("imagewidth");
|
||||||
var x = e.GetOptionalProperty<uint>("x", 0);
|
var x = e.GetOptionalProperty<uint>("x").GetValueOr(0);
|
||||||
var y = e.GetOptionalProperty<uint>("y", 0);
|
var y = e.GetOptionalProperty<uint>("y").GetValueOr(0);
|
||||||
var width = e.GetOptionalProperty<uint>("width", imageWidth ?? 0);
|
var width = e.GetOptionalProperty<uint>("width").GetValueOr(imageWidth.GetValueOr(0));
|
||||||
var height = e.GetOptionalProperty<uint>("height", imageHeight ?? 0);
|
var height = e.GetOptionalProperty<uint>("height").GetValueOr(imageHeight.GetValueOr(0));
|
||||||
var objectGroup = e.GetOptionalPropertyCustom<ObjectLayer?>("objectgroup", e => ReadObjectLayer(e), null);
|
var objectGroup = e.GetOptionalPropertyCustom<ObjectLayer>("objectgroup", e => ReadObjectLayer(e));
|
||||||
var probability = e.GetOptionalProperty<float>("probability", 0.0f);
|
var probability = e.GetOptionalProperty<float>("probability").GetValueOr(0.0f);
|
||||||
var properties = e.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = e.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
// var terrain, replaced by wangsets
|
var type = e.GetOptionalProperty<string>("type").GetValueOr("");
|
||||||
var type = e.GetOptionalProperty<string>("type", "");
|
|
||||||
|
|
||||||
var imageModel = image != null ? new Image
|
Optional<Image> imageModel = image.HasValue ? new Image
|
||||||
{
|
{
|
||||||
Format = Helpers.ParseImageFormatFromSource(image),
|
Format = Helpers.ParseImageFormatFromSource(image),
|
||||||
Source = image,
|
Source = image,
|
||||||
Height = imageHeight ?? 0,
|
Height = imageHeight ?? 0,
|
||||||
Width = imageWidth ?? 0
|
Width = imageWidth ?? 0
|
||||||
} : null;
|
} : Optional<Image>.Empty;
|
||||||
|
|
||||||
return new Tile
|
return new Tile
|
||||||
{
|
{
|
||||||
|
@ -206,13 +207,13 @@ public abstract partial class TmjReaderBase
|
||||||
|
|
||||||
internal Wangset ReadWangset(JsonElement element)
|
internal Wangset ReadWangset(JsonElement element)
|
||||||
{
|
{
|
||||||
var @clalss = element.GetOptionalProperty<string>("class", "");
|
var @clalss = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||||
var colors = element.GetOptionalPropertyCustom<List<WangColor>>("colors", e => e.GetValueAsList<WangColor>(el => ReadWangColor(el)), []);
|
var colors = element.GetOptionalPropertyCustom<List<WangColor>>("colors", e => e.GetValueAsList<WangColor>(el => ReadWangColor(el))).GetValueOr([]);
|
||||||
var name = element.GetRequiredProperty<string>("name");
|
var name = element.GetRequiredProperty<string>("name");
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
var tile = element.GetOptionalProperty<int>("tile", 0);
|
var tile = element.GetOptionalProperty<int>("tile").GetValueOr(0);
|
||||||
var type = element.GetOptionalProperty<string>("type", "");
|
var type = element.GetOptionalProperty<string>("type").GetValueOr("");
|
||||||
var wangTiles = element.GetOptionalPropertyCustom<List<WangTile>>("wangtiles", e => e.GetValueAsList<WangTile>(ReadWangTile), []);
|
var wangTiles = element.GetOptionalPropertyCustom<List<WangTile>>("wangtiles", e => e.GetValueAsList<WangTile>(ReadWangTile)).GetValueOr([]);
|
||||||
|
|
||||||
return new Wangset
|
return new Wangset
|
||||||
{
|
{
|
||||||
|
@ -227,12 +228,12 @@ public abstract partial class TmjReaderBase
|
||||||
|
|
||||||
internal WangColor ReadWangColor(JsonElement element)
|
internal WangColor ReadWangColor(JsonElement element)
|
||||||
{
|
{
|
||||||
var @class = element.GetOptionalProperty<string>("class", "");
|
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||||
var color = element.GetRequiredPropertyParseable<Color>("color", s => Color.Parse(s, CultureInfo.InvariantCulture));
|
var color = element.GetRequiredPropertyParseable<Color>("color");
|
||||||
var name = element.GetRequiredProperty<string>("name");
|
var name = element.GetRequiredProperty<string>("name");
|
||||||
var probability = element.GetOptionalProperty<float>("probability", 1.0f);
|
var probability = element.GetOptionalProperty<float>("probability").GetValueOr(1.0f);
|
||||||
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties, []);
|
var properties = element.GetOptionalPropertyCustom("properties", ReadProperties).GetValueOr([]);
|
||||||
var tile = element.GetOptionalProperty<int>("tile", 0);
|
var tile = element.GetOptionalProperty<int>("tile").GetValueOr(0);
|
||||||
|
|
||||||
return new WangColor
|
return new WangColor
|
||||||
{
|
{
|
||||||
|
@ -248,7 +249,7 @@ public abstract partial class TmjReaderBase
|
||||||
internal static WangTile ReadWangTile(JsonElement element)
|
internal static WangTile ReadWangTile(JsonElement element)
|
||||||
{
|
{
|
||||||
var tileID = element.GetRequiredProperty<uint>("tileid");
|
var tileID = element.GetRequiredProperty<uint>("tileid");
|
||||||
var wangID = element.GetOptionalPropertyCustom<List<byte>>("wangid", e => e.GetValueAsList<byte>(el => (byte)el.GetUInt32()), []);
|
var wangID = element.GetOptionalPropertyCustom<List<byte>>("wangid", e => e.GetValueAsList<byte>(el => (byte)el.GetUInt32())).GetValueOr([]);
|
||||||
|
|
||||||
return new WangTile
|
return new WangTile
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
|
||||||
|
@ -31,40 +30,43 @@ internal static class ExtensionsXmlReader
|
||||||
return enumParser(value);
|
return enumParser(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string? GetOptionalAttribute(this XmlReader reader, string attribute, string? defaultValue = default) =>
|
internal static Optional<string> GetOptionalAttribute(this XmlReader reader, string attribute)
|
||||||
reader.GetAttribute(attribute) ?? defaultValue;
|
{
|
||||||
|
var value = reader.GetAttribute(attribute);
|
||||||
|
return value is null ? new Optional<string>() : new Optional<string>(value);
|
||||||
|
}
|
||||||
|
|
||||||
internal static T? GetOptionalAttributeParseable<T>(this XmlReader reader, string attribute) where T : struct, IParsable<T>
|
internal static Optional<T> GetOptionalAttributeParseable<T>(this XmlReader reader, string attribute) where T : struct, IParsable<T>
|
||||||
{
|
{
|
||||||
var value = reader.GetAttribute(attribute);
|
var value = reader.GetAttribute(attribute);
|
||||||
if (value is null)
|
if (value is null)
|
||||||
return null;
|
return new Optional<T>();
|
||||||
|
|
||||||
return T.Parse(value, CultureInfo.InvariantCulture);
|
return T.Parse(value, CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static T? GetOptionalAttributeParseable<T>(this XmlReader reader, string attribute, Func<string, T> parser) where T : struct
|
internal static Optional<T> GetOptionalAttributeParseable<T>(this XmlReader reader, string attribute, Func<string, T> parser) where T : struct
|
||||||
{
|
{
|
||||||
var value = reader.GetAttribute(attribute);
|
var value = reader.GetAttribute(attribute);
|
||||||
if (value is null)
|
if (value is null)
|
||||||
return null;
|
return new Optional<T>();
|
||||||
|
|
||||||
return parser(value);
|
return parser(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static T? GetOptionalAttributeClass<T>(this XmlReader reader, string attribute) where T : class, IParsable<T>
|
internal static Optional<T> GetOptionalAttributeClass<T>(this XmlReader reader, string attribute) where T : class, IParsable<T>
|
||||||
{
|
{
|
||||||
var value = reader.GetAttribute(attribute);
|
var value = reader.GetAttribute(attribute);
|
||||||
if (value is null)
|
if (value is null)
|
||||||
return null;
|
return new Optional<T>();
|
||||||
|
|
||||||
return T.Parse(value, CultureInfo.InvariantCulture);
|
return T.Parse(value, CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static T? GetOptionalAttributeEnum<T>(this XmlReader reader, string attribute, Func<string, T> enumParser) where T : struct, Enum
|
internal static Optional<T> GetOptionalAttributeEnum<T>(this XmlReader reader, string attribute, Func<string, T> enumParser) where T : struct, Enum
|
||||||
{
|
{
|
||||||
var value = reader.GetAttribute(attribute);
|
var value = reader.GetAttribute(attribute);
|
||||||
return value != null ? enumParser(value) : null;
|
return value != null ? enumParser(value) : new Optional<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static List<T> ReadList<T>(this XmlReader reader, string wrapper, string elementName, Func<XmlReader, T> readElement)
|
internal static List<T> ReadList<T>(this XmlReader reader, string wrapper, string elementName, Func<XmlReader, T> readElement)
|
||||||
|
@ -107,7 +109,6 @@ internal static class ExtensionsXmlReader
|
||||||
reader.ReadEndElement();
|
reader.ReadEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
[return: NotNull]
|
|
||||||
internal static List<T> ProcessChildren<T>(this XmlReader reader, string wrapper, Func<XmlReader, string, T> getProcessAction)
|
internal static List<T> ProcessChildren<T>(this XmlReader reader, string wrapper, Func<XmlReader, string, T> getProcessAction)
|
||||||
{
|
{
|
||||||
var list = new List<T>();
|
var list = new List<T>();
|
||||||
|
|
|
@ -2,14 +2,14 @@ namespace DotTiled.Serialization.Tmx;
|
||||||
|
|
||||||
public abstract partial class TmxReaderBase
|
public abstract partial class TmxReaderBase
|
||||||
{
|
{
|
||||||
internal Chunk ReadChunk(DataEncoding? encoding, DataCompression? compression)
|
internal Chunk ReadChunk(Optional<DataEncoding> encoding, Optional<DataCompression> compression)
|
||||||
{
|
{
|
||||||
var x = _reader.GetRequiredAttributeParseable<int>("x");
|
var x = _reader.GetRequiredAttributeParseable<int>("x");
|
||||||
var y = _reader.GetRequiredAttributeParseable<int>("y");
|
var y = _reader.GetRequiredAttributeParseable<int>("y");
|
||||||
var width = _reader.GetRequiredAttributeParseable<uint>("width");
|
var width = _reader.GetRequiredAttributeParseable<uint>("width");
|
||||||
var height = _reader.GetRequiredAttributeParseable<uint>("height");
|
var height = _reader.GetRequiredAttributeParseable<uint>("height");
|
||||||
|
|
||||||
var usesTileChildrenInsteadOfRawData = encoding is null;
|
var usesTileChildrenInsteadOfRawData = !encoding.HasValue;
|
||||||
if (usesTileChildrenInsteadOfRawData)
|
if (usesTileChildrenInsteadOfRawData)
|
||||||
{
|
{
|
||||||
var globalTileIDsWithFlippingFlags = ReadTileChildrenInWrapper("chunk", _reader);
|
var globalTileIDsWithFlippingFlags = ReadTileChildrenInWrapper("chunk", _reader);
|
||||||
|
@ -18,7 +18,7 @@ public abstract partial class TmxReaderBase
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var globalTileIDsWithFlippingFlags = ReadRawData(_reader, encoding!.Value, compression);
|
var globalTileIDsWithFlippingFlags = ReadRawData(_reader, encoding.Value, compression);
|
||||||
var (globalTileIDs, flippingFlags) = ReadAndClearFlippingFlagsFromGIDs(globalTileIDsWithFlippingFlags);
|
var (globalTileIDs, flippingFlags) = ReadAndClearFlippingFlagsFromGIDs(globalTileIDsWithFlippingFlags);
|
||||||
return new Chunk { X = x, Y = y, Width = width, Height = height, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags };
|
return new Chunk { X = x, Y = y, Width = width, Height = height, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags };
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,20 +30,20 @@ public abstract partial class TmxReaderBase
|
||||||
var chunks = _reader
|
var chunks = _reader
|
||||||
.ReadList("data", "chunk", (r) => ReadChunk(encoding, compression))
|
.ReadList("data", "chunk", (r) => ReadChunk(encoding, compression))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = null, Chunks = chunks };
|
return new Data { Encoding = encoding, Compression = compression, Chunks = chunks };
|
||||||
}
|
}
|
||||||
|
|
||||||
var usesTileChildrenInsteadOfRawData = encoding is null && compression is null;
|
var usesTileChildrenInsteadOfRawData = !encoding.HasValue && !compression.HasValue;
|
||||||
if (usesTileChildrenInsteadOfRawData)
|
if (usesTileChildrenInsteadOfRawData)
|
||||||
{
|
{
|
||||||
var tileChildrenGlobalTileIDsWithFlippingFlags = ReadTileChildrenInWrapper("data", _reader);
|
var tileChildrenGlobalTileIDsWithFlippingFlags = ReadTileChildrenInWrapper("data", _reader);
|
||||||
var (tileChildrenGlobalTileIDs, tileChildrenFlippingFlags) = ReadAndClearFlippingFlagsFromGIDs(tileChildrenGlobalTileIDsWithFlippingFlags);
|
var (tileChildrenGlobalTileIDs, tileChildrenFlippingFlags) = ReadAndClearFlippingFlagsFromGIDs(tileChildrenGlobalTileIDsWithFlippingFlags);
|
||||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = tileChildrenGlobalTileIDs, FlippingFlags = tileChildrenFlippingFlags, Chunks = null };
|
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = tileChildrenGlobalTileIDs, FlippingFlags = tileChildrenFlippingFlags };
|
||||||
}
|
}
|
||||||
|
|
||||||
var rawDataGlobalTileIDsWithFlippingFlags = ReadRawData(_reader, encoding!.Value, compression);
|
var rawDataGlobalTileIDsWithFlippingFlags = ReadRawData(_reader, encoding, compression);
|
||||||
var (rawDataGlobalTileIDs, rawDataFlippingFlags) = ReadAndClearFlippingFlagsFromGIDs(rawDataGlobalTileIDsWithFlippingFlags);
|
var (rawDataGlobalTileIDs, rawDataFlippingFlags) = ReadAndClearFlippingFlagsFromGIDs(rawDataGlobalTileIDsWithFlippingFlags);
|
||||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = rawDataGlobalTileIDs, FlippingFlags = rawDataFlippingFlags, Chunks = null };
|
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = rawDataGlobalTileIDs, FlippingFlags = rawDataFlippingFlags };
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static (uint[] GlobalTileIDs, FlippingFlags[] FlippingFlags) ReadAndClearFlippingFlagsFromGIDs(uint[] globalTileIDs)
|
internal static (uint[] GlobalTileIDs, FlippingFlags[] FlippingFlags) ReadAndClearFlippingFlagsFromGIDs(uint[] globalTileIDs)
|
||||||
|
@ -62,19 +62,19 @@ public abstract partial class TmxReaderBase
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static uint[] ReadTileChildrenInWrapper(string wrapper, XmlReader reader) =>
|
internal static uint[] ReadTileChildrenInWrapper(string wrapper, XmlReader reader) =>
|
||||||
reader.ReadList(wrapper, "tile", (r) => r.GetOptionalAttributeParseable<uint>("gid") ?? 0).ToArray();
|
reader.ReadList(wrapper, "tile", (r) => r.GetOptionalAttributeParseable<uint>("gid").GetValueOr(0)).ToArray();
|
||||||
|
|
||||||
internal static uint[] ReadRawData(XmlReader reader, DataEncoding encoding, DataCompression? compression)
|
internal static uint[] ReadRawData(XmlReader reader, DataEncoding encoding, Optional<DataCompression> compression)
|
||||||
{
|
{
|
||||||
var data = reader.ReadElementContentAsString();
|
var data = reader.ReadElementContentAsString();
|
||||||
if (encoding == DataEncoding.Csv)
|
if (encoding == DataEncoding.Csv)
|
||||||
return ParseCsvData(data);
|
return ParseCsvData(data);
|
||||||
|
|
||||||
using var bytes = new MemoryStream(Convert.FromBase64String(data));
|
using var bytes = new MemoryStream(Convert.FromBase64String(data));
|
||||||
if (compression is null)
|
if (!compression.HasValue)
|
||||||
return ReadMemoryStreamAsInt32Array(bytes);
|
return ReadMemoryStreamAsInt32Array(bytes);
|
||||||
|
|
||||||
var decompressed = compression switch
|
var decompressed = compression.Value switch
|
||||||
{
|
{
|
||||||
DataCompression.GZip => DecompressGZip(bytes),
|
DataCompression.GZip => DecompressGZip(bytes),
|
||||||
DataCompression.ZLib => DecompressZLib(bytes),
|
DataCompression.ZLib => DecompressZLib(bytes),
|
||||||
|
|
|
@ -13,16 +13,15 @@ public abstract partial class TmxReaderBase
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var version = _reader.GetRequiredAttribute("version");
|
var version = _reader.GetRequiredAttribute("version");
|
||||||
var tiledVersion = _reader.GetRequiredAttribute("tiledversion");
|
var tiledVersion = _reader.GetOptionalAttribute("tiledversion");
|
||||||
var @class = _reader.GetOptionalAttribute("class") ?? "";
|
var @class = _reader.GetOptionalAttribute("class").GetValueOr("");
|
||||||
var orientation = _reader.GetRequiredAttributeEnum<MapOrientation>("orientation", s => s switch
|
var orientation = _reader.GetRequiredAttributeEnum<MapOrientation>("orientation", Helpers.CreateMapper<MapOrientation>(
|
||||||
{
|
s => throw new InvalidOperationException($"Unknown orientation '{s}'"),
|
||||||
"orthogonal" => MapOrientation.Orthogonal,
|
("orthogonal", MapOrientation.Orthogonal),
|
||||||
"isometric" => MapOrientation.Isometric,
|
("isometric", MapOrientation.Isometric),
|
||||||
"staggered" => MapOrientation.Staggered,
|
("staggered", MapOrientation.Staggered),
|
||||||
"hexagonal" => MapOrientation.Hexagonal,
|
("hexagonal", MapOrientation.Hexagonal)
|
||||||
_ => throw new InvalidOperationException($"Unknown orientation '{s}'")
|
));
|
||||||
});
|
|
||||||
var renderOrder = _reader.GetOptionalAttributeEnum<RenderOrder>("renderorder", s => s switch
|
var renderOrder = _reader.GetOptionalAttributeEnum<RenderOrder>("renderorder", s => s switch
|
||||||
{
|
{
|
||||||
"right-down" => RenderOrder.RightDown,
|
"right-down" => RenderOrder.RightDown,
|
||||||
|
@ -30,8 +29,8 @@ public abstract partial class TmxReaderBase
|
||||||
"left-down" => RenderOrder.LeftDown,
|
"left-down" => RenderOrder.LeftDown,
|
||||||
"left-up" => RenderOrder.LeftUp,
|
"left-up" => RenderOrder.LeftUp,
|
||||||
_ => throw new InvalidOperationException($"Unknown render order '{s}'")
|
_ => throw new InvalidOperationException($"Unknown render order '{s}'")
|
||||||
}) ?? RenderOrder.RightDown;
|
}).GetValueOr(RenderOrder.RightDown);
|
||||||
var compressionLevel = _reader.GetOptionalAttributeParseable<int>("compressionlevel") ?? -1;
|
var compressionLevel = _reader.GetOptionalAttributeParseable<int>("compressionlevel").GetValueOr(-1);
|
||||||
var width = _reader.GetRequiredAttributeParseable<uint>("width");
|
var width = _reader.GetRequiredAttributeParseable<uint>("width");
|
||||||
var height = _reader.GetRequiredAttributeParseable<uint>("height");
|
var height = _reader.GetRequiredAttributeParseable<uint>("height");
|
||||||
var tileWidth = _reader.GetRequiredAttributeParseable<uint>("tilewidth");
|
var tileWidth = _reader.GetRequiredAttributeParseable<uint>("tilewidth");
|
||||||
|
@ -49,15 +48,15 @@ public abstract partial class TmxReaderBase
|
||||||
"even" => StaggerIndex.Even,
|
"even" => StaggerIndex.Even,
|
||||||
_ => throw new InvalidOperationException($"Unknown stagger index '{s}'")
|
_ => throw new InvalidOperationException($"Unknown stagger index '{s}'")
|
||||||
});
|
});
|
||||||
var parallaxOriginX = _reader.GetOptionalAttributeParseable<float>("parallaxoriginx") ?? 0.0f;
|
var parallaxOriginX = _reader.GetOptionalAttributeParseable<float>("parallaxoriginx").GetValueOr(0.0f);
|
||||||
var parallaxOriginY = _reader.GetOptionalAttributeParseable<float>("parallaxoriginy") ?? 0.0f;
|
var parallaxOriginY = _reader.GetOptionalAttributeParseable<float>("parallaxoriginy").GetValueOr(0.0f);
|
||||||
var backgroundColor = _reader.GetOptionalAttributeClass<Color>("backgroundcolor") ?? Color.Parse("#00000000", CultureInfo.InvariantCulture);
|
var backgroundColor = _reader.GetOptionalAttributeClass<Color>("backgroundcolor").GetValueOr(Color.Parse("#00000000", CultureInfo.InvariantCulture));
|
||||||
var nextLayerID = _reader.GetRequiredAttributeParseable<uint>("nextlayerid");
|
var nextLayerID = _reader.GetRequiredAttributeParseable<uint>("nextlayerid");
|
||||||
var nextObjectID = _reader.GetRequiredAttributeParseable<uint>("nextobjectid");
|
var nextObjectID = _reader.GetRequiredAttributeParseable<uint>("nextobjectid");
|
||||||
var infinite = (_reader.GetOptionalAttributeParseable<uint>("infinite") ?? 0) == 1;
|
var infinite = _reader.GetOptionalAttributeParseable<uint>("infinite").GetValueOr(0) == 1;
|
||||||
|
|
||||||
// At most one of
|
// At most one of
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
|
|
||||||
// Any number of
|
// Any number of
|
||||||
List<BaseLayer> layers = [];
|
List<BaseLayer> layers = [];
|
||||||
|
@ -66,7 +65,7 @@ public abstract partial class TmxReaderBase
|
||||||
_reader.ProcessChildren("map", (r, elementName) => elementName switch
|
_reader.ProcessChildren("map", (r, elementName) => elementName switch
|
||||||
{
|
{
|
||||||
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
|
"properties" => () => Helpers.SetAtMostOnce(ref properties, ReadProperties(), "Properties"),
|
||||||
"tileset" => () => tilesets.Add(ReadTileset()),
|
"tileset" => () => tilesets.Add(ReadTileset(version, tiledVersion)),
|
||||||
"layer" => () => layers.Add(ReadTileLayer(infinite)),
|
"layer" => () => layers.Add(ReadTileLayer(infinite)),
|
||||||
"objectgroup" => () => layers.Add(ReadObjectLayer()),
|
"objectgroup" => () => layers.Add(ReadObjectLayer()),
|
||||||
"imagelayer" => () => layers.Add(ReadImageLayer()),
|
"imagelayer" => () => layers.Add(ReadImageLayer()),
|
||||||
|
|
|
@ -12,29 +12,29 @@ public abstract partial class TmxReaderBase
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
||||||
var name = _reader.GetOptionalAttribute("name") ?? "";
|
var name = _reader.GetOptionalAttribute("name").GetValueOr("");
|
||||||
var @class = _reader.GetOptionalAttribute("class") ?? "";
|
var @class = _reader.GetOptionalAttribute("class").GetValueOr("");
|
||||||
var x = _reader.GetOptionalAttributeParseable<uint>("x") ?? 0;
|
var x = _reader.GetOptionalAttributeParseable<uint>("x").GetValueOr(0);
|
||||||
var y = _reader.GetOptionalAttributeParseable<uint>("y") ?? 0;
|
var y = _reader.GetOptionalAttributeParseable<uint>("y").GetValueOr(0);
|
||||||
var width = _reader.GetOptionalAttributeParseable<uint>("width");
|
var width = _reader.GetOptionalAttributeParseable<uint>("width").GetValueOr(0);
|
||||||
var height = _reader.GetOptionalAttributeParseable<uint>("height");
|
var height = _reader.GetOptionalAttributeParseable<uint>("height").GetValueOr(0);
|
||||||
var opacity = _reader.GetOptionalAttributeParseable<float>("opacity") ?? 1.0f;
|
var opacity = _reader.GetOptionalAttributeParseable<float>("opacity").GetValueOr(1.0f);
|
||||||
var visible = (_reader.GetOptionalAttributeParseable<uint>("visible") ?? 1) == 1;
|
var visible = _reader.GetOptionalAttributeParseable<uint>("visible").GetValueOr(1) == 1;
|
||||||
var tintColor = _reader.GetOptionalAttributeClass<Color>("tintcolor");
|
var tintColor = _reader.GetOptionalAttributeClass<Color>("tintcolor");
|
||||||
var offsetX = _reader.GetOptionalAttributeParseable<float>("offsetx") ?? 0.0f;
|
var offsetX = _reader.GetOptionalAttributeParseable<float>("offsetx").GetValueOr(0.0f);
|
||||||
var offsetY = _reader.GetOptionalAttributeParseable<float>("offsety") ?? 0.0f;
|
var offsetY = _reader.GetOptionalAttributeParseable<float>("offsety").GetValueOr(0.0f);
|
||||||
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx") ?? 1.0f;
|
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx").GetValueOr(1.0f);
|
||||||
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy") ?? 1.0f;
|
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy").GetValueOr(1.0f);
|
||||||
var color = _reader.GetOptionalAttributeClass<Color>("color");
|
var color = _reader.GetOptionalAttributeClass<Color>("color");
|
||||||
var drawOrder = _reader.GetOptionalAttributeEnum<DrawOrder>("draworder", s => s switch
|
var drawOrder = _reader.GetOptionalAttributeEnum<DrawOrder>("draworder", s => s switch
|
||||||
{
|
{
|
||||||
"topdown" => DrawOrder.TopDown,
|
"topdown" => DrawOrder.TopDown,
|
||||||
"index" => DrawOrder.Index,
|
"index" => DrawOrder.Index,
|
||||||
_ => throw new InvalidOperationException($"Unknown draw order '{s}'")
|
_ => throw new InvalidOperationException($"Unknown draw order '{s}'")
|
||||||
}) ?? DrawOrder.TopDown;
|
}).GetValueOr(DrawOrder.TopDown);
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
List<DotTiled.Object> objects = [];
|
List<DotTiled.Object> objects = [];
|
||||||
|
|
||||||
_reader.ProcessChildren("objectgroup", (r, elementName) => elementName switch
|
_reader.ProcessChildren("objectgroup", (r, elementName) => elementName switch
|
||||||
|
@ -71,11 +71,11 @@ public abstract partial class TmxReaderBase
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var template = _reader.GetOptionalAttribute("template");
|
var template = _reader.GetOptionalAttribute("template");
|
||||||
DotTiled.Object? obj = null;
|
DotTiled.Object obj = null;
|
||||||
if (template is not null)
|
if (template.HasValue)
|
||||||
obj = _externalTemplateResolver(template).Object;
|
obj = _externalTemplateResolver(template).Object;
|
||||||
|
|
||||||
uint? idDefault = obj?.ID ?? null;
|
uint idDefault = obj?.ID.GetValueOr(0) ?? 0;
|
||||||
string nameDefault = obj?.Name ?? "";
|
string nameDefault = obj?.Name ?? "";
|
||||||
string typeDefault = obj?.Type ?? "";
|
string typeDefault = obj?.Type ?? "";
|
||||||
float xDefault = obj?.X ?? 0f;
|
float xDefault = obj?.X ?? 0f;
|
||||||
|
@ -83,25 +83,25 @@ public abstract partial class TmxReaderBase
|
||||||
float widthDefault = obj?.Width ?? 0f;
|
float widthDefault = obj?.Width ?? 0f;
|
||||||
float heightDefault = obj?.Height ?? 0f;
|
float heightDefault = obj?.Height ?? 0f;
|
||||||
float rotationDefault = obj?.Rotation ?? 0f;
|
float rotationDefault = obj?.Rotation ?? 0f;
|
||||||
uint? gidDefault = obj is TileObject tileObj ? tileObj.GID : null;
|
Optional<uint> gidDefault = obj is TileObject tileObj ? tileObj.GID : Optional<uint>.Empty;
|
||||||
bool visibleDefault = obj?.Visible ?? true;
|
bool visibleDefault = obj?.Visible ?? true;
|
||||||
List<IProperty>? propertiesDefault = obj?.Properties ?? null;
|
List<IProperty> propertiesDefault = obj?.Properties ?? null;
|
||||||
|
|
||||||
var id = _reader.GetOptionalAttributeParseable<uint>("id") ?? idDefault;
|
var id = _reader.GetOptionalAttributeParseable<uint>("id").GetValueOr(idDefault);
|
||||||
var name = _reader.GetOptionalAttribute("name") ?? nameDefault;
|
var name = _reader.GetOptionalAttribute("name").GetValueOr(nameDefault);
|
||||||
var type = _reader.GetOptionalAttribute("type") ?? typeDefault;
|
var type = _reader.GetOptionalAttribute("type").GetValueOr(typeDefault);
|
||||||
var x = _reader.GetOptionalAttributeParseable<float>("x") ?? xDefault;
|
var x = _reader.GetOptionalAttributeParseable<float>("x").GetValueOr(xDefault);
|
||||||
var y = _reader.GetOptionalAttributeParseable<float>("y") ?? yDefault;
|
var y = _reader.GetOptionalAttributeParseable<float>("y").GetValueOr(yDefault);
|
||||||
var width = _reader.GetOptionalAttributeParseable<float>("width") ?? widthDefault;
|
var width = _reader.GetOptionalAttributeParseable<float>("width").GetValueOr(widthDefault);
|
||||||
var height = _reader.GetOptionalAttributeParseable<float>("height") ?? heightDefault;
|
var height = _reader.GetOptionalAttributeParseable<float>("height").GetValueOr(heightDefault);
|
||||||
var rotation = _reader.GetOptionalAttributeParseable<float>("rotation") ?? rotationDefault;
|
var rotation = _reader.GetOptionalAttributeParseable<float>("rotation").GetValueOr(rotationDefault);
|
||||||
var gid = _reader.GetOptionalAttributeParseable<uint>("gid") ?? gidDefault;
|
var gid = _reader.GetOptionalAttributeParseable<uint>("gid").GetValueOrOptional(gidDefault);
|
||||||
var visible = _reader.GetOptionalAttributeParseable<bool>("visible") ?? visibleDefault;
|
var visible = _reader.GetOptionalAttributeParseable<bool>("visible").GetValueOr(visibleDefault);
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
DotTiled.Object? foundObject = null;
|
DotTiled.Object foundObject = null;
|
||||||
int propertiesCounter = 0;
|
int propertiesCounter = 0;
|
||||||
List<IProperty>? properties = propertiesDefault;
|
List<IProperty> properties = propertiesDefault;
|
||||||
|
|
||||||
_reader.ProcessChildren("object", (r, elementName) => elementName switch
|
_reader.ProcessChildren("object", (r, elementName) => elementName switch
|
||||||
{
|
{
|
||||||
|
@ -116,7 +116,7 @@ public abstract partial class TmxReaderBase
|
||||||
|
|
||||||
if (foundObject is null)
|
if (foundObject is null)
|
||||||
{
|
{
|
||||||
if (gid is not null)
|
if (gid.HasValue)
|
||||||
foundObject = new TileObject { ID = id, GID = gid.Value };
|
foundObject = new TileObject { ID = id, GID = gid.Value };
|
||||||
else
|
else
|
||||||
foundObject = new RectangleObject { ID = id };
|
foundObject = new RectangleObject { ID = id };
|
||||||
|
@ -137,7 +137,7 @@ public abstract partial class TmxReaderBase
|
||||||
return OverrideObject(obj, foundObject);
|
return OverrideObject(obj, foundObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static DotTiled.Object OverrideObject(DotTiled.Object? obj, DotTiled.Object foundObject)
|
internal static DotTiled.Object OverrideObject(DotTiled.Object obj, DotTiled.Object foundObject)
|
||||||
{
|
{
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return foundObject;
|
return foundObject;
|
||||||
|
@ -301,10 +301,10 @@ public abstract partial class TmxReaderBase
|
||||||
// No attributes
|
// No attributes
|
||||||
|
|
||||||
// At most one of
|
// At most one of
|
||||||
Tileset? tileset = null;
|
Tileset tileset = null;
|
||||||
|
|
||||||
// Should contain exactly one of
|
// Should contain exactly one of
|
||||||
DotTiled.Object? obj = null;
|
DotTiled.Object obj = null;
|
||||||
|
|
||||||
_reader.ProcessChildren("template", (r, elementName) => elementName switch
|
_reader.ProcessChildren("template", (r, elementName) => elementName switch
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,9 +25,9 @@ public abstract partial class TmxReaderBase
|
||||||
"object" => PropertyType.Object,
|
"object" => PropertyType.Object,
|
||||||
"class" => PropertyType.Class,
|
"class" => PropertyType.Class,
|
||||||
_ => throw new XmlException("Invalid property type")
|
_ => throw new XmlException("Invalid property type")
|
||||||
}) ?? PropertyType.String;
|
}).GetValueOr(PropertyType.String);
|
||||||
var propertyType = r.GetOptionalAttribute("propertytype");
|
var propertyType = r.GetOptionalAttribute("propertytype");
|
||||||
if (propertyType is not null)
|
if (propertyType.HasValue)
|
||||||
{
|
{
|
||||||
return ReadPropertyWithCustomType();
|
return ReadPropertyWithCustomType();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace DotTiled.Serialization.Tmx;
|
namespace DotTiled.Serialization.Tmx;
|
||||||
|
|
||||||
|
@ -8,22 +7,22 @@ public abstract partial class TmxReaderBase
|
||||||
internal TileLayer ReadTileLayer(bool dataUsesChunks)
|
internal TileLayer ReadTileLayer(bool dataUsesChunks)
|
||||||
{
|
{
|
||||||
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
||||||
var name = _reader.GetOptionalAttribute("name") ?? "";
|
var name = _reader.GetOptionalAttribute("name").GetValueOr("");
|
||||||
var @class = _reader.GetOptionalAttribute("class") ?? "";
|
var @class = _reader.GetOptionalAttribute("class").GetValueOr("");
|
||||||
var x = _reader.GetOptionalAttributeParseable<uint>("x") ?? 0;
|
var x = _reader.GetOptionalAttributeParseable<uint>("x").GetValueOr(0);
|
||||||
var y = _reader.GetOptionalAttributeParseable<uint>("y") ?? 0;
|
var y = _reader.GetOptionalAttributeParseable<uint>("y").GetValueOr(0);
|
||||||
var width = _reader.GetRequiredAttributeParseable<uint>("width");
|
var width = _reader.GetRequiredAttributeParseable<uint>("width");
|
||||||
var height = _reader.GetRequiredAttributeParseable<uint>("height");
|
var height = _reader.GetRequiredAttributeParseable<uint>("height");
|
||||||
var opacity = _reader.GetOptionalAttributeParseable<float>("opacity") ?? 1.0f;
|
var opacity = _reader.GetOptionalAttributeParseable<float>("opacity").GetValueOr(1.0f);
|
||||||
var visible = (_reader.GetOptionalAttributeParseable<uint>("visible") ?? 1) == 1;
|
var visible = _reader.GetOptionalAttributeParseable<uint>("visible").GetValueOr(1) == 1;
|
||||||
var tintColor = _reader.GetOptionalAttributeClass<Color>("tintcolor");
|
var tintColor = _reader.GetOptionalAttributeClass<Color>("tintcolor");
|
||||||
var offsetX = _reader.GetOptionalAttributeParseable<float>("offsetx") ?? 0.0f;
|
var offsetX = _reader.GetOptionalAttributeParseable<float>("offsetx").GetValueOr(0.0f);
|
||||||
var offsetY = _reader.GetOptionalAttributeParseable<float>("offsety") ?? 0.0f;
|
var offsetY = _reader.GetOptionalAttributeParseable<float>("offsety").GetValueOr(0.0f);
|
||||||
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx") ?? 1.0f;
|
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx").GetValueOr(1.0f);
|
||||||
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy") ?? 1.0f;
|
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy").GetValueOr(1.0f);
|
||||||
|
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
Data? data = null;
|
Data data = null;
|
||||||
|
|
||||||
_reader.ProcessChildren("layer", (r, elementName) => elementName switch
|
_reader.ProcessChildren("layer", (r, elementName) => elementName switch
|
||||||
{
|
{
|
||||||
|
@ -48,7 +47,7 @@ public abstract partial class TmxReaderBase
|
||||||
OffsetY = offsetY,
|
OffsetY = offsetY,
|
||||||
ParallaxX = parallaxX,
|
ParallaxX = parallaxX,
|
||||||
ParallaxY = parallaxY,
|
ParallaxY = parallaxY,
|
||||||
Data = data,
|
Data = data ?? Optional<Data>.Empty,
|
||||||
Properties = properties ?? []
|
Properties = properties ?? []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -56,22 +55,22 @@ public abstract partial class TmxReaderBase
|
||||||
internal ImageLayer ReadImageLayer()
|
internal ImageLayer ReadImageLayer()
|
||||||
{
|
{
|
||||||
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
||||||
var name = _reader.GetOptionalAttribute("name") ?? "";
|
var name = _reader.GetOptionalAttribute("name").GetValueOr("");
|
||||||
var @class = _reader.GetOptionalAttribute("class") ?? "";
|
var @class = _reader.GetOptionalAttribute("class").GetValueOr("");
|
||||||
var x = _reader.GetOptionalAttributeParseable<uint>("x") ?? 0;
|
var x = _reader.GetOptionalAttributeParseable<uint>("x").GetValueOr(0);
|
||||||
var y = _reader.GetOptionalAttributeParseable<uint>("y") ?? 0;
|
var y = _reader.GetOptionalAttributeParseable<uint>("y").GetValueOr(0);
|
||||||
var opacity = _reader.GetOptionalAttributeParseable<float>("opacity") ?? 1.0f;
|
var opacity = _reader.GetOptionalAttributeParseable<float>("opacity").GetValueOr(1f);
|
||||||
var visible = _reader.GetOptionalAttributeParseable<bool>("visible") ?? true;
|
var visible = _reader.GetOptionalAttributeParseable<bool>("visible").GetValueOr(true);
|
||||||
var tintColor = _reader.GetOptionalAttributeClass<Color>("tintcolor");
|
var tintColor = _reader.GetOptionalAttributeClass<Color>("tintcolor");
|
||||||
var offsetX = _reader.GetOptionalAttributeParseable<float>("offsetx") ?? 0.0f;
|
var offsetX = _reader.GetOptionalAttributeParseable<float>("offsetx").GetValueOr(0.0f);
|
||||||
var offsetY = _reader.GetOptionalAttributeParseable<float>("offsety") ?? 0.0f;
|
var offsetY = _reader.GetOptionalAttributeParseable<float>("offsety").GetValueOr(0.0f);
|
||||||
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx") ?? 1.0f;
|
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx").GetValueOr(1.0f);
|
||||||
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy") ?? 1.0f;
|
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy").GetValueOr(1.0f);
|
||||||
var repeatX = (_reader.GetOptionalAttributeParseable<uint>("repeatx") ?? 0) == 1;
|
var repeatX = _reader.GetOptionalAttributeParseable<uint>("repeatx").GetValueOr(0) == 1;
|
||||||
var repeatY = (_reader.GetOptionalAttributeParseable<uint>("repeaty") ?? 0) == 1;
|
var repeatY = _reader.GetOptionalAttributeParseable<uint>("repeaty").GetValueOr(0) == 1;
|
||||||
|
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
Image? image = null;
|
Image image = null;
|
||||||
|
|
||||||
_reader.ProcessChildren("imagelayer", (r, elementName) => elementName switch
|
_reader.ProcessChildren("imagelayer", (r, elementName) => elementName switch
|
||||||
{
|
{
|
||||||
|
@ -104,17 +103,17 @@ public abstract partial class TmxReaderBase
|
||||||
internal Group ReadGroup()
|
internal Group ReadGroup()
|
||||||
{
|
{
|
||||||
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
||||||
var name = _reader.GetOptionalAttribute("name") ?? "";
|
var name = _reader.GetOptionalAttribute("name").GetValueOr("");
|
||||||
var @class = _reader.GetOptionalAttribute("class") ?? "";
|
var @class = _reader.GetOptionalAttribute("class").GetValueOr("");
|
||||||
var opacity = _reader.GetOptionalAttributeParseable<float>("opacity") ?? 1.0f;
|
var opacity = _reader.GetOptionalAttributeParseable<float>("opacity").GetValueOr(1.0f);
|
||||||
var visible = (_reader.GetOptionalAttributeParseable<uint>("visible") ?? 1) == 1;
|
var visible = _reader.GetOptionalAttributeParseable<uint>("visible").GetValueOr(1) == 1;
|
||||||
var tintColor = _reader.GetOptionalAttributeClass<Color>("tintcolor");
|
var tintColor = _reader.GetOptionalAttributeClass<Color>("tintcolor");
|
||||||
var offsetX = _reader.GetOptionalAttributeParseable<float>("offsetx") ?? 0.0f;
|
var offsetX = _reader.GetOptionalAttributeParseable<float>("offsetx").GetValueOr(0f);
|
||||||
var offsetY = _reader.GetOptionalAttributeParseable<float>("offsety") ?? 0.0f;
|
var offsetY = _reader.GetOptionalAttributeParseable<float>("offsety").GetValueOr(0f);
|
||||||
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx") ?? 1.0f;
|
var parallaxX = _reader.GetOptionalAttributeParseable<float>("parallaxx").GetValueOr(1f);
|
||||||
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy") ?? 1.0f;
|
var parallaxY = _reader.GetOptionalAttributeParseable<float>("parallaxy").GetValueOr(1f);
|
||||||
|
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
List<BaseLayer> layers = [];
|
List<BaseLayer> layers = [];
|
||||||
|
|
||||||
_reader.ProcessChildren("group", (r, elementName) => elementName switch
|
_reader.ProcessChildren("group", (r, elementName) => elementName switch
|
||||||
|
|
|
@ -7,21 +7,36 @@ namespace DotTiled.Serialization.Tmx;
|
||||||
|
|
||||||
public abstract partial class TmxReaderBase
|
public abstract partial class TmxReaderBase
|
||||||
{
|
{
|
||||||
internal Tileset ReadTileset()
|
internal Tileset ReadTileset(
|
||||||
|
Optional<string> parentVersion = null,
|
||||||
|
Optional<string> parentTiledVersion = null)
|
||||||
{
|
{
|
||||||
// Attributes
|
|
||||||
var version = _reader.GetOptionalAttribute("version");
|
|
||||||
var tiledVersion = _reader.GetOptionalAttribute("tiledversion");
|
|
||||||
var firstGID = _reader.GetOptionalAttributeParseable<uint>("firstgid");
|
var firstGID = _reader.GetOptionalAttributeParseable<uint>("firstgid");
|
||||||
var source = _reader.GetOptionalAttribute("source");
|
var source = _reader.GetOptionalAttribute("source");
|
||||||
var name = _reader.GetOptionalAttribute("name");
|
|
||||||
var @class = _reader.GetOptionalAttribute("class") ?? "";
|
// Check if external tileset
|
||||||
var tileWidth = _reader.GetOptionalAttributeParseable<uint>("tilewidth");
|
if (source.HasValue && firstGID.HasValue)
|
||||||
var tileHeight = _reader.GetOptionalAttributeParseable<uint>("tileheight");
|
{
|
||||||
var spacing = _reader.GetOptionalAttributeParseable<uint>("spacing") ?? 0;
|
// Is external tileset
|
||||||
var margin = _reader.GetOptionalAttributeParseable<uint>("margin") ?? 0;
|
var externalTileset = _externalTilesetResolver(source);
|
||||||
var tileCount = _reader.GetOptionalAttributeParseable<uint>("tilecount");
|
externalTileset.FirstGID = firstGID;
|
||||||
var columns = _reader.GetOptionalAttributeParseable<uint>("columns");
|
externalTileset.Source = source;
|
||||||
|
|
||||||
|
_reader.ProcessChildren("tileset", (r, elementName) => r.Skip);
|
||||||
|
return externalTileset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
var version = _reader.GetOptionalAttribute("version").GetValueOrOptional(parentVersion);
|
||||||
|
var tiledVersion = _reader.GetOptionalAttribute("tiledversion").GetValueOrOptional(parentTiledVersion);
|
||||||
|
var name = _reader.GetRequiredAttribute("name");
|
||||||
|
var @class = _reader.GetOptionalAttribute("class").GetValueOr("");
|
||||||
|
var tileWidth = _reader.GetRequiredAttributeParseable<uint>("tilewidth");
|
||||||
|
var tileHeight = _reader.GetRequiredAttributeParseable<uint>("tileheight");
|
||||||
|
var spacing = _reader.GetOptionalAttributeParseable<uint>("spacing").GetValueOr(0);
|
||||||
|
var margin = _reader.GetOptionalAttributeParseable<uint>("margin").GetValueOr(0);
|
||||||
|
var tileCount = _reader.GetRequiredAttributeParseable<uint>("tilecount");
|
||||||
|
var columns = _reader.GetRequiredAttributeParseable<uint>("columns");
|
||||||
var objectAlignment = _reader.GetOptionalAttributeEnum<ObjectAlignment>("objectalignment", s => s switch
|
var objectAlignment = _reader.GetOptionalAttributeEnum<ObjectAlignment>("objectalignment", s => s switch
|
||||||
{
|
{
|
||||||
"unspecified" => ObjectAlignment.Unspecified,
|
"unspecified" => ObjectAlignment.Unspecified,
|
||||||
|
@ -35,27 +50,27 @@ public abstract partial class TmxReaderBase
|
||||||
"bottom" => ObjectAlignment.Bottom,
|
"bottom" => ObjectAlignment.Bottom,
|
||||||
"bottomright" => ObjectAlignment.BottomRight,
|
"bottomright" => ObjectAlignment.BottomRight,
|
||||||
_ => throw new InvalidOperationException($"Unknown object alignment '{s}'")
|
_ => throw new InvalidOperationException($"Unknown object alignment '{s}'")
|
||||||
}) ?? ObjectAlignment.Unspecified;
|
}).GetValueOr(ObjectAlignment.Unspecified);
|
||||||
var renderSize = _reader.GetOptionalAttributeEnum<TileRenderSize>("rendersize", s => s switch
|
var renderSize = _reader.GetOptionalAttributeEnum<TileRenderSize>("rendersize", s => s switch
|
||||||
{
|
{
|
||||||
"tile" => TileRenderSize.Tile,
|
"tile" => TileRenderSize.Tile,
|
||||||
"grid" => TileRenderSize.Grid,
|
"grid" => TileRenderSize.Grid,
|
||||||
_ => throw new InvalidOperationException($"Unknown render size '{s}'")
|
_ => throw new InvalidOperationException($"Unknown render size '{s}'")
|
||||||
}) ?? TileRenderSize.Tile;
|
}).GetValueOr(TileRenderSize.Tile);
|
||||||
var fillMode = _reader.GetOptionalAttributeEnum<FillMode>("fillmode", s => s switch
|
var fillMode = _reader.GetOptionalAttributeEnum<FillMode>("fillmode", s => s switch
|
||||||
{
|
{
|
||||||
"stretch" => FillMode.Stretch,
|
"stretch" => FillMode.Stretch,
|
||||||
"preserve-aspect-fit" => FillMode.PreserveAspectFit,
|
"preserve-aspect-fit" => FillMode.PreserveAspectFit,
|
||||||
_ => throw new InvalidOperationException($"Unknown fill mode '{s}'")
|
_ => throw new InvalidOperationException($"Unknown fill mode '{s}'")
|
||||||
}) ?? FillMode.Stretch;
|
}).GetValueOr(FillMode.Stretch);
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
Image? image = null;
|
Image image = null;
|
||||||
TileOffset? tileOffset = null;
|
TileOffset tileOffset = null;
|
||||||
Grid? grid = null;
|
Grid grid = null;
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
List<Wangset>? wangsets = null;
|
List<Wangset> wangsets = null;
|
||||||
Transformations? transformations = null;
|
Transformations transformations = null;
|
||||||
List<Tile> tiles = [];
|
List<Tile> tiles = [];
|
||||||
|
|
||||||
_reader.ProcessChildren("tileset", (r, elementName) => elementName switch
|
_reader.ProcessChildren("tileset", (r, elementName) => elementName switch
|
||||||
|
@ -70,15 +85,6 @@ public abstract partial class TmxReaderBase
|
||||||
_ => r.Skip
|
_ => r.Skip
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check if tileset is referring to external file
|
|
||||||
if (source is not null)
|
|
||||||
{
|
|
||||||
var resolvedTileset = _externalTilesetResolver(source);
|
|
||||||
resolvedTileset.FirstGID = firstGID;
|
|
||||||
resolvedTileset.Source = source;
|
|
||||||
return resolvedTileset;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Tileset
|
return new Tileset
|
||||||
{
|
{
|
||||||
Version = version,
|
Version = version,
|
||||||
|
@ -100,9 +106,9 @@ public abstract partial class TmxReaderBase
|
||||||
TileOffset = tileOffset,
|
TileOffset = tileOffset,
|
||||||
Grid = grid,
|
Grid = grid,
|
||||||
Properties = properties ?? [],
|
Properties = properties ?? [],
|
||||||
Wangsets = wangsets,
|
Wangsets = wangsets ?? [],
|
||||||
Transformations = transformations,
|
Transformations = transformations,
|
||||||
Tiles = tiles
|
Tiles = tiles ?? []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +134,7 @@ public abstract partial class TmxReaderBase
|
||||||
_ => r.Skip
|
_ => r.Skip
|
||||||
});
|
});
|
||||||
|
|
||||||
if (format is null && source is not null)
|
if (!format.HasValue && source.HasValue)
|
||||||
format = Helpers.ParseImageFormatFromSource(source);
|
format = Helpers.ParseImageFormatFromSource(source);
|
||||||
|
|
||||||
return new Image
|
return new Image
|
||||||
|
@ -144,8 +150,8 @@ public abstract partial class TmxReaderBase
|
||||||
internal TileOffset ReadTileOffset()
|
internal TileOffset ReadTileOffset()
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var x = _reader.GetOptionalAttributeParseable<float>("x") ?? 0f;
|
var x = _reader.GetOptionalAttributeParseable<float>("x").GetValueOr(0f);
|
||||||
var y = _reader.GetOptionalAttributeParseable<float>("y") ?? 0f;
|
var y = _reader.GetOptionalAttributeParseable<float>("y").GetValueOr(0f);
|
||||||
|
|
||||||
_reader.ReadStartElement("tileoffset");
|
_reader.ReadStartElement("tileoffset");
|
||||||
return new TileOffset { X = x, Y = y };
|
return new TileOffset { X = x, Y = y };
|
||||||
|
@ -159,7 +165,7 @@ public abstract partial class TmxReaderBase
|
||||||
"orthogonal" => GridOrientation.Orthogonal,
|
"orthogonal" => GridOrientation.Orthogonal,
|
||||||
"isometric" => GridOrientation.Isometric,
|
"isometric" => GridOrientation.Isometric,
|
||||||
_ => throw new InvalidOperationException($"Unknown orientation '{s}'")
|
_ => throw new InvalidOperationException($"Unknown orientation '{s}'")
|
||||||
}) ?? GridOrientation.Orthogonal;
|
}).GetValueOr(GridOrientation.Orthogonal);
|
||||||
var width = _reader.GetRequiredAttributeParseable<uint>("width");
|
var width = _reader.GetRequiredAttributeParseable<uint>("width");
|
||||||
var height = _reader.GetRequiredAttributeParseable<uint>("height");
|
var height = _reader.GetRequiredAttributeParseable<uint>("height");
|
||||||
|
|
||||||
|
@ -170,10 +176,10 @@ public abstract partial class TmxReaderBase
|
||||||
internal Transformations ReadTransformations()
|
internal Transformations ReadTransformations()
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var hFlip = (_reader.GetOptionalAttributeParseable<uint>("hflip") ?? 0) == 1;
|
var hFlip = _reader.GetOptionalAttributeParseable<uint>("hflip").GetValueOr(0) == 1;
|
||||||
var vFlip = (_reader.GetOptionalAttributeParseable<uint>("vflip") ?? 0) == 1;
|
var vFlip = _reader.GetOptionalAttributeParseable<uint>("vflip").GetValueOr(0) == 1;
|
||||||
var rotate = (_reader.GetOptionalAttributeParseable<uint>("rotate") ?? 0) == 1;
|
var rotate = _reader.GetOptionalAttributeParseable<uint>("rotate").GetValueOr(0) == 1;
|
||||||
var preferUntransformed = (_reader.GetOptionalAttributeParseable<uint>("preferuntransformed") ?? 0) == 1;
|
var preferUntransformed = _reader.GetOptionalAttributeParseable<uint>("preferuntransformed").GetValueOr(0) == 1;
|
||||||
|
|
||||||
_reader.ReadStartElement("transformations");
|
_reader.ReadStartElement("transformations");
|
||||||
return new Transformations { HFlip = hFlip, VFlip = vFlip, Rotate = rotate, PreferUntransformed = preferUntransformed };
|
return new Transformations { HFlip = hFlip, VFlip = vFlip, Rotate = rotate, PreferUntransformed = preferUntransformed };
|
||||||
|
@ -183,18 +189,18 @@ public abstract partial class TmxReaderBase
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
var id = _reader.GetRequiredAttributeParseable<uint>("id");
|
||||||
var type = _reader.GetOptionalAttribute("type") ?? "";
|
var type = _reader.GetOptionalAttribute("type").GetValueOr("");
|
||||||
var probability = _reader.GetOptionalAttributeParseable<float>("probability") ?? 0f;
|
var probability = _reader.GetOptionalAttributeParseable<float>("probability").GetValueOr(0f);
|
||||||
var x = _reader.GetOptionalAttributeParseable<uint>("x") ?? 0;
|
var x = _reader.GetOptionalAttributeParseable<uint>("x").GetValueOr(0);
|
||||||
var y = _reader.GetOptionalAttributeParseable<uint>("y") ?? 0;
|
var y = _reader.GetOptionalAttributeParseable<uint>("y").GetValueOr(0);
|
||||||
var width = _reader.GetOptionalAttributeParseable<uint>("width");
|
var width = _reader.GetOptionalAttributeParseable<uint>("width");
|
||||||
var height = _reader.GetOptionalAttributeParseable<uint>("height");
|
var height = _reader.GetOptionalAttributeParseable<uint>("height");
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
Image? image = null;
|
Image image = null;
|
||||||
ObjectLayer? objectLayer = null;
|
ObjectLayer objectLayer = null;
|
||||||
List<Frame>? animation = null;
|
List<Frame> animation = null;
|
||||||
|
|
||||||
_reader.ProcessChildren("tile", (r, elementName) => elementName switch
|
_reader.ProcessChildren("tile", (r, elementName) => elementName switch
|
||||||
{
|
{
|
||||||
|
@ -217,12 +223,12 @@ public abstract partial class TmxReaderBase
|
||||||
Probability = probability,
|
Probability = probability,
|
||||||
X = x,
|
X = x,
|
||||||
Y = y,
|
Y = y,
|
||||||
Width = width ?? image?.Width ?? 0,
|
Width = width.HasValue ? width : image?.Width ?? 0,
|
||||||
Height = height ?? image?.Height ?? 0,
|
Height = height.HasValue ? height : image?.Height ?? 0,
|
||||||
Properties = properties ?? [],
|
Properties = properties ?? [],
|
||||||
Image = image,
|
Image = image is null ? Optional<Image>.Empty : image,
|
||||||
ObjectLayer = objectLayer,
|
ObjectLayer = objectLayer is null ? Optional<ObjectLayer>.Empty : objectLayer,
|
||||||
Animation = animation
|
Animation = animation ?? []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,11 +239,11 @@ public abstract partial class TmxReaderBase
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var name = _reader.GetRequiredAttribute("name");
|
var name = _reader.GetRequiredAttribute("name");
|
||||||
var @class = _reader.GetOptionalAttribute("class") ?? "";
|
var @class = _reader.GetOptionalAttribute("class").GetValueOr("");
|
||||||
var tile = _reader.GetRequiredAttributeParseable<int>("tile");
|
var tile = _reader.GetRequiredAttributeParseable<int>("tile");
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
List<WangColor> wangColors = [];
|
List<WangColor> wangColors = [];
|
||||||
List<WangTile> wangTiles = [];
|
List<WangTile> wangTiles = [];
|
||||||
|
|
||||||
|
@ -267,13 +273,13 @@ public abstract partial class TmxReaderBase
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
var name = _reader.GetRequiredAttribute("name");
|
var name = _reader.GetRequiredAttribute("name");
|
||||||
var @class = _reader.GetOptionalAttribute("class") ?? "";
|
var @class = _reader.GetOptionalAttribute("class").GetValueOr("");
|
||||||
var color = _reader.GetRequiredAttributeParseable<Color>("color");
|
var color = _reader.GetRequiredAttributeParseable<Color>("color");
|
||||||
var tile = _reader.GetRequiredAttributeParseable<int>("tile");
|
var tile = _reader.GetRequiredAttributeParseable<int>("tile");
|
||||||
var probability = _reader.GetOptionalAttributeParseable<float>("probability") ?? 0f;
|
var probability = _reader.GetOptionalAttributeParseable<float>("probability").GetValueOr(0f);
|
||||||
|
|
||||||
// Elements
|
// Elements
|
||||||
List<IProperty>? properties = null;
|
List<IProperty> properties = null;
|
||||||
|
|
||||||
_reader.ProcessChildren("wangcolor", (r, elementName) => elementName switch
|
_reader.ProcessChildren("wangcolor", (r, elementName) => elementName switch
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,5 +21,5 @@ public class TsxTilesetReader : TmxReaderBase, ITilesetReader
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public new Tileset ReadTileset() => base.ReadTileset();
|
public Tileset ReadTileset() => base.ReadTileset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ public class Template
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If the template represents a tile object, this property will contain the tileset that the tile belongs to.
|
/// If the template represents a tile object, this property will contain the tileset that the tile belongs to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Tileset? Tileset { get; set; }
|
public Optional<Tileset> Tileset { get; set; } = Optional<Tileset>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The object that this template represents.
|
/// The object that this template represents.
|
||||||
|
|
|
@ -34,25 +34,25 @@ public class Image
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The format of the image.
|
/// The format of the image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ImageFormat? Format { get; set; }
|
public Optional<ImageFormat> Format { get; set; } = Optional<ImageFormat>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The reference to the image file.
|
/// The reference to the image file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Source { get; set; }
|
public Optional<string> Source { get; set; } = Optional<string>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a specific color that is treated as transparent.
|
/// Defines a specific color that is treated as transparent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Color? TransparentColor { get; set; }
|
public Optional<Color> TransparentColor { get; set; } = Optional<Color>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The image width in pixels, used for tile index correction when the image changes.
|
/// The image width in pixels, used for tile index correction when the image changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? Width { get; set; }
|
public Optional<uint> Width { get; set; } = Optional<uint>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The image height in pixels, used for tile index correction when the image changes.
|
/// The image height in pixels, used for tile index correction when the image changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? Height { get; set; }
|
public Optional<uint> Height { get; set; } = Optional<uint>.Empty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,15 +54,15 @@ public class Tile : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The image representing this tile. Only used for tilesets that composed of a collection of images.
|
/// The image representing this tile. Only used for tilesets that composed of a collection of images.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Image? Image { get; set; }
|
public Optional<Image> Image { get; set; } = Optional<Image>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unclear what this is for.
|
/// Used when the tile contains e.g. collision information.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ObjectLayer? ObjectLayer { get; set; }
|
public Optional<ObjectLayer> ObjectLayer { get; set; } = Optional<ObjectLayer>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The animation frames for this tile.
|
/// The animation frames for this tile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Frame>? Animation { get; set; }
|
public List<Frame> Animation { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,27 +98,27 @@ public class Tileset : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The TMX format version. Is incremented to match minor Tiled releases.
|
/// The TMX format version. Is incremented to match minor Tiled releases.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Version { get; set; }
|
public Optional<string> Version { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Tiled version used to save the file in case it was loaded from an external tileset file.
|
/// The Tiled version used to save the file in case it was loaded from an external tileset file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? TiledVersion { get; set; }
|
public Optional<string> TiledVersion { get; set; } = Optional<string>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The first global tile ID of this tileset (this global ID maps to the first tile in this tileset).
|
/// The first global tile ID of this tileset (this global ID maps to the first tile in this tileset).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? FirstGID { get; set; }
|
public Optional<uint> FirstGID { get; set; } = Optional<uint>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If this tileset is stored in an external TSX (Tile Set XML) file, this attribute refers to that file.
|
/// If this tileset is stored in an external TSX (Tile Set XML) file, this attribute refers to that file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Source { get; set; }
|
public Optional<string> Source { get; set; } = Optional<string>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of this tileset.
|
/// The name of this tileset.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Name { get; set; }
|
public required string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The class of this tileset.
|
/// The class of this tileset.
|
||||||
|
@ -128,32 +128,32 @@ public class Tileset : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The width of the tiles in this tileset, which should be at least 1 (non-zero) except in the case of image collection tilesets (in which case it stores the maximum tile width).
|
/// The width of the tiles in this tileset, which should be at least 1 (non-zero) except in the case of image collection tilesets (in which case it stores the maximum tile width).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? TileWidth { get; set; }
|
public required uint TileWidth { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The height of the tiles in this tileset, which should be at least 1 (non-zero) except in the case of image collection tilesets (in which case it stores the maximum tile height).
|
/// The height of the tiles in this tileset, which should be at least 1 (non-zero) except in the case of image collection tilesets (in which case it stores the maximum tile height).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? TileHeight { get; set; }
|
public required uint TileHeight { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The spacing in pixels between the tiles in this tileset (applies to the tileset image). Irrelevant for image collection tilesets.
|
/// The spacing in pixels between the tiles in this tileset (applies to the tileset image). Irrelevant for image collection tilesets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float? Spacing { get; set; } = 0f;
|
public uint Spacing { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The margin around the tiles in this tileset (applies to the tileset image). Irrelevant for image collection tilesets.
|
/// The margin around the tiles in this tileset (applies to the tileset image). Irrelevant for image collection tilesets.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float? Margin { get; set; } = 0f;
|
public uint Margin { get; set; } = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of tiles in this tileset.
|
/// The number of tiles in this tileset.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? TileCount { get; set; }
|
public required uint TileCount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of tile columns in the tileset.
|
/// The number of tile columns in the tileset.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint? Columns { get; set; }
|
public required uint Columns { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Controls the aligntment for tile objects.
|
/// Controls the aligntment for tile objects.
|
||||||
|
@ -173,17 +173,17 @@ public class Tileset : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If the tileset is based on a single image, which is cut into tiles based on the given attributes of the tileset, then this is that image.
|
/// If the tileset is based on a single image, which is cut into tiles based on the given attributes of the tileset, then this is that image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Image? Image { get; set; }
|
public Optional<Image> Image { get; set; } = Optional<Image>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is used to specify an offset in pixels, to be applied when drawing a tile from the related tileset. When not present, no offset is applied.
|
/// This is used to specify an offset in pixels, to be applied when drawing a tile from the related tileset. When not present, no offset is applied.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TileOffset? TileOffset { get; set; }
|
public Optional<TileOffset> TileOffset { get; set; } = Optional<TileOffset>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ths is only used in case of isometric orientation, and determines how tile overlays for terrain and collision information are rendered.
|
/// Ths is only used in case of isometric orientation, and determines how tile overlays for terrain and collision information are rendered.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Grid? Grid { get; set; }
|
public Optional<Grid> Grid { get; set; } = Optional<Grid>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tileset properties.
|
/// Tileset properties.
|
||||||
|
@ -198,12 +198,12 @@ public class Tileset : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the list of Wang sets defined for this tileset.
|
/// Contains the list of Wang sets defined for this tileset.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<Wangset>? Wangsets { get; set; }
|
public List<Wangset> Wangsets { get; set; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to describe which transformations can be applied to the tiles (e.g. to extend a Wang set by transforming existing tiles).
|
/// Used to describe which transformations can be applied to the tiles (e.g. to extend a Wang set by transforming existing tiles).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Transformations? Transformations { get; set; }
|
public Optional<Transformations> Transformations { get; set; } = Optional<Transformations>.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If this tileset is based on a collection of images, then this list of tiles will contain the individual images that make up the tileset.
|
/// If this tileset is based on a collection of images, then this list of tiles will contain the individual images that make up the tileset.
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class Wangset : HasPropertiesBase
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Wang colors in the Wang set.
|
/// The Wang colors in the Wang set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<WangColor>? WangColors { get; set; } = [];
|
public List<WangColor> WangColors { get; set; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Wang tiles in the Wang set.
|
/// The Wang tiles in the Wang set.
|
||||||
|
|
Loading…
Add table
Reference in a new issue