Selaa lähdekoodia

[Method Bind] Add support for default argument values and static method binding. Sync headers.

bruvzg 3 vuotta sitten
vanhempi
commit
031a83b0ea

+ 403 - 60
godot-headers/extension_api.json

@@ -8290,7 +8290,7 @@
 					"hash": 3,
 					"arguments": [
 						{
-							"name": "phi",
+							"name": "angle",
 							"type": "float"
 						}
 					]
@@ -9779,11 +9779,11 @@
 					"hash": 3,
 					"arguments": [
 						{
-							"name": "by_axis",
+							"name": "axis",
 							"type": "Vector3"
 						},
 						{
-							"name": "phi",
+							"name": "angle",
 							"type": "float"
 						}
 					]
@@ -10557,7 +10557,7 @@
 					"hash": 3,
 					"arguments": [
 						{
-							"name": "phi",
+							"name": "angle",
 							"type": "float"
 						}
 					]
@@ -11997,7 +11997,7 @@
 							"type": "Vector3"
 						},
 						{
-							"name": "phi",
+							"name": "angle",
 							"type": "float"
 						}
 					]
@@ -12212,7 +12212,7 @@
 							"type": "Vector3"
 						},
 						{
-							"name": "phi",
+							"name": "angle",
 							"type": "float"
 						}
 					]
@@ -12372,7 +12372,7 @@
 							"type": "Vector3"
 						},
 						{
-							"name": "phi",
+							"name": "angle",
 							"type": "float"
 						}
 					]
@@ -30002,56 +30002,6 @@
 						}
 					]
 				},
-				{
-					"name": "set_start_node",
-					"is_const": false,
-					"is_vararg": false,
-					"is_static": false,
-					"is_virtual": false,
-					"hash": 134188166,
-					"arguments": [
-						{
-							"name": "name",
-							"type": "StringName"
-						}
-					]
-				},
-				{
-					"name": "get_start_node",
-					"is_const": true,
-					"is_vararg": false,
-					"is_static": false,
-					"is_virtual": false,
-					"hash": 135338183,
-					"return_value": {
-						"type": "String"
-					}
-				},
-				{
-					"name": "set_end_node",
-					"is_const": false,
-					"is_vararg": false,
-					"is_static": false,
-					"is_virtual": false,
-					"hash": 134188166,
-					"arguments": [
-						{
-							"name": "name",
-							"type": "StringName"
-						}
-					]
-				},
-				{
-					"name": "get_end_node",
-					"is_const": true,
-					"is_vararg": false,
-					"is_static": false,
-					"is_virtual": false,
-					"hash": 135338183,
-					"return_value": {
-						"type": "String"
-					}
-				},
 				{
 					"name": "set_graph_offset",
 					"is_const": false,
@@ -120220,6 +120170,156 @@
 				}
 			]
 		},
+		{
+			"name": "MissingNode",
+			"is_refcounted": false,
+			"is_instantiable": true,
+			"inherits": "Node",
+			"api_type": "core",
+			"methods": [
+				{
+					"name": "set_original_class",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "name",
+							"type": "String"
+						}
+					]
+				},
+				{
+					"name": "get_original_class",
+					"is_const": true,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 135338183,
+					"return_value": {
+						"type": "String"
+					}
+				},
+				{
+					"name": "set_recording_properties",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "enable",
+							"type": "bool"
+						}
+					]
+				},
+				{
+					"name": "is_recording_properties",
+					"is_const": true,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 135338183,
+					"return_value": {
+						"type": "bool"
+					}
+				}
+			],
+			"properties": [
+				{
+					"type": "String",
+					"name": "original_class",
+					"setter": "set_original_class",
+					"getter": "get_original_class",
+					"index": -1
+				},
+				{
+					"type": "bool",
+					"name": "recording_properties",
+					"setter": "set_recording_properties",
+					"getter": "is_recording_properties",
+					"index": -1
+				}
+			]
+		},
+		{
+			"name": "MissingResource",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "Resource",
+			"api_type": "core",
+			"methods": [
+				{
+					"name": "set_original_class",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "name",
+							"type": "String"
+						}
+					]
+				},
+				{
+					"name": "get_original_class",
+					"is_const": true,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 135338183,
+					"return_value": {
+						"type": "String"
+					}
+				},
+				{
+					"name": "set_recording_properties",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "enable",
+							"type": "bool"
+						}
+					]
+				},
+				{
+					"name": "is_recording_properties",
+					"is_const": true,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 135338183,
+					"return_value": {
+						"type": "bool"
+					}
+				}
+			],
+			"properties": [
+				{
+					"type": "String",
+					"name": "original_class",
+					"setter": "set_original_class",
+					"getter": "get_original_class",
+					"index": -1
+				},
+				{
+					"type": "bool",
+					"name": "recording_properties",
+					"setter": "set_recording_properties",
+					"getter": "is_recording_properties",
+					"index": -1
+				}
+			]
+		},
 		{
 			"name": "MobileVRInterface",
 			"is_refcounted": true,
@@ -124876,7 +124976,14 @@
 					"is_vararg": false,
 					"is_static": false,
 					"is_virtual": false,
-					"hash": 134152229
+					"hash": 133279208,
+					"arguments": [
+						{
+							"name": "on_thread",
+							"type": "bool",
+							"default_value": "true"
+						}
+					]
 				}
 			],
 			"signals": [
@@ -130865,6 +130972,24 @@
 						}
 					]
 				},
