Created
July 8, 2024 08:25
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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