mirror of
https://github.com/dcronqvist/DotTiled.git
synced 2025-02-05 08:52:50 +02:00
Make Optional<T> into readonly struct to avoid heap allocations
This commit is contained in:
parent
de41fb5508
commit
92702a512d
35 changed files with 177 additions and 205 deletions
|
@ -178,7 +178,7 @@ For enum definitions, the <xref:System.FlagsAttribute> can be used to indicate t
|
|||
> Tiled supports enums which can store their values as either strings or integers, and depending on the storage type you have specified in Tiled, you must make sure to have the same storage type in your <xref:DotTiled.CustomEnumDefinition>. This can be done by setting the `StorageType` property to either `CustomEnumStorageType.String` or `CustomEnumStorageType.Int` when creating the definition, or by passing the storage type as an argument to the <xref:DotTiled.CustomEnumDefinition.FromEnum``1(DotTiled.CustomEnumStorageType)> method. To be consistent with Tiled, <xref:DotTiled.CustomEnumDefinition.FromEnum``1(DotTiled.CustomEnumStorageType)> will default to `CustomEnumStorageType.String` for the storage type parameter.
|
||||
|
||||
> [!WARNING]
|
||||
> If you have a custom enum type in Tiled, but do not define it in DotTiled, you must be aware that the type of the parsed property will be either <xref:DotTiled.StringProperty> or <xref:IntProperty>. It is not possible to determine the correct way to parse the enum property without the custom enum definition, which is why you will instead be given a property of type `string` or `int` when accessing the property in DotTiled. This can lead to inconsistencies between the map in Tiled and the loaded map with DotTiled. It is therefore recommended to define your custom enum types in DotTiled if you want to access the properties as <xref:EnumProperty> instances.
|
||||
> If you have a custom enum type in Tiled, but do not define it in DotTiled, you must be aware that the type of the parsed property will be either <xref:DotTiled.StringProperty> or <xref:DotTiled.IntProperty>. It is not possible to determine the correct way to parse the enum property without the custom enum definition, which is why you will instead be given a property of type `string` or `int` when accessing the property in DotTiled. This can lead to inconsistencies between the map in Tiled and the loaded map with DotTiled. It is therefore recommended to define your custom enum types in DotTiled if you want to access the properties as <xref:DotTiled.EnumProperty> instances.
|
||||
|
||||
## Mapping properties to C# classes or enums
|
||||
|
||||
|
|
|
@ -79,6 +79,6 @@ public class Program
|
|||
[
|
||||
new CustomClassDefinition() { Name = "a" },
|
||||
];
|
||||
return allDefinedTypes.FirstOrDefault(ctd => ctd.Name == name) is ICustomTypeDefinition ctd ? new Optional<ICustomTypeDefinition>(ctd) : Optional<ICustomTypeDefinition>.Empty;
|
||||
return allDefinedTypes.FirstOrDefault(ctd => ctd.Name == name) is ICustomTypeDefinition ctd ? new Optional<ICustomTypeDefinition>(ctd) : Optional.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,10 +42,10 @@ public partial class MapParser : Node2D
|
|||
|
||||
private Tileset ResolveTileset(string source)
|
||||
{
|
||||
string tilesetString = FileAccess.Open($"res://{source}", FileAccess.ModeFlags.Read).GetAsText();
|
||||
using TilesetReader tilesetReader =
|
||||
new TilesetReader(tilesetString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
string tilesetString = FileAccess.Open($"res://{source}", FileAccess.ModeFlags.Read).GetAsText();
|
||||
using TilesetReader tilesetReader =
|
||||
new TilesetReader(tilesetString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
return tilesetReader.ReadTileset();
|
||||
}
|
||||
|
||||
private Template ResolveTemplate(string source)
|
||||
|
@ -62,6 +62,6 @@ public partial class MapParser : Node2D
|
|||
[
|
||||
new CustomClassDefinition() { Name = "a" },
|
||||
];
|
||||
return allDefinedTypes.FirstOrDefault(ctd => ctd.Name == name) is ICustomTypeDefinition ctd ? new Optional<ICustomTypeDefinition>(ctd) : Optional<ICustomTypeDefinition>.Empty;
|
||||
return allDefinedTypes.FirstOrDefault(ctd => ctd.Name == name) is ICustomTypeDefinition ctd ? new Optional<ICustomTypeDefinition>(ctd) : Optional.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ public static partial class DotTiledAssert
|
|||
AssertEqual(expected.X, actual.X, nameof(TileLayer.X));
|
||||
AssertEqual(expected.Y, actual.Y, nameof(TileLayer.Y));
|
||||
|
||||
Assert.NotNull(actual.Data);
|
||||
AssertData(expected.Data, actual.Data);
|
||||
AssertOptionalsEqual(expected.Data, actual.Data, nameof(TileLayer.Data), AssertData);
|
||||
}
|
||||
|
||||
private static void AssertLayer(ObjectLayer expected, ObjectLayer actual)
|
||||
|
@ -60,8 +59,7 @@ public static partial class DotTiledAssert
|
|||
AssertEqual(expected.X, actual.X, nameof(ImageLayer.X));
|
||||
AssertEqual(expected.Y, actual.Y, nameof(ImageLayer.Y));
|
||||
|
||||
Assert.NotNull(actual.Image);
|
||||
AssertImage(expected.Image, actual.Image);
|
||||
AssertOptionalsEqual(expected.Image, actual.Image, nameof(ImageLayer.Image), AssertImage);
|
||||
}
|
||||
|
||||
private static void AssertLayer(Group expected, Group actual)
|
||||
|
|
|
@ -33,12 +33,6 @@ public static partial class DotTiledAssert
|
|||
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");
|
||||
|
@ -51,12 +45,6 @@ public static partial class DotTiledAssert
|
|||
|
||||
internal 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");
|
||||
|
|
|
@ -58,7 +58,7 @@ public partial class TestData
|
|||
new IntProperty { Name = "intprop", Value = 8 },
|
||||
new ObjectProperty { Name = "objectprop", Value = 5 },
|
||||
new StringProperty { Name = "stringprop", Value = "This is a string, hello world!" },
|
||||
new ColorProperty { Name = "unsetcolorprop", Value = Optional<Color>.Empty }
|
||||
new ColorProperty { Name = "unsetcolorprop", Value = Optional.Empty }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
|
|
@ -59,30 +59,6 @@ public class OptionalTests
|
|||
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]
|
||||
|
@ -237,18 +213,6 @@ public class OptionalTests
|
|||
_ = 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()
|
||||
{
|
||||
|
|
|
@ -71,8 +71,8 @@ public class LoaderTests
|
|||
""");
|
||||
|
||||
var resourceCache = Substitute.For<IResourceCache>();
|
||||
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
|
||||
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional<Template>.Empty);
|
||||
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional.Empty);
|
||||
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional.Empty);
|
||||
|
||||
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
|
||||
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
|
||||
|
@ -134,8 +134,8 @@ public class LoaderTests
|
|||
""");
|
||||
|
||||
var resourceCache = Substitute.For<IResourceCache>();
|
||||
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
|
||||
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional<Template>.Empty);
|
||||
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional.Empty);
|
||||
resourceCache.GetTemplate(Arg.Any<string>()).Returns(Optional.Empty);
|
||||
|
||||
var customTypeDefinitions = Enumerable.Empty<ICustomTypeDefinition>();
|
||||
var loader = new Loader(resourceReader, resourceCache, customTypeDefinitions);
|
||||
|
@ -219,7 +219,7 @@ public class LoaderTests
|
|||
""");
|
||||
|
||||
var resourceCache = Substitute.For<IResourceCache>();
|
||||
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional<Tileset>.Empty);
|
||||
resourceCache.GetTileset(Arg.Any<string>()).Returns(Optional.Empty);
|
||||
resourceCache.GetTemplate("template.tx").Returns(new Optional<Template>(new Template
|
||||
{
|
||||
Object = new PolygonObject
|
||||
|
|
|
@ -39,7 +39,7 @@ public partial class MapReaderTests
|
|||
return new Optional<ICustomTypeDefinition>(ctd);
|
||||
}
|
||||
|
||||
return Optional<ICustomTypeDefinition>.Empty;
|
||||
return Optional.Empty;
|
||||
}
|
||||
using var mapReader = new MapReader(mapString, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public partial class TmjMapReaderTests
|
|||
return new Optional<ICustomTypeDefinition>(ctd);
|
||||
}
|
||||
|
||||
return Optional<ICustomTypeDefinition>.Empty;
|
||||
return Optional.Empty;
|
||||
}
|
||||
using var mapReader = new TmjMapReader(json, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public partial class TmxMapReaderTests
|
|||
return new Optional<ICustomTypeDefinition>(ctd);
|
||||
}
|
||||
|
||||
return Optional<ICustomTypeDefinition>.Empty;
|
||||
return Optional.Empty;
|
||||
}
|
||||
using var mapReader = new TmxMapReader(reader, ResolveTileset, ResolveTemplate, ResolveCustomType);
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public abstract class BaseLayer : HasPropertiesBase
|
|||
/// <summary>
|
||||
/// A tint color that is multiplied with any tiles drawn by this layer.
|
||||
/// </summary>
|
||||
public Optional<Color> TintColor { get; set; } = Optional<Color>.Empty;
|
||||
public Optional<Color> TintColor { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Horizontal offset for this layer in pixels.
|
||||
|
|
|
@ -118,27 +118,27 @@ public class Data
|
|||
/// <summary>
|
||||
/// The encoding used to encode the tile layer data.
|
||||
/// </summary>
|
||||
public Optional<DataEncoding> Encoding { get; set; } = Optional<DataEncoding>.Empty;
|
||||
public Optional<DataEncoding> Encoding { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The compression method used to compress the tile layer data.
|
||||
/// </summary>
|
||||
public Optional<DataCompression> Compression { get; set; } = Optional<DataCompression>.Empty;
|
||||
public Optional<DataCompression> Compression { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// <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>
|
||||
public Optional<uint[]> GlobalTileIDs { get; set; } = Optional<uint[]>.Empty;
|
||||
public Optional<uint[]> GlobalTileIDs { get; set; } = Optional.Empty;
|
||||
|
||||
/// <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"/>.
|
||||
/// </summary>
|
||||
public Optional<FlippingFlags[]> FlippingFlags { get; set; } = Optional<FlippingFlags[]>.Empty;
|
||||
public Optional<FlippingFlags[]> FlippingFlags { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// If the map is infinite, it will instead contain a list of chunks.
|
||||
/// </summary>
|
||||
public Optional<Chunk[]> Chunks { get; set; } = Optional<Chunk[]>.Empty;
|
||||
public Optional<Chunk[]> Chunks { get; set; } = Optional.Empty;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ObjectLayer : BaseLayer
|
|||
/// <summary>
|
||||
/// A color that is multiplied with any tile objects drawn by this layer.
|
||||
/// </summary>
|
||||
public Optional<Color> Color { get; set; } = Optional<Color>.Empty;
|
||||
public Optional<Color> Color { get; set; } = Optional.Empty;
|
||||
|
||||
/// <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"/>).
|
||||
|
|
|
@ -10,7 +10,7 @@ public abstract class Object : HasPropertiesBase
|
|||
/// <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.
|
||||
/// </summary>
|
||||
public Optional<uint> ID { get; set; } = Optional<uint>.Empty;
|
||||
public Optional<uint> ID { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the object. An arbitrary string.
|
||||
|
@ -55,7 +55,7 @@ public abstract class Object : HasPropertiesBase
|
|||
/// <summary>
|
||||
/// A reference to a template file.
|
||||
/// </summary>
|
||||
public Optional<string> Template { get; set; } = Optional<string>.Empty;
|
||||
public Optional<string> Template { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Object properties.
|
||||
|
|
|
@ -28,5 +28,5 @@ public class TileLayer : BaseLayer
|
|||
/// <summary>
|
||||
/// The tile layer data.
|
||||
/// </summary>
|
||||
public Optional<Data> Data { get; set; } = Optional<Data>.Empty;
|
||||
public Optional<Data> Data { get; set; } = Optional.Empty;
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ public class Map : HasPropertiesBase
|
|||
/// <summary>
|
||||
/// The Tiled version used to save the file.
|
||||
/// </summary>
|
||||
public Optional<string> TiledVersion { get; set; } = Optional<string>.Empty;
|
||||
public Optional<string> TiledVersion { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The class of this map.
|
||||
|
@ -146,17 +146,17 @@ public class Map : HasPropertiesBase
|
|||
/// <summary>
|
||||
/// Only for hexagonal maps. Determines the width or height (depending on the staggered axis) of the tile's edge, in pixels.
|
||||
/// </summary>
|
||||
public Optional<uint> HexSideLength { get; set; } = Optional<uint>.Empty;
|
||||
public Optional<uint> HexSideLength { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// For staggered and hexagonal maps, determines which axis (X or Y) is staggered.
|
||||
/// </summary>
|
||||
public Optional<StaggerAxis> StaggerAxis { get; set; } = Optional<StaggerAxis>.Empty;
|
||||
public Optional<StaggerAxis> StaggerAxis { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// For staggered and hexagonal maps, determines whether the "even" or "odd" indexes along the staggered axis are shifted.
|
||||
/// </summary>
|
||||
public Optional<StaggerIndex> StaggerIndex { get; set; } = Optional<StaggerIndex>.Empty;
|
||||
public Optional<StaggerIndex> StaggerIndex { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// X coordinate of the parallax origin in pixels.
|
||||
|
|
|
@ -2,62 +2,94 @@ using System;
|
|||
|
||||
namespace DotTiled;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an empty value.
|
||||
/// </summary>
|
||||
public readonly struct OptionalEmpty;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an empty <see cref="Optional{T}"/> object.
|
||||
/// </summary>
|
||||
public static class Optional
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an empty <see cref="Optional{T}"/> object.
|
||||
/// </summary>
|
||||
public static readonly OptionalEmpty Empty = default;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public readonly struct Optional<T>
|
||||
{
|
||||
#pragma warning disable IDE0032 // Use auto property
|
||||
private readonly bool _hasValue;
|
||||
private readonly T _value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the current <see cref="Optional{T}"/> object has a value.
|
||||
/// Returns <see langword="true"/> if the <see cref="Value"/> will return a meaningful value.
|
||||
/// </summary>
|
||||
public bool HasValue { get; }
|
||||
/// <returns></returns>
|
||||
public bool HasValue => _hasValue;
|
||||
#pragma warning restore IDE0032 // Use auto property
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the current <see cref="Optional{T}"/> object if it has been set; otherwise, throws an exception.
|
||||
/// Constructs an <see cref="Optional{T}"/> with a meaningful value.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public Optional(T value)
|
||||
{
|
||||
_hasValue = true;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the current object. Not meaningful unless <see cref="HasValue"/> returns <see langword="true"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Unlike <see cref="Nullable{T}.Value"/>, this property does not throw an exception when
|
||||
/// <see cref="HasValue"/> is <see langword="false"/>.</para>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// <para>The value if <see cref="HasValue"/> is <see langword="true"/>; otherwise, the default value for type
|
||||
/// <typeparamref name="T"/>.</para>
|
||||
/// </returns>
|
||||
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.
|
||||
/// Creates a new object initialized to a meaningful 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>
|
||||
/// <param name="value"></param>
|
||||
public static implicit operator Optional<T>(T value)
|
||||
{
|
||||
if (value is null)
|
||||
return new();
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return new(value);
|
||||
return new Optional<T>(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicitly converts an <see cref="Optional{T}"/> object to a value.
|
||||
/// Creates a new object initialized to an empty value.
|
||||
/// </summary>
|
||||
/// <param name="optional">The <see cref="Optional{T}"/> object to be converted.</param>
|
||||
public static implicit operator T(Optional<T> optional)
|
||||
/// <param name="_"></param>
|
||||
public static implicit operator Optional<T>(OptionalEmpty _)
|
||||
{
|
||||
return optional.Value;
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of this object.
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
// Note: For nullable types, it's possible to have _hasValue true and _value null.
|
||||
return _hasValue
|
||||
? _value?.ToString() ?? "null"
|
||||
: "Empty";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -71,17 +103,6 @@ public class Optional<T>
|
|||
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>
|
||||
|
@ -96,9 +117,6 @@ public class Optional<T>
|
|||
/// <returns></returns>
|
||||
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)
|
||||
{
|
||||
|
@ -129,9 +147,13 @@ public class Optional<T>
|
|||
public override int GetHashCode() => HasValue ? _value!.GetHashCode() : 0;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an empty <see cref="Optional{T}"/> object.
|
||||
/// Determines whether the specified <see cref="Optional{T}"/> objects are not equal.
|
||||
/// </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
|
||||
/// <param name="left"></param>
|
||||
/// <param name="right"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Optional<T> left, Optional<T> right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ public class DefaultResourceCache : IResourceCache
|
|||
if (_templates.TryGetValue(path, out var template))
|
||||
return new Optional<Template>(template);
|
||||
|
||||
return Optional<Template>.Empty;
|
||||
return Optional.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@ -25,7 +25,7 @@ public class DefaultResourceCache : IResourceCache
|
|||
if (_tilesets.TryGetValue(path, out var tileset))
|
||||
return new Optional<Tileset>(tileset);
|
||||
|
||||
return Optional<Tileset>.Empty;
|
||||
return Optional.Empty;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
|
@ -91,7 +91,7 @@ internal static partial class Helpers
|
|||
if (string.IsNullOrWhiteSpace(className))
|
||||
return null;
|
||||
|
||||
var customType = customTypeResolver(className) ?? throw new InvalidOperationException($"Could not resolve custom type '{className}'.");
|
||||
var customType = customTypeResolver(className);
|
||||
if (!customType.HasValue)
|
||||
return null;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ public interface IResourceCache
|
|||
/// Retrieves a tileset from the cache with the given <paramref name="path"/>.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the tileset file.</param>
|
||||
/// <returns>The tileset if it exists in the cache; otherwise, <see cref="Optional{Tileset}.Empty"/>.</returns>
|
||||
/// <returns>The tileset if it exists in the cache; otherwise, <see cref="Optional.Empty"/>.</returns>
|
||||
Optional<Tileset> GetTileset(string path);
|
||||
|
||||
/// <summary>
|
||||
|
@ -30,6 +30,6 @@ public interface IResourceCache
|
|||
/// Retrieves a template from the cache with the given <paramref name="path"/>.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the template file.</param>
|
||||
/// <returns>The template if it exists in the cache; otherwise, <see cref="Optional{Template}.Empty"/>.</returns>
|
||||
/// <returns>The template if it exists in the cache; otherwise, <see cref="Optional.Empty"/>.</returns>
|
||||
Optional<Template> GetTemplate(string path);
|
||||
}
|
||||
|
|
|
@ -119,6 +119,6 @@ public class Loader
|
|||
if (_customTypeDefinitions.TryGetValue(name, out var customTypeDefinition))
|
||||
return new Optional<ICustomTypeDefinition>(customTypeDefinition);
|
||||
|
||||
return Optional<ICustomTypeDefinition>.Empty;
|
||||
return Optional.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ internal static class ExtensionsJsonElement
|
|||
internal static Optional<T> GetOptionalProperty<T>(this JsonElement element, string propertyName)
|
||||
{
|
||||
if (!element.TryGetProperty(propertyName, out var property))
|
||||
return Optional<T>.Empty;
|
||||
return Optional.Empty;
|
||||
|
||||
if (property.ValueKind == JsonValueKind.Null)
|
||||
return Optional<T>.Empty;
|
||||
return Optional.Empty;
|
||||
|
||||
return property.GetValueAs<T>();
|
||||
}
|
||||
|
@ -67,15 +67,15 @@ internal static class ExtensionsJsonElement
|
|||
internal static Optional<T> GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName) where T : IParsable<T>
|
||||
{
|
||||
if (!element.TryGetProperty(propertyName, out var property))
|
||||
return Optional<T>.Empty;
|
||||
return Optional.Empty;
|
||||
|
||||
return T.Parse(property.GetString()!, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
internal static Optional<T> GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName, Func<string, T> parser)
|
||||
internal static Optional<T> GetOptionalPropertyParseable<T>(this JsonElement element, string propertyName, Func<string, Optional<T>> parser)
|
||||
{
|
||||
if (!element.TryGetProperty(propertyName, out var property))
|
||||
return Optional<T>.Empty;
|
||||
return Optional.Empty;
|
||||
|
||||
return parser(property.GetString()!);
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ internal static class ExtensionsJsonElement
|
|||
internal static Optional<T> GetOptionalPropertyCustom<T>(this JsonElement element, string propertyName, Func<JsonElement, T> parser)
|
||||
{
|
||||
if (!element.TryGetProperty(propertyName, out var property))
|
||||
return Optional<T>.Empty;
|
||||
return Optional.Empty;
|
||||
|
||||
return parser(property);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ public abstract partial class TmjReaderBase
|
|||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
GlobalTileIDs = data.GlobalTileIDs,
|
||||
FlippingFlags = data.FlippingFlags
|
||||
GlobalTileIDs = data.GlobalTileIDs.Value,
|
||||
FlippingFlags = data.FlippingFlags.Value
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ public abstract partial class TmjReaderBase
|
|||
|
||||
internal DotTiled.Object ReadObject(JsonElement element)
|
||||
{
|
||||
Optional<uint> idDefault = Optional<uint>.Empty;
|
||||
Optional<uint> idDefault = Optional.Empty;
|
||||
string nameDefault = "";
|
||||
string typeDefault = "";
|
||||
float xDefault = 0f;
|
||||
|
@ -80,7 +80,7 @@ public abstract partial class TmjReaderBase
|
|||
var template = element.GetOptionalProperty<string>("template");
|
||||
if (template.HasValue)
|
||||
{
|
||||
var resolvedTemplate = _externalTemplateResolver(template);
|
||||
var resolvedTemplate = _externalTemplateResolver(template.Value);
|
||||
var templObj = resolvedTemplate.Object;
|
||||
|
||||
idDefault = templObj.ID;
|
||||
|
@ -225,7 +225,7 @@ public abstract partial class TmjReaderBase
|
|||
text.Value.Visible = visible;
|
||||
text.Value.Template = template;
|
||||
text.Value.Properties = properties;
|
||||
return text;
|
||||
return text.Value;
|
||||
}
|
||||
|
||||
return new RectangleObject
|
||||
|
|
|
@ -16,7 +16,7 @@ public abstract partial class TmjReaderBase
|
|||
{
|
||||
"zlib" => DataCompression.ZLib,
|
||||
"gzip" => DataCompression.GZip,
|
||||
"" => Optional<DataCompression>.Empty,
|
||||
"" => Optional.Empty,
|
||||
_ => throw new JsonException($"Unsupported compression '{s}'.")
|
||||
});
|
||||
var chunks = element.GetOptionalPropertyCustom<Data>("chunks", e => ReadDataAsChunks(e, compression, encoding));
|
||||
|
@ -62,7 +62,7 @@ public abstract partial class TmjReaderBase
|
|||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
Data = data ?? chunks
|
||||
Data = data.GetValueOrOptional(chunks)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ public abstract partial class TmjReaderBase
|
|||
{
|
||||
internal Tileset ReadTileset(
|
||||
JsonElement element,
|
||||
Optional<string> parentVersion = null,
|
||||
Optional<string> parentTiledVersion = null)
|
||||
Optional<string> parentVersion = default,
|
||||
Optional<string> parentTiledVersion = default)
|
||||
{
|
||||
var backgroundColor = element.GetOptionalPropertyParseable<Color>("backgroundcolor");
|
||||
var @class = element.GetOptionalProperty<string>("class").GetValueOr("");
|
||||
|
@ -63,7 +63,7 @@ public abstract partial class TmjReaderBase
|
|||
|
||||
if (source.HasValue)
|
||||
{
|
||||
var resolvedTileset = _externalTilesetResolver(source);
|
||||
var resolvedTileset = _externalTilesetResolver(source.Value);
|
||||
resolvedTileset.FirstGID = firstGID;
|
||||
resolvedTileset.Source = source;
|
||||
return resolvedTileset;
|
||||
|
@ -71,34 +71,34 @@ public abstract partial class TmjReaderBase
|
|||
|
||||
Optional<Image> imageModel = image.HasValue ? new Image
|
||||
{
|
||||
Format = Helpers.ParseImageFormatFromSource(image),
|
||||
Format = Helpers.ParseImageFormatFromSource(image.Value),
|
||||
Source = image,
|
||||
Height = imageHeight,
|
||||
Width = imageWidth,
|
||||
TransparentColor = transparentColor
|
||||
} : Optional<Image>.Empty;
|
||||
} : Optional.Empty;
|
||||
|
||||
return new Tileset
|
||||
{
|
||||
Class = @class,
|
||||
Columns = columns,
|
||||
Columns = columns.Value,
|
||||
FillMode = fillMode,
|
||||
FirstGID = firstGID,
|
||||
Grid = grid,
|
||||
Image = imageModel,
|
||||
Margin = margin,
|
||||
Name = name,
|
||||
Margin = margin.Value,
|
||||
Name = name.Value,
|
||||
ObjectAlignment = objectAlignment,
|
||||
Properties = properties,
|
||||
Source = source,
|
||||
Spacing = spacing,
|
||||
TileCount = tileCount,
|
||||
Spacing = spacing.Value,
|
||||
TileCount = tileCount.Value,
|
||||
TiledVersion = tiledVersion,
|
||||
TileHeight = tileHeight,
|
||||
TileHeight = tileHeight.Value,
|
||||
TileOffset = tileOffset,
|
||||
RenderSize = tileRenderSize,
|
||||
Tiles = tiles,
|
||||
TileWidth = tileWidth,
|
||||
TileWidth = tileWidth.Value,
|
||||
Version = version,
|
||||
Wangsets = wangsets,
|
||||
Transformations = transformations
|
||||
|
@ -171,11 +171,11 @@ public abstract partial class TmjReaderBase
|
|||
|
||||
Optional<Image> imageModel = image.HasValue ? new Image
|
||||
{
|
||||
Format = Helpers.ParseImageFormatFromSource(image),
|
||||
Format = Helpers.ParseImageFormatFromSource(image.Value),
|
||||
Source = image,
|
||||
Height = imageHeight ?? 0,
|
||||
Width = imageWidth ?? 0
|
||||
} : Optional<Image>.Empty;
|
||||
Height = imageHeight.GetValueOr(0),
|
||||
Width = imageWidth.GetValueOr(0)
|
||||
} : Optional.Empty;
|
||||
|
||||
return new Tile
|
||||
{
|
||||
|
|
|
@ -64,10 +64,10 @@ public abstract partial class TmxReaderBase
|
|||
internal static uint[] ReadTileChildrenInWrapper(string wrapper, XmlReader reader) =>
|
||||
reader.ReadList(wrapper, "tile", (r) => r.GetOptionalAttributeParseable<uint>("gid").GetValueOr(0)).ToArray();
|
||||
|
||||
internal static uint[] ReadRawData(XmlReader reader, DataEncoding encoding, Optional<DataCompression> compression)
|
||||
internal static uint[] ReadRawData(XmlReader reader, Optional<DataEncoding> encoding, Optional<DataCompression> compression)
|
||||
{
|
||||
var data = reader.ReadElementContentAsString();
|
||||
if (encoding == DataEncoding.Csv)
|
||||
if (encoding.Value == DataEncoding.Csv)
|
||||
return ParseCsvData(data);
|
||||
|
||||
using var bytes = new MemoryStream(Convert.FromBase64String(data));
|
||||
|
|
|
@ -74,7 +74,7 @@ public abstract partial class TmxReaderBase
|
|||
var template = _reader.GetOptionalAttribute("template");
|
||||
DotTiled.Object obj = null;
|
||||
if (template.HasValue)
|
||||
obj = _externalTemplateResolver(template).Object;
|
||||
obj = _externalTemplateResolver(template.Value).Object;
|
||||
|
||||
uint idDefault = obj?.ID.GetValueOr(0) ?? 0;
|
||||
string nameDefault = obj?.Name ?? "";
|
||||
|
@ -84,7 +84,7 @@ public abstract partial class TmxReaderBase
|
|||
float widthDefault = obj?.Width ?? 0f;
|
||||
float heightDefault = obj?.Height ?? 0f;
|
||||
float rotationDefault = obj?.Rotation ?? 0f;
|
||||
Optional<uint> gidDefault = obj is TileObject tileObj ? tileObj.GID : Optional<uint>.Empty;
|
||||
Optional<uint> gidDefault = obj is TileObject tileObj ? tileObj.GID : Optional.Empty;
|
||||
bool visibleDefault = obj?.Visible ?? true;
|
||||
List<IProperty> propertiesDefault = obj?.Properties ?? null;
|
||||
|
||||
|
@ -242,15 +242,15 @@ public abstract partial class TmxReaderBase
|
|||
internal TextObject ReadTextObject()
|
||||
{
|
||||
// Attributes
|
||||
var fontFamily = _reader.GetOptionalAttribute("fontfamily") ?? "sans-serif";
|
||||
var pixelSize = _reader.GetOptionalAttributeParseable<int>("pixelsize") ?? 16;
|
||||
var wrap = _reader.GetOptionalAttributeParseable<bool>("wrap") ?? false;
|
||||
var color = _reader.GetOptionalAttributeClass<Color>("color") ?? Color.Parse("#000000", CultureInfo.InvariantCulture);
|
||||
var bold = _reader.GetOptionalAttributeParseable<bool>("bold") ?? false;
|
||||
var italic = _reader.GetOptionalAttributeParseable<bool>("italic") ?? false;
|
||||
var underline = _reader.GetOptionalAttributeParseable<bool>("underline") ?? false;
|
||||
var strikeout = _reader.GetOptionalAttributeParseable<bool>("strikeout") ?? false;
|
||||
var kerning = _reader.GetOptionalAttributeParseable<bool>("kerning") ?? true;
|
||||
var fontFamily = _reader.GetOptionalAttribute("fontfamily").GetValueOr("sans-serif");
|
||||
var pixelSize = _reader.GetOptionalAttributeParseable<int>("pixelsize").GetValueOr(16);
|
||||
var wrap = _reader.GetOptionalAttributeParseable<bool>("wrap").GetValueOr(false);
|
||||
var color = _reader.GetOptionalAttributeClass<Color>("color").GetValueOr(Color.Parse("#000000", CultureInfo.InvariantCulture));
|
||||
var bold = _reader.GetOptionalAttributeParseable<bool>("bold").GetValueOr(false);
|
||||
var italic = _reader.GetOptionalAttributeParseable<bool>("italic").GetValueOr(false);
|
||||
var underline = _reader.GetOptionalAttributeParseable<bool>("underline").GetValueOr(false);
|
||||
var strikeout = _reader.GetOptionalAttributeParseable<bool>("strikeout").GetValueOr(false);
|
||||
var kerning = _reader.GetOptionalAttributeParseable<bool>("kerning").GetValueOr(true);
|
||||
var hAlign = _reader.GetOptionalAttributeEnum<TextHorizontalAlignment>("halign", s => s switch
|
||||
{
|
||||
"left" => TextHorizontalAlignment.Left,
|
||||
|
@ -258,14 +258,14 @@ public abstract partial class TmxReaderBase
|
|||
"right" => TextHorizontalAlignment.Right,
|
||||
"justify" => TextHorizontalAlignment.Justify,
|
||||
_ => throw new InvalidOperationException($"Unknown horizontal alignment '{s}'")
|
||||
}) ?? TextHorizontalAlignment.Left;
|
||||
}).GetValueOr(TextHorizontalAlignment.Left);
|
||||
var vAlign = _reader.GetOptionalAttributeEnum<TextVerticalAlignment>("valign", s => s switch
|
||||
{
|
||||
"top" => TextVerticalAlignment.Top,
|
||||
"center" => TextVerticalAlignment.Center,
|
||||
"bottom" => TextVerticalAlignment.Bottom,
|
||||
_ => throw new InvalidOperationException($"Unknown vertical alignment '{s}'")
|
||||
}) ?? TextVerticalAlignment.Top;
|
||||
}).GetValueOr(TextVerticalAlignment.Top);
|
||||
|
||||
// Elements
|
||||
var text = _reader.ReadElementContentAsString("text", "");
|
||||
|
|
|
@ -49,7 +49,7 @@ public abstract partial class TmxReaderBase
|
|||
OffsetY = offsetY,
|
||||
ParallaxX = parallaxX,
|
||||
ParallaxY = parallaxY,
|
||||
Data = data ?? Optional<Data>.Empty,
|
||||
Data = data is null ? Optional.Empty : new Optional<Data>(data),
|
||||
Properties = properties ?? []
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ namespace DotTiled.Serialization.Tmx;
|
|||
public abstract partial class TmxReaderBase
|
||||
{
|
||||
internal Tileset ReadTileset(
|
||||
Optional<string> parentVersion = null,
|
||||
Optional<string> parentTiledVersion = null)
|
||||
Optional<string> parentVersion = default,
|
||||
Optional<string> parentTiledVersion = default)
|
||||
{
|
||||
var firstGID = _reader.GetOptionalAttributeParseable<uint>("firstgid");
|
||||
var source = _reader.GetOptionalAttribute("source");
|
||||
|
@ -18,7 +18,7 @@ public abstract partial class TmxReaderBase
|
|||
if (source.HasValue && firstGID.HasValue)
|
||||
{
|
||||
// Is external tileset
|
||||
var externalTileset = _externalTilesetResolver(source);
|
||||
var externalTileset = _externalTilesetResolver(source.Value);
|
||||
externalTileset.FirstGID = firstGID;
|
||||
externalTileset.Source = source;
|
||||
|
||||
|
@ -136,7 +136,7 @@ public abstract partial class TmxReaderBase
|
|||
});
|
||||
|
||||
if (!format.HasValue && source.HasValue)
|
||||
format = Helpers.ParseImageFormatFromSource(source);
|
||||
format = Helpers.ParseImageFormatFromSource(source.Value);
|
||||
|
||||
return new Image
|
||||
{
|
||||
|
@ -225,11 +225,11 @@ public abstract partial class TmxReaderBase
|
|||
Probability = probability,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width.HasValue ? width : image?.Width ?? 0,
|
||||
Height = height.HasValue ? height : image?.Height ?? 0,
|
||||
Width = width.HasValue ? width.Value : image?.Width.GetValueOr(0) ?? 0,
|
||||
Height = height.HasValue ? height.Value : image?.Height.GetValueOr(0) ?? 0,
|
||||
Properties = properties ?? [],
|
||||
Image = image is null ? Optional<Image>.Empty : image,
|
||||
ObjectLayer = objectLayer is null ? Optional<ObjectLayer>.Empty : objectLayer,
|
||||
Image = image is null ? Optional.Empty : image,
|
||||
ObjectLayer = objectLayer is null ? Optional.Empty : objectLayer,
|
||||
Animation = animation ?? []
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ public class Template
|
|||
/// <summary>
|
||||
/// If the template represents a tile object, this property will contain the tileset that the tile belongs to.
|
||||
/// </summary>
|
||||
public Optional<Tileset> Tileset { get; set; } = Optional<Tileset>.Empty;
|
||||
public Optional<Tileset> Tileset { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The object that this template represents.
|
||||
|
|
|
@ -34,25 +34,25 @@ public class Image
|
|||
/// <summary>
|
||||
/// The format of the image.
|
||||
/// </summary>
|
||||
public Optional<ImageFormat> Format { get; set; } = Optional<ImageFormat>.Empty;
|
||||
public Optional<ImageFormat> Format { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The reference to the image file.
|
||||
/// </summary>
|
||||
public Optional<string> Source { get; set; } = Optional<string>.Empty;
|
||||
public Optional<string> Source { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a specific color that is treated as transparent.
|
||||
/// </summary>
|
||||
public Optional<Color> TransparentColor { get; set; } = Optional<Color>.Empty;
|
||||
public Optional<Color> TransparentColor { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The image width in pixels, used for tile index correction when the image changes.
|
||||
/// </summary>
|
||||
public Optional<uint> Width { get; set; } = Optional<uint>.Empty;
|
||||
public Optional<uint> Width { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The image height in pixels, used for tile index correction when the image changes.
|
||||
/// </summary>
|
||||
public Optional<uint> Height { get; set; } = Optional<uint>.Empty;
|
||||
public Optional<uint> Height { get; set; } = Optional.Empty;
|
||||
}
|
||||
|
|
|
@ -54,12 +54,12 @@ public class Tile : HasPropertiesBase
|
|||
/// <summary>
|
||||
/// The image representing this tile. Only used for tilesets that composed of a collection of images.
|
||||
/// </summary>
|
||||
public Optional<Image> Image { get; set; } = Optional<Image>.Empty;
|
||||
public Optional<Image> Image { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Used when the tile contains e.g. collision information.
|
||||
/// </summary>
|
||||
public Optional<ObjectLayer> ObjectLayer { get; set; } = Optional<ObjectLayer>.Empty;
|
||||
public Optional<ObjectLayer> ObjectLayer { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The animation frames for this tile.
|
||||
|
|
|
@ -103,17 +103,17 @@ public class Tileset : HasPropertiesBase
|
|||
/// <summary>
|
||||
/// The Tiled version used to save the file in case it was loaded from an external tileset file.
|
||||
/// </summary>
|
||||
public Optional<string> TiledVersion { get; set; } = Optional<string>.Empty;
|
||||
public Optional<string> TiledVersion { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The first global tile ID of this tileset (this global ID maps to the first tile in this tileset).
|
||||
/// </summary>
|
||||
public Optional<uint> FirstGID { get; set; } = Optional<uint>.Empty;
|
||||
public Optional<uint> FirstGID { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// If this tileset is stored in an external TSX (Tile Set XML) file, this attribute refers to that file.
|
||||
/// </summary>
|
||||
public Optional<string> Source { get; set; } = Optional<string>.Empty;
|
||||
public Optional<string> Source { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The name of this tileset.
|
||||
|
@ -173,17 +173,17 @@ public class Tileset : HasPropertiesBase
|
|||
/// <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.
|
||||
/// </summary>
|
||||
public Optional<Image> Image { get; set; } = Optional<Image>.Empty;
|
||||
public Optional<Image> Image { get; set; } = Optional.Empty;
|
||||
|
||||
/// <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.
|
||||
/// </summary>
|
||||
public Optional<TileOffset> TileOffset { get; set; } = Optional<TileOffset>.Empty;
|
||||
public Optional<TileOffset> TileOffset { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Ths is only used in case of isometric orientation, and determines how tile overlays for terrain and collision information are rendered.
|
||||
/// </summary>
|
||||
public Optional<Grid> Grid { get; set; } = Optional<Grid>.Empty;
|
||||
public Optional<Grid> Grid { get; set; } = Optional.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Tileset properties.
|
||||
|
@ -203,7 +203,7 @@ public class Tileset : HasPropertiesBase
|
|||
/// <summary>
|
||||
/// Used to describe which transformations can be applied to the tiles (e.g. to extend a Wang set by transforming existing tiles).
|
||||
/// </summary>
|
||||
public Optional<Transformations> Transformations { get; set; } = Optional<Transformations>.Empty;
|
||||
public Optional<Transformations> Transformations { get; set; } = Optional.Empty;
|
||||
|
||||
/// <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.
|
||||
|
|
Loading…
Add table
Reference in a new issue