godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.14k stars 95 forks source link

Add a `Callable::bindv` method to GDScript 2.0 #6034

Closed apiary23 closed 1 year ago

apiary23 commented 1 year ago

Describe the project you are working on

General GDScript code; this should apply to any project that uses signals.

Describe the problem or limitation you are having in your project

Many projects I've worked on using GDScript used the now-obsolete Object method connect(signal_name, receiver, method_name, args_array). This relatively compact signal-connection method is now no longer possible since Callable.bind can only receive varargs and not an array.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The Callable class would have a new method called bindv that would allow creating a new Callable by binding an array of arguments instead of varargs.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

The C++ source for Callable has a method bindp takes an array of Variant pointers, which means this limitation wouldn't exist when using GDNative or an engine module. This proposal is basically just to expose this bindp method to GDScript, though it would make sense to call it bindv for parity with the distinction between the call and callv methods.

If this enhancement will not be used often, can it be worked around with a few lines of script?

After seeing this issue I realized there's an extremely simple pure GDScript way around this limitation:

static func bindv(c: Callable, args: Array[Variant]):
    var res := c
    for idx in range(args.size(), 0, -1):
        res = res.bind(args[idx-1])
    return res

Which could be used like some_signal.connect(bindv(some_callable, ["foo", "bar"])).

While this is a very simple and convenient workaround, it is naturally slower than native code due to being GDScript, must be referenced from an arbitrary static class, and adds a small amount of overhead because there are multiple nested Callable instances that will be invoked in sequence when the returned Callable is invoked.

If this proposal is rejected for technical or conventional reasons, it seems reasonable to at least document this workaround to accommodate projects that rely on the old connect method.

Is there a reason why this should be core and not an add-on in the asset library?

This would be a change to Godot's core and could not be implemented by an addon, excepting the workaround stated above.

TokisanGames commented 1 year ago

For bindable arrays, see https://github.com/godotengine/godot/issues/64668 And https://github.com/godotengine/godot/pull/71000