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:
@@ -6,6 +6,7 @@ using System.Collections;
|
|||||||
using GlitchyEngine.Renderer;
|
using GlitchyEngine.Renderer;
|
||||||
using GlitchyEngine;
|
using GlitchyEngine;
|
||||||
using GlitchyEngine.Content;
|
using GlitchyEngine.Content;
|
||||||
|
using GlitchyEngine.Scripting;
|
||||||
|
|
||||||
namespace GlitchyEditor.EditWindows
|
namespace GlitchyEditor.EditWindows
|
||||||
{
|
{
|
||||||
@@ -68,6 +69,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
ShowComponentEditor<Rigidbody2DComponent>("Rigidbody 2D", entity, => ShowRigidBody2DComponentEditor, => ShowComponentContextMenu<Rigidbody2DComponent>);
|
ShowComponentEditor<Rigidbody2DComponent>("Rigidbody 2D", entity, => ShowRigidBody2DComponentEditor, => ShowComponentContextMenu<Rigidbody2DComponent>);
|
||||||
ShowComponentEditor<BoxCollider2DComponent>("Box collider 2D", entity, => ShowBoxCollider2DComponentEditor, => ShowComponentContextMenu<BoxCollider2DComponent>);
|
ShowComponentEditor<BoxCollider2DComponent>("Box collider 2D", entity, => ShowBoxCollider2DComponentEditor, => ShowComponentContextMenu<BoxCollider2DComponent>);
|
||||||
ShowComponentEditor<CircleCollider2DComponent>("Circle collider 2D", entity, => ShowCircleCollider2DComponentEditor, => ShowComponentContextMenu<CircleCollider2DComponent>);
|
ShowComponentEditor<CircleCollider2DComponent>("Circle collider 2D", entity, => ShowCircleCollider2DComponentEditor, => ShowComponentContextMenu<CircleCollider2DComponent>);
|
||||||
|
ShowComponentEditor<ScriptComponent>("Script Component", entity, => ShowScriptComponentEditor, => ShowComponentContextMenu<ScriptComponent>);
|
||||||
|
|
||||||
ShowAddComponentButton(entity);
|
ShowAddComponentButton(entity);
|
||||||
}
|
}
|
||||||
@@ -429,6 +431,35 @@ namespace GlitchyEditor.EditWindows
|
|||||||
circleCollider.RestitutionThreshold = restitutionThreshold;
|
circleCollider.RestitutionThreshold = restitutionThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ShowScriptComponentEditor(Entity entity, ScriptComponent* scriptComponent)
|
||||||
|
{
|
||||||
|
static char8[64] buffer = .();
|
||||||
|
|
||||||
|
StringView search = StringView();
|
||||||
|
|
||||||
|
if (ImGui.InputText("##ScriptName", &buffer, buffer.Count))
|
||||||
|
{
|
||||||
|
search = StringView(&buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui.BeginCombo("##Type", scriptComponent.Instance?.ScriptClass.FullName.ToScopeCStr!()))
|
||||||
|
{
|
||||||
|
for (let (className, script) in ScriptEngine.EntityClasses)
|
||||||
|
{
|
||||||
|
if (!search.IsWhiteSpace && !className.Contains(search, true))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ImGui.Selectable(className.ToScopeCStr!(),
|
||||||
|
className == scriptComponent.Instance?.ScriptClass.FullName))
|
||||||
|
{
|
||||||
|
scriptComponent.Instance = new ScriptInstance(script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndCombo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void LabelColumn(StringView label)
|
private static void LabelColumn(StringView label)
|
||||||
{
|
{
|
||||||
ImGui.TextUnformatted(label);
|
ImGui.TextUnformatted(label);
|
||||||
@@ -584,6 +615,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
ShowComponentButton<CircleCollider2DComponent>("Circle collider 2D");
|
ShowComponentButton<CircleCollider2DComponent>("Circle collider 2D");
|
||||||
ShowComponentButton<MeshComponent>("Mesh");
|
ShowComponentButton<MeshComponent>("Mesh");
|
||||||
ShowComponentButton<MeshRendererComponent>("Mesh Renderer");
|
ShowComponentButton<MeshRendererComponent>("Mesh Renderer");
|
||||||
|
ShowComponentButton<ScriptComponent>("C# Script");
|
||||||
|
|
||||||
ImGui.EndCombo();
|
ImGui.EndCombo();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
using GlitchyEngine.World;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
|
||||||
namespace GlitchyEngine.Scripting;
|
namespace GlitchyEngine.Scripting;
|
||||||
|
|
||||||
static class ScriptEngine
|
static class ScriptEngine
|
||||||
@@ -10,66 +14,63 @@ static class ScriptEngine
|
|||||||
private static MonoDomain* s_AppDomain;
|
private static MonoDomain* s_AppDomain;
|
||||||
|
|
||||||
private static MonoAssembly* s_CoreAssembly;
|
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()
|
public static void Init()
|
||||||
{
|
{
|
||||||
Mono.mono_set_assemblies_path("mono/lib");
|
Mono.mono_set_assemblies_path("mono/lib");
|
||||||
|
|
||||||
s_RootDomain = Mono.mono_jit_init("GlitchyEngineJITRuntime");
|
s_RootDomain = Mono.mono_jit_init("GlitchyEngineJITRuntime");
|
||||||
|
|
||||||
Log.EngineLogger.Assert(s_RootDomain != null, "Failed to initialize mono root domain");
|
Log.EngineLogger.Assert(s_RootDomain != null, "Failed to initialize mono root domain");
|
||||||
|
|
||||||
// Create an App Domain
|
ScriptGlue.Init();
|
||||||
s_AppDomain = Mono.mono_domain_create_appdomain("GlitchyEngineScriptRuntime", null);
|
|
||||||
Mono.mono_domain_set(s_AppDomain, true);
|
|
||||||
|
|
||||||
s_CoreAssembly = LoadCSharpAssembly("resources/scripts/ScriptCore.dll");
|
LoadAssembly("resources/scripts/ScriptCore.dll");
|
||||||
PrintAssemblyTypes(s_CoreAssembly);
|
|
||||||
|
|
||||||
function MonoString*() v = => Sample;
|
//Samples();
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LinkName(.C), AlwaysInclude, Export]
|
public static void SetContext(Scene scene)
|
||||||
public static void DoSomething()
|
|
||||||
{
|
{
|
||||||
Console.WriteLine("P/Invoke: Hallo von der Engine!");
|
SetReference!(s_Context, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LinkName(.C), AlwaysInclude]
|
public static void InitializeInstance(Entity entity, ScriptComponent* script)
|
||||||
public static MonoString* Sample()
|
|
||||||
{
|
{
|
||||||
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)
|
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);
|
File.ReadAll(assemblyPath, data);
|
||||||
|
|
||||||
@@ -77,6 +78,8 @@ static class ScriptEngine
|
|||||||
MonoImageOpenStatus status = .ImageInvalid;
|
MonoImageOpenStatus status = .ImageInvalid;
|
||||||
MonoImage* image = Mono.mono_image_open_from_data_full(data.Ptr, (.)data.Count, true, &status, false);
|
MonoImage* image = Mono.mono_image_open_from_data_full(data.Ptr, (.)data.Count, true, &status, false);
|
||||||
|
|
||||||
|
delete data;
|
||||||
|
|
||||||
if (status != .Ok)
|
if (status != .Ok)
|
||||||
{
|
{
|
||||||
char8* errorMessage = Mono.mono_image_strerror(status);
|
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);
|
MonoAssembly* assembly = Mono.mono_assembly_load_from_full(image, assemblyPath.ToScopeCStr!(), &status, 0);
|
||||||
Mono.mono_image_close(image);
|
Mono.mono_image_close(image);
|
||||||
|
|
||||||
// Create object
|
|
||||||
|
|
||||||
// call simple method
|
|
||||||
|
|
||||||
// call method with args
|
|
||||||
|
|
||||||
return assembly;
|
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)
|
private static void PrintAssemblyTypes(MonoAssembly* assembly)
|
||||||
{
|
{
|
||||||
MonoImage* image = Mono.mono_assembly_get_image(assembly);
|
MonoImage* image = Mono.mono_assembly_get_image(assembly);
|
||||||
@@ -114,17 +234,5 @@ static class ScriptEngine
|
|||||||
|
|
||||||
Log.EngineLogger.Info($"{StringView(nameSpace)}.{StringView(name)}");
|
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 GlitchyEngine.Core;
|
||||||
using Box2D;
|
using Box2D;
|
||||||
using GlitchyEngine.Content;
|
using GlitchyEngine.Content;
|
||||||
|
using GlitchyEngine.Scripting;
|
||||||
|
using Mono;
|
||||||
|
|
||||||
namespace GlitchyEngine.World
|
namespace GlitchyEngine.World
|
||||||
{
|
{
|
||||||
@@ -442,4 +444,26 @@ namespace GlitchyEngine.World
|
|||||||
[Inline]
|
[Inline]
|
||||||
internal ref b2Vec2 b2Offset mut => ref *(Box2D.b2Vec2*)(void*)&Offset;
|
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 Box2D;
|
||||||
using GlitchyEngine.Core;
|
using GlitchyEngine.Core;
|
||||||
using GlitchyEngine.Content;
|
using GlitchyEngine.Content;
|
||||||
|
using GlitchyEngine.Scripting;
|
||||||
|
|
||||||
namespace GlitchyEngine.World
|
namespace GlitchyEngine.World
|
||||||
{
|
{
|
||||||
@@ -75,6 +76,7 @@ namespace GlitchyEngine.World
|
|||||||
CopyComponents<Rigidbody2DComponent>(this, target);
|
CopyComponents<Rigidbody2DComponent>(this, target);
|
||||||
CopyComponents<BoxCollider2DComponent>(this, target);
|
CopyComponents<BoxCollider2DComponent>(this, target);
|
||||||
CopyComponents<CircleCollider2DComponent>(this, target);
|
CopyComponents<CircleCollider2DComponent>(this, target);
|
||||||
|
CopyComponents<ScriptComponent>(this, target);
|
||||||
|
|
||||||
// Copy transforms
|
// Copy transforms
|
||||||
for (let (sourceHandle, sourceTransform) in _ecsWorld.Enumerate<TransformComponent>())
|
for (let (sourceHandle, sourceTransform) in _ecsWorld.Enumerate<TransformComponent>())
|
||||||
@@ -127,10 +129,12 @@ namespace GlitchyEngine.World
|
|||||||
public void OnRuntimeStart()
|
public void OnRuntimeStart()
|
||||||
{
|
{
|
||||||
OnSimulationStart();
|
OnSimulationStart();
|
||||||
|
ScriptEngine.SetContext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRuntimeStop()
|
public void OnRuntimeStop()
|
||||||
{
|
{
|
||||||
|
ScriptEngine.SetContext(null);
|
||||||
OnSimulationStop();
|
OnSimulationStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,6 +215,8 @@ namespace GlitchyEngine.World
|
|||||||
Runtime = 0x04 | Physics,
|
Runtime = 0x04 | Physics,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//private append List<UUID> _destroyQueue = .();
|
||||||
|
|
||||||
public void Update(GameTime gameTime, UpdateMode mode)
|
public void Update(GameTime gameTime, UpdateMode mode)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
@@ -231,6 +237,17 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
script.Instance.[Friend]OnUpdate(gameTime);
|
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))
|
if (mode.HasFlag(.Physics))
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ static class Mono
|
|||||||
public static extern char8* mono_metadata_string_heap(MonoImage *meta, uint32 table_index);
|
public static extern char8* mono_metadata_string_heap(MonoImage *meta, uint32 table_index);
|
||||||
|
|
||||||
typealias gconstpointer = void*;
|
typealias gconstpointer = void*;
|
||||||
|
typealias gpointer = void*;
|
||||||
|
|
||||||
[LinkName(.C)]
|
[LinkName(.C)]
|
||||||
public static extern void mono_add_internal_call(char8* name, gconstpointer method);
|
public static extern void mono_add_internal_call(char8* name, gconstpointer method);
|
||||||
@@ -96,6 +97,32 @@ static class Mono
|
|||||||
|
|
||||||
[LinkName(.C)]
|
[LinkName(.C)]
|
||||||
public static extern void* mono_domain_unload(MonoDomain* domain);
|
public static extern void* mono_domain_unload(MonoDomain* domain);
|
||||||
|
|
||||||
|
|
||||||
|
[LinkName(.C)]
|
||||||
|
public static extern gpointer mono_method_get_unmanaged_thunk(MonoMethod *method);
|
||||||
|
|
||||||
|
[LinkName(.C)]
|
||||||
|
public static extern mono_bool mono_class_is_subclass_of(MonoClass *monoClass, MonoClass *parentClass,
|
||||||
|
mono_bool check_interfaces);
|
||||||
|
|
||||||
|
[LinkName(.C)]
|
||||||
|
public static extern uint32 mono_gchandle_new(MonoObject* obj, mono_bool pinned);
|
||||||
|
|
||||||
|
[LinkName(.C)]
|
||||||
|
public static extern void mono_gchandle_free(uint32 gchandle);
|
||||||
|
|
||||||
|
[LinkName(.C)]
|
||||||
|
public static extern char8* mono_string_to_utf8(MonoString *s);
|
||||||
|
|
||||||
|
[LinkName(.C)]
|
||||||
|
public static extern void mono_free(void* ptr);
|
||||||
|
|
||||||
|
[LinkName(.C)]
|
||||||
|
public static extern MonoClassField* mono_class_get_field_from_name(MonoClass* monoClass, char8* name);
|
||||||
|
|
||||||
|
[LinkName(.C)]
|
||||||
|
public static extern void mono_field_set_value(MonoObject* obj, MonoClassField* field, void* value);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MonoDomain;
|
struct MonoDomain;
|
||||||
@@ -114,6 +141,10 @@ struct MonoObject;
|
|||||||
|
|
||||||
struct MonoMethod;
|
struct MonoMethod;
|
||||||
|
|
||||||
|
struct MonoException;
|
||||||
|
|
||||||
|
struct MonoClassField;
|
||||||
|
|
||||||
enum MonoImageOpenStatus
|
enum MonoImageOpenStatus
|
||||||
{
|
{
|
||||||
Ok,
|
Ok,
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
namespace GlitchyEngine
|
|
||||||
{
|
|
||||||
public class CSharpTesting
|
public class CSharpTesting
|
||||||
{
|
{
|
||||||
public float MyPublicFloatVar = 5.0f;
|
public float MyPublicFloatVar = 5.0f;
|
||||||
@@ -13,6 +14,14 @@ namespace GlitchyEngine
|
|||||||
Console.WriteLine("Hallo von C#!");
|
Console.WriteLine("Hallo von C#!");
|
||||||
DoSomething();
|
DoSomething();
|
||||||
Console.WriteLine(Sample());
|
Console.WriteLine(Sample());
|
||||||
|
|
||||||
|
Vector3 a = new Vector3(1, 2, 3);
|
||||||
|
Vector3 b = new Vector3(3, 2, 1);
|
||||||
|
|
||||||
|
Vector3 result;
|
||||||
|
//Vector3.Add_Internal(a, b, out result);
|
||||||
|
|
||||||
|
//Console.WriteLine(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport ("__Internal", EntryPoint="DoSomething")]
|
[DllImport ("__Internal", EntryPoint="DoSomething")]
|
||||||
@@ -33,4 +42,3 @@ namespace GlitchyEngine
|
|||||||
return MyPublicFloatVar;
|
return MyPublicFloatVar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using GlitchyEngine.Core;
|
||||||
|
|
||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
public class Component : EngineObject
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using GlitchyEngine.Core;
|
||||||
|
|
||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
public class Transform : EngineObject
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
namespace GlitchyEngine.Core;
|
||||||
|
|
||||||
|
public class EngineObject
|
||||||
|
{
|
||||||
|
protected internal UUID _uuid;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UUID used for identifying the object in the engine.
|
||||||
|
/// </summary>
|
||||||
|
public UUID UUID => _uuid;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Empty constructor not used. Do NOT USE!
|
||||||
|
/// </summary>
|
||||||
|
protected EngineObject()
|
||||||
|
{}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new EngineObject with the given ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">UUID of the object.</param>
|
||||||
|
internal EngineObject(UUID uuid)
|
||||||
|
{
|
||||||
|
_uuid = uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace GlitchyEngine.Core;
|
||||||
|
|
||||||
|
public struct UUID
|
||||||
|
{
|
||||||
|
private ulong _uuid;
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
internal struct EntityHandle
|
||||||
|
{
|
||||||
|
public uint Version;
|
||||||
|
public uint Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Entity : EngineObject
|
||||||
|
{
|
||||||
|
//private UUID _uuid;
|
||||||
|
|
||||||
|
//public UUID UUID => _uuid;
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Empty constructor not used. Do NOT USE!
|
||||||
|
///// </summary>
|
||||||
|
//protected Entity()
|
||||||
|
//{}
|
||||||
|
|
||||||
|
//internal Entity(UUID uuid)
|
||||||
|
//{
|
||||||
|
// _uuid = uuid;
|
||||||
|
//}
|
||||||
|
|
||||||
|
public T GetComponent<T>() where T : Component
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//public Transform Transform => new (){_uuid = _uuid};
|
||||||
|
|
||||||
|
public Vector3 Translation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
ScriptGlue.Entity_GetTranslation(_uuid, out Vector3 translation);
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
set => ScriptGlue.Entity_SetTranslation(_uuid, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will be executed once after the entity as be created.
|
||||||
|
// void OnCreate();
|
||||||
|
|
||||||
|
// Will be executed every frame.
|
||||||
|
// void OnUpdate(GameTime);
|
||||||
|
|
||||||
|
// Will be executed once when the entity is being destroyed.
|
||||||
|
// void OnDestroy();
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
public static class Input
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsKeyPressed(Key key);
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsKeyReleased(Key key);
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsKeyToggled(Key key);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsKeyPressing(Key key);
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsKeyReleasing(Key key);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsMouseButtonPressed(MouseButton mouseButton);
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsMouseButtonReleased(MouseButton mouseButton);
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsMouseButtonPressing(MouseButton mouseButton);
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern bool IsMouseButtonReleasing(MouseButton mouseButton);
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
public enum Key
|
||||||
|
{
|
||||||
|
// Based on Win32 Virtual Keys
|
||||||
|
LeftButton = 1, // Left mouse button
|
||||||
|
RightRutton = 2, // Right mouse button
|
||||||
|
MiddleButton = 4, // Middle mouse button(three - button mouse)
|
||||||
|
XButton1 = 5, // X1 mouse button
|
||||||
|
XButton2 = 6, // X2 mouse button
|
||||||
|
Backspace = 8, // Backspace key
|
||||||
|
Tab = 9, // Tab key
|
||||||
|
Return = 13, // Enter key
|
||||||
|
Shift = 16, // Shift key
|
||||||
|
Control = 17, // Ctrl key
|
||||||
|
Alt = 18, // Alt key
|
||||||
|
Pause = 19, // Pause key
|
||||||
|
CapsLock = 20, // Caps Lock key
|
||||||
|
Escape = 27, // ESC key
|
||||||
|
Space = 32, // Spacebar
|
||||||
|
Prior = 33, // Page Up key
|
||||||
|
Next = 34, // Page Down key
|
||||||
|
End = 35, // END key
|
||||||
|
Home = 36, // HOME key
|
||||||
|
Left = 37, // LEFT ARROW key
|
||||||
|
Up = 38, // UP ARROW key
|
||||||
|
Right = 39, // RIGHT ARROW key
|
||||||
|
Down = 40, // DOWN ARROW key
|
||||||
|
Print = 42, // PRINT key
|
||||||
|
Insert = 45, // INS key
|
||||||
|
Delete = 46, // DEL key
|
||||||
|
Help = 47, // HELP key
|
||||||
|
Zero = 48, // 0 key
|
||||||
|
One = 49, // 1 key
|
||||||
|
Two = 50, // 2 key
|
||||||
|
Three = 51, // 3 key
|
||||||
|
Four = 52, // 4 key
|
||||||
|
Five = 53, // 5 key
|
||||||
|
Six = 54, // 6 key
|
||||||
|
Seven = 55, // 7 key
|
||||||
|
Eight = 56, // 8 key
|
||||||
|
Nine = 57, // 9 key
|
||||||
|
A = 65, // A key
|
||||||
|
B = 66, // B key
|
||||||
|
C = 67, // C key
|
||||||
|
D = 68, // D key
|
||||||
|
E = 69, // E key
|
||||||
|
F = 70, // F key
|
||||||
|
G = 71, // G key
|
||||||
|
H = 72, // H key
|
||||||
|
I = 73, // I key
|
||||||
|
J = 74, // J key
|
||||||
|
K = 75, // K key
|
||||||
|
L = 76, // L key
|
||||||
|
M = 77, // M key
|
||||||
|
N = 78, // N key
|
||||||
|
O = 79, // O key
|
||||||
|
P = 80, // P key
|
||||||
|
Q = 81, // Q key
|
||||||
|
R = 82, // R key
|
||||||
|
S = 83, // S key
|
||||||
|
T = 84, // T key
|
||||||
|
U = 85, // U key
|
||||||
|
V = 86, // V key
|
||||||
|
W = 87, // W key
|
||||||
|
X = 88, // X key
|
||||||
|
Y = 89, // Y key
|
||||||
|
Z = 90, // Z key
|
||||||
|
LeftSuper = 91, // Left Windows key(Microsoft® Natural® keyboard)
|
||||||
|
RightSuper = 92, // Right Windows key(Natural keyboard)
|
||||||
|
ContextMenu = 93, // Context Menu key (VK_APPS)
|
||||||
|
Numpad0 = 96, // Numeric keypad 0 key
|
||||||
|
Numpad1 = 97, // Numeric keypad 1 key
|
||||||
|
Numpad2 = 98, // Numeric keypad 2 key
|
||||||
|
Numpad3 = 99, // Numeric keypad 3 key
|
||||||
|
Numpad4 = 100, // Numeric keypad 4 key
|
||||||
|
Numpad5 = 101, // Numeric keypad 5 key
|
||||||
|
Numpad6 = 102, // Numeric keypad 6 key
|
||||||
|
Numpad7 = 103, // Numeric keypad 7 key
|
||||||
|
Numpad8 = 104, // Numeric keypad 8 key
|
||||||
|
Numpad9 = 105, // Numeric keypad 9 key
|
||||||
|
Multiply = 106, // Multiply key
|
||||||
|
Add = 107, // Add key
|
||||||
|
Separator = 108, // Separator key
|
||||||
|
Subtract = 109, // Subtract key
|
||||||
|
Decimal = 110, // Decimal key
|
||||||
|
Divide = 111, // Divide key
|
||||||
|
F1 = 112, // F1 key
|
||||||
|
F2 = 113, // F2 key
|
||||||
|
F3 = 114, // F3 key
|
||||||
|
F4 = 115, // F4 key
|
||||||
|
F5 = 116, // F5 key
|
||||||
|
F6 = 117, // F6 key
|
||||||
|
F7 = 118, // F7 key
|
||||||
|
F8 = 119, // F8 key
|
||||||
|
F9 = 120, // F9 key
|
||||||
|
F10 = 121, // F10 key
|
||||||
|
F11 = 122, // F11 key
|
||||||
|
F12 = 123, // F12 key
|
||||||
|
F13 = 124, // F13 key
|
||||||
|
F14 = 125, // F14 key
|
||||||
|
F15 = 126, // F15 key
|
||||||
|
F16 = 127, // F16 key
|
||||||
|
F17 = 128, // F17 key
|
||||||
|
F18 = 129, // F18 key
|
||||||
|
F19 = 130, // F19 key
|
||||||
|
F20 = 131, // F20 key
|
||||||
|
F21 = 132, // F21 key
|
||||||
|
F22 = 133, // F22 key
|
||||||
|
F23 = 134, // F23 key
|
||||||
|
F24 = 135, // F24 key
|
||||||
|
Numlock = 144, // NUM LOCK key
|
||||||
|
Scroll = 145, // SCROLL LOCK key
|
||||||
|
LeftShift = 160, // Left SHIFT key
|
||||||
|
RightShift = 161, // Right SHIFT key
|
||||||
|
LeftControl = 162, // Left CONTROL key
|
||||||
|
RightControl = 163, // Right CONTROL key
|
||||||
|
LeftAlt = 164, // Left Alt key
|
||||||
|
RightAlt = 165 // Right Alt key
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
public class Log
|
||||||
|
{
|
||||||
|
public enum LogLevel
|
||||||
|
{
|
||||||
|
Trace = 0,
|
||||||
|
Debug,
|
||||||
|
Info,
|
||||||
|
Warning,
|
||||||
|
Error,
|
||||||
|
Critical,
|
||||||
|
Off
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Trace(string message)
|
||||||
|
{
|
||||||
|
LogMessage_Impl(LogLevel.Trace, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
//public static void LogDebug(string message)
|
||||||
|
//{
|
||||||
|
// LogMessage_Impl(LogLevel.Info, message);
|
||||||
|
//}
|
||||||
|
|
||||||
|
public static void Info(string message)
|
||||||
|
{
|
||||||
|
LogMessage_Impl(LogLevel.Info, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Warning(string message)
|
||||||
|
{
|
||||||
|
LogMessage_Impl(LogLevel.Warning, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error(string message)
|
||||||
|
{
|
||||||
|
LogMessage_Impl(LogLevel.Error, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Critical(string message)
|
||||||
|
{
|
||||||
|
LogMessage_Impl(LogLevel.Critical, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
public static extern string LogMessage_Impl(LogLevel logLevel, string message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Math;
|
||||||
|
|
||||||
|
public struct Vector2
|
||||||
|
{
|
||||||
|
public static readonly Vector2 Zero = new(0.0f, 0.0f);
|
||||||
|
public static readonly Vector2 UnitX = new(1.0f, 0.0f);
|
||||||
|
public static readonly Vector2 UnitY = new(0.0f, 1.0f);
|
||||||
|
public static readonly Vector2 One = new(0.0f, 0.0f);
|
||||||
|
|
||||||
|
public const int ComponentCount = 2;
|
||||||
|
|
||||||
|
public float X, Y;
|
||||||
|
|
||||||
|
public Vector2()
|
||||||
|
{
|
||||||
|
X = Y = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2(float x, float y)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch(index)
|
||||||
|
{
|
||||||
|
case 0: return X;
|
||||||
|
case 1: return Y;
|
||||||
|
default: throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch(index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
X = value;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Y = value;
|
||||||
|
break;
|
||||||
|
default: throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
using System;
|
||||||
|
using System.CodeDom;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Math;
|
||||||
|
|
||||||
|
public struct Vector3
|
||||||
|
{
|
||||||
|
public static readonly Vector3 Zero = new(0.0f, 0.0f, 0.0f);
|
||||||
|
public static readonly Vector3 UnitX = new(1.0f, 0.0f, 0.0f);
|
||||||
|
public static readonly Vector3 UnitY = new(0.0f, 1.0f, 0.0f);
|
||||||
|
public static readonly Vector3 UnitZ = new(0.0f, 0.0f, 1.0f);
|
||||||
|
public static readonly Vector3 One = new(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
public static readonly Vector3 Forward = new(0.0f, 0.0f, 1.0f);
|
||||||
|
public static readonly Vector3 Backward = new(0.0f, 0.0f, -1.0f);
|
||||||
|
public static readonly Vector3 Left = new(-1.0f, 0.0f, 0.0f);
|
||||||
|
public static readonly Vector3 Right = new(1.0f, 0.0f, 0.0f);
|
||||||
|
public static readonly Vector3 Up = new(0.0f, 1.0f, 0.0f);
|
||||||
|
public static readonly Vector3 Down = new(0.0f, -1.0f, 0.0f);
|
||||||
|
|
||||||
|
public const int ComponentCount = 3;
|
||||||
|
|
||||||
|
public float X, Y, Z;
|
||||||
|
|
||||||
|
public Vector3()
|
||||||
|
{
|
||||||
|
X = Y = Z = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3(float x, float y, float z)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
}
|
||||||
|
public Vector3(Vector2 xy, float z)
|
||||||
|
{
|
||||||
|
X = xy.X;
|
||||||
|
Y = xy.Y;
|
||||||
|
Z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch(index)
|
||||||
|
{
|
||||||
|
case 0: return X;
|
||||||
|
case 1: return Y;
|
||||||
|
case 2: return Z;
|
||||||
|
default: throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch(index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
X = value;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Y = value;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Z = value;
|
||||||
|
break;
|
||||||
|
default: throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator +(in Vector3 a, in Vector3 b) => new(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator +(float a, in Vector3 b) => new(a + b.X, a + b.Y, a + b.Z);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator +(in Vector3 a, float b) => new(a.X + b, a.Y + b, a.Z + b);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator +(in Vector3 a) => a;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator -(in Vector3 a, in Vector3 b) => new(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator -(float a, in Vector3 b) => new(a - b.X, a - b.Y, a - b.Z);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator -(in Vector3 a, float b) => new(a.X - b, a.Y - b, a.Z - b);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator -(in Vector3 a) => new Vector3(-a.X, -a.Y, -a.Z);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator *(in Vector3 a, in Vector3 b) => new(a.X * b.X, a.Y * b.Y, a.Z * b.Z);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator *(float a, in Vector3 b) => new(a * b.X, a * b.Y, a * b.Z);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator *(in Vector3 a, float b) => new(a.X * b, a.Y * b, a.Z * b);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator /(in Vector3 a, in Vector3 b) => new(a.X / b.X, a.Y / b.Y, a.Z / b.Z);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator /(float a, in Vector3 b) => new(a / b.X, a / b.Y, a / b.Z);
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3 operator /(in Vector3 a, float b) => new(a.X / b, a.Y / b, a.Z / b);
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static bool operator ==(Vector3 a, Vector3 b)
|
||||||
|
{
|
||||||
|
float diffX = a.X - b.X;
|
||||||
|
float diffY = a.Y - b.Y;
|
||||||
|
float diffZ = a.Z - b.Z;
|
||||||
|
|
||||||
|
return diffX * diffX + diffY * diffY + diffZ * diffZ < 0.00001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static bool operator !=(Vector3 a, Vector3 b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"X:{X}, Y:{Y}, Z:{Z}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
public enum MouseButton : byte
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
LeftButton,
|
||||||
|
RightButton,
|
||||||
|
MiddleButton,
|
||||||
|
XButton1,
|
||||||
|
XButton2,
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
class MyTestEntity : Entity
|
||||||
|
{
|
||||||
|
//Rigidbody2D _rigidBody;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called after the script component was created. (The entity might not be fully created yet)
|
||||||
|
/// </summary>
|
||||||
|
void OnCreate()
|
||||||
|
{
|
||||||
|
Log.Info($"Create! {UUID}");
|
||||||
|
|
||||||
|
//_rigidBody = GetComponent<Rigidbody2D>();
|
||||||
|
}
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Called after the entity was created completely.
|
||||||
|
///// </summary>
|
||||||
|
//void OnInstantiate()
|
||||||
|
//{
|
||||||
|
// Log.Warning($"Instantiated!");
|
||||||
|
//}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called every frame.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deltaTime"></param>
|
||||||
|
void OnUpdate(float deltaTime)
|
||||||
|
{
|
||||||
|
if (Input.IsKeyPressed(Key.A))
|
||||||
|
{
|
||||||
|
Log.Info($"HALLO!");
|
||||||
|
|
||||||
|
Vector3 translation = Translation;
|
||||||
|
translation.Y += 1.0f * deltaTime;
|
||||||
|
|
||||||
|
Translation = translation;
|
||||||
|
|
||||||
|
//_rigidBody.ApplyImpulse(new Vector2(0, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Input.IsMouseButtonReleasing(MouseButton.LeftButton))
|
||||||
|
{
|
||||||
|
Log.Info("Ouha!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called before the component is being destroyed.
|
||||||
|
/// </summary>
|
||||||
|
void OnDestroy()
|
||||||
|
{
|
||||||
|
Log.Trace("Destroy");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,8 +43,21 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Components\Component.cs" />
|
||||||
|
<Compile Include="Components\Transform.cs" />
|
||||||
|
<Compile Include="Core\EngineObject.cs" />
|
||||||
|
<Compile Include="Core\UUID.cs" />
|
||||||
<Compile Include="CSharpTesting.cs" />
|
<Compile Include="CSharpTesting.cs" />
|
||||||
|
<Compile Include="Entity.cs" />
|
||||||
|
<Compile Include="Input.cs" />
|
||||||
|
<Compile Include="Key.cs" />
|
||||||
|
<Compile Include="Log.cs" />
|
||||||
|
<Compile Include="Math\Vector2.cs" />
|
||||||
|
<Compile Include="Math\Vector3.cs" />
|
||||||
|
<Compile Include="MouseButton.cs" />
|
||||||
|
<Compile Include="MyTestEntity.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="ScriptGlue.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
namespace GlitchyEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All methods in here are glued to the ScriptGlue.bf in the engine.
|
||||||
|
/// </summary>
|
||||||
|
internal static class ScriptGlue
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern void Entity_GetTranslation(UUID entityId, out Vector3 translation);
|
||||||
|
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||||
|
internal static extern void Entity_SetTranslation(UUID entityId, in Vector3 translation);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user