Browse Source

Merge pull request #16071 from neikeq/issue-15656

Mono: Fix NodePath and RID bindings
Rémi Verschelde 7 years ago
parent
commit
76ec728003

+ 69 - 37
modules/mono/editor/bindings_generator.cpp

@@ -250,8 +250,15 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
 
 		const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type);
 
-		String im_sig = "IntPtr " CS_PARAM_METHODBIND ", IntPtr " CS_PARAM_INSTANCE;
-		String im_unique_sig = imethod.return_type.operator String() + ",IntPtr,IntPtr";
+		String im_sig;
+		String im_unique_sig;
+
+		if (p_itype.is_object_type) {
+			im_sig += "IntPtr " CS_PARAM_METHODBIND ", ";
+			im_unique_sig += imethod.return_type.operator String() + ",IntPtr,IntPtr";
+		}
+
+		im_sig += "IntPtr " CS_PARAM_INSTANCE;
 
 		// Get arguments information
 		int i = 0;
@@ -263,25 +270,37 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
 			im_sig += " arg";
 			im_sig += itos(i + 1);
 
-			im_unique_sig += ",";
-			im_unique_sig += get_unique_sig(*arg_type);
+			if (p_itype.is_object_type) {
+				im_unique_sig += ",";
+				im_unique_sig += get_unique_sig(*arg_type);
+			}
 
 			i++;
 		}
 
-		// godot_icall_{argc}_{icallcount}
-		String icall_method = ICALL_PREFIX + itos(imethod.arguments.size()) + "_" + itos(method_icalls.size());
+		String icall_method = ICALL_PREFIX;
+
+		if (p_itype.is_object_type) {
+			icall_method += itos(imethod.arguments.size()) + "_" + itos(method_icalls.size()); // godot_icall_{argc}_{icallcount}
+		} else {
+			icall_method += p_itype.name + "_" + imethod.name; // godot_icall_{Type}_{method}
+		}
 
 		InternalCall im_icall = InternalCall(p_itype.api_type, icall_method, return_type->im_type_out, im_sig, im_unique_sig);
 
-		List<InternalCall>::Element *match = method_icalls.find(im_icall);
+		if (p_itype.is_object_type) {
+			List<InternalCall>::Element *match = method_icalls.find(im_icall);
 
-		if (match) {
-			if (p_itype.api_type != ClassDB::API_EDITOR)
-				match->get().editor_only = false;
-			method_icalls_map.insert(&E->get(), &match->get());
+			if (match) {
+				if (p_itype.api_type != ClassDB::API_EDITOR)
+					match->get().editor_only = false;
+				method_icalls_map.insert(&E->get(), &match->get());
+			} else {
+				List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
+				method_icalls_map.insert(&E->get(), &added->get());
+			}
 		} else {
-			List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
+			List<InternalCall>::Element *added = builtin_method_icalls.push_back(im_icall);
 			method_icalls_map.insert(&E->get(), &added->get());
 		}
 	}
@@ -525,6 +544,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
 		ADD_INTERNAL_CALL(E->get());
 	for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
 		ADD_INTERNAL_CALL(E->get());
+	for (const List<InternalCall>::Element *E = builtin_method_icalls.front(); E; E = E->next())
+		ADD_INTERNAL_CALL(E->get());
 
 #undef ADD_INTERNAL_CALL
 
@@ -616,6 +637,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
 		cs_icalls_content.push_back(m_icall.im_sig + ");\n");                                  \
 	}
 
+	// No need to add builtin_method_icalls. Builtin types are core only
+
 	for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
 		ADD_INTERNAL_CALL(E->get());
 	for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
@@ -694,9 +717,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 	output.push_back(itype.is_singleton ? "static class " : "class ");
 	output.push_back(itype.proxy_name);
 
