wip: Serialization 2

This commit is contained in:
Syntriax 2024-02-10 17:10:02 +03:00
parent 361a7c53b9
commit 0708ba89cc
13 changed files with 158 additions and 21 deletions

View File

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using Engine.Serialization.DTOs;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
namespace Engine.Serialization;
internal class BehaviourControllerYamlConverter : IYamlTypeConverter
{
public bool Accepts(Type type) => type == typeof(BehaviourControllerDTO);
public object ReadYaml(IParser parser, Type type)
{
if (parser.Current is not MappingStart)
throw new InvalidOperationException("Expected MappingStart");
parser.MoveNext();
var behaviourController = new BehaviourControllerDTO();
while (parser.Current != null && parser.Current is not MappingEnd)
{
var propertyName = ((Scalar)parser.Current).Value;
parser.MoveNext();
switch (propertyName)
{
case nameof(BehaviourControllerDTO.ClassType):
behaviourController.ClassType = ((Scalar)parser.Current).Value;
break;
case nameof(BehaviourControllerDTO.Behaviours):
behaviourController.Behaviours = (List<BehaviourDTO>)new BehaviourDTOListConverter().ReadYaml(parser, typeof(List<BehaviourDTO>));
break;
}
parser.MoveNext();
}
return behaviourController;
}
public void WriteYaml(IEmitter emitter, object? value, Type type)
{
var behaviourController = (BehaviourControllerDTO)(value ?? throw new Exception());
BehaviourDTOListConverter behaviourDTOListConverter = new();
emitter.Emit(new MappingStart());
emitter.Emit(new Scalar(nameof(BehaviourControllerDTO.ClassType)));
emitter.Emit(new Scalar(behaviourController.ClassType));
emitter.Emit(new Scalar(nameof(BehaviourControllerDTO.Behaviours)));
behaviourDTOListConverter.WriteYaml(emitter, behaviourController.Behaviours, typeof(List<BehaviourDTO>));
emitter.Emit(new MappingEnd());
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using Engine.Serialization.DTOs;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
namespace Engine.Serialization;
public class BehaviourDTOListConverter : IYamlTypeConverter
{
public bool Accepts(Type type)
{
return type == typeof(List<BehaviourDTO>);
}
public object ReadYaml(IParser parser, Type type)
{
var behaviours = new List<BehaviourDTO>();
if (parser.Current is SequenceStart)
{
parser.MoveNext();
while (parser.Current != null && !(parser.Current is SequenceEnd))
{
behaviours.Add((BehaviourDTO)new BehaviourYamlConverter().ReadYaml(parser, typeof(BehaviourDTO)));
parser.MoveNext();
}
}
return behaviours;
}
public void WriteYaml(IEmitter emitter, object? value, Type type)
{
var behaviours = (List<BehaviourDTO>)(value ?? throw new Exception());
emitter.Emit(new SequenceStart(null, null, false, SequenceStyle.Block));
foreach (var behaviour in behaviours)
new BehaviourYamlConverter().WriteYaml(emitter, behaviour, typeof(BehaviourDTO));
emitter.Emit(new SequenceEnd());
}
}

View File

@ -25,8 +25,8 @@ internal class BehaviourYamlConverter : IYamlTypeConverter
parser.MoveNext(); parser.MoveNext();
switch (propertyName) switch (propertyName)
{ {
case nameof(BehaviourDTO.ClassName): case nameof(BehaviourDTO.ClassType):
behaviour.ClassName = ((Scalar)parser.Current).Value; behaviour.ClassType = ((Scalar)parser.Current).Value;
break; break;
case nameof(BehaviourDTO.Priority): case nameof(BehaviourDTO.Priority):
behaviour.Priority = int.Parse(((Scalar)parser.Current).Value); behaviour.Priority = int.Parse(((Scalar)parser.Current).Value);
@ -48,8 +48,8 @@ internal class BehaviourYamlConverter : IYamlTypeConverter
emitter.Emit(new MappingStart()); emitter.Emit(new MappingStart());
emitter.Emit(new Scalar(nameof(BehaviourDTO.ClassName))); emitter.Emit(new Scalar(nameof(BehaviourDTO.ClassType)));
emitter.Emit(new Scalar(behaviour.ClassName.ToString())); emitter.Emit(new Scalar(behaviour.ClassType.ToString()));
emitter.Emit(new Scalar(nameof(BehaviourDTO.Priority))); emitter.Emit(new Scalar(nameof(BehaviourDTO.Priority)));
emitter.Emit(new Scalar(behaviour.Priority.ToString())); emitter.Emit(new Scalar(behaviour.Priority.ToString()));

View File

@ -0,0 +1,8 @@
using System.Collections.Generic;
namespace Engine.Serialization.DTOs;
internal record struct BehaviourControllerDTO(
string ClassType,
List<BehaviourDTO> Behaviours
);

View File

@ -1,7 +1,7 @@
namespace Engine.Serialization.DTOs; namespace Engine.Serialization.DTOs;
internal record struct BehaviourDTO( internal record struct BehaviourDTO(
string ClassName, string ClassType,
int Priority, int Priority,
StateEnableDTO StateEnable StateEnableDTO StateEnable
); );

View File

@ -1,11 +1,10 @@
using System.Collections.Generic;
namespace Engine.Serialization.DTOs; namespace Engine.Serialization.DTOs;
internal record struct GameObjectDTO( internal record struct GameObjectDTO(
string ClassType,
string Id, string Id,
string Name, string Name,
TransformDTO Transform, TransformDTO Transform,
List<BehaviourDTO> Behaviours, BehaviourControllerDTO BehaviourController,
StateEnableDTO StateEnable StateEnableDTO StateEnable
); );

View File

@ -1,6 +1,6 @@
namespace Engine.Serialization.DTOs; namespace Engine.Serialization.DTOs;
internal record struct StateEnableDTO( internal record struct StateEnableDTO(
string ClassName, string ClassType,
bool Enabled bool Enabled
); );

View File

@ -3,6 +3,7 @@ using Syntriax.Engine.Core;
namespace Engine.Serialization.DTOs; namespace Engine.Serialization.DTOs;
internal record struct TransformDTO( internal record struct TransformDTO(
string ClassType,
string? ParentId, string? ParentId,
Vector2D Position, Vector2D Position,
Vector2D Scale, Vector2D Scale,

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Engine.Serialization.DTOs; using Engine.Serialization.DTOs;
@ -51,20 +52,23 @@ internal class GameObjectYamlConverter : IYamlTypeConverter
{ {
var gameObject = (GameObjectDTO)(value ?? throw new Exception()); var gameObject = (GameObjectDTO)(value ?? throw new Exception());
Vector2DYamlConverter vector2DYamlConverter = new(); TransformYamlConverter transformYamlConverter = new();
StateEnableYamlConverter stateEnableYamlConverter = new(); StateEnableYamlConverter stateEnableYamlConverter = new();
BehaviourControllerYamlConverter behaviourControllerYamlConverter = new();
emitter.Emit(new MappingStart()); emitter.Emit(new MappingStart());
emitter.Emit(new Scalar(nameof(GameObjectDTO.Id))); emitter.Emit(new Scalar(nameof(GameObjectDTO.Id)));
emitter.Emit(new Scalar(gameObject.Id.ToString())); emitter.Emit(new Scalar(gameObject.Id.ToString()));
emitter.Emit(new Scalar(nameof(GameObjectDTO.ClassType)));
emitter.Emit(new Scalar(gameObject.ClassType));
emitter.Emit(new Scalar(nameof(GameObjectDTO.Name))); emitter.Emit(new Scalar(nameof(GameObjectDTO.Name)));
emitter.Emit(new Scalar(gameObject.Name.ToString())); emitter.Emit(new Scalar(gameObject.Name.ToString()));
emitter.Emit(new Scalar(nameof(GameObjectDTO.Transform))); emitter.Emit(new Scalar(nameof(GameObjectDTO.Transform)));
vector2DYamlConverter.WriteYaml(emitter, gameObject.Transform, typeof(TransformDTO)); transformYamlConverter.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))); emitter.Emit(new Scalar(nameof(GameObjectDTO.StateEnable)));
stateEnableYamlConverter.WriteYaml(emitter, gameObject.StateEnable, typeof(StateEnableDTO)); stateEnableYamlConverter.WriteYaml(emitter, gameObject.StateEnable, typeof(StateEnableDTO));
emitter.Emit(new Scalar(nameof(GameObjectDTO.BehaviourController)));
behaviourControllerYamlConverter.WriteYaml(emitter, gameObject.BehaviourController, typeof(BehaviourControllerDTO));
emitter.Emit(new MappingEnd()); emitter.Emit(new MappingEnd());
} }
} }

View File

@ -7,19 +7,21 @@ namespace Engine.Serialization;
internal static class InternalExtensions internal static class InternalExtensions
{ {
public static TransformDTO ToDTO(this ITransform transform) public static TransformDTO ToDTO(this ITransform transform)
=> new(transform.Parent?.GameObject.Id, transform.Position, transform.Scale, transform.Rotation); => new(transform.GetType().FullName ?? throw new System.Exception(), transform.Parent?.GameObject.Id, transform.Position, transform.Scale, transform.Rotation);
public static GameObjectDTO ToDTO(this IGameObject gameObject) public static GameObjectDTO ToDTO(this IGameObject gameObject)
=> new(gameObject.Id, gameObject.Name, gameObject.Transform.ToDTO(), gameObject.BehaviourController.ToDTO(), gameObject.StateEnable.ToDTO()); => new(gameObject.GetType().FullName ?? throw new System.Exception(), gameObject.Id, gameObject.Name, gameObject.Transform.ToDTO(), gameObject.BehaviourController.ToDTO(), gameObject.StateEnable.ToDTO());
public static StateEnableDTO ToDTO(this IStateEnable stateEnable) public static StateEnableDTO ToDTO(this IStateEnable stateEnable)
=> new(stateEnable.GetType().FullName ?? throw new System.Exception(), stateEnable.Enabled); => new(stateEnable.GetType().FullName ?? throw new System.Exception(), stateEnable.Enabled);
public static List<BehaviourDTO> ToDTO(this IBehaviourController behaviourController) public static BehaviourControllerDTO ToDTO(this IBehaviourController behaviourController)
{ {
List<BehaviourDTO> dtos = []; List<BehaviourDTO> dtos = [];
foreach (var behaviour in behaviourController) foreach (var behaviour in behaviourController)
dtos.Add(new(behaviour.GetType().FullName ?? throw new System.Exception(), behaviour.Priority, behaviour.StateEnable.ToDTO())); dtos.Add(new(behaviour.GetType().FullName ?? throw new System.Exception(), behaviour.Priority, behaviour.StateEnable.ToDTO()));
return dtos; return new(behaviourController.GetType().FullName ?? throw new System.Exception(), dtos);
} }
public static BehaviourDTO ToDTO(this IBehaviour behaviour)
=> new(behaviour.GetType().FullName ?? throw new System.Exception(), behaviour.Priority, behaviour.StateEnable.ToDTO());
} }

View File

@ -0,0 +1,27 @@
using System;
using Engine.Serialization.DTOs;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Core.Factory;
namespace Engine.Serialization;
public static class Serialization
{
private static readonly ISerializer defaultSerializer = new YamlSerializer();
public static string SerializeGameObject(IGameObject gameObject) => Serialize(gameObject.ToDTO(), defaultSerializer);
public static T DeserializeGameObject<T>(string serializedString) where T : class, IGameObject
{
GameObjectDTO gameObjectDTO = Deserialize<GameObjectDTO>(serializedString, defaultSerializer);
Type gameObjectType = (gameObjectDTO.ClassType is not null) ? TypeFactory.Get(gameObjectDTO.ClassType) : typeof(GameObject);
T t = new GameObjectFactory().Instantiate<T>(gameObjectType);
return t;
}
public static string Serialize<T>(T @object) => Serialize(@object, defaultSerializer);
public static string Serialize<T>(T @object, ISerializer serializer) => serializer.Serialize(@object);
public static T Deserialize<T>(string serializedString) => Deserialize<T>(serializedString, defaultSerializer);
public static T Deserialize<T>(string serializedString, ISerializer serializer) => serializer.Deserialize<T>(serializedString);
}

View File

@ -26,8 +26,8 @@ internal class StateEnableYamlConverter : IYamlTypeConverter
parser.MoveNext(); parser.MoveNext();
switch (propertyName) switch (propertyName)
{ {
case nameof(StateEnableDTO.ClassName): case nameof(StateEnableDTO.ClassType):
stateEnable.ClassName = ((Scalar)parser.Current).Value; stateEnable.ClassType = ((Scalar)parser.Current).Value;
break; break;
case nameof(StateEnableDTO.Enabled): case nameof(StateEnableDTO.Enabled):
stateEnable.Enabled = bool.Parse(((Scalar)parser.Current).Value); stateEnable.Enabled = bool.Parse(((Scalar)parser.Current).Value);
@ -43,8 +43,8 @@ internal class StateEnableYamlConverter : IYamlTypeConverter
var stateEnable = (StateEnableDTO)(value ?? throw new Exception()); var stateEnable = (StateEnableDTO)(value ?? throw new Exception());
emitter.Emit(new MappingStart()); emitter.Emit(new MappingStart());
emitter.Emit(new Scalar(nameof(StateEnableDTO.ClassName))); emitter.Emit(new Scalar(nameof(StateEnableDTO.ClassType)));
emitter.Emit(new Scalar(stateEnable.ClassName)); emitter.Emit(new Scalar(stateEnable.ClassType));
emitter.Emit(new Scalar(nameof(StateEnableDTO.Enabled))); emitter.Emit(new Scalar(nameof(StateEnableDTO.Enabled)));
emitter.Emit(new Scalar(stateEnable.Enabled.ToString())); emitter.Emit(new Scalar(stateEnable.Enabled.ToString()));
emitter.Emit(new MappingEnd()); emitter.Emit(new MappingEnd());

View File

@ -58,6 +58,8 @@ internal class TransformYamlConverter : IYamlTypeConverter
emitter.Emit(new Scalar(nameof(TransformDTO.ParentId))); emitter.Emit(new Scalar(nameof(TransformDTO.ParentId)));
emitter.Emit(new Scalar(transform.ParentId)); emitter.Emit(new Scalar(transform.ParentId));
} }
emitter.Emit(new Scalar(nameof(TransformDTO.ClassType)));
emitter.Emit(new Scalar(transform.ClassType));
emitter.Emit(new Scalar(nameof(TransformDTO.Position))); emitter.Emit(new Scalar(nameof(TransformDTO.Position)));
vector2DYamlConverter.WriteYaml(emitter, transform.Position, typeof(Vector2D)); vector2DYamlConverter.WriteYaml(emitter, transform.Position, typeof(Vector2D));
emitter.Emit(new Scalar(nameof(TransformDTO.Scale))); emitter.Emit(new Scalar(nameof(TransformDTO.Scale)));