migueldeicaza / SwiftGodot

New Godot bindings for Swift
https://migueldeicaza.github.io/SwiftGodotDocs/tutorials/swiftgodot-tutorials/
MIT License
985 stars 55 forks source link

Callable.bind() and .bindv() does not work #491

Closed rktprof closed 1 month ago

rktprof commented 1 month ago

Describe the bug If you want to send a parameter back to GDscript via callback, you can use a Callable as a parameter, Callable has a function to bind parameters to it that doesn't work in SwiftGodot

In this example, onComplete should be called with the first parameter being 0 for success and 1 for error, but no parameters are added:

@Callable
func mySwiftFunction(onComplete:Callable) {
    Task {
        do {
            // Do async work
            onComplete.bind(Variant(0))
        } catch {
            onComplete.bind(Variant(1))
        }

        print("Bound arguments: \(onComplete.getBoundArgumentsCount())")
        onComplete.callDeferred()
    }
}

The same is true for bindv() which takes an array instead

To Reproduce

  1. Implement the above function and call it from GDScript
  2. It will print "Bound arguments: 0" and the callback will be called without parameters

Expected behavior the .bind() and .bindv() function should bind parameters to the callable

Additional context You can work around this by using Callable.callv(arguments:GArray) to call with arguments directly, but there is no way of doing this while using Callable.callDeferred()

It might not be possible to do this the same was it is done in GDScript, but in that case the bind() and bindv() functions should be removed as they do nothing, and having a callDeferredv(arguments:GArray) would be really helpful as it is a way of bringing a callback into the main thread

migueldeicaza commented 1 month ago

First, the good news.

Calling bind returns a new callable that has been bound - it does not change the existing callable, so what you want to do in this case is do:

let bound: Callable

do {
    bound = onCallable.bind(Variant(0))
} catch {
    bound = onCallable.bind(Variant(1))
}
bound.callDeferred()

The bad news for me, is that I think that I need to fix the generator, because the bind method is supposed to take a list of arguments, and I am not sure how you managed to get that to compile, as I had to resort to bindv,

migueldeicaza commented 1 month ago

And now, I have implemented the missing methods too, closing.