diff --git a/gdextension/gdextension_interface.h b/gdextension/gdextension_interface.h index fce377f9..cb0b1515 100644 --- a/gdextension/gdextension_interface.h +++ b/gdextension/gdextension_interface.h @@ -1271,6 +1271,18 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantHasMember)(GDExtensionVaria */ typedef GDExtensionBool (*GDExtensionInterfaceVariantHasKey)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid); +/** + * @name variant_get_object_instance_id + * @since 4.4 + * + * Gets the object instance ID from a variant of type GDEXTENSION_VARIANT_TYPE_OBJECT. + * + * @param p_self A pointer to the Variant. + * + * @return The instance ID for the contained object. + */ +typedef GDObjectInstanceID (*GDExtensionInterfaceVariantGetObjectInstanceId)(GDExtensionConstVariantPtr p_self); + /** * @name variant_get_type_name * @since 4.1 diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index 61dbb960..8c96bd1c 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -82,6 +82,7 @@ extern "C" GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_ extern "C" GDExtensionInterfaceVariantHasMethod gdextension_interface_variant_has_method; extern "C" GDExtensionInterfaceVariantHasMember gdextension_interface_variant_has_member; extern "C" GDExtensionInterfaceVariantHasKey gdextension_interface_variant_has_key; +extern "C" GDExtensionInterfaceVariantGetObjectInstanceId gdextension_interface_variant_get_object_instance_id; extern "C" GDExtensionInterfaceVariantGetTypeName gdextension_interface_variant_get_type_name; extern "C" GDExtensionInterfaceVariantCanConvert gdextension_interface_variant_can_convert; extern "C" GDExtensionInterfaceVariantCanConvertStrict gdextension_interface_variant_can_convert_strict; diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index b0d57fbb..10aea96d 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -264,6 +264,8 @@ public: operator PackedColorArray() const; operator PackedVector4Array() const; + Object *get_validated_object() const; + Variant &operator=(const Variant &other); Variant &operator=(Variant &&other); bool operator==(const Variant &other) const; diff --git a/src/godot.cpp b/src/godot.cpp index f6d0d43c..2e8f4bea 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -88,6 +88,7 @@ GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_type = null GDExtensionInterfaceVariantHasMethod gdextension_interface_variant_has_method = nullptr; GDExtensionInterfaceVariantHasMember gdextension_interface_variant_has_member = nullptr; GDExtensionInterfaceVariantHasKey gdextension_interface_variant_has_key = nullptr; +GDExtensionInterfaceVariantGetObjectInstanceId gdextension_interface_variant_get_object_instance_id = nullptr; GDExtensionInterfaceVariantGetTypeName gdextension_interface_variant_get_type_name = nullptr; GDExtensionInterfaceVariantCanConvert gdextension_interface_variant_can_convert = nullptr; GDExtensionInterfaceVariantCanConvertStrict gdextension_interface_variant_can_convert_strict = nullptr; @@ -367,6 +368,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge LOAD_PROC_ADDRESS(variant_has_method, GDExtensionInterfaceVariantHasMethod); LOAD_PROC_ADDRESS(variant_has_member, GDExtensionInterfaceVariantHasMember); LOAD_PROC_ADDRESS(variant_has_key, GDExtensionInterfaceVariantHasKey); + LOAD_PROC_ADDRESS(variant_get_object_instance_id, GDExtensionInterfaceVariantGetObjectInstanceId); LOAD_PROC_ADDRESS(variant_get_type_name, GDExtensionInterfaceVariantGetTypeName); LOAD_PROC_ADDRESS(variant_can_convert, GDExtensionInterfaceVariantCanConvert); LOAD_PROC_ADDRESS(variant_can_convert_strict, GDExtensionInterfaceVariantCanConvertStrict); diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp index 9dcf7058..1f57d48a 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -448,12 +448,7 @@ Variant::operator ObjectID() const { if (get_type() == Type::INT) { return ObjectID(operator uint64_t()); } else if (get_type() == Type::OBJECT) { - Object *obj = operator Object *(); - if (obj != nullptr) { - return ObjectID(obj->get_instance_id()); - } else { - return ObjectID(); - } + return ObjectID(internal::gdextension_interface_variant_get_object_instance_id(_native_ptr())); } else { return ObjectID(); } @@ -515,6 +510,10 @@ Variant::operator PackedVector4Array() const { return PackedVector4Array(this); } +Object *Variant::get_validated_object() const { + return ObjectDB::get_instance(operator ObjectID()); +} + Variant &Variant::operator=(const Variant &other) { clear(); internal::gdextension_interface_variant_new_copy(_native_ptr(), other._native_ptr()); diff --git a/test/project/main.gd b/test/project/main.gd index b2625b9a..864c3d55 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -206,6 +206,12 @@ func _ready(): assert_equal(example.test_variant_float_conversion(10.0), 10.0) assert_equal(example.test_variant_float_conversion(10), 10.0) + # Test checking if objects are valid. + var object_of_questionable_validity = Object.new() + assert_equal(example.test_object_is_valid(object_of_questionable_validity), true) + object_of_questionable_validity.free() + assert_equal(example.test_object_is_valid(object_of_questionable_validity), false) + # Test that ptrcalls from GDExtension to the engine are correctly encoding Object and RefCounted. var new_node = Node.new() example.test_add_child(new_node) diff --git a/test/src/example.cpp b/test/src/example.cpp index 8075f551..f49a2302 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -215,6 +215,7 @@ void Example::_bind_methods() { ClassDB::bind_method(D_METHOD("test_variant_vector2i_conversion", "variant"), &Example::test_variant_vector2i_conversion); ClassDB::bind_method(D_METHOD("test_variant_int_conversion", "variant"), &Example::test_variant_int_conversion); ClassDB::bind_method(D_METHOD("test_variant_float_conversion", "variant"), &Example::test_variant_float_conversion); + ClassDB::bind_method(D_METHOD("test_object_is_valid", "variant"), &Example::test_object_is_valid); ClassDB::bind_method(D_METHOD("test_add_child", "node"), &Example::test_add_child); ClassDB::bind_method(D_METHOD("test_set_tileset", "tilemap", "tileset"), &Example::test_set_tileset); @@ -579,6 +580,10 @@ float Example::test_variant_float_conversion(const Variant &p_variant) const { return p_variant; } +bool Example::test_object_is_valid(const Variant &p_variant) const { + return static_cast(p_variant.get_validated_object()); +} + void Example::test_add_child(Node *p_node) { add_child(p_node); } diff --git a/test/src/example.h b/test/src/example.h index 6d88cf11..40f934fa 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -145,6 +145,7 @@ public: Vector2i test_variant_vector2i_conversion(const Variant &p_variant) const; int test_variant_int_conversion(const Variant &p_variant) const; float test_variant_float_conversion(const Variant &p_variant) const; + bool test_object_is_valid(const Variant &p_variant) const; void test_add_child(Node *p_node); void test_set_tileset(TileMap *p_tilemap, const Ref &p_tileset) const;