Allow method binds to take Object subclasses as arguments

As done in upstream Godot via GH-57205.

Add a test that ensures it works also for "gdextended" objects.
pull/989/head
Fabio Alessandrelli 2023-01-10 11:48:21 +01:00
parent 129c358a72
commit 9fd33b5cde
4 changed files with 26 additions and 3 deletions

View File

@ -86,22 +86,37 @@ namespace godot {
template <class T> template <class T>
struct VariantCaster { struct VariantCaster {
static _FORCE_INLINE_ T cast(const Variant &p_variant) { static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
if constexpr (std::is_base_of<Object, TStripped>::value) {
return Object::cast_to<TStripped>(p_variant);
} else {
return p_variant; return p_variant;
} }
}
}; };
template <class T> template <class T>
struct VariantCaster<T &> { struct VariantCaster<T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) { static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
if constexpr (std::is_base_of<Object, TStripped>::value) {
return Object::cast_to<TStripped>(p_variant);
} else {
return p_variant; return p_variant;
} }
}
}; };
template <class T> template <class T>
struct VariantCaster<const T &> { struct VariantCaster<const T &> {
static _FORCE_INLINE_ T cast(const Variant &p_variant) { static _FORCE_INLINE_ T cast(const Variant &p_variant) {
using TStripped = std::remove_pointer_t<T>;
if constexpr (std::is_base_of<Object, TStripped>::value) {
return Object::cast_to<TStripped>(p_variant);
} else {
return p_variant; return p_variant;
} }
}
}; };
template <typename T> template <typename T>

View File

@ -33,6 +33,7 @@ func _ready():
var ret_ref = $Example.return_extended_ref() var ret_ref = $Example.return_extended_ref()
prints(" returned ref", ret_ref.get_instance_id(), ", id:", ret_ref.get_id()) prints(" returned ref", ret_ref.get_instance_id(), ", id:", ret_ref.get_id())
prints(" returned ", $Example.get_v4()) prints(" returned ", $Example.get_v4())
prints(" test node argument", $Example.test_node_argument($Example))
prints("VarArg method calls") prints("VarArg method calls")
var ref = ExampleRef.new() var ref = ExampleRef.new()

View File

@ -122,6 +122,7 @@ void Example::_bind_methods() {
ClassDB::bind_method(D_METHOD("test_tarray_arg", "array"), &Example::test_tarray_arg); ClassDB::bind_method(D_METHOD("test_tarray_arg", "array"), &Example::test_tarray_arg);
ClassDB::bind_method(D_METHOD("test_tarray"), &Example::test_tarray); ClassDB::bind_method(D_METHOD("test_tarray"), &Example::test_tarray);
ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary); ClassDB::bind_method(D_METHOD("test_dictionary"), &Example::test_dictionary);
ClassDB::bind_method(D_METHOD("test_node_argument"), &Example::test_node_argument);
ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200)); ClassDB::bind_method(D_METHOD("def_args", "a", "b"), &Example::def_args, DEFVAL(100), DEFVAL(200));
@ -212,6 +213,11 @@ ExampleRef *Example::return_extended_ref() const {
return memnew(ExampleRef()); return memnew(ExampleRef());
} }
Example *Example::test_node_argument(Example *p_node) const {
UtilityFunctions::print(" Test node argument called with ", p_node ? String::num(p_node->get_instance_id()) : "null");
return p_node;
}
Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const { Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
// This is therefor the prefered way of instancing and returning a refcounted object: // This is therefor the prefered way of instancing and returning a refcounted object:
Ref<ExampleRef> ref; Ref<ExampleRef> ref;

View File

@ -100,6 +100,7 @@ public:
void test_tarray_arg(const TypedArray<int64_t> &p_array); void test_tarray_arg(const TypedArray<int64_t> &p_array);
TypedArray<Vector2> test_tarray() const; TypedArray<Vector2> test_tarray() const;
Dictionary test_dictionary() const; Dictionary test_dictionary() const;
Example *test_node_argument(Example *p_node) const;
// Property. // Property.
void set_custom_position(const Vector2 &pos); void set_custom_position(const Vector2 &pos);