Skip to content

Commit

Permalink
Finish implementing non-reflection based CreateManagedForGodotObjectB…
Browse files Browse the repository at this point in the history
…inding
  • Loading branch information
Delsin-Yu committed Sep 13, 2024
1 parent 729572b commit aa8cd4f
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 80 deletions.
18 changes: 18 additions & 0 deletions modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand Down
14 changes: 9 additions & 5 deletions modules/mono/editor/bindings_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1768,14 +1768,17 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
for (const KeyValue<StringName, TypeInterface> &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;
}

cs_builtin_ctors_content.append(INDENT2 BINDINGS_CLASS_CONSTRUCTOR_DICTIONARY ".Add(\"");
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");
}

Expand Down Expand Up @@ -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{");
Expand All @@ -1915,14 +1916,17 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
for (const KeyValue<StringName, TypeInterface> &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;
}

cs_builtin_ctors_content.append(INDENT2 "builtinMethodConstructors.Add(\"");
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");
}

Expand Down
14 changes: 1 addition & 13 deletions modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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<GodotClassNameAttribute>();
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<GodotClassNameAttribute>();
// 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
Expand Down

0 comments on commit aa8cd4f

Please sign in to comment.