+				{
+					"name": "is_process_running",
+					"is_const": true,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 135374120,
+					"return_value": {
+						"type": "bool"
+					},
+					"arguments": [
+						{
+							"name": "pid",
+							"type": "int",
+							"meta": "int32"
+						}
+					]
+				},
 				{
 					"name": "get_process_id",
 					"is_const": true,
@@ -151227,6 +151352,206 @@
 				}
 			]
 		},
+		{
+			"name": "PlaceholderCubemap",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "PlaceholderTextureLayered",
+			"api_type": "core"
+		},
+		{
+			"name": "PlaceholderCubemapArray",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "PlaceholderTextureLayered",
+			"api_type": "core"
+		},
+		{
+			"name": "PlaceholderMaterial",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "Material",
+			"api_type": "core"
+		},
+		{
+			"name": "PlaceholderMesh",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "Mesh",
+			"api_type": "core",
+			"methods": [
+				{
+					"name": "set_aabb",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "aabb",
+							"type": "AABB"
+						}
+					]
+				}
+			],
+			"properties": [
+				{
+					"type": "AABB",
+					"name": "aabb",
+					"setter": "set_aabb",
+					"getter": "get_aabb",
+					"index": -1
+				}
+			]
+		},
+		{
+			"name": "PlaceholderTexture2D",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "Texture2D",
+			"api_type": "core",
+			"methods": [
+				{
+					"name": "set_size",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "size",
+							"type": "Vector2"
+						}
+					]
+				}
+			],
+			"properties": [
+				{
+					"type": "Vector2i",
+					"name": "size",
+					"setter": "set_size",
+					"getter": "get_size",
+					"index": -1
+				}
+			]
+		},
+		{
+			"name": "PlaceholderTexture2DArray",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "PlaceholderTextureLayered",
+			"api_type": "core"
+		},
+		{
+			"name": "PlaceholderTexture3D",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "Texture3D",
+			"api_type": "core",
+			"methods": [
+				{
+					"name": "set_size",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "size",
+							"type": "Vector3i"
+						}
+					]
+				},
+				{
+					"name": "get_size",
+					"is_const": true,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 135338183,
+					"return_value": {
+						"type": "Vector3i"
+					}
+				}
+			],
+			"properties": [
+				{
+					"type": "Vector3i",
+					"name": "size",
+					"setter": "set_size",
+					"getter": "get_size",
+					"index": -1
+				}
+			]
+		},
+		{
+			"name": "PlaceholderTextureLayered",
+			"is_refcounted": true,
+			"is_instantiable": false,
+			"inherits": "TextureLayered",
+			"api_type": "core",
+			"methods": [
+				{
+					"name": "set_size",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "size",
+							"type": "Vector2i"
+						}
+					]
+				},
+				{
+					"name": "get_size",
+					"is_const": true,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 135338183,
+					"return_value": {
+						"type": "Vector2i"
+					}
+				},
+				{
+					"name": "set_layers",
+					"is_const": false,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 134188166,
+					"arguments": [
+						{
+							"name": "layers",
+							"type": "int",
+							"meta": "int32"
+						}
+					]
+				}
+			],
+			"properties": [
+				{
+					"type": "Vector2i",
+					"name": "size",
+					"setter": "set_size",
+					"getter": "get_size",
+					"index": -1
+				},
+				{
+					"type": "int",
+					"name": "layers",
+					"setter": "set_layers",
+					"getter": "get_layers",
+					"index": -1
+				}
+			]
+		},
 		{
 			"name": "PlaneMesh",
 			"is_refcounted": true,
@@ -176586,6 +176911,17 @@
 						"type": "enum::RenderingDevice.DeviceType"
 					}
 				},
