#How to Bind Arguments to Built-In Signals

13 messages · Page 1 of 1 (latest)

covert zephyr
#

I'm trying to populate a list of selectable classes for the player. Each is represented by data in a Resource. So far so good for displaying things.

But if I make the displays have a button, and want to "send" the displayed class via the pressed signal, I run into trouble. I found a handy template for how the syntax should work on StackExchange that goes like this:
object.signal_name.connect(method_name.bind([extra, arguments]))

But the ClassSelectMenu, who is populating the ClassDisplay buttons and assigning them a resource, does not HAVE the extra arguments. They will be coming from the ClassDisplay - so I run into an error. It seems to bind anything, I have to use a member of the script that's doing the binding, which isn't what I want. I want to tell the method connecting to pressed to expect an extra argument.

I'd appreciate if anyone can help me understand this.
Thank you for reading!

#

For more context, the class select buttons are setup like this:

    for class_res in class_resources:
        var new_display = class_select_display_scene.instantiate() as Button
        
        new_display.setup(class_res)
        new_display.pressed.connect(_on_class_display_pressed.bind(MEMBER_OF_NEW_DISPLAY))
        classes_container.add_child(new_display)

... and it triggers this ...

func _on_class_display_pressed(_displayed_class: ClassResource) -> void:
    print("class_display_pressed is receiving %s" % [_displayed_class.name])

I get the error that MEMBER_OF_NEW_DISPLAY (renamed it that for this post) isn't declared. But I just want to await for "some value" from the button's pressed signal. Without coupling them super awkwardly I don't know how.

#

(wow swifty didn't like my indentation. Sorry for the jumble!)

obtuse igloo
#

Do you have your classes as tres files? Like warrior.tres, etc? If so you can preload them all and do something like

var warrior_class = preload(res://warrior.tres)

func _ready():
    btn_warrior.pressed.connect(on_btn_warrior_pressed.bind(warrior_class))
covert zephyr
#

Not preloaded, but the class_res that I'm iterating over here is a compiled array of those resources. So I could say...

new_display.pressed.connect(_on_class_display_pressed.bind(class_res))

... what I'm not clear on is WHAT I'm doing when I bind, in that case. Is that then saying that, when this display button's pressed signal is emitted, it comes with the ClassSelectMenu's "address" of that resource (since that's what is passed into the bind function's arguments)?

obtuse igloo
#

I'll make it easier, let's say you have a function like

func function(number : int):
    print(number)

Now if you connect such a signal like the pressed signal, you notice it doesnt has an argument, it's like saying pressed.emit() with no arguments. So in order to not generate an error by calling the function without args, you connect the signal to the function like for example

btn.pressed.connect(function.bind(1))

So now every time btn is pressed, it triggers function(1). Now try to apply that to your case and see if you can make sense of it

covert zephyr
#

I see!
I was thinking bind would mean "prepare the pressed signal and the thing that's responding to it to accept a new signature" and that the button, itself, would have to supply the resource reference. That helps a lot, thank you!

elfin rivet
# obtuse igloo I'll make it easier, let's say you have a function like ``` func function(number...

I know this is not my question post, but this looks rather nice as an alternative to what I've been doing, which is just adding a simple script to my buttons that I connect their signal to, then relay that signal with a new one that includes the parameter I need to pass to whatever function is ultimately listening. To that end, I would like to ask: If using .bind() like this, can I bind using a variable reference and when emitting the signal, will that reflect any changes to the variable's value that have happened since the time of binding? I'm assuming this is a yes, but I'm not sure.

obtuse igloo
elfin rivet
#

And it's already come in handy. I have a static script with a connection function that checks to see if there's already a connection and connects if not, and I changed it to take an array of binds with a default of [] (so it wont break my existing code). Makes it a hell of a lot easier to set up my area triggers in code properly.

#

It's unnecessary, but I like that it helps my other scripts be just a little cleaner. I'm weird like that. 😛

#

It's literally just this:

class_name Connect


static func connect_if_not_connected(from : Signal, to : Callable, binds : Array = []):
    if not from.is_connected(to):
        from.connect(to.bind(binds))

And it's used like this Connect.connect_if_not_connected(signal_name, callable_name, [bind0, bind1, etc])
So, it's just a wrapper that probably is superfluous, since connecting something that's already connected just gives a warning (nothing serious). I'd just rather have the engine yell at me less so that when it yells I can take it seriously.