Fix Object::notification order
Previously the `p_reversed` parameter didn't influence the order in a correct way. Also script overridden _notification functions were not called in the correct order. To fix this some `notification` functions had to add a `p_reversed` parameter. This made it necessary to adjust cpp-bindings. Co-authored-by: David Snopek <dsnopek@gmail.com>
This commit is contained in:
parent
247c3548d8
commit
c4705a590b
|
@ -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) {
|
||||
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);
|
||||
|
||||
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.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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
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);
|
||||
script_instance_extension->instance = p_instance_data;
|
||||
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(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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
* @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
|
||||
|
|
|
@ -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 (script_instance) {
|
||||
script_instance->notification(p_notification);
|
||||
if (p_reversed) {
|
||||
if (script_instance) {
|
||||
script_instance->notification(p_notification, p_reversed);
|
||||
}
|
||||
} else {
|
||||
_notificationv(p_notification, p_reversed);
|
||||
}
|
||||
|
||||
if (_extension && _extension->notification) {
|
||||
_extension->notification(_extension_instance, 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 (p_reversed) {
|
||||
_notificationv(p_notification, p_reversed);
|
||||
} else {
|
||||
if (script_instance) {
|
||||
script_instance->notification(p_notification, p_reversed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 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;
|
||||
|
@ -476,7 +476,7 @@ public:
|
|||
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; }
|
||||
|
||||
|
|
|
@ -630,7 +630,11 @@ VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionLocation)
|
|||
|
||||
class ScriptInstanceExtension : public ScriptInstance {
|
||||
public:
|
||||
const GDExtensionScriptInstanceInfo *native_info;
|
||||
const GDExtensionScriptInstanceInfo2 *native_info;
|
||||
struct {
|
||||
GDExtensionClassNotification notification_func;
|
||||
} deprecated_native_info;
|
||||
|
||||
GDExtensionScriptInstanceDataPtr instance = nullptr;
|
||||
|
||||
// There should not be warnings on explicit casts.
|
||||
|
@ -746,11 +750,16 @@ public:
|
|||
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) {
|
||||
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 {
|
||||
if (native_info->to_string_func) {
|
||||
GDExtensionBool valid;
|
||||
|
|
|
@ -1921,14 +1921,23 @@ Variant GDScriptInstance::callp(const StringName &p_method, const Variant **p_ar
|
|||
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.
|
||||
Variant value = p_notification;
|
||||
const Variant *args[1] = { &value };
|
||||
|
||||
List<GDScript *> pl;
|
||||
GDScript *sptr = script.ptr();
|
||||
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) {
|
||||
Callable::CallError err;
|
||||
E->value->call(this, args, 1, err);
|
||||
|
@ -1936,7 +1945,6 @@ void GDScriptInstance::notification(int p_notification) {
|
|||
//print error about notification call
|
||||
}
|
||||
}
|
||||
sptr = sptr->_base;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -332,7 +332,7 @@ public:
|
|||
|
||||
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);
|
||||
|
||||
virtual Ref<Script> get_script() const;
|
||||
|
|
|
@ -1978,7 +1978,7 @@ const Variant CSharpInstance::get_rpc_config() const {
|
|||
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) {
|
||||
// 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
|
||||
|
@ -1996,7 +1996,7 @@ void CSharpInstance::notification(int p_notification) {
|
|||
return;
|
||||
}
|
||||
|
||||
_call_notification(p_notification);
|
||||
_call_notification(p_notification, p_reversed);
|
||||
|
||||
GDMonoCache::managed_callbacks.CSharpInstanceBridge_CallDispose(
|
||||
gchandle.get_intptr(), /* okIfNull */ false);
|
||||
|
@ -2004,10 +2004,10 @@ void CSharpInstance::notification(int p_notification) {
|
|||
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;
|
||||
const Variant *args[1] = { &arg };
|
||||
StringName method_name = SNAME("_notification");
|
||||
|
|
|
@ -283,8 +283,8 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
gr_nodes[i]->notification(p_notification);
|
||||
gr_nodes[i]->notification(p_notification, true);
|
||||
} else {
|
||||
MessageQueue::get_singleton()->push_notification(gr_nodes[i], p_notification);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
|
||||
return Variant();
|
||||
}
|
||||
void notification(int p_notification) override {
|
||||
void notification(int p_notification, bool p_reversed = false) override {
|
||||
}
|
||||
Ref<Script> get_script() const override {
|
||||
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
|
||||
|
||||
#endif // TEST_OBJECT_H
|
||||
|
|
Loading…
Reference in New Issue