+				{
+					"name": "get_video_adapter_api_version",
+					"is_const": true,
+					"is_vararg": false,
+					"is_static": false,
+					"is_virtual": false,
+					"hash": 135338183,
+					"return_value": {
+						"type": "String"
+					}
+				},
 				{
 					"name": "make_sphere_mesh",
 					"is_const": false,
@@ -215014,6 +215350,13 @@
 				}
 			]
 		},
+		{
+			"name": "TextServerFallback",
+			"is_refcounted": true,
+			"is_instantiable": true,
+			"inherits": "TextServerExtension",
+			"api_type": "core"
+		},
 		{
 			"name": "TextServerManager",
 			"is_refcounted": false,
@@ -223084,7 +223427,7 @@
 					]
 				},
 				{
-					"name": "get_datetime_dict_from_string",
+					"name": "get_datetime_dict_from_datetime_string",
 					"is_const": true,
 					"is_vararg": false,
 					"is_static": false,
@@ -223105,7 +223448,7 @@
 					]
 				},
 				{
-					"name": "get_datetime_string_from_dict",
+					"name": "get_datetime_string_from_datetime_dict",
 					"is_const": true,
 					"is_vararg": false,
 					"is_static": false,

+ 112 - 0
include/godot_cpp/core/binder_common.hpp

@@ -440,6 +440,118 @@ GDNativeExtensionClassMethodArgumentMetadata call_get_argument_metadata(int p_ar
 	return md;
 }
 
+template <class... P, size_t... Is>
+void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, GDNativeCallError &r_error, IndexSequence<Is...>) {
+	r_error.error = GDNATIVE_CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+	(p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+	(p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+}
+
+template <class... P>
+void call_with_variant_args_static_dv(void (*p_method)(P...), const GDNativeVariantPtr *p_args, int p_argcount, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+	if ((size_t)p_argcount > sizeof...(P)) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+	int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+	if (missing > dvs) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
+	std::array<const Variant *, sizeof...(P)> argsp;
+	for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+		if (i < p_argcount) {
+			args[i] = Variant(p_args[i]);
+		} else {
+			args[i] = default_values[i - p_argcount + (dvs - missing)];
+		}
+		argsp[i] = &args[i];
+	}
+
+	call_with_variant_args_static(p_method, argsp.data(), r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P, size_t... Is>
+void call_with_ptr_args_static_method_helper(void (*p_method)(P...), const GDNativeTypePtr *p_args, IndexSequence<Is...>) {
+	p_method(PtrToArg<P>::convert(p_args[Is])...);
+}
+
+template <class... P>
+void call_with_ptr_args_static_method(void (*p_method)(P...), const GDNativeTypePtr *p_args) {
+	call_with_ptr_args_static_method_helper<P...>(p_method, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P, size_t... Is>
+void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_args, Variant &r_ret, GDNativeCallError &r_error, IndexSequence<Is...>) {
+	r_error.error = GDNATIVE_CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+	r_ret = (p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+	r_ret = (p_method)(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+}
+
+template <class R, class... P>
+void call_with_variant_args_static_ret_dv(R (*p_method)(P...), const GDNativeVariantPtr *p_args, int p_argcount, Variant &r_ret, GDNativeCallError &r_error, const std::vector<Variant> &default_values) {
+#ifdef DEBUG_ENABLED
+	if ((size_t)p_argcount > sizeof...(P)) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_MANY_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+	int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+	if (missing > dvs) {
+		r_error.error = GDNATIVE_CALL_ERROR_TOO_FEW_ARGUMENTS;
+		r_error.argument = sizeof...(P);
+		return;
+	}
+#endif
+
+	Variant args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; // Avoid zero sized array.
+	std::array<const Variant *, sizeof...(P)> argsp;
+	for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+		if (i < p_argcount) {
+			args[i] = Variant(p_args[i]);
+		} else {
+			args[i] = default_values[i - p_argcount + (dvs - missing)];
+		}
+		argsp[i] = &args[i];
+	}
+
+	call_with_variant_args_static_ret(p_method, argsp.data(), r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P, size_t... Is>
+void call_with_ptr_args_static_method_ret_helper(R (*p_method)(P...), const GDNativeTypePtr *p_args, void *r_ret, IndexSequence<Is...>) {
+	PtrToArg<R>::encode(p_method(PtrToArg<P>::convert(p_args[Is])...), r_ret);
+}
+
+template <class R, class... P>
+void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const GDNativeTypePtr *p_args, void *r_ret) {
+	call_with_ptr_args_static_method_ret_helper<R, P...>(p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{});
+}
+
 #if defined(__GNUC__) && !defined(__clang__)
 #pragma GCC diagnostic pop
 #endif

+ 28 - 5
include/godot_cpp/core/class_db.hpp

@@ -46,6 +46,8 @@
 
 namespace godot {
 
+#define DEFVAL(m_defval) (m_defval)
+
 struct MethodDefinition {
 	const char *name = nullptr;
 	std::list<std::string> args;
@@ -101,10 +103,15 @@ public:
 	template <class T>
 	static void register_class();
 
-	template <class N, class M>
-	static MethodBind *bind_method(N p_method_name, M p_method);
+	template <class N, class M, typename... VarArgs>
+	static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args);
+
+	template <class N, class M, typename... VarArgs>
+	static MethodBind *bind_static_method(const char *p_class, N p_method_name, M p_method, VarArgs... p_args);
+
 	template <class M>
 	static MethodBind *bind_vararg_method(uint32_t p_flags, const char *p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const std::vector<Variant> &p_default_args = std::vector<Variant>{}, bool p_return_nil_is_variant = true);
+
 	static void add_property_group(const char *p_class, const char *p_name, const char *p_prefix);
 	static void add_property_subgroup(const char *p_class, const char *p_name, const char *p_prefix);
 	static void add_property(const char *p_class, const PropertyInfo &p_pinfo, const char *p_setter, const char *p_getter, int p_index = -1);
@@ -172,11 +179,27 @@ void ClassDB::register_class() {
 	initialize_class(classes[cl.name]);
 }
 
-template <class N, class M>
-MethodBind *ClassDB::bind_method(N p_method_name, M p_method) {
+template <class N, class M, typename... VarArgs>
+MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) {
+	Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+	const Variant *argptrs[sizeof...(p_args) + 1];
+	for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+		argptrs[i] = &args[i];
+	}
 	MethodBind *bind = create_method_bind(p_method);
+	return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args));
+}
 
-	return bind_methodfi(0, bind, p_method_name, nullptr, 0);
+template <class N, class M, typename... VarArgs>
+MethodBind *ClassDB::bind_static_method(const char *p_class, N p_method_name, M p_method, VarArgs... p_args) {
+	Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+	const Variant *argptrs[sizeof...(p_args) + 1];
+	for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+		argptrs[i] = &args[i];
+	}
+	MethodBind *bind = create_static_method_bind(p_method);
+	bind->set_instance_class(p_class);
+	return bind_methodfi(0, bind, p_method_name, sizeof...(p_args) == 0 ? nullptr : (const void **)argptrs, sizeof...(p_args));
 }
 
 template <class M>

+ 141 - 5
include/godot_cpp/core/method_bind.hpp

@@ -53,8 +53,10 @@ class MethodBind {
 	int argument_count = 0;
 	uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
 
+	bool _static = false;
 	bool _is_const = false;
 	bool _has_return = false;
+	bool _vararg = false;
 
 	std::vector<std::string> argument_names;
 	GDNativeVariantType *argument_types = nullptr;
@@ -66,6 +68,8 @@ protected:
 	void generate_argument_types(int p_count);
 	void set_const(bool p_const);
 	void set_return(bool p_return);
+	void set_static(bool p_static);
+	void set_vararg(bool p_vararg);
 	void set_argument_count(int p_count);
 
 public:
@@ -96,8 +100,10 @@ public:
 
 	_FORCE_INLINE_ int get_argument_count() const { return argument_count; };
 	_FORCE_INLINE_ bool is_const() const { return _is_const; }
+	_FORCE_INLINE_ bool is_static() const { return _static; }
+	_FORCE_INLINE_ bool is_vararg() const { return _vararg; }
 	_FORCE_INLINE_ bool has_return() const { return _has_return; }
-	_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags; }
+	_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDNATIVE_EXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDNATIVE_EXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDNATIVE_EXTENSION_METHOD_FLAG_STATIC : 0); }
 	_FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
 	void set_argument_names(const std::vector<std::string> &p_names);
 	std::vector<std::string> get_argument_names() const;
@@ -155,15 +161,13 @@ public:
 		ERR_FAIL(); // Can't call.
 	}
 
