Selaa lähdekoodia

Merge pull request #106016 from Ivorforce/gdtype-loves-gdextension

Expand `GDType` to cover GDExtension types as well
Thaddeus Crews 2 viikkoa sitten
vanhempi
sitoutus
662db6eb59

+ 4 - 0
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) {

+ 22 - 4
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;
 }
 

+ 3 - 1
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<APIType, uint32_t> 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<StringName, HashMap<StringName, Variant>> default_values;
 	static HashSet<StringName> default_values_cached;
@@ -334,6 +335,7 @@ public:
 	static void get_extension_class_list(const Ref<GDExtension> &p_extension, List<StringName> *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<StringName> &p_classes);
 	static void get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes);
 	static StringName get_parent_class_nocheck(const StringName &p_class);

+ 2 - 2
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);
 		}
 	}
 }

+ 36 - 11
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));
+	gdtype = nullptr;
+}
+
+ObjectGDExtension::~ObjectGDExtension() {
+	if (gdtype) {
+		memdelete(const_cast<GDType *>(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<PropertyInfo> *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

+ 11 - 12
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<StringName, Variant> metadata;
 	HashMap<StringName, Variant *> 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<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator);
 
 	bool _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false);