Skip to content

Commit f44aa13

Browse files
committed
Merge pull request godotengine#111090 from dsnopek/gdextension-compat-unexposed-classes-redo
GDExtension: Prevent breaking compatibility for unexposed classes that can only be created once
2 parents 96c0d7c + 2c707a9 commit f44aa13

File tree

4 files changed

+33
-5
lines changed

4 files changed

+33
-5
lines changed

core/extension/gdextension.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
267267
};
268268

269269
const ClassCreationDeprecatedInfo legacy = {
270+
false,
270271
p_extension_funcs->notification_func, // GDExtensionClassNotification notification_func;
271272
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
272273
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
@@ -281,7 +282,7 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar
281282
const GDExtensionClassCreationInfo5 class_info5 = {
282283
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
283284
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
284-
true, // GDExtensionBool is_exposed;
285+
p_extension_funcs->is_exposed, // GDExtensionBool is_exposed;
285286
false, // GDExtensionBool is_runtime;
286287
nullptr, // GDExtensionConstStringPtr icon_path;
287288
p_extension_funcs->set_func, // GDExtensionClassSet set_func;
@@ -305,6 +306,7 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar
305306
};
306307

307308
const ClassCreationDeprecatedInfo legacy = {
309+
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
308310
nullptr, // GDExtensionClassNotification notification_func;
309311
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
310312
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
@@ -319,7 +321,7 @@ void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_librar
319321
const GDExtensionClassCreationInfo5 class_info5 = {
320322
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
321323
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
322-
true, // GDExtensionBool is_exposed;
324+
p_extension_funcs->is_exposed, // GDExtensionBool is_exposed;
323325
p_extension_funcs->is_runtime, // GDExtensionBool is_runtime;
324326
nullptr, // GDExtensionConstStringPtr icon_path;
325327
p_extension_funcs->set_func, // GDExtensionClassSet set_func;
@@ -343,6 +345,7 @@ void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_librar
343345
};
344346

345347
const ClassCreationDeprecatedInfo legacy = {
348+
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
346349
nullptr, // GDExtensionClassNotification notification_func;
347350
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
348351
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance2 create_instance_func;
@@ -355,9 +358,16 @@ void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_librar
355358

356359
void GDExtension::_register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs) {
357360
GDExtensionClassCreationInfo5 class_info5 = *p_extension_funcs;
358-
// Force classes to be exposed, because the behavior of unexposed classes changed in an incompatible (albeit, minor) way.
359-
class_info5.is_exposed = true;
360-
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info5);
361+
const ClassCreationDeprecatedInfo legacy = {
362+
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
363+
nullptr, // GDExtensionClassNotification notification_func;
364+
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
365+
nullptr, // GDExtensionClassCreateInstance2 create_instance_func;
366+
nullptr, // GDExtensionClassGetRID get_rid;
367+
nullptr, // GDExtensionClassGetVirtual get_virtual_func;
368+
nullptr, // GDExtensionClassGetVirtual get_virtual_func;
369+
};
370+
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info5, &legacy);
361371
}
362372
#endif // DISABLE_DEPRECATED
363373

@@ -447,6 +457,7 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
447457
extension->gdextension.validate_property = p_extension_funcs->validate_property_func;
448458
#ifndef DISABLE_DEPRECATED
449459
if (p_deprecated_funcs) {
460+
extension->gdextension.legacy_unexposed_class = p_deprecated_funcs->legacy_unexposed_class;
450461
extension->gdextension.notification = p_deprecated_funcs->notification_func;
451462
extension->gdextension.free_property_list = p_deprecated_funcs->free_property_list_func;
452463
extension->gdextension.create_instance = p_deprecated_funcs->create_instance_func;

core/extension/gdextension.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class GDExtension : public Resource {
6767

6868
struct ClassCreationDeprecatedInfo {
6969
#ifndef DISABLE_DEPRECATED
70+
bool legacy_unexposed_class = false;
7071
GDExtensionClassNotification notification_func = nullptr;
7172
GDExtensionClassFreePropertyList free_property_list_func = nullptr;
7273
GDExtensionClassCreateInstance create_instance_func = nullptr;

core/object/class_db.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,12 @@ Object *ClassDB::_instantiate_internal(const StringName &p_class, bool p_require
564564
}
565565
ERR_FAIL_NULL_V_MSG(ti, nullptr, vformat("Cannot get class '%s'.", String(p_class)));
566566
ERR_FAIL_COND_V_MSG(ti->disabled, nullptr, vformat("Class '%s' is disabled.", String(p_class)));
567+
#ifndef DISABLE_DEPRECATED
568+
// Force legacy unexposed classes to skip the exposed check to preserve backcompat.
569+
if (ti->gdextension && ti->gdextension->legacy_unexposed_class) {
570+
p_exposed_only = false;
571+
}
572+
#endif // DISABLE_DEPRECATED
567573
if (p_exposed_only) {
568574
ERR_FAIL_COND_V_MSG(!ti->exposed, nullptr, vformat("Class '%s' isn't exposed.", String(p_class)));
569575
}
@@ -623,6 +629,13 @@ bool ClassDB::_can_instantiate(ClassInfo *p_class_info, bool p_exposed_only) {
623629
return false;
624630
}
625631

632+
#ifndef DISABLE_DEPRECATED
633+
// Force legacy unexposed classes to skip the exposed check to preserve backcompat.
634+
if (p_class_info->gdextension && p_class_info->gdextension->legacy_unexposed_class) {
635+
p_exposed_only = false;
636+
}
637+
#endif // DISABLE_DEPRECATED
638+
626639
if (p_exposed_only && !p_class_info->exposed) {
627640
return false;
628641
}

core/object/object.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,9 @@ struct ObjectGDExtension {
330330
bool is_runtime = false;
331331
bool is_placeholder = false;
332332
#endif
333+
#ifndef DISABLE_DEPRECATED
334+
bool legacy_unexposed_class = false;
335+
#endif // DISABLE_DEPRECATED
333336
GDExtensionClassSet set;
334337
GDExtensionClassGet get;
335338
GDExtensionClassGetPropertyList get_property_list;

0 commit comments

Comments
 (0)