-	virtual bool is_const() const { return false; }
-
-	virtual bool is_vararg() const { return true; }
-
 	MethodBindVarArgBase(
 			R (T::*p_method)(const Variant **, GDNativeInt, GDNativeCallError &),
 			const MethodInfo &p_method_info,
 			bool p_return_nil_is_variant) :
 			method(p_method), method_info(p_method_info) {
+		set_vararg(true);
+		set_const(true);
 		set_argument_count(method_info.arguments.size());
 		if (method_info.arguments.size()) {
 			std::vector<std::string> names;
@@ -572,6 +576,138 @@ MethodBind *create_method_bind(R (T::*p_method)(P...) const) {
 	return a;
 }
 
+// STATIC BINDS
+
+// no return
+
+template <class... P>
+class MethodBindTS : public MethodBind {
+	void (*function)(P...);
+
+protected:
+// GCC raises warnings in the case P = {} as the comparison is always false...
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+	virtual GDNativeVariantType gen_argument_type(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			return call_get_argument_type<P...>(p_arg);
+		} else {
+			return GDNATIVE_VARIANT_TYPE_NIL;
+		}
+	}
+
+	virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
+		GDNativePropertyInfo pi;
+		call_get_argument_type_info<P...>(p_arg, pi);
+		return pi;
+	}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+public:
+	virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_arg) const {
+		return call_get_argument_metadata<P...>(p_arg);
+	}
+
+	virtual Variant call(GDExtensionClassInstancePtr p_object, const GDNativeVariantPtr *p_args, const GDNativeInt p_arg_count, GDNativeCallError &r_error) const {
+		(void)p_object; // unused
+		call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments());
+		return Variant();
+	}
+
+	virtual void ptrcall(GDExtensionClassInstancePtr p_object, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
+		(void)p_object;
+		(void)r_ret;
+		call_with_ptr_args_static_method(function, p_args);
+	}
+
+	MethodBindTS(void (*p_function)(P...)) {
+		function = p_function;
+		generate_argument_types(sizeof...(P));
+		set_argument_count(sizeof...(P));
+		set_static(true);
+	}
+};
+
+template <class... P>
+MethodBind *create_static_method_bind(void (*p_method)(P...)) {
+	MethodBind *a = memnew((MethodBindTS<P...>)(p_method));
+	return a;
+}
+
+// return
+
+template <class R, class... P>
+class MethodBindTRS : public MethodBind {
+	R(*function)
+	(P...);
+
+protected:
+// GCC raises warnings in the case P = {} as the comparison is always false...
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+	virtual GDNativeVariantType gen_argument_type(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			return call_get_argument_type<P...>(p_arg);
+		} else {
+			return GetTypeInfo<R>::VARIANT_TYPE;
+		}
+	}
+
+	virtual GDNativePropertyInfo gen_argument_type_info(int p_arg) const {
+		if (p_arg >= 0 && p_arg < (int)sizeof...(P)) {
+			GDNativePropertyInfo pi;
+			call_get_argument_type_info<P...>(p_arg, pi);
+			return pi;
+		} else {
+			return GetTypeInfo<R>::get_class_info();
+		}
+	}
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+public:
+	virtual GDNativeExtensionClassMethodArgumentMetadata get_argument_metadata(int p_arg) const {
+		if (p_arg >= 0) {
+			return call_get_argument_metadata<P...>(p_arg);
+		} else {
+			return GetTypeInfo<R>::METADATA;
+		}
+	}
+
+	virtual Variant call(GDExtensionClassInstancePtr p_object, const GDNativeVariantPtr *p_args, const GDNativeInt p_arg_count, GDNativeCallError &r_error) const {
+		Variant ret;
+		call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments());
+		return ret;
+	}
+
+	virtual void ptrcall(GDExtensionClassInstancePtr p_object, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const {
+		(void)p_object;
+		call_with_ptr_args_static_method_ret(function, p_args, r_ret);
+	}
+
+	MethodBindTRS(R (*p_function)(P...)) {
+		function = p_function;
+		generate_argument_types(sizeof...(P));
+		set_argument_count(sizeof...(P));
+		set_static(true);
+		set_return(true);
+	}
+};
+
+template <class R, class... P>
+MethodBind *create_static_method_bind(R (*p_method)(P...)) {
+	MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method));
+	return a;
+}
+
 } // namespace godot
 
 #endif // ! GODOT_CPP_METHOD_BIND_HPP

