Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Object::notification order #78634

Merged
merged 1 commit into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion core/extension/gdextension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,40 @@ class GDExtensionMethodBind : public MethodBind {
}
};

#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) {
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) {
dsnopek marked this conversation as resolved.
Show resolved Hide resolved
_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);

StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
Expand Down Expand Up @@ -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.property_can_revert = p_extension_funcs->property_can_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.reference = p_extension_funcs->reference_func;
extension->gdextension.unreference = p_extension_funcs->unreference_func;
Expand All @@ -337,6 +375,7 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library

ClassDB::register_extension_class(&extension->gdextension);
}

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);

Expand Down Expand Up @@ -548,7 +587,10 @@ GDExtension::~GDExtension() {
void GDExtension::initialize_gdextensions() {
gdextension_setup_interface();

#ifndef DISABLE_DEPRECATED
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_integer_constant", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_integer_constant);
register_interface_function("classdb_register_extension_class_property", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_property);
Expand Down
10 changes: 10 additions & 0 deletions core/extension/gdextension.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,17 @@ class GDExtension : public Resource {

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);
#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_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);
Expand Down
39 changes: 39 additions & 0 deletions core/extension/gdextension_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,43 @@ static void gdextension_ref_set_object(GDExtensionRefPtr p_ref, GDExtensionObjec
ref->reference_ptr(o);
}

#ifndef DISABLE_DEPRECATED
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is taking the address of a temporary, which is causing crashes when the functions are called later.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, right because unlike classdb_register_extension_class we're not copying the data into a new internal struct, we're directly referring to the struct provided by the GDExtension. We should probably not do that - it'd probably be better to copy that data into an instance of the struct on the Godot side...

Copy link
Contributor

@maiself maiself Aug 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying the data might be better in general. This is per instance tho, so either we duplicate the memory for each instance, or somehow create a mapping...

Another solution for this specific case is to add another class with a virtual override Godot side:

  • ScriptInstance
  • ScriptInstanceExtensionDeprecated (add this)
  • ScriptInstanceExtension

Then have gdextension_script_instance_create[2] create the correct class. (edit: might require reinterpret_cast on the native_info member to make this work...)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a proposed fix that copies the data: #81205

This is per instance tho, so either we duplicate the memory for each instance, or somehow create a mapping...

Hm, yeah, I suppose this does make each instance take up 23 pointers more memory... This is a trickier problem than I thought at first!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that. Looks like I don't have a good intuition for these kind of problems.

Copy link
Contributor

@dsnopek dsnopek Aug 31, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another solution for this specific case is to add another class with a virtual override Godot side

Yeah, I worry about the scalability of this approach: what happens as we make more changes to this struct? (We already have a change queued up for #81119)

I'd like to avoid the compatibility code continuing to require maintenance and growing in complexity over time. Copying is at least simple and straight forward. But copying as done in my current PR is always a performance and memory hit, even on the new code path. What if the hit was only on the compatibility path, maybe that's an OK trade-off?

Directly relates this comment on the PR: #81205 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about that. Looks like I don't have a good intuition for these kind of problems.

No worries - several other people (including me) read through your code without noticing it :-)

script_instance_extension->deprecated_native_info.notification_func = p_info->notification_func;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that if not (p_info->notification_func) {script_instance_extension->deprecated_native_info.notification_func = nullptr} is needed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think this is fine. If p_info->notification_func is nullptr, then script_instance_extension->deprecated_native_info.notification_func will get set to nullptr as well.

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);
script_instance_extension->instance = p_instance_data;
script_instance_extension->native_info = p_info;
Expand Down Expand Up @@ -1269,7 +1305,10 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(object_get_instance_id);
REGISTER_INTERFACE_FUNC(ref_get_object);
REGISTER_INTERFACE_FUNC(ref_set_object);
#ifndef DISABLE_DEPRECATED
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_update);
REGISTER_INTERFACE_FUNC(object_get_script_instance);
Expand Down
99 changes: 95 additions & 4 deletions core/extension/gdextension_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ typedef const GDExtensionPropertyInfo *(*GDExtensionClassGetPropertyList)(GDExte
typedef void (*GDExtensionClassFreePropertyList)(GDExtensionClassInstancePtr p_instance, const GDExtensionPropertyInfo *p_list);
typedef GDExtensionBool (*GDExtensionClassPropertyCanRevert)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name);
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 (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
Expand All @@ -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.
GDExtensionClassGetRID get_rid_func;
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;

Expand Down Expand Up @@ -366,7 +387,8 @@ typedef void (*GDExtensionScriptInstanceFreeMethodList)(GDExtensionScriptInstanc
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 (*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 (*GDExtensionScriptInstanceRefCountIncremented)(GDExtensionScriptInstanceDataPtr p_instance);
Expand Down Expand Up @@ -420,7 +442,46 @@ typedef struct {

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 */

Expand Down Expand Up @@ -2116,6 +2177,7 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
/**
* @name script_instance_create
* @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.
*
Expand All @@ -2126,6 +2188,19 @@ typedef void (*GDExtensionInterfaceRefSetObject)(GDExtensionRefPtr p_ref, GDExte
*/
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
* @since 4.2
Expand Down Expand Up @@ -2217,6 +2292,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
/**
* @name classdb_register_extension_class
* @since 4.1
* @deprecated in Godot 4.2. Use `classdb_register_extension_class2` instead.
*
* Registers an extension class in the ClassDB.
*
Expand All @@ -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);

/**
* @name classdb_register_extension_class2
dsnopek marked this conversation as resolved.
Show resolved Hide resolved
* @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
* @since 4.1
Expand Down
26 changes: 21 additions & 5 deletions core/object/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
_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);
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions core/object/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,10 @@ struct ObjectGDExtension {
GDExtensionClassFreePropertyList free_property_list;
GDExtensionClassPropertyCanRevert property_can_revert;
GDExtensionClassPropertyGetRevert property_get_revert;
#ifndef DISABLE_DEPRECATED
GDExtensionClassNotification notification;
#endif // DISABLE_DEPRECATED
GDExtensionClassNotification2 notification2;
GDExtensionClassToString to_string;
GDExtensionClassReference reference;
GDExtensionClassReference unreference;
Expand Down
4 changes: 2 additions & 2 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class ScriptInstance {
}

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) {
if (r_valid) {
*r_valid = false;
Expand Down Expand Up @@ -476,7 +476,7 @@ class PlaceHolderScriptInstance : public ScriptInstance {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
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; }

Expand Down
Loading