diff --git a/classes/deck/nodes/general/collect.gd b/classes/deck/nodes/general/collect.gd new file mode 100644 index 0000000..b85ab28 --- /dev/null +++ b/classes/deck/nodes/general/collect.gd @@ -0,0 +1,93 @@ +# (c) 2023-present Eroax +# (c) 2023-present Yagich +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +extends DeckNode + +var input_count: int: + get: + if input_count == 0: + return get_input_ports().size() + else: + return input_count + + +func _init() -> void: + name = "Collect into Array" + node_type = "collect" + description = "Provides infinite inputs and an output that is an array of all connected inputs." + props_to_serialize = [&"input_count"] + + add_output_port( + DeckType.Types.ARRAY, + "Array", + "", + Port.UsageType.VALUE_REQUEST, + ) + + add_input_port( + DeckType.Types.ANY, + "Element 1", + "", + Port.UsageType.VALUE_REQUEST, + ) + + incoming_connection_added.connect(_on_incoming_connection_added) + incoming_connection_removed.connect(_on_incoming_connection_removed) + + +func _on_incoming_connection_added(port_idx: int) -> void: + if port_idx + 1 < get_input_ports().size(): + return + + add_input_port( + DeckType.Types.ANY, + "Element %s" % (get_input_ports().size() + 1), + "", + Port.UsageType.VALUE_REQUEST, + ) + + +func _on_incoming_connection_removed(port_idx: int) -> void: + var last_connected_port := 0 + var incoming_connections := _belonging_to.connections.get_all_incoming_connections(_id) + if not incoming_connections.is_empty(): + last_connected_port = incoming_connections.keys().reduce(Util.array_max, -INF) + + #prints("l:", last_connected_port, "p:", port_idx) + + if port_idx < last_connected_port: + return + + if get_input_ports().size() <= 2: + return + + var lasts_connected_port_global = get_input_ports()[last_connected_port].index + var d = range(get_all_ports().size() - 1, lasts_connected_port_global + 1, -1) + for i in d: + ports.remove_at(i) + ports_updated.emit() + + +func _pre_port_load() -> void: + ports.remove_at(1) + for i in input_count: + add_input_port( + DeckType.Types.ANY, + "Element %s" % (i + 1), + "", + Port.UsageType.VALUE_REQUEST, + ) + input_count = 0 + + +func _value_request(_on_port: int) -> Variant: + var connections := _belonging_to.connections.get_all_incoming_connections(_id) + if connections.size() == 0: + return [] + + var arr := [] + arr.resize(connections.keys().reduce(Util.array_max, -INF) + 1) + for input_port in connections: + arr[input_port] = await resolve_input_port_value_async(input_port) + + return arr diff --git a/classes/util.gd b/classes/util.gd index b40f353..6c1d0c8 100644 --- a/classes/util.gd +++ b/classes/util.gd @@ -46,6 +46,11 @@ static func globalize_path(path: String) -> String: return path.format({"$PWD": pwd}) +## Use as the callback in [method Array.reduce] to find the greatest element. +static func array_max(accum, e): + return max(accum, e) + + ## An object representing multiple connections. ## ## Useful when there's a need to connect multiple signals in one operation, to be disconnected later.