-	if (itype.is_singleton || !itype.is_object_type) {
+	if (itype.is_singleton) {
 		output.push_back("\n");
-	} else if (!is_derived_type) {
+	} else if (!is_derived_type || !itype.is_object_type /* assuming only object types inherit */) {
 		output.push_back(" : IDisposable\n");
 	} else if (obj_types.has(itype.base_name)) {
 		output.push_back(" : ");
@@ -838,7 +861,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 		output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
 
 		// Add the virtual Dispose
-		output.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
+		output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
 									  "if (disposed) return;\n" INDENT3
 									  "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "NativeCalls.godot_icall_");
 		output.push_back(itype.proxy_name);
@@ -929,7 +952,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 			output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
 
 			// Add the virtual Dispose
-			output.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
+			output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
 										  "if (disposed) return;\n" INDENT3
 										  "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3
 										  "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN
@@ -1122,10 +1145,14 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 
 	String method_bind_field = "method_bind_" + itos(p_method_bind_count);
 
-	String icall_params = method_bind_field + ", " + sformat(p_itype.cs_in, "this");
 	String arguments_sig;
 	String cs_in_statements;
 
+	String icall_params;
+	if (p_itype.is_object_type)
+		icall_params += method_bind_field + ", ";
+	icall_params += sformat(p_itype.cs_in, "this");
+
 	List<String> default_args_doc;
 
 	// Retrieve information from the arguments
@@ -1200,7 +1227,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 
 	// Generate method
 	{
-		if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
+		if (p_itype.is_object_type && !p_imethod.is_virtual && !p_imethod.requires_object_call) {
 			p_output.push_back(MEMBER_BEGIN "private ");
 			p_output.push_back(p_itype.is_singleton ? "static IntPtr " : "IntPtr ");
 			p_output.push_back(method_bind_field + " = " CS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
@@ -1381,6 +1408,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
 	output.push_back(itos(GDMono::get_singleton()->get_api_editor_hash()) +
 					 "; }\n#endif // TOOLS_ENABLED\n");
 	output.push_back("void register_generated_icalls() " OPEN_BLOCK);
+	output.push_back("\tgodot_register_header_icalls();");
 
 #define ADD_INTERNAL_CALL_REGISTRATION(m_icall)                                                     \
 	{                                                                                               \
@@ -1443,6 +1471,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
 		output.push_back("#endif\n");
 	}
 
+	for (const List<InternalCall>::Element *E = builtin_method_icalls.front(); E; E = E->next())
+		ADD_INTERNAL_CALL_REGISTRATION(E->get());
+
 #undef ADD_INTERNAL_CALL_REGISTRATION
 
 	output.push_back(CLOSE_BLOCK "}\n");
@@ -1518,6 +1549,9 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
 		i++;
 	}
 
+	if (!p_itype.is_object_type)
+		return OK; // no auto-generated icall functions for builtin types
+
 	const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod);
 	ERR_FAIL_NULL_V(match, ERR_BUG);
 
@@ -2113,36 +2147,34 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 
 #undef INSERT_STRUCT_TYPE
 
-#define INSERT_PRIMITIVE_TYPE(m_type)                              \
-	{                                                              \
-		itype = TypeInterface::create_value_type(String(#m_type)); \
-		itype.c_arg_in = "&%s";                                    \
-		itype.c_type_in = #m_type;                                 \
-		itype.c_type_out = #m_type;                                \
-		itype.im_type_in = #m_type;                                \
-		itype.im_type_out = #m_type;                               \
-		builtin_types.insert(itype.cname, itype);                  \
-	}
-
-	INSERT_PRIMITIVE_TYPE(bool)
-	//INSERT_PRIMITIVE_TYPE(int)
+	// bool
+	itype = TypeInterface::create_value_type(String("bool"));
+	itype.c_arg_in = "&%s";
+	// /* MonoBoolean <---> bool
+	itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+	itype.c_out = "\treturn (%0)%1;\n";
+	itype.c_type = "bool";
+	// */
+	itype.c_type_in = "MonoBoolean";
+	itype.c_type_out = itype.c_type_in;
+	itype.im_type_in = itype.name;
+	itype.im_type_out = itype.name;
+	builtin_types.insert(itype.cname, itype);
 
 	// int
 	itype = TypeInterface::create_value_type(String("int"));
 	itype.c_arg_in = "&%s_in";
-	//* ptrcall only supports int64_t and uint64_t
+	// /* ptrcall only supports int64_t and uint64_t
 	itype.c_in = "\t%0 %1_in = (%0)%1;\n";
 	itype.c_out = "\treturn (%0)%1;\n";
 	itype.c_type = "int64_t";
-	//*/
-	itype.c_type_in = itype.name;
-	itype.c_type_out = itype.name;
+	// */
+	itype.c_type_in = "int32_t";
+	itype.c_type_out = itype.c_type_in;
 	itype.im_type_in = itype.name;
 	itype.im_type_out = itype.name;
 	builtin_types.insert(itype.cname, itype);
 
-#undef INSERT_PRIMITIVE_TYPE
-
 	// real_t
 	itype = TypeInterface();
 #ifdef REAL_T_IS_DOUBLE

+ 1 - 0
modules/mono/editor/bindings_generator.h

@@ -441,6 +441,7 @@ class BindingsGenerator {
 	Map<StringName, String> extra_members;
 
 	List<InternalCall> method_icalls;
+	List<InternalCall> builtin_method_icalls;
 	Map<const MethodInterface *, const InternalCall *> method_icalls_map;
 
 	List<const InternalCall *> generated_icall_funcs;

+ 59 - 0
modules/mono/glue/builtin_types_glue.h

@@ -0,0 +1,59 @@
+#ifndef BUILTIN_TYPES_GLUE_H
+#define BUILTIN_TYPES_GLUE_H
+
+#include "core/node_path.h"
+#include "core/rid.h"
+
+#include <mono/metadata/object.h>
+
+#include "../mono_gd/gd_mono_marshal.h"
+
+MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr) {
+	return (MonoBoolean)p_ptr->is_absolute();
+}
+
+uint32_t godot_icall_NodePath_get_name_count(NodePath *p_ptr) {
+	return p_ptr->get_name_count();
+}
+
+MonoString *godot_icall_NodePath_get_name(NodePath *p_ptr, uint32_t p_idx) {
+	return GDMonoMarshal::mono_string_from_godot(p_ptr->get_name(p_idx));
+}
+
+uint32_t godot_icall_NodePath_get_subname_count(NodePath *p_ptr) {
+	return p_ptr->get_subname_count();
+}
+
+MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) {
+	return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx));
+}
+
+MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) {
+	return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames());
+}
+
+NodePath *godot_icall_NodePath_get_as_property_path(NodePath *p_ptr) {
+	return memnew(NodePath(p_ptr->get_as_property_path()));
+}
+
+MonoBoolean godot_icall_NodePath_is_empty(NodePath *p_ptr) {
+	return (MonoBoolean)p_ptr->is_empty();
+}
+
+uint32_t godot_icall_RID_get_id(RID *p_ptr) {
+	return p_ptr->get_id();
+}
+
+void godot_register_builtin_type_icalls() {
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_as_property_path", (void *)godot_icall_NodePath_get_as_property_path);
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_concatenated_subnames", (void *)godot_icall_NodePath_get_concatenated_subnames);
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_name", (void *)godot_icall_NodePath_get_name);
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_name_count", (void *)godot_icall_NodePath_get_name_count);
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_subname", (void *)godot_icall_NodePath_get_subname);
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_get_subname_count", (void *)godot_icall_NodePath_get_subname_count);
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_is_absolute", (void *)godot_icall_NodePath_is_absolute);
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_NodePath_is_empty", (void *)godot_icall_NodePath_is_empty);
+	mono_add_internal_call("Godot.NativeCalls::godot_icall_RID_get_id", (void *)godot_icall_RID_get_id);
+}
+
+#endif // BUILTIN_TYPES_GLUE_H

