-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Fixes to allow object-less callables throughout Godot #82695
Fixes to allow object-less callables throughout Godot #82695
Conversation
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.
Thanks!
I went through each change, and tried to think through what it was doing before, and check if the new code is roughly equivalent. For the most part this is looking good to me! I haven't had a chance to do any testing.
69ca2c8
to
4165c1f
Compare
Updated as discussed and rebased on master. |
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 looking good to me personally!
It doesn't fully fix all cases in the code base, but it does fix many of the most common ones, and it does so in a fairly safe and conservative way. When development on Godot 4.3 opens, we can look at the remaining tricky cases in order to fix this comprehensively, hopefully, standardizing on Callable::is_valid()
everywhere.
But this PR would be nice to get in Godot 4.2 for GDExtension, since we added the ability to create custom callables from GDExtension in PR #79005, and fixing this issue even somewhat opens up what GDExtensions are able to do.
I need a sanity recap about this. Let me rubberduck the situation: We have the possibility of a Assuming the above is correct, are we sure these changes are fine for both cases? I'd say so, since after all the original issue was about the C++ side (wasn't it?) and GDScript static callables would pass the target-must-be-non-null-and-not-dangling check either if done at each call site (before this PR) or implicitly inside the default Is all this disquisition true? |
Yesterday, I re-tested the |
I just tested connecting to a signal with a |
Thanks for testing it, @dsnopek. (And greetings!) My only pending thing is #82695 (comment). Otherwise (even if without applying it), this has my blessings. |
4165c1f
to
e47802a
Compare
@@ -78,13 +78,6 @@ void GodotArea2D::set_space(GodotSpace2D *p_space) { | |||
} | |||
|
|||
void GodotArea2D::set_monitor_callback(const Callable &p_callback) { | |||
ObjectID id = p_callback.get_object_id(); | |||
|
|||
if (id == monitor_callback.get_object_id()) { |
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 looks like some optimization and should work without an object too (though the condition probably needs changing). Why was this removed?
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.
For object-less callables this will always fall into the optimized path because get_object_id()
will always return ObjectID(0)
, so for those callables its no good, and why I removed it. Im not sure what this condition could be changed to.
I tried to see what this optimization and the code that follows was about, but I'm not so familiar with the physics servers inner workings. This code goes all they way back to the original opensource commit, so no explanation there. When I tried to follow all the paths that could lead here it seemed that the optimized path doesn't ever get used in the current code, tho I didn't test it.
In short, I don't know why that code is there in the first place, how to properly change it to support object-less callables (tho maybe just adding p_callback.is_standard() &&
to the condition would be enough?), and it doesn't appear that removing it would harm anything.
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.
Maybe something like id.is_valid() && id == monitor_callback.get_object_id()
?
This code allows to swap callbacks without clearing shapes if the object is the same. So the condition I suggested would make it skipped if the new callback has no object.
That said, I'm also not very familiar with physics code either. This "optimization" doesn't look very important; normally the callbacks are changed only when toggling area's monitoring
property, which is rather uncommon thing to do.
e47802a
to
5e15586
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.
I only tested Tweens, but the code seems fine.
Thanks! |
This fixes #81887
I searched the entire Godot source code for
Callable
methodsget_object()
,get_object_id()
andget_method()
, which could potentially be used to detect if a callable is associated with an object. Several places in the code used these methods to check callable validity instead of usingCallable::is_valid()
, causing object-less callables to be rejected. I then carefully and selectively updated the code to use the correct methods.A few places remain where object-less callables may not be handled correctly. These files use
get_object()
andget_method()
for various purposes:scene/main/node.cpp
: serializationeditor/editor_node.cpp
: serializationscene/resources/packed_scene.cpp
: serializationcore/core_bind.cpp
: error messagescore/variant/callable.cpp
: custom callableget_method()
core/variant/variant.cpp
: error messagesWhile I was quite thorough, its possible I may have missed things. I also left gdscript and mono alone.