diff --git a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf index 91f2cf2..82e79d9 100644 --- a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf +++ b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf @@ -21,9 +21,11 @@ namespace GlitchyEditor.EditWindows public static this() { - ScriptGlue.OnRegisterNativeCalls.Add(new () => { - ScriptGlue.RegisterCall("ScriptGlue::ImGuiExtension_ShowAssetDropTarget", => ShowAssetDropTarget); - }); + /*ScriptGlue.OnRegisterNativeCalls.Add(new () => { + // TODO: Implement + Runtime.NotImplemented(); + //ScriptGlue.RegisterCall("ScriptGlue::ImGuiExtension_ShowAssetDropTarget", => ShowAssetDropTarget); + });*/ } public static void ShowComponents(Entity entity, Type componentType = null) diff --git a/GlitchyEditor/src/EditWindows/LogWindow.bf b/GlitchyEditor/src/EditWindows/LogWindow.bf index f42dc95..3300a32 100644 --- a/GlitchyEditor/src/EditWindows/LogWindow.bf +++ b/GlitchyEditor/src/EditWindows/LogWindow.bf @@ -45,7 +45,7 @@ class MessageSource /// If true, the message is only meant for engine developers... so only me :( public bool IsEngineMessage = false; - public MonoExceptionHelper Exception = null ~ _?.ReleaseRef(); + public ScriptException Exception = null ~ _?.ReleaseRef(); public String AdditionalData = null ~ delete _; } @@ -370,7 +370,7 @@ class LogWindow : EditorWindow _messages.Add(logMessage); } - public void LogException(DateTime timestamp, MonoExceptionHelper exception) + public void LogException(DateTime timestamp, ScriptException exception) { StringView firstLine = exception.StackTrace; @@ -383,7 +383,7 @@ class LogWindow : EditorWindow message.AppendF($"Exception: \"{exception.FullName}\" | Message: \"{exception.Message}\" {firstLine}\0"); // TODO: are mono exceptions never engine only? - LogMessage logMessage = new LogMessage(timestamp, message, .Error, new MessageSource(){Entity = exception.Instance, Exception = exception..AddRef(), IsEngineMessage = false}); + LogMessage logMessage = new LogMessage(timestamp, message, .Error, new MessageSource(){Entity = exception.EntityId, Exception = exception..AddRef(), IsEngineMessage = false}); _messages.Add(logMessage); } } \ No newline at end of file diff --git a/GlitchyEditor/src/EditorLogger.bf b/GlitchyEditor/src/EditorLogger.bf index db2e89e..07acbcc 100644 --- a/GlitchyEditor/src/EditorLogger.bf +++ b/GlitchyEditor/src/EditorLogger.bf @@ -110,12 +110,12 @@ public class EditorLogger : Logger String message = scope String(4096); - MonoExceptionHelper exceptionHelper = null; + ScriptException exceptionHelper = null; MessageOrigin messageOrigin = null; if (args.Count > 0) { - exceptionHelper = args[^1] as MonoExceptionHelper; + exceptionHelper = args[^1] as ScriptException; messageOrigin = args[^1] as MessageOrigin; } diff --git a/GlitchyEngine/src/Content/Asset.bf b/GlitchyEngine/src/Content/Asset.bf index 8ac6bf2..d025d5e 100644 --- a/GlitchyEngine/src/Content/Asset.bf +++ b/GlitchyEngine/src/Content/Asset.bf @@ -21,7 +21,7 @@ abstract class Asset : RefCounter /// This identifier can be used to request the Asset from the content manager. public StringView Identifier { - get => _identifier; + get => _identifier..EnsureNullTerminator(); set => _identifier.Set(value); } diff --git a/GlitchyEngine/src/Scripting/CoreClrHelper.bf b/GlitchyEngine/src/Scripting/CoreClrHelper.bf index 17ac918..3d1d6cd 100644 --- a/GlitchyEngine/src/Scripting/CoreClrHelper.bf +++ b/GlitchyEngine/src/Scripting/CoreClrHelper.bf @@ -36,6 +36,12 @@ static class CoreClrHelper private function void CreateScriptInstanceFunc(UUID entityId, char8* scriptClassName); static CreateScriptInstanceFunc _createScriptInstance; + private function void ThrowExceptionFunc(char8* message); + static ThrowExceptionFunc _throwException; + + private function void RegisterComponentTypeFunc(StringView fullComponentTypeName, function void(UUID entityId) addComponent, function bool(UUID entityId) hasComponent, function void(UUID entityId) removeComponent); + static RegisterComponentTypeFunc _registerComponentType; + public static ScriptFunctionPointers _entityScriptFunctions; public static void Init(StringView coreAssemblyPath) @@ -106,6 +112,9 @@ static class CoreClrHelper GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "CreateScriptInstance", out _createScriptInstance); + GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "ThrowException", out _throwException); + GetFunctionPointerUnmanagedCallersOnly("GlitchyEngine.ScriptGlue, ScriptCore", "RegisterComponentType", out _registerComponentType); + InitEntityFunctions(); } @@ -182,4 +191,14 @@ static class CoreClrHelper return rc; } + + public static void ThrowException(StringView message) + { + _throwException(message.Ptr); + } + + 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); + } } \ No newline at end of file diff --git a/GlitchyEngine/src/Scripting/MonoExceptionHelper.bf b/GlitchyEngine/src/Scripting/MonoExceptionHelper.bf index 1bcb271..05444fe 100644 --- a/GlitchyEngine/src/Scripting/MonoExceptionHelper.bf +++ b/GlitchyEngine/src/Scripting/MonoExceptionHelper.bf @@ -1,21 +1,21 @@ using System; using GlitchyEngine.Core; -using Mono; namespace GlitchyEngine.Scripting; -public class MonoExceptionHelper : RefCounter +public class ScriptException : RefCounter { - private String _fullName ~ delete _; + private String _fullName ~ delete:append _; - private String _message ~ delete _; + private String _message ~ delete:append _; - private String _stackTrace ~ delete _; + private String _stackTrace ~ delete:append _; /// The clean stack trace only contains the Managed Stack (the full trace contains one line for the native-to-managed entry) private StringView _cleanStackTrace; - private MonoExceptionHelper _innerException ~ _?.ReleaseRef(); + //TODO + //private ScriptException _innerException ~ _?.ReleaseRef(); public StringView FullName => _fullName; public StringView Message => _message; @@ -23,59 +23,22 @@ public class MonoExceptionHelper : RefCounter public StringView StackTrace => _stackTrace; public StringView CleanStackTrace => _cleanStackTrace; - public MonoExceptionHelper InnerException => _innerException; + //public ScriptException InnerException => _innerException; - public UUID Instance { get; set; } + public UUID EntityId { get; set; } - public this(MonoException* exception) + [AllowAppend] + public this(UUID entityId, StringView fullExceptionClassName, StringView message, StringView stackTrace) { - MonoObject* exObject = (MonoObject*)exception; + String allocFullExceptionClassName = append String(fullExceptionClassName); + String allocMessage = append String(fullExceptionClassName); + String allocStackTrace = append String(fullExceptionClassName); - MonoClass* monoClass = Mono.mono_object_get_class(exObject); + _fullName = allocFullExceptionClassName; + _message = allocMessage; + _stackTrace = allocStackTrace; - StringView classNamespace = .(Mono.mono_class_get_namespace(monoClass)); - StringView className = .(Mono.mono_class_get_name(monoClass)); - _fullName = new $"{classNamespace}.{className}"; - - GetMessage(exObject, monoClass); - - GetStackTrace(exception); - - GetInnerException(exObject, monoClass); - } - - private void GetMessage(MonoObject* exceptionObject, MonoClass* monoClass) - { - var messageProperty = Mono.mono_class_get_property_from_name(monoClass, "Message"); - - MonoObject* message = Mono.mono_property_get_value(messageProperty, exceptionObject, null, null); - char8* exMessage = Mono.mono_string_to_utf8((.)message); - - _message = new String(exMessage); - - Mono.mono_free(exMessage); - } - - private void GetStackTrace(MonoException* exception) - { - char8* stacktracePtr = Mono.mono_exception_get_managed_backtrace(exception); - _stackTrace = new String(stacktracePtr); - - int entryIndex = _stackTrace.IndexOf("at (wrapper native-to-managed)"); - - if (entryIndex != -1) - _cleanStackTrace = _stackTrace.Substring(0, entryIndex); - else - _cleanStackTrace = _stackTrace; - } - - private void GetInnerException(MonoObject* exceptionObject, MonoClass* monoClass) - { - MonoProperty* innerExceptionProperty = Mono.mono_class_get_property_from_name(monoClass, "InnerException"); - - MonoObject* innerException = Mono.mono_property_get_value(innerExceptionProperty, exceptionObject, null, null); - - if (innerException != null) - _innerException = new MonoExceptionHelper((MonoException*)innerException); + // TODO + _cleanStackTrace = _stackTrace; } } diff --git a/GlitchyEngine/src/Scripting/ScriptEngine.bf b/GlitchyEngine/src/Scripting/ScriptEngine.bf index 128bdfd..5215cd8 100644 --- a/GlitchyEngine/src/Scripting/ScriptEngine.bf +++ b/GlitchyEngine/src/Scripting/ScriptEngine.bf @@ -507,15 +507,18 @@ static class ScriptEngine return scriptClass; } - internal static void HandleMonoException(MonoException* exception, UUID entityId) + internal static void HandleException() { - MonoExceptionHelper wrappedException = new MonoExceptionHelper(exception); + } + + internal static void LogScriptException(ScriptException exception, UUID entityId) + { String entityInfo = scope .(); if (entityId != .Zero) { - wrappedException.Instance = entityId; + exception.EntityId = entityId; Result sourceEntity = Context.GetEntityByID(entityId); @@ -525,14 +528,13 @@ static class ScriptEngine } } - Log.ClientLogger.Error($"Mono Exception \"{wrappedException.FullName}\": \"{wrappedException.Message}\"{entityInfo}\nStackTrace:\n{wrappedException.StackTrace}", wrappedException); - - wrappedException.ReleaseRef(); + Log.ClientLogger.Error($"Mono Exception \"{exception.FullName}\": \"{exception.Message}\"{entityInfo}\nStackTrace:\n{exception.StackTrace}", exception); } - + + // TODO: This can go soon? internal static void HandleMonoException(MonoException* exception, ScriptInstance sourceInstance = null) { - HandleMonoException(exception, sourceInstance?.EntityId ?? .Zero); + //LogScriptException(exception, sourceInstance?.EntityId ?? .Zero); } public static void ShowScriptEditor(Entity entity, ScriptComponent* scriptComponent) diff --git a/GlitchyEngine/src/Scripting/ScriptGlue.bf b/GlitchyEngine/src/Scripting/ScriptGlue.bf index d14efe0..a0477da 100644 --- a/GlitchyEngine/src/Scripting/ScriptGlue.bf +++ b/GlitchyEngine/src/Scripting/ScriptGlue.bf @@ -1,4 +1,3 @@ -using Mono; using System; using GlitchLog; using System.Reflection; @@ -16,14 +15,16 @@ using GlitchyEngine.Content; using GlitchyEngine.Renderer; using System.Diagnostics; using System.IO; -using static GlitchyEngine.Renderer.Text.FontRenderer; using System.Linq; +using static GlitchyEngine.Renderer.Text.FontRenderer; + namespace GlitchyEngine.Scripting; using internal GlitchyEngine.Scripting; using internal GlitchyEngine.Content; +// TODO: Move to logger? class MessageOrigin { private String _fileName ~ delete:append _; @@ -44,12 +45,6 @@ class MessageOrigin struct RegisterCallAttribute : Attribute { - public String MethodName; - - public this(String methodName) - { - MethodName = methodName; - } } struct TypeTranslationTemplate @@ -377,9 +372,9 @@ struct EngineFunctions static class ScriptGlue { - private static Dictionary s_AddComponentMethods = new .() ~ delete _; + /*private static Dictionary s_AddComponentMethods = new .() ~ delete _; private static Dictionary s_HasComponentMethods = new .() ~ delete _; - private static Dictionary s_RemoveComponentMethods = new .() ~ delete _; + private static Dictionary s_RemoveComponentMethods = new .() ~ delete _;*/ /* Adding this attribute to a method will log method entry and returned Result errors */ [AttributeUsage(.Method)] @@ -435,18 +430,18 @@ static class ScriptGlue { Debug.Profiler.ProfileFunction!(); - s_AddComponentMethods.Clear(); + /*s_AddComponentMethods.Clear(); s_HasComponentMethods.Clear(); - s_RemoveComponentMethods.Clear(); + s_RemoveComponentMethods.Clear();*/ - RegisterComponent("GlitchyEngine.Core.Transform"); - RegisterComponent("GlitchyEngine.Physics.Rigidbody2D"); - RegisterComponent("GlitchyEngine.Core.Camera"); - RegisterComponent("GlitchyEngine.Graphics.SpriteRenderer"); - RegisterComponent("GlitchyEngine.Graphics.CircleRenderer"); - RegisterComponent("GlitchyEngine.Graphics.Text.TextRenderer"); - RegisterComponent("GlitchyEngine.Graphics.Mesh"); - RegisterComponent("GlitchyEngine.Graphics.MeshRenderer"); + RegisterComponent(); + RegisterComponent(); + RegisterComponent(); + RegisterComponent(); + RegisterComponent(); + RegisterComponent(); + RegisterComponent(); + RegisterComponent(); } private static void RegisterCalls() @@ -462,34 +457,26 @@ static class ScriptGlue } - private static void RegisterComponent(StringView cSharpClassName = "") where T : struct, new + private static void RegisterComponent() where T : struct, new { - String className; + Log.EngineLogger.Error("ScriptGlue::RegisterComponent not updated yet."); - if (cSharpClassName.IsWhiteSpace) - { - className = scope:: $"GlitchyEngine."; - typeof(T).GetName(className); - } - else - { - className = scope:: String(cSharpClassName); - } + String fullComponentTypeName = scope String(); + typeof(T).GetFullName(fullComponentTypeName); - className.EnsureNullTerminator(); - - MonoType* managedType = Mono.mono_reflection_type_from_name(className.CStr(), ScriptEngine.[Friend]s_CoreAssemblyImage); - - if (managedType != null) - { - s_AddComponentMethods[managedType] = (entity) => entity.AddComponent(); - s_HasComponentMethods[managedType] = (entity) => entity.HasComponent(); - s_RemoveComponentMethods[managedType] = (entity) => entity.RemoveComponent(); - } - else - { - Log.EngineLogger.AssertDebug(managedType != null, scope $"No C# component with name \"{className}\" found for Beef type \"{typeof(T)}\""); - } + CoreClrHelper.RegisterComponent(fullComponentTypeName, + addComponent: (entityId) => { + Entity entity = GetEntitySafe(entityId); + entity.AddComponent(); + }, + hasComponent: (entityId) => { + Entity entity = GetEntitySafe(entityId); + return entity.HasComponent(); + }, + removeComponent: (entityId) => { + Entity entity = GetEntitySafe(entityId); + entity.RemoveComponent(); + }); } /// Gets the entity with the given id. Throws a mono exception, if the entity doesn't exist. @@ -577,62 +564,35 @@ static class ScriptGlue [NoReturn] static void ThrowArgumentException(char8* argument, char8* message) { - MonoException* exception = Mono.mono_get_exception_argument(argument, message); - Mono.mono_raise_exception(exception); + + //MonoException* exception = Mono.mono_get_exception_argument(argument, message); + //Mono.mono_raise_exception(exception); } /// Throws an InvalidOperationException in the mono runtime. [NoReturn] static void ThrowInvalidOperationException(char8* message) { - MonoException* exception = Mono.mono_get_exception_invalid_operation(message); - Mono.mono_raise_exception(exception); + //MonoException* exception = Mono.mono_get_exception_invalid_operation(message); + //Mono.mono_raise_exception(exception); } /// Throws an NotImplementedException in the mono runtime. [NoReturn] - static void ThrowNotImplementedException(char8* message) + static void ThrowNotImplementedException(StringView message) { - MonoException* exception = Mono.mono_get_exception_invalid_operation(message); - Mono.mono_raise_exception(exception); + //MonoException* exception = Mono.mono_get_exception_invalid_operation(message); + //Mono.mono_raise_exception(exception); + CoreClrHelper.ThrowException(message); } #endregion #region Log - /*[RegisterCall("ScriptGlue::Log_LogMessage")] - static void Log_LogMessage(int32 logLevel, MonoString* message, MonoString* fileName, int lineNumber) - { - char8* utfMessage = Mono.mono_string_to_utf8(message); - - String escapedMessage = scope String(StringView(utfMessage)); - - escapedMessage.Replace("{", "{{"); - escapedMessage.Replace("}", "}}"); - - if (fileName != null) - { - char8* utfFileName = Mono.mono_string_to_utf8(fileName); - - MessageOrigin messageOrigin = new MessageOrigin(StringView(utfFileName), lineNumber); - - - Log.ClientLogger.Log((LogLevel)logLevel, escapedMessage, messageOrigin); - - Mono.mono_free(utfFileName); - } - else - { - Log.ClientLogger.Log((LogLevel)logLevel, escapedMessage); - } - - Mono.mono_free(utfMessage); - }*/ - - [RegisterCall("ScriptGlue::Log_LogMessage")] - [CallingConvention(.Cdecl)] - static void Log_LogMessage(LogLevel logLevel, char16* messagePtr, char16* fileNamePtr, int lineNumber) + [RegisterCall] + //[CallingConvention(.Cdecl)] + static void Log_LogMessage(LogLevel logLevel, char8* messagePtr, char8* fileNamePtr, int lineNumber) { String escapedMessage = new:ScopedAlloc! String(messagePtr); @@ -640,6 +600,11 @@ static class ScriptGlue escapedMessage.Replace("{", "{{"); escapedMessage.Replace("}", "}}"); + if (escapedMessage == "Exception") + { + ThrowNotImplementedException("Test exception"); + } + if (fileNamePtr != null) { String fileName = new:ScopedAlloc! String(fileNamePtr); @@ -654,75 +619,66 @@ static class ScriptGlue } } - [RegisterCall("ScriptGlue::Log_LogException")] - static void Log_LogException(MonoException* exception, UUID entityId) + [RegisterCall] + static void Log_LogException(UUID entityId, char8* fullExceptionClassName, char8* exceptionMessage, char8* stackTrace) { - ScriptEngine.HandleMonoException(exception, entityId); + ScriptException exception = new ScriptException(entityId, StringView(fullExceptionClassName), StringView(exceptionMessage), StringView(stackTrace)); + + ScriptEngine.LogScriptException(exception, entityId); } #endregion #region Input - [RegisterCall("Input::IsKeyPressed")] + [RegisterCall] static bool Input_IsKeyPressed(Key key) => Input.IsKeyPressed(key); - [RegisterCall("Input::IsKeyReleased")] + [RegisterCall] static bool Input_IsKeyReleased(Key key) => Input.IsKeyReleased(key); - [RegisterCall("Input::IsKeyToggled")] + [RegisterCall] static bool Input_IsKeyToggled(Key key) => Input.IsKeyToggled(key); - [RegisterCall("Input::IsKeyPressing")] + [RegisterCall] static bool Input_IsKeyPressing(Key key) => Input.IsKeyPressing(key); - [RegisterCall("Input::IsKeyReleasing")] + [RegisterCall] static bool Input_IsKeyReleasing(Key key) => Input.IsKeyReleasing(key); - [RegisterCall("Input::IsMouseButtonPressed")] + [RegisterCall] static bool Input_IsMouseButtonPressed(MouseButton mouseButton) => Input.IsMouseButtonPressed(mouseButton); - [RegisterCall("Input::IsMouseButtonReleased")] + [RegisterCall] static bool Input_IsMouseButtonReleased(MouseButton mouseButton) => Input.IsMouseButtonReleased(mouseButton); - [RegisterCall("Input::IsMouseButtonPressing")] + [RegisterCall] static bool Input_IsMouseButtonPressing(MouseButton mouseButton) => Input.IsMouseButtonPressing(mouseButton); - [RegisterCall("Input::IsMouseButtonReleasing")] + [RegisterCall] static bool Input_IsMouseButtonReleasing(MouseButton mouseButton) => Input.IsMouseButtonReleasing(mouseButton); #endregion Input #region Scene/Entity stuff - [RegisterCall("ScriptGlue::Entity_Create")] - static void Entity_Create(MonoObject* scriptInstance, MonoString* monoEntityName, MonoArray* componentTypes, out UUID entityId) + [RegisterCall] + static void Entity_Create(char8* entityName, out UUID entityId) { - char8* entityName = Mono.mono_string_to_utf8(monoEntityName); - Entity entity = ScriptEngine.Context.CreateEntity(StringView(entityName)); - Mono.mono_free(entityName); - entityId = entity.UUID; - - // TODO: Script instance - - if (componentTypes != null) - { - Entity_AddComponents(entityId, componentTypes); - } } - [RegisterCall("ScriptGlue::Entity_Destroy")] + [RegisterCall] static void Entity_Destroy(UUID entityId) { Entity entity = GetEntitySafe(entityId); ScriptEngine.Context.DestroyEntityDeferred(entity); } - [RegisterCall("ScriptGlue::Entity_CreateInstance")] + [RegisterCall] static void Entity_CreateInstance(UUID entityId, out UUID newEntityId) { Entity entity = GetEntitySafe(entityId); @@ -731,95 +687,29 @@ static class ScriptGlue newEntityId = newEntity.UUID; } - [RegisterCall("ScriptGlue::Entity_AddComponents")] - static void Entity_AddComponents(UUID entityId, MonoArray* componentTypes) - { - if (componentTypes == null) - return; - - uint length = Mono.mono_array_length(componentTypes); - for (uint i < length) - { - MonoReflectionType* reflectionType = Mono.mono_array_get(componentTypes, i); - - if (reflectionType != null) - Entity_AddComponent(entityId, reflectionType); - } - } - - [RegisterCall("ScriptGlue::Entity_AddComponent")] - static void Entity_AddComponent(UUID entityId, MonoReflectionType* componentType) - { - MonoType* type = Mono.mono_reflection_type_get_type(componentType); - - Entity entity = GetEntitySafe(entityId); - if (s_AddComponentMethods.TryGetValue(type, let addMethod)) - addMethod(entity); - else - Log.EngineLogger.AssertDebug(false, "No managed component with the given type registered."); - } - - [RegisterCall("ScriptGlue::Entity_HasComponent")] - static bool Entity_HasComponent(UUID entityId, MonoReflectionType* componentType) - { - MonoType* type = Mono.mono_reflection_type_get_type(componentType); - - Result foundEntity = ScriptEngine.Context.GetEntityByID(entityId); - - if (foundEntity case .Ok(let entity)) - { - if (s_HasComponentMethods.TryGetValue(type, let hasMethod)) - return hasMethod(entity); - } - else - { - Log.ClientLogger.Warning($"No entity found with the given id \"{entityId}\"."); - - return false; - } - - Log.EngineLogger.AssertDebug(false, "No managed component with the given type registered."); - - return false; - } - - [RegisterCall("ScriptGlue::Entity_RemoveComponent")] - static void Entity_RemoveComponent(UUID entityId, MonoReflectionType* componentType) - { - MonoType* type = Mono.mono_reflection_type_get_type(componentType); - - Entity entity = GetEntitySafe(entityId); - if (s_RemoveComponentMethods.TryGetValue(type, let removeMethod)) - removeMethod(entity); - else - Log.EngineLogger.AssertDebug(false, "No managed component with the given type registered."); - } - - [RegisterCall("ScriptGlue::Entity_FindEntityWithName")] - static void Entity_FindEntityWithName(MonoString* monoName, out UUID outUuid) + [RegisterCall] + static void Entity_FindEntityWithName(char8* entityName, out UUID outUuid) { outUuid = UUID(0); - char8* entityName = Mono.mono_string_to_utf8(monoName); - StringView nameString = StringView(entityName); Result entityResult = ScriptEngine.Context.GetEntityByName(nameString); - Mono.mono_free(entityName); - if (entityResult case .Ok(let entity)) outUuid = entity.UUID; } - [RegisterCall("ScriptGlue::Entity_GetScriptInstance")] - static void Entity_GetScriptInstance(UUID entityId, out MonoObject* instance) + // TODO: Do we need this? + [RegisterCall] + static void Entity_GetScriptInstance(UUID entityId, out void* instance) { - instance = ScriptEngine.GetManagedInstance(entityId); + ThrowNotImplementedException("Entity_AddComponents"); + //instance = ScriptEngine.GetManagedInstance(entityId); } - [RegisterCall("ScriptGlue::Entity_SetScript")] - static MonoObject* Entity_SetScript(UUID entityId, MonoReflectionType* scriptType) + [RegisterCall] + static bool Entity_SetScript(UUID entityId, char8* fullScriptTypeName) { Entity entity = GetEntitySafe(entityId); @@ -834,59 +724,54 @@ static class ScriptGlue scriptComponent = entity.GetComponent(); } - //if (scriptComponent.Instance != null) - // ScriptEngine.Context.DestroyScriptDeferred(scriptComponent.Instance, false); + if (scriptComponent.Instance != null) + ScriptEngine.Context.DestroyScriptDeferred(scriptComponent.Instance, false); scriptComponent.Instance = null; - MonoType* type = Mono.mono_reflection_type_get_type(scriptType); - - scriptComponent.ScriptClassName = StringView(Mono.mono_type_full_name(type)); + scriptComponent.ScriptClassName = StringView(fullScriptTypeName); // Initializes the created instance // TODO: this returns false, if no script with ScriptClassName exists, we have to handle this case correctly I think. - ScriptEngine.InitializeInstance(entity, scriptComponent); + if (!ScriptEngine.InitializeInstance(entity, scriptComponent)) + { + ThrowNotImplementedException("Werfe eine vernünftige Exception, bitte"); + } //return scriptComponent.Instance.MonoInstance; - return null; + return true; } - [RegisterCall("ScriptGlue::Entity_RemoveScript")] + [RegisterCall] static void Entity_RemoveScript(UUID entityId) { ScriptComponent* scriptComponent = GetComponentSafe(entityId); - //ScriptEngine.Context.DestroyScriptDeferred(scriptComponent.Instance, true); + ScriptEngine.Context.DestroyScriptDeferred(scriptComponent.Instance, true); } - [RegisterCall("ScriptGlue::Entity_GetName")] - static MonoString* Entity_GetName(UUID entityId) + [RegisterCall] + static char8* Entity_GetName(UUID entityId) { Result foundEntity = ScriptEngine.Context.GetEntityByID(entityId); if (foundEntity case .Ok(let entity)) { - MonoString* name = Mono.mono_string_new_len(ScriptEngine.[Friend]s_AppDomain, entity.Name.Ptr, (.)entity.Name.Length); - - return name; + return entity.Name.Ptr; } return null; } - [RegisterCall("ScriptGlue::Entity_SetName")] - static void Entity_SetName(UUID entityId, MonoString* name) + [RegisterCall] + static void Entity_SetName(UUID entityId, char8* name) { Entity entity = ScriptEngine.Context.GetEntityByID(entityId); - char8* rawName = Mono.mono_string_to_utf8(name); - - entity.Name = StringView(rawName); - - Mono.mono_free(rawName); + entity.Name = StringView(name); } - [RegisterCall("ScriptGlue::Entity_GetEditorFlags")] + [RegisterCall] static void Entity_GetEditorFlags(UUID entityId, out EditorFlags editorFlags) { editorFlags = .Default; @@ -896,7 +781,7 @@ static class ScriptGlue #endif } - [RegisterCall("ScriptGlue::Entity_SetEditorFlags")] + [RegisterCall] static void Entity_SetEditorFlags(UUID entityId, EditorFlags editorFlags) { #if GE_EDITOR @@ -907,9 +792,9 @@ static class ScriptGlue #endregion -#region TransformComponent +#region TransformComponen - [RegisterCall("ScriptGlue::Transform_GetParent")] + [RegisterCall] static void Transform_GetParent(UUID entityId, out UUID parentId) { Entity entity = GetEntitySafe(entityId); @@ -917,7 +802,7 @@ static class ScriptGlue parentId = entity.Parent?.UUID ?? .Zero; } - [RegisterCall("ScriptGlue::Transform_SetParent")] + [RegisterCall] static void Transform_SetParent(UUID entityId, in UUID parentId) { Entity entity = GetEntitySafe(entityId); @@ -927,7 +812,7 @@ static class ScriptGlue entity.Parent = parent; } - [RegisterCall("ScriptGlue::Transform_GetTranslation")] + [RegisterCall] static void Transform_GetTranslation(UUID entityId, out float3 translation) { Entity entity = GetEntitySafe(entityId); @@ -935,7 +820,7 @@ static class ScriptGlue translation = entity.Transform.Position; } - [RegisterCall("ScriptGlue::Transform_SetTranslation")] + [RegisterCall] static void Transform_SetTranslation(UUID entityId, in float3 translation) { Entity entity = GetEntitySafe(entityId); @@ -950,7 +835,7 @@ static class ScriptGlue // TODO: we need to handle repositioning of colliders that are children of the entity with rigidbody... } - [RegisterCall("ScriptGlue::Transform_GetWorldTranslation")] + [RegisterCall] static void Transform_GetWorldTranslation(UUID entityId, out float3 translationWorld) { Entity entity = GetEntitySafe(entityId); @@ -960,7 +845,7 @@ static class ScriptGlue translationWorld = transform.WorldTransform.Translation; //(float4(entity.Transform.Position, 1.0f) * entity.Transform.WorldTransform).XYZ; } - [RegisterCall("ScriptGlue::Transform_SetWorldTranslation")] + [RegisterCall] static void Transform_SetWorldTranslation(UUID entityId, in float3 translation) { Log.ClientLogger.Warning("Transform_SetWorldTranslation is not implemented!"); @@ -977,7 +862,7 @@ static class ScriptGlue // TODO: we need to handle repositioning of colliders that are children of the entity with rigidbody... } - [RegisterCall("ScriptGlue::Transform_TransformPointToWorld")] + [RegisterCall] static void Transform_TransformPointToWorld(UUID entityId, float3 point, out float3 pointWorld) { Entity entity = GetEntitySafe(entityId); @@ -987,7 +872,7 @@ static class ScriptGlue pointWorld = (float4(localPoint, 1.0f) * entity.Transform.WorldTransform).XYZ; } - [RegisterCall("ScriptGlue::Transform_GetRotation")] + [RegisterCall] static void Transform_GetRotation(UUID entityId, out Quaternion rotation) { Entity entity = GetEntitySafe(entityId); @@ -995,7 +880,7 @@ static class ScriptGlue rotation = entity.Transform.Rotation; } - [RegisterCall("ScriptGlue::Transform_SetRotation")] + [RegisterCall] static void Transform_SetRotation(UUID entityId, in Quaternion rotation) { Entity entity = GetEntitySafe(entityId); @@ -1009,7 +894,7 @@ static class ScriptGlue // TODO: When rotating around the X- or Y-axis we need to deform and reposition the colliders accordingly... } - [RegisterCall("ScriptGlue::Transform_GetRotationEuler")] + [RegisterCall] static void Transform_GetRotationEuler(UUID entityId, out float3 rotationEuler) { Entity entity = GetEntitySafe(entityId); @@ -1017,7 +902,7 @@ static class ScriptGlue rotationEuler = entity.Transform.RotationEuler; } - [RegisterCall("ScriptGlue::Transform_SetRotationEuler")] + [RegisterCall] static void Transform_SetRotationEuler(UUID entityId, in float3 rotationEuler) { Entity entity = GetEntitySafe(entityId); @@ -1043,7 +928,7 @@ static class ScriptGlue } } - [RegisterCall("ScriptGlue::Transform_GetRotationAxisAngle")] + [RegisterCall] static void Transform_GetRotationAxisAngle(UUID entityId, out AxisAngle rotationAxisAngle) { Entity entity = GetEntitySafe(entityId); @@ -1051,7 +936,7 @@ static class ScriptGlue rotationAxisAngle = AxisAngle(entity.Transform.RotationAxisAngle); } - [RegisterCall("ScriptGlue::Transform_SetRotationAxisAngle")] + [RegisterCall] static void Transform_SetRotationAxisAngle(UUID entityId, AxisAngle rotationAxisAngle) { Entity entity = GetEntitySafe(entityId); @@ -1064,7 +949,7 @@ static class ScriptGlue } } - [RegisterCall("ScriptGlue::Transform_GetScale")] + [RegisterCall] static void Transform_GetScale(UUID entityId, out float3 scale) { Entity entity = GetEntitySafe(entityId); @@ -1072,7 +957,7 @@ static class ScriptGlue scale = entity.Transform.Scale; } - [RegisterCall("ScriptGlue::Transform_SetScale")] + [RegisterCall] static void Transform_SetScale(UUID entityId, float3 scale) { Entity entity = GetEntitySafe(entityId); @@ -1087,114 +972,114 @@ static class ScriptGlue #endregion TransformComponent -#region Rigidbody2D +#region Rigidbody2 - [RegisterCall("ScriptGlue::Rigidbody2D_ApplyForce")] + [RegisterCall] static void Rigidbody2D_ApplyForce(UUID entityId, in float2 force, in float2 point, bool wakeUp) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); Box2D.Body.ApplyForce(rigidBody.[Friend]RuntimeBody, force, point, wakeUp); } - [RegisterCall("ScriptGlue::Rigidbody2D_ApplyForceToCenter")] + [RegisterCall] static void Rigidbody2D_ApplyForceToCenter(UUID entityId, in float2 force, bool wakeUp) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); Box2D.Body.ApplyForceToCenter(rigidBody.[Friend]RuntimeBody, force, wakeUp); } - [RegisterCall("ScriptGlue::Rigidbody2D_SetPosition")] + [RegisterCall] static void Rigidbody2D_SetPosition(UUID entityId, in float2 position) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); rigidBody.SetPosition(position); } - [RegisterCall("ScriptGlue::Rigidbody2D_GetPosition")] + [RegisterCall] static void Rigidbody2D_GetPosition(UUID entityId, out float2 position) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); position = rigidBody.GetPosition(); } - [RegisterCall("ScriptGlue::Rigidbody2D_SetRotation")] + [RegisterCall] static void Rigidbody2D_SetRotation(UUID entityId, in float rotation) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); rigidBody.SetAngle(rotation); } - [RegisterCall("ScriptGlue::Rigidbody2D_GetRotation")] + [RegisterCall] static void Rigidbody2D_GetRotation(UUID entityId, out float rotation) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); rotation = rigidBody.GetAngle(); } - [RegisterCall("ScriptGlue::Rigidbody2D_GetLinearVelocity")] + [RegisterCall] static void Rigidbody2D_GetLinearVelocity(UUID entityId, out float2 velocity) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); velocity = rigidBody.GetLinearVelocity(); } - [RegisterCall("ScriptGlue::Rigidbody2D_SetLinearVelocity")] + [RegisterCall] static void Rigidbody2D_SetLinearVelocity(UUID entityId, in float2 velocity) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); rigidBody.SetLinearVelocity(velocity); } - [RegisterCall("ScriptGlue::Rigidbody2D_GetAngularVelocity")] + [RegisterCall] static void Rigidbody2D_GetAngularVelocity(UUID entityId, out float velocity) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); velocity = rigidBody.GetAngularVelocity(); } - [RegisterCall("ScriptGlue::Rigidbody2D_SetAngularVelocity")] + [RegisterCall] static void Rigidbody2D_SetAngularVelocity(UUID entityId, in float velocity) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); rigidBody.SetAngularVelocity(velocity); } - [RegisterCall("ScriptGlue::Rigidbody2D_GetBodyType")] + [RegisterCall] static void Rigidbody2D_GetBodyType(UUID entityId, out Rigidbody2DComponent.BodyType bodyType) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); bodyType = rigidBody.BodyType; } - [RegisterCall("ScriptGlue::Rigidbody2D_SetBodyType")] + [RegisterCall] static void Rigidbody2D_SetBodyType(UUID entityId, in Rigidbody2DComponent.BodyType bodyType) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); rigidBody.BodyType = bodyType; } - [RegisterCall("ScriptGlue::Rigidbody2D_IsFixedRotation")] + [RegisterCall] static void Rigidbody2D_IsFixedRotation(UUID entityId, out bool isFixedRotation) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); isFixedRotation = rigidBody.FixedRotation; } - [RegisterCall("ScriptGlue::Rigidbody2D_SetFixedRotation")] + [RegisterCall] static void Rigidbody2D_SetFixedRotation(UUID entityId, in bool isFixedRotation) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); rigidBody.FixedRotation = isFixedRotation; } - [RegisterCall("ScriptGlue::Rigidbody2D_GetGravityScale")] + [RegisterCall] static void Rigidbody2D_GetGravityScale(UUID entityId, out float gravityScale) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); gravityScale = rigidBody.GravityScale; } - [RegisterCall("ScriptGlue::Rigidbody2D_SetGravityScale")] + [RegisterCall] static void Rigidbody2D_SetGravityScale(UUID entityId, in float gravityScale) { Rigidbody2DComponent* rigidBody = GetComponentSafe(entityId); @@ -1203,128 +1088,128 @@ static class ScriptGlue #endregion Rigidbody2D -#region Camera +#region Camer - [RegisterCall("ScriptGlue::Camera_GetProjectionType")] + [RegisterCall] static void Camera_GetProjectionType(UUID entityId, out SceneCamera.ProjectionType projectionType) { CameraComponent* camera = GetComponentSafe(entityId); projectionType = camera.Camera.ProjectionType; } - [RegisterCall("ScriptGlue::Camera_SetProjectionType")] + [RegisterCall] static void Camera_SetProjectionType(UUID entityId, in SceneCamera.ProjectionType projectionType) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.ProjectionType = projectionType; } - [RegisterCall("ScriptGlue::Camera_GetPerspectiveFovY")] + [RegisterCall] static void Camera_GetPerspectiveFovY(UUID entityId, out float fovY) { CameraComponent* camera = GetComponentSafe(entityId); fovY = camera.Camera.PerspectiveFovY; } - [RegisterCall("ScriptGlue::Camera_SetPerspectiveFovY")] + [RegisterCall] static void Camera_SetPerspectiveFovY(UUID entityId, float fovY) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.PerspectiveFovY = fovY; } - [RegisterCall("ScriptGlue::Camera_GetPerspectiveNearPlane")] + [RegisterCall] static void Camera_GetPerspectiveNearPlane(UUID entityId, out float nearPlane) { CameraComponent* camera = GetComponentSafe(entityId); nearPlane = camera.Camera.PerspectiveNearPlane; } - [RegisterCall("ScriptGlue::Camera_SetPerspectiveNearPlane")] + [RegisterCall] static void Camera_SetPerspectiveNearPlane(UUID entityId, float nearPlane) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.PerspectiveNearPlane = nearPlane; } - [RegisterCall("ScriptGlue::Camera_GetPerspectiveFarPlane")] + [RegisterCall] static void Camera_GetPerspectiveFarPlane(UUID entityId, out float farPlane) { CameraComponent* camera = GetComponentSafe(entityId); farPlane = camera.Camera.PerspectiveFarPlane; } - [RegisterCall("ScriptGlue::Camera_SetPerspectiveFarPlane")] + [RegisterCall] static void Camera_SetPerspectiveFarPlane(UUID entityId, float farPlane) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.PerspectiveFarPlane = farPlane; } - [RegisterCall("ScriptGlue::Camera_GetOrthographicHeight")] + [RegisterCall] static void Camera_GetOrthographicHeight(UUID entityId, out float height) { CameraComponent* camera = GetComponentSafe(entityId); height = camera.Camera.OrthographicHeight; } - [RegisterCall("ScriptGlue::Camera_SetOrthographicHeight")] + [RegisterCall] static void Camera_SetOrthographicHeight(UUID entityId, float height) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.OrthographicHeight = height; } - [RegisterCall("ScriptGlue::Camera_SetOrthographicNearPlane")] + [RegisterCall] static void Camera_SetOrthographicNearPlane(UUID entityId, float nearPlane) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.OrthographicNearPlane = nearPlane; } - [RegisterCall("ScriptGlue::Camera_GetOrthographicNearPlane")] + [RegisterCall] static void Camera_GetOrthographicNearPlane(UUID entityId, out float nearPlane) { CameraComponent* camera = GetComponentSafe(entityId); nearPlane = camera.Camera.OrthographicNearPlane; } - [RegisterCall("ScriptGlue::Camera_SetOrthographicFarPlane")] + [RegisterCall] static void Camera_SetOrthographicFarPlane(UUID entityId, float farPlane) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.OrthographicFarPlane = farPlane; } - [RegisterCall("ScriptGlue::Camera_GetOrthographicFarPlane")] + [RegisterCall] static void Camera_GetOrthographicFarPlane(UUID entityId, out float farPlane) { CameraComponent* camera = GetComponentSafe(entityId); farPlane = camera.Camera.OrthographicFarPlane; } - [RegisterCall("ScriptGlue::Camera_SetAspectRatio")] + [RegisterCall] static void Camera_SetAspectRatio(UUID entityId, float aspectRatio) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.AspectRatio = aspectRatio; } - [RegisterCall("ScriptGlue::Camera_GetAspectRatio")] + [RegisterCall] static void Camera_GetAspectRatio(UUID entityId, out float aspectRatio) { CameraComponent* camera = GetComponentSafe(entityId); aspectRatio = camera.Camera.AspectRatio; } - [RegisterCall("ScriptGlue::Camera_SetFixedAspectRatio")] + [RegisterCall] static void Camera_SetFixedAspectRatio(UUID entityId, bool fixedAspectRatio) { CameraComponent* camera = GetComponentSafe(entityId); camera.Camera.FixedAspectRatio = fixedAspectRatio; } - [RegisterCall("ScriptGlue::Camera_GetFixedAspectRatio")] + [RegisterCall] static void Camera_GetFixedAspectRatio(UUID entityId, out bool fixedAspectRatio) { CameraComponent* camera = GetComponentSafe(entityId); @@ -1337,7 +1222,7 @@ static class ScriptGlue // TODO: We need a wrapper class! - [RegisterCall("ScriptGlue::Physics2D_GetGravity")] + [RegisterCall] static void Physics2D_GetGravity(out float2 gravity) { Scene scene = ScriptEngine.Context; @@ -1345,7 +1230,7 @@ static class ScriptGlue gravity = scene.Physics2DSettings.Gravity; } - [RegisterCall("ScriptGlue::Physics2D_SetGravity")] + [RegisterCall] static void Physics2D_SetGravity(in float2 gravity) { Scene scene = ScriptEngine.Context; @@ -1357,42 +1242,42 @@ static class ScriptGlue #region CircleRenderer - [RegisterCall("ScriptGlue::CircleRenderer_GetColor")] + [RegisterCall] static void CircleRenderer_GetColor(UUID entityId, out ColorRGBA color) { CircleRendererComponent* circleRenderer = GetComponentSafe(entityId); color = circleRenderer.Color; } - [RegisterCall("ScriptGlue::CircleRenderer_SetColor")] + [RegisterCall] static void CircleRenderer_SetColor(UUID entityId, ColorRGBA color) { CircleRendererComponent* circleRenderer = GetComponentSafe(entityId); circleRenderer.Color = color; } - [RegisterCall("ScriptGlue::CircleRenderer_GetUvTransform")] + [RegisterCall] static void CircleRenderer_GetUvTransform(UUID entityId, out float4 uvTransform) { CircleRendererComponent* circleRenderer = GetComponentSafe(entityId); uvTransform = circleRenderer.UvTransform; } - [RegisterCall("ScriptGlue::CircleRenderer_SetUvTransform")] + [RegisterCall] static void CircleRenderer_SetUvTransform(UUID entityId, float4 uvTransform) { CircleRendererComponent* circleRenderer = GetComponentSafe(entityId); circleRenderer.UvTransform = uvTransform; } - [RegisterCall("ScriptGlue::CircleRenderer_GetInnerRadius")] + [RegisterCall] static void CircleRenderer_GetInnerRadius(UUID entityId, out float innerRadius) { CircleRendererComponent* circleRenderer = GetComponentSafe(entityId); innerRadius = circleRenderer.InnerRadius; } - [RegisterCall("ScriptGlue::CircleRenderer_SetInnerRadius")] + [RegisterCall] static void CircleRenderer_SetInnerRadius(UUID entityId, float innerRadius) { CircleRendererComponent* circleRenderer = GetComponentSafe(entityId); @@ -1403,35 +1288,35 @@ static class ScriptGlue #region SpriteRenderer - [RegisterCall("ScriptGlue::SpriteRenderer_GetColor")] + [RegisterCall] static void SpriteRenderer_GetColor(UUID entityId, out ColorRGBA color) { SpriteRendererComponent* spriteRenderer = GetComponentSafe(entityId); color = spriteRenderer.Color; } - [RegisterCall("ScriptGlue::SpriteRenderer_SetColor")] + [RegisterCall] static void SpriteRenderer_SetColor(UUID entityId, ColorRGBA color) { SpriteRendererComponent* spriteRenderer = GetComponentSafe(entityId); spriteRenderer.Color = color; } - [RegisterCall("ScriptGlue::SpriteRenderer_GetUvTransform")] + [RegisterCall] static void SpriteRenderer_GetUvTransform(UUID entityId, out float4 uvTransform) { SpriteRendererComponent* spriteRenderer = GetComponentSafe(entityId); uvTransform = spriteRenderer.UvTransform; } - [RegisterCall("ScriptGlue::SpriteRenderer_SetUvTransform")] + [RegisterCall] static void SpriteRenderer_SetUvTransform(UUID entityId, float4 uvTransform) { SpriteRendererComponent* spriteRenderer = GetComponentSafe(entityId); spriteRenderer.UvTransform = uvTransform; } - [RegisterCall("ScriptGlue::SpriteRenderer_GetMaterial")] + [RegisterCall] static void SpriteRenderer_GetMaterial(UUID entityId, out AssetHandle assetId) { SpriteRendererComponent* spriteRenderer = GetComponentSafe(entityId); @@ -1451,7 +1336,7 @@ static class ScriptGlue assetId = spriteRenderer.Material; } - [RegisterCall("ScriptGlue::SpriteRenderer_SetMaterial")] + [RegisterCall] static void SpriteRenderer_SetMaterial(UUID entityId, AssetHandle assetId) { SpriteRendererComponent* spriteRenderer = GetComponentSafe(entityId); @@ -1463,13 +1348,13 @@ static class ScriptGlue #region TextRenderer - [RegisterCall("ScriptGlue::TextRenderer_GetIsRichText")] + [RegisterCall] static bool TextRenderer_GetIsRichText(UUID entityId) { return GetComponentSafe(entityId).IsRichText; } - [RegisterCall("ScriptGlue::TextRenderer_SetIsRichText")] + [RegisterCall] static void TextRenderer_SetIsRichText(UUID entityId, bool isRichText) { TextRendererComponent* textComponent = GetComponentSafe(entityId); @@ -1478,36 +1363,32 @@ static class ScriptGlue textComponent.NeedsRebuild = true; } - [RegisterCall("ScriptGlue::TextRenderer_GetText")] - static void TextRenderer_GetText(UUID entityId, out MonoString* text) + [RegisterCall] + static void TextRenderer_GetText(UUID entityId, out char8* text) { TextRendererComponent* textComponent = GetComponentSafe(entityId); - text = Mono.mono_string_new_len(ScriptEngine.[Friend]s_AppDomain, textComponent.Text.Ptr, (uint32)textComponent.Text.Length); + text = textComponent.Text.Ptr; } - [RegisterCall("ScriptGlue::TextRenderer_SetText")] - static void TextRenderer_SetText(UUID entityId, MonoString* text) + [RegisterCall] + static void TextRenderer_SetText(UUID entityId, char8* text) { TextRendererComponent* textComponent = GetComponentSafe(entityId); - char8* rawText = Mono.mono_string_to_utf8(text); - - textComponent.Text = StringView(rawText); + textComponent.Text = StringView(text); textComponent.NeedsRebuild = true; - - Mono.mono_free(rawText); } - [RegisterCall("ScriptGlue::TextRenderer_GetColor")] + [RegisterCall] static void TextRenderer_GetColor(UUID entityId, out ColorRGBA color) { TextRendererComponent* textComponent = GetComponentSafe(entityId); color = textComponent.Color; } - [RegisterCall("ScriptGlue::TextRenderer_SetColor")] + [RegisterCall] static void TextRenderer_SetColor(UUID entityId, ColorRGBA color) { TextRendererComponent* textComponent = GetComponentSafe(entityId); @@ -1515,14 +1396,14 @@ static class ScriptGlue textComponent.NeedsRebuild = true; } - [RegisterCall("ScriptGlue::TextRenderer_GetHorizontalAlignment")] + [RegisterCall] static void TextRenderer_GetHorizontalAlignment(UUID entityId, [GlueParam("out HorizontalTextAlignment")] out HorizontalTextAlignment horizontalAlignment) { TextRendererComponent* textComponent = GetComponentSafe(entityId); horizontalAlignment = textComponent.HorizontalAlignment; } - [RegisterCall("ScriptGlue::TextRenderer_SetHorizontalAlignment")] + [RegisterCall] static void TextRenderer_SetHorizontalAlignment(UUID entityId, [GlueParam("HorizontalTextAlignment")] HorizontalTextAlignment horizontalAlignment) { TextRendererComponent* textComponent = GetComponentSafe(entityId); @@ -1530,14 +1411,14 @@ static class ScriptGlue textComponent.NeedsRebuild = true; } - [RegisterCall("ScriptGlue::TextRenderer_GetFontSize")] + [RegisterCall] static void TextRenderer_GetFontSize(UUID entityId, out float fontSize) { TextRendererComponent* textComponent = GetComponentSafe(entityId); fontSize = textComponent.FontSize; } - [RegisterCall("ScriptGlue::TextRenderer_SetFontSize")] + [RegisterCall] static void TextRenderer_SetFontSize(UUID entityId, float fontSize) { TextRendererComponent* textComponent = GetComponentSafe(entityId); @@ -1552,7 +1433,7 @@ static class ScriptGlue #region MeshRenderer - [RegisterCall("ScriptGlue::MeshRenderer_GetMaterial")] + [RegisterCall] static void MeshRenderer_GetMaterial(UUID entityId, out AssetHandle assetId) { MeshRendererComponent* meshRenderer = GetComponentSafe(entityId); @@ -1572,7 +1453,7 @@ static class ScriptGlue assetId = meshRenderer.Material; } - [RegisterCall("ScriptGlue::MeshRenderer_GetSharedMaterial")] + [RegisterCall] static void MeshRenderer_GetSharedMaterial(UUID entityId, out AssetHandle assetId) { MeshRendererComponent* meshRenderer = GetComponentSafe(entityId); @@ -1589,7 +1470,7 @@ static class ScriptGlue } } - [RegisterCall("ScriptGlue::MeshRenderer_SetMaterial")] + [RegisterCall] static void MeshRenderer_SetMaterial(UUID entityId, AssetHandle assetId) { MeshRendererComponent* meshRenderer = GetComponentSafe(entityId); @@ -1599,46 +1480,34 @@ static class ScriptGlue #endregion #region Math - - private static void RegisterMathFunctions() + + [RegisterCall] + static float Math_ModfFloat(float x, out float integerPart) { - RegisterCall("ScriptGlue::modf_float", => GlitchyEngine.Math.modf); - RegisterCall("ScriptGlue::modf_float2", => GlitchyEngine.Math.modf); - RegisterCall("ScriptGlue::modf_float3", => GlitchyEngine.Math.modf); - RegisterCall("ScriptGlue::modf_float4", => GlitchyEngine.Math.modf); - - RegisterHalfFunctions(); + return modf(x, out integerPart); } - private static void RegisterHalfFunctions() + [RegisterCall] + static float2 Math_ModfFloat2(float2 x, out float2 integerPart) { - RegisterCall("Math.Half::FromFloat32", (value, halfValue) => halfValue = GlitchyEngine.Math.half.FromFloat32(value)); - RegisterCall("Math.Half::ToFloat32", (value, floatValue) => floatValue = GlitchyEngine.Math.half.ToFloat32(value)); - - RegisterCall("Math.Half::LessThan_Impl", (left, right, result) => result = left < right); - RegisterCall("Math.Half::LessThanOrEqual_Impl", (left, right, result) => result = left <= right); - RegisterCall("Math.Half::GreaterThan_Impl", (left, right, result) => result = left > right); - RegisterCall("Math.Half::GreaterThanOrEqual_Impl", (left, right, result) => result = left >= right); + return modf(x, out integerPart); + } - RegisterCall("Math.Half::Add_Impl", (left, right, result) => result = left + right); - RegisterCall("Math.Half::Subtract_Impl", (left, right, result) => result = left - right); - RegisterCall("Math.Half::Multiply_Impl", (left, right, result) => result = left * right); - RegisterCall("Math.Half::Divide_Impl", (left, right, result) => result = left / right); - RegisterCall("Math.Half::Modulo_Impl", (left, right, result) => result = left % right); - RegisterCall("Math.Half::Negate_Impl", (value, result) => result = -value); - RegisterCall("Math.Half::Increment_Impl", (value, result) => result = ++value); - RegisterCall("Math.Half::Decrement_Impl", (value, result) => result = --value); - - RegisterCall("Math.Half::IsNegative_Impl", (value) => value.IsNegative); - RegisterCall("Math.Half::IsFinite_Impl", (value) => value.IsFinite); - RegisterCall("Math.Half::IsInfinity_Impl", (value) => value.IsInfinity); - RegisterCall("Math.Half::IsNan_Impl", (value) => value.IsNaN); - RegisterCall("Math.Half::IsSubnormal_Impl", (value) => value.IsSubnormal); + [RegisterCall] + static float3 Math_ModfFloat3(float3 x, out float3 integerPart) + { + return modf(x, out integerPart); + } + + [RegisterCall] + static float4 Math_ModfFloat4(float4 x, out float4 integerPart) + { + return modf(x, out integerPart); } #endregion - [RegisterCall("ScriptGlue::UUID_CreateNew")] + [RegisterCall] static void UUID_Create(out UUID id) { id = UUID.Create(); @@ -1646,25 +1515,25 @@ static class ScriptGlue #region Application - [RegisterCall("ScriptGlue::Application_IsEditor")] + [RegisterCall] static bool Application_IsEditor() { return ScriptEngine.ApplicationInfo.IsEditor; } - [RegisterCall("ScriptGlue::Application_IsPlayer")] + [RegisterCall] static bool Application_IsPlayer() { return ScriptEngine.ApplicationInfo.IsPlayer; } - [RegisterCall("ScriptGlue::Application_IsInEditMode")] + [RegisterCall] static bool Application_IsInEditMode() { return ScriptEngine.ApplicationInfo.IsInEditMode; } - [RegisterCall("ScriptGlue::Application_IsInPlayMode")] + [RegisterCall] static bool Application_IsInPlayMode() { return ScriptEngine.ApplicationInfo.IsInPlayMode; @@ -1674,52 +1543,40 @@ static class ScriptGlue #region Serialization - [RegisterCall("ScriptGlue::Serialization_SerializeField")] - static void Serialization_SerializeField(void* serializationContext, SerializationType type, MonoString* nameObject, MonoObject* valueObject, MonoString* fullTypeName) + [RegisterCall] + static void Serialization_SerializeField(void* serializationContext, SerializationType type, char8* fieldName, void* valueObject, char8* fullTypeName) { SerializedObject context = Internal.UnsafeCastToObject(serializationContext) as SerializedObject; Log.EngineLogger.AssertDebug(context != null); - char8* name = Mono.mono_string_to_utf8(nameObject); - - context.AddField(StringView(name), type, valueObject, fullTypeName); - - Mono.mono_free(name); + context.AddField(StringView(fieldName), type, valueObject, StringView(fullTypeName)); } - [RegisterCall("ScriptGlue::Serialization_CreateObject")] - static void Serialization_CreateObject(void* currentContext, bool isStatic, MonoString* typeName, out void* newContext, out UUID newId) + [RegisterCall] + static void Serialization_CreateObject(void* currentContext, bool isStatic, char8* typeName, out void* newContext, out UUID newId) { SerializedObject context = Internal.UnsafeCastToObject(currentContext) as SerializedObject; Log.EngineLogger.AssertDebug(context != null); - char8* rawTypeName = Mono.mono_string_to_utf8(typeName); - - SerializedObject newObject = new SerializedObject(context.Serializer, isStatic, StringView(rawTypeName)); - - Mono.mono_free(rawTypeName); + SerializedObject newObject = new SerializedObject(context.Serializer, isStatic, StringView(typeName)); newContext = Internal.UnsafeCastToPtr(newObject); newId = newObject.Id; } - [RegisterCall("ScriptGlue::Serialization_DeserializeField")] - public static void Serialization_DeserializeField(void* internalContext, SerializationType expectedType, MonoString* fieldName, uint8* target, out SerializationType actualType) + [RegisterCall] + public static void Serialization_DeserializeField(void* internalContext, SerializationType expectedType, char8* fieldName, uint8* target, out SerializationType actualType) { SerializedObject context = Internal.UnsafeCastToObject(internalContext) as SerializedObject; Log.EngineLogger.AssertDebug(context != null); - char8* name = Mono.mono_string_to_utf8(fieldName); - - context.GetField(StringView(name), expectedType, target, out actualType); - - Mono.mono_free(name); + context.GetField(StringView(fieldName), expectedType, target, out actualType); } - [RegisterCall("ScriptGlue::Serialization_GetObject")] + [RegisterCall] public static void Serialization_GetObject(void* internalContext, UUID id, out void* objectContext) { SerializedObject context = Internal.UnsafeCastToObject(internalContext) as SerializedObject; @@ -1736,14 +1593,14 @@ static class ScriptGlue objectContext = Internal.UnsafeCastToPtr(foundObject); } - [RegisterCall("ScriptGlue::Serialization_GetObjectTypeName")] - public static void Serialization_GetObjectTypeName(void* internalContext, out MonoString* fullTypeName) + [RegisterCall] + public static void Serialization_GetObjectTypeName(void* internalContext, out char8* fullTypeName) { SerializedObject context = Internal.UnsafeCastToObject(internalContext) as SerializedObject; Log.EngineLogger.AssertDebug(context != null); - fullTypeName = Mono.mono_string_new(ScriptEngine.[Friend]s_AppDomain, context.TypeName); + fullTypeName = context.TypeName.CStr(); } #endregion @@ -1788,78 +1645,62 @@ static class ScriptGlue asset } - [RegisterCall("ScriptGlue::Asset_GetIdentifier")] - static void Asset_GetIdentifier(UUID assetId, out MonoString* text) + [RegisterCall] + static void Asset_GetIdentifier(UUID assetId, out char8* identifier) { Asset asset = GetAssetOrThrow!(assetId); - text = Mono.mono_string_new_len(ScriptEngine.[Friend]s_AppDomain, asset.Identifier.Ptr, (uint32)asset.Identifier.Length); + identifier = asset.Identifier.Ptr; } - [RegisterCall("ScriptGlue::Asset_SetIdentifier")] - static void Asset_SetIdentifier(UUID assetId, MonoString* text) + [RegisterCall] + static void Asset_SetIdentifier(UUID assetId, char8* identifier) { + AssetHandle handle = .(assetId); + Asset asset = Content.GetAsset(handle, blocking: true); + ThrowNotImplementedException("Asset.GetIdentifier is not implemented."); - /*AssetHandle handle = .(assetId); - Asset asset = Content.GetAsset(handle, blocking: true); - - char8* rawText = Mono.mono_string_to_utf8(text); - + /* // TODO: I think it's not THAT easy. asset.Identifier = StringView(rawText); - - Mono.mono_free(rawText);*/ + */ } #endregion #region Material - [RegisterCall("ScriptGlue::Material_SetVariable")] - static void Material_SetVariable(AssetHandle assetHandle, MonoString* managedVariableName, ShaderVariableType elementType, int32 rows, int32 columns, int32 arrayLength, uint8* rawData, int32 dataLength) + [RegisterCall] + static void Material_SetVariable(AssetHandle assetHandle, char8* variableName, ShaderVariableType elementType, int32 rows, int32 columns, int32 arrayLength, void* rawData, int32 dataLength) { Material material = GetAssetOrThrow!(assetHandle); - char8* rawVariableName = Mono.mono_string_to_utf8(managedVariableName); - - material.[Friend]SetVariableRaw(StringView(rawVariableName), elementType, rows, columns , arrayLength, Span(rawData, dataLength)); - - Mono.mono_free(rawVariableName); + material.[Friend]SetVariableRaw(StringView(variableName), elementType, rows, columns , arrayLength, Span((uint8*)rawData, dataLength)); } - [RegisterCall("ScriptGlue::Material_ResetVariable")] - static void Material_ResetVariable(AssetHandle assetHandle, MonoString* managedVariableName) + [RegisterCall] + static void Material_ResetVariable(AssetHandle assetHandle, char8* variableName) { Material material = GetAssetOrThrow!(assetHandle); - char8* rawVariableName = Mono.mono_string_to_utf8(managedVariableName); - - material.ResetVariable(StringView(rawVariableName)); - - Mono.mono_free(rawVariableName); + material.ResetVariable(StringView(variableName)); } - [RegisterCall("ScriptGlue::Material_SetTexture")] - static void Material_SetTexture(AssetHandle materialHandle, MonoString* managedVariableName, AssetHandle textureHandle) + [RegisterCall] + static void Material_SetTexture(AssetHandle materialHandle, char8* variableName, AssetHandle textureHandle) { Material material = GetAssetOrThrow!(materialHandle); - char8* rawVariableName = Mono.mono_string_to_utf8(managedVariableName); - - material.SetTexture(StringView(rawVariableName), textureHandle); - - Mono.mono_free(rawVariableName); + material.SetTexture(StringView(variableName), textureHandle); } - [RegisterCall("ScriptGlue::Material_GetTexture")] - static void Material_GetTexture(AssetHandle materialHandle, MonoString* managedVariableName, out AssetHandle textureHandle) + [RegisterCall] + static void Material_GetTexture(AssetHandle materialHandle, char8* variableName, out AssetHandle textureHandle) { Material material = GetAssetOrThrow!(materialHandle); - char8* rawVariableName = Mono.mono_string_to_utf8(managedVariableName); - - var v = material.GetTexture(StringView(rawVariableName), ?); + var v = material.GetTexture(StringView(variableName), ?); if (v case .Err(let err)) { @@ -1867,36 +1708,25 @@ static class ScriptGlue } textureHandle = v.Value; - - Mono.mono_free(rawVariableName); } - [RegisterCall("ScriptGlue::Material_ResetTexture")] - static void Material_ResetTexture(AssetHandle materialHandle, MonoString* managedVariableName) + [RegisterCall] + static void Material_ResetTexture(AssetHandle materialHandle, char8* variableName) { Material material = GetAssetOrThrow!(materialHandle); - char8* rawVariableName = Mono.mono_string_to_utf8(managedVariableName); - - material.ResetTexture(StringView(rawVariableName)); - - Mono.mono_free(rawVariableName); + material.ResetTexture(StringView(variableName)); } #endregion #region ImGui Extension - [RegisterCall("ScriptGlue::ImGuiExtension_ListElementGrabber")] + [RegisterCall] static void ImGuiExtension_ListElementGrabber() { ImGui.ImGui.ListElementGrabber(); } #endregion - - public static void RegisterCall(String name, T method) where T : var - { - Mono.mono_add_internal_call(scope $"GlitchyEngine.{name}", (void*)method); - } } \ No newline at end of file diff --git a/GlitchyEngine/src/Serialization/SerializedObject.bf b/GlitchyEngine/src/Serialization/SerializedObject.bf index a5644d2..f7fe34a 100644 --- a/GlitchyEngine/src/Serialization/SerializedObject.bf +++ b/GlitchyEngine/src/Serialization/SerializedObject.bf @@ -90,7 +90,7 @@ class SerializedObject Fields.Add(nameCopy, (fieldType, data)); } - public void AddField(StringView name, SerializationType primitiveType, MonoObject* value, MonoString* fullTypeName) + public void AddField(StringView name, SerializationType primitiveType, void* value, StringView fullTypeName) { FieldData data = .(); @@ -102,15 +102,10 @@ class SerializedObject if (value != null) { - MonoString* string = (.)value; - char8* rawStringValue = Mono.mono_string_to_utf8(string); - - String stringValue = new String(rawStringValue); + String stringValue = new String((char8*)value); _ownedString.Add(stringValue); - Mono.mono_free(rawStringValue); - valueView = stringValue; } @@ -118,21 +113,14 @@ class SerializedObject case .EngineObjectReference: String typeName = null; - if (fullTypeName != null) + if (!fullTypeName.IsEmpty) { - char8* rawTypeName = Mono.mono_string_to_utf8(fullTypeName); - typeName = new String(rawTypeName); - - _ownedString.Add(typeName); - - Mono.mono_free(rawTypeName); + _ownedString.Add(new String(fullTypeName)); } - data.EngineObject = (FullTypeName: typeName, ID: *(UUID*)Mono.mono_object_unbox(value)); + data.EngineObject = (FullTypeName: typeName, ID: *(UUID*)value); default: - void* rawValue = Mono.mono_object_unbox(value); - - SetDataSimple(primitiveType, rawValue, ref data); + SetDataSimple(primitiveType, value, ref data); } AddField(name, primitiveType, data); diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index f6ebcec..2a16643 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -686,7 +686,7 @@ namespace GlitchyEngine.World private append List _destroyQueue = .(); - private append List _destroyScriptQueue = .(); + private append List _destroyScriptQueue = .(); float physicsDelta = 0; @@ -926,7 +926,7 @@ namespace GlitchyEngine.World * @param scriptInstance The script instance to destroy. * @param removeComponent If set to true the ScriptComponent will be removed from the entity. */ - public void DestroyScriptDeferred(ScriptInstance scriptInstance, bool removeComponent) + public void DestroyScriptDeferred(NewScriptInstance scriptInstance, bool removeComponent) { _destroyScriptQueue.Add(scriptInstance..AddRef()); diff --git a/ScriptCore/Entity.cs b/ScriptCore/Entity.cs index fb8e9fc..27d8d72 100644 --- a/ScriptCore/Entity.cs +++ b/ScriptCore/Entity.cs @@ -70,12 +70,17 @@ public class Entity : EngineObject private void Create(string? name, Type[]? components) { - ScriptGlue.Entity_Create(this, name, components, out _uuid); + ScriptGlue.Entity_Create(name, out _uuid); if (_uuid == UUID.Zero) { throw new InvalidOperationException("Failed to create the Entity. Received UUID.Zero from the engine."); } + + if (components != null) + { + AddComponents(components); + } } /// @@ -98,7 +103,10 @@ public class Entity : EngineObject /// /// The type of the component. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool HasComponent(Type type) => ScriptGlue.Entity_HasComponent(_uuid, type); + public bool HasComponent(Type type) + { + return ScriptGlue.Entity_HasComponent(_uuid, type); + } /// /// Gets the component with the specified type. @@ -208,8 +216,6 @@ public class Entity : EngineObject } } - ScriptGlue.Entity_AddComponents(_uuid, componentTypes); - Component?[] components = new Component[componentTypes.Length]; foreach ((Type componentType, int index) in componentTypes.WithIndex()) @@ -218,6 +224,8 @@ public class Entity : EngineObject if (componentType == null!) continue; + ScriptGlue.Entity_AddComponent(_uuid, componentType); + components[index] = ActivatorExtension.CreateComponent(componentType, _uuid); } @@ -232,7 +240,8 @@ public class Entity : EngineObject where T1 : Component, new() where T2 : Component, new() { - ScriptGlue.Entity_AddComponents(_uuid, new []{typeof(T1), typeof(T2)}); + ScriptGlue.Entity_AddComponent(_uuid, typeof(T1)); + ScriptGlue.Entity_AddComponent(_uuid, typeof(T2)); return (new T1 { _uuid = _uuid }, new T2 { _uuid = _uuid }); } @@ -246,7 +255,9 @@ public class Entity : EngineObject where T2 : Component, new() where T3 : Component, new() { - ScriptGlue.Entity_AddComponents(_uuid, new []{typeof(T1), typeof(T2), typeof(T3)}); + ScriptGlue.Entity_AddComponent(_uuid, typeof(T1)); + ScriptGlue.Entity_AddComponent(_uuid, typeof(T2)); + ScriptGlue.Entity_AddComponent(_uuid, typeof(T3)); return (new T1 { _uuid = _uuid }, new T2 { _uuid = _uuid }, new T3 { _uuid = _uuid }); } @@ -285,7 +296,14 @@ public class Entity : EngineObject /// A reference to the new script or , if the operation failed. public T? SetScript() where T : Entity { - return ScriptGlue.Entity_SetScript(_uuid, typeof(T)) as T; + Entity? scriptInstance = null; + + if (ScriptGlue.Entity_SetScript(_uuid, typeof(T).FullName)) + { + ScriptGlue.Entity_GetScriptInstance(_uuid, out scriptInstance); + } + + return scriptInstance as T; } /// @@ -323,7 +341,7 @@ public class Entity : EngineObject /// if the has a script component of the given type; or if the either has no script or the script is not of the specified type. public bool Is() where T : Entity { - ScriptGlue.Entity_GetScriptInstance(_uuid, out object? scriptInstance); + ScriptGlue.Entity_GetScriptInstance(_uuid, out Entity? scriptInstance); return scriptInstance is T; } @@ -341,7 +359,7 @@ public class Entity : EngineObject return false; } - ScriptGlue.Entity_GetScriptInstance(_uuid, out object? scriptInstance); + ScriptGlue.Entity_GetScriptInstance(_uuid, out Entity? scriptInstance); return type.IsInstanceOfType(scriptInstance); } @@ -353,7 +371,7 @@ public class Entity : EngineObject /// The script instance of the given type; or if the has no script of the given type. public T? As() where T : Entity { - ScriptGlue.Entity_GetScriptInstance(_uuid, out object? scriptInstance); + ScriptGlue.Entity_GetScriptInstance(_uuid, out Entity? scriptInstance); return scriptInstance as T; } @@ -371,7 +389,7 @@ public class Entity : EngineObject return null; } - ScriptGlue.Entity_GetScriptInstance(_uuid, out object? scriptInstance); + ScriptGlue.Entity_GetScriptInstance(_uuid, out Entity? scriptInstance); return scriptInstance; } @@ -386,7 +404,7 @@ public class Entity : EngineObject { Debug.Assert(typeof(Entity).IsAssignableFrom(type)); - ScriptGlue.Entity_GetScriptInstance(id, out object? scriptInstance); + ScriptGlue.Entity_GetScriptInstance(id, out Entity? scriptInstance); return scriptInstance as Entity; } diff --git a/ScriptCore/Extensions/ImGuiExtension.cs b/ScriptCore/Extensions/ImGuiExtension.cs index 9fa1a00..d673c09 100644 --- a/ScriptCore/Extensions/ImGuiExtension.cs +++ b/ScriptCore/Extensions/ImGuiExtension.cs @@ -77,7 +77,9 @@ public static class ImGuiExtension public static bool ShowAssetDropTarget(ref UUID uuid) { - return ScriptGlue.ImGuiExtension_ShowAssetDropTarget(ref uuid); + // TODO: !!! + // return ScriptGlue.ImGuiExtension_ShowAssetDropTarget(ref uuid); + return false; } public static bool Checkbox2(string label, ref bool2 value) => CheckboxN(2, label, ref value.X); diff --git a/ScriptCore/Graphics/Material.cs b/ScriptCore/Graphics/Material.cs index b6bc975..181103b 100644 --- a/ScriptCore/Graphics/Material.cs +++ b/ScriptCore/Graphics/Material.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.SymbolStore; +using System; +using System.Diagnostics.SymbolStore; using GlitchyEngine.Core; using GlitchyEngine.Math; @@ -22,7 +23,7 @@ public class Material : Asset { unsafe { - ScriptGlue.Material_SetVariable(_uuid, name, ShaderVariableType.Float, 1, 4, 1, &value, sizeof(float4)); + ScriptGlue.Material_SetVariable(_uuid, name, ShaderVariableType.Float, 1, 4, 1, (IntPtr)(void*)&value, sizeof(float4)); } } diff --git a/ScriptCore/Graphics/SpriteRenderer.cs b/ScriptCore/Graphics/SpriteRenderer.cs index e267a71..fbde34d 100644 --- a/ScriptCore/Graphics/SpriteRenderer.cs +++ b/ScriptCore/Graphics/SpriteRenderer.cs @@ -30,10 +30,20 @@ public class SpriteRenderer : Component { get { - ScriptGlue.SpriteRenderer_GetUvTransform(_uuid, out UVTransform uvTransform); - return uvTransform; + unsafe + { + // TODO: Is this a type we want to have in the engine? + ScriptGlue.SpriteRenderer_GetUvTransform(_uuid, out float4 uvTransform); + return *(UVTransform*)&uvTransform; + } + } + set + { + unsafe + { + ScriptGlue.SpriteRenderer_SetUvTransform(_uuid, *(float4*)&value); + } } - set => ScriptGlue.SpriteRenderer_SetUvTransform(_uuid, value); } /// diff --git a/ScriptCore/Log.cs b/ScriptCore/Log.cs index e76db2c..c510efe 100644 --- a/ScriptCore/Log.cs +++ b/ScriptCore/Log.cs @@ -141,6 +141,6 @@ public class Log /// The exception to log. public static void Exception(Exception exception) { - ScriptGlue.Log_LogException(exception); + ScriptGlue.Log_LogException(UUID.Zero, exception.GetType().FullName, exception.Message, exception.StackTrace); } } diff --git a/ScriptCore/Math/Math.cs b/ScriptCore/Math/Math.cs index df46de5..1a30266 100644 --- a/ScriptCore/Math/Math.cs +++ b/ScriptCore/Math/Math.cs @@ -152,16 +152,16 @@ public static partial class Math /// /// Splits the value x into fractional and integer parts, each of which has the same sign as x. /// - public static float modf(float x, out float integerPart) => ScriptGlue.modf_float(x, out integerPart); + public static float modf(float x, out float integerPart) => ScriptGlue.Math_ModfFloat(x, out integerPart); /// - public static float2 modf(float2 x, out float2 integerPart) => ScriptGlue.modf_float2(x, out integerPart); + public static float2 modf(float2 x, out float2 integerPart) => ScriptGlue.Math_ModfFloat2(x, out integerPart); /// - public static float3 modf(float3 x, out float3 integerPart) => ScriptGlue.modf_float3(x, out integerPart); + public static float3 modf(float3 x, out float3 integerPart) => ScriptGlue.Math_ModfFloat3(x, out integerPart); /// - public static float4 modf(float4 x, out float4 integerPart) => ScriptGlue.modf_float4(x, out integerPart); + public static float4 modf(float4 x, out float4 integerPart) => ScriptGlue.Math_ModfFloat4(x, out integerPart); /// /// Returns the fractional (or decimal) part of x; which is greater than or equal to 0 and less than 1. diff --git a/ScriptCore/Properties/launchSettings.json b/ScriptCore/Properties/launchSettings.json new file mode 100644 index 0000000..92a3a14 --- /dev/null +++ b/ScriptCore/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "Start Editor": { + "commandName": "Executable", + "executablePath": "..\\build\\Debug_Win64\\GlitchyEditor\\GlitchyEditor.exe", + "commandLineArgs": "\"D:\\Development\\Git\\SingleStateToOrbit\"", + "workingDirectory": "..\\GlitchyEditor", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/ScriptCore/ScriptGlue.cs b/ScriptCore/ScriptGlue.cs index db031b6..5bdbf4e 100644 --- a/ScriptCore/ScriptGlue.cs +++ b/ScriptCore/ScriptGlue.cs @@ -26,24 +26,31 @@ namespace GlitchyEngine; [StructLayout(LayoutKind.Sequential)] internal unsafe partial struct EngineFunctions { - //public delegate* unmanaged[Cdecl] Log_LogMessage; } /// /// All methods in here are glued to the ScriptGlue.bf in the engine. -/// TODO: This could be auto-generated fairly easily /// internal static unsafe partial class ScriptGlue { #region Script Glueing infrastructure static ScriptGlue() + { + ConfigureDllImportResolver(); + } + + private static void ConfigureDllImportResolver() { NativeLibrary.SetDllImportResolver(typeof(ScriptGlue).Assembly, ImportResolver); // TODO: With this we can actually use the official ImGui.NET-Branch in the future! NativeLibrary.SetDllImportResolver(typeof(ImGui).Assembly, ImportResolver); } + /// + /// Resolves an import request for the DLL __Internal ([DllImport("__Internal")]) to the current executable file. + /// This allows calling functions that are part of the native executable (e.g. native libraries we want to use from C# scripts). + /// private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) { if (libraryName == "__Internal") @@ -59,24 +66,34 @@ internal static unsafe partial class ScriptGlue return IntPtr.Zero; } - - private static EngineFunctions _engineFunctions; + + private static AssemblyLoadContext? _scriptAssemblyContext; + private static Assembly? _appAssembly; + + /// + /// Entity script instances + /// + private static readonly Dictionary EntityScriptInstances = new(); + + /// + /// Called by the engine to provide a struct containing all functions pointers that can be called from C## + /// + /// The struct containing the function pointers to the engine functions. [UnmanagedCallersOnly] - public static unsafe void SetEngineFunctions(EngineFunctions* engineFunctions) + public static void SetEngineFunctions(EngineFunctions* engineFunctions) { _engineFunctions = *engineFunctions; Log.Info("Yeah"); } - private static AssemblyLoadContext? _scriptAssemblyContext; - - private static Assembly? _appAssembly; - + /// + /// Called by the engine to load the provided assembly (containing user scripts) and optionally debug symbols. + /// [UnmanagedCallersOnly] - public static unsafe void LoadScriptAssembly(byte* assemblyData, long assemblyLength, byte* pdbData, long pdbLength) + public static void LoadScriptAssembly(byte* assemblyData, long assemblyLength, byte* pdbData, long pdbLength) { using UnmanagedMemoryStream assemblyStream = new(assemblyData, assemblyLength); @@ -100,7 +117,10 @@ internal static unsafe partial class ScriptGlue Console.WriteLine($"Fehler: {e}"); } } - + + /// + /// Called by the engine to unload the assembly (containing user scripts). + /// [UnmanagedCallersOnly] public static void UnloadAssemblies() { @@ -108,15 +128,9 @@ internal static unsafe partial class ScriptGlue _scriptAssemblyContext = null; } - struct ScriptClassInfo - { - public byte[] Name; - public Guid Guid; - } - private static NativeScriptClassInfo[]? _unsafeClasses; - struct NativeScriptClassInfo + public struct NativeScriptClassInfo { public IntPtr Name; public Guid Guid; @@ -133,8 +147,16 @@ internal static unsafe partial class ScriptGlue OnDestroy = 0x4 } + /// + /// Called by the engine to receive a list of all script classes. + /// + /// Pointer to the array of s + /// The number of elements in + /// + /// The array returned by must be freed using . + /// [UnmanagedCallersOnly] - public static unsafe void GetScriptClasses(void** outBuffer, long* length) + public static void GetScriptClasses(NativeScriptClassInfo** outBuffer, long* length) { using var contextualReflection = AssemblyLoadContext.EnterContextualReflection(_appAssembly); @@ -189,17 +211,20 @@ internal static unsafe partial class ScriptGlue }; } - *outBuffer = (void*)Marshal.UnsafeAddrOfPinnedArrayElement(_unsafeClasses, 0); + *outBuffer = (NativeScriptClassInfo*)Marshal.UnsafeAddrOfPinnedArrayElement(_unsafeClasses, 0); *length = _unsafeClasses.Length; } + /// + /// Called by the engine to free the data allocated by + /// [UnmanagedCallersOnly] public static void FreeScriptClassNames() { Internal_FreeScriptClassNames(); } - internal static void Internal_FreeScriptClassNames() + private static void Internal_FreeScriptClassNames() { if (_unsafeClasses == null) return; @@ -212,13 +237,19 @@ internal static unsafe partial class ScriptGlue _unsafeClasses = null; } - private static Dictionary _entityScripts = new(); - [UnmanagedCallersOnly] public static void ShowEntityEditor(UUID entityId) { - (Entity entity, Type type) = _entityScripts[entityId]; - EntityEditor.ShowEntityEditor(entity); + try + { + (Entity entity, Type type) = EntityScriptInstances[entityId]; + EntityEditor.ShowEntityEditor(entity); + } + catch (Exception e) + { + Console.WriteLine(e); + // TODO: Log exceptions to console + } } [UnmanagedCallersOnly] @@ -226,7 +257,7 @@ internal static unsafe partial class ScriptGlue { try { - (Entity entity, Type type) = _entityScripts[entityId]; + (Entity entity, Type type) = EntityScriptInstances[entityId]; entity.OnCreate(); } catch (Exception e) @@ -241,19 +272,19 @@ internal static unsafe partial class ScriptGlue { // using var _ = AssemblyLoadContext.EnterContextualReflection(_appAssembly); // TODO: Check if reflection works correctly in entities - (Entity entity, Type type) = _entityScripts[entityId]; + (Entity entity, Type type) = EntityScriptInstances[entityId]; entity.OnUpdate(deltaTime); } [UnmanagedCallersOnly] public static void InvokeEntityOnDestroy(UUID entityId, float deltaTime) { - (Entity entity, Type type) = _entityScripts[entityId]; + (Entity entity, Type type) = EntityScriptInstances[entityId]; entity.OnDestroy(); } [UnmanagedCallersOnly] - public static unsafe void CreateScriptInstance(UUID entityId, byte* scriptClassName) + public static void CreateScriptInstance(UUID entityId, byte* scriptClassName) { using var _ = AssemblyLoadContext.EnterContextualReflection(_appAssembly); @@ -269,212 +300,104 @@ internal static unsafe partial class ScriptGlue Entity? scriptInstance = ActivatorExtension.CreateEngineObject(scriptType, entityId) as Entity; - // - // // Get the constructor - // ConstructorInfo? constructor = scriptType.GetConstructor( - // BindingFlags.Instance | BindingFlags.Public, - // null, - // [], - // null); - // - // Debug.Assert(constructor != null, "Script class constructor not found."); - // - // // Call the constructor to create an instance - // Entity? scriptInstance = constructor?.Invoke(null) as Entity; Debug.Assert(scriptInstance != null, "Failed to create script instance."); - // - // if (scriptInstance != null) - // scriptInstance._uuid = entityId; - //ScriptFunctions functions = new(); - - _entityScripts.Add(entityId, (scriptInstance!, scriptType)); - - //MethodInfo? onCreateMethod = scriptType.GetMethod("OnCreate", BindingFlags.Instance | BindingFlags.NonPublic); - //if (onCreateMethod != null) - //{ - // var v = MethodHelpers.GetFunctionPointerForNativeCode(onCreateMethod, null); - //} - //if (onCreateMethod != null) - //{ - // //Delegate del = CreateDelegateWithTarget(onCreateMethod, scriptInstance); - - // //var createDelegate = onCreateMethod.CreateDelegate(scriptInstance); - // //var createDelegate = onCreateMethod.CreateDelegate(typeof(OnCreateMethodDelegate), scriptInstance); - // //onCreateMethod.CreateDelegate(scriptInstance); - - // //functions.OnCreateMethod = Marshal.GetFunctionPointerForDelegate(createDelegate); - //} - // - // MethodInfo? onUpdateMethod = scriptType.GetMethod("OnUpdate", BindingFlags.Instance | BindingFlags.NonPublic); - // if (onUpdateMethod != null) - // { - // // Create the delegate from your method and instance - // OnUpdateMethodDelegate onUpdateDelegate = (OnUpdateMethodDelegate)Delegate.CreateDelegate(typeof(OnUpdateMethodDelegate), scriptInstance, onUpdateMethod); - // - // // Get the function pointer from your delegate - // functions.OnUpdateMethod = Marshal.GetFunctionPointerForDelegate(onUpdateDelegate); - // } - - - //functions.OnUpdateMethod = Marshal.GetFunctionPointerForDelegate((float deltaTime) => onUpdateMethod.Invoke(scriptInstance, new object?[]{ deltaTime })); - - //MethodInfo? onDestroyMethod = scriptType.GetMethod("OnUpdate", BindingFlags.Instance | BindingFlags.NonPublic); - //if (onDestroyMethod != null) - // functions.OnDestroyMethod = Marshal.GetFunctionPointerForDelegate(() => onDestroyMethod.Invoke(scriptInstance, null)); - - //return functions; + EntityScriptInstances.Add(entityId, (scriptInstance!, scriptType)); } - static Delegate CreateDelegate(MethodInfo method) + struct ComponentFunctionPointers { - if (method == null) - { - throw new ArgumentNullException(nameof(method)); - } - - if (!method.IsStatic) - { - throw new ArgumentException("The provided method must be static.", nameof(method)); - } - - if (method.IsGenericMethod) - { - throw new ArgumentException("The provided method must not be generic.", nameof(method)); - } - - return method.CreateDelegate(Expression.GetDelegateType( - (from parameter in method.GetParameters() select parameter.ParameterType) - .Concat(new[] { method.ReturnType }) - .ToArray())); + public delegate* unmanaged[Cdecl] AddComponent; + public delegate* unmanaged[Cdecl] HasComponent; + public delegate* unmanaged[Cdecl] RemoveComponent; } - /// - /// Create delegate by methodinfo in target - /// - /// method info - /// A instance of the object which contains the method where will be execute - /// delegate or null - public static Delegate? CreateDelegateWithTarget(MethodInfo? method, object? target) + private static readonly Dictionary ComponentTypeFunctions = new(); + + [UnmanagedCallersOnly] + public static void RegisterComponentType(byte* fullComponentTypeName, + delegate* unmanaged[Cdecl] addComponent, + delegate* unmanaged[Cdecl] hasComponent, + delegate* unmanaged[Cdecl] removeComponent) { - if (method is null || - target is null) - return null; + string? beefComponentTypeName = Marshal.PtrToStringUTF8((IntPtr)fullComponentTypeName); - //if (method.IsStatic) - // return null; + if (beefComponentTypeName == null) + return; - if (method.IsGenericMethod) - return null; - - return method.CreateDelegate(Expression.GetDelegateType( - (from parameter in method.GetParameters() select parameter.ParameterType) - .Concat(new[] { method.ReturnType }) - .ToArray()), target); - } - - internal static class MethodHelpers - { - private const string DelegateTypesAssemblyName = "JitDelegateTypes"; - - private static ModuleBuilder _modBuilder; - - private static ConcurrentDictionary<(string, object), Delegate> _delegatesCache; - private static ConcurrentDictionary _delegateTypesCache; - - static MethodHelpers() + foreach(Type componentType in TypeExtension.FindDerivedTypes(typeof(Component))) { - AssemblyBuilder asmBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(DelegateTypesAssemblyName), AssemblyBuilderAccess.Run); - - _modBuilder = asmBuilder.DefineDynamicModule(DelegateTypesAssemblyName); - - _delegatesCache = new ConcurrentDictionary<(string, object), Delegate>(); - _delegateTypesCache = new ConcurrentDictionary(); - } - - public static IntPtr GetFunctionPointerForNativeCode(MethodInfo meth, object instance = null) - { - string funcName = GetFullName(meth); - - Delegate dlg = _delegatesCache.GetOrAdd((funcName, instance), (_) => + if (!componentType.TryGetCustomAttribute(out EngineClassAttribute mapping) || + mapping.EngineClassName != beefComponentTypeName) continue; + + ComponentTypeFunctions[componentType] = new ComponentFunctionPointers { - Type[] parameters = meth.GetParameters().Select(x => x.ParameterType).ToArray(); + AddComponent = addComponent, + HasComponent = hasComponent, + RemoveComponent = removeComponent + }; - Type delegateType = GetDelegateType(parameters, meth.ReturnType); - - return Delegate.CreateDelegate(delegateType, instance, meth); - }); - - return Marshal.GetFunctionPointerForDelegate(dlg); - } - - private static string GetFullName(MethodInfo meth) - { - return $"{meth.DeclaringType.FullName}.{meth.Name}"; - } - - private static Type GetDelegateType(Type[] parameters, Type returnType) - { - string key = GetFunctionSignatureKey(parameters, returnType); - - return _delegateTypesCache.GetOrAdd(key, (_) => MakeDelegateType(parameters, returnType, key)); - } - - private const MethodAttributes CtorAttributes = - MethodAttributes.RTSpecialName | - MethodAttributes.HideBySig | - MethodAttributes.Public; - - private const MethodImplAttributes ImplAttributes = - MethodImplAttributes.Runtime | - MethodImplAttributes.Managed; - - private const MethodAttributes InvokeAttributes = - MethodAttributes.Public | - MethodAttributes.HideBySig | - MethodAttributes.NewSlot | - MethodAttributes.Virtual; - - private const TypeAttributes DelegateTypeAttributes = - TypeAttributes.Class | - TypeAttributes.Public | - TypeAttributes.Sealed | - TypeAttributes.AnsiClass | - TypeAttributes.AutoClass; - - private static readonly Type[] _delegateCtorSignature = { typeof(object), typeof(IntPtr) }; - - private static Type MakeDelegateType(Type[] parameters, Type returnType, string name) - { - TypeBuilder builder = _modBuilder.DefineType(name, DelegateTypeAttributes, typeof(MulticastDelegate)); - - builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, _delegateCtorSignature).SetImplementationFlags(ImplAttributes); - - builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes); - - return builder.CreateTypeInfo(); - } - - private static string GetFunctionSignatureKey(Type[] parameters, Type returnType) - { - string sig = GetTypeName(returnType); - - foreach (Type type in parameters) - { - sig += '_' + GetTypeName(type); - } - - return sig; - } - - private static string GetTypeName(Type type) - { - return type.FullName.Replace(".", string.Empty); + break; } } #endregion + + public static void Entity_AddComponent(UUID entityId, Type componentType) + { + ComponentTypeFunctions[componentType].AddComponent(entityId); + } + public static bool Entity_HasComponent(UUID entityId, Type componentType) + { + return ComponentTypeFunctions[componentType].HasComponent(entityId); + } + + public static void Entity_RemoveComponent(UUID entityId, Type componentType) + { + ComponentTypeFunctions[componentType].RemoveComponent(entityId); + } + + public static void Entity_GetScriptInstance(UUID entityId, out Entity? instance) + { + // We currently can implement this method here, because we only have C# scripts. + // If we ever need to do something to interop with other script languages, then this would change. + if (EntityScriptInstances.TryGetValue(entityId, out var match)) + { + instance = match.Entity; + } + + instance = null; + } + + public static void Serialization_SerializeField(IntPtr serializationContext, SerializationType type, string fieldName, object? valueObject, string fullTypeName) + { + byte* fieldNameConverted = (byte*)Marshal.StringToCoTaskMemUTF8(fieldName); + byte* fullTypeNameConverted = (byte*)Marshal.StringToCoTaskMemUTF8(fullTypeName); + + void* valueObjectConverted = null; + bool deleteValueObject = false; + + switch (type) + { + case SerializationType.String: + valueObjectConverted = (void*)Marshal.StringToCoTaskMemUTF8(fullTypeName); + deleteValueObject = true; + break; + default: + if (valueObject is not null) + valueObjectConverted = Unsafe.AsPointer(ref Unsafe.Unbox(valueObject)); + break; + } + + _engineFunctions.Serialization_SerializeField((void*)serializationContext, type, fieldNameConverted, valueObjectConverted, fullTypeNameConverted); + + Marshal.FreeCoTaskMem((IntPtr)fieldNameConverted); + Marshal.FreeCoTaskMem((IntPtr)fullTypeNameConverted); + + if (deleteValueObject) + Marshal.FreeCoTaskMem((IntPtr)valueObjectConverted); + } //#region Log diff --git a/ScriptCoreGenerator/ScriptGlueGenerator.cs b/ScriptCoreGenerator/ScriptGlueGenerator.cs index 46c88c5..337e351 100644 --- a/ScriptCoreGenerator/ScriptGlueGenerator.cs +++ b/ScriptCoreGenerator/ScriptGlueGenerator.cs @@ -100,6 +100,8 @@ public class ScriptGlueGenerator : IIncrementalGenerator public string? WrapperConvertInput; public string? WrapperCleanupInput; + public string? WrapperOutConversion; + public string? ReturnValueConversion = "return returnValue;"; public string CSharpWrapperType @@ -237,6 +239,17 @@ public class ScriptGlueGenerator : IIncrementalGenerator WrapperConvertInput = "fixed (char* {0} = {1}) {{", WrapperCleanupInput = "}}" }); + + beefTypeToMappedType.Add("char8*", new MappedType + { + BeefTypeName = "char8*", + CSharpTypeName = "byte*", + CSharpWrapperType = "string", + ReturnValueConversion = "return Marshal.PtrToStringUTF8((IntPtr)returnValue);", + WrapperConvertInput = "byte* {0} = (byte*)Marshal.StringToCoTaskMemUTF8({1});", + WrapperCleanupInput = "Marshal.FreeCoTaskMem((IntPtr){0});", + WrapperOutConversion = "{1} = Marshal.PtrToStringUTF8((IntPtr){0}) ?? \"\";" + }); beefTypeToMappedType.Add("int32", new MappedType { @@ -249,6 +262,16 @@ public class ScriptGlueGenerator : IIncrementalGenerator BeefTypeName = "System.Numerics.Quaternion", ReturnValueConversion = null }); + + beefTypeToMappedType.Add("void*", new MappedType + { + BeefTypeName = "void*", + CSharpTypeName = "void*", + CSharpWrapperType = "IntPtr", + ReturnValueConversion = "return (IntPtr)returnValue;", + WrapperConvertInput = "void* {0} = (void*){1};", + WrapperOutConversion = "{1} = (IntPtr){0};" + }); } private static void GenerateFunctionPointer(GlueMethod method, Dictionary beefTypeToMappedType, StringBuilder output) @@ -341,7 +364,17 @@ public class ScriptGlueGenerator : IIncrementalGenerator break; } - if (parameterType.WrapperConvertInput is not null) + if (parameterModifier == TypeModifier.Out && parameterType.WrapperOutConversion is not null) + { + string tmpArgName = $"{param.Name}Tmp"; + + call.Append($"var {tmpArgName}"); + + cleanup.Append("\t\t"); + cleanup.AppendFormat(parameterType.WrapperOutConversion, tmpArgName, param.Name); + cleanup.AppendLine(); + } + else if (parameterType.WrapperConvertInput is not null) { string convertedParamName = $"{param.Name}Converted"; @@ -422,7 +455,9 @@ public class ScriptGlueGenerator : IIncrementalGenerator wrappers.Append(""" // + using System; using System.Collections.Generic; + using System.Runtime.InteropServices; namespace GlitchyEngine;