You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-11 13:10:58 +00:00
Merge pull request #91018 from Daylily-Zeleen/daylily-zeleen/optionally_postinitialization_for_extension_owner
Allow ClassDB to create a Object without postinitialization for GDExtension.
This commit is contained in:
@@ -181,7 +181,7 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GDExtensionObjectPtr placeholder_class_create_instance(void *p_class_userdata) {
|
||||
static GDExtensionObjectPtr placeholder_class_create_instance(void *p_class_userdata, bool p_notify_postinitialize) {
|
||||
ClassDB::ClassInfo *ti = (ClassDB::ClassInfo *)p_class_userdata;
|
||||
|
||||
// Find the closest native parent, that isn't a runtime class.
|
||||
@@ -192,7 +192,7 @@ public:
|
||||
ERR_FAIL_NULL_V(native_parent->creation_func, nullptr);
|
||||
|
||||
// Construct a placeholder.
|
||||
Object *obj = native_parent->creation_func();
|
||||
Object *obj = native_parent->creation_func(p_notify_postinitialize);
|
||||
|
||||
// ClassDB::set_object_extension_instance() won't be called for placeholders.
|
||||
// We need need to make sure that all the things it would have done (even if
|
||||
@@ -525,12 +525,12 @@ StringName ClassDB::get_compatibility_class(const StringName &p_class) {
|
||||
return StringName();
|
||||
}
|
||||
|
||||
Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require_real_class) {
|
||||
Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require_real_class, bool p_notify_postinitialize) {
|
||||
ClassInfo *ti;
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
ti = classes.getptr(p_class);
|
||||
if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) {
|
||||
if (!_can_instantiate(ti)) {
|
||||
if (compat_classes.has(p_class)) {
|
||||
ti = classes.getptr(compat_classes[p_class]);
|
||||
}
|
||||
@@ -539,34 +539,78 @@ Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require
|
||||
ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, "Class '" + String(p_class) + "' is disabled.");
|
||||
ERR_FAIL_NULL_V_MSG(ti->creation_func, nullptr, "Class '" + String(p_class) + "' or its base class cannot be instantiated.");
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if ((ti->api == API_EDITOR || ti->api == API_EDITOR_EXTENSION) && !Engine::get_singleton()->is_editor_hint()) {
|
||||
ERR_PRINT("Class '" + String(p_class) + "' can only be instantiated by editor.");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
if (ti->gdextension && ti->gdextension->create_instance) {
|
||||
ObjectGDExtension *extension = ti->gdextension;
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (!p_require_real_class && ti->is_runtime && Engine::get_singleton()->is_editor_hint()) {
|
||||
extension = get_placeholder_extension(ti->name);
|
||||
}
|
||||
#endif
|
||||
return (Object *)extension->create_instance(extension->class_userdata);
|
||||
} else {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (!p_require_real_class && ti->is_runtime && Engine::get_singleton()->is_editor_hint()) {
|
||||
if (!ti->inherits_ptr || !ti->inherits_ptr->creation_func) {
|
||||
ERR_PRINT(vformat("Cannot make a placeholder instance of runtime class %s because its parent cannot be constructed.", ti->name));
|
||||
} else {
|
||||
ObjectGDExtension *extension = get_placeholder_extension(ti->name);
|
||||
return (Object *)extension->create_instance(extension->class_userdata);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ti->creation_func();
|
||||
#ifdef TOOLS_ENABLED
|
||||
// Try to create placeholder.
|
||||
if (!p_require_real_class && ti->is_runtime && Engine::get_singleton()->is_editor_hint()) {
|
||||
bool can_create_placeholder = false;
|
||||
if (ti->gdextension) {
|
||||
if (ti->gdextension->create_instance2) {
|
||||
can_create_placeholder = true;
|
||||
}
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
else if (ti->gdextension->create_instance) {
|
||||
can_create_placeholder = true;
|
||||
}
|
||||
#endif // DISABLE_DEPRECATED
|
||||
} else if (!ti->inherits_ptr || !ti->inherits_ptr->creation_func) {
|
||||
ERR_PRINT(vformat("Cannot make a placeholder instance of runtime class %s because its parent cannot be constructed.", ti->name));
|
||||
} else {
|
||||
can_create_placeholder = true;
|
||||
}
|
||||
|
||||
if (can_create_placeholder) {
|
||||
ObjectGDExtension *extension = get_placeholder_extension(ti->name);
|
||||
return (Object *)extension->create_instance2(extension->class_userdata, p_notify_postinitialize);
|
||||
}
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
if (ti->gdextension && ti->gdextension->create_instance2) {
|
||||
ObjectGDExtension *extension = ti->gdextension;
|
||||
return (Object *)extension->create_instance2(extension->class_userdata, p_notify_postinitialize);
|
||||
}
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
else if (ti->gdextension && ti->gdextension->create_instance) {
|
||||
ObjectGDExtension *extension = ti->gdextension;
|
||||
return (Object *)extension->create_instance(extension->class_userdata);
|
||||
}
|
||||
#endif // DISABLE_DEPRECATED
|
||||
else {
|
||||
return ti->creation_func(p_notify_postinitialize);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClassDB::_can_instantiate(ClassInfo *p_class_info) {
|
||||
if (!p_class_info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_class_info->disabled || !p_class_info->creation_func) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!p_class_info->gdextension) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_class_info->gdextension->create_instance2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
if (p_class_info->gdextension->create_instance) {
|
||||
return true;
|
||||
}
|
||||
#endif // DISABLE_DEPRECATED
|
||||
return false;
|
||||
}
|
||||
|
||||
Object *ClassDB::instantiate(const StringName &p_class) {
|
||||
@@ -577,6 +621,10 @@ Object *ClassDB::instantiate_no_placeholders(const StringName &p_class) {
|
||||
return _instantiate_internal(p_class, true);
|
||||
}
|
||||
|
||||
Object *ClassDB::instantiate_without_postinitialization(const StringName &p_class) {
|
||||
return _instantiate_internal(p_class, true, false);
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class) {
|
||||
ObjectGDExtension *placeholder_extension = placeholder_extensions.getptr(p_class);
|
||||
@@ -588,7 +636,7 @@ ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class)
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
ti = classes.getptr(p_class);
|
||||
if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) {
|
||||
if (!_can_instantiate(ti)) {
|
||||
if (compat_classes.has(p_class)) {
|
||||
ti = classes.getptr(compat_classes[p_class]);
|
||||
}
|
||||
@@ -649,7 +697,10 @@ ObjectGDExtension *ClassDB::get_placeholder_extension(const StringName &p_class)
|
||||
placeholder_extension->get_rid = &PlaceholderExtensionInstance::placeholder_instance_get_rid;
|
||||
|
||||
placeholder_extension->class_userdata = ti;
|
||||
placeholder_extension->create_instance = &PlaceholderExtensionInstance::placeholder_class_create_instance;
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
placeholder_extension->create_instance = nullptr;
|
||||
#endif // DISABLE_DEPRECATED
|
||||
placeholder_extension->create_instance2 = &PlaceholderExtensionInstance::placeholder_class_create_instance;
|
||||
placeholder_extension->free_instance = &PlaceholderExtensionInstance::placeholder_class_free_instance;
|
||||
placeholder_extension->get_virtual = &PlaceholderExtensionInstance::placeholder_class_get_virtual;
|
||||
placeholder_extension->get_virtual_call_data = nullptr;
|
||||
@@ -666,7 +717,7 @@ void ClassDB::set_object_extension_instance(Object *p_object, const StringName &
|
||||
{
|
||||
OBJTYPE_RLOCK;
|
||||
ti = classes.getptr(p_class);
|
||||
if (!ti || ti->disabled || !ti->creation_func || (ti->gdextension && !ti->gdextension->create_instance)) {
|
||||
if (!_can_instantiate(ti)) {
|
||||
if (compat_classes.has(p_class)) {
|
||||
ti = classes.getptr(compat_classes[p_class]);
|
||||
}
|
||||
@@ -703,7 +754,7 @@ bool ClassDB::can_instantiate(const StringName &p_class) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance));
|
||||
return _can_instantiate(ti);
|
||||
}
|
||||
|
||||
bool ClassDB::is_abstract(const StringName &p_class) {
|
||||
@@ -718,7 +769,18 @@ bool ClassDB::is_abstract(const StringName &p_class) {
|
||||
Ref<Script> scr = ResourceLoader::load(path);
|
||||
return scr.is_valid() && scr->is_valid() && scr->is_abstract();
|
||||
}
|
||||
return ti->creation_func == nullptr && (!ti->gdextension || ti->gdextension->create_instance == nullptr);
|
||||
|
||||
if (ti->creation_func != nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!ti->gdextension) {
|
||||
return true;
|
||||
}
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
return ti->gdextension->create_instance2 == nullptr && ti->gdextension->create_instance == nullptr;
|
||||
#else
|
||||
return ti->gdextension->create_instance2 == nullptr;
|
||||
#endif // DISABLE_DEPRECATED
|
||||
}
|
||||
|
||||
bool ClassDB::is_virtual(const StringName &p_class) {
|
||||
@@ -738,7 +800,7 @@ bool ClassDB::is_virtual(const StringName &p_class) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return (!ti->disabled && ti->creation_func != nullptr && !(ti->gdextension && !ti->gdextension->create_instance) && ti->is_virtual);
|
||||
return (_can_instantiate(ti) && ti->is_virtual);
|
||||
}
|
||||
|
||||
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
|
||||
|
||||
Reference in New Issue
Block a user