Browse Source

Merge pull request #78634 from Sauermann/fix-notification-order

Fix `Object::notification` order
Rémi Verschelde 1 year ago
parent
commit
8edc0b43b9

+ 43 - 1
core/extension/gdextension.cpp

@@ -281,7 +281,40 @@ public:
 	}
 	}
 };
 };
 
 
+#ifndef DISABLE_DEPRECATED
 void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs) {
 void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs) {
+	const GDExtensionClassCreationInfo2 class_info2 = {
+		p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
+		p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
+		p_extension_funcs->set_func, // GDExtensionClassSet set_func;
+		p_extension_funcs->get_func, // GDExtensionClassGet get_func;
+		p_extension_funcs->get_property_list_func, // GDExtensionClassGetPropertyList get_property_list_func;
+		p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
+		p_extension_funcs->property_can_revert_func, // GDExtensionClassPropertyCanRevert property_can_revert_func;
+		p_extension_funcs->property_get_revert_func, // GDExtensionClassPropertyGetRevert property_get_revert_func;
+		nullptr, // GDExtensionClassNotification2 notification_func;
+		p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func;
+		p_extension_funcs->reference_func, // GDExtensionClassReference reference_func;
+		p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func;
+		p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
+		p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
+		p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
+		p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
+		p_extension_funcs->class_userdata, // void *class_userdata;
+	};
+
+	const ClassCreationDeprecatedInfo legacy = {
+		p_extension_funcs->notification_func,
+	};
+	_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info2, &legacy);
+}
+#endif // DISABLE_DEPRECATED
+
+void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs) {
+	_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, p_extension_funcs);
+}
+
+void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs) {
 	GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
 	GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
 
 
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
 	StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
@@ -325,7 +358,12 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
 	extension->gdextension.free_property_list = p_extension_funcs->free_property_list_func;
 	extension->gdextension.free_property_list = p_extension_funcs->free_property_list_func;
 	extension->gdextension.property_can_revert = p_extension_funcs->property_can_revert_func;
 	extension->gdextension.property_can_revert = p_extension_funcs->property_can_revert_func;
 	extension->gdextension.property_get_revert = p_extension_funcs->property_get_revert_func;
 	extension->gdextension.property_get_revert = p_extension_funcs->property_get_revert_func;
-	extension->gdextension.notification = p_extension_funcs->notification_func;
+#ifndef DISABLE_DEPRECATED
+	if (p_deprecated_funcs) {
+		extension->gdextension.notification = p_deprecated_funcs->notification_func;
+	}
+#endif // DISABLE_DEPRECATED
+	extension->gdextension.notification2 = p_extension_funcs->notification_func;
 	extension->gdextension.to_string = p_extension_funcs->to_string_func;
 	extension->gdextension.to_string = p_extension_funcs->to_string_func;
 	extension->gdextension.reference = p_extension_funcs->reference_func;
 	extension->gdextension.reference = p_extension_funcs->reference_func;
 	extension->gdextension.unreference = p_extension_funcs->unreference_func;
 	extension->gdextension.unreference = p_extension_funcs->unreference_func;
@@ -337,6 +375,7 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
 
 
 	ClassDB::register_extension_class(&extension->gdextension);
 	ClassDB::register_extension_class(&extension->gdextension);
 }
 }
