Simplified serialization/deserialization of EngineObjects + added support for Assets (actually any EngineObject!)

This commit is contained in:
Simon Lübeß
2025-03-01 00:48:31 +01:00
parent b5088329f5
commit 10e8b3c282
6 changed files with 41 additions and 42 deletions
@@ -121,7 +121,7 @@ public class ScriptInstanceSerializer
{ {
for (var fieldData in ref object.Fields.Values) for (var fieldData in ref object.Fields.Values)
{ {
if (fieldData.PrimitiveType != .EntityReference && fieldData.PrimitiveType != .ComponentReference) if (fieldData.PrimitiveType != .EngineObjectReference)
continue; continue;
if (originalToCopyIds.TryGetValue(fieldData.Data.EngineObject.ID, let copyId)) if (originalToCopyIds.TryGetValue(fieldData.Data.EngineObject.ID, let copyId))
@@ -36,10 +36,9 @@ public enum SerializationType : uint32
case Enum = 1 << 26; case Enum = 1 << 26;
case EntityReference = 1 << 25; case EngineObjectReference = 1 << 25;
case ComponentReference = 1 << 24;
case ObjectReference = 1 << 23; case ObjectReference = 1 << 24;
public int GetSize() public int GetSize()
{ {
@@ -63,7 +62,9 @@ public enum SerializationType : uint32
return 8; return 8;
case .Decimal: case .Decimal:
return 16; return 16;
case .EntityReference, .ComponentReference, .ObjectReference: case .EngineObjectReference:
return sizeof(UUID);
case .ObjectReference:
return sizeof(UUID); return sizeof(UUID);
case .String: case .String:
return sizeof(StringView); return sizeof(StringView);
@@ -115,7 +115,7 @@ class SerializedObject
} }
data.StringView = valueView; data.StringView = valueView;
case .EntityReference, .ComponentReference: case .EngineObjectReference:
String typeName = null; String typeName = null;
if (fullTypeName != null) if (fullTypeName != null)
@@ -191,7 +191,7 @@ class SerializedObject
{ {
case .String, .Enum: case .String, .Enum:
*(StringView*)target = field.Data.StringView; *(StringView*)target = field.Data.StringView;
case .EntityReference, .ComponentReference: case .EngineObjectReference:
let engineObjectData = field.Data.EngineObject; let engineObjectData = field.Data.EngineObject;
*(char8**)target = engineObjectData.FullTypeName?.CStr(); *(char8**)target = engineObjectData.FullTypeName?.CStr();
@@ -303,13 +303,8 @@ class SerializedObject
writer.Type("Enum"); writer.Type("Enum");
#unwarn #unwarn
Serialize.Value(writer, ValueView(typeof(StringView), &field.Data.StringView), environment); Serialize.Value(writer, ValueView(typeof(StringView), &field.Data.StringView), environment);
case .EntityReference: case .EngineObjectReference:
writer.Type("Entity"); writer.Type("EngineObject");
if (field.Data.EngineObject.FullTypeName != null)
writer.Type(field.Data.EngineObject.FullTypeName);
Serialize.Value(writer, field.Data.EngineObject.ID, environment);
case .ComponentReference:
writer.Type("Component");
if (field.Data.EngineObject.FullTypeName != null) if (field.Data.EngineObject.FullTypeName != null)
writer.Type(field.Data.EngineObject.FullTypeName); writer.Type(field.Data.EngineObject.FullTypeName);
Serialize.Value(writer, field.Data.EngineObject.ID, environment); Serialize.Value(writer, field.Data.EngineObject.ID, environment);
@@ -502,7 +497,7 @@ class SerializedObject
break HandleField; break HandleField;
} }
else if (fieldTypeName == "Entity" || fieldTypeName == "Component") else if (fieldTypeName == "EngineObject")
{ {
String entityTypeName = null; String entityTypeName = null;
@@ -521,7 +516,7 @@ class SerializedObject
Deserialize.[Friend]Integer!(typeof(uint64), reader, ValueView(typeof(uint64), &id)); Deserialize.[Friend]Integer!(typeof(uint64), reader, ValueView(typeof(uint64), &id));
UUID reference = UUID(id); UUID reference = UUID(id);
fieldType = (fieldTypeName == "Entity") ? .EntityReference : .ComponentReference; fieldType = .EngineObjectReference;
fieldData.EngineObject = (FullTypeName: entityTypeName, ID: reference); fieldData.EngineObject = (FullTypeName: entityTypeName, ID: reference);
break HandleField; break HandleField;
@@ -139,17 +139,17 @@ public class DeserializationObject
_structScopeName = _structScopeName.Remove(_structScopeName.Length - scopeToRemove.Length - 1); _structScopeName = _structScopeName.Remove(_structScopeName.Length - scopeToRemove.Length - 1);
} }
[StructLayout(LayoutKind.Explicit)]
private unsafe struct DataHelper
{
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct EngineObjectReferenceHelper public unsafe struct EngineObjectReferenceHelper
{ {
public byte* FullTypeName; public byte* FullTypeName;
public long FullTypeNameLength; public long FullTypeNameLength;
public UUID Id; public UUID Id;
} }
[StructLayout(LayoutKind.Explicit)]
private struct DataHelper
{
[FieldOffset(0)] [FieldOffset(0)]
public EngineObjectReferenceHelper EngineObjectReference; public EngineObjectReferenceHelper EngineObjectReference;
@@ -220,8 +220,7 @@ public class DeserializationObject
SerializationType.Double => *(double*)rawData, SerializationType.Double => *(double*)rawData,
SerializationType.Decimal => *(decimal*)rawData, SerializationType.Decimal => *(decimal*)rawData,
SerializationType.Enum => GetString(), SerializationType.Enum => GetString(),
SerializationType.EntityReference => dataHelper.EngineObjectReference, SerializationType.EngineObjectReference => dataHelper.EngineObjectReference,
SerializationType.ComponentReference => dataHelper.EngineObjectReference,
SerializationType.ObjectReference => dataHelper.UUID, SerializationType.ObjectReference => dataHelper.UUID,
_ => NoValueDeserialized _ => NoValueDeserialized
}; };
@@ -549,12 +548,13 @@ public class DeserializationObject
bool isEntity = typeof(Entity).IsAssignableFrom(fieldType); bool isEntity = typeof(Entity).IsAssignableFrom(fieldType);
bool isComponent = fieldType.IsSubclassOf(typeof(Component)); bool isComponent = fieldType.IsSubclassOf(typeof(Component));
bool isEngineObject = fieldType.IsSubclassOf(typeof(EngineObject));
if (isEntity || isComponent) if (isEntity || isComponent || isEngineObject)
{ {
object? fieldData = GetFieldValue(fieldName, isEntity ? SerializationType.EntityReference : SerializationType.ComponentReference); object? fieldData = GetFieldValue(fieldName, SerializationType.EngineObjectReference);
if (fieldData is not DataHelper.EngineObjectReferenceHelper data) if (fieldData is not EngineObjectReferenceHelper data)
return NoValueDeserialized; return NoValueDeserialized;
UUID id = data.Id; UUID id = data.Id;
@@ -578,12 +578,20 @@ public class DeserializationObject
return Entity.GetScriptReference(id, type); return Entity.GetScriptReference(id, type);
} }
else if (isComponent)
{ {
Entity entity = new Entity(id); Entity entity = new Entity(id);
return entity.GetComponent(type); return entity.GetComponent(type);
} }
if (isEngineObject)
{
EngineObject? engineObject = ActivatorExtension.CreateEngineObject(type, id);
return engineObject;
}
return NoValueDeserialized;
} }
else else
{ {
@@ -35,10 +35,10 @@ public enum SerializationType : uint
Enum = 1 << 26, Enum = 1 << 26,
EntityReference = 1 << 25, // Used for everything that inherits from EngineObject (Assets, Components, Entities)
ComponentReference = 1 << 24, EngineObjectReference = 1 << 25,
ObjectReference = 1 << 23, ObjectReference = 1 << 24,
} }
public static class SerializationTypeExtension public static class SerializationTypeExtension
@@ -69,8 +69,7 @@ public static class SerializationTypeExtension
SerializationType.Double => typeof(double), SerializationType.Double => typeof(double),
SerializationType.Decimal => typeof(decimal), SerializationType.Decimal => typeof(decimal),
SerializationType.Enum => typeof(Enum), SerializationType.Enum => typeof(Enum),
SerializationType.EntityReference => typeof(UUID), SerializationType.EngineObjectReference => typeof(UUID),
SerializationType.ComponentReference => typeof(UUID),
SerializationType.ObjectReference => typeof(UUID), SerializationType.ObjectReference => typeof(UUID),
_ => null _ => null
}; };
+2 -6
View File
@@ -316,13 +316,9 @@ public class SerializedObject
public void SerializeClass(string fieldName, object? fieldValue, Type fieldType) public void SerializeClass(string fieldName, object? fieldValue, Type fieldType)
{ {
if (typeof(Entity).IsAssignableFrom(fieldType)) if (fieldType.IsSubclassOf(typeof(EngineObject)))
{ {
AddField(fieldName, SerializationType.EntityReference, ((Entity?)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName); AddField(fieldName, SerializationType.EngineObjectReference, ((EngineObject?)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName);
}
else if (fieldType.IsSubclassOf(typeof(Component)))
{
AddField(fieldName, SerializationType.ComponentReference, ((Component?)fieldValue)?.UUID ?? UUID.Zero, fieldValue?.GetType().FullName);
} }
else else
{ {