From aa8cd4fb52eecfcf322d3e511266bc52b80e60b4 Mon Sep 17 00:00:00 2001 From: DE YU <71481700+Delsin-Yu@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:41:18 +0800 Subject: [PATCH] Finish implementing non-reflection based CreateManagedForGodotObjectBinding --- .../GodotTools/GodotTools/GodotSharpEditor.cs | 18 +++ modules/mono/editor/bindings_generator.cpp | 14 +- .../mono/glue/GodotSharp/GodotPlugins/Main.cs | 14 +- .../Core/Bridge/ScriptManagerBridge.cs | 121 +++++++++--------- 4 files changed, 87 insertions(+), 80 deletions(-) diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index d3899c809a2b..673f98ee1494 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Reflection; using GodotTools.Build; using GodotTools.Ides; using GodotTools.Ides.Rider; @@ -700,6 +701,23 @@ public void OnAfterDeserialize() private static IntPtr InternalCreateInstance(IntPtr unmanagedCallbacks, int unmanagedCallbacksSize) { Internal.Initialize(unmanagedCallbacks, unmanagedCallbacksSize); + + var populateConstructorMethod = + AppDomain.CurrentDomain + .GetAssemblies() + .First(x => x.GetName().Name == "GodotSharpEditor") + .GetType("Godot.EditorConstructors")? + .GetMethod("AddEditorConstructors", + BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + + if (populateConstructorMethod == null) + { + throw new MissingMethodException("Godot.EditorConstructors", + "AddEditorConstructors"); + } + + populateConstructorMethod.Invoke(null, null); + return new GodotSharpEditor().NativeInstance; } } diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 9187ad44b517..408e2730c3f4 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -1768,7 +1768,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { for (const KeyValue &E : obj_types) { const TypeInterface &itype = E.value; - if (!itype.is_instantiable || itype.api_type != ClassDB::API_CORE) { + if (itype.api_type != ClassDB::API_CORE || itype.is_singleton_instance) { continue; } @@ -1776,6 +1776,9 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) { cs_builtin_ctors_content.append(itype.name); cs_builtin_ctors_content.append("\", " CS_PARAM_INSTANCE " => new "); cs_builtin_ctors_content.append(itype.proxy_name); + if (itype.is_singleton && !itype.is_compat_singleton) { + cs_builtin_ctors_content.append("Instance"); + } cs_builtin_ctors_content.append("(" CS_PARAM_INSTANCE "));\n"); } @@ -1901,9 +1904,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { StringBuilder cs_builtin_ctors_content; cs_builtin_ctors_content.append("namespace " BINDINGS_NAMESPACE ";\n\n"); - cs_builtin_ctors_content.append("using System.Diagnostics.CodeAnalysis;\n" - "using Godot;\n" - "\n"); + cs_builtin_ctors_content.append("using System.Diagnostics.CodeAnalysis;\n\n"); cs_builtin_ctors_content.append("[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicMethods)]\n"); cs_builtin_ctors_content.append("internal static class " BINDINGS_CLASS_CONSTRUCTOR_EDITOR "\n{"); @@ -1915,7 +1916,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { for (const KeyValue &E : obj_types) { const TypeInterface &itype = E.value; - if (!itype.is_instantiable || itype.api_type != ClassDB::API_EDITOR) { + if (itype.api_type != ClassDB::API_EDITOR || itype.is_singleton_instance) { continue; } @@ -1923,6 +1924,9 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) { cs_builtin_ctors_content.append(itype.name); cs_builtin_ctors_content.append("\", " CS_PARAM_INSTANCE " => new "); cs_builtin_ctors_content.append(itype.proxy_name); + if (itype.is_singleton && !itype.is_compat_singleton) { + cs_builtin_ctors_content.append("Instance"); + } cs_builtin_ctors_content.append("(" CS_PARAM_INSTANCE "));\n"); } diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs index c3ea4fbb4430..5b751d643bd3 100644 --- a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs +++ b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs @@ -176,19 +176,7 @@ private static unsafe IntPtr LoadToolsAssembly(char* nAssemblyPath, var (assembly, _) = LoadPlugin(assemblyPath, isCollectible: false); NativeLibrary.SetDllImportResolver(assembly, _dllImportResolver!); - - var populateConstructorMethod = assembly.GetType("GodotTools.EditorConstructors")? - .GetMethod("AddEditorConstructors", - BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); - - if (populateConstructorMethod == null) - { - throw new MissingMethodException("GodotTools.EditorConstructors", - "AddEditorConstructors"); - } - - populateConstructorMethod.Invoke(null, null); - + var method = assembly.GetType("GodotTools.GodotSharpEditor")? .GetMethod("InternalCreateInstance", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index fc6f005f03da..c59aef161f16 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -101,9 +101,6 @@ internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_na Console.WriteLine($"CreateManaged: {nativeTypeNameStr}"); - // TODO: Singleton Types - // TODO: NativeTypeNameStr that starts with Godot. - var instance = Constructors.Invoke(nativeTypeNameStr, godotObject); return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(instance)); @@ -301,65 +298,65 @@ internal static void SetGodotObjectPtr(IntPtr gcHandlePtr, IntPtr newPtr) } } - private static Type? TypeGetProxyClass(string nativeTypeNameStr) - { - // Performance is not critical here as this will be replaced with a generated dictionary. - - if (nativeTypeNameStr[0] == '_') - nativeTypeNameStr = nativeTypeNameStr.Substring(1); - - Type? wrapperType = typeof(GodotObject).Assembly.GetType("Godot." + nativeTypeNameStr); - - if (wrapperType == null) - { - wrapperType = GetTypeByGodotClassAttr(typeof(GodotObject).Assembly, nativeTypeNameStr); - } - - if (wrapperType == null) - { - var editorAssembly = AppDomain.CurrentDomain.GetAssemblies() - .FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor"); - - if (editorAssembly != null) - { - wrapperType = editorAssembly.GetType("Godot." + nativeTypeNameStr); - - if (wrapperType == null) - { - wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr); - } - } - } - - static Type? GetTypeByGodotClassAttr(Assembly assembly, string nativeTypeNameStr) - { - var types = assembly.GetTypes(); - foreach (var type in types) - { - var attr = type.GetCustomAttribute(); - if (attr?.Name == nativeTypeNameStr) - { - return type; - } - } - return null; - } - - static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed; - - if (wrapperType != null && IsStatic(wrapperType)) - { - // A static class means this is a Godot singleton class. Try to get the Instance proxy type. - wrapperType = TypeGetProxyClass($"{wrapperType.Name}Instance"); - if (wrapperType == null) - { - // Otherwise, fallback to GodotObject. - return typeof(GodotObject); - } - } - - return wrapperType; - } + // private static Type? TypeGetProxyClass(string nativeTypeNameStr) + // { + // // Performance is not critical here as this will be replaced with a generated dictionary. + // + // if (nativeTypeNameStr[0] == '_') + // nativeTypeNameStr = nativeTypeNameStr.Substring(1); + // + // Type? wrapperType = typeof(GodotObject).Assembly.GetType("Godot." + nativeTypeNameStr); + // + // if (wrapperType == null) + // { + // wrapperType = GetTypeByGodotClassAttr(typeof(GodotObject).Assembly, nativeTypeNameStr); + // } + // + // if (wrapperType == null) + // { + // var editorAssembly = AppDomain.CurrentDomain.GetAssemblies() + // .FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor"); + // + // if (editorAssembly != null) + // { + // wrapperType = editorAssembly.GetType("Godot." + nativeTypeNameStr); + // + // if (wrapperType == null) + // { + // wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr); + // } + // } + // } + // + // static Type? GetTypeByGodotClassAttr(Assembly assembly, string nativeTypeNameStr) + // { + // var types = assembly.GetTypes(); + // foreach (var type in types) + // { + // var attr = type.GetCustomAttribute(); + // if (attr?.Name == nativeTypeNameStr) + // { + // return type; + // } + // } + // return null; + // } + // + // static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed; + // + // if (wrapperType != null && IsStatic(wrapperType)) + // { + // // A static class means this is a Godot singleton class. Try to get the Instance proxy type. + // wrapperType = TypeGetProxyClass($"{wrapperType.Name}Instance"); + // if (wrapperType == null) + // { + // // Otherwise, fallback to GodotObject. + // return typeof(GodotObject); + // } + // } + // + // return wrapperType; + // } // Called from GodotPlugins // ReSharper disable once UnusedMember.Local