+
 void GDExtension::_register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info) {
 void GDExtension::_register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info) {
 	GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
 	GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
 
 
@@ -548,7 +587,10 @@ GDExtension::~GDExtension() {
 void GDExtension::initialize_gdextensions() {
 void GDExtension::initialize_gdextensions() {
 	gdextension_setup_interface();
 	gdextension_setup_interface();
 
 
+#ifndef DISABLE_DEPRECATED
 	register_interface_function("classdb_register_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class);
 	register_interface_function("classdb_register_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class);
+#endif // DISABLE_DEPRECATED
+	register_interface_function("classdb_register_extension_class2", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class2);
 	register_interface_function("classdb_register_extension_class_method", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_method);
 	register_interface_function("classdb_register_extension_class_method", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_method);
 	register_interface_function("classdb_register_extension_class_integer_constant", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_integer_constant);
 	register_interface_function("classdb_register_extension_class_integer_constant", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_integer_constant);
 	register_interface_function("classdb_register_extension_class_property", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_property);
 	register_interface_function("classdb_register_extension_class_property", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_property);

+ 10 - 0
core/extension/gdextension.h

@@ -53,7 +53,17 @@ class GDExtension : public Resource {
 
 
 	HashMap<StringName, Extension> extension_classes;
 	HashMap<StringName, Extension> extension_classes;
 
 
+	struct ClassCreationDeprecatedInfo {
+#ifndef DISABLE_DEPRECATED
+		GDExtensionClassNotification notification_func = nullptr;
+#endif // DISABLE_DEPRECATED
+	};
+
+#ifndef DISABLE_DEPRECATED
 	static void _register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
 	static void _register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
+#endif // DISABLE_DEPRECATED
+	static void _register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs);
+	static void _register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs = nullptr);
 	static void _register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info);
 	static void _register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info);
 	static void _register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield);
 	static void _register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield);
 	static void _register_extension_class_property(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter);
 	static void _register_extension_class_property(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionPropertyInfo *p_info, GDExtensionConstStringNamePtr p_setter, GDExtensionConstStringNamePtr p_getter);

+ 39 - 0
core/extension/gdextension_interface.cpp

@@ -1041,7 +1041,43 @@ static void gdextension_ref_set_object(GDExtensionRefPtr p_ref, GDExtensionObjec
 	ref->reference_ptr(o);
 	ref->reference_ptr(o);
 }
 }
 
 
+#ifndef DISABLE_DEPRECATED
 static GDExtensionScriptInstancePtr gdextension_script_instance_create(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data) {
 static GDExtensionScriptInstancePtr gdextension_script_instance_create(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data) {
+	const GDExtensionScriptInstanceInfo2 info_2 = {
+		p_info->set_func,
+		p_info->get_func,
+		p_info->get_property_list_func,
+		p_info->free_property_list_func,
+		p_info->property_can_revert_func,
+		p_info->property_get_revert_func,
+		p_info->get_owner_func,
+		p_info->get_property_state_func,
+		p_info->get_method_list_func,
+		p_info->free_method_list_func,
+		p_info->get_property_type_func,
+		p_info->has_method_func,
+		p_info->call_func,
+		nullptr, // notification_func.
+		p_info->to_string_func,
+		p_info->refcount_incremented_func,
+		p_info->refcount_decremented_func,
+		p_info->get_script_func,
+		p_info->is_placeholder_func,
+		p_info->set_fallback_func,
+		p_info->get_fallback_func,
+		p_info->get_language_func,
+		p_info->free_func,
+	};
+
+	ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension);
+	script_instance_extension->instance = p_instance_data;
+	script_instance_extension->native_info = &info_2;
+	script_instance_extension->deprecated_native_info.notification_func = p_info->notification_func;
+	return reinterpret_cast<GDExtensionScriptInstancePtr>(script_instance_extension);
+}
+#endif // DISABLE_DEPRECATED
+
+static GDExtensionScriptInstancePtr gdextension_script_instance_create2(const GDExtensionScriptInstanceInfo2 *p_info, GDExtensionScriptInstanceDataPtr p_instance_data) {
 	ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension);
 	ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension);
 	script_instance_extension->instance = p_instance_data;
 	script_instance_extension->instance = p_instance_data;
 	script_instance_extension->native_info = p_info;
 	script_instance_extension->native_info = p_info;
@@ -1269,7 +1305,10 @@ void gdextension_setup_interface() {
 	REGISTER_INTERFACE_FUNC(object_get_instance_id);
 	REGISTER_INTERFACE_FUNC(object_get_instance_id);
 	REGISTER_INTERFACE_FUNC(ref_get_object);
 	REGISTER_INTERFACE_FUNC(ref_get_object);
 	REGISTER_INTERFACE_FUNC(ref_set_object);
 	REGISTER_INTERFACE_FUNC(ref_set_object);
+#ifndef DISABLE_DEPRECATED
 	REGISTER_INTERFACE_FUNC(script_instance_create);
 	REGISTER_INTERFACE_FUNC(script_instance_create);
+#endif // DISABLE_DEPRECATED
+	REGISTER_INTERFACE_FUNC(script_instance_create2);
 	REGISTER_INTERFACE_FUNC(placeholder_script_instance_create);
 	REGISTER_INTERFACE_FUNC(placeholder_script_instance_create);
 	REGISTER_INTERFACE_FUNC(placeholder_script_instance_update);
 	REGISTER_INTERFACE_FUNC(placeholder_script_instance_update);
 	REGISTER_INTERFACE_FUNC(object_get_script_instance);
 	REGISTER_INTERFACE_FUNC(object_get_script_instance);

+ 95 - 4
core/extension/gdextension_interface.h

@@ -258,7 +258,8 @@ typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExte
 typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list);
 typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list);
 typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name);
 typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name);
 typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
 typedef GDExtensionBool (*GDExtensionClassPropertyGetRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionVariantPtr r_ret);
