ScriptEngine work and cleanup

This commit is contained in:
Simon Lübeß
2025-07-18 12:40:44 +02:00
parent 271286fb7e
commit 28311165ad
22 changed files with 204 additions and 1031 deletions
+11 -7
View File
@@ -7,9 +7,9 @@ namespace GlitchyEngine.Scripting;
public struct ScriptFunctionPointers public struct ScriptFunctionPointers
{ {
public function void() OnCreate; public function void(UUID entityId) OnCreate;
public function void(float) OnUpdate; public function void(UUID entityId, float deltaTime) OnUpdate;
public function void() OnDestroy; public function void(UUID entityId, bool callEntity) OnDestroy;
} }
static class CoreClrHelper static class CoreClrHelper
@@ -39,7 +39,7 @@ static class CoreClrHelper
private function void ThrowExceptionFunc(char8* message); private function void ThrowExceptionFunc(char8* message);
static ThrowExceptionFunc _throwException; static ThrowExceptionFunc _throwException;
private function void RegisterComponentTypeFunc(StringView fullComponentTypeName, function void(UUID entityId) addComponent, function bool(UUID entityId) hasComponent, function void(UUID entityId) removeComponent); private function void RegisterComponentTypeFunc(char8* fullComponentTypeName, function void(UUID entityId) addComponent, function bool(UUID entityId) hasComponent, function void(UUID entityId) removeComponent);
static RegisterComponentTypeFunc _registerComponentType; static RegisterComponentTypeFunc _registerComponentType;
public static ScriptFunctionPointers _entityScriptFunctions; public static ScriptFunctionPointers _entityScriptFunctions;
@@ -180,7 +180,8 @@ static class CoreClrHelper
return rc; return rc;
} }
public static int GetFunctionPointerUnmanagedCallersOnly<T>(StringView typeName, StringView methodName, out T outDelegate) where T: operator explicit void*
public static Result<void, int> GetFunctionPointerUnmanagedCallersOnly<T>(StringView typeName, StringView methodName, out T outDelegate) where T: operator explicit void*
{ {
void* funPtr = null; void* funPtr = null;
@@ -189,7 +190,10 @@ static class CoreClrHelper
outDelegate = (T)funPtr; outDelegate = (T)funPtr;
return rc; if (rc == 0)
return .Ok;
return .Err(rc);
} }
public static void ThrowException(StringView message) public static void ThrowException(StringView message)
@@ -199,6 +203,6 @@ static class CoreClrHelper
public static void RegisterComponent(StringView fullComponentTypeName, function void(UUID entityId) addComponent, function bool(UUID entityId) hasComponent, function void(UUID entityId) removeComponent) public static void RegisterComponent(StringView fullComponentTypeName, function void(UUID entityId) addComponent, function bool(UUID entityId) hasComponent, function void(UUID entityId) removeComponent)
{ {
_registerComponentType(fullComponentTypeName, addComponent, hasComponent, removeComponent); _registerComponentType(fullComponentTypeName.Ptr, addComponent, hasComponent, removeComponent);
} }
} }
@@ -14,7 +14,7 @@ class EntityEditorWrapper : NewScriptClass
private ShowEntityEditorFunc _showEntityEditorFunc; private ShowEntityEditorFunc _showEntityEditorFunc;
[AllowAppend] [AllowAppend]
public this() : base(FullName, .Empty, .None, false) public this() : base("GlitchyEngine.ScriptGlue.ShowEntityEditor", .Empty, .None, false)
{ {
CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "ShowEntityEditor", out _showEntityEditorFunc); CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "ShowEntityEditor", out _showEntityEditorFunc);
@@ -1,5 +1,4 @@
using System; using System;
using Mono;
using GlitchyEngine.Core; using GlitchyEngine.Core;
using GlitchyEngine.Serialization; using GlitchyEngine.Serialization;
@@ -7,19 +6,19 @@ namespace GlitchyEngine.Scripting;
using internal GlitchyEngine.Scripting; using internal GlitchyEngine.Scripting;
class EntitySerializerWrapper : ScriptClass class EntitySerializerWrapper : NewScriptClass
{ {
function void CreateSerializationContextMethod(void* serializerPtr, MonoException** exception); function void CreateSerializationContextMethod(void* serializerPtr);
function void ClearSerializationContextMethod(void* serializerPtr, MonoException** exception); //function void ClearSerializationContextMethod(void* serializerPtr);
function void DestroySerializationContextMethod(void* serializerPtr, MonoException** exception); function void DestroySerializationContextMethod(void* serializerPtr);
function void SerializeMethod(MonoObject* entity, void* serializedObjPtr, void* serializerPtr, MonoException** exception); function void SerializeMethod(UUID entityId, void* serializedObjPtr, void* serializerPtr);
function void DeserializeMethod(MonoObject* entity, void* serializedObjPtr, void* serializerPtr, MonoException** exception); function void DeserializeMethod(UUID entityId, void* serializedObjPtr, void* serializerPtr);
function void SerializeStaticMethod(MonoReflectionType* type, void* serializedObjPtr, void* serializerPtr, MonoException** exception); function void SerializeStaticMethod(char8* fullTypeName, void* serializedObjPtr, void* serializerPtr);
function void DeserializeStaticMethod(MonoReflectionType* type, void* serializedObjPtr, void* serializerPtr, MonoException** exception); function void DeserializeStaticMethod(char8* fullTypeName, void* serializedObjPtr, void* serializerPtr);
private CreateSerializationContextMethod _createSerializationContextMethod; private CreateSerializationContextMethod _createSerializationContextMethod;
private ClearSerializationContextMethod _clearSerializationContextMethod; //private ClearSerializationContextMethod _clearSerializationContextMethod;
private DestroySerializationContextMethod _destroySerializationContextMethod; private DestroySerializationContextMethod _destroySerializationContextMethod;
private SerializeMethod _serializeMethod; private SerializeMethod _serializeMethod;
@@ -28,70 +27,24 @@ class EntitySerializerWrapper : ScriptClass
private DeserializeStaticMethod _deserializeStaticMethod; private DeserializeStaticMethod _deserializeStaticMethod;
[AllowAppend] [AllowAppend]
public this(StringView classNamespace, StringView className, MonoImage* image) : base(classNamespace, className, image) public this() : base("GlitchyEngine.Serialization.EntitySerializer", .Empty, .None, false)
{ {
_serializeMethod = (SerializeMethod)GetMethodThunk("Serialize", 3); CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "CreateSerializationContext", out _createSerializationContextMethod);
CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "DestroySerializationContext", out _destroySerializationContextMethod);
if (_serializeMethod == null) CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "EntitySerializer_Serialize", out _serializeMethod);
{ CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "EntitySerializer_Deserialize", out _deserializeMethod);
Log.EngineLogger.Error("EntitySerializer has no \"Serialize\" method."); CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "EntitySerializer_SerializeStaticFields", out _serializeStaticMethod);
} CoreClrHelper.GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "EntitySerializer_DeserializeStaticFields", out _deserializeStaticMethod);
_deserializeMethod = (DeserializeMethod)GetMethodThunk("Deserialize", 3);
if (_serializeMethod == null)
{
Log.EngineLogger.Error("EntitySerializer has no \"Deserialize\" method.");
}
_serializeStaticMethod = (SerializeStaticMethod)GetMethodThunk("SerializeStaticFields", 3);
if (_serializeStaticMethod == null)
{
Log.EngineLogger.Error("EntitySerializer has no \"SerializeStaticStatic\" method.");
}
_deserializeStaticMethod = (SerializeStaticMethod)GetMethodThunk("DeserializeStaticFields", 3);
if (_deserializeStaticMethod == null)
{
Log.EngineLogger.Error("EntitySerializer has no \"DeserializeStaticStatic\" method.");
}
_createSerializationContextMethod = (CreateSerializationContextMethod)GetMethodThunk("CreateSerializationContext", 1);
if (_createSerializationContextMethod == null)
{
Log.EngineLogger.Error("EntitySerializer has no \"CreateSerializationContext\" method.");
}
_clearSerializationContextMethod = (ClearSerializationContextMethod)GetMethodThunk("ClearSerializationContext", 1);
if (_clearSerializationContextMethod == null)
{
Log.EngineLogger.Error("EntitySerializer has no \"ClearSerializationContext\" method.");
}
_destroySerializationContextMethod = (DestroySerializationContextMethod)GetMethodThunk("DestroySerializationContext", 1);
if (_destroySerializationContextMethod == null)
{
Log.EngineLogger.Error("EntitySerializer has no \"DestroySerializationContext\" method.");
}
} }
public void CreateSerializationContext(ScriptInstanceSerializer serializer) public void CreateSerializationContext(ScriptInstanceSerializer serializer)
{ {
void* serializerPtr = Internal.UnsafeCastToPtr(serializer); void* serializerPtr = Internal.UnsafeCastToPtr(serializer);
MonoException* exception = null; _createSerializationContextMethod(serializerPtr);
_createSerializationContextMethod(serializerPtr, &exception);
if (exception != null)
ScriptEngine.[Friend]HandleMonoException(exception, null);
} }
public void ClearSerializationContext(ScriptInstanceSerializer serializer) /*public void ClearSerializationContext(ScriptInstanceSerializer serializer)
{ {
void* serializerPtr = Internal.UnsafeCastToPtr(serializer); void* serializerPtr = Internal.UnsafeCastToPtr(serializer);
@@ -100,70 +53,44 @@ class EntitySerializerWrapper : ScriptClass
if (exception != null) if (exception != null)
ScriptEngine.[Friend]HandleMonoException(exception, null); ScriptEngine.[Friend]HandleMonoException(exception, null);
} }*/
public void DestroySerializationContext(ScriptInstanceSerializer serializer) public void DestroySerializationContext(ScriptInstanceSerializer serializer)
{ {
void* serializerPtr = Internal.UnsafeCastToPtr(serializer); void* serializerPtr = Internal.UnsafeCastToPtr(serializer);
MonoException* exception = null; _destroySerializationContextMethod(serializerPtr);
_destroySerializationContextMethod(serializerPtr, &exception);
if (exception != null)
ScriptEngine.[Friend]HandleMonoException(exception, null);
} }
public void Serialize(ScriptInstance instance, SerializedObject serializedObject) public void Serialize(NewScriptInstance instance, SerializedObject serializedObject)
{ {
void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject); void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject);
void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer); void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer);
MonoException* exception = null; _serializeMethod(instance.EntityId, serializedObjectPtr, serializerPtr);
_serializeMethod(instance.[Friend]_instance, serializedObjectPtr, serializerPtr, &exception);
if (exception != null)
ScriptEngine.[Friend]HandleMonoException(exception, instance);
} }
public void SerializeStatic(ScriptClass @class, SerializedObject serializedObject) public void SerializeStatic(NewScriptClass @class, SerializedObject serializedObject)
{ {
void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject); void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject);
void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer); void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer);
MonoType* type = Mono.mono_class_get_type(@class.[Friend]_monoClass); _serializeStaticMethod(@class.FullName.CStr(), serializedObjectPtr, serializerPtr);
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, type);
MonoException* exception = null;
_serializeStaticMethod(reflectionType, serializedObjectPtr, serializerPtr, &exception);
if (exception != null)
ScriptEngine.[Friend]HandleMonoException(exception, null);
} }
public void Deserialize(ScriptInstance instance, SerializedObject serializedObject) public void Deserialize(NewScriptInstance instance, SerializedObject serializedObject)
{ {
void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject); void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject);
void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer); void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer);
MonoException* exception = null; _deserializeMethod(instance.EntityId, serializedObjectPtr, serializerPtr);
_deserializeMethod(instance.[Friend]_instance, serializedObjectPtr, serializerPtr, &exception);
if (exception != null)
ScriptEngine.[Friend]HandleMonoException(exception, instance);
} }
public void DeserializeStatic(ScriptClass @class, SerializedObject serializedObject) public void DeserializeStatic(NewScriptClass @class, SerializedObject serializedObject)
{ {
void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject); void* serializedObjectPtr = Internal.UnsafeCastToPtr(serializedObject);
void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer); void* serializerPtr = Internal.UnsafeCastToPtr(serializedObject.Serializer);
MonoType* type = Mono.mono_class_get_type(@class.[Friend]_monoClass); _deserializeStaticMethod(@class.FullName.CStr(), serializedObjectPtr, serializerPtr);
MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, type);
MonoException* exception = null;
_deserializeStaticMethod(reflectionType, serializedObjectPtr, serializerPtr, &exception);
if (exception != null)
ScriptEngine.[Friend]HandleMonoException(exception, null);
} }
} }
@@ -72,13 +72,13 @@ class NewScriptInstance : RefCounter
public void InvokeOnCreate() public void InvokeOnCreate()
{ {
if (_scriptClass.Methods.HasFlag(.OnCreate)) if (_scriptClass.Methods.HasFlag(.OnCreate))
CoreClrHelper._entityScriptFunctions.OnCreate(); CoreClrHelper._entityScriptFunctions.OnCreate(_entityId);
} }
public void InvokeOnUpdate(float deltaTime) public void InvokeOnUpdate(float deltaTime)
{ {
if (_scriptClass.Methods.HasFlag(.OnUpdate)) if (_scriptClass.Methods.HasFlag(.OnUpdate))
CoreClrHelper._entityScriptFunctions.OnUpdate(deltaTime); CoreClrHelper._entityScriptFunctions.OnUpdate(_entityId, deltaTime);
} }
public void Destroy() public void Destroy()
@@ -86,10 +86,11 @@ class NewScriptInstance : RefCounter
if (!IsInitialized) if (!IsInitialized)
return; return;
if (_scriptClass.Methods.HasFlag(.OnDestroy) && (ScriptEngine.ApplicationInfo.IsInPlayMode || ScriptClass.RunInEditMode)) /*if (_scriptClass.Methods.HasFlag(.OnDestroy) && (ScriptEngine.ApplicationInfo.IsInPlayMode || ScriptClass.RunInEditMode))
{ {
CoreClrHelper._entityScriptFunctions.OnDestroy(); CoreClrHelper._entityScriptFunctions.OnDestroy();
} }*/
CoreClrHelper._entityScriptFunctions.OnDestroy(_entityId, (ScriptEngine.ApplicationInfo.IsInPlayMode || ScriptClass.RunInEditMode));
IsInitialized = false; IsInitialized = false;
-245
View File
@@ -1,245 +0,0 @@
using Mono;
using System;
using GlitchyEngine.Core;
using System.Collections;
using GlitchyEngine.Scripting.Classes;
namespace GlitchyEngine.Scripting;
using internal GlitchyEngine.Scripting;
class SharpClass : RefCounter
{
protected String _fullName ~ delete _; // TODO APPEND
protected StringView _namespace;
protected StringView _className;
protected internal MonoClass* _monoClass;
public StringView Namespace => _namespace;
public StringView ClassName => _className;
public StringView FullName => _fullName;
[AllowAppend]
public this(StringView classNamespace, StringView className, MonoImage* image)
{
// TODO APPEND
String fullName = new String(classNamespace.Length + 1 + className.Length);
//append $"{classNamespace}.{className}";
fullName.AppendF($"{classNamespace}.{className}");
_fullName = fullName;
_namespace = _fullName.Substring(0, classNamespace.Length);
_className = _fullName.Substring(classNamespace.Length + 1);
_monoClass = Mono.mono_class_from_name(image, _namespace.ToScopeCStr!(), _className.ToScopeCStr!());
Log.EngineLogger.AssertDebug(_monoClass != null);
}
}
class ScriptClass : SharpClass
{
typealias OnCreateMethod = function MonoObject*(MonoObject* instance, MonoException** exception);
typealias OnUpdateMethod = function MonoObject*(MonoObject* instance, float deltaTime, MonoException** exception);
typealias OnDestroyMethod = function MonoObject*(MonoObject* instance, MonoException** exception);
private bool _runInEditMode;
private MonoMethod* _constructor;
private OnCreateMethod _onCreate;
private OnUpdateMethod _onUpdate;
private OnDestroyMethod _onDestroy;
private function [CallingConvention(.Cdecl)] MonoObject*(MonoObject* instance, MonoObject* collision2d, MonoException** exception) _onCollisionEnter2D;
private function [CallingConvention(.Cdecl)] MonoObject*(MonoObject* instance, MonoObject* collision2d, MonoException** exception) _onCollisionLeave2D;
public bool HasCollisionEnter2D => _onCollisionEnter2D != null;
public bool HasCollisionLeave2D => _onCollisionLeave2D != null;
public bool RunInEditMode => _runInEditMode;
[AllowAppend]
public this(StringView classNamespace, StringView className, MonoImage* image) :
base(classNamespace, className, image)
{
_constructor = FindConstructor();
_onCreate = (OnCreateMethod)GetMethodThunk("OnCreate");
_onUpdate = (OnUpdateMethod)GetMethodThunk("OnUpdate", 1);
_onDestroy = (OnDestroyMethod)GetMethodThunk("OnDestroy");
_onCollisionEnter2D = (.)GetMethodThunk("OnCollisionEnter2D", 1);
_onCollisionLeave2D = (.)GetMethodThunk("OnCollisionLeave2D", 1);
DetermineRunInEditMode();
}
/// Determines whether or not scripts of this class will be executed in edit mode.
private void DetermineRunInEditMode()
{
// TODO: This is only relevant for the editor!
MonoCustomAttrInfo* attributes = Mono.mono_custom_attrs_from_class(_monoClass);
//if (attributes != null && ScriptEngine.Classes.RunInEditModeAttribute != null)
// _runInEditMode = Mono.mono_custom_attrs_has_attr(attributes, ScriptEngine.Classes.RunInEditModeAttribute._monoClass);
}
private MonoMethod* FindConstructor()
{
MonoMethod* constructor = null;
MonoMethodDesc* constructorDesc = Mono.mono_method_desc_new(":.ctor(GlitchyEngine.Core.UUID)", true);
// Entities usually don't have a constructor that takes the UUID, so we have to look for it in the parents.
for (MonoClass* @class = _monoClass; @class != null; @class = Mono.mono_class_get_parent(@class))
{
constructor = Mono.mono_method_desc_search_in_class(constructorDesc, @class);
if (constructor != null)
break;
}
Mono.mono_method_desc_free(constructorDesc);
return constructor;
}
private void CallConstructorChain(MonoObject* instance, UUID uuid, out MonoException* exception)
{
exception = null;
if (_constructor == null)
return;
#unwarn
void*[1] args = void*[](&uuid);
Mono.mono_runtime_invoke(_constructor, instance, &args, (.)&exception);
}
public void OnCreate(MonoObject* instance, out MonoException* exception)
{
exception = null;
if (_onCreate != null)
_onCreate(instance, &exception);
}
public void OnUpdate(MonoObject* instance, float deltaTime, out MonoException* exception)
{
exception = null;
if (_onUpdate != null)
_onUpdate(instance, deltaTime, &exception);
}
public void OnDestroy(MonoObject* instance, out MonoException* exception)
{
exception = null;
if (_onDestroy != null)
_onDestroy(instance, &exception);
}
public void OnCollisionEnter2D(MonoObject* instance, Collision2D collision, out MonoException* exception)
{
exception = null;
if (_onCollisionEnter2D != null)
{
//MonoObject* monoObject = ScriptEngine.Classes.Collision2D.BoxValue(collision);
//_onCollisionEnter2D(instance, monoObject, &exception);
}
}
public void OnCollisionLeave2D(MonoObject* instance, Collision2D collision, out MonoException* exception)
{
exception = null;
if (_onCollisionEnter2D != null)
{
//MonoObject* monoObject = ScriptEngine.Classes.Collision2D.BoxValue(collision);
//_onCollisionLeave2D(instance, monoObject, &exception);
}
}
public MonoObject* CreateInstance(UUID uuid, out MonoException* exception)
{
MonoObject* instance = Mono.mono_object_new(ScriptEngine.[Friend]s_AppDomain, _monoClass);
// Invoke empty constructor to initialize fields with default values specified in the script itself
Mono.mono_runtime_object_init(instance);
// Invoke UUID Constructors:
CallConstructorChain(instance, uuid, out exception);
// Invoke constructor with UUID
//#unwarn
//ScriptEngine.[Friend]s_EngineObject.Invoke(ScriptEngine.[Friend]s_EngineObject._constructor, instance, out exception, &uuid);
return instance;
}
public MonoObject* CreateInstance()
{
MonoObject* instance = Mono.mono_object_new(ScriptEngine.[Friend]s_AppDomain, _monoClass);
// Invoke empty constructor to fill fields
Mono.mono_runtime_object_init(instance);
return instance;
}
public MonoMethod* GetMethod(StringView name, int argCount = 0)
{
return Mono.mono_class_get_method_from_name(_monoClass, name.ToScopeCStr!(), argCount);
}
public void* GetMethodThunk(StringView name, int argCount = 0)
{
MonoMethod* method = GetMethod(name, argCount);
if (method == null)
return null;
return Mono.mono_method_get_unmanaged_thunk(method);
}
public MonoObject* Invoke(MonoMethod* method, MonoObject* instance, void** args = null)
{
MonoObject* exception = null;
MonoObject* result = Mono.mono_runtime_invoke(method, instance, args, &exception);
if (exception != null)
ScriptEngine.HandleMonoException((MonoException*)exception);
return result;
}
public MonoObject* Invoke(MonoMethod* method, MonoObject* instance, out MonoException* exception, params void*[] args)
{
exception = null;
MonoObject* result = Mono.mono_runtime_invoke(method, instance, args.Ptr, (.)&exception);
return result;
}
public T Invoke<T>(MonoMethod* method, MonoObject* instance, params void*[] args)
{
MonoObject* object = Invoke(method, instance, args.Ptr);
return *(T*)Mono.mono_object_unbox(object);
}
public MonoObject* BoxValue<T>(in T value)
{
return Mono.mono_value_box(ScriptEngine.[Friend]s_AppDomain, _monoClass, &value);
}
public MonoObject* BoxValue(void* value)
{
return Mono.mono_value_box(ScriptEngine.[Friend]s_AppDomain, _monoClass, value);
}
}
+10 -30
View File
@@ -1,4 +1,3 @@
using Mono;
using System; using System;
using System.IO; using System.IO;
using System.Collections; using System.Collections;
@@ -54,7 +53,7 @@ class EngineClasses
DeleteAndNullify!(s_EntityEditor); DeleteAndNullify!(s_EntityEditor);
ReleaseRefAndNullify!(s_EntitySerializer); DeleteAndNullify!(s_EntitySerializer);
//ReleaseRefAndNullify!(s_SerializationContext); //ReleaseRefAndNullify!(s_SerializationContext);
DeleteAndNullify!(s_Collision2D); DeleteAndNullify!(s_Collision2D);
@@ -73,7 +72,7 @@ class EngineClasses
// Editor classes // Editor classes
s_EntityEditor = new EntityEditorWrapper(); s_EntityEditor = new EntityEditorWrapper();
//s_EntitySerializer = new EntitySerializerWrapper("GlitchyEngine.Serialization", "EntitySerializer"); s_EntitySerializer = new EntitySerializerWrapper();
s_Collision2D = new NewScriptClass("GlitchyEngine.Physics.Collision2D", .Empty, .None); s_Collision2D = new NewScriptClass("GlitchyEngine.Physics.Collision2D", .Empty, .None);
@@ -84,15 +83,6 @@ class EngineClasses
static class ScriptEngine static class ScriptEngine
{ {
private static MonoDomain* s_RootDomain;
private static MonoDomain* s_AppDomain;
private static MonoAssembly* s_CoreAssembly;
private static MonoImage* s_CoreAssemblyImage;
private static MonoAssembly* s_AppAssembly;
private static MonoImage* s_AppAssemblyImage;
private static Scene s_Context ~ _?.ReleaseRef(); private static Scene s_Context ~ _?.ReleaseRef();
private static EngineClasses _classes = new .() ~ delete _; private static EngineClasses _classes = new .() ~ delete _;
@@ -287,6 +277,9 @@ static class ScriptEngine
{ {
Debug.Profiler.ProfileFunction!(); Debug.Profiler.ProfileFunction!();
// TODO: We should probably verify, that all required types actually exist.
Classes.LoadClasses();
ScriptGlue.Init(); ScriptGlue.Init();
// TODO: Check if files exist // TODO: Check if files exist
@@ -415,9 +408,6 @@ static class ScriptEngine
{ {
Debug.Profiler.ProfileFunction!(); Debug.Profiler.ProfileFunction!();
// TODO: We should probably verify, that all required types actually exist.
Classes.LoadClasses();
CoreClrHelper.GetScriptClasses(let data, let entryCount); CoreClrHelper.GetScriptClasses(let data, let entryCount);
Span<ScriptClassInfo> scriptClasses = .((.)data, entryCount); Span<ScriptClassInfo> scriptClasses = .((.)data, entryCount);
@@ -459,8 +449,7 @@ static class ScriptEngine
{ {
Debug.Profiler.ProfileScope!("Initialize Instances"); Debug.Profiler.ProfileScope!("Initialize Instances");
Log.EngineLogger.Error("Recreating and copying instances (ReloadAssemblies) not updated yet."); // We need to create a new instance for every entity
/*// We need to create a new instance for every entity
for (let (id, scriptInstance) in _entityScriptInstances) for (let (id, scriptInstance) in _entityScriptInstances)
{ {
if (Context.GetEntityByID(id) case .Ok(let entity)) if (Context.GetEntityByID(id) case .Ok(let entity))
@@ -472,7 +461,7 @@ static class ScriptEngine
{ {
Log.EngineLogger.AssertDebug(false, "Entities script was just serialized but the entity doesn't exist anymore."); Log.EngineLogger.AssertDebug(false, "Entities script was just serialized but the entity doesn't exist anymore.");
} }
}*/ }
} }
contextSerializer.DeserializeScriptInstances(); contextSerializer.DeserializeScriptInstances();
@@ -491,8 +480,9 @@ static class ScriptEngine
s_RootDomain = null;*/ s_RootDomain = null;*/
} }
// TODO: Do we still need this? It was only called by ScriptGlue
/// Returns the script instance or null. /// Returns the script instance or null.
public static MonoObject* GetManagedInstance(UUID entityId) public static void* GetManagedInstance(UUID entityId)
{ {
//if (_entityScriptInstances.TryGetValue(entityId, let scriptInstance)) //if (_entityScriptInstances.TryGetValue(entityId, let scriptInstance))
// return scriptInstance.MonoInstance; // return scriptInstance.MonoInstance;
@@ -507,11 +497,6 @@ static class ScriptEngine
return scriptClass; return scriptClass;
} }
internal static void HandleException()
{
}
internal static void LogScriptException(ScriptException exception, UUID entityId) internal static void LogScriptException(ScriptException exception, UUID entityId)
{ {
String entityInfo = scope .(); String entityInfo = scope .();
@@ -531,12 +516,7 @@ static class ScriptEngine
Log.ClientLogger.Error($"Mono Exception \"{exception.FullName}\": \"{exception.Message}\"{entityInfo}\nStackTrace:\n{exception.StackTrace}", exception); Log.ClientLogger.Error($"Mono Exception \"{exception.FullName}\": \"{exception.Message}\"{entityInfo}\nStackTrace:\n{exception.StackTrace}", exception);
} }
// TODO: This can go soon? // TODO: Wrap like the other classes
internal static void HandleMonoException(MonoException* exception, ScriptInstance sourceInstance = null)
{
//LogScriptException(exception, sourceInstance?.EntityId ?? .Zero);
}
public static void ShowScriptEditor(Entity entity, ScriptComponent* scriptComponent) public static void ShowScriptEditor(Entity entity, ScriptComponent* scriptComponent)
{ {
if (scriptComponent.Instance == null) if (scriptComponent.Instance == null)
+4 -15
View File
@@ -372,10 +372,6 @@ struct EngineFunctions
static class ScriptGlue static class ScriptGlue
{ {
/*private static Dictionary<MonoType*, function void(Entity entityId)> s_AddComponentMethods = new .() ~ delete _;
private static Dictionary<MonoType*, function bool(Entity entityId)> s_HasComponentMethods = new .() ~ delete _;
private static Dictionary<MonoType*, function void(Entity entityId)> s_RemoveComponentMethods = new .() ~ delete _;*/
/* Adding this attribute to a method will log method entry and returned Result<T> errors */ /* Adding this attribute to a method will log method entry and returned Result<T> errors */
[AttributeUsage(.Method)] [AttributeUsage(.Method)]
struct RegisterMethodAttribute : Attribute, IOnMethodInit struct RegisterMethodAttribute : Attribute, IOnMethodInit
@@ -408,9 +404,6 @@ static class ScriptGlue
public static Event<delegate void()> OnRegisterNativeCalls ~ _.Dispose(); public static Event<delegate void()> OnRegisterNativeCalls ~ _.Dispose();
/*private function void SetEngineFunctions(EngineFunctions* engineFunctions);
private static SetEngineFunctions _setEngineFunctions;*/
private function void SetEngineFunctions(EngineFunctions* engineFunctions); private function void SetEngineFunctions(EngineFunctions* engineFunctions);
private static SetEngineFunctions _setEngineFunctions; private static SetEngineFunctions _setEngineFunctions;
@@ -423,17 +416,13 @@ static class ScriptGlue
RegisterCalls(); RegisterCalls();
//RegisterMathFunctions(); RegisterManagedComponents();
} }
public static void RegisterManagedComponents() public static void RegisterManagedComponents()
{ {
Debug.Profiler.ProfileFunction!(); Debug.Profiler.ProfileFunction!();
/*s_AddComponentMethods.Clear();
s_HasComponentMethods.Clear();
s_RemoveComponentMethods.Clear();*/
RegisterComponent<TransformComponent>(); RegisterComponent<TransformComponent>();
RegisterComponent<Rigidbody2DComponent>(); RegisterComponent<Rigidbody2DComponent>();
RegisterComponent<CameraComponent>(); RegisterComponent<CameraComponent>();
@@ -459,12 +448,10 @@ static class ScriptGlue
private static void RegisterComponent<T>() where T : struct, new private static void RegisterComponent<T>() where T : struct, new
{ {
Log.EngineLogger.Error("ScriptGlue::RegisterComponent not updated yet.");
String fullComponentTypeName = scope String(); String fullComponentTypeName = scope String();
typeof(T).GetFullName(fullComponentTypeName); typeof(T).GetFullName(fullComponentTypeName);
CoreClrHelper.RegisterComponent(fullComponentTypeName, CoreClrHelper.RegisterComponent(fullComponentTypeName..EnsureNullTerminator(),
addComponent: (entityId) => { addComponent: (entityId) => {
Entity entity = GetEntitySafe(entityId); Entity entity = GetEntitySafe(entityId);
entity.AddComponent<T>(); entity.AddComponent<T>();
@@ -1550,6 +1537,8 @@ static class ScriptGlue
Log.EngineLogger.AssertDebug(context != null); Log.EngineLogger.AssertDebug(context != null);
Log.EngineLogger.Trace(StringView(fieldName));
context.AddField(StringView(fieldName), type, valueObject, StringView(fullTypeName)); context.AddField(StringView(fieldName), type, valueObject, StringView(fullTypeName));
} }
@@ -1,136 +0,0 @@
using Mono;
using GlitchyEngine.Core;
using System;
using GlitchyEngine.Scripting.Classes;
namespace GlitchyEngine.Scripting;
using internal GlitchyEngine.Scripting;
class ScriptInstance : RefCounter
{
private ScriptClass _scriptClass;
private MonoObject* _instance;
private uint32 _gcHandle;
private UUID _entityId;
public ScriptClass ScriptClass => _scriptClass;
/// Gets whether or not the instance has ben initialized.
public bool IsInitialized => _instance != null;
/// Gets whether or not the Create-Method of this instance has been called before.
public bool IsCreated => _isCreated;
private bool _isCreated = false;
internal MonoObject* MonoInstance => _instance;
public UUID EntityId => _entityId;
public this(UUID entityId, ScriptClass scriptClass)
{
Log.EngineLogger.AssertDebug(scriptClass != null);
_entityId = entityId;
_scriptClass = scriptClass..AddRef();
}
private ~this()
{
Destroy();
_scriptClass?.ReleaseRef();
}
public void Destroy()
{
if (_instance != null)
{
if (ScriptEngine.ApplicationInfo.IsInPlayMode || ScriptClass.RunInEditMode)
{
InvokeOnDestroy();
}
Mono.mono_gchandle_free(_gcHandle);
_instance = null;
ScriptEngine.UnregisterScriptInstance(_entityId);
}
}
public void Instantiate(UUID uuid)
{
_instance = _scriptClass.CreateInstance(uuid, let exception);
_gcHandle = Mono.mono_gchandle_new(_instance, true);
if (exception != null)
ScriptEngine.HandleMonoException(exception, this);
}
public void InvokeOnCreate()
{
_scriptClass.OnCreate(_instance, let exception);
_isCreated = true;
if (exception != null)
ScriptEngine.HandleMonoException(exception, this);
}
public void InvokeOnUpdate(float deltaTime)
{
_scriptClass.OnUpdate(_instance, deltaTime, let exception);
if (exception != null)
ScriptEngine.HandleMonoException(exception, this);
}
public void InvokeOnDestroy()
{
_scriptClass.OnDestroy(_instance, let exception);
if (exception != null)
ScriptEngine.HandleMonoException(exception, this);
}
public void InvokeOnCollisionEnter2D(Collision2D collision)
{
if (!_scriptClass.HasCollisionEnter2D)
return;
_scriptClass.OnCollisionEnter2D(_instance, collision, let exception);
if (exception != null)
ScriptEngine.HandleMonoException(exception, this);
}
public void InvokeOnCollisionLeave2D(Collision2D collision)
{
if (!_scriptClass.HasCollisionLeave2D)
return;
_scriptClass.OnCollisionLeave2D(_instance, collision, let exception);
if (exception != null)
ScriptEngine.HandleMonoException(exception, this);
}
/// Creates a new instance of the given component class and initializes it for the current entity.
public MonoObject* CreateComponentInstance(ScriptClass componentClassType)
{
MonoObject* componentInstance = componentClassType.CreateInstance();
// TODO: We could cache the property, but this might be fine
MonoProperty* entityProperty = Mono.mono_class_get_property_from_name(componentClassType.[Friend]_monoClass, "Entity");
MonoObject* exception = null;
Mono.mono_property_set_value(entityProperty, componentInstance, (void**)&_instance, &exception);
if (exception != null)
ScriptEngine.HandleMonoException((MonoException*)exception, this);
return componentInstance;
}
}
@@ -23,12 +23,12 @@ public class ScriptInstanceSerializer
public void Clear() public void Clear()
{ {
ClearDictionaryAndDeleteValues!(_serializedData); ClearDictionaryAndDeleteValues!(_serializedData);
//ScriptEngine.Classes.EntitySerializer.DestroySerializationContext(this); ScriptEngine.Classes.EntitySerializer.DestroySerializationContext(this);
} }
public void Init() public void Init()
{ {
//ScriptEngine.Classes.EntitySerializer.CreateSerializationContext(this); ScriptEngine.Classes.EntitySerializer.CreateSerializationContext(this);
} }
/// Serializes all script instances that are currently managed by the ScriptEngine. /// Serializes all script instances that are currently managed by the ScriptEngine.
@@ -36,11 +36,7 @@ public class ScriptInstanceSerializer
{ {
Debug.Profiler.ProfileFunction!(); Debug.Profiler.ProfileFunction!();
Log.EngineLogger.Error("SerializeScriptInstances not implemented."); Init();
return;
/*Init();
for (let (id, scriptInstance) in ScriptEngine._entityScriptInstances) for (let (id, scriptInstance) in ScriptEngine._entityScriptInstances)
{ {
@@ -50,18 +46,18 @@ public class ScriptInstanceSerializer
for (let (name, scriptClass) in ScriptEngine.EntityClasses) for (let (name, scriptClass) in ScriptEngine.EntityClasses)
{ {
SerializeStaticScriptClassFields(scriptClass); SerializeStaticScriptClassFields(scriptClass);
}*/ }
} }
/// Serializes the given script instance. /// Serializes the given script instance.
public void SerializeScriptInstance(ScriptInstance script) public void SerializeScriptInstance(NewScriptInstance script)
{ {
SerializedObject object = new SerializedObject(this, false, 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. /// Serializes the given script instance.
public void SerializeStaticScriptClassFields(ScriptClass scriptClass) public void SerializeStaticScriptClassFields(NewScriptClass scriptClass)
{ {
SerializedObject object = new SerializedObject(this, true, scriptClass.FullName, null); SerializedObject object = new SerializedObject(this, true, scriptClass.FullName, null);
object.SerializeStaticFields(scriptClass); object.SerializeStaticFields(scriptClass);
@@ -72,11 +68,7 @@ public class ScriptInstanceSerializer
{ {
Debug.Profiler.ProfileFunction!(); Debug.Profiler.ProfileFunction!();
Log.EngineLogger.Error("SerializeScriptInstances not implemented."); Init();
return;
/*Init();
for (let (id, script) in ScriptEngine._entityScriptInstances) for (let (id, script) in ScriptEngine._entityScriptInstances)
{ {
@@ -86,12 +78,12 @@ public class ScriptInstanceSerializer
for (let (name, scriptClass) in ScriptEngine.EntityClasses) for (let (name, scriptClass) in ScriptEngine.EntityClasses)
{ {
DeserializeStaticScriptClassFields(scriptClass); 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.
/// @returns true if the script had serialized data; false otherwise. /// @returns true if the script had serialized data; false otherwise.
public bool DeserializeScriptInstance(UUID id, ScriptInstance script) public bool DeserializeScriptInstance(UUID id, NewScriptInstance script)
{ {
if (_serializedData.TryGetValue(id, let object)) if (_serializedData.TryGetValue(id, let object))
{ {
@@ -103,7 +95,7 @@ public class ScriptInstanceSerializer
return false; return false;
} }
public bool DeserializeStaticScriptClassFields(ScriptClass scriptClass) public bool DeserializeStaticScriptClassFields(NewScriptClass scriptClass)
{ {
for (let object in _serializedData.Values) for (let object in _serializedData.Values)
{ {
@@ -192,22 +192,22 @@ class SerializedObject
} }
} }
public void Serialize(ScriptInstance scriptInstance) public void Serialize(NewScriptInstance scriptInstance)
{ {
ScriptEngine.Classes.EntitySerializer.Serialize(scriptInstance, this); ScriptEngine.Classes.EntitySerializer.Serialize(scriptInstance, this);
} }
public void Deserialize(ScriptInstance scriptInstance) public void Deserialize(NewScriptInstance scriptInstance)
{ {
ScriptEngine.Classes.EntitySerializer.Deserialize(scriptInstance, this); ScriptEngine.Classes.EntitySerializer.Deserialize(scriptInstance, this);
} }
public void SerializeStaticFields(ScriptClass scriptClass) public void SerializeStaticFields(NewScriptClass scriptClass)
{ {
ScriptEngine.Classes.EntitySerializer.SerializeStatic(scriptClass, this); ScriptEngine.Classes.EntitySerializer.SerializeStatic(scriptClass, this);
} }
public void DeserializeStaticFields(ScriptClass scriptClass) public void DeserializeStaticFields(NewScriptClass scriptClass)
{ {
ScriptEngine.Classes.EntitySerializer.DeserializeStatic(scriptClass, this); ScriptEngine.Classes.EntitySerializer.DeserializeStatic(scriptClass, this);
} }
+1 -1
View File
@@ -956,7 +956,7 @@ namespace GlitchyEngine.World
Dictionary<EcsEntity, EcsEntity> sourceToTargetEntity = scope .(); Dictionary<EcsEntity, EcsEntity> sourceToTargetEntity = scope .();
Dictionary<UUID, UUID> sourceIdToTargetId = scope .(); Dictionary<UUID, UUID> sourceIdToTargetId = scope .();
Dictionary<UUID, Entity> targetIdToSourceEntity = scope .(); Dictionary<UUID, Entity> targetIdToSourceEntity = scope .();
List<(UUID oldId, ScriptInstance scriptInstance)> newScripts = scope .(); List<(UUID oldId, NewScriptInstance scriptInstance)> newScripts = scope .();
Entity CopyEntityAndChildren(Entity original, Entity? copyParent) Entity CopyEntityAndChildren(Entity original, Entity? copyParent)
{ {
+1
View File
@@ -25,6 +25,7 @@ public enum ProjectionType : byte
/// <summary> /// <summary>
/// A component representing a camera that is attached to the entity. /// A component representing a camera that is attached to the entity.
/// </summary> /// </summary>
[EngineClass("GlitchyEngine.World.CameraComponent")]
public class Camera : Component public class Camera : Component
{ {
/// <summary> /// <summary>
+1
View File
@@ -8,6 +8,7 @@ namespace GlitchyEngine.Core;
/// <br/><br/> /// <br/><br/>
/// Every entity has a transform component. /// Every entity has a transform component.
/// </summary> /// </summary>
[EngineClass("GlitchyEngine.World.TransformComponent")]
public class Transform : Component public class Transform : Component
{ {
public Entity? Parent public Entity? Parent
+1
View File
@@ -6,6 +6,7 @@ namespace GlitchyEngine.Graphics;
/// <summary> /// <summary>
/// Component that renders a circle. /// Component that renders a circle.
/// </summary> /// </summary>
[EngineClass("GlitchyEngine.World.CircleRendererComponent")]
public class CircleRenderer : Component public class CircleRenderer : Component
{ {
// TODO: Texture2D Sprite // TODO: Texture2D Sprite
+1
View File
@@ -6,6 +6,7 @@ namespace GlitchyEngine.Graphics;
/// Holds a reference to a Mesh. /// Holds a reference to a Mesh.
/// Can be used in combination with a <see cref="MeshRenderer"/> on the same <see cref="Entity"/> to render the mesh. /// Can be used in combination with a <see cref="MeshRenderer"/> on the same <see cref="Entity"/> to render the mesh.
/// </summary> /// </summary>
[EngineClass("GlitchyEngine.Renderer.MeshComponent")]
public class Mesh : Component public class Mesh : Component
{ {
+1
View File
@@ -5,6 +5,7 @@ namespace GlitchyEngine.Graphics;
/// <summary> /// <summary>
/// Renders a Mesh. The Mesh can be specified by adding a <see cref="Mesh"/> component to the same <see cref="Entity"/>. /// Renders a Mesh. The Mesh can be specified by adding a <see cref="Mesh"/> component to the same <see cref="Entity"/>.
/// </summary> /// </summary>
[EngineClass("GlitchyEngine.World.MeshRendererComponent")]
public class MeshRenderer : Component public class MeshRenderer : Component
{ {
/// <summary> /// <summary>
+1
View File
@@ -6,6 +6,7 @@ namespace GlitchyEngine.Graphics;
/// <summary> /// <summary>
/// Component that renders a sprite. /// Component that renders a sprite.
/// </summary> /// </summary>
[EngineClass("GlitchyEngine.World.SpriteRendererComponent")]
public class SpriteRenderer : Component public class SpriteRenderer : Component
{ {
// TODO: Texture2D/Sprite // TODO: Texture2D/Sprite
+1
View File
@@ -7,6 +7,7 @@ namespace GlitchyEngine.Graphics.Text;
/// <summary> /// <summary>
/// Renders text. /// Renders text.
/// </summary> /// </summary>
[EngineClass("GlitchyEngine.World.Components.TextRendererComponent")]
public class TextRenderer : Component public class TextRenderer : Component
{ {
/// <summary> /// <summary>
+1
View File
@@ -6,6 +6,7 @@ namespace GlitchyEngine.Physics;
/// <summary> /// <summary>
/// Rigid body component for 2D physics. /// Rigid body component for 2D physics.
/// </summary> /// </summary>
[EngineClass("GlitchyEngine.World.Rigidbody2DComponent")]
public class Rigidbody2D : Component public class Rigidbody2D : Component
{ {
/// <summary> /// <summary>
+114 -462
View File
@@ -1,25 +1,15 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using GlitchyEngine.Core; using GlitchyEngine.Core;
using GlitchyEngine.Editor; using GlitchyEngine.Editor;
using GlitchyEngine.Extensions; using GlitchyEngine.Extensions;
using GlitchyEngine.Graphics;
using GlitchyEngine.Graphics.Text;
using GlitchyEngine.Math;
using GlitchyEngine.Physics;
using GlitchyEngine.Serialization; using GlitchyEngine.Serialization;
using ImGuiNET; using ImGuiNET;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
namespace GlitchyEngine; namespace GlitchyEngine;
@@ -262,39 +252,62 @@ internal static unsafe partial class ScriptGlue
} }
catch (Exception e) catch (Exception e)
{ {
Console.WriteLine(e); Log.Exception(e);
// TODO: Log exceptions to console
} }
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
public static void InvokeEntityOnUpdate(UUID entityId, float deltaTime) public static void InvokeEntityOnUpdate(UUID entityId, float deltaTime)
{ {
// using var _ = AssemblyLoadContext.EnterContextualReflection(_appAssembly); // TODO: Check if reflection works correctly in entities try
{
(Entity entity, Type type) = EntityScriptInstances[entityId]; (Entity entity, Type type) = EntityScriptInstances[entityId];
entity.OnUpdate(deltaTime); entity.OnUpdate(deltaTime);
} }
catch (Exception e)
{
Log.Exception(e);
}
}
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
public static void InvokeEntityOnDestroy(UUID entityId, float deltaTime) public static void InvokeEntityOnDestroy(UUID entityId, byte callDestroy)
{ {
(Entity entity, Type type) = EntityScriptInstances[entityId]; try
entity.OnDestroy(); {
if (EntityScriptInstances.Remove(entityId, out var match) && callDestroy > 0)
{
match.Entity.OnDestroy();
}
}
catch (Exception e)
{
Log.Exception(e);
}
}
internal static Type? GetTypeFromNativeString(byte* fullTypeName)
{
if (fullTypeName == null)
return null;
using var _ = AssemblyLoadContext.EnterContextualReflection(_appAssembly);
Debug.Assert(_appAssembly != null);
string? typeName = Marshal.PtrToStringUTF8((IntPtr)fullTypeName);
Debug.Assert(typeName != null);
return _appAssembly.GetType(typeName);
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
public static void CreateScriptInstance(UUID entityId, byte* scriptClassName) public static void CreateScriptInstance(UUID entityId, byte* scriptClassName)
{ {
using var _ = AssemblyLoadContext.EnterContextualReflection(_appAssembly); Log.Info("Exception");
Debug.Assert(_appAssembly != null); Type? scriptType = GetTypeFromNativeString(scriptClassName);
string? typeName = Marshal.PtrToStringUTF8((IntPtr)scriptClassName);
Debug.Assert(typeName != null);
Type? scriptType = _appAssembly.GetType(typeName);
Debug.Assert(scriptType != null, "Script class Type not found."); Debug.Assert(scriptType != null, "Script class Type not found.");
@@ -337,11 +350,71 @@ internal static unsafe partial class ScriptGlue
RemoveComponent = removeComponent RemoveComponent = removeComponent
}; };
break; return;
}
} }
#endregion Log.Error($"Failed to register component type \"{beefComponentTypeName}\": No matching component class found.");
}
[UnmanagedCallersOnly]
internal static void ThrowException(IntPtr message)
{
throw new Exception(Marshal.PtrToStringUTF8(message));
}
#region EntitySerializer
[UnmanagedCallersOnly]
public static void CreateSerializationContext(IntPtr engineSerializer)
{
EntitySerializer.CreateSerializationContext(engineSerializer);
}
[UnmanagedCallersOnly]
public static void DestroySerializationContext(IntPtr engineSerializer)
{
EntitySerializer.DestroySerializationContext(engineSerializer);
}
[UnmanagedCallersOnly]
public static void EntitySerializer_Serialize(UUID entityId, IntPtr engineObject, IntPtr engineSerializer)
{
if (!EntityScriptInstances.TryGetValue(entityId, out var match))
return;
EntitySerializer.Serialize(match.Entity, engineObject, engineSerializer);
}
[UnmanagedCallersOnly]
public static void EntitySerializer_Deserialize(UUID entityId, IntPtr engineObject, IntPtr engineSerializer)
{
if (!EntityScriptInstances.TryGetValue(entityId, out var match))
return;
EntitySerializer.Deserialize(match.Entity, engineObject, engineSerializer);
}
[UnmanagedCallersOnly]
public static void EntitySerializer_SerializeStaticFields(byte* fullTypeName, IntPtr engineObject, IntPtr engineSerializer)
{
Type? type = GetTypeFromNativeString(fullTypeName);
Debug.Assert(type != null);
EntitySerializer.SerializeStaticFields(type, engineObject, engineSerializer);
}
[UnmanagedCallersOnly]
public static void EntitySerializer_DeserializeStaticFields(byte* fullTypeName, IntPtr engineObject, IntPtr engineSerializer)
{
Type? type = GetTypeFromNativeString(fullTypeName);
Debug.Assert(type != null);
EntitySerializer.DeserializeStaticFields(type, engineObject, engineSerializer);
}
#endregion EntitySerializer
#endregion
public static void Entity_AddComponent(UUID entityId, Type componentType) public static void Entity_AddComponent(UUID entityId, Type componentType)
{ {
@@ -386,7 +459,12 @@ internal static unsafe partial class ScriptGlue
break; break;
default: default:
if (valueObject is not null) if (valueObject is not null)
valueObjectConverted = Unsafe.AsPointer(ref Unsafe.Unbox<byte>(valueObject)); {
void* p = &valueObject;
// Skip Object Header (IntPtr) + Method Table (IntPtr)
valueObjectConverted = (byte*)*(IntPtr*)p + sizeof(IntPtr);
float i = *(float*)valueObjectConverted;
}
break; break;
} }
@@ -398,430 +476,4 @@ internal static unsafe partial class ScriptGlue
if (deleteValueObject) if (deleteValueObject)
Marshal.FreeCoTaskMem((IntPtr)valueObjectConverted); Marshal.FreeCoTaskMem((IntPtr)valueObjectConverted);
} }
//#region Log
// //public unsafe static void Log_LogMessage(GlitchyEngine.Log.LogLevel logLevel, string messagePtr, string fileNamePtr, int lineNumber)
// //{
// // fixed (char* messagePtrConverted = messagePtr) {
// // fixed (char* fileNamePtrConverted = fileNamePtr) {
// // _engineFunctions.Log_LogMessage(logLevel, messagePtrConverted, fileNamePtrConverted, lineNumber);
// // }
// // }
// //
// //
// //}
// //internal static unsafe void Log_LogMessage(Log.LogLevel logLevel, string message, string filePath, int line)
// //{
// // // unsafe
// // // {
// // // byte* mess = (byte*)Marshal.StringToCoTaskMemUTF8(message);
// // //
// // // fixed (char* messagePtr = message)
// // // fixed (char* filePathPtr = filePath)
// // // {
// // // _engineFunctions.Log_LogMessage(logLevel, messagePtr, filePathPtr, line);
// // // }
// // //
// // // Marshal.FreeCoTaskMem((IntPtr)mess);
// // // }
// //}
// [MethodImpl(MethodImplOptions.InternalCall)]
// public static extern void Log_LogException(Exception exception);
//#endregion
//#region Entity
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_Create(object scriptInstance, string? entityName, Type[]? componentTypes, out UUID entityId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_Destroy(UUID entityId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_CreateInstance(UUID entityId, out UUID newEntityId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_AddComponent(UUID entityId, Type componentType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_AddComponents(UUID entityId, Type[] componentTypes);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Entity_HasComponent(UUID entityId, Type componentType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_RemoveComponent(UUID entityId, Type componentType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_FindEntityWithName(string name, out UUID uuid);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_GetScriptInstance(UUID entityId, out object? instance);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern object Entity_SetScript(UUID entityId, Type scriptType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Entity_RemoveScript(UUID entityId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// public static extern string Entity_GetName(UUID entityId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// public static extern string Entity_SetName(UUID entityId, string name);
// [MethodImpl(MethodImplOptions.InternalCall)]
// public static extern void Entity_GetEditorFlags(UUID uuid, out EditorFlags flags);
// [MethodImpl(MethodImplOptions.InternalCall)]
// public static extern void Entity_SetEditorFlags(UUID uuid, EditorFlags editorFlags);
//#endregion Entity
//#region TransformComponent
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_GetParent(UUID entityId, out UUID parentId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_SetParent(UUID entityId, in UUID parentId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_GetTranslation(UUID entityId, out float3 translation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_SetTranslation(UUID entityId, in float3 translation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_GetWorldTranslation(UUID entityId, out float3 translation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_SetWorldTranslation(UUID entityId, in float3 translation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_GetRotation(UUID entityId, out Quaternion rotation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_SetRotation(UUID entityId, in Quaternion rotation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_GetRotationEuler(UUID entityId, out float3 rotationEuler);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_SetRotationEuler(UUID entityId, in float3 rotationEuler);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_GetRotationAxisAngle(UUID entityId, out RotationAxisAngle translation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_SetRotationAxisAngle(UUID entityId, RotationAxisAngle translation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_GetScale(UUID entityId, out float3 scale);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Transform_SetScale(UUID entityId, in float3 scale);
//#endregion TransformComponent
//#region RigidBody2D
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_ApplyForce(UUID entityId, in float2 force, float2 point, bool wakeUp);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_ApplyForceToCenter(UUID entityId, in float2 force, bool wakeUp);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_SetPosition(UUID entityId, in float2 position);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_GetPosition(UUID entityId, out float2 position);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_SetRotation(UUID entityId, in float rotation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_GetRotation(UUID entityId, out float rotation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_SetLinearVelocity(UUID entityId, in float2 velocity);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_GetLinearVelocity(UUID entityId, out float2 velocity);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_SetAngularVelocity(UUID entityId, in float velocity);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_GetAngularVelocity(UUID entityId, out float velocity);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_GetBodyType(UUID entityId, out BodyType bodyType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_SetBodyType(UUID entityId, in BodyType bodyType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_IsFixedRotation(UUID entityId, out bool isFixedRotation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_SetFixedRotation(UUID entityId, in bool isFixedRotation);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_GetGravityScale(UUID entityId, out float gravityScale);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Rigidbody2D_SetGravityScale(UUID entityId, in float gravityScale);
//#endregion RigidBody2D
//#region Camera
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetProjectionType(UUID entityId, out ProjectionType projectionType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetProjectionType(UUID entityId, in ProjectionType projectionType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetPerspectiveFovY(UUID entityId, out float fovY);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetPerspectiveFovY(UUID entityId, float fovY);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetPerspectiveNearPlane(UUID entityId, out float nearPlane);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetPerspectiveNearPlane(UUID entityId, float nearPlane);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetPerspectiveFarPlane(UUID entityId, out float farPlane);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetPerspectiveFarPlane(UUID entityId, float farPlane);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetOrthographicHeight(UUID entityId, out float height);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetOrthographicHeight(UUID entityId, float height);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetOrthographicNearPlane(UUID entityId, out float nearPlane);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetOrthographicNearPlane(UUID entityId, float nearPlane);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetOrthographicFarPlane(UUID entityId, out float farPlane);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetOrthographicFarPlane(UUID entityId, float farPlane);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetAspectRatio(UUID entityId, out float aspectRatio);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetAspectRatio(UUID entityId, float aspectRatio);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_GetFixedAspectRatio(UUID entityId, out bool fixedAspectRatio);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Camera_SetFixedAspectRatio(UUID entityId, bool fixedAspectRatio);
//#endregion
//#region Physics2D
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Physics2D_GetGravity(out float2 gravity);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Physics2D_SetGravity(in float2 gravity);
//#endregion Physics2D
//#region CircleRenderer
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void CircleRenderer_GetColor(UUID entityId, out ColorRGBA color);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void CircleRenderer_SetColor(UUID entityId, ColorRGBA color);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void CircleRenderer_GetUvTransform(UUID entityId, out float4 uvTransform);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void CircleRenderer_SetUvTransform(UUID entityId, float4 uvTransform);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void CircleRenderer_GetInnerRadius(UUID entityId, out float innerRadius);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void CircleRenderer_SetInnerRadius(UUID entityId, float innerRadius);
//#endregion
//#region SpriteRenderer
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void SpriteRenderer_GetColor(UUID entityId, out ColorRGBA color);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void SpriteRenderer_SetColor(UUID entityId, ColorRGBA color);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void SpriteRenderer_GetUvTransform(UUID entityId, out UVTransform uvTransform);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void SpriteRenderer_SetUvTransform(UUID entityId, UVTransform uvTransform);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void SpriteRenderer_GetMaterial(UUID entityId, out UUID materialId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void SpriteRenderer_SetMaterial(UUID entityId, UUID materialId);
//#endregion
//#region TextRenderer
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool TextRenderer_GetIsRichText(UUID entityId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_SetIsRichText(UUID entityId, bool isRichText);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_GetText(UUID entityId, out string text);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_SetText(UUID entityId, string text);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_GetColor(UUID entityId, out ColorRGBA color);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_SetColor(UUID entityId, ColorRGBA color);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_GetHorizontalAlignment(UUID entityId, out HorizontalTextAlignment horizontalAlignment);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_SetHorizontalAlignment(UUID entityId, HorizontalTextAlignment horizontalAlignment);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_GetFontSize(UUID uuid, out float fontSize);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void TextRenderer_SetFontSize(UUID uuid, float fontSize);
//#endregion
//#region MeshRenderer
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void MeshRenderer_GetMaterial(UUID entityId, out UUID materialId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void MeshRenderer_SetMaterial(UUID entityId, UUID materialId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void MeshRenderer_GetSharedMaterial(UUID entityId, out UUID materialId);
//#endregion
//#region Math
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern float modf_float(float x, out float integerPart);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern float2 modf_float2(float2 x, out float2 integerPart);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern float3 modf_float3(float3 x, out float3 integerPart);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern float4 modf_float4(float4 x, out float4 integerPart);
//#endregion
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void UUID_CreateNew(out UUID uuid);
//#region Application
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Application_IsEditor();
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Application_IsPlayer();
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Application_IsInEditMode();
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Application_IsInPlayMode();
//#endregion
//#region Serialization
// [MethodImpl(MethodImplOptions.InternalCall)]
// 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, bool isStatic, string fullTypeName, out IntPtr context, out UUID id);
// [MethodImpl(MethodImplOptions.InternalCall)]
// public static extern unsafe void Serialization_DeserializeField(IntPtr internalContext, SerializationType expectedType, string fieldName, byte* value, out SerializationType actualType);
// [MethodImpl(MethodImplOptions.InternalCall)]
// public static extern void Serialization_GetObject(IntPtr internalContext, UUID id, out IntPtr objectContext);
// [MethodImpl(MethodImplOptions.InternalCall)]
// public static extern void Serialization_GetObjectTypeName(IntPtr internalContext, out string fullTypeName);
//#endregion
//#region Asset
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Asset_GetIdentifier(UUID assetId, out string text);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void Asset_SetIdentifier(UUID assetId, string text);
//#endregion
//#region Material
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern unsafe bool Material_SetVariable(UUID assetId, string variableName, Material.ShaderVariableType elementType, int rows, int columns, int arrayLength, void* rawData, int dataLength);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Material_ResetVariable(UUID assetId, string variableName);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Material_SetTexture(UUID materialId, string textureName, UUID textureId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Material_GetTexture(UUID materialId, string textureName, out UUID textureId);
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool Material_ResetTexture(UUID materialId, string textureName);
//#endregion
//#region ImGui
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern void ImGuiExtension_ListElementGrabber();
// [MethodImpl(MethodImplOptions.InternalCall)]
// internal static extern bool ImGuiExtension_ShowAssetDropTarget(ref UUID assetId);
//#endregion
} }
@@ -562,9 +562,9 @@ public class DeserializationObject
if (id == UUID.Zero) if (id == UUID.Zero)
return null; return null;
string fullTypeName = Encoding.UTF8.GetString(data.FullTypeName, (int)data.FullTypeNameLength); string? fullTypeName = data.FullTypeName != null ? Encoding.UTF8.GetString(data.FullTypeName, (int)data.FullTypeNameLength) : null;
Type? type = GetTypeFromName(fullTypeName); Type? type = fullTypeName is not null ? GetTypeFromName(fullTypeName) : null;
if (type == null) if (type == null)
return NoValueDeserialized; return NoValueDeserialized;
+4 -3
View File
@@ -1,9 +1,10 @@
using GlitchyEngine.Editor; using GlitchyEngine.Core;
using GlitchyEngine.Editor;
using GlitchyEngine.Extensions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using GlitchyEngine.Core; using System.Runtime.InteropServices;
using GlitchyEngine.Extensions;
namespace GlitchyEngine.Serialization; namespace GlitchyEngine.Serialization;