-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
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
Fix Object::notification
order
#78634
Conversation
295b50a
to
8e37f9d
Compare
IMO we should consider writing tests for this as well (either in this PR or in a follow up). |
This PR is failing the CI checks, those need to be resolved. |
8e37f9d
to
b10b64c
Compare
baa2fe1
to
ec6375a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GDExtension compatibility changes are definitely headed in the right direction! I have just a couple of notes
ec6375a
to
e7a6bae
Compare
@dsnopek Thank you for the detailed review. I believe, that I have addressed all your comments. From other deprecation-uses, I'm aware of #ifdef DISABLE_DEPRECATED
#endif // DISABLE_DEPRECATED Should they be used here as well? |
Thanks, the changes look great!
Hm. I'm not exactly sure how we'd use that in this context.
But maybe we could exclude the implementation of the old function in |
Thanks for the explanation, which lets me think, that |
1fbed41
to
eed2c82
Compare
2754298
to
5c06755
Compare
5c06755
to
7c70ffc
Compare
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 <[email protected]>
7c70ffc
to
c4705a5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
Thanks! |
|
||
ScriptInstanceExtension *script_instance_extension = memnew(ScriptInstanceExtension); | ||
script_instance_extension->instance = p_instance_data; | ||
script_instance_extension->native_info = &info_2; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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...)
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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 :-)
const GDExtensionScriptInstanceInfo *native_info; | ||
const GDExtensionScriptInstanceInfo2 *native_info; | ||
struct { | ||
GDExtensionClassNotification notification_func; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not GDExtensionScriptInstanceNotification?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack, yes, you're right, this should be GDExtensionScriptInstanceNotification
. Luckly, the C types of the arguments are equivalent, so I don't think this breaks anything, but it should be fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this just a straightforward rename from GDExtensionScriptInstanceInfo2
to GDExtensionScriptInstanceNotification
? In that case I can create a PR. Not sure about other implications.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it should just be changing the type from GDExtensionClassNotification
to GDExtensionScriptInstanceNotification
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
@Gallilus I think we'll need more information about your crash to provide any helpful advice. Can you give the full stack trace? Can you share the code that's building the |
It tries to access a notification function when a .lr script gets attached. Only I have not defined a function jet so it should skip it. Not? code here
|
How is In C++, memory isn't initialized to zero by default. So, if you aren't setting anything, |
Found the problem, I think. |
Object::notification()
doesn't fully respect itsp_reversed
parameter #52325Object::notification
order (cpp-bindings) godot-cpp#1151Previously 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 ap_reversed
parameter. This made it necessary to adjust mono and cpp bindings, since they use these functions.MRP for testing: ReverseNotification.zip (based on notes in #52325)
Updated 2023-08-29: Fix merge conflict with #80394