-typedef void (*GDExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what);
+typedef void (*GDExtensionClassNotification)(GDExtensionClassInstancePtr p_instance, int32_t p_what); // Deprecated. Use GDExtensionClassNotification2 instead.
+typedef void (*GDExtensionClassNotification2)(GDExtensionClassInstancePtr p_instance, int32_t p_what, bool p_reversed);
 typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr p_out);
 typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr p_out);
 typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
 typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
 typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
 typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
@@ -285,7 +286,27 @@ typedef struct {
 	GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
 	GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
 	GDExtensionClassGetRID get_rid_func;
 	GDExtensionClassGetRID get_rid_func;
 	void *class_userdata; // Per-class user data, later accessible in instance bindings.
 	void *class_userdata; // Per-class user data, later accessible in instance bindings.
-} GDExtensionClassCreationInfo;
+} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo2 instead.
+
+typedef struct {
+	GDExtensionBool is_virtual;
+	GDExtensionBool is_abstract;
+	GDExtensionClassSet set_func;
+	GDExtensionClassGet get_func;
+	GDExtensionClassGetPropertyList get_property_list_func;
+	GDExtensionClassFreePropertyList free_property_list_func;
+	GDExtensionClassPropertyCanRevert property_can_revert_func;
+	GDExtensionClassPropertyGetRevert property_get_revert_func;
+	GDExtensionClassNotification2 notification_func;
+	GDExtensionClassToString to_string_func;
+	GDExtensionClassReference reference_func;
+	GDExtensionClassUnreference unreference_func;
+	GDExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
+	GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
+	GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
+	GDExtensionClassGetRID get_rid_func;
+	void *class_userdata; // Per-class user data, later accessible in instance bindings.
+} GDExtensionClassCreationInfo2;
 
 
 typedef void *GDExtensionClassLibraryPtr;
 typedef void *GDExtensionClassLibraryPtr;
 
 
@@ -366,7 +387,8 @@ typedef void (*GDExtensionScriptInstanceFreeMethodList)(GDExtensionScriptInstanc
 typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
 typedef GDExtensionBool (*GDExtensionScriptInstanceHasMethod)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionConstStringNamePtr p_name);
 
 
 typedef void (*GDExtensionScriptInstanceCall)(GDExtensionScriptInstanceDataPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
 typedef void (*GDExtensionScriptInstanceCall)(GDExtensionScriptInstanceDataPtr p_self, GDExtensionConstStringNamePtr p_method, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
-typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what);
+typedef void (*GDExtensionScriptInstanceNotification)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what); // Deprecated. Use GDExtensionScriptInstanceNotification2 instead.
+typedef void (*GDExtensionScriptInstanceNotification2)(GDExtensionScriptInstanceDataPtr p_instance, int32_t p_what, bool p_reversed);
 typedef void (*GDExtensionScriptInstanceToString)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
 typedef void (*GDExtensionScriptInstanceToString)(GDExtensionScriptInstanceDataPtr p_instance, GDExtensionBool *r_is_valid, GDExtensionStringPtr r_out);
 
 
 typedef void (*GDExtensionScriptInstanceRefCountIncremented)(GDExtensionScriptInstanceDataPtr p_instance);
 typedef void (*GDExtensionScriptInstanceRefCountIncremented)(GDExtensionScriptInstanceDataPtr p_instance);
