Script default values after init, Fix memory leak, Copy Script values on Play

This commit is contained in:
Simon Lübeß
2023-05-31 14:38:07 +02:00
parent 6a59deb9e2
commit f4607a6210
8 changed files with 130 additions and 30 deletions
@@ -437,13 +437,17 @@ namespace GlitchyEditor.EditWindows
StringView search = StringView(); StringView search = StringView();
if (ImGui.InputText("##ScriptName", &buffer, buffer.Count)) char8* scriptLabel = scriptComponent.Instance?.ScriptClass.FullName.ToScopeCStr!() ?? "Select Script...";
{
search = StringView(&buffer);
}
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) for (let (className, script) in ScriptEngine.EntityClasses)
{ {
if (!search.IsWhiteSpace && !className.Contains(search, true)) if (!search.IsWhiteSpace && !className.Contains(search, true))
@@ -457,8 +461,7 @@ namespace GlitchyEditor.EditWindows
ScriptEngine.InitializeInstance(entity, scriptComponent); ScriptEngine.InitializeInstance(entity, scriptComponent);
} }
} }
ImGui.EndPopup();
ImGui.EndCombo();
} }
/*T GetFieldValue<T>() /*T GetFieldValue<T>()
@@ -473,17 +476,17 @@ namespace GlitchyEditor.EditWindows
T GetFieldValue<T>(ScriptInstance scriptInstance, in ScriptField scriptField) T GetFieldValue<T>(ScriptInstance scriptInstance, in ScriptField scriptField)
{ {
return scriptInstance.GetFieldValue<T>(scriptField.[Friend]_monoField); return scriptInstance.GetFieldValue<T>(scriptField);
} }
void GetFieldValue<T>(ScriptInstance scriptInstance, in ScriptField scriptField, out T value) void GetFieldValue<T>(ScriptInstance scriptInstance, in ScriptField scriptField, out T value)
{ {
value = scriptInstance.GetFieldValue<T>(scriptField.[Friend]_monoField); value = scriptInstance.GetFieldValue<T>(scriptField);
} }
void SetFieldValue<T>(ScriptInstance scriptInstance, in ScriptField scriptField, in T value) void SetFieldValue<T>(ScriptInstance scriptInstance, in ScriptField scriptField, in T value)
{ {
scriptInstance.SetFieldValue<T>(scriptField.[Friend]_monoField, value); scriptInstance.SetFieldValue<T>(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); ShowClassFields(scriptComponent.Instance.ScriptClass, scriptComponent.Instance);
} }
@@ -87,6 +87,8 @@ class SharpClass : SharpType
if (sharpType == null) if (sharpType == null)
continue; continue;
sharpType.ReleaseRef();
} }
//Mono.MonoTypeEnum fieldType = Mono.Mono.mono_type_get_type(type); //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); 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 #unwarn
ScriptEngine.[Friend]s_EngineObject.Invoke(ScriptEngine.[Friend]s_EngineObject._constructor, instance, &uuid); ScriptEngine.[Friend]s_EngineObject.Invoke(ScriptEngine.[Friend]s_EngineObject._constructor, instance, &uuid);
+1 -1
View File
@@ -254,7 +254,7 @@ static class ScriptEngine
StringView typeName = StringView(Mono.mono_type_get_name(monoType)); StringView typeName = StringView(Mono.mono_type_get_name(monoType));
if (_sharpClasses.TryGetValue(typeName, let sharpType)) if (_sharpClasses.TryGetValue(typeName, let sharpType))
return sharpType; return sharpType..AddRef();
Mono.MonoTypeEnum fieldType = Mono.Mono.mono_type_get_type(monoType); Mono.MonoTypeEnum fieldType = Mono.Mono.mono_type_get_type(monoType);
+88 -5
View File
@@ -13,7 +13,13 @@ class ScriptInstance : RefCounter
public ScriptClass ScriptClass => _scriptClass; public ScriptClass ScriptClass => _scriptClass;
public bool IsInstatiated => _instance != null; /// Gets whether or not the instance has ben initialized.
public bool IsInitialized => _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) public this(ScriptClass scriptClass)
{ {
@@ -40,6 +46,7 @@ class ScriptInstance : RefCounter
public void InvokeOnCreate() public void InvokeOnCreate()
{ {
_scriptClass.OnCreate(_instance); _scriptClass.OnCreate(_instance);
_isCreated = true;
} }
public void InvokeOnUpdate(float deltaTime) public void InvokeOnUpdate(float deltaTime)
@@ -52,21 +59,97 @@ class ScriptInstance : RefCounter
_scriptClass.OnDestroy(_instance); _scriptClass.OnDestroy(_instance);
} }
public T GetFieldValue<T>(MonoClassField* field) public T GetFieldValue<T>(ScriptField field)
{ {
return _scriptClass.GetFieldValue<T>(_instance, field); return _scriptClass.GetFieldValue<T>(_instance, field.[Friend]_monoField);
} }
public void SetFieldValue<T>(MonoClassField* field, in T value) public void SetFieldValue<T>(ScriptField field, in T value)
{ {
_scriptClass.SetFieldValue<T>(_instance, field, value); _scriptClass.SetFieldValue<T>(_instance, field.[Friend]_monoField, value);
} }
public void CopyEditorFieldsTo(ScriptInstance target) public void CopyEditorFieldsTo(ScriptInstance target)
{ {
for (let (fieldName, field) in ScriptClass.Fields) for (let (fieldName, field) in ScriptClass.Fields)
{ {
switch (field.FieldType)
{
case .Bool:
var value = GetFieldValue<bool>(field);
target.SetFieldValue(field, value);
case .SByte:
var value = GetFieldValue<int8>(field);
target.SetFieldValue(field, value);
case .Short:
var value = GetFieldValue<int16>(field);
target.SetFieldValue(field, value);
case .Int:
var value = GetFieldValue<int32>(field);
target.SetFieldValue(field, value);
case .Long:
var value = GetFieldValue<int64>(field);
target.SetFieldValue(field, value);
case .Byte:
var value = GetFieldValue<uint8>(field);
target.SetFieldValue(field, value);
case .UShort:
var value = GetFieldValue<uint16>(field);
target.SetFieldValue(field, value);
case .UInt:
var value = GetFieldValue<uint32>(field);
target.SetFieldValue(field, value);
case .ULong:
var value = GetFieldValue<uint64>(field);
target.SetFieldValue(field, value);
case .Float:
var value = GetFieldValue<float>(field);
target.SetFieldValue(field, value);
/*case .Vector2:
GetFieldValue<Vector2>(field, var value);
if (ImGui.EditVector2(fieldName, ref value))
SetFieldValue(field, value);
case .Vector3:
GetFieldValue<Vector3>(field, var value);
if (ImGui.EditVector3(fieldName, ref value))
SetFieldValue(field, value);
case .Vector4:
GetFieldValue<Vector4>(field, var value);
if (ImGui.EditVector4(fieldName, ref value))
SetFieldValue(field, value);
case .Double:
var value = GetFieldValue<double>(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<uint8[128]>(scriptField);
Mono.MonoObject* dings = (Mono.MonoObject*)&bla;
//ShowFields
}*/
default:
Log.EngineLogger.Error($"Unhandled field type {field.FieldType}");
}
} }
} }
} }
@@ -457,7 +457,9 @@ namespace GlitchyEngine.World
set mut => SetReference!(_instance, value); 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 public void Dispose() mut
{ {
+8 -7
View File
@@ -73,7 +73,6 @@ namespace GlitchyEngine.World
// TODO: perhaps use reflection and comptime // TODO: perhaps use reflection and comptime
// Copy components // Copy components
//CopyComponents<TransformComponent>(this, target); /* Parent will be copied below*/
CopyComponents<MeshRendererComponent>(this, target); CopyComponents<MeshRendererComponent>(this, target);
CopyComponents<MeshComponent>(this, target); CopyComponents<MeshComponent>(this, target);
CopyComponents<EditorComponent>(this, target); CopyComponents<EditorComponent>(this, target);
@@ -85,8 +84,8 @@ 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 ScriptComponents... needs extra handling for the script instances
for (let (sourceHandle, sourceComponent) in _ecsWorld.Enumerate<ScriptComponent>()) for (let (sourceHandle, sourceComponent) in _ecsWorld.Enumerate<ScriptComponent>())
{ {
Entity sourceEntity = .(sourceHandle, this); Entity sourceEntity = .(sourceHandle, this);
@@ -94,15 +93,16 @@ 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>();
// TODO: Do proper copy
targetComponent.Instance = new ScriptInstance(sourceComponent.Instance.ScriptClass); targetComponent.Instance = new ScriptInstance(sourceComponent.Instance.ScriptClass);
targetComponent.Instance..ReleaseRef(); targetComponent.Instance..ReleaseRef();
// We need an instance so we can copy the variables to it
ScriptEngine.InitializeInstance(targetEntity, targetComponent);
sourceComponent.Instance.CopyEditorFieldsTo(targetComponent.Instance); sourceComponent.Instance.CopyEditorFieldsTo(targetComponent.Instance);
} }
// Copy transforms // Copy transforms... needs special handling for the Parent<->Child relations
for (let (sourceHandle, sourceTransform) in _ecsWorld.Enumerate<TransformComponent>()) for (let (sourceHandle, sourceTransform) in _ecsWorld.Enumerate<TransformComponent>())
{ {
Entity sourceEntity = Entity(sourceHandle, this); Entity sourceEntity = Entity(sourceHandle, this);
@@ -272,9 +272,10 @@ namespace GlitchyEngine.World
// Run scripts // Run scripts
for (var (entity, script) in _ecsWorld.Enumerate<ScriptComponent>()) for (var (entity, script) in _ecsWorld.Enumerate<ScriptComponent>())
{ {
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)) if (mode.HasFlag(.Runtime))
script.Instance.InvokeOnCreate(); script.Instance.InvokeOnCreate();
+3
View File
@@ -105,6 +105,9 @@ static class Mono
[LinkName(.C)] [LinkName(.C)]
public static extern MonoObject* mono_runtime_invoke(MonoMethod* method, void* obj, void** param, MonoObject** exc); 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)] [LinkName(.C)]
public static extern void* mono_object_unbox(MonoObject* obj); public static extern void* mono_object_unbox(MonoObject* obj);
+4 -3
View File
@@ -1,6 +1,8 @@
using System;
namespace GlitchyEngine.Core; namespace GlitchyEngine.Core;
public class EngineObject public abstract class EngineObject
{ {
protected internal UUID _uuid; protected internal UUID _uuid;
@@ -12,8 +14,7 @@ public class EngineObject
/// <summary> /// <summary>
/// Empty constructor not used. Do NOT USE! /// Empty constructor not used. Do NOT USE!
/// </summary> /// </summary>
protected EngineObject() protected EngineObject() { }
{}
/// <summary> /// <summary>
/// Creates a new EngineObject with the given ID. /// Creates a new EngineObject with the given ID.