+ 12 - 6
modules/mono/glue/glue_header.h

@@ -28,6 +28,8 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
+#include "builtin_types_glue.h"
+
 #include "../csharp_script.h"
 #include "../mono_gd/gd_mono_class.h"
 #include "../mono_gd/gd_mono_internals.h"
@@ -91,12 +93,6 @@ MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) {
 	return GDMonoMarshal::mono_string_from_godot(p_np->operator String());
 }
 
-MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) {
-	Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer();
-	// TODO Check possible Array/Vector<uint8_t> problem?
-	return GDMonoMarshal::Array_to_mono_array(Variant(ret));
-}
-
 // -- RID --
 
 RID *godot_icall_RID_Ctor(Object *p_from) {
@@ -115,6 +111,12 @@ void godot_icall_RID_Dtor(RID *p_ptr) {
 
 // -- String --
 
+MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) {
+	Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer();
+	// TODO Check possible Array/Vector<uint8_t> problem?
+	return GDMonoMarshal::Array_to_mono_array(Variant(ret));
+}
+
 MonoString *godot_icall_String_md5_text(MonoString *p_str) {
 	String ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_text();
 	return GDMonoMarshal::mono_string_from_godot(ret);
@@ -303,3 +305,7 @@ MonoObject *godot_icall_Godot_weakref(Object *p_obj) {
 
 	return GDMonoUtils::create_managed_for_godot_object(CACHED_CLASS(WeakRef), Reference::get_class_static(), Object::cast_to<Object>(wref.ptr()));
 }
+
+void godot_register_header_icalls() {
+	godot_register_builtin_type_icalls();
+}