@@ -420,7 +442,46 @@ typedef struct {
 
 
 	GDExtensionScriptInstanceFree free_func;
 	GDExtensionScriptInstanceFree free_func;
 
 
-} GDExtensionScriptInstanceInfo;
+} GDExtensionScriptInstanceInfo; // Deprecated. Use GDExtensionScriptInstanceInfo2 instead.
+
+typedef struct {
+	GDExtensionScriptInstanceSet set_func;
+	GDExtensionScriptInstanceGet get_func;
+	GDExtensionScriptInstanceGetPropertyList get_property_list_func;
+	GDExtensionScriptInstanceFreePropertyList free_property_list_func;
+
+	GDExtensionScriptInstancePropertyCanRevert property_can_revert_func;
+	GDExtensionScriptInstancePropertyGetRevert property_get_revert_func;
+
+	GDExtensionScriptInstanceGetOwner get_owner_func;
+	GDExtensionScriptInstanceGetPropertyState get_property_state_func;
+
+	GDExtensionScriptInstanceGetMethodList get_method_list_func;
+	GDExtensionScriptInstanceFreeMethodList free_method_list_func;
+	GDExtensionScriptInstanceGetPropertyType get_property_type_func;
+
+	GDExtensionScriptInstanceHasMethod has_method_func;
+
+	GDExtensionScriptInstanceCall call_func;
+	GDExtensionScriptInstanceNotification2 notification_func;
+
+	GDExtensionScriptInstanceToString to_string_func;
+
+	GDExtensionScriptInstanceRefCountIncremented refcount_incremented_func;
+	GDExtensionScriptInstanceRefCountDecremented refcount_decremented_func;
+
+	GDExtensionScriptInstanceGetScript get_script_func;
+
+	GDExtensionScriptInstanceIsPlaceholder is_placeholder_func;
+
+	GDExtensionScriptInstanceSet set_fallback_func;
+	GDExtensionScriptInstanceGet get_fallback_func;
+
+	GDExtensionScriptInstanceGetLanguage get_language_func;
+
+	GDExtensionScriptInstanceFree free_func;
+
+} GDExtensionScriptInstanceInfo2;
 
 
 /* INITIALIZATION */
 /* INITIALIZATION */
 
 
@@ -2116,6 +2177,7 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
 /**
 /**
  * @name script_instance_create
  * @name script_instance_create
  * @since 4.1
  * @since 4.1
+ * @deprecated in Godot 4.2. Use `script_instance_create2` instead.
  *
  *
  * Creates a script instance that contains the given info and instance data.
  * Creates a script instance that contains the given info and instance data.
  *
  *
@@ -2126,6 +2188,19 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
  */
  */
 typedef GDExtensionScriptInstancePtr (*GDExtensionInterfaceScriptInstanceCreate)(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data);
 typedef GDExtensionScriptInstancePtr (*GDExtensionInterfaceScriptInstanceCreate)(const GDExtensionScriptInstanceInfo *p_info, GDExtensionScriptInstanceDataPtr p_instance_data);
 
 
+/**
+ * @name script_instance_create2
+ * @since 4.2
+ *
+ * Creates a script instance that contains the given info and instance data.
+ *
+ * @param p_info A pointer to a GDExtensionScriptInstanceInfo2 struct.
+ * @param p_instance_data A pointer to a data representing the script instance in the GDExtension. This will be passed to all the function pointers on p_info.
+ *
+ * @return A pointer to a ScriptInstanceExtension object.
+ */
+typedef GDExtensionScriptInstancePtr (*GDExtensionInterfaceScriptInstanceCreate2)(const GDExtensionScriptInstanceInfo2 *p_info, GDExtensionScriptInstanceDataPtr p_instance_data);
+
 /**
 /**
  * @name placeholder_script_instance_create
  * @name placeholder_script_instance_create
  * @since 4.2
  * @since 4.2
@@ -2217,6 +2292,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
 /**
 /**
  * @name classdb_register_extension_class
  * @name classdb_register_extension_class
  * @since 4.1
  * @since 4.1
+ * @deprecated in Godot 4.2. Use `classdb_register_extension_class2` instead.
  *
  *
  * Registers an extension class in the ClassDB.
  * Registers an extension class in the ClassDB.
  *
  *
@@ -2229,6 +2305,21 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
  */
  */
 typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
 typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
 
 
