From aa33b53e6700295e8965339c06bd7ae178af884e Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Mon, 6 Oct 2025 22:35:40 +0200 Subject: [PATCH] Use `GDType` for GDExtension types as well. Co-authored-by: David Snopek --- core/extension/gdextension.cpp | 4 +++ core/object/class_db.cpp | 26 ++++++++++++++++--- core/object/class_db.h | 4 ++- core/object/gdtype.cpp | 4 +-- core/object/object.cpp | 47 ++++++++++++++++++++++++++-------- core/object/object.h | 23 ++++++++--------- 6 files changed, 78 insertions(+), 30 deletions(-) diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 55858658cf4..254095e9158 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -491,6 +491,8 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr } #endif + extension->gdextension.create_gdtype(); + ClassDB::register_extension_class(&extension->gdextension); if (p_extension_funcs->icon_path != nullptr) { @@ -970,6 +972,8 @@ void GDExtension::_clear_extension(Extension *p_extension) { obj->clear_internal_extension(); } + + p_extension->gdextension.destroy_gdtype(); } void GDExtension::track_instance_binding(Object *p_object) { diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index d44bfc867ef..d574267a824 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -196,6 +196,8 @@ public: obj->_extension = ClassDB::get_placeholder_extension(ti->name); obj->_extension_instance = memnew(PlaceholderExtensionInstance(ti->name)); + obj->_reset_gdtype(); + #ifdef TOOLS_ENABLED if (obj->_extension->track_instance) { obj->_extension->track_instance(obj->_extension->tracking_userdata, obj); @@ -756,10 +758,19 @@ ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class) placeholder_extension->call_virtual_with_data = nullptr; placeholder_extension->recreate_instance = &PlaceholderExtensionInstance::placeholder_class_recreate_instance; + placeholder_extension->create_gdtype(); + return placeholder_extension; } #endif +const GDType *ClassDB::get_gdtype(const StringName &p_class) { + Locker::Lock lock(Locker::STATE_READ); + ClassInfo *type = classes.getptr(p_class); + ERR_FAIL_NULL_V(type, nullptr); + return type->gdtype; +} + void ClassDB::set_object_extension_instance(Object *p_object, const StringName &p_class, GDExtensionClassInstancePtr p_instance) { ERR_FAIL_NULL(p_object); ClassInfo *ti; @@ -779,6 +790,8 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName & p_object->_extension = ti->gdextension; p_object->_extension_instance = p_instance; + p_object->_reset_gdtype(); + #ifdef TOOLS_ENABLED if (p_object->_extension->track_instance) { p_object->_extension->track_instance(p_object->_extension->tracking_userdata, p_object); @@ -870,17 +883,20 @@ use_script: return scr.is_valid() && scr->is_valid() && scr->is_abstract(); } -void ClassDB::_add_class(const StringName &p_class, const StringName &p_inherits) { +void ClassDB::_add_class(const GDType &p_class, const GDType *p_inherits) { Locker::Lock lock(Locker::STATE_WRITE); - const StringName &name = p_class; + const StringName &name = p_class.get_name(); - ERR_FAIL_COND_MSG(classes.has(name), vformat("Class '%s' already exists.", String(p_class))); + ERR_FAIL_COND_MSG(classes.has(name), vformat("Class '%s' already exists.", name)); classes[name] = ClassInfo(); ClassInfo &ti = classes[name]; ti.name = name; - ti.inherits = p_inherits; + ti.gdtype = &p_class; + if (p_inherits) { + ti.inherits = p_inherits->get_name(); + } ti.api = current_api; if (ti.inherits) { @@ -2350,6 +2366,8 @@ void ClassDB::register_extension_class(ObjectGDExtension *p_extension) { c.is_runtime = p_extension->is_runtime; #endif + c.gdtype = p_extension->gdtype; + classes[p_extension->class_name] = c; } diff --git a/core/object/class_db.h b/core/object/class_db.h index 86340425415..82ada5480a2 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -123,6 +123,7 @@ public: APIType api = API_NONE; ClassInfo *inherits_ptr = nullptr; void *class_ptr = nullptr; + const GDType *gdtype = nullptr; ObjectGDExtension *gdextension = nullptr; @@ -218,7 +219,7 @@ public: static APIType current_api; static HashMap api_hashes_cache; - static void _add_class(const StringName &p_class, const StringName &p_inherits); + static void _add_class(const GDType &p_class, const GDType *p_inherits); static HashMap> default_values; static HashSet default_values_cached; @@ -334,6 +335,7 @@ public: static void get_extension_class_list(const Ref &p_extension, List *p_classes); static ObjectGDExtension *get_placeholder_extension(const StringName &p_class); #endif + static const GDType *get_gdtype(const StringName &p_class); static void get_inheriters_from_class(const StringName &p_class, LocalVector &p_classes); static void get_direct_inheriters_from_class(const StringName &p_class, List *p_classes); static StringName get_parent_class_nocheck(const StringName &p_class); diff --git a/core/object/gdtype.cpp b/core/object/gdtype.cpp index 25ce7aef3c0..389a110f905 100644 --- a/core/object/gdtype.cpp +++ b/core/object/gdtype.cpp @@ -32,11 +32,11 @@ GDType::GDType(const GDType *p_super_type, StringName p_name) : super_type(p_super_type), name(std::move(p_name)) { - name_hierarchy.push_back(StringName(name, true)); + name_hierarchy.push_back(name); if (super_type) { for (const StringName &ancestor_name : super_type->name_hierarchy) { - name_hierarchy.push_back(StringName(ancestor_name, true)); + name_hierarchy.push_back(ancestor_name); } } } diff --git a/core/object/object.cpp b/core/object/object.cpp index 740881a9fd3..10bd258b707 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -230,6 +230,25 @@ Object::Connection::operator Variant() const { return d; } +void ObjectGDExtension::create_gdtype() { + ERR_FAIL_COND(gdtype); + + gdtype = memnew(GDType(ClassDB::get_gdtype(parent_class_name), class_name)); +} + +void ObjectGDExtension::destroy_gdtype() { + ERR_FAIL_COND(!gdtype); + + memdelete(const_cast(gdtype)); + gdtype = nullptr; +} + +ObjectGDExtension::~ObjectGDExtension() { + if (gdtype) { + memdelete(const_cast(gdtype)); + } +} + bool Object::Connection::operator<(const Connection &p_conn) const { if (signal == p_conn.signal) { return callable < p_conn.callable; @@ -279,6 +298,7 @@ bool Object::_predelete() { } _extension = nullptr; _extension_instance = nullptr; + // _gdtype_ptr = nullptr; // The pointer already set to nullptr above, no need to do it again. } #ifdef TOOLS_ENABLED else if (_instance_bindings != nullptr) { @@ -1379,6 +1399,16 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int return err; } +void Object::_reset_gdtype() const { + if (_extension) { + // Set to extension's type. + _gdtype_ptr = _extension->gdtype; + } else { + // Reset to internal type. + _gdtype_ptr = &_get_typev(); + } +} + void Object::_add_user_signal(const String &p_name, const Array &p_args) { // this version of add_user_signal is meant to be used from scripts or external apis // without access to ADD_SIGNAL in bind_methods @@ -1734,7 +1764,7 @@ void Object::initialize_class() { if (initialized) { return; } - _add_class_to_classdb(get_class_static(), StringName()); + _add_class_to_classdb(get_gdtype_static(), nullptr); _bind_methods(); _bind_compatibility_methods(); initialized = true; @@ -1810,8 +1840,8 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) { } } -void Object::_add_class_to_classdb(const StringName &p_class, const StringName &p_inherits) { - ClassDB::_add_class(p_class, p_inherits); +void Object::_add_class_to_classdb(const GDType &p_type, const GDType *p_inherits) { + ClassDB::_add_class(p_type, p_inherits); } void Object::_get_property_list_from_classdb(const StringName &p_class, List *p_list, bool p_no_inheritance, const Object *p_validator) { @@ -2128,9 +2158,6 @@ const GDType &Object::get_gdtype() const { } bool Object::is_class(const String &p_class) const { - if (_extension && _extension->is_class(p_class)) { - return true; - } for (const StringName &name : get_gdtype().get_name_hierarchy()) { if (name == p_class) { return true; @@ -2140,11 +2167,6 @@ bool Object::is_class(const String &p_class) const { } const StringName &Object::get_class_name() const { - if (_extension) { - // Can't put inside the unlikely as constructor can run it. - return _extension->class_name; - } - return get_gdtype().get_name(); } @@ -2277,6 +2299,8 @@ void Object::clear_internal_extension() { } _extension = nullptr; _extension_instance = nullptr; + // Reset GDType to internal type. + _gdtype_ptr = &_get_typev(); // Clear the instance bindings. _instance_binding_mutex.lock(); @@ -2305,6 +2329,7 @@ void Object::reset_internal_extension(ObjectGDExtension *p_extension) { _extension_instance = p_extension->recreate_instance ? p_extension->recreate_instance(p_extension->class_userdata, (GDExtensionObjectPtr)this) : nullptr; ERR_FAIL_NULL_MSG(_extension_instance, "Unable to recreate GDExtension instance - does this extension support hot reloading?"); _extension = p_extension; + _gdtype_ptr = p_extension->gdtype; } } #endif diff --git a/core/object/object.h b/core/object/object.h index c6446a2a020..60451ce43cd 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -349,16 +349,6 @@ struct ObjectGDExtension { GDExtensionClassReference unreference; GDExtensionClassGetRID get_rid; - _FORCE_INLINE_ bool is_class(const String &p_class) const { - const ObjectGDExtension *e = this; - while (e) { - if (p_class == e->class_name.operator String()) { - return true; - } - e = e->parent; - } - return false; - } void *class_userdata = nullptr; #ifndef DISABLE_DEPRECATED @@ -380,6 +370,14 @@ struct ObjectGDExtension { void (*track_instance)(void *p_userdata, void *p_instance) = nullptr; void (*untrack_instance)(void *p_userdata, void *p_instance) = nullptr; #endif + + /// A type for this Object extension. + /// This is not exposed through the GDExtension API (yet) so it is inferred from above parameters. + const GDType *gdtype; + void create_gdtype(); + void destroy_gdtype(); + + ~ObjectGDExtension(); }; #define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__) @@ -525,7 +523,7 @@ public: return; \ } \ m_inherits::initialize_class(); \ - _add_class_to_classdb(get_class_static(), super_type::get_class_static()); \ + _add_class_to_classdb(get_gdtype_static(), &super_type::get_gdtype_static()); \ if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \ _bind_methods(); \ } \ @@ -673,6 +671,7 @@ private: HashMap metadata; HashMap metadata_properties; mutable const GDType *_gdtype_ptr = nullptr; + void _reset_gdtype() const; void _add_user_signal(const String &p_name, const Array &p_args = Array()); bool _has_user_signal(const StringName &p_name) const; @@ -793,7 +792,7 @@ protected: friend class ::ClassDB; friend class PlaceholderExtensionInstance; - static void _add_class_to_classdb(const StringName &p_class, const StringName &p_inherits); + static void _add_class_to_classdb(const GDType &p_class, const GDType *p_inherits); static void _get_property_list_from_classdb(const StringName &p_class, List *p_list, bool p_no_inheritance, const Object *p_validator); bool _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false);