mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Serialize Enums (and maybe Entitiy/Component refs)
This commit is contained in:
+31
-1
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using GlitchyEngine.Core;
|
||||
using GlitchyEngine.Extensions;
|
||||
@@ -101,7 +102,7 @@ public class Entity : EngineObject
|
||||
|
||||
if (HasComponent(componentType))
|
||||
{
|
||||
return Activator.CreateInstance(componentType) as Component;
|
||||
return Activator.CreateInstance(componentType, true, _uuid) as Component;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -291,6 +292,35 @@ public class Entity : EngineObject
|
||||
return scriptInstance as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the script of the given type, or null, if the entity has no script of the given type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the script.</param>
|
||||
/// <returns>The script instance or null.</returns>
|
||||
public object As(Type type)
|
||||
{
|
||||
Debug.Assert(type.IsSubclassOf(typeof(Entity)));
|
||||
|
||||
ScriptGlue.Entity_GetScriptInstance(_uuid, out object scriptInstance);
|
||||
|
||||
return scriptInstance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the script of the given type, or null, if the entity has no script of the given type.
|
||||
/// </summary>
|
||||
/// <param name="id">The id of the entity whose script instance shall be returned.</param>
|
||||
/// <param name="type">The type of the script.</param>
|
||||
/// <returns>The script instance or null.</returns>
|
||||
internal static object GetScriptReference(UUID id, Type type)
|
||||
{
|
||||
Debug.Assert(type.IsSubclassOf(typeof(Entity)));
|
||||
|
||||
ScriptGlue.Entity_GetScriptInstance(id, out object scriptInstance);
|
||||
|
||||
return scriptInstance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the entity and all it's children.
|
||||
/// </summary>
|
||||
|
||||
@@ -140,7 +140,7 @@ internal static class ScriptGlue
|
||||
#region Serialization
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void Serialization_SerializeField(IntPtr serializationContext, SerializationType type, string name, object value);
|
||||
internal static extern void Serialization_SerializeField(IntPtr serializationContext, SerializationType type, string name, object value, string fullTypeName = null);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void Serialization_CreateObject(IntPtr currentContext, string fullTypeName, out IntPtr context, out UUID id);
|
||||
|
||||
@@ -93,11 +93,11 @@ public static class EntitySerializer
|
||||
_structScopeName.Remove(_structScopeName.Length - scopeToRemove.Length - 1);
|
||||
}
|
||||
|
||||
private void AddField(string fieldName, SerializationType serializationType, object value)
|
||||
private void AddField(string fieldName, SerializationType serializationType, object value, string fullTypeName = null)
|
||||
{
|
||||
string completeFieldName = $"{_structScopeName}{fieldName}";
|
||||
|
||||
ScriptGlue.Serialization_SerializeField(_internalContext, serializationType, completeFieldName, value);
|
||||
ScriptGlue.Serialization_SerializeField(_internalContext, serializationType, completeFieldName, value, fullTypeName);
|
||||
}
|
||||
|
||||
public void Serialize(Entity entity)
|
||||
@@ -228,11 +228,11 @@ public static class EntitySerializer
|
||||
{
|
||||
if (typeof(Entity).IsAssignableFrom(fieldType))
|
||||
{
|
||||
AddField(fieldName, SerializationType.EntityReference, ((Entity)fieldValue)?.UUID ?? UUID.Zero);
|
||||
AddField(fieldName, SerializationType.EntityReference, ((Entity)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName);
|
||||
}
|
||||
else if (typeof(Component).IsAssignableFrom(fieldType))
|
||||
{
|
||||
AddField(fieldName, SerializationType.ComponentReference, ((Component)fieldValue)?.UUID ?? UUID.Zero);
|
||||
AddField(fieldName, SerializationType.ComponentReference, ((Component)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -363,6 +363,20 @@ public static class EntitySerializer
|
||||
_structScopeName.Remove(_structScopeName.Length - scopeToRemove.Length - 1);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct DataHelper
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct EngineObjectReferenceHelper
|
||||
{
|
||||
public IntPtr FullTypeName;
|
||||
public UUID Id;
|
||||
}
|
||||
|
||||
[FieldOffset(0)]
|
||||
public EngineObjectReferenceHelper EngineObjectReference;
|
||||
}
|
||||
|
||||
private unsafe object GetFieldValue(string fieldName, SerializationType serializationType)
|
||||
{
|
||||
string completeFieldName = $"{_structScopeName}{fieldName}";
|
||||
@@ -372,6 +386,8 @@ public static class EntitySerializer
|
||||
byte* rawData = stackalloc byte[16];
|
||||
//byte* rawData = (byte*)&backingFieldOnStack;
|
||||
|
||||
ref DataHelper dataHelper = ref Unsafe.AsRef<DataHelper>(rawData);
|
||||
|
||||
ScriptGlue.Serialization_DeserializeField(_internalContext, serializationType, completeFieldName, rawData);
|
||||
|
||||
string GetString()
|
||||
@@ -423,12 +439,10 @@ public static class EntitySerializer
|
||||
return *(decimal*)rawData;
|
||||
|
||||
case SerializationType.Enum:
|
||||
string value = GetString();
|
||||
// TODO!
|
||||
return null;
|
||||
|
||||
return GetString();
|
||||
case SerializationType.EntityReference:
|
||||
case SerializationType.ComponentReference:
|
||||
return dataHelper.EngineObjectReference;
|
||||
case SerializationType.ObjectReference:
|
||||
return *(UUID*)rawData;
|
||||
default:
|
||||
@@ -476,7 +490,7 @@ public static class EntitySerializer
|
||||
}
|
||||
else if (fieldType.IsEnum)
|
||||
{
|
||||
// SerializeEnum(fieldName, fieldValue, fieldType);
|
||||
newFieldValue = DeserializeEnum(field.Name, fieldType);
|
||||
}
|
||||
else if (fieldType.IsArray)
|
||||
{
|
||||
@@ -563,9 +577,21 @@ public static class EntitySerializer
|
||||
return GetFieldValue(fieldName, expectedType);
|
||||
}
|
||||
|
||||
private void DeserializeEnum(string fieldName, object fieldValue, Type fieldType)
|
||||
private object DeserializeEnum(string fieldName, Type enumType)
|
||||
{
|
||||
//AddField(fieldName, SerializationType.Enum, fieldValue.ToString());
|
||||
if (GetFieldValue(fieldName, SerializationType.Enum) is not string valueName)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
return Enum.Parse(enumType, valueName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Error($"Failed to parse \"{valueName}\" as enum-type \"{enumType}\"");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private object DeserializeStruct(string fieldName, object targetInstance)
|
||||
@@ -581,36 +607,40 @@ public static class EntitySerializer
|
||||
|
||||
private object DeserializeClass(string fieldName, Type fieldType)
|
||||
{
|
||||
if (typeof(Entity).IsAssignableFrom(fieldType))
|
||||
bool isEntity = typeof(Entity).IsAssignableFrom(fieldType);
|
||||
bool isComponent = fieldType.IsSubclassOf(typeof(Component));
|
||||
|
||||
if (isEntity || isComponent)
|
||||
{
|
||||
UUID id = (UUID)GetFieldValue(fieldName, SerializationType.EntityReference);
|
||||
|
||||
var data = (DataHelper.EngineObjectReferenceHelper)GetFieldValue(fieldName, SerializationType.EntityReference);
|
||||
|
||||
UUID id = data.Id;
|
||||
|
||||
if (id == UUID.Zero)
|
||||
return null;
|
||||
|
||||
Entity reference = new Entity(id);
|
||||
string fullTypeName = Marshal.PtrToStringUni(data.FullTypeName);
|
||||
|
||||
if (fieldType.IsSubclassOf(typeof(Entity)))
|
||||
return reference.As<Entity>();
|
||||
|
||||
return reference;
|
||||
}
|
||||
else if (typeof(Component).IsAssignableFrom(fieldType))
|
||||
{
|
||||
UUID id = (UUID)GetFieldValue(fieldName, SerializationType.ComponentReference);
|
||||
|
||||
if (id == UUID.Zero)
|
||||
Type type = GetTypeFromName(fullTypeName);
|
||||
|
||||
if (type == null)
|
||||
return null;
|
||||
|
||||
// TODO: Get class
|
||||
if (isEntity)
|
||||
{
|
||||
// We have to differentiate between simple Entity references and script instances
|
||||
// (because we decided to use the same type for both, so we could have a field Entity which contains a script instance instead of an Entity reference)
|
||||
if (type == typeof(Entity))
|
||||
return new Entity(id);
|
||||
|
||||
//Entity reference = new Entity(id);
|
||||
return Entity.GetScriptReference(id, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity entity = new Entity(id);
|
||||
|
||||
//if (fieldType.IsSubclassOf(typeof(Entity)))
|
||||
// return reference.As<Entity>();
|
||||
|
||||
//return reference;
|
||||
return null;
|
||||
return entity.GetComponent(type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user