+/**
+ * @name classdb_register_extension_class2
+ * @since 4.2
+ *
+ * Registers an extension class in the ClassDB.
+ *
+ * Provided struct can be safely freed once the function returns.
+ *
+ * @param p_library A pointer the library received by the GDExtension's entry point function.
+ * @param p_class_name A pointer to a StringName with the class name.
+ * @param p_parent_class_name A pointer to a StringName with the parent class name.
+ * @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo2 struct.
+ */
+typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs);
+
 /**
 /**
  * @name classdb_register_extension_class_method
  * @name classdb_register_extension_class_method
  * @since 4.1
  * @since 4.1

+ 21 - 5
core/object/object.cpp

@@ -799,14 +799,30 @@ Variant Object::call_const(const StringName &p_method, const Variant **p_args, i
 }
 }
 
 
 void Object::notification(int p_notification, bool p_reversed) {
 void Object::notification(int p_notification, bool p_reversed) {
-	_notificationv(p_notification, p_reversed);
+	if (p_reversed) {
+		if (script_instance) {
+			script_instance->notification(p_notification, p_reversed);
+		}
+	} else {
+		_notificationv(p_notification, p_reversed);
+	}
 
 
-	if (script_instance) {
-		script_instance->notification(p_notification);
+	if (_extension) {
+		if (_extension->notification2) {
+			_extension->notification2(_extension_instance, p_notification, p_reversed);
+#ifndef DISABLE_DEPRECATED
+		} else if (_extension->notification) {
+			_extension->notification(_extension_instance, p_notification);
+#endif // DISABLE_DEPRECATED
+		}
 	}
 	}
 
 
-	if (_extension && _extension->notification) {
-		_extension->notification(_extension_instance, p_notification);
+	if (p_reversed) {
+		_notificationv(p_notification, p_reversed);
+	} else {
+		if (script_instance) {
+			script_instance->notification(p_notification, p_reversed);
+		}
 	}
 	}
 }
 }
 
 

+ 3 - 0
core/object/object.h

@@ -321,7 +321,10 @@ struct ObjectGDExtension {
 	GDExtensionClassFreePropertyList free_property_list;
 	GDExtensionClassFreePropertyList free_property_list;
 	GDExtensionClassPropertyCanRevert property_can_revert;
 	GDExtensionClassPropertyCanRevert property_can_revert;
 	GDExtensionClassPropertyGetRevert property_get_revert;
 	GDExtensionClassPropertyGetRevert property_get_revert;
+#ifndef DISABLE_DEPRECATED
 	GDExtensionClassNotification notification;
 	GDExtensionClassNotification notification;
+#endif // DISABLE_DEPRECATED
+	GDExtensionClassNotification2 notification2;
 	GDExtensionClassToString to_string;
 	GDExtensionClassToString to_string;
 	GDExtensionClassReference reference;
 	GDExtensionClassReference reference;
 	GDExtensionClassReference unreference;
 	GDExtensionClassReference unreference;

+ 2 - 2
core/object/script_language.h

@@ -205,7 +205,7 @@ public:
 	}
 	}
 
 
 	virtual Variant call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error); // implement if language supports const functions
 	virtual Variant call_const(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error); // implement if language supports const functions
-	virtual void notification(int p_notification) = 0;
+	virtual void notification(int p_notification, bool p_reversed = false) = 0;
 	virtual String to_string(bool *r_valid) {
 	virtual String to_string(bool *r_valid) {
 		if (r_valid) {
 		if (r_valid) {
 			*r_valid = false;
 			*r_valid = false;
@@ -476,7 +476,7 @@ public:
 		r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
 		r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
 		return Variant();
 		return Variant();
 	}
 	}
-	virtual void notification(int p_notification) override {}
+	virtual void notification(int p_notification, bool p_reversed = false) override {}
 
 
 	virtual Ref<Script> get_script() const override { return script; }
 	virtual Ref<Script> get_script() const override { return script; }
 
 

+ 12 - 3
core/object/script_language_extension.h

@@ -630,7 +630,11 @@ VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionLocation)
 
 
 class ScriptInstanceExtension : public ScriptInstance {
 class ScriptInstanceExtension : public ScriptInstance {
 public:
 public:
-	const GDExtensionScriptInstanceInfo *native_info;
+	const GDExtensionScriptInstanceInfo2 *native_info;
+	struct {
+		GDExtensionClassNotification notification_func;
+	} deprecated_native_info;
+
 	GDExtensionScriptInstanceDataPtr instance = nullptr;
 	GDExtensionScriptInstanceDataPtr instance = nullptr;
 
 
 // There should not be warnings on explicit casts.
 // There should not be warnings on explicit casts.
@@ -746,11 +750,16 @@ public:
 		return ret;
 		return ret;
 	}
 	}
 
 
-	virtual void notification(int p_notification) override {
+	virtual void notification(int p_notification, bool p_reversed = false) override {
 		if (native_info->notification_func) {
 		if (native_info->notification_func) {
-			native_info->notification_func(instance, p_notification);
+			native_info->notification_func(instance, p_notification, p_reversed);
+#ifndef DISABLE_DEPRECATED
+		} else if (deprecated_native_info.notification_func) {
+			deprecated_native_info.notification_func(instance, p_notification);
+#endif // DISABLE_DEPRECATED
 		}
 		}
 	}
 	}
+
 	virtual String to_string(bool *r_valid) override {
 	virtual String to_string(bool *r_valid) override {
 		if (native_info->to_string_func) {
 		if (native_info->to_string_func) {
 			GDExtensionBool valid;
 			GDExtensionBool valid;

+ 11 - 3
modules/gdscript/gdscript.cpp

@@ -1921,14 +1921,23 @@ Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_ar
 	return Variant();
 	return Variant();
 }
 }
 
 
-void GDScriptInstance::notification(int p_notification) {
+void GDScriptInstance::notification(int p_notification, bool p_reversed) {
 	//notification is not virtual, it gets called at ALL levels just like in C.
 	//notification is not virtual, it gets called at ALL levels just like in C.
 	Variant value = p_notification;
 	Variant value = p_notification;
 	const Variant *args[1] = { &value };
 	const Variant *args[1] = { &value };
 
 
+	List<GDScript *> pl;
 	GDScript *sptr = script.ptr();
 	GDScript *sptr = script.ptr();
 	while (sptr) {
 	while (sptr) {
-		HashMap<StringName, GDScriptFunction *>::Iterator E = sptr->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
+		if (p_reversed) {
+			pl.push_back(sptr);
+		} else {
+			pl.push_front(sptr);
+		}
+		sptr = sptr->_base;
+	}
+	for (GDScript *sc : pl) {
+		HashMap<StringName, GDScriptFunction *>::Iterator E = sc->member_functions.find(GDScriptLanguage::get_singleton()->strings._notification);
 		if (E) {
 		if (E) {
 			Callable::CallError err;
 			Callable::CallError err;
 			E->value->call(this, args, 1, err);
 			E->value->call(this, args, 1, err);
@@ -1936,7 +1945,6 @@ void GDScriptInstance::notification(int p_notification) {
 				//print error about notification call
 				//print error about notification call
 			}
 			}
 		}
 		}
-		sptr = sptr->_base;
 	}
 	}
 }
 }
 
 

+ 1 - 1
modules/gdscript/gdscript.h

@@ -332,7 +332,7 @@ public:
 
 
 	Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }
 	Variant debug_get_member_by_index(int p_idx) const { return members[p_idx]; }
 
 
-	virtual void notification(int p_notification);
+	virtual void notification(int p_notification, bool p_reversed = false);
 	String to_string(bool *r_valid);
 	String to_string(bool *r_valid);
 
 
 	virtual Ref<Script> get_script() const;
 	virtual Ref<Script> get_script() const;

+ 4 - 4
modules/mono/csharp_script.cpp

@@ -1978,7 +1978,7 @@ const Variant CSharpInstance::get_rpc_config() const {
 	return script->get_rpc_config();
 	return script->get_rpc_config();
 }
 }
 
 
-void CSharpInstance::notification(int p_notification) {
+void CSharpInstance::notification(int p_notification, bool p_reversed) {
 	if (p_notification == Object::NOTIFICATION_PREDELETE) {
 	if (p_notification == Object::NOTIFICATION_PREDELETE) {
 		// When NOTIFICATION_PREDELETE is sent, we also take the chance to call Dispose().
 		// When NOTIFICATION_PREDELETE is sent, we also take the chance to call Dispose().
 		// It's safe to call Dispose() multiple times and NOTIFICATION_PREDELETE is guaranteed
 		// It's safe to call Dispose() multiple times and NOTIFICATION_PREDELETE is guaranteed
@@ -1996,7 +1996,7 @@ void CSharpInstance::notification(int p_notification) {
 			return;
 			return;
 		}
 		}
 
 
-		_call_notification(p_notification);
+		_call_notification(p_notification, p_reversed);
 
 
 		GDMonoCache::managed_callbacks.CSharpInstanceBridge_CallDispose(
 		GDMonoCache::managed_callbacks.CSharpInstanceBridge_CallDispose(
 				gchandle.get_intptr(), /* okIfNull */ false);
 				gchandle.get_intptr(), /* okIfNull */ false);
