Skip to content

Instantly share code, notes, and snippets.

@bitbutter
Created July 8, 2024 08:25
Show Gist options
  • Save bitbutter/9de986ea0fc1f40ea023c7db9e68cf6a to your computer and use it in GitHub Desktop.
Save bitbutter/9de986ea0fc1f40ea023c7db9e68cf6a to your computer and use it in GitHub Desktop.
A godot 4 class. Waits for multiple signals to be received before continuing
class_name SignalWaiter
signal AllFinished
# Internal variables
var _active_nodes = {}
var _signal_connections = {}
var _callables = []
## External method to add a node, its callable, and the signal to listen for.
## node: The node to add.
## callable: A Callable to call when running.
## signal_name: The signal name to listen for from the node.
func add_item(node: Node, callable: Callable, signal_name: String):
_active_nodes[node] = true
_callables.append(callable)
_wait_for_signal(node, signal_name)
## External method to run all callables and await the AllFinished signal.
func run():
for callable in _callables:
if callable != null:
callable.call()
if _all_signals_already_emitted():
emit_signal("AllFinished")
else:
await AllFinished
## Internal method to set up signal listening on a node.
func _wait_for_signal(node: Node, signal_name: String):
if not node.has_signal(signal_name):
print("Error: Signal '", signal_name, "' not found in ", node)
return
var callback = Callable(self, "_on_node_signal_received").bind(node)
if not node.is_connected(signal_name,callback):
var err : Error = node.connect(signal_name, callback)
assert(err == OK, "problem connecting to "+signal_name+". callback:"+str(callback)+". node: "+node.name+". error: "+error_string(err))
else:
assert(false,node.name+" "+signal_name+" already connected to signalwaiter callback! (duplicate cells in array?)")
_signal_connections[node] = [signal_name, callback]
## Internal method called when a signal is received.
func _on_node_signal_received(node: Node):
_active_nodes[node] = false
if _all_signals_already_emitted():
emit_signal("AllFinished")
## Internal method to check if all signals have been emitted.
func _all_signals_already_emitted():
for waiting_for_this_node in _active_nodes.values():
if waiting_for_this_node:
return false
return true
# Example code
#
#var signal_waiter := SignalWaiter.new()
#
## the nodes all have a jump method, and emit a FinishedJumping signal
#for n in nodes:
#signal_waiter.add_item(n,Callable(n,"jump"),"FinishedJumping")
#
## calls the callable for each item
#signal_waiter.run()
#
## wait "FinishedExploding" emitted by every node
#await signal_waiter.AllFinished
#
## do the next thing
#%Label.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment