diff --git a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf index dfe793a..29f49f4 100644 --- a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf +++ b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf @@ -437,13 +437,17 @@ namespace GlitchyEditor.EditWindows StringView search = StringView(); - if (ImGui.InputText("##ScriptName", &buffer, buffer.Count)) - { - search = StringView(&buffer); - } + char8* scriptLabel = scriptComponent.Instance?.ScriptClass.FullName.ToScopeCStr!() ?? "Select Script..."; - if (ImGui.BeginCombo("##Type", scriptComponent.Instance?.ScriptClass.FullName.ToScopeCStr!())) + if (ImGui.Button(scriptLabel)) + ImGui.OpenPopup("SelectScript"); + + if (ImGui.BeginPopup("SelectScript")) { + ImGui.InputText("##ScriptSearch", &buffer, buffer.Count); + + search = StringView(&buffer); + for (let (className, script) in ScriptEngine.EntityClasses) { if (!search.IsWhiteSpace && !className.Contains(search, true)) @@ -457,10 +461,9 @@ namespace GlitchyEditor.EditWindows ScriptEngine.InitializeInstance(entity, scriptComponent); } } - - ImGui.EndCombo(); + ImGui.EndPopup(); } - + /*T GetFieldValue() { return scriptComponent.Instance.GetFieldValue(monoField); @@ -473,17 +476,17 @@ namespace GlitchyEditor.EditWindows T GetFieldValue(ScriptInstance scriptInstance, in ScriptField scriptField) { - return scriptInstance.GetFieldValue(scriptField.[Friend]_monoField); + return scriptInstance.GetFieldValue(scriptField); } void GetFieldValue(ScriptInstance scriptInstance, in ScriptField scriptField, out T value) { - value = scriptInstance.GetFieldValue(scriptField.[Friend]_monoField); + value = scriptInstance.GetFieldValue(scriptField); } void SetFieldValue(ScriptInstance scriptInstance, in ScriptField scriptField, in T value) { - scriptInstance.SetFieldValue(scriptField.[Friend]_monoField, value); + scriptInstance.SetFieldValue(scriptField, value); } @@ -618,7 +621,7 @@ namespace GlitchyEditor.EditWindows } }*/ - if (scriptComponent.Instance?.IsInstatiated == true) + if (scriptComponent.Instance?.IsInitialized == true) { ShowClassFields(scriptComponent.Instance.ScriptClass, scriptComponent.Instance); } diff --git a/GlitchyEngine/src/Scripting/ScriptClass.bf b/GlitchyEngine/src/Scripting/ScriptClass.bf index 56fd7af..c236c24 100644 --- a/GlitchyEngine/src/Scripting/ScriptClass.bf +++ b/GlitchyEngine/src/Scripting/ScriptClass.bf @@ -87,6 +87,8 @@ class SharpClass : SharpType if (sharpType == null) continue; + + sharpType.ReleaseRef(); } //Mono.MonoTypeEnum fieldType = Mono.Mono.mono_type_get_type(type); @@ -182,6 +184,11 @@ class ScriptClass : SharpClass { MonoObject* instance = Mono.mono_object_new(ScriptEngine.[Friend]s_AppDomain, _monoClass); + // TODO: I think this is a bit dirty + // Invoke empty constructor to fill fields + Mono.mono_runtime_object_init(instance); + + // Invoke constructor with UUID #unwarn ScriptEngine.[Friend]s_EngineObject.Invoke(ScriptEngine.[Friend]s_EngineObject._constructor, instance, &uuid); diff --git a/GlitchyEngine/src/Scripting/ScriptEngine.bf b/GlitchyEngine/src/Scripting/ScriptEngine.bf index 3585114..7d0bba2 100644 --- a/GlitchyEngine/src/Scripting/ScriptEngine.bf +++ b/GlitchyEngine/src/Scripting/ScriptEngine.bf @@ -254,7 +254,7 @@ static class ScriptEngine StringView typeName = StringView(Mono.mono_type_get_name(monoType)); if (_sharpClasses.TryGetValue(typeName, let sharpType)) - return sharpType; + return sharpType..AddRef(); Mono.MonoTypeEnum fieldType = Mono.Mono.mono_type_get_type(monoType); diff --git a/GlitchyEngine/src/Scripting/ScriptInstance.bf b/GlitchyEngine/src/Scripting/ScriptInstance.bf index a3a0f9a..85d1062 100644 --- a/GlitchyEngine/src/Scripting/ScriptInstance.bf +++ b/GlitchyEngine/src/Scripting/ScriptInstance.bf @@ -12,8 +12,14 @@ class ScriptInstance : RefCounter private uint32 _gcHandle; public ScriptClass ScriptClass => _scriptClass; + + /// Gets whether or not the instance has ben initialized. + public bool IsInitialized => _instance != null; - public bool IsInstatiated => _instance != null; + /// Gets whether or not the Create-Method of this instance has been called before. + public bool IsCreated => _isCreated; + + private bool _isCreated = false; public this(ScriptClass scriptClass) { @@ -40,6 +46,7 @@ class ScriptInstance : RefCounter public void InvokeOnCreate() { _scriptClass.OnCreate(_instance); + _isCreated = true; } public void InvokeOnUpdate(float deltaTime) @@ -52,21 +59,97 @@ class ScriptInstance : RefCounter _scriptClass.OnDestroy(_instance); } - public T GetFieldValue(MonoClassField* field) + public T GetFieldValue(ScriptField field) { - return _scriptClass.GetFieldValue(_instance, field); + return _scriptClass.GetFieldValue(_instance, field.[Friend]_monoField); } - public void SetFieldValue(MonoClassField* field, in T value) + public void SetFieldValue(ScriptField field, in T value) { - _scriptClass.SetFieldValue(_instance, field, value); + _scriptClass.SetFieldValue(_instance, field.[Friend]_monoField, value); } public void CopyEditorFieldsTo(ScriptInstance target) { for (let (fieldName, field) in ScriptClass.Fields) { + switch (field.FieldType) + { + case .Bool: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + case .SByte: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + case .Short: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + case .Int: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + case .Long: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + + case .Byte: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + case .UShort: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + case .UInt: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + case .ULong: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + + case .Float: + var value = GetFieldValue(field); + target.SetFieldValue(field, value); + + /*case .Vector2: + GetFieldValue(field, var value); + if (ImGui.EditVector2(fieldName, ref value)) + SetFieldValue(field, value); + case .Vector3: + GetFieldValue(field, var value); + if (ImGui.EditVector3(fieldName, ref value)) + SetFieldValue(field, value); + case .Vector4: + GetFieldValue(field, var value); + if (ImGui.EditVector4(fieldName, ref value)) + SetFieldValue(field, value); + + case .Double: + var value = GetFieldValue(field); + if (ImGui.DragScalar(fieldName.ToScopeCStr!(), .Double, &value)) + SetFieldValue(field, value); + + case .Entity: + // TODO! + + case .Class: + // TODO! + case .Enum: + // TODO! + case .Struct: + // TODO!*/ + /*case .Struct: + ShowStructFields(); + { + + uint8[128] bla = ?; + GetFieldValue(scriptField); + + Mono.MonoObject* dings = (Mono.MonoObject*)&bla; + + //ShowFields + }*/ + default: + Log.EngineLogger.Error($"Unhandled field type {field.FieldType}"); + } } } } \ No newline at end of file diff --git a/GlitchyEngine/src/World/Components/Components.bf b/GlitchyEngine/src/World/Components/Components.bf index d8643bb..6faf5ec 100644 --- a/GlitchyEngine/src/World/Components/Components.bf +++ b/GlitchyEngine/src/World/Components/Components.bf @@ -457,7 +457,9 @@ namespace GlitchyEngine.World set mut => SetReference!(_instance, value); } - public bool InInstantiated => _instance?.IsInstatiated ?? false; + public bool IsInitialized => _instance?.IsInitialized ?? false; + + public bool IsCreated => _instance?.IsCreated ?? false; public void Dispose() mut { diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 9215a27..db498ce 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -73,7 +73,6 @@ namespace GlitchyEngine.World // TODO: perhaps use reflection and comptime // Copy components - //CopyComponents(this, target); /* Parent will be copied below*/ CopyComponents(this, target); CopyComponents(this, target); CopyComponents(this, target); @@ -85,8 +84,8 @@ namespace GlitchyEngine.World CopyComponents(this, target); CopyComponents(this, target); CopyComponents(this, target); - //CopyComponents(this, target); - + + // Copy ScriptComponents... needs extra handling for the script instances for (let (sourceHandle, sourceComponent) in _ecsWorld.Enumerate()) { Entity sourceEntity = .(sourceHandle, this); @@ -94,15 +93,16 @@ namespace GlitchyEngine.World Entity targetEntity = target.GetEntityByID(sourceEntity.UUID); ScriptComponent* targetComponent = targetEntity.AddComponent(); - // TODO: Do proper copy - targetComponent.Instance = new ScriptInstance(sourceComponent.Instance.ScriptClass); targetComponent.Instance..ReleaseRef(); + // We need an instance so we can copy the variables to it + ScriptEngine.InitializeInstance(targetEntity, targetComponent); + sourceComponent.Instance.CopyEditorFieldsTo(targetComponent.Instance); } - // Copy transforms + // Copy transforms... needs special handling for the Parent<->Child relations for (let (sourceHandle, sourceTransform) in _ecsWorld.Enumerate()) { Entity sourceEntity = Entity(sourceHandle, this); @@ -272,9 +272,10 @@ namespace GlitchyEngine.World // Run scripts for (var (entity, script) in _ecsWorld.Enumerate()) { - if (!script.InInstantiated) + if (!script.IsCreated) { - ScriptEngine.InitializeInstance(Entity(entity, this), script); + if (!script.IsInitialized) + ScriptEngine.InitializeInstance(Entity(entity, this), script); if (mode.HasFlag(.Runtime)) script.Instance.InvokeOnCreate(); diff --git a/GlitchyEngineHelper/src/Mono/Mono.bf b/GlitchyEngineHelper/src/Mono/Mono.bf index bf99fc5..426503f 100644 --- a/GlitchyEngineHelper/src/Mono/Mono.bf +++ b/GlitchyEngineHelper/src/Mono/Mono.bf @@ -105,6 +105,9 @@ static class Mono [LinkName(.C)] public static extern MonoObject* mono_runtime_invoke(MonoMethod* method, void* obj, void** param, MonoObject** exc); + [LinkName(.C)] + public static extern MonoMethod* mono_object_get_virtual_method(MonoObject* obj, MonoMethod* method); + [LinkName(.C)] public static extern void* mono_object_unbox(MonoObject* obj); diff --git a/ScriptCore/Core/EngineObject.cs b/ScriptCore/Core/EngineObject.cs index 76e775c..5587146 100644 --- a/ScriptCore/Core/EngineObject.cs +++ b/ScriptCore/Core/EngineObject.cs @@ -1,6 +1,8 @@ +using System; + namespace GlitchyEngine.Core; -public class EngineObject +public abstract class EngineObject { protected internal UUID _uuid; @@ -12,8 +14,7 @@ public class EngineObject /// /// Empty constructor not used. Do NOT USE! /// - protected EngineObject() - {} + protected EngineObject() { } /// /// Creates a new EngineObject with the given ID.