@@ -2004,10 +2004,10 @@ void CSharpInstance::notification(int p_notification) {
 		return;
 		return;
 	}
 	}
 
 
-	_call_notification(p_notification);
+	_call_notification(p_notification, p_reversed);
 }
 }
 
 
-void CSharpInstance::_call_notification(int p_notification) {
+void CSharpInstance::_call_notification(int p_notification, bool p_reversed) {
 	Variant arg = p_notification;
 	Variant arg = p_notification;
 	const Variant *args[1] = { &arg };
 	const Variant *args[1] = { &arg };
 	StringName method_name = SNAME("_notification");
 	StringName method_name = SNAME("_notification");

+ 2 - 2
modules/mono/csharp_script.h

@@ -283,8 +283,8 @@ public:
 
 
 	const Variant get_rpc_config() const override;
 	const Variant get_rpc_config() const override;
 
 
-	void notification(int p_notification) override;
-	void _call_notification(int p_notification);
+	void notification(int p_notification, bool p_reversed = false) override;
+	void _call_notification(int p_notification, bool p_reversed = false);
 
 
 	String to_string(bool *r_valid) override;
 	String to_string(bool *r_valid) override;
 
 

+ 1 - 1
scene/main/scene_tree.cpp

@@ -344,7 +344,7 @@ void SceneTree::notify_group_flags(uint32_t p_call_flags, const StringName &p_gr
 			}
 			}
 
 
 			if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
 			if (!(p_call_flags & GROUP_CALL_DEFERRED)) {
-				gr_nodes[i]->notification(p_notification);
+				gr_nodes[i]->notification(p_notification, true);
 			} else {
 			} else {
 				MessageQueue::get_singleton()->push_notification(gr_nodes[i], p_notification);
 				MessageQueue::get_singleton()->push_notification(gr_nodes[i], p_notification);
 			}
 			}

