summaryrefslogtreecommitdiffstats
path: root/core/object/class_db.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/object/class_db.cpp')
-rw-r--r--core/object/class_db.cpp75
1 files changed, 69 insertions, 6 deletions
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index fb7eb42738..a10405dfae 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -501,12 +501,27 @@ void ClassDB::add_compatibility_class(const StringName &p_class, const StringNam
compat_classes[p_class] = p_fallback;
}
-Object *ClassDB::instance(const StringName &p_class) {
+thread_local bool initializing_with_extension = false;
+thread_local ObjectNativeExtension *initializing_extension = nullptr;
+thread_local GDExtensionClassInstancePtr initializing_extension_instance = nullptr;
+
+void ClassDB::instance_get_native_extension_data(ObjectNativeExtension **r_extension, GDExtensionClassInstancePtr *r_extension_instance) {
+ if (initializing_with_extension) {
+ *r_extension = initializing_extension;
+ *r_extension_instance = initializing_extension_instance;
+ initializing_with_extension = false;
+ } else {
+ *r_extension = nullptr;
+ *r_extension_instance = nullptr;
+ }
+}
+
+Object *ClassDB::instantiate(const StringName &p_class) {
ClassInfo *ti;
{
OBJTYPE_RLOCK;
ti = classes.getptr(p_class);
- if (!ti || ti->disabled || !ti->creation_func) {
+ if (!ti || ti->disabled || !ti->creation_func || (ti->native_extension && !ti->native_extension->create_instance)) {
if (compat_classes.has(p_class)) {
ti = classes.getptr(compat_classes[p_class]);
}
@@ -521,10 +536,15 @@ Object *ClassDB::instance(const StringName &p_class) {
return nullptr;
}
#endif
+ if (ti->native_extension) {
+ initializing_with_extension = true;
+ initializing_extension = ti->native_extension;
+ initializing_extension_instance = ti->native_extension->create_instance(ti->native_extension->class_userdata);
+ }
return ti->creation_func();
}
-bool ClassDB::can_instance(const StringName &p_class) {
+bool ClassDB::can_instantiate(const StringName &p_class) {
OBJTYPE_RLOCK;
ClassInfo *ti = classes.getptr(p_class);
@@ -534,7 +554,7 @@ bool ClassDB::can_instance(const StringName &p_class) {
return false;
}
#endif
- return (!ti->disabled && ti->creation_func != nullptr);
+ return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance));
}
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
@@ -1310,6 +1330,24 @@ bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inhe
return false;
}
+void ClassDB::bind_method_custom(const StringName &p_class, MethodBind *p_method) {
+ ClassInfo *type = classes.getptr(p_class);
+ if (!type) {
+ ERR_FAIL_MSG("Couldn't bind custom method '" + p_method->get_name() + "' for instance '" + p_class + "'.");
+ }
+
+ if (type->method_map.has(p_method->get_name())) {
+ // overloading not supported
+ ERR_FAIL_MSG("Method already bound '" + p_class + "::" + p_method->get_name() + "'.");
+ }
+
+#ifdef DEBUG_METHODS_ENABLED
+ type->method_order.push_back(p_method->get_name());
+#endif
+
+ type->method_map[p_method->get_name()] = p_method;
+}
+
#ifdef DEBUG_METHODS_ENABLED
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
StringName mdname = method_name.name;
@@ -1484,8 +1522,8 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
if (Engine::get_singleton()->has_singleton(p_class)) {
c = Engine::get_singleton()->get_singleton_object(p_class);
cleanup_c = false;
- } else if (ClassDB::can_instance(p_class)) {
- c = ClassDB::instance(p_class);
+ } else if (ClassDB::can_instantiate(p_class)) {
+ c = ClassDB::instantiate(p_class);
cleanup_c = true;
}
@@ -1545,6 +1583,31 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
return var;
}
+void ClassDB::register_extension_class(ObjectNativeExtension *p_extension) {
+ GLOBAL_LOCK_FUNCTION;
+
+ ERR_FAIL_COND_MSG(classes.has(p_extension->class_name), "Class already registered: " + String(p_extension->class_name));
+ ERR_FAIL_COND_MSG(classes.has(p_extension->parent_class_name), "Parent class name for extension class not found: " + String(p_extension->parent_class_name));
+
+ ClassInfo *parent = classes.getptr(p_extension->parent_class_name);
+
+ ClassInfo c;
+ c.api = p_extension->editor_class ? API_EDITOR_EXTENSION : API_EXTENSION;
+ c.native_extension = p_extension;
+ c.name = p_extension->class_name;
+ c.creation_func = parent->creation_func;
+ c.inherits = parent->name;
+ c.class_ptr = parent->class_ptr;
+ c.inherits_ptr = parent;
+
+ classes[p_extension->class_name] = c;
+}
+
+void ClassDB::unregister_extension_class(const StringName &p_class) {
+ ERR_FAIL_COND(!classes.has(p_class));
+ classes.erase(p_class);
+}
+
RWLock ClassDB::lock;
void ClassDB::cleanup_defaults() {