wip: Serialization
This commit is contained in:
parent
2cf6135063
commit
361a7c53b9
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
|
||||
using Engine.Serialization.DTOs;
|
||||
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Core.Events;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Engine.Serialization;
|
||||
|
||||
internal class BehaviourYamlConverter : IYamlTypeConverter
|
||||
{
|
||||
public bool Accepts(Type type) => type == typeof(BehaviourDTO);
|
||||
|
||||
public object ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
if (parser.Current is not MappingStart)
|
||||
throw new InvalidOperationException("Expected MappingStart");
|
||||
|
||||
parser.MoveNext();
|
||||
var behaviour = new BehaviourDTO();
|
||||
while (parser.Current != null && parser.Current is not MappingEnd)
|
||||
{
|
||||
var propertyName = ((Scalar)parser.Current).Value;
|
||||
parser.MoveNext();
|
||||
switch (propertyName)
|
||||
{
|
||||
case nameof(BehaviourDTO.ClassName):
|
||||
behaviour.ClassName = ((Scalar)parser.Current).Value;
|
||||
break;
|
||||
case nameof(BehaviourDTO.Priority):
|
||||
behaviour.Priority = int.Parse(((Scalar)parser.Current).Value);
|
||||
break;
|
||||
case nameof(BehaviourDTO.StateEnable):
|
||||
behaviour.StateEnable = (StateEnableDTO)(new StateEnableYamlConverter().ReadYaml(parser, typeof(StateEnableDTO)) ?? new Exception());
|
||||
break;
|
||||
}
|
||||
parser.MoveNext();
|
||||
}
|
||||
return behaviour;
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type)
|
||||
{
|
||||
var behaviour = (BehaviourDTO)(value ?? throw new Exception());
|
||||
|
||||
StateEnableYamlConverter stateEnableYamlConverter = new();
|
||||
|
||||
emitter.Emit(new MappingStart());
|
||||
|
||||
emitter.Emit(new Scalar(nameof(BehaviourDTO.ClassName)));
|
||||
emitter.Emit(new Scalar(behaviour.ClassName.ToString()));
|
||||
|
||||
emitter.Emit(new Scalar(nameof(BehaviourDTO.Priority)));
|
||||
emitter.Emit(new Scalar(behaviour.Priority.ToString()));
|
||||
|
||||
emitter.Emit(new Scalar(nameof(BehaviourDTO.StateEnable)));
|
||||
stateEnableYamlConverter.WriteYaml(emitter, behaviour.StateEnable, typeof(StateEnableDTO));
|
||||
|
||||
emitter.Emit(new MappingEnd());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace Engine.Serialization.DTOs;
|
||||
|
||||
internal record struct BehaviourDTO(
|
||||
string ClassName,
|
||||
int Priority,
|
||||
StateEnableDTO StateEnable
|
||||
);
|
|
@ -0,0 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Engine.Serialization.DTOs;
|
||||
|
||||
internal record struct GameObjectDTO(
|
||||
string Id,
|
||||
string Name,
|
||||
TransformDTO Transform,
|
||||
List<BehaviourDTO> Behaviours,
|
||||
StateEnableDTO StateEnable
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
namespace Engine.Serialization.DTOs;
|
||||
|
||||
internal record struct StateEnableDTO(
|
||||
string ClassName,
|
||||
bool Enabled
|
||||
);
|
|
@ -0,0 +1,10 @@
|
|||
using Syntriax.Engine.Core;
|
||||
|
||||
namespace Engine.Serialization.DTOs;
|
||||
|
||||
internal record struct TransformDTO(
|
||||
string? ParentId,
|
||||
Vector2D Position,
|
||||
Vector2D Scale,
|
||||
float Rotation
|
||||
);
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YamlDotNet" Version="15.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Engine.Core\Engine.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Engine.Serialization.DTOs;
|
||||
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Core.Events;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Engine.Serialization;
|
||||
|
||||
internal class GameObjectYamlConverter : IYamlTypeConverter
|
||||
{
|
||||
public bool Accepts(Type type) => type == typeof(GameObjectDTO);
|
||||
|
||||
public object ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
if (parser.Current is not MappingStart)
|
||||
throw new InvalidOperationException("Expected MappingStart");
|
||||
|
||||
parser.MoveNext();
|
||||
var gameObject = new GameObjectDTO();
|
||||
while (parser.Current != null && parser.Current is not MappingEnd)
|
||||
{
|
||||
var propertyName = ((Scalar)parser.Current).Value;
|
||||
parser.MoveNext();
|
||||
switch (propertyName)
|
||||
{
|
||||
case nameof(GameObjectDTO.Id):
|
||||
gameObject.Id = ((Scalar)parser.Current).Value;
|
||||
break;
|
||||
case nameof(GameObjectDTO.Name):
|
||||
gameObject.Name = ((Scalar)parser.Current).Value;
|
||||
break;
|
||||
case nameof(GameObjectDTO.Transform):
|
||||
gameObject.Transform = (TransformDTO)(new TransformYamlConverter().ReadYaml(parser, typeof(TransformDTO)) ?? new Exception());
|
||||
break;
|
||||
// case nameof(GameObjectDTO.Behaviours):
|
||||
// gameObject.Rotation = (List<BehaviourDTO>)(new BehaviourYamlConverter().ReadYaml(parser, typeof(BehaviourDTO)) ?? new Exception());
|
||||
// break;
|
||||
case nameof(GameObjectDTO.StateEnable):
|
||||
gameObject.StateEnable = (StateEnableDTO)(new StateEnableYamlConverter().ReadYaml(parser, typeof(StateEnableDTO)) ?? new Exception());
|
||||
break;
|
||||
}
|
||||
parser.MoveNext();
|
||||
}
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type)
|
||||
{
|
||||
var gameObject = (GameObjectDTO)(value ?? throw new Exception());
|
||||
|
||||
Vector2DYamlConverter vector2DYamlConverter = new();
|
||||
StateEnableYamlConverter stateEnableYamlConverter = new();
|
||||
|
||||
emitter.Emit(new MappingStart());
|
||||
emitter.Emit(new Scalar(nameof(GameObjectDTO.Id)));
|
||||
emitter.Emit(new Scalar(gameObject.Id.ToString()));
|
||||
emitter.Emit(new Scalar(nameof(GameObjectDTO.Name)));
|
||||
emitter.Emit(new Scalar(gameObject.Name.ToString()));
|
||||
emitter.Emit(new Scalar(nameof(GameObjectDTO.Transform)));
|
||||
vector2DYamlConverter.WriteYaml(emitter, gameObject.Transform, typeof(TransformDTO));
|
||||
// emitter.Emit(new Scalar(nameof(GameObjectDTO.Behaviours)));
|
||||
// vector2DYamlConverter.WriteYaml(emitter, gameObject.Behaviours, typeof(BehavioursDTO));
|
||||
emitter.Emit(new Scalar(nameof(GameObjectDTO.StateEnable)));
|
||||
stateEnableYamlConverter.WriteYaml(emitter, gameObject.StateEnable, typeof(StateEnableDTO));
|
||||
emitter.Emit(new MappingEnd());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace Engine.Serialization;
|
||||
|
||||
public interface ISerializer
|
||||
{
|
||||
public string Serialize<T>(T @object);
|
||||
public T Deserialize<T>(string serializedString);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using System.Collections.Generic;
|
||||
using Engine.Serialization.DTOs;
|
||||
using Syntriax.Engine.Core.Abstract;
|
||||
|
||||
namespace Engine.Serialization;
|
||||
|
||||
internal static class InternalExtensions
|
||||
{
|
||||
public static TransformDTO ToDTO(this ITransform transform)
|
||||
=> new(transform.Parent?.GameObject.Id, transform.Position, transform.Scale, transform.Rotation);
|
||||
|
||||
public static GameObjectDTO ToDTO(this IGameObject gameObject)
|
||||
=> new(gameObject.Id, gameObject.Name, gameObject.Transform.ToDTO(), gameObject.BehaviourController.ToDTO(), gameObject.StateEnable.ToDTO());
|
||||
|
||||
public static StateEnableDTO ToDTO(this IStateEnable stateEnable)
|
||||
=> new(stateEnable.GetType().FullName ?? throw new System.Exception(), stateEnable.Enabled);
|
||||
|
||||
public static List<BehaviourDTO> ToDTO(this IBehaviourController behaviourController)
|
||||
{
|
||||
List<BehaviourDTO> dtos = [];
|
||||
foreach (var behaviour in behaviourController)
|
||||
dtos.Add(new(behaviour.GetType().FullName ?? throw new System.Exception(), behaviour.Priority, behaviour.StateEnable.ToDTO()));
|
||||
return dtos;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Engine.Serialization.DTOs;
|
||||
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Core.Events;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Engine.Serialization;
|
||||
|
||||
internal class StateEnableYamlConverter : IYamlTypeConverter
|
||||
{
|
||||
public bool Accepts(Type type) => type == typeof(StateEnableDTO);
|
||||
|
||||
public object ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
if (parser.Current is not MappingStart)
|
||||
throw new InvalidOperationException("Expected MappingStart");
|
||||
|
||||
parser.MoveNext();
|
||||
var stateEnable = new StateEnableDTO();
|
||||
while (parser.Current != null && parser.Current is not MappingEnd)
|
||||
{
|
||||
var propertyName = ((Scalar)parser.Current).Value;
|
||||
parser.MoveNext();
|
||||
switch (propertyName)
|
||||
{
|
||||
case nameof(StateEnableDTO.ClassName):
|
||||
stateEnable.ClassName = ((Scalar)parser.Current).Value;
|
||||
break;
|
||||
case nameof(StateEnableDTO.Enabled):
|
||||
stateEnable.Enabled = bool.Parse(((Scalar)parser.Current).Value);
|
||||
break;
|
||||
}
|
||||
parser.MoveNext();
|
||||
}
|
||||
return stateEnable;
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type)
|
||||
{
|
||||
var stateEnable = (StateEnableDTO)(value ?? throw new Exception());
|
||||
|
||||
emitter.Emit(new MappingStart());
|
||||
emitter.Emit(new Scalar(nameof(StateEnableDTO.ClassName)));
|
||||
emitter.Emit(new Scalar(stateEnable.ClassName));
|
||||
emitter.Emit(new Scalar(nameof(StateEnableDTO.Enabled)));
|
||||
emitter.Emit(new Scalar(stateEnable.Enabled.ToString()));
|
||||
emitter.Emit(new MappingEnd());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Engine.Serialization.DTOs;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Core.Events;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Engine.Serialization;
|
||||
|
||||
internal class TransformYamlConverter : IYamlTypeConverter
|
||||
{
|
||||
public bool Accepts(Type type) => type == typeof(TransformDTO);
|
||||
|
||||
public object ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
if (parser.Current is not MappingStart)
|
||||
throw new InvalidOperationException("Expected MappingStart");
|
||||
|
||||
parser.MoveNext();
|
||||
var transform = new TransformDTO();
|
||||
while (parser.Current != null && parser.Current is not MappingEnd)
|
||||
{
|
||||
var propertyName = ((Scalar)parser.Current).Value;
|
||||
parser.MoveNext();
|
||||
switch (propertyName)
|
||||
{
|
||||
case nameof(TransformDTO.ParentId):
|
||||
transform.ParentId = new Vector2DYamlConverter().ReadYaml(parser, typeof(Vector2D))?.ToString();
|
||||
break;
|
||||
case nameof(TransformDTO.Position):
|
||||
transform.Position = (Vector2D)(new Vector2DYamlConverter().ReadYaml(parser, typeof(Vector2D)) ?? new Exception());
|
||||
break;
|
||||
case nameof(TransformDTO.Scale):
|
||||
transform.Scale = (Vector2D)(new Vector2DYamlConverter().ReadYaml(parser, typeof(Vector2D)) ?? new Exception());
|
||||
break;
|
||||
case nameof(TransformDTO.Rotation):
|
||||
transform.Rotation = float.Parse(((Scalar)parser.Current).Value);
|
||||
break;
|
||||
}
|
||||
parser.MoveNext();
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type)
|
||||
{
|
||||
var transform = (TransformDTO)(value ?? throw new Exception());
|
||||
|
||||
Vector2DYamlConverter vector2DYamlConverter = new();
|
||||
|
||||
emitter.Emit(new MappingStart());
|
||||
if (transform.ParentId is not null)
|
||||
{
|
||||
emitter.Emit(new Scalar(nameof(TransformDTO.ParentId)));
|
||||
emitter.Emit(new Scalar(transform.ParentId));
|
||||
}
|
||||
emitter.Emit(new Scalar(nameof(TransformDTO.Position)));
|
||||
vector2DYamlConverter.WriteYaml(emitter, transform.Position, typeof(Vector2D));
|
||||
emitter.Emit(new Scalar(nameof(TransformDTO.Scale)));
|
||||
vector2DYamlConverter.WriteYaml(emitter, transform.Scale, typeof(Vector2D));
|
||||
emitter.Emit(new Scalar(nameof(TransformDTO.Rotation)));
|
||||
emitter.Emit(new Scalar(transform.Rotation.ToString()));
|
||||
emitter.Emit(new MappingEnd());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Core.Events;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Engine.Serialization;
|
||||
|
||||
internal class Vector2DYamlConverter : IYamlTypeConverter
|
||||
{
|
||||
public bool Accepts(Type type) => type == typeof(Vector2D);
|
||||
|
||||
public object? ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
if (parser.Current is not MappingStart)
|
||||
throw new InvalidOperationException("Expected MappingStart");
|
||||
|
||||
parser.MoveNext();
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
while (parser.Current != null && parser.Current is not MappingEnd)
|
||||
{
|
||||
var propertyName = ((Scalar)parser.Current).Value;
|
||||
parser.MoveNext();
|
||||
switch (propertyName)
|
||||
{
|
||||
case nameof(Vector2D.X): x = float.Parse(((Scalar)parser.Current).Value); break;
|
||||
case nameof(Vector2D.Y): y = float.Parse(((Scalar)parser.Current).Value); break;
|
||||
}
|
||||
parser.MoveNext();
|
||||
}
|
||||
return new Vector2D(x, y);
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object? value, Type type)
|
||||
{
|
||||
var vector = (Vector2D)(value ?? throw new Exception());
|
||||
emitter.Emit(new MappingStart());
|
||||
emitter.Emit(new Scalar(nameof(Vector2D.X)));
|
||||
emitter.Emit(new Scalar(vector.X.ToString()));
|
||||
emitter.Emit(new Scalar(nameof(Vector2D.Y)));
|
||||
emitter.Emit(new Scalar(vector.Y.ToString()));
|
||||
emitter.Emit(new MappingEnd());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
namespace Engine.Serialization;
|
||||
|
||||
public class YamlSerializer : ISerializer
|
||||
{
|
||||
private readonly YamlDotNet.Serialization.ISerializer serializer = new SerializerBuilder()
|
||||
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
||||
.WithTypeConverter(new Vector2DYamlConverter())
|
||||
.WithTypeConverter(new TransformYamlConverter())
|
||||
.WithTypeConverter(new BehaviourYamlConverter())
|
||||
.WithTypeConverter(new GameObjectYamlConverter())
|
||||
.WithTypeConverter(new StateEnableYamlConverter())
|
||||
.Build();
|
||||
private readonly YamlDotNet.Serialization.IDeserializer deserializer = new DeserializerBuilder()
|
||||
.WithNamingConvention(UnderscoredNamingConvention.Instance)
|
||||
.WithTypeConverter(new Vector2DYamlConverter())
|
||||
.WithTypeConverter(new TransformYamlConverter())
|
||||
.WithTypeConverter(new BehaviourYamlConverter())
|
||||
.WithTypeConverter(new GameObjectYamlConverter())
|
||||
.WithTypeConverter(new StateEnableYamlConverter())
|
||||
.Build();
|
||||
|
||||
public string Serialize<T>(T @object) => serializer.Serialize(@object);
|
||||
public T Deserialize<T>(string serializedString) => deserializer.Deserialize<T>(serializedString);
|
||||
}
|
Loading…
Reference in New Issue