+ 69 - 1
tests/core/object/test_object.h

@@ -98,7 +98,7 @@ public:
 	Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
 	Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
 		return Variant();
 		return Variant();
 	}
 	}
-	void notification(int p_notification) override {
+	void notification(int p_notification, bool p_reversed = false) override {
 	}
 	}
 	Ref<Script> get_script() const override {
 	Ref<Script> get_script() const override {
 		return Ref<Script>();
 		return Ref<Script>();
@@ -426,6 +426,74 @@ TEST_CASE("[Object] Signals") {
 	}
 	}
 }
 }
 
 
+class NotificationObject1 : public Object {
+	GDCLASS(NotificationObject1, Object);
+
+protected:
+	void _notification(int p_what) {
+		switch (p_what) {
+			case 12345: {
+				order_internal1 = order_global++;
+			} break;
+		}
+	}
+
+public:
+	static int order_global;
+	int order_internal1 = -1;
+
+	void reset_order() {
+		order_internal1 = -1;
+		order_global = 1;
+	}
+};
+
+int NotificationObject1::order_global = 1;
+
+class NotificationObject2 : public NotificationObject1 {
+	GDCLASS(NotificationObject2, NotificationObject1);
+
+protected:
+	void _notification(int p_what) {
+		switch (p_what) {
+			case 12345: {
+				order_internal2 = order_global++;
+			} break;
+		}
+	}
+
+public:
+	int order_internal2 = -1;
+	void reset_order() {
+		NotificationObject1::reset_order();
+		order_internal2 = -1;
+	}
+};
+
+TEST_CASE("[Object] Notification order") { // GH-52325
+	NotificationObject2 *test_notification_object = memnew(NotificationObject2);
+
+	SUBCASE("regular order") {
+		test_notification_object->notification(12345, false);
+
+		CHECK_EQ(test_notification_object->order_internal1, 1);
+		CHECK_EQ(test_notification_object->order_internal2, 2);
+
+		test_notification_object->reset_order();
+	}
+
+	SUBCASE("reverse order") {
+		test_notification_object->notification(12345, true);
+
+		CHECK_EQ(test_notification_object->order_internal1, 2);
+		CHECK_EQ(test_notification_object->order_internal2, 1);
+
+		test_notification_object->reset_order();
+	}
+
+	memdelete(test_notification_object);
+}
+
 } // namespace TestObject
 } // namespace TestObject
 
 
 #endif // TEST_OBJECT_H
 #endif // TEST_OBJECT_H