I think this goes against the idea of signals: Emit upwards in the hierarchy, and don't worry about whether it's listened for. I think there are ways around this if you know how many other nodes are listening for the signal.
But I'm implementing the following hack for this:
I have an internal signal called something like signal_handled
, and then my child node looks like this:
signal signal_name
signal _signal_handled
@export var number_of_signal_handlers: int = 3
func on_button() -> void:
signal_name.emit()
for i in number_of_signal_handlers:
await _signal_handled
# Whatever you want to happen after the signal handlers have finished.
And my listeners look like this:
onready var child_node
func _ready() -> void:
child_node.signal_name.connect(_handle_signal)
func _handle_signal() -> void:
# Do whatever you want here
child_node._signal_handled.emit()
It's obviously a fragile solution that's prone to issues, but in my specific case there's only one thing listening to the signal and calling the child node's internal signal.
I think this is kinda in keeping with the idea of coroutines, where control is passed back and forth in the form of 'cooperative concurrency'.