From 1435dac4d67b5dc2af081414c27b382dafa3a1b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Thu, 3 Sep 2026 22:35:14 +0200 Subject: [PATCH] Fixed exception logging and entity id of messages --- .../src/EditWindows/EntityHierarchyWindow.bf | 2 + GlitchyEditor/src/EditWindows/LogWindow.bf | 45 +++++--- GlitchyEditor/src/EditorLogger.bf | 2 +- .../src/Extension/System/Collections/List.bf | 21 ++++ GlitchyEngine/src/Scripting/ScriptEngine.bf | 10 +- .../src/Scripting/ScriptException.bf | 97 +++++++++++++--- GlitchyEngine/src/Scripting/ScriptGlue.bf | 46 ++++++-- ScriptCore/Log.cs | 108 ++++++++++++++---- ScriptCore/ScriptGlue.cs | 45 ++++++++ ScriptCoreGenerator/ScriptGlueGenerator.cs | 27 ++++- 10 files changed, 331 insertions(+), 72 deletions(-) create mode 100644 GlitchyEngine/src/Extension/System/Collections/List.bf diff --git a/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf b/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf index b048a16..5a5ef0c 100644 --- a/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf +++ b/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf @@ -66,6 +66,8 @@ namespace GlitchyEditor.EditWindows { _entityToHighlight = e; + SelectEntity(e, true); + Entity walker = _entityToHighlight; while (walker.Parent != null) diff --git a/GlitchyEditor/src/EditWindows/LogWindow.bf b/GlitchyEditor/src/EditWindows/LogWindow.bf index 51e3a27..4c9f4a8 100644 --- a/GlitchyEditor/src/EditWindows/LogWindow.bf +++ b/GlitchyEditor/src/EditWindows/LogWindow.bf @@ -8,6 +8,7 @@ using GlitchyEngine.Scripting; using GlitchyEngine.Renderer; using GlitchyEngine; using GlitchyEditor.CodeEditors; +using System.IO; namespace GlitchyEditor.EditWindows; @@ -295,12 +296,30 @@ class LogWindow : EditorWindow { if (ImGui.CollapsingHeader(message.Message.Ptr)) { - // Show the native to managed entry point only if we show engine messages + String lineBuffer = scope .(); + for (StackFrameInfo frameInfo in message.Source.Exception.StackTrace.Frames) + { + String relativeSourcePath = scope .(frameInfo.FileName); - if (_showEngineMessages) - ImGui.TextUnformatted(message.Source.Exception.StackTrace); - else - ImGui.TextUnformatted(message.Source.Exception.CleanStackTrace); + relativeSourcePath.Replace(Editor.Instance.ContentManager.ResourcesDirectory, "Resources"); + relativeSourcePath.Replace(Editor.Instance.ContentManager.AssetDirectory, "Assets"); + + //Path.GetRelativePath(frameInfo.FileName, Editor.Instance.CurrentProject.WorkspacePath, relativeSourcePath); + + StackFrameInfo sfi = scope .(relativeSourcePath, frameInfo.MethodSignature, frameInfo.Line, frameInfo.Column); + + //_editor.CurrentProject.PathInProject(); + + lineBuffer.Clear(); + lineBuffer.SetF($" {sfi}"); + + float width = ImGui.CalcTextSize(lineBuffer.CStr()).x; + if (ImGui.Selectable(lineBuffer, false, .None, .(width, 0))) + { + // TODO: Columns? + Editor.Instance.IdeAdapter.OpenScript(frameInfo.FileName, frameInfo.Line, frameInfo.Column); + } + } ImGui.NewLine(); } @@ -319,6 +338,13 @@ class LogWindow : EditorWindow { Editor.Instance.IdeAdapter.OpenScript(message.Source.MessageOrigin.FileName, message.Source.MessageOrigin.LineNumber); } + else if (message.Source.Exception != null) + { + // TODO: Column? + let firstFrame = message.Source.Exception.StackTrace.Frames[0]; + Editor.Instance.IdeAdapter.OpenScript(firstFrame.FileName, firstFrame.Line); + //message.Source.Exception.StackTrace + } } // Dont show the counter if we only have one message. @@ -373,15 +399,8 @@ class LogWindow : EditorWindow public void LogException(DateTime timestamp, ScriptException exception) { - StringView firstLine = exception.StackTrace; - - int firstInIndex = exception.StackTrace.IndexOf("\n"); - - if (firstInIndex != -1) - firstLine = firstLine.Substring(0, firstInIndex); - String message = scope .(128); - message.AppendF($"Exception: \"{exception.FullName}\" | Message: \"{exception.Message}\" {firstLine}\0"); + message.AppendF($"Exception: \"{exception.FullName}\" | Message: \"{exception.Message}\" {exception.StackTrace.Frames[0]}\0"); // TODO: are mono exceptions never engine only? LogMessage logMessage = new LogMessage(timestamp, message, .Error, new MessageSource(){Entity = exception.EntityId, Exception = exception, IsEngineMessage = false}); diff --git a/GlitchyEditor/src/EditorLogger.bf b/GlitchyEditor/src/EditorLogger.bf index 07acbcc..9e7f03b 100644 --- a/GlitchyEditor/src/EditorLogger.bf +++ b/GlitchyEditor/src/EditorLogger.bf @@ -139,7 +139,7 @@ public class EditorLogger : Logger } else if (args.Count > 0 && messageOrigin != null) { - Editor.Instance.LogWindow.Log(timestamp, level, message, new .() {IsEngineMessage = IsEngineLogger, MessageOrigin = new MessageOrigin(messageOrigin.FileName, messageOrigin.LineNumber)}); + Editor.Instance.LogWindow.Log(timestamp, level, message, new .() {Entity = (messageOrigin.EntityId != .Zero ? messageOrigin.EntityId : null), IsEngineMessage = IsEngineLogger, MessageOrigin = new MessageOrigin(messageOrigin.EntityId, messageOrigin.FileName, messageOrigin.CallerMemberName, messageOrigin.LineNumber, messageOrigin.ColumnNumber)}); } else { diff --git a/GlitchyEngine/src/Extension/System/Collections/List.bf b/GlitchyEngine/src/Extension/System/Collections/List.bf new file mode 100644 index 0000000..ba7dedd --- /dev/null +++ b/GlitchyEngine/src/Extension/System/Collections/List.bf @@ -0,0 +1,21 @@ +namespace System.Collections; + +extension List +{ + public bool Equals(List other) + { + if (this === other) + return true; + + if (this.Count != other.Count) + return false; + + for (int i < this.Count) + { + if (this[i] != other[i]) + return false; + } + + return true; + } +} diff --git a/GlitchyEngine/src/Scripting/ScriptEngine.bf b/GlitchyEngine/src/Scripting/ScriptEngine.bf index 38a4c36..d5b1811 100644 --- a/GlitchyEngine/src/Scripting/ScriptEngine.bf +++ b/GlitchyEngine/src/Scripting/ScriptEngine.bf @@ -492,19 +492,17 @@ static class ScriptEngine return scriptClass; } - internal static void LogScriptException(ScriptException exception, UUID entityId) + internal static void LogScriptException(ScriptException exception) { String entityInfo = scope .(); - if (entityId != .Zero && Context != null) + if (exception.EntityId != .Zero && Context != null) { - exception.EntityId = entityId; - - Result sourceEntity = Context.GetEntityByID(entityId); + Result sourceEntity = Context.GetEntityByID(exception.EntityId); if (sourceEntity case .Ok(let e)) { - entityInfo.AppendF($" ({e.Name} | {entityId})"); + entityInfo.AppendF($" ({e.Name} | {exception.EntityId})"); } } diff --git a/GlitchyEngine/src/Scripting/ScriptException.bf b/GlitchyEngine/src/Scripting/ScriptException.bf index ce0b45d..eb9f34f 100644 --- a/GlitchyEngine/src/Scripting/ScriptException.bf +++ b/GlitchyEngine/src/Scripting/ScriptException.bf @@ -1,44 +1,107 @@ using System; using GlitchyEngine.Core; +using System.Collections; namespace GlitchyEngine.Scripting; - public class ScriptException { private String _fullName ~ delete:append _; private String _message ~ delete:append _; - 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; - - //TODO - //private ScriptException _innerException ~ _?.ReleaseRef(); + private StackTrace _stackTrace ~ delete _; public StringView FullName => _fullName; public StringView Message => _message; - public StringView StackTrace => _stackTrace; - public StringView CleanStackTrace => _cleanStackTrace; + public StackTrace StackTrace => _stackTrace; - //public ScriptException InnerException => _innerException; - - public UUID EntityId { get; set; } + public UUID EntityId { get; private set; } [AllowAppend] - public this(UUID entityId, StringView fullExceptionClassName, StringView message, StringView stackTrace) + public this(UUID entityId, StringView fullExceptionClassName, StringView message, StackTrace ownStackTrace) { String allocFullExceptionClassName = append String(fullExceptionClassName); String allocMessage = append String(message); - String allocStackTrace = append String(stackTrace); + + EntityId = entityId; + + _stackTrace = ownStackTrace; _fullName = allocFullExceptionClassName; _message = allocMessage; - _stackTrace = allocStackTrace; + } +} - // TODO - _cleanStackTrace = _stackTrace; +public class StackFrameInfo +{ + private String _fileName ~ delete:append _; + private String _methodSignature ~ delete:append _; + public int Line; + public int Column; + + public StringView FileName => _fileName; + + public StringView MethodSignature => _methodSignature; + + [AllowAppend] + public this(StringView fileName, StringView methodSignature, int line, int column) + { + String allocFileName = append String(fileName); + String allocMethodSignature = append String(methodSignature); + + _fileName = allocFileName; + _methodSignature = allocMethodSignature; + + Line = line; + Column = column; + } + + public override void ToString(String outBuffer) + { + outBuffer.Append("at "); + + if (MethodSignature.IsEmpty) + outBuffer.Append(""); + else + outBuffer.Append(MethodSignature); + + outBuffer.Append(" in "); + + if (!_fileName.IsEmpty) + outBuffer.AppendF($"{FileName}, line {Line}:{Column}"); + else + outBuffer.Append(""); + } +} + +public class StackTrace +{ + private List _stackFrameInfos ~ DeleteContainerAndItems!(_); + + public Span Frames => _stackFrameInfos; + + public this(List ownStackFrameInfos) + { + _stackFrameInfos = ownStackFrameInfos; + } + + [Commutable] + public static bool operator ==(StackTrace a, StackTrace b) + { + if (a == null || b == null) + return a === b; + + return a._stackFrameInfos.Equals(b._stackFrameInfos); + } + + public override void ToString(String outBuffer) + { + for (let frame in _stackFrameInfos) + { + frame.ToString(outBuffer); + outBuffer.Append('\n'); + } } } diff --git a/GlitchyEngine/src/Scripting/ScriptGlue.bf b/GlitchyEngine/src/Scripting/ScriptGlue.bf index 4f0adcc..00ee040 100644 --- a/GlitchyEngine/src/Scripting/ScriptGlue.bf +++ b/GlitchyEngine/src/Scripting/ScriptGlue.bf @@ -28,19 +28,29 @@ using internal GlitchyEngine.Content; // TODO: Move to logger? class MessageOrigin { + private UUID _entityId; private String _fileName ~ delete:append _; + private String _callerMemberName ~ delete:append _; private int _lineNumber; + private int _columnNumber; + public UUID EntityId => _entityId; public StringView FileName => _fileName; + public StringView CallerMemberName => _callerMemberName; public int LineNumber => _lineNumber; + public int ColumnNumber => _columnNumber; [AllowAppend] - public this(StringView fileName, int lineNumber) + public this(UUID entityId, StringView fileName, StringView callerMemberName, int lineNumber, int columnNumber) { String file = append String(fileName); + String caller = append String(callerMemberName); + _entityId = entityId; _fileName = file; + _callerMemberName = caller; _lineNumber = lineNumber; + _columnNumber = columnNumber; } } @@ -445,7 +455,7 @@ static class ScriptGlue #region Log [RegisterCall, CallingConvention(.Cdecl)] - static void Log_LogMessage(LogLevel logLevel, StringView messagePtr, StringView fileNamePtr, int lineNumber) + static void Log_LogMessage(LogLevel logLevel, UUID entityId, StringView messagePtr, StringView fileNamePtr, StringView callerMemberNamePtr, int lineNumber, int columnNumber) { String escapedMessage = new:ScopedAlloc! String(messagePtr); @@ -455,9 +465,7 @@ static class ScriptGlue if (!fileNamePtr.IsEmpty) { - String fileName = new:ScopedAlloc! String(fileNamePtr); - - MessageOrigin messageOrigin = scope MessageOrigin(fileName, lineNumber); + MessageOrigin messageOrigin = scope MessageOrigin(entityId, fileNamePtr, callerMemberNamePtr, lineNumber, columnNumber); Log.ClientLogger.Log((LogLevel)logLevel, escapedMessage, messageOrigin); } @@ -467,11 +475,27 @@ static class ScriptGlue } } - [RegisterCall, CallingConvention(.Cdecl)] - static void Log_LogException(UUID entityId, StringView fullExceptionClassName, StringView exceptionMessage, StringView stackTrace) + [Ordered] + public struct GlueStackFrameInfo { - ScriptException exception = new ScriptException(entityId, fullExceptionClassName, exceptionMessage, stackTrace); - ScriptEngine.LogScriptException(exception, entityId); + public StringView FileName; + public StringView MethodSignature; + public int32 Line; + public int32 Column; + } + + [RegisterCall, CallingConvention(.Cdecl)] + static void Log_LogException(UUID entityId, StringView fullExceptionClassName, StringView exceptionMessage, GlueStackFrameInfo* stackFrameInfos, int32 stackFrameCount) + { + List frames = new .(stackFrameCount); + + for (GlueStackFrameInfo frameInfo in Span(stackFrameInfos, stackFrameCount)) + { + frames.Add(new StackFrameInfo(frameInfo.FileName, frameInfo.MethodSignature, frameInfo.Line, frameInfo.Column)); + } + + ScriptException exception = new ScriptException(entityId, fullExceptionClassName, exceptionMessage, new StackTrace(frames)); + ScriptEngine.LogScriptException(exception); } #endregion @@ -642,7 +666,7 @@ static class ScriptGlue #endregion -#region TransformComponen +#region TransformComponent [RegisterCall, CallingConvention(.Cdecl)] static EngineResult Transform_GetParent(UUID entityId, out UUID parentId) @@ -966,7 +990,7 @@ static class ScriptGlue #endregion Rigidbody2D -#region Camer +#region Camera [RegisterCall, CallingConvention(.Cdecl)] static void Camera_GetProjectionType(UUID entityId, out SceneCamera.ProjectionType projectionType) diff --git a/ScriptCore/Log.cs b/ScriptCore/Log.cs index c510efe..8c301e1 100644 --- a/ScriptCore/Log.cs +++ b/ScriptCore/Log.cs @@ -1,7 +1,11 @@ +using GlitchyEngine.Core; using System; using System.Diagnostics; +using System.Linq; +using System.Reflection; using System.Runtime.CompilerServices; -using GlitchyEngine.Core; +using System.Runtime.InteropServices; +using static GlitchyEngine.Log; namespace GlitchyEngine; @@ -31,9 +35,10 @@ public class Log /// The message to log. /// File path of the caller. /// Line number of the caller. - public static void Trace(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Trace(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Trace, message, callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Trace, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -42,9 +47,10 @@ public class Log /// The message to log. /// File path of the caller. /// Line number of the caller. - public static void Info(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Info(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Info, message, callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Info, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -53,9 +59,10 @@ public class Log /// The message to log. /// File path of the caller. /// Line number of the caller. - public static void Warning(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Warning(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Warning, message, callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Warning, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -64,9 +71,10 @@ public class Log /// The message to log. /// File path of the caller. /// Line number of the caller. - public static void Error(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Error(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Error, message, callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Error, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -75,9 +83,10 @@ public class Log /// The message to log. /// File path of the caller. /// Line number of the caller. - public static void Critical(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Critical(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Critical, message, callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Critical, ScriptGlue.CurrentEntityId, message, callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -86,9 +95,10 @@ public class Log /// The object to serialize. /// File path of the caller. /// Line number of the caller. - public static void Trace(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Trace(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Trace, obj.ToString(), callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Trace, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -97,9 +107,10 @@ public class Log /// The object to serialize. /// File path of the caller. /// Line number of the caller. - public static void Info(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Info(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Info, obj.ToString(), callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Info, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -108,9 +119,10 @@ public class Log /// The object to serialize. /// File path of the caller. /// Line number of the caller. - public static void Warning(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Warning(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Warning, obj.ToString(), callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Warning, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -119,9 +131,10 @@ public class Log /// The object to serialize. /// File path of the caller. /// Line number of the caller. - public static void Error(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Error(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Error, obj.ToString(), callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Error, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0); } /// @@ -130,9 +143,30 @@ public class Log /// The object to serialize. /// File path of the caller. /// Line number of the caller. - public static void Critical(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) + /// Name of the calling member. + public static void Critical(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0, [CallerMemberName]string callerMemberName = "") { - ScriptGlue.Log_LogMessage(LogLevel.Critical, obj.ToString(), callerFilePath, callerLineNumber); + ScriptGlue.Log_LogMessage(LogLevel.Critical, ScriptGlue.CurrentEntityId, obj.ToString(), callerFilePath, callerMemberName, callerLineNumber, 0); + } + + [DebuggerDisplay("{ToString(),raw}")] + [StructLayout(LayoutKind.Sequential, Pack = 0)] + [EngineClass("GlitchyEngine.Scripting.ScriptGlue.GlueStackFrameInfo")] + internal struct StackFrameInfo + { + public Native.StringView FileName; + public Native.StringView MethodSignature; + public int LineNumber; + public int ColumnNumber; + } + + static string GetFullSignature(MethodBase method) + { + var typeName = method.DeclaringType?.FullName ?? ""; + var parameters = string.Join(", ", + method.GetParameters().Select(p => $"{p.ParameterType.Name}")); + + return $"{typeName}.{method.Name}({parameters})"; } /// @@ -141,6 +175,36 @@ public class Log /// The exception to log. public static void Exception(Exception exception) { - ScriptGlue.Log_LogException(UUID.Zero, exception.GetType().FullName, exception.Message, exception.StackTrace); + StackTrace st = new StackTrace(exception, true); + StackFrame[] frames = st.GetFrames(); + + StackFrameInfo[] stackFrameInfos = new StackFrameInfo[frames.Length]; + + // We only need StackFrameInfo for exception logging, so it's okay to manually handle the marshalling here. + foreach (StackFrame stackFrame in frames) + { + MethodBase? method = stackFrame.GetMethod(); + string methodSignature = method != null ? GetFullSignature(method) : ""; + stackFrameInfos[frames.IndexOf(stackFrame)] = new StackFrameInfo + { + FileName = Native.StringView.FromManagedString(stackFrame.GetFileName()), + MethodSignature = Native.StringView.FromManagedString(methodSignature), + LineNumber = stackFrame.GetFileLineNumber(), + ColumnNumber = stackFrame.GetFileColumnNumber() + }; + } + + unsafe + { + fixed (StackFrameInfo* stackFrames = stackFrameInfos) + { + ScriptGlue.Log_LogException(ScriptGlue.CurrentEntityId, exception.GetType().FullName, exception.Message, stackFrames, stackFrameInfos.Length); + } + } + + foreach (StackFrameInfo stackFrameInfo in stackFrameInfos) + { + Native.StringView.FreeNativeMemory(stackFrameInfo.FileName); + } } } diff --git a/ScriptCore/ScriptGlue.cs b/ScriptCore/ScriptGlue.cs index 7dcd7d0..b486cfe 100644 --- a/ScriptCore/ScriptGlue.cs +++ b/ScriptCore/ScriptGlue.cs @@ -14,6 +14,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Loader; using System.Text; +using System.Threading; namespace GlitchyEngine; @@ -272,11 +273,16 @@ internal static unsafe partial class ScriptGlue _unsafeClasses = null; } + private static readonly AsyncLocal _currentEntityId = new (); + + internal static UUID CurrentEntityId => _currentEntityId.Value; + [UnmanagedCallersOnly] public static void ShowEntityEditor(UUID entityId) { try { + _currentEntityId.Value = entityId; (Entity entity, Type type) = EntityScriptInstances[entityId]; EntityEditor.ShowEntityEditor(entity); } @@ -284,6 +290,10 @@ internal static unsafe partial class ScriptGlue { Log.Exception(e); } + finally + { + _currentEntityId.Value = UUID.Zero; + } } [UnmanagedCallersOnly] @@ -291,6 +301,7 @@ internal static unsafe partial class ScriptGlue { try { + _currentEntityId.Value = entityId; (Entity entity, Type type) = EntityScriptInstances[entityId]; entity.OnCreate(); } @@ -298,6 +309,10 @@ internal static unsafe partial class ScriptGlue { Log.Exception(e); } + finally + { + _currentEntityId.Value = UUID.Zero; + } } [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] @@ -305,6 +320,7 @@ internal static unsafe partial class ScriptGlue { try { + _currentEntityId.Value = entityId; (Entity entity, Type type) = EntityScriptInstances[entityId]; entity.OnUpdate(deltaTime); } @@ -312,6 +328,10 @@ internal static unsafe partial class ScriptGlue { Log.Exception(e); } + finally + { + _currentEntityId.Value = UUID.Zero; + } } [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] @@ -319,6 +339,7 @@ internal static unsafe partial class ScriptGlue { try { + _currentEntityId.Value = entityId; (Entity entity, Type type) = EntityScriptInstances[entityId]; entity.OnCollisionEnter2D(collision); } @@ -326,6 +347,10 @@ internal static unsafe partial class ScriptGlue { Log.Exception(e); } + finally + { + _currentEntityId.Value = UUID.Zero; + } } [UnmanagedCallersOnly] @@ -333,6 +358,7 @@ internal static unsafe partial class ScriptGlue { try { + _currentEntityId.Value = entityId; if (EntityScriptInstances.Remove(entityId, out var match) && callDestroy > 0) { match.Entity.OnDestroy(); @@ -342,6 +368,10 @@ internal static unsafe partial class ScriptGlue { Log.Exception(e); } + finally + { + _currentEntityId.Value = UUID.Zero; + } } internal static Type? GetTypeFromNativeString(byte* fullTypeName) @@ -365,6 +395,7 @@ internal static unsafe partial class ScriptGlue { try { + _currentEntityId.Value = entityId; Type? scriptType = GetTypeFromNativeString(scriptClassName); Debug.Assert(scriptType != null, "Script class Type not found."); @@ -379,6 +410,10 @@ internal static unsafe partial class ScriptGlue { Log.Exception(e); } + finally + { + _currentEntityId.Value = UUID.Zero; + } } struct ComponentFunctionPointers @@ -459,6 +494,7 @@ internal static unsafe partial class ScriptGlue { try { + _currentEntityId.Value = entityId; if (!EntityScriptInstances.TryGetValue(entityId, out var match)) return; @@ -468,6 +504,10 @@ internal static unsafe partial class ScriptGlue { Log.Exception(e); } + finally + { + _currentEntityId.Value = UUID.Zero; + } } [UnmanagedCallersOnly] @@ -475,6 +515,7 @@ internal static unsafe partial class ScriptGlue { try { + _currentEntityId.Value = entityId; if (!EntityScriptInstances.TryGetValue(entityId, out var match)) return; @@ -484,6 +525,10 @@ internal static unsafe partial class ScriptGlue { Log.Exception(e); } + finally + { + _currentEntityId.Value = UUID.Zero; + } } [UnmanagedCallersOnly] diff --git a/ScriptCoreGenerator/ScriptGlueGenerator.cs b/ScriptCoreGenerator/ScriptGlueGenerator.cs index 0814cd0..1dd87e7 100644 --- a/ScriptCoreGenerator/ScriptGlueGenerator.cs +++ b/ScriptCoreGenerator/ScriptGlueGenerator.cs @@ -122,7 +122,8 @@ public class ScriptGlueGenerator : IIncrementalGenerator None, Ref, In, - Out + Out, + Pointer } private static (MappedType Type, TypeModifier Modifier) DecodeType(string beefType, Dictionary beefTypeToMappedType) @@ -145,6 +146,15 @@ public class ScriptGlueGenerator : IIncrementalGenerator beefType = beefType.Substring(3); } + if (beefTypeToMappedType.TryGetValue(beefType, out var mapping)) + return (mapping, modifier); + + if (beefType.EndsWith("*")) + { + modifier = TypeModifier.Pointer; + beefType = beefType.Substring(0, beefType.Length - 1); + } + if (beefTypeToMappedType.TryGetValue(beefType, out MappedType? mappedType)) { return (mappedType, modifier); @@ -296,6 +306,14 @@ public class ScriptGlueGenerator : IIncrementalGenerator } parameterText.Append(parameterType.CSharpTypeName); + + switch (parameterModifier) + { + case TypeModifier.Pointer: + parameterText.Append("*"); + break; + } + parameterText.Append(", "); } @@ -345,7 +363,12 @@ public class ScriptGlueGenerator : IIncrementalGenerator break; } - parameterText.Append($"{parameterType.CSharpWrapperType} {param.Name}"); + parameterText.Append($"{parameterType.CSharpWrapperType}"); + + if (parameterModifier == TypeModifier.Pointer) + parameterText.Append("*"); + + parameterText.Append($" {param.Name}"); switch (parameterModifier) {