-
-
Notifications
You must be signed in to change notification settings - Fork 21.7k
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
Allow method binds to take Object subclasses as arguments #57205
Allow method binds to take Object subclasses as arguments #57205
Conversation
This commit adds a condition to VariantCaster that casts Variants of type OBJECT to any type T, if T is derived from Object. This change enables a fair bit of code cleanup. First, the Variant implicit cast operators for Node and Control can be removed, which allows for some invalid includes to be removed. Second, helper methods in Tree whose sole purpose was to cast arguments to TreeItem * are no longer necessary. A few small changes also had to be made to other files, due to the changes cascading down all the includes.
424c782
to
051ef47
Compare
That's pretty cool! There might be quite a few other occurrences of bindings where return types or arguments have been limited to |
@akien-mga; Just to be clear, you recommend that OP do not change any more bindings in this PR? |
Does this mean that we can bind |
My take on this was #42060, @reduz was not happy with implementation because that would require using So yeah... I confirm this would be useful, even from the user perspective (I'd also remove specific casts from the Goost module in two places (https://github.com/goostengine/goost):
Therefore, this PR supersedes #42060 as well. |
EDIT: Never mind, there's no way to get the name of an |
Would still be good if @neikeq gives it a review |
Why were they needed? Is it because of DEFVALs? |
Because you could not bind methods with |
Yeah, see https://github.com/godotengine/godot/pull/57205/files#diff-73e583f1bfffebc5e30a925726bf40f32d72daaea940bf229e71479e98f8d1f7R339 - prior to this PR the only types that could be used in bindings were |
Ah, I see. I never realized we were using only those 3 object types in method signatures. |
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 great to me! I'm looking forward to improving the existing bindings with this more flexible system.
So I had a look at occurrences for Normal method bindingsSome cases that could be improved easily with the new feature:
Virtual methodsVirtual methods are bound with
(This could return PropertyInfoI found a few under-specified object types for some signals declared like this:
This can be worked around via a stringly typed hint in
(Even though it's not a Resource type but a Node here.) This is used throughout the engine for signals and properties to specific their actual type in the bindings. Edit: This seems only needed for signals, for properties the type is inferred from the setter/getter. |
This would be nice to implement in 3.x, if that doesn't break compatibility (I need this for custom modules and implementing custom data structures, such as graph: goostengine/goost#172). |
I'm not sure if this can be implemented in 3.x, since |
@Xrayez I tried briefly to make this work on 3.x with a constexpr bool, but the compiler unfortunately didn't cooperate. I don't have any major projects with Godot ongoing, so I'd prefer to focus on 4.0 as much as possible. I would be glad to continue to try and get this working on 3.x if you want me to, but it may be most efficient for goost to use your |
No worries, since it's possible to workaround, it's not a big deal. Sometimes I do forget to cast custom objects, though (just like |
using TStripped = std::remove_pointer_t<T>; | ||
if constexpr (std::is_base_of<Object, TStripped>::value) { | ||
Object *obj = p_variant; | ||
return Object::cast_to<TStripped>(p_variant) || !obj; |
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.
Isn't this supposed to be !obj || Object::cast_to<TStripped>(p_variant)
? Getting EA_BAD_ACCESS errors at this line
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.
Yes, it is. Object::cast_to<T>()
takes in an Object *, so both values will be the result of p_variant->operator Object*()
and will be the same. So, if obj
is a nullptr, we shouldn't attempt the cast.
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.
Related #84858
Would your change fix the same issue? Maybe it's better solution.
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, it doesn't. This should be changed either way because it's semantically incorrect, but it doesn't fix the issues I was having in #86602
Using some new C++ features, this PR adds a condition to
VariantCaster
that castsVariant
s of typeOBJECT
to any typeT
, ifT
is derived fromObject
.This change enables a fair bit of code cleanup. First, the
Variant
implicit cast operators forNode
andControl
can be removed, which allows for some of the invalid includes mentioned in #53295 to be removed. Second, helper methods in Tree, whose sole purpose was to cast arguments toTreeItem *
, are no longer necessary.A few small changes also had to be made to other files, due to the changes cascading down all the includes.
Fixes #21160, closes #20538, supersedes #57169