mirror of
https://github.com/dcronqvist/DotTiled.git
synced 2025-02-05 08:52:50 +02:00
Stuck on how to handle class properties
This commit is contained in:
parent
0f05bd10aa
commit
2a10ebb496
3 changed files with 296 additions and 105 deletions
|
@ -14,12 +14,45 @@ public partial class TmjMapReaderTests
|
||||||
"nextobjectid":1,
|
"nextobjectid":1,
|
||||||
"nextlayerid":1,
|
"nextlayerid":1,
|
||||||
"orientation":"orthogonal",
|
"orientation":"orthogonal",
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name":"mapProperty1",
|
||||||
|
"type":"string",
|
||||||
|
"value":"one"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapProperty3",
|
||||||
|
"type":"string",
|
||||||
|
"value":"twoeee"
|
||||||
|
}
|
||||||
|
],
|
||||||
"renderorder":"right-down",
|
"renderorder":"right-down",
|
||||||
"tileheight":32,
|
"tileheight":32,
|
||||||
"tilewidth":32,
|
"tilewidth":32,
|
||||||
"version":"1",
|
"version":"1",
|
||||||
"tiledversion":"1.0.3",
|
"tiledversion":"1.0.3",
|
||||||
"width":4
|
"width":4,
|
||||||
|
"tilesets": [
|
||||||
|
{
|
||||||
|
"columns":19,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"image/fishbaddie_parts.png",
|
||||||
|
"imageheight":480,
|
||||||
|
"imagewidth":640,
|
||||||
|
"margin":3,
|
||||||
|
"name":"",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"myProperty1",
|
||||||
|
"type":"string",
|
||||||
|
"value":"myProperty1_value"
|
||||||
|
}],
|
||||||
|
"spacing":1,
|
||||||
|
"tilecount":266,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
|
|
@ -14,40 +14,26 @@ internal partial class Tmj
|
||||||
internal string PropertyName { get; } = propertyName;
|
internal string PropertyName { get; } = propertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class RequiredProperty<T>(string propertyName, Action<T> withValue) : JsonProperty(propertyName)
|
internal delegate void UseReader(ref Utf8JsonReader reader);
|
||||||
|
|
||||||
|
internal class RequiredProperty(string propertyName, UseReader useReader) : JsonProperty(propertyName)
|
||||||
{
|
{
|
||||||
internal Action<T> WithValue { get; } = withValue;
|
internal UseReader UseReader { get; } = useReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class OptionalProperty<T>(string propertyName, Action<T?> withValue, bool allowNull = false) : JsonProperty(propertyName)
|
internal class OptionalProperty(string propertyName, UseReader useReader, bool allowNull = true) : JsonProperty(propertyName)
|
||||||
{
|
{
|
||||||
internal Action<T?> WithValue { get; } = withValue;
|
internal UseReader UseReader { get; } = useReader;
|
||||||
internal bool AllowNull { get; } = allowNull;
|
internal bool AllowNull { get; } = allowNull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class ExtensionsUtf8JsonReader
|
internal static class ExtensionsUtf8JsonReader
|
||||||
{
|
{
|
||||||
private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck)
|
internal static T Progress<T>(ref this Utf8JsonReader reader, T value)
|
||||||
{
|
{
|
||||||
while (toCheck != typeof(object))
|
reader.Read();
|
||||||
{
|
return value;
|
||||||
var cur = toCheck!.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
|
|
||||||
if (generic == cur)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
toCheck = toCheck.BaseType!;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Require<T>(this ref Utf8JsonReader reader, ProcessProperty process)
|
|
||||||
{
|
|
||||||
if (reader.TokenType == JsonTokenType.Null)
|
|
||||||
throw new JsonException("Value is required.");
|
|
||||||
|
|
||||||
process(ref reader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void MoveToContent(this ref Utf8JsonReader reader)
|
internal static void MoveToContent(this ref Utf8JsonReader reader)
|
||||||
|
@ -59,16 +45,15 @@ internal static class ExtensionsUtf8JsonReader
|
||||||
|
|
||||||
internal delegate void ProcessProperty(ref Utf8JsonReader reader);
|
internal delegate void ProcessProperty(ref Utf8JsonReader reader);
|
||||||
|
|
||||||
internal static void ProcessJsonObject(this Utf8JsonReader reader, (string PropertyName, ProcessProperty Processor)[] processors)
|
private static void ProcessJsonObject(this ref Utf8JsonReader reader, (string PropertyName, ProcessProperty Processor)[] processors)
|
||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.StartObject)
|
if (reader.TokenType != JsonTokenType.StartObject)
|
||||||
throw new JsonException("Expected start of object.");
|
throw new JsonException("Expected start of object.");
|
||||||
|
|
||||||
while (reader.Read())
|
reader.Read();
|
||||||
{
|
|
||||||
if (reader.TokenType == JsonTokenType.EndObject)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
while (reader.TokenType != JsonTokenType.EndObject)
|
||||||
|
{
|
||||||
if (reader.TokenType != JsonTokenType.PropertyName)
|
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||||
throw new JsonException("Expected property name.");
|
throw new JsonException("Expected property name.");
|
||||||
|
|
||||||
|
@ -77,7 +62,11 @@ internal static class ExtensionsUtf8JsonReader
|
||||||
|
|
||||||
if (!processors.Any(x => x.PropertyName == propertyName))
|
if (!processors.Any(x => x.PropertyName == propertyName))
|
||||||
{
|
{
|
||||||
reader.Skip();
|
var depthBefore = reader.CurrentDepth;
|
||||||
|
|
||||||
|
while (reader.TokenType != JsonTokenType.PropertyName || reader.CurrentDepth > depthBefore)
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,74 +74,66 @@ internal static class ExtensionsUtf8JsonReader
|
||||||
processor(ref reader);
|
processor(ref reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new JsonException("Expected end of object.");
|
if (reader.TokenType != JsonTokenType.EndObject)
|
||||||
|
throw new JsonException("Expected end of object.");
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate T UseReader<T>(ref Utf8JsonReader reader);
|
internal static void ProcessJsonObject(this ref Utf8JsonReader reader, Tmj.JsonProperty[] properties, string objectTypeName)
|
||||||
|
|
||||||
internal static void ProcessJsonObject(this Utf8JsonReader reader, Tmj.JsonProperty[] properties)
|
|
||||||
{
|
{
|
||||||
List<string> processedProperties = [];
|
List<string> processedProperties = [];
|
||||||
|
|
||||||
bool CheckType<T>(ref Utf8JsonReader reader, Tmj.JsonProperty prop, UseReader<T?> useReader)
|
ProcessJsonObject(ref reader, properties.Select<Tmj.JsonProperty, (string, ProcessProperty)>(x => (x.PropertyName, (ref Utf8JsonReader reader) =>
|
||||||
{
|
{
|
||||||
return CheckRequire<T>(ref reader, prop, (ref Utf8JsonReader r) => useReader(ref r)!) || CheckOptional<T>(ref reader, prop, useReader);
|
if (processedProperties.Contains(x.PropertyName))
|
||||||
}
|
throw new JsonException($"Property '{x.PropertyName}' was already processed.");
|
||||||
|
|
||||||
bool CheckRequire<T>(ref Utf8JsonReader reader, Tmj.JsonProperty prop, UseReader<T> useReader)
|
processedProperties.Add(x.PropertyName);
|
||||||
{
|
|
||||||
if (prop is Tmj.RequiredProperty<T> requiredProp)
|
if (x is Tmj.RequiredProperty req)
|
||||||
{
|
{
|
||||||
reader.Require<string>((ref Utf8JsonReader r) =>
|
if (reader.TokenType == JsonTokenType.Null)
|
||||||
{
|
throw new JsonException($"Required property '{req.PropertyName}' cannot be null when reading {objectTypeName}.");
|
||||||
requiredProp.WithValue(useReader(ref r));
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckOptional<T>(ref Utf8JsonReader reader, Tmj.JsonProperty prop, UseReader<T?> useReader)
|
req.UseReader(ref reader);
|
||||||
{
|
}
|
||||||
if (prop is Tmj.OptionalProperty<T> optionalProp)
|
else if (x is Tmj.OptionalProperty opt)
|
||||||
{
|
{
|
||||||
if (reader.TokenType == JsonTokenType.Null && !optionalProp.AllowNull)
|
if (reader.TokenType == JsonTokenType.Null && !opt.AllowNull)
|
||||||
throw new JsonException("Value cannot be null for optional property.");
|
throw new JsonException($"Value cannot be null for optional property '{opt.PropertyName}' when reading {objectTypeName}.");
|
||||||
else if (reader.TokenType == JsonTokenType.Null && optionalProp.AllowNull)
|
else if (reader.TokenType == JsonTokenType.Null && opt.AllowNull)
|
||||||
optionalProp.WithValue(default);
|
return;
|
||||||
else
|
|
||||||
optionalProp.WithValue(useReader(ref reader));
|
opt.UseReader(ref reader);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessJsonObject(reader, properties.Select<Tmj.JsonProperty, (string, ProcessProperty)>(x => (x.PropertyName.ToLowerInvariant(), (ref Utf8JsonReader reader) =>
|
|
||||||
{
|
|
||||||
var lowerInvariant = x.PropertyName.ToLowerInvariant();
|
|
||||||
|
|
||||||
if (processedProperties.Contains(lowerInvariant))
|
|
||||||
throw new JsonException($"Property '{lowerInvariant}' was already processed.");
|
|
||||||
|
|
||||||
processedProperties.Add(lowerInvariant);
|
|
||||||
|
|
||||||
if (CheckType<string>(ref reader, x, (ref Utf8JsonReader r) => r.GetString()!))
|
|
||||||
return;
|
|
||||||
if (CheckType<int>(ref reader, x, (ref Utf8JsonReader r) => r.GetInt32()))
|
|
||||||
return;
|
|
||||||
if (CheckType<uint>(ref reader, x, (ref Utf8JsonReader r) => r.GetUInt32()))
|
|
||||||
return;
|
|
||||||
if (CheckType<float>(ref reader, x, (ref Utf8JsonReader r) => r.GetSingle()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
throw new NotSupportedException($"Unsupported property type '{x.GetType().GenericTypeArguments.First()}'.");
|
|
||||||
}
|
}
|
||||||
)).ToArray());
|
)).ToArray());
|
||||||
|
|
||||||
foreach (var property in properties)
|
foreach (var property in properties)
|
||||||
{
|
{
|
||||||
if (IsSubclassOfRawGeneric(typeof(Tmj.RequiredProperty<>), property.GetType()) && !processedProperties.Contains(property.PropertyName.ToLowerInvariant()))
|
if (property is Tmj.RequiredProperty && !processedProperties.Contains(property.PropertyName))
|
||||||
throw new JsonException($"Required property '{property.PropertyName}' was not found.");
|
throw new JsonException($"Required property '{property.PropertyName}' was not found when reading {objectTypeName}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal delegate void UseReader(ref Utf8JsonReader reader);
|
||||||
|
|
||||||
|
internal static void ProcessJsonArray(this ref Utf8JsonReader reader, UseReader useReader)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonTokenType.StartArray)
|
||||||
|
throw new JsonException("Expected start of array.");
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
while (reader.TokenType != JsonTokenType.EndArray)
|
||||||
|
{
|
||||||
|
useReader(ref reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonTokenType.EndArray)
|
||||||
|
throw new JsonException("Expected end of array.");
|
||||||
|
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace DotTiled;
|
namespace DotTiled;
|
||||||
|
@ -27,11 +29,18 @@ internal partial class Tmj
|
||||||
uint nextObjectID = 0;
|
uint nextObjectID = 0;
|
||||||
bool infinite = false;
|
bool infinite = false;
|
||||||
|
|
||||||
|
// At most one of
|
||||||
|
Dictionary<string, IProperty>? properties = null;
|
||||||
|
|
||||||
|
// Any number of
|
||||||
|
List<BaseLayer> layers = [];
|
||||||
|
List<Tileset> tilesets = [];
|
||||||
|
|
||||||
reader.ProcessJsonObject([
|
reader.ProcessJsonObject([
|
||||||
new RequiredProperty<string>("version", value => version = value),
|
new RequiredProperty("version", (ref Utf8JsonReader reader) => version = reader.Progress(reader.GetString()!)),
|
||||||
new RequiredProperty<string>("tiledVersion", value => tiledVersion = value),
|
new RequiredProperty("tiledversion", (ref Utf8JsonReader reader) => tiledVersion = reader.Progress(reader.GetString()!)),
|
||||||
new OptionalProperty<string>("class", value => @class = value ?? ""),
|
new OptionalProperty("class", (ref Utf8JsonReader reader) => @class = reader.Progress(reader.GetString() ?? ""), allowNull: true),
|
||||||
new RequiredProperty<string>("orientation", value => orientation = value switch
|
new RequiredProperty("orientation", (ref Utf8JsonReader reader) => orientation = reader.Progress(reader.GetString()) switch
|
||||||
{
|
{
|
||||||
"orthogonal" => MapOrientation.Orthogonal,
|
"orthogonal" => MapOrientation.Orthogonal,
|
||||||
"isometric" => MapOrientation.Isometric,
|
"isometric" => MapOrientation.Isometric,
|
||||||
|
@ -39,7 +48,7 @@ internal partial class Tmj
|
||||||
"hexagonal" => MapOrientation.Hexagonal,
|
"hexagonal" => MapOrientation.Hexagonal,
|
||||||
_ => throw new JsonException("Invalid orientation.")
|
_ => throw new JsonException("Invalid orientation.")
|
||||||
}),
|
}),
|
||||||
new OptionalProperty<string>("renderOrder", value => renderOrder = value switch
|
new OptionalProperty("renderorder", (ref Utf8JsonReader reader) => renderOrder = reader.Progress(reader.GetString()) switch
|
||||||
{
|
{
|
||||||
"right-down" => RenderOrder.RightDown,
|
"right-down" => RenderOrder.RightDown,
|
||||||
"right-up" => RenderOrder.RightUp,
|
"right-up" => RenderOrder.RightUp,
|
||||||
|
@ -47,31 +56,34 @@ internal partial class Tmj
|
||||||
"left-up" => RenderOrder.LeftUp,
|
"left-up" => RenderOrder.LeftUp,
|
||||||
_ => throw new JsonException("Invalid render order.")
|
_ => throw new JsonException("Invalid render order.")
|
||||||
}),
|
}),
|
||||||
new OptionalProperty<int>("compressionLevel", value => compressionLevel = value),
|
new OptionalProperty("compressionlevel", (ref Utf8JsonReader reader) => compressionLevel = reader.Progress(reader.GetInt32())),
|
||||||
new RequiredProperty<uint>("width", value => width = value),
|
new RequiredProperty("width", (ref Utf8JsonReader reader) => width = reader.Progress(reader.GetUInt32())),
|
||||||
new RequiredProperty<uint>("height", value => height = value),
|
new RequiredProperty("height", (ref Utf8JsonReader reader) => height = reader.Progress(reader.GetUInt32())),
|
||||||
new RequiredProperty<uint>("tileWidth", value => tileWidth = value),
|
new RequiredProperty("tilewidth", (ref Utf8JsonReader reader) => tileWidth = reader.Progress(reader.GetUInt32())),
|
||||||
new RequiredProperty<uint>("tileHeight", value => tileHeight = value),
|
new RequiredProperty("tileheight", (ref Utf8JsonReader reader) => tileHeight = reader.Progress(reader.GetUInt32())),
|
||||||
new OptionalProperty<uint>("hexSideLength", value => hexSideLength = value),
|
new OptionalProperty("hexsidelength", (ref Utf8JsonReader reader) => hexSideLength = reader.Progress(reader.GetUInt32())),
|
||||||
new OptionalProperty<string>("staggerAxis", value => staggerAxis = value switch
|
new OptionalProperty("staggeraxis", (ref Utf8JsonReader reader) => staggerAxis = reader.Progress(reader.GetString()) switch
|
||||||
{
|
{
|
||||||
"x" => StaggerAxis.X,
|
"x" => StaggerAxis.X,
|
||||||
"y" => StaggerAxis.Y,
|
"y" => StaggerAxis.Y,
|
||||||
_ => throw new JsonException("Invalid stagger axis.")
|
_ => throw new JsonException("Invalid stagger axis.")
|
||||||
}),
|
}),
|
||||||
new OptionalProperty<string>("staggerIndex", value => staggerIndex = value switch
|
new OptionalProperty("staggerindex", (ref Utf8JsonReader reader) => staggerIndex = reader.Progress(reader.GetString()) switch
|
||||||
{
|
{
|
||||||
"odd" => StaggerIndex.Odd,
|
"odd" => StaggerIndex.Odd,
|
||||||
"even" => StaggerIndex.Even,
|
"even" => StaggerIndex.Even,
|
||||||
_ => throw new JsonException("Invalid stagger index.")
|
_ => throw new JsonException("Invalid stagger index.")
|
||||||
}),
|
}),
|
||||||
new OptionalProperty<float>("parallaxOriginX", value => parallaxOriginX = value),
|
new OptionalProperty("parallaxoriginx", (ref Utf8JsonReader reader) => parallaxOriginX = reader.Progress(reader.GetSingle())),
|
||||||
new OptionalProperty<float>("parallaxOriginY", value => parallaxOriginY = value),
|
new OptionalProperty("parallaxoriginy", (ref Utf8JsonReader reader) => parallaxOriginY = reader.Progress(reader.GetSingle())),
|
||||||
new OptionalProperty<string>("backgroundColor", value => backgroundColor = Color.Parse(value!, CultureInfo.InvariantCulture)),
|
new OptionalProperty("backgroundcolor", (ref Utf8JsonReader reader) => backgroundColor = Color.Parse(reader.Progress(reader.GetString()!), CultureInfo.InvariantCulture)),
|
||||||
new RequiredProperty<uint>("nextLayerID", value => nextLayerID = value),
|
new RequiredProperty("nextlayerid", (ref Utf8JsonReader reader) => nextLayerID = reader.Progress(reader.GetUInt32())),
|
||||||
new RequiredProperty<uint>("nextObjectID", value => nextObjectID = value),
|
new RequiredProperty("nextobjectid", (ref Utf8JsonReader reader) => nextObjectID = reader.Progress(reader.GetUInt32())),
|
||||||
new OptionalProperty<uint>("infinite", value => infinite = value == 1)
|
new OptionalProperty("infinite", (ref Utf8JsonReader reader) => infinite = reader.Progress(reader.GetUInt32()) == 1),
|
||||||
]);
|
|
||||||
|
new OptionalProperty("properties", (ref Utf8JsonReader reader) => properties = ReadProperties(ref reader)),
|
||||||
|
new OptionalProperty("tilesets", (ref Utf8JsonReader reader) => tilesets = ReadTilesets(ref reader))
|
||||||
|
], "map");
|
||||||
|
|
||||||
return new Map
|
return new Map
|
||||||
{
|
{
|
||||||
|
@ -94,9 +106,174 @@ internal partial class Tmj
|
||||||
NextLayerID = nextLayerID,
|
NextLayerID = nextLayerID,
|
||||||
NextObjectID = nextObjectID,
|
NextObjectID = nextObjectID,
|
||||||
Infinite = infinite,
|
Infinite = infinite,
|
||||||
//Properties = properties,
|
Properties = properties,
|
||||||
//Tilesets = tilesets,
|
Tilesets = tilesets,
|
||||||
//Layers = layers
|
Layers = layers
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Dictionary<string, IProperty> ReadProperties(ref Utf8JsonReader reader)
|
||||||
|
{
|
||||||
|
var properties = new Dictionary<string, IProperty>();
|
||||||
|
|
||||||
|
reader.ProcessJsonArray((ref Utf8JsonReader reader) =>
|
||||||
|
{
|
||||||
|
var property = ReadProperty(ref reader);
|
||||||
|
properties.Add(property.Name, property);
|
||||||
|
});
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IProperty ReadProperty(ref Utf8JsonReader reader)
|
||||||
|
{
|
||||||
|
string name = default!;
|
||||||
|
string type = default!;
|
||||||
|
IProperty property = null;
|
||||||
|
|
||||||
|
reader.ProcessJsonObject([
|
||||||
|
new RequiredProperty("name", (ref Utf8JsonReader reader) => name = reader.Progress(reader.GetString()!)),
|
||||||
|
new RequiredProperty("type", (ref Utf8JsonReader reader) => type = reader.Progress(reader.GetString()!)),
|
||||||
|
new RequiredProperty("value", (ref Utf8JsonReader reader) =>
|
||||||
|
{
|
||||||
|
property = type switch
|
||||||
|
{
|
||||||
|
"string" => new StringProperty { Name = name, Value = reader.Progress(reader.GetString()!) },
|
||||||
|
"int" => new IntProperty { Name = name, Value = reader.Progress(reader.GetInt32()) },
|
||||||
|
"float" => new FloatProperty { Name = name, Value = reader.Progress(reader.GetSingle()) },
|
||||||
|
"bool" => new BoolProperty { Name = name, Value = reader.Progress(reader.GetBoolean()) },
|
||||||
|
"color" => new ColorProperty { Name = name, Value = Color.Parse(reader.Progress(reader.GetString()!), CultureInfo.InvariantCulture) },
|
||||||
|
"file" => new FileProperty { Name = name, Value = reader.Progress(reader.GetString()!) },
|
||||||
|
"object" => new ObjectProperty { Name = name, Value = reader.Progress(reader.GetUInt32()) },
|
||||||
|
// "class" => ReadClassProperty(ref reader),
|
||||||
|
_ => throw new JsonException("Invalid property type.")
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
], "property");
|
||||||
|
|
||||||
|
return property!;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<Tileset> ReadTilesets(ref Utf8JsonReader reader)
|
||||||
|
{
|
||||||
|
var tilesets = new List<Tileset>();
|
||||||
|
|
||||||
|
reader.ProcessJsonArray((ref Utf8JsonReader reader) =>
|
||||||
|
{
|
||||||
|
var tileset = ReadTileset(ref reader);
|
||||||
|
tilesets.Add(tileset);
|
||||||
|
});
|
||||||
|
|
||||||
|
return tilesets;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Tileset ReadTileset(ref Utf8JsonReader reader)
|
||||||
|
{
|
||||||
|
string? version = null;
|
||||||
|
string? tiledVersion = null;
|
||||||
|
uint? firstGID = null;
|
||||||
|
string? source = null;
|
||||||
|
string? name = null;
|
||||||
|
string @class = "";
|
||||||
|
uint? tileWidth = null;
|
||||||
|
uint? tileHeight = null;
|
||||||
|
uint? spacing = null;
|
||||||
|
uint? margin = null;
|
||||||
|
uint? tileCount = null;
|
||||||
|
uint? columns = null;
|
||||||
|
ObjectAlignment objectAlignment = ObjectAlignment.Unspecified;
|
||||||
|
FillMode fillMode = FillMode.Stretch;
|
||||||
|
|
||||||
|
string? image = null;
|
||||||
|
uint? imageWidth = null;
|
||||||
|
uint? imageHeight = null;
|
||||||
|
|
||||||
|
Dictionary<string, IProperty>? properties = null;
|
||||||
|
|
||||||
|
reader.ProcessJsonObject([
|
||||||
|
new OptionalProperty("version", (ref Utf8JsonReader reader) => version = reader.Progress(reader.GetString())),
|
||||||
|
new OptionalProperty("tiledversion", (ref Utf8JsonReader reader) => tiledVersion = reader.Progress(reader.GetString())),
|
||||||
|
new OptionalProperty("firstgid", (ref Utf8JsonReader reader) => firstGID = reader.Progress(reader.GetUInt32())),
|
||||||
|
new OptionalProperty("source", (ref Utf8JsonReader reader) => source = reader.Progress(reader.GetString())),
|
||||||
|
new OptionalProperty("name", (ref Utf8JsonReader reader) => name = reader.Progress(reader.GetString())),
|
||||||
|
new OptionalProperty("class", (ref Utf8JsonReader reader) => @class = reader.Progress(reader.GetString() ?? ""), allowNull: true),
|
||||||
|
new OptionalProperty("tilewidth", (ref Utf8JsonReader reader) => tileWidth = reader.Progress(reader.GetUInt32())),
|
||||||
|
new OptionalProperty("tileheight", (ref Utf8JsonReader reader) => tileHeight = reader.Progress(reader.GetUInt32())),
|
||||||
|
new OptionalProperty("spacing", (ref Utf8JsonReader reader) => spacing = reader.Progress(reader.GetUInt32())),
|
||||||
|
new OptionalProperty("margin", (ref Utf8JsonReader reader) => margin = reader.Progress(reader.GetUInt32())),
|
||||||
|
new OptionalProperty("tilecount", (ref Utf8JsonReader reader) => tileCount = reader.Progress(reader.GetUInt32())),
|
||||||
|
new OptionalProperty("columns", (ref Utf8JsonReader reader) => columns = reader.Progress(reader.GetUInt32())),
|
||||||
|
new OptionalProperty("objectalignment", (ref Utf8JsonReader reader) => objectAlignment = reader.Progress(reader.GetString()) switch
|
||||||
|
{
|
||||||
|
"unspecified" => ObjectAlignment.Unspecified,
|
||||||
|
"topleft" => ObjectAlignment.TopLeft,
|
||||||
|
"top" => ObjectAlignment.Top,
|
||||||
|
"topright" => ObjectAlignment.TopRight,
|
||||||
|
"left" => ObjectAlignment.Left,
|
||||||
|
"center" => ObjectAlignment.Center,
|
||||||
|
"right" => ObjectAlignment.Right,
|
||||||
|
"bottomleft" => ObjectAlignment.BottomLeft,
|
||||||
|
"bottom" => ObjectAlignment.Bottom,
|
||||||
|
"bottomright" => ObjectAlignment.BottomRight,
|
||||||
|
_ => throw new JsonException("Invalid object alignment.")
|
||||||
|
}),
|
||||||
|
new OptionalProperty("fillmode", (ref Utf8JsonReader reader) => fillMode = reader.Progress(reader.GetString()) switch
|
||||||
|
{
|
||||||
|
"stretch" => FillMode.Stretch,
|
||||||
|
"preserve-aspect-fit" => FillMode.PreserveAspectFit,
|
||||||
|
_ => throw new JsonException("Invalid fill mode.")
|
||||||
|
}),
|
||||||
|
|
||||||
|
new OptionalProperty("image", (ref Utf8JsonReader reader) => image = reader.Progress(reader.GetString())),
|
||||||
|
new OptionalProperty("imagewidth", (ref Utf8JsonReader reader) => imageWidth = reader.Progress(reader.GetUInt32())),
|
||||||
|
new OptionalProperty("imageheight", (ref Utf8JsonReader reader) => imageHeight = reader.Progress(reader.GetUInt32())),
|
||||||
|
|
||||||
|
new OptionalProperty("properties", (ref Utf8JsonReader reader) => properties = ReadProperties(ref reader))
|
||||||
|
], "tileset");
|
||||||
|
|
||||||
|
Image? imageInstance = image is not null ? new Image
|
||||||
|
{
|
||||||
|
Format = ParseImageFormatFromSource(image),
|
||||||
|
Width = imageWidth,
|
||||||
|
Height = imageHeight,
|
||||||
|
Source = image
|
||||||
|
} : null;
|
||||||
|
|
||||||
|
return new Tileset
|
||||||
|
{
|
||||||
|
Version = version,
|
||||||
|
TiledVersion = tiledVersion,
|
||||||
|
FirstGID = firstGID,
|
||||||
|
Source = source,
|
||||||
|
Name = name,
|
||||||
|
Class = @class,
|
||||||
|
TileWidth = tileWidth,
|
||||||
|
TileHeight = tileHeight,
|
||||||
|
Spacing = spacing,
|
||||||
|
Margin = margin,
|
||||||
|
TileCount = tileCount,
|
||||||
|
Columns = columns,
|
||||||
|
ObjectAlignment = objectAlignment,
|
||||||
|
FillMode = fillMode,
|
||||||
|
Image = imageInstance,
|
||||||
|
Properties = properties
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImageFormat ParseImageFormatFromSource(string? source)
|
||||||
|
{
|
||||||
|
if (source is null)
|
||||||
|
throw new JsonException("Image source is required to determine image format.");
|
||||||
|
|
||||||
|
var extension = Path.GetExtension(source);
|
||||||
|
return extension switch
|
||||||
|
{
|
||||||
|
".png" => ImageFormat.Png,
|
||||||
|
".jpg" => ImageFormat.Jpg,
|
||||||
|
".jpeg" => ImageFormat.Jpg,
|
||||||
|
".gif" => ImageFormat.Gif,
|
||||||
|
".bmp" => ImageFormat.Bmp,
|
||||||
|
_ => throw new JsonException("Invalid image format.")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue