mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Basic Script reloading
+ ScriptComponent now saves script name instead of direct ScriptClass reference + Added ClearDictionaryAndDeleteKeys helper + Moved ScriptFieldType to separate file + _ScriptFieldMap now uses String as Key
This commit is contained in:
@@ -470,14 +470,14 @@ namespace GlitchyEditor.EditWindows
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ImGui.Selectable(className.ToScopeCStr!(),
|
if (ImGui.Selectable(className.ToScopeCStr!(),
|
||||||
className == scriptComponent.Instance?.ScriptClass.FullName))
|
className == scriptComponent.ScriptClassName))
|
||||||
{
|
{
|
||||||
//scriptComponent.Instance = new ScriptInstance(scriptClass);
|
//scriptComponent.Instance = new ScriptInstance(scriptClass);
|
||||||
// decrement refCount to 1 (scriptComponent.Instance increments its)
|
// decrement refCount to 1 (scriptComponent.Instance increments its)
|
||||||
//scriptComponent.Instance.ReleaseRef();
|
//scriptComponent.Instance.ReleaseRef();
|
||||||
//ScriptEngine.InitializeInstance(entity, scriptComponent);
|
//ScriptEngine.InitializeInstance(entity, scriptComponent);
|
||||||
|
|
||||||
scriptComponent.ScriptClass = scriptClass;
|
scriptComponent.ScriptClassName = scriptClass.FullName;
|
||||||
|
|
||||||
ScriptEngine.CreateScriptFieldMap(entity);
|
ScriptEngine.CreateScriptFieldMap(entity);
|
||||||
}
|
}
|
||||||
@@ -485,6 +485,8 @@ namespace GlitchyEditor.EditWindows
|
|||||||
ImGui.EndPopup();
|
ImGui.EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScriptClass scriptClass = ScriptEngine.GetScriptClass(scriptComponent.ScriptClassName);
|
||||||
|
|
||||||
/*T GetFieldValue<T>()
|
/*T GetFieldValue<T>()
|
||||||
{
|
{
|
||||||
return scriptComponent.Instance.GetFieldValue<T>(monoField);
|
return scriptComponent.Instance.GetFieldValue<T>(monoField);
|
||||||
@@ -595,68 +597,68 @@ namespace GlitchyEditor.EditWindows
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (scriptComponent.ScriptClass != null)
|
else if (scriptClass != null)
|
||||||
{
|
{
|
||||||
let scriptFields = ScriptEngine.GetScriptFieldMap(entity);
|
let scriptFields = ScriptEngine.GetScriptFieldMap(entity);
|
||||||
|
|
||||||
for (var (name, field) in ref scriptFields)
|
for (var (name, field) in ref scriptFields)
|
||||||
{
|
{
|
||||||
switch (field.Field.FieldType)
|
switch (field.Type)
|
||||||
{
|
{
|
||||||
case .Bool:
|
case .Bool:
|
||||||
var value = field.GetData<bool>();
|
var value = field.GetData<bool>();
|
||||||
if (ImGui.Checkbox(name.ToScopeCStr!(), &value))
|
if (ImGui.Checkbox(name.CStr(), &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
|
|
||||||
case .SByte:
|
case .SByte:
|
||||||
var value = field.GetData<int8>();
|
var value = field.GetData<int8>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .S8, &value))
|
if (ImGui.DragScalar(name.CStr(), .S8, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Short:
|
case .Short:
|
||||||
var value = field.GetData<int16>();
|
var value = field.GetData<int16>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .S16, &value))
|
if (ImGui.DragScalar(name.CStr(), .S16, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Int:
|
case .Int:
|
||||||
var value = field.GetData<int32>();
|
var value = field.GetData<int32>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .S32, &value))
|
if (ImGui.DragScalar(name.CStr(), .S32, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Int2:
|
case .Int2:
|
||||||
var value = field.GetData<int2>();
|
var value = field.GetData<int2>();
|
||||||
if (ImGui.DragScalarN(name.ToScopeCStr!(), .S32, &value, 2))
|
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 2))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Int3:
|
case .Int3:
|
||||||
var value = field.GetData<int3>();
|
var value = field.GetData<int3>();
|
||||||
if (ImGui.DragScalarN(name.ToScopeCStr!(), .S32, &value, 3))
|
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 3))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Int4:
|
case .Int4:
|
||||||
var value = field.GetData<int4>();
|
var value = field.GetData<int4>();
|
||||||
if (ImGui.DragScalarN(name.ToScopeCStr!(), .S32, &value, 4))
|
if (ImGui.DragScalarN(name.CStr(), .S32, &value, 4))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Long:
|
case .Long:
|
||||||
var value = field.GetData<int64>();
|
var value = field.GetData<int64>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .S64, &value))
|
if (ImGui.DragScalar(name.CStr(), .S64, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
|
|
||||||
case .Byte:
|
case .Byte:
|
||||||
var value = field.GetData<uint8>();
|
var value = field.GetData<uint8>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .U8, &value))
|
if (ImGui.DragScalar(name.CStr(), .U8, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .UShort:
|
case .UShort:
|
||||||
var value = field.GetData<uint16>();
|
var value = field.GetData<uint16>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .U16, &value))
|
if (ImGui.DragScalar(name.CStr(), .U16, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .UInt:
|
case .UInt:
|
||||||
var value = field.GetData<uint32>();
|
var value = field.GetData<uint32>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .U32, &value))
|
if (ImGui.DragScalar(name.CStr(), .U32, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .ULong:
|
case .ULong:
|
||||||
var value = field.GetData<uint64>();
|
var value = field.GetData<uint64>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .U64, &value))
|
if (ImGui.DragScalar(name.CStr(), .U64, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
|
|
||||||
case .Float:
|
case .Float:
|
||||||
var value = field.GetData<float>();
|
var value = field.GetData<float>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .Float, &value))
|
if (ImGui.DragScalar(name.CStr(), .Float, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .float2:
|
case .float2:
|
||||||
var value = field.GetData<float2>();
|
var value = field.GetData<float2>();
|
||||||
@@ -673,19 +675,19 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
case .Double:
|
case .Double:
|
||||||
var value = field.GetData<double>();
|
var value = field.GetData<double>();
|
||||||
if (ImGui.DragScalar(name.ToScopeCStr!(), .Double, &value))
|
if (ImGui.DragScalar(name.CStr(), .Double, &value))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Double2:
|
case .Double2:
|
||||||
var value = field.GetData<double2>();
|
var value = field.GetData<double2>();
|
||||||
if (ImGui.DragScalarN(name.ToScopeCStr!(), .Double, &value, 2))
|
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 2))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Double3:
|
case .Double3:
|
||||||
var value = field.GetData<double3>();
|
var value = field.GetData<double3>();
|
||||||
if (ImGui.DragScalarN(name.ToScopeCStr!(), .Double, &value, 3))
|
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 3))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
case .Double4:
|
case .Double4:
|
||||||
var value = field.GetData<double4>();
|
var value = field.GetData<double4>();
|
||||||
if (ImGui.DragScalarN(name.ToScopeCStr!(), .Double, &value, 4))
|
if (ImGui.DragScalarN(name.CStr(), .Double, &value, 4))
|
||||||
field.SetData(value);
|
field.SetData(value);
|
||||||
|
|
||||||
case .Enum:
|
case .Enum:
|
||||||
@@ -701,7 +703,7 @@ namespace GlitchyEditor.EditWindows
|
|||||||
// TODO!
|
// TODO!
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Log.EngineLogger.Error($"Unhandled field type {field.Field.FieldType}");
|
Log.EngineLogger.Error($"Unhandled field type {field.Type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using GlitchyEngine.Renderer.Animation;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using GlitchyEngine.Core;
|
using GlitchyEngine.Core;
|
||||||
using GlitchyEditor.Assets;
|
using GlitchyEditor.Assets;
|
||||||
|
using GlitchyEngine.Scripting;
|
||||||
|
|
||||||
namespace GlitchyEditor
|
namespace GlitchyEditor
|
||||||
{
|
{
|
||||||
@@ -730,6 +731,15 @@ namespace GlitchyEditor
|
|||||||
ImGui.EndMenu();
|
ImGui.EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ImGui.BeginMenu("Tools", true))
|
||||||
|
{
|
||||||
|
if(ImGui.MenuItem("Reload Scripts"))
|
||||||
|
ScriptEngine.ReloadAssemblies();
|
||||||
|
|
||||||
|
ImGui.EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ImGui.EndMainMenuBar();
|
ImGui.EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,5 +60,15 @@ namespace GlitchyEngine
|
|||||||
delete container;
|
delete container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static mixin ClearDictionaryAndDeleteKeys(var dictionary)
|
||||||
|
{
|
||||||
|
if (dictionary != null)
|
||||||
|
{
|
||||||
|
for (var value in dictionary)
|
||||||
|
delete value.key;
|
||||||
|
delete dictionary;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ public struct ScriptField
|
|||||||
|
|
||||||
public struct ScriptFieldInstance
|
public struct ScriptFieldInstance
|
||||||
{
|
{
|
||||||
public ScriptField Field;
|
public ScriptFieldType Type;
|
||||||
// TODO: I hate this, but we need to be able to store an entire matrix
|
// TODO: I hate this, but we need to be able to store an entire matrix
|
||||||
internal uint8[sizeof(GlitchyEngine.Math.Matrix)] _data;
|
internal uint8[sizeof(GlitchyEngine.Math.Matrix)] _data;
|
||||||
|
|
||||||
public this(ScriptField field)
|
public this(ScriptFieldType type)
|
||||||
{
|
{
|
||||||
Field = field;
|
Type = type;
|
||||||
_data = default;
|
_data = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ public struct ScriptFieldInstance
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public typealias ScriptFieldMap = Dictionary<StringView, ScriptFieldInstance>;
|
public typealias ScriptFieldMap = Dictionary<String, ScriptFieldInstance>;
|
||||||
|
|
||||||
abstract class SharpType : RefCounter
|
abstract class SharpType : RefCounter
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,100 +2,14 @@ using Mono;
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
using GlitchyEngine.World;
|
using GlitchyEngine.World;
|
||||||
using GlitchyEngine.Core;
|
|
||||||
|
|
||||||
namespace GlitchyEngine.Scripting;
|
namespace GlitchyEngine.Scripting;
|
||||||
|
|
||||||
using internal GlitchyEngine.Scripting;
|
using internal GlitchyEngine.Scripting;
|
||||||
|
|
||||||
enum ScriptFieldType
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
|
|
||||||
Class,
|
|
||||||
Enum,
|
|
||||||
Struct,
|
|
||||||
|
|
||||||
// TODO!
|
|
||||||
Bool,
|
|
||||||
|
|
||||||
SByte,
|
|
||||||
Short,
|
|
||||||
Int, Int2, Int3, Int4,
|
|
||||||
Long,
|
|
||||||
Byte,
|
|
||||||
UShort,
|
|
||||||
UInt, // UInt2, UInt3, UInt4,
|
|
||||||
ULong,
|
|
||||||
// Half, Half2, Half3, Half4,
|
|
||||||
Float, float2, float3, float4,
|
|
||||||
Double, Double2, Double3, Double4,
|
|
||||||
|
|
||||||
Entity
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ScriptFieldType
|
|
||||||
{
|
|
||||||
public Type GetBeefType()
|
|
||||||
{
|
|
||||||
switch(this)
|
|
||||||
{
|
|
||||||
case .Bool:
|
|
||||||
return typeof(bool);
|
|
||||||
|
|
||||||
case .SByte:
|
|
||||||
return typeof(int8);
|
|
||||||
case .Short:
|
|
||||||
return typeof(int16);
|
|
||||||
case .Int:
|
|
||||||
return typeof(int32);
|
|
||||||
case .Int2:
|
|
||||||
return typeof(int2);
|
|
||||||
case .Int3:
|
|
||||||
return typeof(int3);
|
|
||||||
case .Int4:
|
|
||||||
return typeof(int4);
|
|
||||||
case .Long:
|
|
||||||
return typeof(int64);
|
|
||||||
|
|
||||||
case .Byte:
|
|
||||||
return typeof(uint8);
|
|
||||||
case .UShort:
|
|
||||||
return typeof(uint16);
|
|
||||||
case .UInt:
|
|
||||||
return typeof(uint32);
|
|
||||||
case .ULong:
|
|
||||||
return typeof(uint64);
|
|
||||||
|
|
||||||
case .Float:
|
|
||||||
return typeof(float);
|
|
||||||
case .float2:
|
|
||||||
return typeof(float2);
|
|
||||||
case .float3:
|
|
||||||
return typeof(float3);
|
|
||||||
case .float4:
|
|
||||||
return typeof(float4);
|
|
||||||
|
|
||||||
case .Double:
|
|
||||||
return typeof(double);
|
|
||||||
case .Double2:
|
|
||||||
return typeof(double2);
|
|
||||||
case .Double3:
|
|
||||||
return typeof(double3);
|
|
||||||
case .Double4:
|
|
||||||
return typeof(double4);
|
|
||||||
|
|
||||||
case .Entity:
|
|
||||||
return typeof(UUID);
|
|
||||||
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static sealed class ScriptEngineHelper
|
static sealed class ScriptEngineHelper
|
||||||
{
|
{
|
||||||
private static Dictionary<StringView, ScriptFieldType> _scriptFieldTypes = new Dictionary<StringView, ScriptFieldType>()
|
private static Dictionary<StringView, ScriptFieldType> _scriptFieldTypes = new Dictionary<StringView, ScriptFieldType>()
|
||||||
@@ -163,7 +77,15 @@ static class ScriptEngine
|
|||||||
|
|
||||||
public static Scene Context => s_Context;
|
public static Scene Context => s_Context;
|
||||||
|
|
||||||
private static Dictionary<UUID, ScriptFieldMap> _entityFields = new .() ~ DeleteDictionaryAndValues!(_);
|
private static Dictionary<UUID, ScriptFieldMap> _entityFields = new .() ~
|
||||||
|
{
|
||||||
|
for (var value in _entityFields.Values)
|
||||||
|
{
|
||||||
|
DeleteDictionaryAndKeys!(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete _;
|
||||||
|
};
|
||||||
|
|
||||||
internal static class Attributes
|
internal static class Attributes
|
||||||
{
|
{
|
||||||
@@ -179,6 +101,11 @@ static class ScriptEngine
|
|||||||
|
|
||||||
ScriptGlue.Init();
|
ScriptGlue.Init();
|
||||||
|
|
||||||
|
LoadScriptAssemblies();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadScriptAssemblies()
|
||||||
|
{
|
||||||
CreateAppDomain("GlitchyEngineScriptRuntime");
|
CreateAppDomain("GlitchyEngineScriptRuntime");
|
||||||
(s_CoreAssembly, s_CoreAssemblyImage) = LoadAssembly("resources/scripts/ScriptCore.dll");
|
(s_CoreAssembly, s_CoreAssemblyImage) = LoadAssembly("resources/scripts/ScriptCore.dll");
|
||||||
(s_AppAssembly, s_AppAssemblyImage) = LoadAssembly("SandboxProject/Assets/Scripts/bin/Sandbox.dll");
|
(s_AppAssembly, s_AppAssemblyImage) = LoadAssembly("SandboxProject/Assets/Scripts/bin/Sandbox.dll");
|
||||||
@@ -186,8 +113,6 @@ static class ScriptEngine
|
|||||||
GetEntitiesFromAssemblies();
|
GetEntitiesFromAssemblies();
|
||||||
|
|
||||||
ScriptGlue.RegisterManagedComponents();
|
ScriptGlue.RegisterManagedComponents();
|
||||||
|
|
||||||
//Samples();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetContext(Scene scene)
|
public static void SetContext(Scene scene)
|
||||||
@@ -206,26 +131,38 @@ static class ScriptEngine
|
|||||||
SetContext(null);
|
SetContext(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InitializeInstance(Entity entity, ScriptComponent* script)
|
public static bool InitializeInstance(Entity entity, ScriptComponent* script)
|
||||||
{
|
{
|
||||||
|
ScriptClass scriptClass = GetScriptClass(script.ScriptClassName);
|
||||||
|
|
||||||
|
if (scriptClass == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
script.Instance = new ScriptInstance(scriptClass);
|
||||||
|
script.Instance..ReleaseRef();
|
||||||
|
|
||||||
_entityScriptInstances[entity.UUID] = script.Instance..AddRef();
|
_entityScriptInstances[entity.UUID] = script.Instance..AddRef();
|
||||||
|
|
||||||
script.Instance.Instantiate(entity.UUID);
|
script.Instance.Instantiate(entity.UUID);
|
||||||
|
|
||||||
CopyEditorFieldsToInstance(entity, script);
|
CopyEditorFieldsToInstance(entity, script);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script)
|
private static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script)
|
||||||
{
|
{
|
||||||
// Technically the map is for a different entity (namely the editor-entity),
|
// Technically the map is for a different entity (namely the editor-entity),
|
||||||
// however the UUID is the same, so we get the correct field map
|
// however the UUID is the same, so we get the correct field map
|
||||||
let fiels = GetScriptFieldMap(entity);
|
let fields = GetScriptFieldMap(entity);
|
||||||
|
|
||||||
for (var (fieldName, field) in fiels)
|
for (var (fieldName, field) in fields)
|
||||||
{
|
{
|
||||||
// TODO: a litte assertion maybe?
|
// TODO: a litte assertion maybe?
|
||||||
|
|
||||||
script.Instance.SetFieldValue(field.Field, field._data);
|
ScriptField scriptField = script.Instance.ScriptClass.Fields[fieldName];
|
||||||
|
|
||||||
|
script.Instance.SetFieldValue(scriptField, field._data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,13 +215,22 @@ static class ScriptEngine
|
|||||||
}
|
}
|
||||||
_entityScripts.Clear();
|
_entityScripts.Clear();
|
||||||
|
|
||||||
if (s_EngineObject == null)
|
for (var sharpClass in _sharpClasses)
|
||||||
{
|
{
|
||||||
s_EngineObject = new ScriptClass("GlitchyEngine.Core", "EngineObject", s_CoreAssemblyImage);
|
sharpClass.value.ReleaseRef();
|
||||||
s_EntityRoot = new ScriptClass("GlitchyEngine", "Entity", s_CoreAssemblyImage);
|
|
||||||
|
|
||||||
Log.EngineLogger.Assert(s_EntityRoot != null);
|
|
||||||
}
|
}
|
||||||
|
_sharpClasses.Clear();
|
||||||
|
|
||||||
|
if (s_EngineObject != null)
|
||||||
|
{
|
||||||
|
s_EngineObject.ReleaseRef();
|
||||||
|
s_EntityRoot.ReleaseRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
s_EngineObject = new ScriptClass("GlitchyEngine.Core", "EngineObject", s_CoreAssemblyImage);
|
||||||
|
s_EntityRoot = new ScriptClass("GlitchyEngine", "Entity", s_CoreAssemblyImage);
|
||||||
|
|
||||||
|
Log.EngineLogger.Assert(s_EntityRoot != null);
|
||||||
|
|
||||||
Attributes.s_ShowInEditorAttribute = Mono.mono_class_from_name(s_CoreAssemblyImage, "GlitchyEngine.Editor", "ShowInEditorAttribute");
|
Attributes.s_ShowInEditorAttribute = Mono.mono_class_from_name(s_CoreAssemblyImage, "GlitchyEngine.Editor", "ShowInEditorAttribute");
|
||||||
|
|
||||||
@@ -311,13 +257,28 @@ static class ScriptEngine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Shutdown()
|
public static void ReloadAssemblies()
|
||||||
{
|
{
|
||||||
/*Mono.mono_assembly_close(s_CoreAssembly);
|
Mono.mono_domain_set(s_RootDomain, false);
|
||||||
s_CoreAssembly = null;
|
|
||||||
|
|
||||||
Mono.mono_domain_unload(s_AppDomain);
|
Mono.mono_domain_unload(s_AppDomain);
|
||||||
s_AppDomain = null;*/
|
|
||||||
|
LoadScriptAssemblies();
|
||||||
|
|
||||||
|
// TODO: ScriptFields might get added
|
||||||
|
// TODO: ScriptField Types may change after reload!
|
||||||
|
// TODO: Scripts may be renamed (probably not detectable (trivially))
|
||||||
|
|
||||||
|
// TODO: Reload in play mode
|
||||||
|
// Only scripts that were changed should actually be reinstatiated
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Shutdown()
|
||||||
|
{
|
||||||
|
Mono.mono_domain_set(s_RootDomain, false);
|
||||||
|
|
||||||
|
Mono.mono_domain_unload(s_AppDomain);
|
||||||
|
s_AppDomain = null;
|
||||||
|
|
||||||
Mono.mono_jit_cleanup(s_RootDomain);
|
Mono.mono_jit_cleanup(s_RootDomain);
|
||||||
s_RootDomain = null;
|
s_RootDomain = null;
|
||||||
@@ -375,19 +336,23 @@ static class ScriptEngine
|
|||||||
|
|
||||||
if (_entityFields.TryGetValue(entity.UUID, var entityFields))
|
if (_entityFields.TryGetValue(entity.UUID, var entityFields))
|
||||||
{
|
{
|
||||||
entityFields.Clear();
|
ClearDictionaryAndDeleteKeys!(entityFields);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entityFields = new Dictionary<StringView, ScriptFieldInstance>();
|
entityFields = new ScriptFieldMap();
|
||||||
_entityFields.Add(entity.UUID, entityFields);
|
_entityFields.Add(entity.UUID, entityFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
let scriptComponent = entity.GetComponent<ScriptComponent>();
|
let scriptComponent = entity.GetComponent<ScriptComponent>();
|
||||||
|
|
||||||
for (let (fieldName, field) in scriptComponent.ScriptClass.Fields)
|
ScriptClass scriptClass = GetScriptClass(scriptComponent.ScriptClassName);
|
||||||
|
|
||||||
|
Log.EngineLogger.AssertDebug(scriptClass != null);
|
||||||
|
|
||||||
|
for (let (fieldName, field) in scriptClass.Fields)
|
||||||
{
|
{
|
||||||
entityFields.Add(fieldName, ScriptFieldInstance(field));
|
entityFields.Add(new String(fieldName), ScriptFieldInstance(field.FieldType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,6 +376,12 @@ static class ScriptEngine
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ScriptClass GetScriptClass(StringView name)
|
||||||
|
{
|
||||||
|
EntityClasses.TryGetValue(name, let scriptClass);
|
||||||
|
|
||||||
|
return scriptClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
using GlitchyEngine.Math;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Scripting;
|
||||||
|
|
||||||
|
enum ScriptFieldType
|
||||||
|
{
|
||||||
|
case None;
|
||||||
|
|
||||||
|
case Class;
|
||||||
|
case Enum;
|
||||||
|
case Struct;
|
||||||
|
|
||||||
|
case Bool;
|
||||||
|
|
||||||
|
case SByte;
|
||||||
|
case Short;
|
||||||
|
case Int, Int2, Int3, Int4;
|
||||||
|
case Long;
|
||||||
|
case Byte;
|
||||||
|
case UShort;
|
||||||
|
case UInt; // UInt2, UInt3, UInt4;
|
||||||
|
case ULong;
|
||||||
|
|
||||||
|
case Float, float2, float3, float4;
|
||||||
|
case Double, Double2, Double3, Double4;
|
||||||
|
|
||||||
|
case Entity;
|
||||||
|
|
||||||
|
public Type GetBeefType()
|
||||||
|
{
|
||||||
|
switch(this)
|
||||||
|
{
|
||||||
|
case .Bool:
|
||||||
|
return typeof(bool);
|
||||||
|
|
||||||
|
case .SByte:
|
||||||
|
return typeof(int8);
|
||||||
|
case .Short:
|
||||||
|
return typeof(int16);
|
||||||
|
case .Int:
|
||||||
|
return typeof(int32);
|
||||||
|
case .Int2:
|
||||||
|
return typeof(int2);
|
||||||
|
case .Int3:
|
||||||
|
return typeof(int3);
|
||||||
|
case .Int4:
|
||||||
|
return typeof(int4);
|
||||||
|
case .Long:
|
||||||
|
return typeof(int64);
|
||||||
|
|
||||||
|
case .Byte:
|
||||||
|
return typeof(uint8);
|
||||||
|
case .UShort:
|
||||||
|
return typeof(uint16);
|
||||||
|
case .UInt:
|
||||||
|
return typeof(uint32);
|
||||||
|
case .ULong:
|
||||||
|
return typeof(uint64);
|
||||||
|
|
||||||
|
case .Float:
|
||||||
|
return typeof(float);
|
||||||
|
case .float2:
|
||||||
|
return typeof(float2);
|
||||||
|
case .float3:
|
||||||
|
return typeof(float3);
|
||||||
|
case .float4:
|
||||||
|
return typeof(float4);
|
||||||
|
|
||||||
|
case .Double:
|
||||||
|
return typeof(double);
|
||||||
|
case .Double2:
|
||||||
|
return typeof(double2);
|
||||||
|
case .Double3:
|
||||||
|
return typeof(double3);
|
||||||
|
case .Double4:
|
||||||
|
return typeof(double4);
|
||||||
|
|
||||||
|
case .Entity:
|
||||||
|
return typeof(UUID);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -57,6 +57,10 @@ static class ScriptGlue
|
|||||||
|
|
||||||
public static void RegisterManagedComponents()
|
public static void RegisterManagedComponents()
|
||||||
{
|
{
|
||||||
|
s_AddComponentMethods.Clear();
|
||||||
|
s_HasComponentMethods.Clear();
|
||||||
|
s_RemoveComponentMethods.Clear();
|
||||||
|
|
||||||
RegisterComponent<TransformComponent>("GlitchyEngine.Transform");
|
RegisterComponent<TransformComponent>("GlitchyEngine.Transform");
|
||||||
RegisterComponent<Rigidbody2DComponent>("GlitchyEngine.RigidBody2D");
|
RegisterComponent<Rigidbody2DComponent>("GlitchyEngine.RigidBody2D");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -507,14 +507,20 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
struct ScriptComponent : IDisposableComponent
|
struct ScriptComponent : IDisposableComponent
|
||||||
{
|
{
|
||||||
private ScriptClass _scriptClass = null;
|
private String _scriptClassName = null;
|
||||||
|
|
||||||
private ScriptInstance _instance = null;
|
private ScriptInstance _instance = null;
|
||||||
|
|
||||||
public ScriptClass ScriptClass
|
public StringView ScriptClassName
|
||||||
{
|
{
|
||||||
get => _scriptClass;
|
get => _scriptClassName;
|
||||||
set mut => SetReference!(_scriptClass, value);
|
set mut
|
||||||
|
{
|
||||||
|
if (_scriptClassName == null)
|
||||||
|
_scriptClassName = new String(value);
|
||||||
|
|
||||||
|
_scriptClassName.Set(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptInstance Instance
|
public ScriptInstance Instance
|
||||||
@@ -525,16 +531,13 @@ namespace GlitchyEngine.World
|
|||||||
set mut => SetReference!(_instance, value);
|
set mut => SetReference!(_instance, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets whether or not this script component has a script assigned (that means ScriptClass isn't null).
|
|
||||||
public bool HasScript => _scriptClass != null;
|
|
||||||
|
|
||||||
public bool IsInitialized => _instance?.IsInitialized ?? false;
|
public bool IsInitialized => _instance?.IsInitialized ?? false;
|
||||||
|
|
||||||
public bool IsCreated => _instance?.IsCreated ?? false;
|
public bool IsCreated => _instance?.IsCreated ?? false;
|
||||||
|
|
||||||
public void Dispose() mut
|
public void Dispose() mut
|
||||||
{
|
{
|
||||||
ReleaseRefAndNullify!(_scriptClass);
|
delete _scriptClassName;
|
||||||
ReleaseRefAndNullify!(_instance);
|
ReleaseRefAndNullify!(_instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,11 +93,10 @@ namespace GlitchyEngine.World
|
|||||||
Entity targetEntity = target.GetEntityByID(sourceEntity.UUID);
|
Entity targetEntity = target.GetEntityByID(sourceEntity.UUID);
|
||||||
ScriptComponent* targetComponent = targetEntity.AddComponent<ScriptComponent>();
|
ScriptComponent* targetComponent = targetEntity.AddComponent<ScriptComponent>();
|
||||||
|
|
||||||
targetComponent.ScriptClass = sourceComponent.ScriptClass;
|
targetComponent.ScriptClassName = sourceComponent.ScriptClassName;
|
||||||
targetComponent.Instance = new ScriptInstance(sourceComponent.ScriptClass);
|
|
||||||
targetComponent.Instance..ReleaseRef();
|
|
||||||
|
|
||||||
// Initializes the created instance
|
// Initializes the created instance
|
||||||
|
// TODO: this returns false, if no script with ScriptClassName exists, we have to handle this case correctly I think.
|
||||||
ScriptEngine.InitializeInstance(targetEntity, targetComponent);
|
ScriptEngine.InitializeInstance(targetEntity, targetComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,9 +189,11 @@ class SceneSerializer
|
|||||||
|
|
||||||
SerializeComponent<ScriptComponent>(writer, entity, "ScriptComponent", scope (component) =>
|
SerializeComponent<ScriptComponent>(writer, entity, "ScriptComponent", scope (component) =>
|
||||||
{
|
{
|
||||||
Serialize.Value(writer, "ScriptClass", component.ScriptClass?.FullName);
|
Serialize.Value(writer, "ScriptClass", component.ScriptClassName);
|
||||||
|
|
||||||
if (component.HasScript)
|
//if (component.HasScript)
|
||||||
|
// TODO: Thats not a good check, I think. At least we know the script class is valid
|
||||||
|
if (ScriptEngine.GetScriptClass(component.ScriptClassName) != null)
|
||||||
{
|
{
|
||||||
let fields = ScriptEngine.GetScriptFieldMap(entity);
|
let fields = ScriptEngine.GetScriptFieldMap(entity);
|
||||||
|
|
||||||
@@ -201,11 +203,10 @@ class SceneSerializer
|
|||||||
{
|
{
|
||||||
for (var (fieldName, fieldInstance) in fields)
|
for (var (fieldName, fieldInstance) in fields)
|
||||||
{
|
{
|
||||||
if (fieldInstance.Field.FieldType == .None)
|
if (fieldInstance.Type == .None)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
switch (fieldInstance.Type)
|
||||||
switch (fieldInstance.Field.FieldType)
|
|
||||||
{
|
{
|
||||||
case .Enum, .Class, .Struct:
|
case .Enum, .Class, .Struct:
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
@@ -213,10 +214,10 @@ class SceneSerializer
|
|||||||
writer.Identifier(fieldName);
|
writer.Identifier(fieldName);
|
||||||
|
|
||||||
String str = scope .();
|
String str = scope .();
|
||||||
fieldInstance.Field.FieldType.ToString(str);
|
fieldInstance.Type.ToString(str);
|
||||||
writer.Type(str);
|
writer.Type(str);
|
||||||
|
|
||||||
Serialize.Value(writer, ValueView(fieldInstance.Field.FieldType.GetBeefType(), &fieldInstance.[Friend]_data), gBonEnv);
|
Serialize.Value(writer, ValueView(fieldInstance.Type.GetBeefType(), &fieldInstance.[Friend]_data), gBonEnv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -558,15 +559,18 @@ class SceneSerializer
|
|||||||
|
|
||||||
if (scriptClassName != null)
|
if (scriptClassName != null)
|
||||||
{
|
{
|
||||||
if (ScriptEngine.EntityClasses.TryGetValue(scriptClassName, let scriptClass))
|
//if (ScriptEngine.EntityClasses.TryGetValue(scriptClassName, let scriptClass))
|
||||||
{
|
/*{
|
||||||
component.ScriptClass = scriptClass;
|
component.ScriptClass = scriptClass;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
component.ScriptClassName = scriptClassName;
|
||||||
|
|
||||||
delete scriptClassName;
|
delete scriptClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.HasScript)
|
//if (component.HasScript)
|
||||||
|
if (ScriptEngine.GetScriptClass(component.ScriptClassName) != null)
|
||||||
{
|
{
|
||||||
// This whole operation is technically a bit junk, because we are not guaranteed to successfully deserialize the scene,
|
// This whole operation is technically a bit junk, because we are not guaranteed to successfully deserialize the scene,
|
||||||
// however we are editing the ScriptEngine because it doesn't care about which scene is active right now.
|
// however we are editing the ScriptEngine because it doesn't care about which scene is active right now.
|
||||||
@@ -606,15 +610,18 @@ class SceneSerializer
|
|||||||
|
|
||||||
StringView fieldName = Try!(reader.Identifier());
|
StringView fieldName = Try!(reader.Identifier());
|
||||||
|
|
||||||
if (fields.ContainsKey(fieldName))
|
// Allocate a string on the stack, because the dictionary uses a string as key
|
||||||
|
String fieldNameString = scope .(fieldName);
|
||||||
|
|
||||||
|
if (fields.ContainsKey(fieldNameString))
|
||||||
{
|
{
|
||||||
var field = ref fields[fieldName];
|
var field = ref fields[fieldNameString];
|
||||||
|
|
||||||
Result<StringView> fieldTypeName = reader.Type();
|
Result<StringView> fieldTypeName = reader.Type();
|
||||||
|
|
||||||
if (fieldTypeName case .Err)
|
if (fieldTypeName case .Err)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Failed to read field type for field \"{fieldName}\" in script \"{component.ScriptClass.FullName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
Log.EngineLogger.Error($"Failed to read field type for field \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||||
reader.FileEntrySkip(1);
|
reader.FileEntrySkip(1);
|
||||||
dontRemoveComma = true;
|
dontRemoveComma = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -622,9 +629,9 @@ class SceneSerializer
|
|||||||
|
|
||||||
Result<ScriptFieldType> fieldType = Enum.Parse<ScriptFieldType>(fieldTypeName, true);
|
Result<ScriptFieldType> fieldType = Enum.Parse<ScriptFieldType>(fieldTypeName, true);
|
||||||
|
|
||||||
if ((fieldType case .Err) || (fieldType != field.Field.FieldType))
|
if ((fieldType case .Err) || (fieldType != field.Type))
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Unexpected field type (\"{fieldTypeName}\" instead of \"{field.Field.FieldType}\" for field: \"{fieldName}\" in script \"{component.ScriptClass.FullName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
Log.EngineLogger.Error($"Unexpected field type (\"{fieldTypeName}\" instead of \"{field.Type}\" for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||||
reader.FileEntrySkip(1);
|
reader.FileEntrySkip(1);
|
||||||
dontRemoveComma = true;
|
dontRemoveComma = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -632,9 +639,9 @@ class SceneSerializer
|
|||||||
|
|
||||||
void* data = &field.[Friend]_data;
|
void* data = &field.[Friend]_data;
|
||||||
|
|
||||||
if (Deserialize.Value(reader, ValueView(field.Field.FieldType.GetBeefType(), data), gBonEnv) case .Err)
|
if (Deserialize.Value(reader, ValueView(field.Type.GetBeefType(), data), gBonEnv) case .Err)
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Failed to deserialize data for field: \"{fieldName}\" in script \"{component.ScriptClass.FullName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
Log.EngineLogger.Error($"Failed to deserialize data for field: \"{fieldName}\" in script \"{component.ScriptClassName}\" of entity {entity.UUID} (\"{entity.Name}\")");
|
||||||
reader.FileEntrySkip(1);
|
reader.FileEntrySkip(1);
|
||||||
dontRemoveComma = true;
|
dontRemoveComma = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -642,7 +649,7 @@ class SceneSerializer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.EngineLogger.Error($"Script \"{component.ScriptClass.FullName}\" doesn't have a field with name \"{fieldName}\". (Entity {entity.UUID} (\"{entity.Name}\"))");
|
Log.EngineLogger.Error($"Script \"{component.ScriptClassName}\" doesn't have a field with name \"{fieldName}\". (Entity {entity.UUID} (\"{entity.Name}\"))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user