diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 514a80089..3150ac530 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -117,6 +117,9 @@ class ClassDB { template static void register_abstract_class(); + template + static MethodBind *bind_inherited_method(N p_method_name, M p_method, VarArgs... p_args); + template static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args); @@ -212,6 +215,17 @@ void ClassDB::register_abstract_class() { ClassDB::_register_class(); } +template +MethodBind *ClassDB::bind_inherited_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_inherited_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)); +} + template 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. diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index 155a76589..3efcc4d6c 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -271,22 +271,11 @@ MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, GDNativ return a; } -#ifndef TYPED_METHOD_BIND -class ___UnexistingClass; -#define MB_T ___UnexistingClass -#else -#define MB_T T -#endif - // No return, not const. -#ifdef TYPED_METHOD_BIND template -#else -template -#endif // TYPED_METHOD_BIND class MethodBindT : public MethodBind { - void (MB_T::*method)(P...); + void (T::*method)(P...); protected: // GCC raises warnings in the case P = {} as the comparison is always false... @@ -321,48 +310,39 @@ class MethodBindT : public MethodBind { } virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const { -#ifdef TYPED_METHOD_BIND call_with_variant_args_dv(static_cast(p_instance), method, p_args, (int)p_argument_count, r_error, get_default_arguments()); -#else - call_with_variant_args_dv(reinterpret_cast(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments()); -#endif return Variant(); } virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const { -#ifdef TYPED_METHOD_BIND call_with_ptr_args(static_cast(p_instance), method, p_args, nullptr); -#else - call_with_ptr_args(reinterpret_cast(p_instance), method, p_args, nullptr); -#endif // TYPED_METHOD_BIND } - MethodBindT(void (MB_T::*p_method)(P...)) { + MethodBindT(void (T::*p_method)(P...)) { method = p_method; generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); } }; +template +MethodBind *create_inherited_method_bind(void (T::*p_method)(P...)) { + MethodBind *a = memnew((MethodBindT)(p_method)); + a->set_instance_class(C::get_class_static()); + return a; +} + template MethodBind *create_method_bind(void (T::*p_method)(P...)) { -#ifdef TYPED_METHOD_BIND MethodBind *a = memnew((MethodBindT)(p_method)); -#else - MethodBind *a = memnew((MethodBindT)(reinterpret_cast(p_method))); -#endif // TYPED_METHOD_BIND a->set_instance_class(T::get_class_static()); return a; } // No return, const. -#ifdef TYPED_METHOD_BIND template -#else -template -#endif // TYPED_METHOD_BIND class MethodBindTC : public MethodBind { - void (MB_T::*method)(P...) const; + void (T::*method)(P...) const; protected: // GCC raises warnings in the case P = {} as the comparison is always false... @@ -397,48 +377,39 @@ class MethodBindTC : public MethodBind { } virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const { -#ifdef TYPED_METHOD_BIND call_with_variant_argsc_dv(static_cast(p_instance), method, p_args, (int)p_argument_count, r_error, get_default_arguments()); -#else - call_with_variant_argsc_dv(reinterpret_cast(p_instance), method, p_args, p_argument_count, r_error, get_default_arguments()); -#endif return Variant(); } virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const { -#ifdef TYPED_METHOD_BIND call_with_ptr_args(static_cast(p_instance), method, p_args, nullptr); -#else - call_with_ptr_args(reinterpret_cast(p_instance), method, p_args, nullptr); -#endif // TYPED_METHOD_BIND } - MethodBindTC(void (MB_T::*p_method)(P...) const) { + MethodBindTC(void (T::*p_method)(P...) const) { method = p_method; generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); } }; +template +MethodBind *create_method_bind(void (T::*p_method)(P...) const) { + MethodBind *a = memnew((MethodBindTC)(p_method)); + a->set_instance_class(T::get_class_static()); + return a; +} + template MethodBind *create_method_bind(void (T::*p_method)(P...) const) { -#ifdef TYPED_METHOD_BIND MethodBind *a = memnew((MethodBindTC)(p_method)); -#else - MethodBind *a = memnew((MethodBindTC)(reinterpret_cast(p_method))); -#endif // TYPED_METHOD_BIND a->set_instance_class(T::get_class_static()); return a; } // Return, not const. -#ifdef TYPED_METHOD_BIND template -#else -template -#endif // TYPED_METHOD_BIND class MethodBindTR : public MethodBind { - R(MB_T::*method) + R(T::*method) (P...); protected: @@ -479,22 +450,14 @@ class MethodBindTR : public MethodBind { virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const { Variant ret; -#ifdef TYPED_METHOD_BIND call_with_variant_args_ret_dv(static_cast(p_instance), method, p_args, (int)p_argument_count, ret, r_error, get_default_arguments()); -#else - call_with_variant_args_ret_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments()); -#endif return ret; } virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const { -#ifdef TYPED_METHOD_BIND call_with_ptr_args(static_cast(p_instance), method, p_args, r_ret); -#else - call_with_ptr_args(reinterpret_cast(p_instance), method, p_args, r_ret); -#endif // TYPED_METHOD_BIND } - MethodBindTR(R (MB_T::*p_method)(P...)) { + MethodBindTR(R (T::*p_method)(P...)) { method = p_method; generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); @@ -502,26 +465,25 @@ class MethodBindTR : public MethodBind { } }; +template +MethodBind *create_inherited_method_bind(R (T::*p_method)(P...)) { + MethodBind *a = memnew((MethodBindTR)(p_method)); + a->set_instance_class(C::get_class_static()); + return a; +} + template MethodBind *create_method_bind(R (T::*p_method)(P...)) { -#ifdef TYPED_METHOD_BIND MethodBind *a = memnew((MethodBindTR)(p_method)); -#else - MethodBind *a = memnew((MethodBindTR)(reinterpret_cast(p_method))); -#endif // TYPED_METHOD_BIND a->set_instance_class(T::get_class_static()); return a; } // Return, const. -#ifdef TYPED_METHOD_BIND template -#else -template -#endif // TYPED_METHOD_BIND class MethodBindTRC : public MethodBind { - R(MB_T::*method) + R(T::*method) (P...) const; protected: @@ -562,22 +524,14 @@ class MethodBindTRC : public MethodBind { virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDNativeVariantPtr *p_args, const GDNativeInt p_argument_count, GDNativeCallError &r_error) const { Variant ret; -#ifdef TYPED_METHOD_BIND call_with_variant_args_retc_dv(static_cast(p_instance), method, p_args, (int)p_argument_count, ret, r_error, get_default_arguments()); -#else - call_with_variant_args_retc_dv((MB_T *)p_instance, method, p_args, p_argument_count, ret, r_error, get_default_arguments()); -#endif return ret; } virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret) const { -#ifdef TYPED_METHOD_BIND call_with_ptr_args(static_cast(p_instance), method, p_args, r_ret); -#else - call_with_ptr_args(reinterpret_cast(p_instance), method, p_args, r_ret); -#endif // TYPED_METHOD_BIND } - MethodBindTRC(R (MB_T::*p_method)(P...) const) { + MethodBindTRC(R (T::*p_method)(P...) const) { method = p_method; generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); @@ -585,13 +539,16 @@ class MethodBindTRC : public MethodBind { } }; +template +MethodBind *create_inherited_method_bind(R (T::*p_method)(P...) const) { + MethodBind *a = memnew((MethodBindTRC)(p_method)); + a->set_instance_class(C::get_class_static()); + return a; +} + template MethodBind *create_method_bind(R (T::*p_method)(P...) const) { -#ifdef TYPED_METHOD_BIND MethodBind *a = memnew((MethodBindTRC)(p_method)); -#else - MethodBind *a = memnew((MethodBindTRC)(reinterpret_cast(p_method))); -#endif // TYPED_METHOD_BIND a->set_instance_class(T::get_class_static()); return a; } diff --git a/test/src/example.cpp b/test/src/example.cpp index 890319d20..23bbbfa8c 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -270,3 +270,16 @@ bool Example::_has_point(const Vector2 &point) const { return false; } + +void ExampleBaseClass::example_void_method() { + return; +} + +int ExampleBaseClass::example_int_method() { + return 42; +} + +void ExampleInheriting::_bind_methods() { + ClassDB::bind_inherited_method(D_METHOD("example_void_method"), &ExampleInheriting::example_void_method); + ClassDB::bind_inherited_method(D_METHOD("example_int_method"), &ExampleInheriting::example_int_method); +} diff --git a/test/src/example.h b/test/src/example.h index 44c1531a9..d47e6112a 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -121,4 +121,17 @@ class ExampleAbstract : public Object { static void _bind_methods() {} }; +class ExampleBaseClass { +public: + void example_void_method(); + int example_int_method(); +}; + +class ExampleInheriting : public ExampleBaseClass, public Object { + GDCLASS(ExampleInheriting, Object) + +protected: + static void _bind_methods(); +}; + #endif // EXAMPLE_CLASS_H