Browse Source

Merge pull request #26071 from neikeq/issue-24953

C#: Add 'Singleton' property to singleton wrapper class
Ignacio Etcheverry 6 years ago
parent
commit
9f57939c12

+ 7 - 1
modules/mono/editor/bindings_generator.cpp

@@ -97,7 +97,7 @@
 #define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
 #define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
 
-#define BINDINGS_GENERATOR_VERSION UINT32_C(6)
+#define BINDINGS_GENERATOR_VERSION UINT32_C(7)
 
 const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
 
@@ -854,6 +854,12 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 	if (itype.is_singleton) {
 		// Add the type name and the singleton pointer as static fields
 
+		output.push_back(MEMBER_BEGIN "private static Godot.Object singleton;\n");
+		output.push_back(MEMBER_BEGIN "public static Godot.Object Singleton\n" INDENT2 "{\n" INDENT3
+									  "get\n" INDENT3 "{\n" INDENT4 "if (singleton == null)\n" INDENT5
+									  "singleton = Engine.GetSingleton(" BINDINGS_NATIVE_NAME_FIELD ");\n" INDENT4
+									  "return singleton;\n" INDENT3 "}\n" INDENT2 "}\n");
+
 		output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
 		output.push_back(itype.name);
 		output.push_back("\";\n");

+ 9 - 1
modules/mono/mono_gd/gd_mono_class.cpp

@@ -59,8 +59,16 @@ MonoType *GDMonoClass::get_mono_type() {
 	return get_mono_type(mono_class);
 }
 
-bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
+uint32_t GDMonoClass::get_flags() const {
+	return mono_class_get_flags(mono_class);
+}
 
+bool GDMonoClass::is_static() const {
+	uint32_t static_class_flags = MONO_TYPE_ATTR_ABSTRACT | MONO_TYPE_ATTR_SEALED;
+	return (get_flags() & static_class_flags) == static_class_flags;
+}
+
+bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
 	return mono_class_is_assignable_from(mono_class, p_from->mono_class);
 }
 

+ 3 - 0
modules/mono/mono_gd/gd_mono_class.h

@@ -109,6 +109,9 @@ public:
 	String get_full_name() const;
 	MonoType *get_mono_type();
 
+	uint32_t get_flags() const;
+	bool is_static() const;
+
 	bool is_assignable_from(GDMonoClass *p_from) const;
 
 	_FORCE_INLINE_ StringName get_namespace() const { return namespace_name; }

+ 5 - 0
modules/mono/mono_gd/gd_mono_utils.cpp

@@ -374,6 +374,11 @@ GDMonoClass *type_get_proxy_class(const StringName &p_type) {
 
 	GDMonoClass *klass = GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
 
+	if (klass && klass->is_static()) {
+		// A static class means this is a Godot singleton class. If an instance is needed we use Godot.Object.
+		return mono_cache.class_GodotObject;
+	}
+
 #ifdef TOOLS_ENABLED
 	if (!klass) {
 		return GDMono::get_singleton()->get_editor_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);