Fixed exception logging and entity id of messages

This commit is contained in:
Simon Lübeß
2026-09-03 22:35:14 +02:00
parent abf7a01917
commit 1435dac4d6
10 changed files with 331 additions and 72 deletions
@@ -66,6 +66,8 @@ namespace GlitchyEditor.EditWindows
{ {
_entityToHighlight = e; _entityToHighlight = e;
SelectEntity(e, true);
Entity walker = _entityToHighlight; Entity walker = _entityToHighlight;
while (walker.Parent != null) while (walker.Parent != null)
+32 -13
View File
@@ -8,6 +8,7 @@ using GlitchyEngine.Scripting;
using GlitchyEngine.Renderer; using GlitchyEngine.Renderer;
using GlitchyEngine; using GlitchyEngine;
using GlitchyEditor.CodeEditors; using GlitchyEditor.CodeEditors;
using System.IO;
namespace GlitchyEditor.EditWindows; namespace GlitchyEditor.EditWindows;
@@ -295,12 +296,30 @@ class LogWindow : EditorWindow
{ {
if (ImGui.CollapsingHeader(message.Message.Ptr)) 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) relativeSourcePath.Replace(Editor.Instance.ContentManager.ResourcesDirectory, "Resources");
ImGui.TextUnformatted(message.Source.Exception.StackTrace); relativeSourcePath.Replace(Editor.Instance.ContentManager.AssetDirectory, "Assets");
else
ImGui.TextUnformatted(message.Source.Exception.CleanStackTrace); //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(); ImGui.NewLine();
} }
@@ -319,6 +338,13 @@ class LogWindow : EditorWindow
{ {
Editor.Instance.IdeAdapter.OpenScript(message.Source.MessageOrigin.FileName, message.Source.MessageOrigin.LineNumber); 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. // Dont show the counter if we only have one message.
@@ -373,15 +399,8 @@ class LogWindow : EditorWindow
public void LogException(DateTime timestamp, ScriptException exception) 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); 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? // TODO: are mono exceptions never engine only?
LogMessage logMessage = new LogMessage(timestamp, message, .Error, new MessageSource(){Entity = exception.EntityId, Exception = exception, IsEngineMessage = false}); LogMessage logMessage = new LogMessage(timestamp, message, .Error, new MessageSource(){Entity = exception.EntityId, Exception = exception, IsEngineMessage = false});
+1 -1
View File
@@ -139,7 +139,7 @@ public class EditorLogger : Logger
} }
else if (args.Count > 0 && messageOrigin != null) 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 else
{ {
@@ -0,0 +1,21 @@
namespace System.Collections;
extension List<T>
{
public bool Equals(List<T> 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;
}
}
+4 -6
View File
@@ -492,19 +492,17 @@ static class ScriptEngine
return scriptClass; return scriptClass;
} }
internal static void LogScriptException(ScriptException exception, UUID entityId) internal static void LogScriptException(ScriptException exception)
{ {
String entityInfo = scope .(); String entityInfo = scope .();
if (entityId != .Zero && Context != null) if (exception.EntityId != .Zero && Context != null)
{ {
exception.EntityId = entityId; Result<Entity> sourceEntity = Context.GetEntityByID(exception.EntityId);
Result<Entity> sourceEntity = Context.GetEntityByID(entityId);
if (sourceEntity case .Ok(let e)) if (sourceEntity case .Ok(let e))
{ {
entityInfo.AppendF($" ({e.Name} | {entityId})"); entityInfo.AppendF($" ({e.Name} | {exception.EntityId})");
} }
} }
+80 -17
View File
@@ -1,44 +1,107 @@
using System; using System;
using GlitchyEngine.Core; using GlitchyEngine.Core;
using System.Collections;
namespace GlitchyEngine.Scripting; namespace GlitchyEngine.Scripting;
public class ScriptException public class ScriptException
{ {
private String _fullName ~ delete:append _; private String _fullName ~ delete:append _;
private String _message ~ delete:append _; private String _message ~ delete:append _;
private String _stackTrace ~ delete:append _; private StackTrace _stackTrace ~ delete _;
/// 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();
public StringView FullName => _fullName; public StringView FullName => _fullName;
public StringView Message => _message; public StringView Message => _message;
public StringView StackTrace => _stackTrace; public StackTrace StackTrace => _stackTrace;
public StringView CleanStackTrace => _cleanStackTrace;
//public ScriptException InnerException => _innerException; public UUID EntityId { get; private set; }
public UUID EntityId { get; set; }
[AllowAppend] [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 allocFullExceptionClassName = append String(fullExceptionClassName);
String allocMessage = append String(message); String allocMessage = append String(message);
String allocStackTrace = append String(stackTrace);
EntityId = entityId;
_stackTrace = ownStackTrace;
_fullName = allocFullExceptionClassName; _fullName = allocFullExceptionClassName;
_message = allocMessage; _message = allocMessage;
_stackTrace = allocStackTrace; }
}
// TODO public class StackFrameInfo
_cleanStackTrace = _stackTrace; {
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("<unknown>");
else
outBuffer.Append(MethodSignature);
outBuffer.Append(" in ");
if (!_fileName.IsEmpty)
outBuffer.AppendF($"{FileName}, line {Line}:{Column}");
else
outBuffer.Append("<unknown>");
}
}
public class StackTrace
{
private List<StackFrameInfo> _stackFrameInfos ~ DeleteContainerAndItems!(_);
public Span<StackFrameInfo> Frames => _stackFrameInfos;
public this(List<StackFrameInfo> 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');
}
} }
} }
+35 -11
View File
@@ -28,19 +28,29 @@ using internal GlitchyEngine.Content;
// TODO: Move to logger? // TODO: Move to logger?
class MessageOrigin class MessageOrigin
{ {
private UUID _entityId;
private String _fileName ~ delete:append _; private String _fileName ~ delete:append _;
private String _callerMemberName ~ delete:append _;
private int _lineNumber; private int _lineNumber;
private int _columnNumber;
public UUID EntityId => _entityId;
public StringView FileName => _fileName; public StringView FileName => _fileName;
public StringView CallerMemberName => _callerMemberName;
public int LineNumber => _lineNumber; public int LineNumber => _lineNumber;
public int ColumnNumber => _columnNumber;
[AllowAppend] [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 file = append String(fileName);
String caller = append String(callerMemberName);
_entityId = entityId;
_fileName = file; _fileName = file;
_callerMemberName = caller;
_lineNumber = lineNumber; _lineNumber = lineNumber;
_columnNumber = columnNumber;
} }
} }
@@ -445,7 +455,7 @@ static class ScriptGlue
#region Log #region Log
[RegisterCall, CallingConvention(.Cdecl)] [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); String escapedMessage = new:ScopedAlloc! String(messagePtr);
@@ -455,9 +465,7 @@ static class ScriptGlue
if (!fileNamePtr.IsEmpty) if (!fileNamePtr.IsEmpty)
{ {
String fileName = new:ScopedAlloc! String(fileNamePtr); MessageOrigin messageOrigin = scope MessageOrigin(entityId, fileNamePtr, callerMemberNamePtr, lineNumber, columnNumber);
MessageOrigin messageOrigin = scope MessageOrigin(fileName, lineNumber);
Log.ClientLogger.Log((LogLevel)logLevel, escapedMessage, messageOrigin); Log.ClientLogger.Log((LogLevel)logLevel, escapedMessage, messageOrigin);
} }
@@ -467,11 +475,27 @@ static class ScriptGlue
} }
} }
[RegisterCall, CallingConvention(.Cdecl)] [Ordered]
static void Log_LogException(UUID entityId, StringView fullExceptionClassName, StringView exceptionMessage, StringView stackTrace) public struct GlueStackFrameInfo
{ {
ScriptException exception = new ScriptException(entityId, fullExceptionClassName, exceptionMessage, stackTrace); public StringView FileName;
ScriptEngine.LogScriptException(exception, entityId); 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<StackFrameInfo> frames = new .(stackFrameCount);
for (GlueStackFrameInfo frameInfo in Span<GlueStackFrameInfo>(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 #endregion
@@ -642,7 +666,7 @@ static class ScriptGlue
#endregion #endregion
#region TransformComponen #region TransformComponent
[RegisterCall, CallingConvention(.Cdecl)] [RegisterCall, CallingConvention(.Cdecl)]
static EngineResult Transform_GetParent(UUID entityId, out UUID parentId) static EngineResult Transform_GetParent(UUID entityId, out UUID parentId)
@@ -966,7 +990,7 @@ static class ScriptGlue
#endregion Rigidbody2D #endregion Rigidbody2D
#region Camer #region Camera
[RegisterCall, CallingConvention(.Cdecl)] [RegisterCall, CallingConvention(.Cdecl)]
static void Camera_GetProjectionType(UUID entityId, out SceneCamera.ProjectionType projectionType) static void Camera_GetProjectionType(UUID entityId, out SceneCamera.ProjectionType projectionType)
+86 -22
View File
@@ -1,7 +1,11 @@
using GlitchyEngine.Core;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using GlitchyEngine.Core; using System.Runtime.InteropServices;
using static GlitchyEngine.Log;
namespace GlitchyEngine; namespace GlitchyEngine;
@@ -31,9 +35,10 @@ public class Log
/// <param name="message">The message to log.</param> /// <param name="message">The message to log.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Trace(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -42,9 +47,10 @@ public class Log
/// <param name="message">The message to log.</param> /// <param name="message">The message to log.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Info(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -53,9 +59,10 @@ public class Log
/// <param name="message">The message to log.</param> /// <param name="message">The message to log.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Warning(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -64,9 +71,10 @@ public class Log
/// <param name="message">The message to log.</param> /// <param name="message">The message to log.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Error(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -75,9 +83,10 @@ public class Log
/// <param name="message">The message to log.</param> /// <param name="message">The message to log.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Critical(string message, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -86,9 +95,10 @@ public class Log
/// <param name="obj">The object to serialize.</param> /// <param name="obj">The object to serialize.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Trace(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -97,9 +107,10 @@ public class Log
/// <param name="obj">The object to serialize.</param> /// <param name="obj">The object to serialize.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Info(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -108,9 +119,10 @@ public class Log
/// <param name="obj">The object to serialize.</param> /// <param name="obj">The object to serialize.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Warning(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -119,9 +131,10 @@ public class Log
/// <param name="obj">The object to serialize.</param> /// <param name="obj">The object to serialize.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Error(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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);
} }
/// <summary> /// <summary>
@@ -130,9 +143,30 @@ public class Log
/// <param name="obj">The object to serialize.</param> /// <param name="obj">The object to serialize.</param>
/// <param name="callerFilePath">File path of the caller.</param> /// <param name="callerFilePath">File path of the caller.</param>
/// <param name="callerLineNumber">Line number of the caller.</param> /// <param name="callerLineNumber">Line number of the caller.</param>
public static void Critical(object obj, [CallerFilePath]string callerFilePath = "", [CallerLineNumber]int callerLineNumber = 0) /// <param name="callerMemberName">Name of the calling member.</param>
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 ?? "<unknown>";
var parameters = string.Join(", ",
method.GetParameters().Select(p => $"{p.ParameterType.Name}"));
return $"{typeName}.{method.Name}({parameters})";
} }
/// <summary> /// <summary>
@@ -141,6 +175,36 @@ public class Log
/// <param name="exception">The exception to log.</param> /// <param name="exception">The exception to log.</param>
public static void Exception(Exception exception) 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) : "<unknown>";
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);
}
} }
} }
+45
View File
@@ -14,6 +14,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Loader; using System.Runtime.Loader;
using System.Text; using System.Text;
using System.Threading;
namespace GlitchyEngine; namespace GlitchyEngine;
@@ -272,11 +273,16 @@ internal static unsafe partial class ScriptGlue
_unsafeClasses = null; _unsafeClasses = null;
} }
private static readonly AsyncLocal<UUID> _currentEntityId = new ();
internal static UUID CurrentEntityId => _currentEntityId.Value;
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
public static void ShowEntityEditor(UUID entityId) public static void ShowEntityEditor(UUID entityId)
{ {
try try
{ {
_currentEntityId.Value = entityId;
(Entity entity, Type type) = EntityScriptInstances[entityId]; (Entity entity, Type type) = EntityScriptInstances[entityId];
EntityEditor.ShowEntityEditor(entity); EntityEditor.ShowEntityEditor(entity);
} }
@@ -284,6 +290,10 @@ internal static unsafe partial class ScriptGlue
{ {
Log.Exception(e); Log.Exception(e);
} }
finally
{
_currentEntityId.Value = UUID.Zero;
}
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
@@ -291,6 +301,7 @@ internal static unsafe partial class ScriptGlue
{ {
try try
{ {
_currentEntityId.Value = entityId;
(Entity entity, Type type) = EntityScriptInstances[entityId]; (Entity entity, Type type) = EntityScriptInstances[entityId];
entity.OnCreate(); entity.OnCreate();
} }
@@ -298,6 +309,10 @@ internal static unsafe partial class ScriptGlue
{ {
Log.Exception(e); Log.Exception(e);
} }
finally
{
_currentEntityId.Value = UUID.Zero;
}
} }
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
@@ -305,6 +320,7 @@ internal static unsafe partial class ScriptGlue
{ {
try try
{ {
_currentEntityId.Value = entityId;
(Entity entity, Type type) = EntityScriptInstances[entityId]; (Entity entity, Type type) = EntityScriptInstances[entityId];
entity.OnUpdate(deltaTime); entity.OnUpdate(deltaTime);
} }
@@ -312,6 +328,10 @@ internal static unsafe partial class ScriptGlue
{ {
Log.Exception(e); Log.Exception(e);
} }
finally
{
_currentEntityId.Value = UUID.Zero;
}
} }
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])] [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
@@ -319,6 +339,7 @@ internal static unsafe partial class ScriptGlue
{ {
try try
{ {
_currentEntityId.Value = entityId;
(Entity entity, Type type) = EntityScriptInstances[entityId]; (Entity entity, Type type) = EntityScriptInstances[entityId];
entity.OnCollisionEnter2D(collision); entity.OnCollisionEnter2D(collision);
} }
@@ -326,6 +347,10 @@ internal static unsafe partial class ScriptGlue
{ {
Log.Exception(e); Log.Exception(e);
} }
finally
{
_currentEntityId.Value = UUID.Zero;
}
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
@@ -333,6 +358,7 @@ internal static unsafe partial class ScriptGlue
{ {
try try
{ {
_currentEntityId.Value = entityId;
if (EntityScriptInstances.Remove(entityId, out var match) && callDestroy > 0) if (EntityScriptInstances.Remove(entityId, out var match) && callDestroy > 0)
{ {
match.Entity.OnDestroy(); match.Entity.OnDestroy();
@@ -342,6 +368,10 @@ internal static unsafe partial class ScriptGlue
{ {
Log.Exception(e); Log.Exception(e);
} }
finally
{
_currentEntityId.Value = UUID.Zero;
}
} }
internal static Type? GetTypeFromNativeString(byte* fullTypeName) internal static Type? GetTypeFromNativeString(byte* fullTypeName)
@@ -365,6 +395,7 @@ internal static unsafe partial class ScriptGlue
{ {
try try
{ {
_currentEntityId.Value = entityId;
Type? scriptType = GetTypeFromNativeString(scriptClassName); Type? scriptType = GetTypeFromNativeString(scriptClassName);
Debug.Assert(scriptType != null, "Script class Type not found."); Debug.Assert(scriptType != null, "Script class Type not found.");
@@ -379,6 +410,10 @@ internal static unsafe partial class ScriptGlue
{ {
Log.Exception(e); Log.Exception(e);
} }
finally
{
_currentEntityId.Value = UUID.Zero;
}
} }
struct ComponentFunctionPointers struct ComponentFunctionPointers
@@ -459,6 +494,7 @@ internal static unsafe partial class ScriptGlue
{ {
try try
{ {
_currentEntityId.Value = entityId;
if (!EntityScriptInstances.TryGetValue(entityId, out var match)) if (!EntityScriptInstances.TryGetValue(entityId, out var match))
return; return;
@@ -468,6 +504,10 @@ internal static unsafe partial class ScriptGlue
{ {
Log.Exception(e); Log.Exception(e);
} }
finally
{
_currentEntityId.Value = UUID.Zero;
}
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
@@ -475,6 +515,7 @@ internal static unsafe partial class ScriptGlue
{ {
try try
{ {
_currentEntityId.Value = entityId;
if (!EntityScriptInstances.TryGetValue(entityId, out var match)) if (!EntityScriptInstances.TryGetValue(entityId, out var match))
return; return;
@@ -484,6 +525,10 @@ internal static unsafe partial class ScriptGlue
{ {
Log.Exception(e); Log.Exception(e);
} }
finally
{
_currentEntityId.Value = UUID.Zero;
}
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
+25 -2
View File
@@ -122,7 +122,8 @@ public class ScriptGlueGenerator : IIncrementalGenerator
None, None,
Ref, Ref,
In, In,
Out Out,
Pointer
} }
private static (MappedType Type, TypeModifier Modifier) DecodeType(string beefType, Dictionary<string, MappedType> beefTypeToMappedType) private static (MappedType Type, TypeModifier Modifier) DecodeType(string beefType, Dictionary<string, MappedType> beefTypeToMappedType)
@@ -145,6 +146,15 @@ public class ScriptGlueGenerator : IIncrementalGenerator
beefType = beefType.Substring(3); 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)) if (beefTypeToMappedType.TryGetValue(beefType, out MappedType? mappedType))
{ {
return (mappedType, modifier); return (mappedType, modifier);
@@ -296,6 +306,14 @@ public class ScriptGlueGenerator : IIncrementalGenerator
} }
parameterText.Append(parameterType.CSharpTypeName); parameterText.Append(parameterType.CSharpTypeName);
switch (parameterModifier)
{
case TypeModifier.Pointer:
parameterText.Append("*");
break;
}
parameterText.Append(", "); parameterText.Append(", ");
} }
@@ -345,7 +363,12 @@ public class ScriptGlueGenerator : IIncrementalGenerator
break; break;
} }
parameterText.Append($"{parameterType.CSharpWrapperType} {param.Name}"); parameterText.Append($"{parameterType.CSharpWrapperType}");
if (parameterModifier == TypeModifier.Pointer)
parameterText.Append("*");
parameterText.Append($" {param.Name}");
switch (parameterModifier) switch (parameterModifier)
{ {