mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Basic entity scripting
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
using Mono;
|
||||
using System;
|
||||
using GlitchyEngine.Core;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
class ScriptClass
|
||||
{
|
||||
private String _namespace ~ delete _;
|
||||
private String _className ~ delete _;
|
||||
private String _fullName ~ delete _;
|
||||
|
||||
private MonoClass* _monoClass;
|
||||
|
||||
//typealias ConstructorMethod = function void(MonoObject* instance, UUID uuid, MonoException** exception);
|
||||
typealias OnCreateMethod = function MonoObject*(MonoObject* instance, MonoException** exception);
|
||||
typealias OnUpdateMethod = function MonoObject*(MonoObject* instance, float deltaTime, MonoException** exception);
|
||||
typealias OnDestroyMethod = function MonoObject*(MonoObject* instance, MonoException** exception);
|
||||
|
||||
private MonoMethod* _constructor;
|
||||
//private ConstructorMethod _constructor;
|
||||
private OnCreateMethod _onCreate;
|
||||
private OnUpdateMethod _onUpdate;
|
||||
private OnDestroyMethod _onDestroy;
|
||||
|
||||
public StringView Namespace => _namespace;
|
||||
public StringView ClassName => _className;
|
||||
public StringView FullName => _fullName;
|
||||
|
||||
[AllowAppend]
|
||||
public this(StringView classNamespace, StringView className)
|
||||
{
|
||||
_namespace = new String(classNamespace);
|
||||
_className = new String(className);
|
||||
_fullName = new $"{_namespace}.{_className}";
|
||||
|
||||
_monoClass = Mono.mono_class_from_name(ScriptEngine.[Friend]s_CoreAssemblyImage, _namespace, _className);
|
||||
|
||||
//_constructor = (ConstructorMethod)GetMethodThunk(".ctor", 1); // GetMethod(".ctor", 1);//
|
||||
_constructor = GetMethod(".ctor", 1);
|
||||
_onCreate = (OnCreateMethod)GetMethodThunk("OnCreate");
|
||||
_onUpdate = (OnUpdateMethod)GetMethodThunk("OnUpdate", 1);
|
||||
_onDestroy = (OnDestroyMethod)GetMethodThunk("OnDestroy");
|
||||
}
|
||||
|
||||
public void OnCreate(MonoObject* instance)
|
||||
{
|
||||
MonoException* exception = null;
|
||||
if (_onCreate != null)
|
||||
_onCreate(instance, &exception);
|
||||
}
|
||||
|
||||
public void OnUpdate(MonoObject* instance, float deltaTime)
|
||||
{
|
||||
MonoException* exception;
|
||||
if (_onUpdate != null)
|
||||
_onUpdate(instance, deltaTime, &exception);
|
||||
}
|
||||
|
||||
public void OnDestroy(MonoObject* instance)
|
||||
{
|
||||
MonoException* exception;
|
||||
if (_onDestroy != null)
|
||||
_onDestroy(instance, &exception);
|
||||
}
|
||||
|
||||
public MonoObject* CreateInstance(UUID uuid)
|
||||
{
|
||||
MonoObject* instance = Mono.mono_object_new(ScriptEngine.[Friend]s_AppDomain, _monoClass);
|
||||
|
||||
#unwarn
|
||||
ScriptEngine.[Friend]s_EngineObject.Invoke(ScriptEngine.[Friend]s_EngineObject._constructor, instance, &uuid);
|
||||
|
||||
//MonoException* exception = null;
|
||||
//#unwarn
|
||||
//ScriptEngine.[Friend]s_EntityRoot._constructor(instance, uuid, &exception);
|
||||
//ScriptEngine.[Friend]s_EntityRoot.Invoke(_constructor, instance, &uuid);
|
||||
|
||||
/*MonoObject* exception = null;
|
||||
#unwarn*/
|
||||
//Mono.mono_runtime_invoke(_constructor, instance, (.)&uuid, &exception);
|
||||
//Mono.mono_runtime_object_init(instance);
|
||||
//MonoException* exception;
|
||||
//_constructor(instance, uuid, &exception);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public MonoMethod* GetMethod(StringView name, int argCount = 0)
|
||||
{
|
||||
return Mono.mono_class_get_method_from_name(_monoClass, name.ToScopeCStr!(), argCount);
|
||||
}
|
||||
|
||||
public void* GetMethodThunk(StringView name, int argCount = 0)
|
||||
{
|
||||
MonoMethod* method = GetMethod(name, argCount);
|
||||
|
||||
if (method == null)
|
||||
return null;
|
||||
|
||||
return Mono.mono_method_get_unmanaged_thunk(method);
|
||||
}
|
||||
|
||||
public MonoObject* Invoke(MonoMethod* method, MonoObject* instance, void** args = null)
|
||||
{
|
||||
MonoObject* exception = null;
|
||||
return Mono.mono_runtime_invoke(method, instance, args, &exception);
|
||||
}
|
||||
|
||||
public MonoObject* Invoke(MonoMethod* method, MonoObject* instance, params void*[] args)
|
||||
{
|
||||
return Mono.mono_runtime_invoke(method, instance, args.Ptr, null);
|
||||
}
|
||||
|
||||
public T Invoke<T>(MonoMethod* method, MonoObject* instance, params void*[] args)
|
||||
{
|
||||
MonoObject* object = Invoke(method, instance, args.Ptr);
|
||||
return *(T*)Mono.mono_object_unbox(object);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,10 @@ using Mono;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using GlitchyEngine.Math;
|
||||
using GlitchyEngine.World;
|
||||
using GlitchyEngine.Core;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
static class ScriptEngine
|
||||
@@ -10,73 +14,72 @@ static class ScriptEngine
|
||||
private static MonoDomain* s_AppDomain;
|
||||
|
||||
private static MonoAssembly* s_CoreAssembly;
|
||||
private static MonoImage* s_CoreAssemblyImage;
|
||||
|
||||
private static Scene s_Context ~ _?.ReleaseRef();
|
||||
|
||||
private static ScriptClass s_EntityRoot ~ delete _;
|
||||
private static ScriptClass s_EngineObject ~ delete _;
|
||||
|
||||
private static Dictionary<StringView, ScriptClass> _entityScripts = new .() ~ {
|
||||
for (var entry in _)
|
||||
{
|
||||
delete entry.value;
|
||||
}
|
||||
delete _entityScripts;
|
||||
};
|
||||
|
||||
private static Dictionary<UUID, ScriptInstance> _entityScriptInstances = new .() ~ {
|
||||
for (var entry in _)
|
||||
{
|
||||
entry.value?.ReleaseRef();
|
||||
}
|
||||
delete _;
|
||||
};
|
||||
|
||||
public static Dictionary<StringView, ScriptClass> EntityClasses => _entityScripts;
|
||||
|
||||
public static Scene Context => s_Context;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
Mono.mono_set_assemblies_path("mono/lib");
|
||||
|
||||
s_RootDomain = Mono.mono_jit_init("GlitchyEngineJITRuntime");
|
||||
|
||||
Log.EngineLogger.Assert(s_RootDomain != null, "Failed to initialize mono root domain");
|
||||
|
||||
// Create an App Domain
|
||||
s_AppDomain = Mono.mono_domain_create_appdomain("GlitchyEngineScriptRuntime", null);
|
||||
Mono.mono_domain_set(s_AppDomain, true);
|
||||
ScriptGlue.Init();
|
||||
|
||||
s_CoreAssembly = LoadCSharpAssembly("resources/scripts/ScriptCore.dll");
|
||||
PrintAssemblyTypes(s_CoreAssembly);
|
||||
LoadAssembly("resources/scripts/ScriptCore.dll");
|
||||
|
||||
function MonoString*() v = => Sample;
|
||||
|
||||
Mono.mono_add_internal_call("GlitchyEngine.CSharpTesting::Sample", v);
|
||||
|
||||
// Create object
|
||||
MonoImage* image = Mono.mono_assembly_get_image(s_CoreAssembly);
|
||||
|
||||
MonoClass* monoClass = Mono.mono_class_from_name(image, "GlitchyEngine", "CSharpTesting");
|
||||
|
||||
MonoObject* instance = Mono.mono_object_new(s_AppDomain, monoClass);
|
||||
Mono.mono_runtime_object_init(instance);
|
||||
|
||||
MonoMethod* simpleMethod = Mono.mono_class_get_method_from_name(monoClass, "PrintFloatVar", 0);
|
||||
Mono.mono_runtime_invoke(simpleMethod, instance, null, null);
|
||||
|
||||
MonoMethod* methodWithArg = Mono.mono_class_get_method_from_name(monoClass, "IncrementFloatVar", 1);
|
||||
|
||||
float increment = 2.0f;
|
||||
void*[1] args = .(&increment);
|
||||
|
||||
MonoObject* returnValue = Mono.mono_runtime_invoke(methodWithArg, instance, &args, null);
|
||||
|
||||
float returnedValue = *(float*)Mono.mono_object_unbox(returnValue);
|
||||
|
||||
Log.EngineLogger.Info($"C# returned: {returnedValue}");
|
||||
|
||||
Mono.mono_runtime_invoke(simpleMethod, instance, null, null);
|
||||
//Samples();
|
||||
}
|
||||
|
||||
[LinkName(.C), AlwaysInclude, Export]
|
||||
public static void DoSomething()
|
||||
public static void SetContext(Scene scene)
|
||||
{
|
||||
Console.WriteLine("P/Invoke: Hallo von der Engine!");
|
||||
SetReference!(s_Context, scene);
|
||||
}
|
||||
|
||||
[LinkName(.C), AlwaysInclude]
|
||||
public static MonoString* Sample()
|
||||
|
||||
public static void InitializeInstance(Entity entity, ScriptComponent* script)
|
||||
{
|
||||
return Mono.mono_string_new(Mono.mono_domain_get(), "Hello!");
|
||||
_entityScriptInstances[entity.UUID] = script.Instance..AddRef();
|
||||
|
||||
script.Instance.Instantiate(entity.UUID);
|
||||
script.Instance.InvokeOnCreate();
|
||||
}
|
||||
|
||||
private static MonoAssembly* LoadCSharpAssembly(StringView assemblyPath)
|
||||
{
|
||||
List<uint8> data = new:ScopedAlloc! List<uint8>(1024);
|
||||
List<uint8> data = new List<uint8>(1024);
|
||||
|
||||
File.ReadAll(assemblyPath, data);
|
||||
|
||||
// NOTE: We can't use this image for anything other than loading the assembly because this image doesn't have a reference to the assembly
|
||||
MonoImageOpenStatus status = .ImageInvalid;
|
||||
MonoImage* image = Mono.mono_image_open_from_data_full(data.Ptr, (.)data.Count, true, &status, false);
|
||||
|
||||
|
||||
delete data;
|
||||
|
||||
if (status != .Ok)
|
||||
{
|
||||
char8* errorMessage = Mono.mono_image_strerror(status);
|
||||
@@ -89,15 +92,132 @@ static class ScriptEngine
|
||||
MonoAssembly* assembly = Mono.mono_assembly_load_from_full(image, assemblyPath.ToScopeCStr!(), &status, 0);
|
||||
Mono.mono_image_close(image);
|
||||
|
||||
// Create object
|
||||
|
||||
// call simple method
|
||||
|
||||
// call method with args
|
||||
|
||||
return assembly;
|
||||
}
|
||||
|
||||
static void LoadAssembly(StringView filepath)
|
||||
{
|
||||
s_AppDomain = Mono.mono_domain_create_appdomain("GlitchyEngineScriptRuntime", null);
|
||||
Mono.mono_domain_set(s_AppDomain, true);
|
||||
|
||||
s_CoreAssembly = LoadCSharpAssembly(filepath);
|
||||
s_CoreAssemblyImage = Mono.mono_assembly_get_image(s_CoreAssembly);
|
||||
GetEntitiesFromAssembly(s_CoreAssembly);
|
||||
}
|
||||
|
||||
private static void GetEntitiesFromAssembly(MonoAssembly* assembly)
|
||||
{
|
||||
for (var entry in _entityScripts)
|
||||
{
|
||||
delete entry.value;
|
||||
}
|
||||
_entityScripts.Clear();
|
||||
|
||||
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);
|
||||
|
||||
s_EngineObject = new ScriptClass("GlitchyEngine.Core", "EngineObject");
|
||||
s_EntityRoot = new ScriptClass("GlitchyEngine", "Entity");
|
||||
|
||||
Log.EngineLogger.Assert(s_EntityRoot != null);
|
||||
|
||||
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]);
|
||||
|
||||
MonoClass* monoClass = Mono.mono_class_from_name(image, nameSpace, name);
|
||||
|
||||
if (monoClass != null && Mono.mono_class_is_subclass_of(monoClass, s_EntityRoot.[Friend]_monoClass, false))
|
||||
{
|
||||
ScriptClass entityScript = new ScriptClass(StringView(nameSpace), StringView(name));
|
||||
_entityScripts.Add(entityScript.FullName, entityScript);
|
||||
|
||||
Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Shutdown()
|
||||
{
|
||||
/*Mono.mono_assembly_close(s_CoreAssembly);
|
||||
s_CoreAssembly = null;
|
||||
|
||||
Mono.mono_domain_unload(s_AppDomain);
|
||||
s_AppDomain = null;*/
|
||||
|
||||
Mono.mono_jit_cleanup(s_RootDomain);
|
||||
s_RootDomain = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*static void Samples()
|
||||
{
|
||||
PrintAssemblyTypes(s_CoreAssembly);
|
||||
|
||||
function MonoString*() v = => Sample;
|
||||
|
||||
Mono.mono_add_internal_call("GlitchyEngine.CSharpTesting::Sample", v);
|
||||
|
||||
function void(in Vector3, in Vector3, out Vector3) v2 = => Add;
|
||||
|
||||
Mono.mono_add_internal_call("GlitchyEngine.Vector3::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 Vector3 a, in Vector3 b, out Vector3 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);
|
||||
@@ -114,17 +234,5 @@ static class ScriptEngine
|
||||
|
||||
Log.EngineLogger.Info($"{StringView(nameSpace)}.{StringView(name)}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Shutdown()
|
||||
{
|
||||
/*Mono.mono_assembly_close(s_CoreAssembly);
|
||||
s_CoreAssembly = null;
|
||||
|
||||
Mono.mono_domain_unload(s_AppDomain);
|
||||
s_AppDomain = null;*/
|
||||
|
||||
Mono.mono_jit_cleanup(s_RootDomain);
|
||||
s_RootDomain = null;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
using Mono;
|
||||
using System;
|
||||
using GlitchLog;
|
||||
using System.Reflection;
|
||||
using GlitchyEngine.Events;
|
||||
using GlitchyEngine.Math;
|
||||
using GlitchyEngine.World;
|
||||
using GlitchyEngine.Core;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
static class ScriptGlue
|
||||
{
|
||||
struct RegisterCallAttribute : Attribute
|
||||
{
|
||||
public String MethodName;
|
||||
|
||||
public this(String methodName)
|
||||
{
|
||||
MethodName = methodName;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adding this attribute to a method will log method entry and returned Result<T> errors */
|
||||
[AttributeUsage(.Method)]
|
||||
struct RegisterMethodAttribute : Attribute, IOnMethodInit
|
||||
{
|
||||
[Comptime]
|
||||
public void OnMethodInit(MethodInfo method, Self* prev)
|
||||
{
|
||||
for (var methodInfo in typeof(ScriptGlue).GetMethods(.Static))
|
||||
{
|
||||
if (methodInfo.GetCustomAttribute<RegisterCallAttribute>() case .Ok(let attribute))
|
||||
{
|
||||
String functionType = scope $"{methodInfo.ReturnType}({methodInfo.GetParamsDecl(.. scope .())})";
|
||||
|
||||
String line = scope $"RegisterCall<function {functionType}>(\"{attribute.MethodName}\", => {methodInfo.Name});\n";
|
||||
|
||||
Compiler.EmitMethodEntry(method, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
RegisterCalls();
|
||||
}
|
||||
|
||||
[RegisterMethod]
|
||||
private static void RegisterCalls()
|
||||
{
|
||||
// Generated at CompTime
|
||||
}
|
||||
|
||||
|
||||
[RegisterCall("Log::LogMessage_Impl")]
|
||||
static void Log(int32 logLevel, MonoString* message)
|
||||
{
|
||||
char8* utfMessage = Mono.mono_string_to_utf8(message);
|
||||
|
||||
Log.ClientLogger.Log((LogLevel)logLevel, StringView(utfMessage));
|
||||
|
||||
Mono.mono_free(utfMessage);
|
||||
}
|
||||
|
||||
#region Input
|
||||
|
||||
[RegisterCall("Input::IsKeyPressed")]
|
||||
static bool Input_IsKeyPressed(Key key) => Input.IsKeyPressed(key);
|
||||
|
||||
[RegisterCall("Input::IsKeyReleased")]
|
||||
static bool Input_IsKeyReleased(Key key) => Input.IsKeyReleased(key);
|
||||
|
||||
[RegisterCall("Input::IsKeyToggled")]
|
||||
static bool Input_IsKeyToggled(Key key) => Input.IsKeyToggled(key);
|
||||
|
||||
[RegisterCall("Input::IsKeyPressing")]
|
||||
static bool Input_IsKeyPressing(Key key) => Input.IsKeyPressing(key);
|
||||
|
||||
[RegisterCall("Input::IsKeyReleasing")]
|
||||
static bool Input_IsKeyReleasing(Key key) => Input.IsKeyReleasing(key);
|
||||
|
||||
|
||||
[RegisterCall("Input::IsMouseButtonPressed")]
|
||||
static bool Input_IsMouseButtonPressed(MouseButton mouseButton) => Input.IsMouseButtonPressed(mouseButton);
|
||||
|
||||
[RegisterCall("Input::IsMouseButtonReleased")]
|
||||
static bool Input_IsMouseButtonReleased(MouseButton mouseButton) => Input.IsMouseButtonReleased(mouseButton);
|
||||
|
||||
[RegisterCall("Input::IsMouseButtonPressing")]
|
||||
static bool Input_IsMouseButtonPressing(MouseButton mouseButton) => Input.IsMouseButtonPressing(mouseButton);
|
||||
|
||||
[RegisterCall("Input::IsMouseButtonReleasing")]
|
||||
static bool Input_IsMouseButtonReleasing(MouseButton mouseButton) => Input.IsMouseButtonReleasing(mouseButton);
|
||||
|
||||
#endregion Input
|
||||
|
||||
#region Scene/Entity stuff
|
||||
|
||||
/*[RegisterCall("Input::IsMouseButtonReleasing")]
|
||||
static void Destroy()
|
||||
{
|
||||
// TODO:
|
||||
}*/
|
||||
|
||||
[RegisterCall("ScriptGlue::Entity_GetTranslation")]
|
||||
static void Entity_GetTranslation(UUID entityId, ref Vector3 translation)
|
||||
{
|
||||
Scene scene = ScriptEngine.Context;
|
||||
Entity entity = scene.GetEntityByID(entityId);
|
||||
|
||||
translation = entity.Transform.Position;
|
||||
}
|
||||
|
||||
[RegisterCall("ScriptGlue::Entity_SetTranslation")]
|
||||
static void Entity_SetTranslation(UUID entityId, ref Vector3 translation)
|
||||
{
|
||||
Scene scene = ScriptEngine.Context;
|
||||
Entity entity = scene.GetEntityByID(entityId);
|
||||
|
||||
entity.Transform.Position = translation;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static void RegisterCall<T>(String name, T method) where T : var
|
||||
{
|
||||
Mono.mono_add_internal_call(scope $"GlitchyEngine.{name}", (void*)method);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using Mono;
|
||||
using GlitchyEngine.Core;
|
||||
|
||||
namespace GlitchyEngine.Scripting;
|
||||
|
||||
class ScriptInstance : RefCounter
|
||||
{
|
||||
private ScriptClass _scriptClass;
|
||||
|
||||
private MonoObject* _instance;
|
||||
private uint32 _gcHandle;
|
||||
|
||||
public ScriptClass ScriptClass => _scriptClass;
|
||||
|
||||
public bool IsInstatiated => _instance != null;
|
||||
|
||||
public this(ScriptClass scriptClass)
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(scriptClass != null);
|
||||
_scriptClass = scriptClass;
|
||||
}
|
||||
|
||||
private ~this()
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
_scriptClass.OnDestroy(_instance);
|
||||
Mono.mono_gchandle_free(_gcHandle);
|
||||
}
|
||||
}
|
||||
|
||||
public void Instantiate(UUID uuid)
|
||||
{
|
||||
_instance = _scriptClass.CreateInstance(uuid);
|
||||
_gcHandle = Mono.mono_gchandle_new(_instance, true);
|
||||
}
|
||||
|
||||
public void InvokeOnCreate()
|
||||
{
|
||||
_scriptClass.OnCreate(_instance);
|
||||
}
|
||||
|
||||
public void InvokeOnUpdate(float deltaTime)
|
||||
{
|
||||
_scriptClass.OnUpdate(_instance, deltaTime);
|
||||
}
|
||||
|
||||
public void InvokeOnDestroy()
|
||||
{
|
||||
_scriptClass.OnDestroy(_instance);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ using GlitchyEngine.Renderer;
|
||||
using GlitchyEngine.Core;
|
||||
using Box2D;
|
||||
using GlitchyEngine.Content;
|
||||
using GlitchyEngine.Scripting;
|
||||
using Mono;
|
||||
|
||||
namespace GlitchyEngine.World
|
||||
{
|
||||
@@ -442,4 +444,26 @@ namespace GlitchyEngine.World
|
||||
[Inline]
|
||||
internal ref b2Vec2 b2Offset mut => ref *(Box2D.b2Vec2*)(void*)&Offset;
|
||||
}
|
||||
|
||||
struct ScriptComponent : IDisposableComponent
|
||||
{
|
||||
private ScriptInstance _instance = null;
|
||||
|
||||
public ScriptInstance Instance
|
||||
{
|
||||
[Inline]
|
||||
get => _instance;
|
||||
[Inline]
|
||||
set mut => SetReference!(_instance, value);
|
||||
}
|
||||
|
||||
public bool InInstantiated => _instance?.IsInstatiated ?? false;
|
||||
|
||||
public void Dispose() mut
|
||||
{
|
||||
ReleaseRefAndNullify!(_instance);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Collections;
|
||||
using Box2D;
|
||||
using GlitchyEngine.Core;
|
||||
using GlitchyEngine.Content;
|
||||
using GlitchyEngine.Scripting;
|
||||
|
||||
namespace GlitchyEngine.World
|
||||
{
|
||||
@@ -75,7 +76,8 @@ namespace GlitchyEngine.World
|
||||
CopyComponents<Rigidbody2DComponent>(this, target);
|
||||
CopyComponents<BoxCollider2DComponent>(this, target);
|
||||
CopyComponents<CircleCollider2DComponent>(this, target);
|
||||
|
||||
CopyComponents<ScriptComponent>(this, target);
|
||||
|
||||
// Copy transforms
|
||||
for (let (sourceHandle, sourceTransform) in _ecsWorld.Enumerate<TransformComponent>())
|
||||
{
|
||||
@@ -127,10 +129,12 @@ namespace GlitchyEngine.World
|
||||
public void OnRuntimeStart()
|
||||
{
|
||||
OnSimulationStart();
|
||||
ScriptEngine.SetContext(this);
|
||||
}
|
||||
|
||||
public void OnRuntimeStop()
|
||||
{
|
||||
ScriptEngine.SetContext(null);
|
||||
OnSimulationStop();
|
||||
}
|
||||
|
||||
@@ -211,6 +215,8 @@ namespace GlitchyEngine.World
|
||||
Runtime = 0x04 | Physics,
|
||||
}
|
||||
|
||||
//private append List<UUID> _destroyQueue = .();
|
||||
|
||||
public void Update(GameTime gameTime, UpdateMode mode)
|
||||
{
|
||||
Debug.Profiler.ProfileRendererFunction!();
|
||||
@@ -231,6 +237,17 @@ namespace GlitchyEngine.World
|
||||
|
||||
script.Instance.[Friend]OnUpdate(gameTime);
|
||||
}
|
||||
|
||||
// Run scripts
|
||||
for (var (entity, script) in _ecsWorld.Enumerate<ScriptComponent>())
|
||||
{
|
||||
if (!script.InInstantiated)
|
||||
{
|
||||
ScriptEngine.InitializeInstance(Entity(entity, this), script);
|
||||
}
|
||||
|
||||
script.Instance.InvokeOnUpdate(gameTime.DeltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode.HasFlag(.Physics))
|
||||
|
||||
Reference in New Issue
Block a user