From 81a61d5a90866baff2784f36cd030a9e484b1763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Tue, 25 Jul 2023 16:37:41 +0200 Subject: [PATCH] Drag'n'drop for components + Added CreateInstance to ScriptClass + Added CreateComponentInstance to ScriptInstance --- .../Assets/Scripts/MyTestEntity.cs | 9 +++- GlitchyEditor/content/Scenes/physics2D.scene | 32 ++++++------- .../src/EditWindows/ComponentEditWindow.bf | 19 ++++++-- GlitchyEngine/src/Scripting/ScriptClass.bf | 10 ++++ GlitchyEngine/src/Scripting/ScriptEngine.bf | 47 +++++++++++++++---- GlitchyEngine/src/Scripting/ScriptInstance.bf | 15 ++++++ GlitchyEngineHelper/src/Mono/Mono.bf | 8 ++++ 7 files changed, 110 insertions(+), 30 deletions(-) diff --git a/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs b/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs index f74c915..051544c 100644 --- a/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs +++ b/GlitchyEditor/SandboxProject/Assets/Scripts/MyTestEntity.cs @@ -66,8 +66,13 @@ namespace Sandbox Log.Info($"Jump Force: {JumpForce}"); - _rigidBody ??= GetComponent() ?? AddComponent(); - + //_rigidBody ??= GetComponent() ?? AddComponent(); + + if (_rigidBody == null) + { + Log.Error("_rigidBody was not set in editor."); + } + if (Camera == null) { Log.Warning("Camera wasn't set in editor. Searching..."); diff --git a/GlitchyEditor/content/Scenes/physics2D.scene b/GlitchyEditor/content/Scenes/physics2D.scene index a8c3087..e37e7d7 100644 --- a/GlitchyEditor/content/Scenes/physics2D.scene +++ b/GlitchyEditor/content/Scenes/physics2D.scene @@ -72,7 +72,7 @@ Color = { R = 1, G = 0.941887021, - B = 0.401484519, + B = 0.401484489, A = 1 }, Sprite = "", @@ -162,7 +162,7 @@ OrthographicHeight = 10, OrthographicNearPlane = 0, OrthographicFarPlane = 10, - AspectRatio = 1.17151165, + AspectRatio = 2.05582929, FixedAspectRatio = false }, ScriptComponent = { @@ -195,8 +195,8 @@ }, TransformComponent = { Position = { - X = -0.121203199, - Y = 0.660161018, + X = -0.121203206, + Y = 0.660161078, Z = 0 }, Rotation = { @@ -234,7 +234,7 @@ ScriptComponent = { ScriptClass = "Sandbox.MyTestEntity", Fields = [ - _rigidBody = (Component)0, + _rigidBody = (Component)15710354273720487680, TheEntity = (Entity)0, JumpForce = (Float)200, MoveForce = (Float)148, @@ -276,7 +276,7 @@ Color = { R = 0.985467017, G = 1, - B = 0.569977999 + B = 0.569977939 } } }, @@ -323,8 +323,8 @@ SpriteRendererComponent = { Color = { R = 0.425658971, - G = 0.855207503, - B = 0.0558161139, + G = 0.855207443, + B = 0.0558161177, A = 1 }, Sprite = "", @@ -338,14 +338,14 @@ TransformComponent = { Position = { X = 6.74610233, - Y = -2.03225923, + Y = -2.03225946, Z = 0 }, Rotation = { X = 0, Y = 0, Z = -0.331792623, - W = 0.943352461 + W = 0.94335258 }, Scale = { X = 5.29557419, @@ -399,8 +399,8 @@ }, TransformComponent = { Position = { - X = 15.2321291, - Y = -1.98709261, + X = 15.2321281, + Y = -1.98709273, Z = 0 }, Rotation = { @@ -410,7 +410,7 @@ W = 0.990847468 }, Scale = { - X = 13.9764547, + X = 13.9764528, Y = 1, Z = 1 }, @@ -462,13 +462,13 @@ TransformComponent = { Position = { X = -6.27842855, - Y = 2.62550187, + Y = 2.62550163, Z = 0 }, Rotation = { X = 0, Y = 0, - Z = 0.187087849, + Z = 0.187087879, W = 0.982343197 }, Scale = { @@ -497,7 +497,7 @@ }, Density = 1, Friction = 0.5, - Restitution = 0.899999917, + Restitution = 0.899999857, RestitutionThreshold = 0.5 } } diff --git a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf index da751e6..383da96 100644 --- a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf +++ b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf @@ -817,11 +817,22 @@ namespace GlitchyEditor.EditWindows // TODO: I don't like the fact, that we are using mono directly ScriptField scriptField = scriptClass.Fields[fieldName]; - MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, scriptField.GetMonoType()); - // TODO: We shouldn't abuse the script glue like that... - // ScriptGlue should only be called by C#, not by Beef... - allowDrop = ScriptGlue.[Friend]Entity_HasComponent(draggedEntity.UUID, reflectionType); + // For some reason we have to retrieve the MonoType like this. Using scriptField.GetMonoType() directly returns the wrong type... + MonoReflectionType* reflectionType = Mono.mono_type_get_object(ScriptEngine.[Friend]s_AppDomain, scriptField.GetMonoType()); + MonoType* actualMonoType = Mono.mono_reflection_type_get_type(reflectionType); + + // TODO: We shouldn't abuse the script glue like that. + // ScriptGlue should only be called by C#, not by Beef. + if (ScriptGlue.[Friend]s_HasComponentMethods.TryGetValue(actualMonoType, let has_component)) + { + allowDrop = has_component(draggedEntity); + } + else + { + Log.EngineLogger.Warning($"No HasComponent-Function found for field {scriptField.Name}"); + allowDrop = false; + } } if (allowDrop) diff --git a/GlitchyEngine/src/Scripting/ScriptClass.bf b/GlitchyEngine/src/Scripting/ScriptClass.bf index 7d88541..e3998cc 100644 --- a/GlitchyEngine/src/Scripting/ScriptClass.bf +++ b/GlitchyEngine/src/Scripting/ScriptClass.bf @@ -284,6 +284,16 @@ class ScriptClass : SharpClass return instance; } + public MonoObject* CreateInstance() + { + MonoObject* instance = Mono.mono_object_new(ScriptEngine.[Friend]s_AppDomain, _monoClass); + + // Invoke empty constructor to fill fields + Mono.mono_runtime_object_init(instance); + + return instance; + } + public MonoMethod* GetMethod(StringView name, int argCount = 0) { return Mono.mono_class_get_method_from_name(_monoClass, name.ToScopeCStr!(), argCount); diff --git a/GlitchyEngine/src/Scripting/ScriptEngine.bf b/GlitchyEngine/src/Scripting/ScriptEngine.bf index fd03d7a..eb8c122 100644 --- a/GlitchyEngine/src/Scripting/ScriptEngine.bf +++ b/GlitchyEngine/src/Scripting/ScriptEngine.bf @@ -179,6 +179,8 @@ static class ScriptEngine GetCoreAttributes(); GetCoreClasses(); + GetComponentsFromAssemblies(); + GetEntitiesFromAssemblies(); ScriptGlue.RegisterManagedComponents(); @@ -214,13 +216,13 @@ static class ScriptEngine script.Instance.Instantiate(entity.UUID); - //CopyEditorFieldsToInstance(entity, script); - return true; } public static void CopyEditorFieldsToInstance(Entity entity, ScriptComponent* script) { + Log.EngineLogger.AssertDebug(script.Instance != null); + // 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 let fields = GetScriptFieldMap(entity); @@ -242,7 +244,17 @@ static class ScriptEngine MonoObject* referencedEntity = GetManagedInstance(referencedId); script.Instance.SetFieldValue(scriptField, referencedEntity); case .Component: + // We create a new instance of a component class + MonoType* type = scriptField.GetMonoType(); + + SharpType sharpType = ScriptEngine.GetSharpType(type); + var componentClass = ComponentClasses[sharpType.FullName]; + + MonoObject* componentInstance = script.Instance.CreateComponentInstance(componentClass); + script.Instance.SetFieldValue(scriptField, componentInstance); + + sharpType.ReleaseRef(); default: script.Instance.SetFieldValue(scriptField, field._data); } @@ -362,13 +374,32 @@ static class ScriptEngine Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\""); } - // Check if it is a component - else if (monoClass != null && Mono.mono_class_is_subclass_of(monoClass, s_ComponentRoot.[Friend]_monoClass, false)) - { - ScriptClass entityScript = new ScriptClass(StringView(nameSpace), StringView(name), s_AppAssemblyImage, .Entity); - _entityScripts.Add(entityScript.FullName, entityScript); + } + } + private static void GetComponentsFromAssemblies() + { + ClearDictionaryAndReleaseValues!(_componentClasses); - Log.EngineLogger.Info($"Added entity \"{entityScript.FullName}\""); + MonoTableInfo* typeDefinitionsTable = Mono.mono_image_get_table_info(s_CoreAssemblyImage, .MONO_TABLE_TYPEDEF); + int32 numTypes = Mono.mono_table_info_get_rows(typeDefinitionsTable); + + 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(s_CoreAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAMESPACE]); + char8* name = Mono.mono_metadata_string_heap(s_CoreAssemblyImage, (.)cols[(.)SOME_RANDOM_ENUM.MONO_TYPEDEF_NAME]); + + MonoClass* monoClass = Mono.mono_class_from_name(s_CoreAssemblyImage, nameSpace, name); + + // Check if it is a component but not the root Component class + if (monoClass != null && monoClass != s_ComponentRoot.[Friend]_monoClass && Mono.mono_class_is_subclass_of(monoClass, s_ComponentRoot.[Friend]_monoClass, false)) + { + ScriptClass componentClass = new ScriptClass(StringView(nameSpace), StringView(name), s_CoreAssemblyImage, .Component); + _componentClasses.Add(componentClass.FullName, componentClass); + + Log.EngineLogger.Info($"Added component \"{componentClass.FullName}\""); } } } diff --git a/GlitchyEngine/src/Scripting/ScriptInstance.bf b/GlitchyEngine/src/Scripting/ScriptInstance.bf index 340cfe8..1511444 100644 --- a/GlitchyEngine/src/Scripting/ScriptInstance.bf +++ b/GlitchyEngine/src/Scripting/ScriptInstance.bf @@ -70,4 +70,19 @@ class ScriptInstance : RefCounter { _scriptClass.SetFieldValue(_instance, field.[Friend]_monoField, value); } + + /// Creates a new instance of the given component class and initializes it for the current entity. + public MonoObject* CreateComponentInstance(ScriptClass componentClassType) + { + MonoObject* componentInstance = componentClassType.CreateInstance(); + + // TODO: We could cache the property, but this might be fine + MonoProperty* entityProperty = Mono.mono_class_get_property_from_name(componentClassType.[Friend]_monoClass, "Entity"); + + MonoObject* exception = null; + + Mono.mono_property_set_value(entityProperty, componentInstance, (void**)&_instance, &exception); + + return componentInstance; + } } \ No newline at end of file diff --git a/GlitchyEngineHelper/src/Mono/Mono.bf b/GlitchyEngineHelper/src/Mono/Mono.bf index 96af9c7..4e7d896 100644 --- a/GlitchyEngineHelper/src/Mono/Mono.bf +++ b/GlitchyEngineHelper/src/Mono/Mono.bf @@ -232,6 +232,12 @@ static class Mono [LinkName(.C)] public static extern MonoThread* mono_thread_current(); + + [LinkName(.C)] + public static extern MonoProperty* mono_class_get_property_from_name(MonoClass *klass, char8* name); + + [LinkName(.C)] + public static extern void mono_property_set_value(MonoProperty *prop, void *obj, void **@params, MonoObject **exc); } struct MonoDomain; @@ -250,6 +256,8 @@ struct MonoObject; struct MonoMethod; +struct MonoProperty; + struct MonoThread; struct MonoException