+ 3 - 3
include/godot_cpp/core/object.hpp

@@ -117,20 +117,20 @@ struct MethodInfo {
 
 template <class... Args>
 MethodInfo::MethodInfo(const char *p_name, const Args &...args) :
-		name(p_name), flags(METHOD_FLAG_NORMAL) {
+		name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
 	arguments = { args... };
 }
 
 template <class... Args>
 MethodInfo::MethodInfo(Variant::Type ret, const char *p_name, const Args &...args) :
-		name(p_name), flags(METHOD_FLAG_NORMAL) {
+		name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
 	return_val.type = ret;
 	arguments = { args... };
 }
 
 template <class... Args>
 MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name, const Args &...args) :
-		name(p_name), return_val(p_ret), flags(METHOD_FLAG_NORMAL) {
+		name(p_name), return_val(p_ret), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
 	arguments = { args... };
 }
 

+ 32 - 14
src/core/class_db.cpp

@@ -95,9 +95,9 @@ void ClassDB::add_property(const char *p_class, const PropertyInfo &p_pinfo, con
 
 	// register with Godot
 	GDNativePropertyInfo prop_info = {
-		(uint32_t)p_pinfo.type, //uint32_t type;
-		p_pinfo.name, //const char *name;
-		p_pinfo.class_name, //const char *class_name;
+		(uint32_t)p_pinfo.type, // uint32_t type;
+		p_pinfo.name, // const char *name;
+		p_pinfo.class_name, // const char *class_name;
 		p_pinfo.hint, // NONE //uint32_t hint;
 		p_pinfo.hint_string, // const char *hint_string;
 		p_pinfo.usage, // DEFAULT //uint32_t usage;
@@ -169,6 +169,16 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const M
 
 	p_bind->set_argument_names(args);
 
+	std::vector<Variant> defvals;
+
+	defvals.resize(p_defcount);
+	for (int i = 0; i < p_defcount; i++) {
+		defvals[i] = *static_cast<const Variant *>(p_defs[i]);
+	}
+
+	p_bind->set_default_arguments(defvals);
+	p_bind->set_hint_flags(p_flags);
+
 	// register our method bind within our plugin
 	type.method_map[method_name.name] = p_bind;
 
@@ -179,19 +189,27 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const M
 }
 
 void ClassDB::bind_method_godot(const char *p_class_name, MethodBind *p_method) {
+	std::vector<GDNativeVariantPtr> def_args;
+	const std::vector<Variant> &def_args_val = p_method->get_default_arguments();
+
+	def_args.resize(def_args_val.size());
+	for (int i = 0; i < def_args_val.size(); i++) {
+		def_args[i] = (GDNativeVariantPtr)&def_args_val[i];
+	}
+
 	GDNativeExtensionClassMethodInfo method_info = {
-		p_method->get_name(), //const char *name;
-		p_method, //void *method_userdata;
-		MethodBind::bind_call, //GDNativeExtensionClassMethodCall call_func;
-		MethodBind::bind_ptrcall, //GDNativeExtensionClassMethodPtrCall ptrcall_func;
-		GDNATIVE_EXTENSION_METHOD_FLAGS_DEFAULT, //uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */
-		(uint32_t)p_method->get_argument_count(), //uint32_t argument_count;
-		(GDNativeBool)p_method->has_return(), //GDNativeBool has_return_value;
+		p_method->get_name(), // const char *name;
+		p_method, // void *method_userdata;
+		MethodBind::bind_call, // GDNativeExtensionClassMethodCall call_func;
+		MethodBind::bind_ptrcall, // GDNativeExtensionClassMethodPtrCall ptrcall_func;
+		p_method->get_hint_flags(), // uint32_t method_flags; /* GDNativeExtensionClassMethodFlags */
+		(uint32_t)p_method->get_argument_count(), // uint32_t argument_count;
+		(GDNativeBool)p_method->has_return(), // GDNativeBool has_return_value;
 		MethodBind::bind_get_argument_type, //(GDNativeExtensionClassMethodGetArgumentType) get_argument_type_func;
-		MethodBind::bind_get_argument_info, //GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
-		MethodBind::bind_get_argument_metadata, //GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
-		p_method->get_hint_flags(), //uint32_t default_argument_count;
-		nullptr, //GDNativeVariantPtr *default_arguments;
+		MethodBind::bind_get_argument_info, // GDNativeExtensionClassMethodGetArgumentInfo get_argument_info_func; /* name and hint information for the argument can be omitted in release builds. Class name should always be present if it applies. */
+		MethodBind::bind_get_argument_metadata, // GDNativeExtensionClassMethodGetArgumentMetadata get_argument_metadata_func;
+		(uint32_t)p_method->get_default_argument_count(), // uint32_t default_argument_count;
+		def_args.data(), // GDNativeVariantPtr *default_arguments;
 	};
 	internal::gdn_interface->classdb_register_extension_class_method(internal::library, p_class_name, &method_info);
 }

+ 8 - 0
src/core/method_bind.cpp

@@ -52,6 +52,14 @@ void MethodBind::set_return(bool p_return) {
 	_has_return = p_return;
 }
 
+void MethodBind::set_static(bool p_static) {
+	_static = p_static;
+}
+
+void MethodBind::set_vararg(bool p_vararg) {
+	_vararg = p_vararg;
+}
+
 void MethodBind::set_argument_names(const std::vector<std::string> &p_names) {
 	argument_names = p_names;
 }

+ 5 - 5
src/core/object.cpp

@@ -33,22 +33,22 @@
 namespace godot {
 
 MethodInfo::MethodInfo() :
-		flags(METHOD_FLAG_NORMAL) {}
+		flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {}
 
 MethodInfo::MethodInfo(const char *p_name) :
-		name(p_name), flags(METHOD_FLAG_NORMAL) {}
+		name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {}
 
 MethodInfo::MethodInfo(Variant::Type ret) :
-		flags(METHOD_FLAG_NORMAL) {
+		flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
 	return_val.type = ret;
 }
 
 MethodInfo::MethodInfo(Variant::Type ret, const char *p_name) :
-		name(p_name), flags(METHOD_FLAG_NORMAL) {
+		name(p_name), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {
 	return_val.type = ret;
 }
 
 MethodInfo::MethodInfo(const PropertyInfo &p_ret, const char *p_name) :
-		name(p_name), return_val(p_ret), flags(METHOD_FLAG_NORMAL) {}
+		name(p_name), return_val(p_ret), flags(GDNATIVE_EXTENSION_METHOD_FLAG_NORMAL) {}
 
 } // namespace godot

+ 32 - 15
test/demo/main.gd

@@ -2,32 +2,49 @@ extends Node
 
 func _ready():
 	# Bind signals
+	prints("Signal bind")
 	$Button.button_up.connect($Example.emit_custom_signal.bind("Button", 42))
+
+	prints("")
+
+	# Call static methods.
+	prints("Static method calls")
+	prints("  static (109)", Example.test_static(9, 100));
+	Example.test_static2();
 	
 	# Call methods.
+	prints("Instance method calls")
 	$Example.simple_func()
 	($Example as Example).simple_const_func() # Force use of ptrcall
-	prints("returned", $Example.return_something("some string"))
-	prints("returned const", $Example.return_something_const())
-	prints("returned ref", $Example.return_extended_ref())
+	prints("  returned", $Example.return_something("some string"))
+	prints("  returned const", $Example.return_something_const())
+	prints("  returned ref", $Example.return_extended_ref())
+
+	prints("VarArg method calls")
 	var ref = ExampleRef.new()
-	prints("sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id())
-	prints("vararg args", $Example.varargs_func("some", "arguments", "to", "test"))
-	prints("vararg_nv ret", $Example.varargs_func_nv("some", "arguments", "to", "test"))
+	prints("  sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id())
+	prints("  vararg args", $Example.varargs_func("some", "arguments", "to", "test"))
+	prints("  vararg_nv ret", $Example.varargs_func_nv("some", "arguments", "to", "test"))
 	$Example.varargs_func_void("some", "arguments", "to", "test")
 
-	prints("test array", $Example.test_array())
-	prints("test dictionary", $Example.test_dictionary())
+	prints("Method calls with default values")
+	prints("  defval (300)", $Example.def_args())
+	prints("  defval (250)", $Example.def_args(50))
+	prints("  defval (150)", $Example.def_args(50, 100))
+
+	prints("Array and Dictionary")
+	prints("  test array", $Example.test_array())
+	prints("  test dictionary", $Example.test_dictionary())
 
-	# Use properties.
-	prints("custom position is", $Example.group_subgroup_custom_position)
+	prints("Properties")
+	prints("  custom position is", $Example.group_subgroup_custom_position)
 	$Example.group_subgroup_custom_position = Vector2(50, 50)
-	prints("custom position now is", $Example.group_subgroup_custom_position)
+	prints("  custom position now is", $Example.group_subgroup_custom_position)
 
-	# Get constants
-	prints("FIRST", $Example.FIRST)
-	prints("ANSWER_TO_EVERYTHING", $Example.ANSWER_TO_EVERYTHING)
-	prints("CONSTANT_WITHOUT_ENUM", $Example.CONSTANT_WITHOUT_ENUM)
+	prints("Constnts")
+	prints("  FIRST", $Example.FIRST)
+	prints("  ANSWER_TO_EVERYTHING", $Example.ANSWER_TO_EVERYTHING)
+	prints("  CONSTANT_WITHOUT_ENUM", $Example.CONSTANT_WITHOUT_ENUM)
 
 func _on_Example_custom_signal(name, value):
 	prints("Example emitted:", name, value)

+ 25 - 8
test/src/example.cpp

@@ -46,6 +46,18 @@ ExampleRef::~ExampleRef() {
 	UtilityFunctions::print("ExampleRef destroyed.");
 }
 
+int Example::test_static(int p_a, int p_b) {
+	return p_a + p_b;
+}
+
+void Example::test_static2() {
+	UtilityFunctions::print("  void static");
+}
+
+int Example::def_args(int p_a, int p_b) {
+	return p_a + p_b;
+}
+
 void Example::_bind_methods() {
 	// Methods.
 	ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
@@ -58,6 +70,11 @@ void Example::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("test_array"), &Example::test_array);
 	ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary);
 
+	ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
+
+	ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static);
+	ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2);
+
 	{
 		MethodInfo mi;
 		mi.arguments.push_back(PropertyInfo(Variant::STRING, "some_argument"));
@@ -108,20 +125,20 @@ Example::~Example() {
 
 // Methods.
 void Example::simple_func() {
-	UtilityFunctions::print("Simple func called.");
+	UtilityFunctions::print("  Simple func called.");
 }
 
 void Example::simple_const_func() const {
-	UtilityFunctions::print("Simple const func called.");
+	UtilityFunctions::print("  Simple const func called.");
 }
 
 String Example::return_something(const String &base) {
-	UtilityFunctions::print("Return something called.");
+	UtilityFunctions::print("  Return something called.");
 	return base;
 }
 
 Viewport *Example::return_something_const() const {
-	UtilityFunctions::print("Return something const called.");
+	UtilityFunctions::print("  Return something const called.");
 	if (is_inside_tree()) {
 		Viewport *result = get_viewport();
 		return result;
@@ -138,22 +155,22 @@ Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
 	ref.instantiate();
 	// TODO the returned value gets dereferenced too early and return a null object otherwise.
 	ref->reference();
-	UtilityFunctions::print("Example ref checks called with value: ", p_ref->get_instance_id(), ", returning value: ", ref->get_instance_id());
+	UtilityFunctions::print("  Example ref checks called with value: ", p_ref->get_instance_id(), ", returning value: ", ref->get_instance_id());
 	return ref;
 }
 
 Variant Example::varargs_func(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
-	UtilityFunctions::print("Varargs (Variant return) called with ", String::num((double)arg_count), " arguments");
+	UtilityFunctions::print("  Varargs (Variant return) called with ", String::num((double)arg_count), " arguments");
 	return arg_count;
 }
 
 int Example::varargs_func_nv(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
-	UtilityFunctions::print("Varargs (int return) called with ", String::num((double)arg_count), " arguments");
+	UtilityFunctions::print("  Varargs (int return) called with ", String::num((double)arg_count), " arguments");
 	return 42;
 }
 
 void Example::varargs_func_void(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error) {
-	UtilityFunctions::print("Varargs (no return) called with ", String::num((double)arg_count), " arguments");
+	UtilityFunctions::print("  Varargs (no return) called with ", String::num((double)arg_count), " arguments");
 }
 
 void Example::emit_custom_signal(const String &name, int value) {

+ 5 - 0
test/src/example.h

@@ -90,6 +90,7 @@ public:
 	int varargs_func_nv(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error);
 	void varargs_func_void(const Variant **args, GDNativeInt arg_count, GDNativeCallError &error);
 	void emit_custom_signal(const String &name, int value);
+	int def_args(int p_a = 100, int p_b = 200);
 
 	Array test_array() const;
 	Dictionary test_dictionary() const;
@@ -98,6 +99,10 @@ public:
 	void set_custom_position(const Vector2 &pos);
 	Vector2 get_custom_position() const;
 
+	// Static method.
+	static int test_static(int p_a, int p_b);
+	static void test_static2();
+
 	// Virtual function override (no need to bind manually).
 	virtual bool _has_point(const Vector2 &point) const override;
 };