mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Automatic script assembly reloading
This commit is contained in:
@@ -112,27 +112,6 @@ namespace Sandbox
|
|||||||
Log.Info($"Ouha! {MyNumber}");
|
Log.Info($"Ouha! {MyNumber}");
|
||||||
Physics2D.Gravity *= new float2(1, -1);
|
Physics2D.Gravity *= new float2(1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Test.Test.P();
|
|
||||||
|
|
||||||
float2 f2 = new();
|
|
||||||
|
|
||||||
f2.X = 5;
|
|
||||||
|
|
||||||
Log.Info($"Haleluja! {f2.X}");
|
|
||||||
|
|
||||||
float4 floaty = new float4(f2, f2);
|
|
||||||
|
|
||||||
float4 megaFloat = floaty.WXYZ;
|
|
||||||
|
|
||||||
if (all(abs(normalize(megaFloat).YZWX - normalize(floaty)) < 0.01f))
|
|
||||||
{
|
|
||||||
Log.Info($"Haleluja3!");
|
|
||||||
}
|
|
||||||
|
|
||||||
float frac = modf(5.6f, out var intPart);
|
|
||||||
|
|
||||||
Log.Info($"Haleluja2! {frac} {intPart}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ using GlitchyEngine.Renderer;
|
|||||||
using GlitchyEngine.Debug;
|
using GlitchyEngine.Debug;
|
||||||
using GlitchyEngine.Content;
|
using GlitchyEngine.Content;
|
||||||
using GlitchyEngine.Scripting;
|
using GlitchyEngine.Scripting;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace GlitchyEngine
|
namespace GlitchyEngine
|
||||||
{
|
{
|
||||||
@@ -28,6 +30,9 @@ namespace GlitchyEngine
|
|||||||
|
|
||||||
private IContentManager _contentManager;
|
private IContentManager _contentManager;
|
||||||
|
|
||||||
|
private append List<delegate void()> _jobQueue = .() ~ ClearAndDeleteItems!(_);
|
||||||
|
private append Monitor _jobQueueMutex = .();
|
||||||
|
|
||||||
public bool IsRunning => _running;
|
public bool IsRunning => _running;
|
||||||
public Window Window => _window;
|
public Window Window => _window;
|
||||||
|
|
||||||
@@ -37,9 +42,11 @@ namespace GlitchyEngine
|
|||||||
|
|
||||||
public GameTime GameTime => _gameTime;
|
public GameTime GameTime => _gameTime;
|
||||||
|
|
||||||
[Inline]
|
[Inline, Obsolete("Use Application.Instance instead.", false)]
|
||||||
public static Application Get() => s_Instance;
|
public static Application Get() => s_Instance;
|
||||||
|
|
||||||
|
public static Application Instance => s_Instance;
|
||||||
|
|
||||||
public Settings Settings {get; private set;} = new .() ~ delete _;
|
public Settings Settings {get; private set;} = new .() ~ delete _;
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
@@ -157,6 +164,8 @@ namespace GlitchyEngine
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
RunJobs();
|
||||||
|
|
||||||
if(allowFrame && !_isMinimized)
|
if(allowFrame && !_isMinimized)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileScope!("Update Layers");
|
Debug.Profiler.ProfileScope!("Update Layers");
|
||||||
@@ -218,5 +227,29 @@ namespace GlitchyEngine
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes the given Job on the main thread. Takes ownership of the delegate.
|
||||||
|
public void InvokeOnMainThread(delegate void() ownJob)
|
||||||
|
{
|
||||||
|
using (_jobQueueMutex.Enter())
|
||||||
|
{
|
||||||
|
_jobQueue.Add(ownJob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunJobs()
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
|
using (_jobQueueMutex.Enter())
|
||||||
|
{
|
||||||
|
for (let job in _jobQueue)
|
||||||
|
{
|
||||||
|
job();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearAndDeleteItems!(_jobQueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ static class ScriptEngine
|
|||||||
delete _;
|
delete _;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static FileSystemWatcher _userAssemblyWatcher ~ delete _;
|
||||||
|
|
||||||
internal static class Attributes
|
internal static class Attributes
|
||||||
{
|
{
|
||||||
internal static MonoClass* s_ShowInEditorAttribute;
|
internal static MonoClass* s_ShowInEditorAttribute;
|
||||||
@@ -102,6 +104,40 @@ static class ScriptEngine
|
|||||||
ScriptGlue.Init();
|
ScriptGlue.Init();
|
||||||
|
|
||||||
LoadScriptAssemblies();
|
LoadScriptAssemblies();
|
||||||
|
|
||||||
|
InitAssemblyWatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InitAssemblyWatcher()
|
||||||
|
{
|
||||||
|
if (_userAssemblyWatcher == null)
|
||||||
|
{
|
||||||
|
// TODO: Obviously don't hardcode path
|
||||||
|
_userAssemblyWatcher = new FileSystemWatcher("SandboxProject/Assets/Scripts/bin/", "*/Sandbox.dll");
|
||||||
|
_userAssemblyWatcher.OnChanged.Add(new (fileName) =>
|
||||||
|
{
|
||||||
|
// TODO: Temporary, we want to be able to reload while in play-mode. (+ Editor Scripts will be a thing some day)
|
||||||
|
if (_entityScriptInstances.Count > 0)
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Warning("There are script instances. Skipping assembly reload.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.EngineLogger.Info("Script reload requested.");
|
||||||
|
_userAssemblyWatcher.StopRaisingEvents();
|
||||||
|
|
||||||
|
Application.Instance.InvokeOnMainThread(new () =>
|
||||||
|
{
|
||||||
|
Log.EngineLogger.Info("Reloading scripts...");
|
||||||
|
ReloadAssemblies();
|
||||||
|
Log.EngineLogger.Info("Scripts reloaded!");
|
||||||
|
|
||||||
|
_userAssemblyWatcher.StartRaisingEvents();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_userAssemblyWatcher.StartRaisingEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadScriptAssemblies()
|
static void LoadScriptAssemblies()
|
||||||
@@ -259,6 +295,8 @@ static class ScriptEngine
|
|||||||
|
|
||||||
public static void ReloadAssemblies()
|
public static void ReloadAssemblies()
|
||||||
{
|
{
|
||||||
|
Debug.Profiler.ProfileFunction!();
|
||||||
|
|
||||||
Mono.mono_domain_set(s_RootDomain, false);
|
Mono.mono_domain_set(s_RootDomain, false);
|
||||||
|
|
||||||
Mono.mono_domain_unload(s_AppDomain);
|
Mono.mono_domain_unload(s_AppDomain);
|
||||||
@@ -382,80 +420,4 @@ static class ScriptEngine
|
|||||||
|
|
||||||
return scriptClass;
|
return scriptClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*static void Samples()
|
|
||||||
{
|
|
||||||
PrintAssemblyTypes(s_CoreAssembly);
|
|
||||||
|
|
||||||
function MonoString*() v = => Sample;
|
|
||||||
|
|
||||||
Mono.mono_add_internal_call("GlitchyEngine.CSharpTesting::Sample", v);
|
|
||||||
|
|
||||||
function void(in float3, in float3, out float3) v2 = => Add;
|
|
||||||
|
|
||||||
Mono.mono_add_internal_call("GlitchyEngine.float3::Add_Internal", v2);
|
|
||||||
|
|
||||||
// Create object
|
|
||||||
ScriptClass myClass = scope .("GlitchyEngine", "CSharpTesting");
|
|
||||||
MonoObject* instance = myClass.CreateInstance();
|
|
||||||
|
|
||||||
MonoMethod* simpleMethod = myClass.GetMethod("PrintFloatVar");
|
|
||||||
myClass.Invoke(simpleMethod, instance);
|
|
||||||
|
|
||||||
MonoMethod* methodWithArg = myClass.GetMethod("IncrementFloatVar", 1);
|
|
||||||
|
|
||||||
float increment = 2.0f;
|
|
||||||
float returnedValue = myClass.Invoke<float>(methodWithArg, instance, &increment);
|
|
||||||
|
|
||||||
Log.EngineLogger.Info($"C# returned: {returnedValue}");
|
|
||||||
|
|
||||||
Mono.mono_runtime_invoke(simpleMethod, instance, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LinkName(.C), AlwaysInclude, Export]
|
|
||||||
public static void DoSomething()
|
|
||||||
{
|
|
||||||
Console.WriteLine("P/Invoke: Hallo von der Engine!");
|
|
||||||
}
|
|
||||||
|
|
||||||
[LinkName(.C), AlwaysInclude, Export]
|
|
||||||
public static void Add(in float3 a, in float3 b, out float3 c)
|
|
||||||
{
|
|
||||||
c = a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LinkName(.C), AlwaysInclude]
|
|
||||||
public static MonoString* Sample()
|
|
||||||
{
|
|
||||||
return Mono.mono_string_new(Mono.mono_domain_get(), "Hello!");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PrintAssemblyTypes(MonoAssembly* assembly)
|
|
||||||
{
|
|
||||||
MonoImage* image = Mono.mono_assembly_get_image(assembly);
|
|
||||||
MonoTableInfo* typeDefinitionsTable = Mono.mono_image_get_table_info(image, .MONO_TABLE_TYPEDEF);
|
|
||||||
int32 numTypes = Mono.mono_table_info_get_rows(typeDefinitionsTable);
|
|
||||||
|
|
||||||
for (int32 i = 0; i < numTypes; i++)
|
|
||||||
{
|
|
||||||
int32[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_SIZE] cols = .();
|
|
||||||
Mono.mono_metadata_decode_row(typeDefinitionsTable, i, (.)&cols, (.)SOME_RANDOM_ENUM.MONO_TYPEDEF_SIZE);
|
|
||||||
|
|
||||||
char8* nameSpace = Mono.mono_metadata_string_heap(image, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAMESPACE]);
|
|
||||||
char8* name = Mono.mono_metadata_string_heap(image, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAME]);
|
|
||||||
|
|
||||||
Log.EngineLogger.Info($"{StringView(nameSpace)}.{StringView(name)}");
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.CodeAnalysis;
|
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
||||||
|
|
||||||
namespace ScriptCoreGenerator
|
|
||||||
{
|
|
||||||
[Generator]
|
|
||||||
public class HelloSourceGenerator : ISourceGenerator
|
|
||||||
{
|
|
||||||
public void Execute(GeneratorExecutionContext context)
|
|
||||||
{
|
|
||||||
var receiver = (MainSyntaxReceiver)context.SyntaxReceiver;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
string output = @"
|
|
||||||
namespace Test{
|
|
||||||
public class Test
|
|
||||||
{
|
|
||||||
public static void P() => GlitchyEngine.Log.Error(""Hello World"");
|
|
||||||
}}
|
|
||||||
";
|
|
||||||
|
|
||||||
// Code generation goes here
|
|
||||||
context.AddSource("Test/Hello.g.cs", output);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Initialize(GeneratorInitializationContext context)
|
|
||||||
{
|
|
||||||
context.RegisterForSyntaxNotifications(() => new MainSyntaxReceiver());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MainSyntaxReceiver : ISyntaxReceiver
|
|
||||||
{
|
|
||||||
public DefinitionAggregate Definitions { get; } = new();
|
|
||||||
public GivethsAggregate Giveths { get; } = new();
|
|
||||||
|
|
||||||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
|
||||||
{
|
|
||||||
Definitions.OnVisitSyntaxNode(syntaxNode);
|
|
||||||
Giveths.OnVisitSyntaxNode(syntaxNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DefinitionAggregate : ISyntaxReceiver
|
|
||||||
{
|
|
||||||
public List<Capture> Captures { get; } = new();
|
|
||||||
|
|
||||||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
|
||||||
{
|
|
||||||
if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "Define" } } attr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var method = attr.GetParent<MethodDeclarationSyntax>();
|
|
||||||
var key = method.Identifier.Text;
|
|
||||||
|
|
||||||
Captures.Add(new Capture(key, method));
|
|
||||||
}
|
|
||||||
|
|
||||||
public record Capture(string Key, MethodDeclarationSyntax Method)
|
|
||||||
{
|
|
||||||
public string Key { get; } = Key;
|
|
||||||
public MethodDeclarationSyntax Method { get; } = Method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GivethsAggregate : ISyntaxReceiver
|
|
||||||
{
|
|
||||||
public List<Capture> Captures { get; } = new();
|
|
||||||
|
|
||||||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
|
||||||
{
|
|
||||||
if (syntaxNode is not AttributeSyntax { Name: IdentifierNameSyntax { Identifier.Text: "Give" } } attr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var target = (attr.ArgumentList.Arguments.Single().Expression as LiteralExpressionSyntax).Token.ValueText;
|
|
||||||
|
|
||||||
var method = attr.GetParent<MethodDeclarationSyntax>();
|
|
||||||
var @class = attr.GetParent<ClassDeclarationSyntax>();
|
|
||||||
|
|
||||||
Captures.Add(new Capture(target, method, @class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public record Capture(string TargetImplementation, MethodDeclarationSyntax Method, ClassDeclarationSyntax Class)
|
|
||||||
{
|
|
||||||
public string TargetImplementation { get; } = TargetImplementation;
|
|
||||||
public MethodDeclarationSyntax Method { get; } = Method;
|
|
||||||
public ClassDeclarationSyntax Class { get; } = Class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user