mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
ScriptEngine: Serialize static fields
This commit is contained in:
@@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using Mono;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
using GlitchyEngine.Serialization;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Scripting;
|
||||||
|
|
||||||
|
using internal GlitchyEngine.Scripting;
|
||||||
|
|
||||||
|
class EntitySerializerWrapper : ScriptClass
|
||||||
|
{
|
||||||
|
function MonoObject* SerializeMethod(MonoObject* entity, void* contextPtr, MonoException** exception);
|
||||||
|
function MonoObject* DeserializeMethod(MonoObject* entity, void* contextPtr, MonoException** exception);
|
||||||
|
function MonoObject* SerializeStaticMethod(MonoReflectionType* type, void* contextPtr, MonoException** exception);
|
||||||
|
function MonoObject* DeserializeStaticMethod(MonoReflectionType* type, void* contextPtr, MonoException** exception);
|
||||||
|
|
||||||
|
private SerializeMethod _serializeMethod;
|
||||||
|
private DeserializeMethod _deserializeMethod;
|
||||||
|
private SerializeStaticMethod _serializeStaticMethod;
|
||||||
|
private DeserializeStaticMethod _deserializeStaticMethod;
|
||||||
|
|
||||||
|
[AllowAppend]
|
||||||
|
public this(StringView classNamespace, StringView className, MonoImage* image) : base(classNamespace, className, image)
|
||||||
|
{
|
||||||
|
_serializeMethod = (SerializeMethod)GetMethodThunk("Serialize", 2);
|
||||||
|
|
||||||
|
if (_serializeMethod == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("EntitySerializer has no \"Serialize\" method.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_deserializeMethod = (DeserializeMethod)GetMethodThunk("Deserialize", 2);
|
||||||
|
|
||||||
|
if (_serializeMethod == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("EntitySerializer has no \"Deserialize\" method.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_serializeStaticMethod = (SerializeStaticMethod)GetMethodThunk("SerializeStaticFields", 2);
|
||||||
|
|
||||||
|
if (_serializeStaticMethod == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("EntitySerializer has no \"SerializeStaticStatic\" method.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_deserializeStaticMethod = (SerializeStaticMethod)GetMethodThunk("DeserializeStaticFields", 2);
|
||||||
|
|
||||||
|
if (_deserializeStaticMethod == null)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Error("EntitySerializer has no \"DeserializeStaticStatic\" method.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serialize(ScriptInstance instance, SerializedObject context)
|
||||||
|
{
|
||||||
|
void* thisPtr = Internal.UnsafeCastToPtr(context);
|
||||||
|
|
||||||
|
MonoException* exception = null;
|
||||||
|
_serializeMethod(instance.[Friend]_instance, thisPtr, &exception);
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
ScriptEngine.[Friend]HandleMonoException(exception, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SerializeStatic(ScriptClass @class, SerializedObject context)
|
||||||
|
{
|
||||||
|
void* thisPtr = Internal.UnsafeCastToPtr(context);
|
||||||
|
|
||||||
|
MonoException* exception = null;
|
||||||
|
|
||||||
|
MonoType* type = Mono.mono_class_get_type(@class.[Friend]_monoClass);
|
||||||
|
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, type);
|
||||||
|
|
||||||
|
_serializeStaticMethod(reflectionType, thisPtr, &exception);
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Deserialize(ScriptInstance instance, SerializedObject context)
|
||||||
|
{
|
||||||
|
void* thisPtr = Internal.UnsafeCastToPtr(context);
|
||||||
|
|
||||||
|
MonoException* exception = null;
|
||||||
|
_deserializeMethod(instance.[Friend]_instance, thisPtr, &exception);
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
ScriptEngine.[Friend]HandleMonoException(exception, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeserializeStatic(ScriptClass @class, SerializedObject context)
|
||||||
|
{
|
||||||
|
void* thisPtr = Internal.UnsafeCastToPtr(context);
|
||||||
|
|
||||||
|
MonoException* exception = null;
|
||||||
|
|
||||||
|
MonoType* type = Mono.mono_class_get_type(@class.[Friend]_monoClass);
|
||||||
|
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, type);
|
||||||
|
|
||||||
|
_deserializeStaticMethod(reflectionType, thisPtr, &exception);
|
||||||
|
|
||||||
|
if (exception != null)
|
||||||
|
ScriptEngine.[Friend]HandleMonoException(exception, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -231,23 +231,6 @@ class ScriptClass : SharpClass
|
|||||||
return *(T*)Mono.mono_object_unbox(object);
|
return *(T*)Mono.mono_object_unbox(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetFieldValue<T>(MonoObject* instance, MonoClassField* field)
|
|
||||||
{
|
|
||||||
T value = default;
|
|
||||||
Mono.mono_field_get_value(instance, field, &value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetFieldValue<T>(MonoObject* instance, MonoClassField* field, in T value)
|
|
||||||
{
|
|
||||||
Mono.mono_field_set_value(instance, field, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetFieldValue<T>(MonoObject* instance, MonoClassField* field, in T value) where T : struct*
|
|
||||||
{
|
|
||||||
Mono.mono_field_set_value(instance, field, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MonoObject* BoxValue<T>(in T value)
|
public MonoObject* BoxValue<T>(in T value)
|
||||||
{
|
{
|
||||||
return Mono.mono_value_box(ScriptEngine.[Friend]s_AppDomain, _monoClass, &value);
|
return Mono.mono_value_box(ScriptEngine.[Friend]s_AppDomain, _monoClass, &value);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class EngineClasses
|
|||||||
|
|
||||||
private EntityEditorWrapper s_EntityEditor ~ _?.ReleaseRef();
|
private EntityEditorWrapper s_EntityEditor ~ _?.ReleaseRef();
|
||||||
|
|
||||||
private ScriptClass s_EntitySerializer ~ _?.ReleaseRef();
|
private EntitySerializerWrapper s_EntitySerializer ~ _?.ReleaseRef();
|
||||||
private ScriptClass s_SerializationContext ~ _?.ReleaseRef();
|
private ScriptClass s_SerializationContext ~ _?.ReleaseRef();
|
||||||
|
|
||||||
private ScriptClass s_Collision2D ~ _?.ReleaseRef();
|
private ScriptClass s_Collision2D ~ _?.ReleaseRef();
|
||||||
@@ -35,7 +35,7 @@ class EngineClasses
|
|||||||
|
|
||||||
public EntityEditorWrapper EntityEditor => s_EntityEditor;
|
public EntityEditorWrapper EntityEditor => s_EntityEditor;
|
||||||
|
|
||||||
public ScriptClass EntitySerializer => s_EntitySerializer;
|
public EntitySerializerWrapper EntitySerializer => s_EntitySerializer;
|
||||||
|
|
||||||
public ScriptClass Collision2D => s_Collision2D;
|
public ScriptClass Collision2D => s_Collision2D;
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ class EngineClasses
|
|||||||
// Editor classes
|
// Editor classes
|
||||||
s_EntityEditor = new EntityEditorWrapper("GlitchyEngine.Editor", "EntityEditor", image);
|
s_EntityEditor = new EntityEditorWrapper("GlitchyEngine.Editor", "EntityEditor", image);
|
||||||
|
|
||||||
s_EntitySerializer = new ScriptClass("GlitchyEngine.Serialization", "EntitySerializer", image);
|
s_EntitySerializer = new EntitySerializerWrapper("GlitchyEngine.Serialization", "EntitySerializer", image);
|
||||||
|
|
||||||
s_Collision2D = new ScriptClass("GlitchyEngine.Physics", "Collision2D", image);
|
s_Collision2D = new ScriptClass("GlitchyEngine.Physics", "Collision2D", image);
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ static class ScriptEngine
|
|||||||
private static FileSystemWatcher _userAssemblyWatcher ~ delete _;
|
private static FileSystemWatcher _userAssemblyWatcher ~ delete _;
|
||||||
|
|
||||||
// TODO: This should be a global setting somewhere
|
// TODO: This should be a global setting somewhere
|
||||||
private static bool _debuggingEnabled = false;
|
private static bool _debuggingEnabled = true;
|
||||||
|
|
||||||
private static String _appAssemblyPath = new .() ~ delete _;
|
private static String _appAssemblyPath = new .() ~ delete _;
|
||||||
|
|
||||||
|
|||||||
@@ -1143,7 +1143,7 @@ static class ScriptGlue
|
|||||||
}
|
}
|
||||||
|
|
||||||
[RegisterCall("ScriptGlue::Serialization_CreateObject")]
|
[RegisterCall("ScriptGlue::Serialization_CreateObject")]
|
||||||
static void Serialization_CreateObject(void* currentContext, MonoString* typeName, out void* newContext, out UUID newId)
|
static void Serialization_CreateObject(void* currentContext, bool isStatic, MonoString* typeName, out void* newContext, out UUID newId)
|
||||||
{
|
{
|
||||||
SerializedObject context = Internal.UnsafeCastToObject(currentContext) as SerializedObject;
|
SerializedObject context = Internal.UnsafeCastToObject(currentContext) as SerializedObject;
|
||||||
|
|
||||||
@@ -1151,7 +1151,7 @@ static class ScriptGlue
|
|||||||
|
|
||||||
char8* rawTypeName = Mono.mono_string_to_utf8(typeName);
|
char8* rawTypeName = Mono.mono_string_to_utf8(typeName);
|
||||||
|
|
||||||
SerializedObject newObject = new SerializedObject(context.Serializer, StringView(rawTypeName));
|
SerializedObject newObject = new SerializedObject(context.Serializer, isStatic, StringView(rawTypeName));
|
||||||
|
|
||||||
Mono.mono_free(rawTypeName);
|
Mono.mono_free(rawTypeName);
|
||||||
|
|
||||||
|
|||||||
@@ -31,19 +31,31 @@ public class ScriptInstanceSerializer
|
|||||||
{
|
{
|
||||||
Debug.Profiler.ProfileFunction!();
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
for (let (id, script) in ScriptEngine._entityScriptInstances)
|
for (let (id, scriptInstance) in ScriptEngine._entityScriptInstances)
|
||||||
{
|
{
|
||||||
SerializeScriptInstance(script);
|
SerializeScriptInstance(scriptInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let (name, scriptClass) in ScriptEngine.EntityClasses)
|
||||||
|
{
|
||||||
|
SerializeStaticScriptClassFields(scriptClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes the given script instance.
|
/// Serializes the given script instance.
|
||||||
public void SerializeScriptInstance(ScriptInstance script)
|
public void SerializeScriptInstance(ScriptInstance script)
|
||||||
{
|
{
|
||||||
SerializedObject object = new SerializedObject(this, script.ScriptClass.FullName, script.EntityId);
|
SerializedObject object = new SerializedObject(this, false, script.ScriptClass.FullName, script.EntityId);
|
||||||
object.Serialize(script);
|
object.Serialize(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serializes the given script instance.
|
||||||
|
public void SerializeStaticScriptClassFields(ScriptClass scriptClass)
|
||||||
|
{
|
||||||
|
SerializedObject object = new SerializedObject(this, true, scriptClass.FullName, null);
|
||||||
|
object.SerializeStaticFields(scriptClass);
|
||||||
|
}
|
||||||
|
|
||||||
/// Deserializes this context into the instances currently managed by the script engine.
|
/// Deserializes this context into the instances currently managed by the script engine.
|
||||||
public void DeserializeScriptInstances()
|
public void DeserializeScriptInstances()
|
||||||
{
|
{
|
||||||
@@ -53,6 +65,11 @@ public class ScriptInstanceSerializer
|
|||||||
{
|
{
|
||||||
DeserializeScriptInstance(id, script);
|
DeserializeScriptInstance(id, script);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let (name, scriptClass) in ScriptEngine.EntityClasses)
|
||||||
|
{
|
||||||
|
DeserializeStaticScriptClassFields(scriptClass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes the data into the given script instance, if there is data available.
|
/// Deserializes the data into the given script instance, if there is data available.
|
||||||
@@ -69,6 +86,25 @@ public class ScriptInstanceSerializer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DeserializeStaticScriptClassFields(ScriptClass scriptClass)
|
||||||
|
{
|
||||||
|
for (let object in _serializedData.Values)
|
||||||
|
{
|
||||||
|
if (object.IsStatic && object.TypeName == scriptClass.FullName)
|
||||||
|
{
|
||||||
|
// No data anyway, save some time.
|
||||||
|
if (object.Fields.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
object.DeserializeStaticFields(scriptClass);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Replaces Entity references in the given serialized data using the specified translation table.
|
/// Replaces Entity references in the given serialized data using the specified translation table.
|
||||||
public void FixupSerializedIds(Dictionary<UUID, UUID> originalToCopyIds)
|
public void FixupSerializedIds(Dictionary<UUID, UUID> originalToCopyIds)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ class SerializedObject
|
|||||||
/// Todo: This sucks because we don't know all UUIDs beforehand and might accidentally assign the ID of an Entity to some class
|
/// Todo: This sucks because we don't know all UUIDs beforehand and might accidentally assign the ID of an Entity to some class
|
||||||
public UUID Id;
|
public UUID Id;
|
||||||
|
|
||||||
|
public bool IsStatic;
|
||||||
|
|
||||||
public String TypeName ~ delete:append _;
|
public String TypeName ~ delete:append _;
|
||||||
|
|
||||||
public ScriptInstanceSerializer Serializer;
|
public ScriptInstanceSerializer Serializer;
|
||||||
@@ -42,12 +44,14 @@ class SerializedObject
|
|||||||
public append Dictionary<StringView, (SerializationType PrimitiveType, FieldData Data)> Fields = .();
|
public append Dictionary<StringView, (SerializationType PrimitiveType, FieldData Data)> Fields = .();
|
||||||
|
|
||||||
[AllowAppend]
|
[AllowAppend]
|
||||||
public this(ScriptInstanceSerializer serializer, StringView? typeName, UUID? id = null)
|
public this(ScriptInstanceSerializer serializer, bool isStatic, StringView? typeName, UUID? id = null)
|
||||||
{
|
{
|
||||||
String typeNameCopy = append String(typeName.Value);
|
String typeNameCopy = append String(typeName.Value);
|
||||||
|
|
||||||
Serializer = serializer;
|
Serializer = serializer;
|
||||||
|
|
||||||
|
IsStatic = isStatic;
|
||||||
|
|
||||||
if (id == null)
|
if (id == null)
|
||||||
{
|
{
|
||||||
// Make sure we have no duplicate keys
|
// Make sure we have no duplicate keys
|
||||||
@@ -200,33 +204,24 @@ class SerializedObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typealias SerializeMethod = function MonoObject*(MonoObject* entity, void* contextPtr, MonoException** exception);
|
|
||||||
typealias DeserializeMethod = function MonoObject*(MonoObject* entity, void* contextPtr, MonoException** exception);
|
|
||||||
|
|
||||||
public void Serialize(ScriptInstance scriptInstance)
|
public void Serialize(ScriptInstance scriptInstance)
|
||||||
{
|
{
|
||||||
SerializeMethod serialize = (SerializeMethod)ScriptEngine.Classes.EntitySerializer.GetMethodThunk("Serialize", 2);
|
ScriptEngine.Classes.EntitySerializer.Serialize(scriptInstance, this);
|
||||||
|
|
||||||
void* thisPtr = Internal.UnsafeCastToPtr(this);
|
|
||||||
|
|
||||||
MonoException* exception = null;
|
|
||||||
serialize(scriptInstance.[Friend]_instance, thisPtr, &exception);
|
|
||||||
|
|
||||||
if (exception != null)
|
|
||||||
ScriptEngine.[Friend]HandleMonoException(exception, scriptInstance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Deserialize(ScriptInstance scriptInstance)
|
public void Deserialize(ScriptInstance scriptInstance)
|
||||||
{
|
{
|
||||||
DeserializeMethod deserialize = (DeserializeMethod)ScriptEngine.Classes.EntitySerializer.GetMethodThunk("Deserialize", 2);
|
ScriptEngine.Classes.EntitySerializer.Deserialize(scriptInstance, this);
|
||||||
|
}
|
||||||
|
|
||||||
void* thisPtr = Internal.UnsafeCastToPtr(this);
|
public void SerializeStaticFields(ScriptClass scriptClass)
|
||||||
|
{
|
||||||
|
ScriptEngine.Classes.EntitySerializer.SerializeStatic(scriptClass, this);
|
||||||
|
}
|
||||||
|
|
||||||
MonoException* exception = null;
|
public void DeserializeStaticFields(ScriptClass scriptClass)
|
||||||
deserialize(scriptInstance.[Friend]_instance, thisPtr, &exception);
|
{
|
||||||
|
ScriptEngine.Classes.EntitySerializer.DeserializeStatic(scriptClass, this);
|
||||||
if (exception != null)
|
|
||||||
ScriptEngine.[Friend]HandleMonoException(exception, scriptInstance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static this
|
static this
|
||||||
@@ -374,7 +369,7 @@ class SerializedObject
|
|||||||
|
|
||||||
Try!(Deserialize.Value<UUID>(reader, "ID", let objectId, environment));
|
Try!(Deserialize.Value<UUID>(reader, "ID", let objectId, environment));
|
||||||
|
|
||||||
SerializedObject object = new SerializedObject(scriptSerializer, type, objectId);
|
SerializedObject object = new SerializedObject(scriptSerializer, false, type, objectId);
|
||||||
|
|
||||||
while (reader.ObjectHasMore())
|
while (reader.ObjectHasMore())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,9 +64,6 @@ class SceneSerializer
|
|||||||
|
|
||||||
using (writer.ObjectBlock())
|
using (writer.ObjectBlock())
|
||||||
{
|
{
|
||||||
// TODO: Scene name goes here!
|
|
||||||
Serialize.Value(writer, "Name", "Scene name here pls!!!");
|
|
||||||
|
|
||||||
Serialize.Value(writer, "Version", FileVersion);
|
Serialize.Value(writer, "Version", FileVersion);
|
||||||
|
|
||||||
writer.Identifier("Entities");
|
writer.Identifier("Entities");
|
||||||
@@ -93,7 +90,30 @@ class SceneSerializer
|
|||||||
{
|
{
|
||||||
for (UUID id in _objectsNotWritten)
|
for (UUID id in _objectsNotWritten)
|
||||||
{
|
{
|
||||||
Serialize.Value(writer, _scriptSerializer.GetSerializedObject(id));
|
SerializedObject object = _scriptSerializer.GetSerializedObject(id);
|
||||||
|
|
||||||
|
if (object.IsStatic)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Serialize.Value(writer, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.EntryEnd();
|
||||||
|
|
||||||
|
writer.Identifier("StaticFields");
|
||||||
|
|
||||||
|
// Write all objects that don't belong to an entity. (referenced Arrays, Classes, etc...)
|
||||||
|
using (writer.ArrayBlock())
|
||||||
|
{
|
||||||
|
for (UUID id in _objectsNotWritten)
|
||||||
|
{
|
||||||
|
SerializedObject object = _scriptSerializer.GetSerializedObject(id);
|
||||||
|
|
||||||
|
if (!object.IsStatic || object.Fields.Count == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Serialize.Value(writer, object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +366,9 @@ class SceneSerializer
|
|||||||
case "Entities":
|
case "Entities":
|
||||||
Try!(DeserializeEntities(reader, loadAsPrefab));
|
Try!(DeserializeEntities(reader, loadAsPrefab));
|
||||||
case "ReferencedObjects":
|
case "ReferencedObjects":
|
||||||
Try!(DeserializeReferencedObjects(reader));
|
Try!(DeserializeReferencedObjects(reader, false));
|
||||||
|
case "StaticFields":
|
||||||
|
Try!(DeserializeReferencedObjects(reader, true));
|
||||||
default:
|
default:
|
||||||
Log.EngineLogger.Warning($"Encountered unexpected Identifier \"{identifier}\".");
|
Log.EngineLogger.Warning($"Encountered unexpected Identifier \"{identifier}\".");
|
||||||
}
|
}
|
||||||
@@ -390,13 +412,15 @@ class SceneSerializer
|
|||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Result<void> DeserializeReferencedObjects(BonReader reader)
|
private Result<void> DeserializeReferencedObjects(BonReader reader, bool isStatic)
|
||||||
{
|
{
|
||||||
Try!(reader.ArrayBlock());
|
Try!(reader.ArrayBlock());
|
||||||
|
|
||||||
while (reader.ArrayHasMore())
|
while (reader.ArrayHasMore())
|
||||||
{
|
{
|
||||||
Try!(SerializedObject.BonDeserialize(reader, _scriptSerializer, _fileVersion, gBonEnv));
|
SerializedObject object = Try!(SerializedObject.BonDeserialize(reader, _scriptSerializer, _fileVersion, gBonEnv));
|
||||||
|
|
||||||
|
object.IsStatic = isStatic;
|
||||||
|
|
||||||
TryEndEntry(reader);
|
TryEndEntry(reader);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,6 +146,22 @@ internal class EntityEditor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool ShowButtonInEditor(MethodInfo methodInfo)
|
||||||
|
{
|
||||||
|
var showButton = methodInfo.GetCustomAttribute<ShowButtonAttribute>();
|
||||||
|
|
||||||
|
if (showButton == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Application.IsInEditMode && !showButton.Visibility.HasFlag(ButtonVisibility.InEditMode))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Application.IsInPlayMode && !showButton.Visibility.HasFlag(ButtonVisibility.InPlayMode))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Entry point for the engine to show the editor for the given script instance.
|
/// Entry point for the engine to show the editor for the given script instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -908,18 +924,65 @@ internal class EntityEditor
|
|||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowEditor(Type type, object? reference)
|
private static void ShowEditor(Type type, object? reference)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
// Iterate all fields
|
// Iterate all fields
|
||||||
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
//foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
||||||
|
foreach (MemberInfo member in type.GetMembers(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
ImGui.PushID(i);
|
ImGui.PushID(i);
|
||||||
|
|
||||||
if (ShowFieldInEditor(field))
|
switch (member)
|
||||||
{
|
{
|
||||||
|
case FieldInfo field:
|
||||||
|
ShowField(field, reference);
|
||||||
|
break;
|
||||||
|
case MethodInfo method:
|
||||||
|
ShowButton(method, reference);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool showedHeader = false;
|
||||||
|
|
||||||
|
foreach (FieldInfo field in type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static))
|
||||||
|
{
|
||||||
|
if (!showedHeader)
|
||||||
|
{
|
||||||
|
BeginNewRow();
|
||||||
|
|
||||||
|
if (!ImGui.TreeNodeEx("Static Fields", ImGuiTreeNodeFlags.AllowOverlap | ImGuiTreeNodeFlags.SpanAllColumns))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
showedHeader = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
ImGui.PushID(i);
|
||||||
|
|
||||||
|
ShowField(field, null);
|
||||||
|
|
||||||
|
ImGui.PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showedHeader)
|
||||||
|
{
|
||||||
|
ImGui.TreePop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ShowField(FieldInfo field, object? reference)
|
||||||
|
{
|
||||||
|
if (!ShowFieldInEditor(field))
|
||||||
|
return;
|
||||||
|
|
||||||
object value = field.GetValue(reference);
|
object value = field.GetValue(reference);
|
||||||
|
|
||||||
IEnumerable<Attribute> attributes = field.GetCustomAttributes();
|
IEnumerable<Attribute> attributes = field.GetCustomAttributes();
|
||||||
@@ -946,40 +1009,14 @@ internal class EntityEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.PopID();
|
private static void ShowButton(MethodInfo method, object? reference)
|
||||||
}
|
|
||||||
|
|
||||||
ShowButtons(type, reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shows all buttons in the UI.
|
|
||||||
/// </summary>
|
|
||||||
private static void ShowButtons(Type type, object? reference)
|
|
||||||
{
|
{
|
||||||
ImGui.PushID("Buttons");
|
if (!ShowButtonInEditor(method))
|
||||||
|
return;
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
// Iterate all methods
|
|
||||||
foreach (MethodInfo method in type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
|
||||||
{
|
|
||||||
var showButton = method.GetCustomAttribute<ShowButtonAttribute>();
|
var showButton = method.GetCustomAttribute<ShowButtonAttribute>();
|
||||||
|
|
||||||
if (showButton == null)
|
BeginNewRow();
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Application.IsInEditMode && !showButton.Visibility.HasFlag(ButtonVisibility.InEditMode))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Application.IsInPlayMode && !showButton.Visibility.HasFlag(ButtonVisibility.InPlayMode))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
ImGui.PushID(i);
|
|
||||||
|
|
||||||
ImGui.TableNextRow();
|
|
||||||
ImGui.TableSetColumnIndex(0);
|
|
||||||
|
|
||||||
if (method.GetParameters().Length > 0)
|
if (method.GetParameters().Length > 0)
|
||||||
{
|
{
|
||||||
@@ -1000,11 +1037,6 @@ internal class EntityEditor
|
|||||||
Log.Exception(ex);
|
Log.Exception(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.PopID();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui.PopID();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ListPayload
|
struct ListPayload
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace GlitchyEngine.Extensions;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extends the <see cref="FieldInfo"/>-class with useful methods.
|
|
||||||
/// </summary>
|
|
||||||
public static class FieldInfoExtension
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Returns <see langword="true"/> if the field has the specified attribute.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type of the attribte.</typeparam>
|
|
||||||
public static bool HasCustomAttribute<T>(this FieldInfo fiedInfo) where T : Attribute
|
|
||||||
{
|
|
||||||
return fiedInfo.GetCustomAttribute<T>() != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extends <see cref="MemberInfo"/> with useful methods.
|
||||||
|
/// </summary>
|
||||||
|
public static class MemberInfoExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns <see langword="true"/> if the member has the specified attribute.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of the attribute.</typeparam>
|
||||||
|
public static bool HasCustomAttribute<T>(this MemberInfo memberInfo) where T : Attribute
|
||||||
|
{
|
||||||
|
return memberInfo.GetCustomAttribute<T>() != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -227,4 +227,17 @@ public static class TypeExtension
|
|||||||
|
|
||||||
return nameBuilder.ToString();
|
return nameBuilder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns <see langword="true"/> if the type has at least one static field; <see langword="false"/> otherwise.
|
||||||
|
/// </summary>
|
||||||
|
public static bool HasStaticFields(this Type type)
|
||||||
|
{
|
||||||
|
foreach (FieldInfo _ in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ internal static class ScriptGlue
|
|||||||
internal static extern void Serialization_SerializeField(IntPtr serializationContext, SerializationType type, string name, object? value, string? fullTypeName = null);
|
internal static extern void Serialization_SerializeField(IntPtr serializationContext, SerializationType type, string name, object? value, string? fullTypeName = null);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
internal static extern void Serialization_CreateObject(IntPtr currentContext, string fullTypeName, out IntPtr context, out UUID id);
|
internal static extern void Serialization_CreateObject(IntPtr currentContext, bool isStatic, string fullTypeName, out IntPtr context, out UUID id);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
public static extern unsafe void Serialization_DeserializeField(IntPtr internalContext, SerializationType expectedType, string fieldName, byte* value, out SerializationType actualType);
|
public static extern unsafe void Serialization_DeserializeField(IntPtr internalContext, SerializationType expectedType, string fieldName, byte* value, out SerializationType actualType);
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ public class DeserializationObject
|
|||||||
|
|
||||||
private IntPtr _internalContext;
|
private IntPtr _internalContext;
|
||||||
|
|
||||||
|
private bool _isStatic;
|
||||||
|
|
||||||
private UUID _id;
|
private UUID _id;
|
||||||
|
|
||||||
private Stack<string> _structScope = new();
|
private Stack<string> _structScope = new();
|
||||||
@@ -57,9 +59,12 @@ public class DeserializationObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeserializationObject(IntPtr internalContext, UUID id, Dictionary<UUID, DeserializationObject> deserializedClasses)
|
public bool IsStatic => _isStatic;
|
||||||
|
|
||||||
|
public DeserializationObject(IntPtr internalContext, bool isStatic, UUID id, Dictionary<UUID, DeserializationObject> deserializedClasses)
|
||||||
{
|
{
|
||||||
_internalContext = internalContext;
|
_internalContext = internalContext;
|
||||||
|
_isStatic = isStatic;
|
||||||
_id = id;
|
_id = id;
|
||||||
DeserializedClasses = deserializedClasses;
|
DeserializedClasses = deserializedClasses;
|
||||||
}
|
}
|
||||||
@@ -114,7 +119,7 @@ public class DeserializationObject
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
context = new DeserializationObject(contextPtr, id, DeserializedClasses);
|
context = new DeserializationObject(contextPtr, false, id, DeserializedClasses);
|
||||||
|
|
||||||
DeserializedClasses.Add(id, context);
|
DeserializedClasses.Add(id, context);
|
||||||
|
|
||||||
@@ -251,6 +256,36 @@ public class DeserializationObject
|
|||||||
DeserializeFields(entity);
|
DeserializeFields(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Deserialize(Type type)
|
||||||
|
{
|
||||||
|
_instance = null;
|
||||||
|
|
||||||
|
DeserializeStaticFields(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeserializeStaticFields(Type type)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
foreach (FieldInfo field in type.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
|
||||||
|
{
|
||||||
|
if (!EntitySerializer.SerializeField(field, true))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
object currentValue = field.GetValue(null);
|
||||||
|
|
||||||
|
object? deserializeValue = DeserializeField(currentValue, field.FieldType, field.Name);
|
||||||
|
|
||||||
|
if (deserializeValue != NoValueDeserialized)
|
||||||
|
{
|
||||||
|
field.SetValue(null, deserializeValue);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
public bool DeserializeFields(object obj)
|
public bool DeserializeFields(object obj)
|
||||||
{
|
{
|
||||||
Type type = obj.GetType();
|
Type type = obj.GetType();
|
||||||
@@ -259,7 +294,7 @@ public class DeserializationObject
|
|||||||
|
|
||||||
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
||||||
{
|
{
|
||||||
if (!EntitySerializer.SerializeField(field))
|
if (!EntitySerializer.SerializeField(field, false))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
object currentValue = field.GetValue(obj);
|
object currentValue = field.GetValue(obj);
|
||||||
|
|||||||
@@ -7,102 +7,40 @@ using GlitchyEngine.Extensions;
|
|||||||
|
|
||||||
namespace GlitchyEngine.Serialization;
|
namespace GlitchyEngine.Serialization;
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum SerializationType : uint
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
Bool = 1u << 31,
|
|
||||||
|
|
||||||
TextTypes = 1 << 30,
|
|
||||||
|
|
||||||
Char = TextTypes | 1,
|
|
||||||
String = TextTypes | 2,
|
|
||||||
|
|
||||||
Number = 1 << 29,
|
|
||||||
Integer = Number | 1 << 28,
|
|
||||||
|
|
||||||
Int8 = Integer | 1,
|
|
||||||
Int16 = Integer | 2,
|
|
||||||
Int32 = Integer | 3,
|
|
||||||
Int64 = Integer | 4,
|
|
||||||
UInt8 = Integer | 5,
|
|
||||||
UInt16 = Integer | 6,
|
|
||||||
UInt32 = Integer | 7,
|
|
||||||
UInt64 = Integer | 8,
|
|
||||||
|
|
||||||
FloatingPoint = Number | 1 << 27,
|
|
||||||
|
|
||||||
Float = FloatingPoint | 1,
|
|
||||||
Double = FloatingPoint | 2,
|
|
||||||
Decimal = FloatingPoint | 3,
|
|
||||||
|
|
||||||
Enum = 1 << 26,
|
|
||||||
|
|
||||||
EntityReference = 1 << 25,
|
|
||||||
ComponentReference = 1 << 24,
|
|
||||||
|
|
||||||
ObjectReference = 1 << 23,
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SerializationTypeExtension
|
|
||||||
{
|
|
||||||
public static bool CanConvertTo(this SerializationType currentType, SerializationType targetType)
|
|
||||||
{
|
|
||||||
if (currentType.HasFlag(SerializationType.Number) && targetType.HasFlag(SerializationType.Number))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Type? GetTypeInstance(this SerializationType currentType)
|
|
||||||
{
|
|
||||||
return currentType switch
|
|
||||||
{
|
|
||||||
SerializationType.Bool => typeof(bool),
|
|
||||||
SerializationType.Char => typeof(char),
|
|
||||||
SerializationType.String => typeof(string),
|
|
||||||
SerializationType.Int8 => typeof(sbyte),
|
|
||||||
SerializationType.Int16 => typeof(short),
|
|
||||||
SerializationType.Int32 => typeof(int),
|
|
||||||
SerializationType.Int64 => typeof(long),
|
|
||||||
SerializationType.UInt8 => typeof(byte),
|
|
||||||
SerializationType.UInt16 => typeof(ushort),
|
|
||||||
SerializationType.UInt32 => typeof(uint),
|
|
||||||
SerializationType.UInt64 => typeof(ulong),
|
|
||||||
SerializationType.Float => typeof(float),
|
|
||||||
SerializationType.Double => typeof(double),
|
|
||||||
SerializationType.Decimal => typeof(decimal),
|
|
||||||
SerializationType.Enum => typeof(Enum),
|
|
||||||
SerializationType.EntityReference => typeof(UUID),
|
|
||||||
SerializationType.ComponentReference => typeof(UUID),
|
|
||||||
SerializationType.ObjectReference => typeof(UUID),
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class EntitySerializer
|
internal static class EntitySerializer
|
||||||
{
|
{
|
||||||
internal static void Serialize(Entity entity, IntPtr internalContext)
|
internal static void Serialize(Entity entity, IntPtr internalContext)
|
||||||
{
|
{
|
||||||
SerializedObject obj = new SerializedObject(internalContext, UUID.Zero, new Dictionary<object, SerializedObject>());
|
SerializedObject obj = new SerializedObject(internalContext, false, UUID.Zero, new Dictionary<object, SerializedObject>());
|
||||||
obj.Serialize(entity);
|
obj.Serialize(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Deserialize(Entity entity, IntPtr internalContext)
|
internal static void Deserialize(Entity entity, IntPtr internalContext)
|
||||||
{
|
{
|
||||||
DeserializationObject obj = new DeserializationObject(internalContext, UUID.Zero, new Dictionary<UUID, DeserializationObject>());
|
DeserializationObject obj = new DeserializationObject(internalContext, false, UUID.Zero, new Dictionary<UUID, DeserializationObject>());
|
||||||
obj.Deserialize(entity);
|
obj.Deserialize(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void SerializeStaticFields(Type type, IntPtr internalContext)
|
||||||
|
{
|
||||||
|
SerializedObject obj = new SerializedObject(internalContext, true, UUID.Zero, new Dictionary<object, SerializedObject>());
|
||||||
|
obj.Serialize(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DeserializeStaticFields(Type type, IntPtr internalContext)
|
||||||
|
{
|
||||||
|
DeserializationObject obj = new DeserializationObject(internalContext, true, UUID.Zero, new Dictionary<UUID, DeserializationObject>());
|
||||||
|
obj.Deserialize(type);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns whether or not the field described by the given <see cref="fieldInfo"/> should be serialized or not.
|
/// Returns whether or not the field described by the given <see cref="fieldInfo"/> should be serialized or not.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static bool SerializeField(FieldInfo fieldInfo)
|
/// <param name="fieldInfo">The field info for which to check whether the field should be serialized or not.</param>
|
||||||
|
/// <param name="staticSerialization">If <see langword="true"/> the only Static fields can be serialized; if <see langword="false"/> only instance fields can be serialized.</param>
|
||||||
|
internal static bool SerializeField(FieldInfo fieldInfo, bool staticSerialization)
|
||||||
{
|
{
|
||||||
// TODO: We want to be able to serialize static fields in the future!
|
if (staticSerialization != fieldInfo.IsStatic)
|
||||||
if (fieldInfo.IsStatic)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var serializeField = fieldInfo.HasCustomAttribute<SerializeFieldAttribute>();
|
var serializeField = fieldInfo.HasCustomAttribute<SerializeFieldAttribute>();
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Serialization;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum SerializationType : uint
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
Bool = 1u << 31,
|
||||||
|
|
||||||
|
TextTypes = 1 << 30,
|
||||||
|
|
||||||
|
Char = TextTypes | 1,
|
||||||
|
String = TextTypes | 2,
|
||||||
|
|
||||||
|
Number = 1 << 29,
|
||||||
|
Integer = Number | 1 << 28,
|
||||||
|
|
||||||
|
Int8 = Integer | 1,
|
||||||
|
Int16 = Integer | 2,
|
||||||
|
Int32 = Integer | 3,
|
||||||
|
Int64 = Integer | 4,
|
||||||
|
UInt8 = Integer | 5,
|
||||||
|
UInt16 = Integer | 6,
|
||||||
|
UInt32 = Integer | 7,
|
||||||
|
UInt64 = Integer | 8,
|
||||||
|
|
||||||
|
FloatingPoint = Number | 1 << 27,
|
||||||
|
|
||||||
|
Float = FloatingPoint | 1,
|
||||||
|
Double = FloatingPoint | 2,
|
||||||
|
Decimal = FloatingPoint | 3,
|
||||||
|
|
||||||
|
Enum = 1 << 26,
|
||||||
|
|
||||||
|
EntityReference = 1 << 25,
|
||||||
|
ComponentReference = 1 << 24,
|
||||||
|
|
||||||
|
ObjectReference = 1 << 23,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SerializationTypeExtension
|
||||||
|
{
|
||||||
|
public static bool CanConvertTo(this SerializationType currentType, SerializationType targetType)
|
||||||
|
{
|
||||||
|
if (currentType.HasFlag(SerializationType.Number) && targetType.HasFlag(SerializationType.Number))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Type? GetTypeInstance(this SerializationType currentType) =>
|
||||||
|
currentType switch
|
||||||
|
{
|
||||||
|
SerializationType.Bool => typeof(bool),
|
||||||
|
SerializationType.Char => typeof(char),
|
||||||
|
SerializationType.String => typeof(string),
|
||||||
|
SerializationType.Int8 => typeof(sbyte),
|
||||||
|
SerializationType.Int16 => typeof(short),
|
||||||
|
SerializationType.Int32 => typeof(int),
|
||||||
|
SerializationType.Int64 => typeof(long),
|
||||||
|
SerializationType.UInt8 => typeof(byte),
|
||||||
|
SerializationType.UInt16 => typeof(ushort),
|
||||||
|
SerializationType.UInt32 => typeof(uint),
|
||||||
|
SerializationType.UInt64 => typeof(ulong),
|
||||||
|
SerializationType.Float => typeof(float),
|
||||||
|
SerializationType.Double => typeof(double),
|
||||||
|
SerializationType.Decimal => typeof(decimal),
|
||||||
|
SerializationType.Enum => typeof(Enum),
|
||||||
|
SerializationType.EntityReference => typeof(UUID),
|
||||||
|
SerializationType.ComponentReference => typeof(UUID),
|
||||||
|
SerializationType.ObjectReference => typeof(UUID),
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -20,15 +20,20 @@ public class SerializedObject
|
|||||||
|
|
||||||
private string _structScopeName = "";
|
private string _structScopeName = "";
|
||||||
|
|
||||||
|
private bool _isStatic;
|
||||||
|
|
||||||
private delegate void SerializeMethod(SerializedObject container, string fieldName, object? fieldValue, Type fieldType);
|
private delegate void SerializeMethod(SerializedObject container, string fieldName, object? fieldValue, Type fieldType);
|
||||||
|
|
||||||
private static Dictionary<Type, SerializeMethod> _customSerializers = new();
|
private static Dictionary<Type, SerializeMethod> _customSerializers = new();
|
||||||
|
|
||||||
public UUID Id => _id;
|
public UUID Id => _id;
|
||||||
|
|
||||||
public SerializedObject(IntPtr internalContext, UUID id, Dictionary<object, SerializedObject> serializedClasses)
|
public bool IsStatic => _isStatic;
|
||||||
|
|
||||||
|
public SerializedObject(IntPtr internalContext, bool isStatic, UUID id, Dictionary<object, SerializedObject> serializedClasses)
|
||||||
{
|
{
|
||||||
_internalContext = internalContext;
|
_internalContext = internalContext;
|
||||||
|
_isStatic = isStatic;
|
||||||
_id = id;
|
_id = id;
|
||||||
_serializedClasses = serializedClasses;
|
_serializedClasses = serializedClasses;
|
||||||
}
|
}
|
||||||
@@ -40,9 +45,9 @@ public class SerializedObject
|
|||||||
if (_serializedClasses.TryGetValue(o, out context))
|
if (_serializedClasses.TryGetValue(o, out context))
|
||||||
return (context, false);
|
return (context, false);
|
||||||
|
|
||||||
ScriptGlue.Serialization_CreateObject(_internalContext, o.GetType().ToString(), out IntPtr contextPtr, out UUID id);
|
ScriptGlue.Serialization_CreateObject(_internalContext, false, o.GetType().ToString(), out IntPtr contextPtr, out UUID id);
|
||||||
|
|
||||||
context = new SerializedObject(contextPtr, id, _serializedClasses);
|
context = new SerializedObject(contextPtr, false, id, _serializedClasses);
|
||||||
|
|
||||||
_serializedClasses.Add(o, context);
|
_serializedClasses.Add(o, context);
|
||||||
|
|
||||||
@@ -95,16 +100,21 @@ public class SerializedObject
|
|||||||
|
|
||||||
public void Serialize(Entity entity)
|
public void Serialize(Entity entity)
|
||||||
{
|
{
|
||||||
SerializeFields(entity);
|
SerializeInstanceFields(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SerializeFields(object obj)
|
public void Serialize(Type type)
|
||||||
|
{
|
||||||
|
SerializeStaticTypeFields(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SerializeInstanceFields(object obj)
|
||||||
{
|
{
|
||||||
Type type = obj.GetType();
|
Type type = obj.GetType();
|
||||||
|
|
||||||
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
||||||
{
|
{
|
||||||
if (!EntitySerializer.SerializeField(field))
|
if (!EntitySerializer.SerializeField(field, false))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
object? fieldValue = field.GetValue(obj);
|
object? fieldValue = field.GetValue(obj);
|
||||||
@@ -114,6 +124,20 @@ public class SerializedObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SerializeStaticTypeFields(Type type)
|
||||||
|
{
|
||||||
|
foreach (FieldInfo field in type.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public))
|
||||||
|
{
|
||||||
|
if (!EntitySerializer.SerializeField(field, true))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
object? fieldValue = field.GetValue(null);
|
||||||
|
Type fieldType = fieldValue?.GetType() ?? field.FieldType;
|
||||||
|
|
||||||
|
SerializeField(field.Name, fieldValue, fieldType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool TryCustomSerializer(string fieldName, object? fieldValue, Type fieldType)
|
private bool TryCustomSerializer(string fieldName, object? fieldValue, Type fieldType)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -285,7 +309,7 @@ public class SerializedObject
|
|||||||
{
|
{
|
||||||
PushScope(fieldName);
|
PushScope(fieldName);
|
||||||
|
|
||||||
SerializeFields(fieldValue);
|
SerializeInstanceFields(fieldValue);
|
||||||
|
|
||||||
PopScope();
|
PopScope();
|
||||||
}
|
}
|
||||||
@@ -312,7 +336,7 @@ public class SerializedObject
|
|||||||
|
|
||||||
if (newContext)
|
if (newContext)
|
||||||
{
|
{
|
||||||
context.SerializeFields(fieldValue);
|
context.SerializeInstanceFields(fieldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddField(fieldName, SerializationType.ObjectReference, context._id);
|
AddField(fieldName, SerializationType.ObjectReference, context._id);
|
||||||
|
|||||||
Reference in New Issue
Block a user