From e257c76dc6ecc65a93a771b58afa5fa902620c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lera=20Elvo=C3=A9?= Date: Sun, 28 Jul 2024 09:30:53 +0000 Subject: [PATCH] add array operation nodes (#171) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix variable viewer deselecting error - add array push/append - set spinbox value AFTER setting the range in descriptor renderer - add array pop node - add array size node - add array set at index node - add array insert node - prevent potential race condition in array pop Reviewed-on: https://codeberg.org/StreamGraph/StreamGraph/pulls/171 Co-authored-by: Lera ElvoƩ Co-committed-by: Lera ElvoƩ --- classes/deck/nodes/general/array_insert.gd | 80 +++++++++++++++++++ classes/deck/nodes/general/array_pop.gd | 75 +++++++++++++++++ classes/deck/nodes/general/array_push.gd | 65 +++++++++++++++ classes/deck/nodes/general/array_set.gd | 80 +++++++++++++++++++ classes/deck/nodes/general/array_size.gd | 32 ++++++++ .../descriptors/spin_box_descriptor.gd | 7 +- graph_node_renderer/variable_viewer.gd | 4 +- 7 files changed, 339 insertions(+), 4 deletions(-) create mode 100644 classes/deck/nodes/general/array_insert.gd create mode 100644 classes/deck/nodes/general/array_pop.gd create mode 100644 classes/deck/nodes/general/array_push.gd create mode 100644 classes/deck/nodes/general/array_set.gd create mode 100644 classes/deck/nodes/general/array_size.gd diff --git a/classes/deck/nodes/general/array_insert.gd b/classes/deck/nodes/general/array_insert.gd new file mode 100644 index 0000000..365bd17 --- /dev/null +++ b/classes/deck/nodes/general/array_insert.gd @@ -0,0 +1,80 @@ +# (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 + +enum InputPorts { + ARRAY, + INDEX, + VALUE, + INSERT, +} + + +func _init() -> void: + name = "Array Insert At" + node_type = "array_insert" + description = "Insert a value into an array." + + add_input_port( + DeckType.Types.ARRAY, + "Array", + "", + ) + + add_input_port( + DeckType.Types.NUMERIC, + "Index", + "spinbox:unbounded", + ) + + add_input_port( + DeckType.Types.ANY, + "Value", + "", + ) + + add_input_port( + DeckType.Types.ANY, + "Insert", + "button", + Port.UsageType.TRIGGER, + ).button_pressed.connect(_receive.bind(InputPorts.INSERT, null)) + + add_output_port( + DeckType.Types.ARRAY, + "Array", + "", + Port.UsageType.TRIGGER, + ) + + +func _receive(to_input_port: int, data: Variant) -> void: + var array: Array + var value: Variant + var index: int + + match to_input_port: + InputPorts.ARRAY: + array = data + index = int(await resolve_input_port_value_async(InputPorts.INDEX)) + value = await resolve_input_port_value_async(InputPorts.VALUE) + InputPorts.INDEX: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + index = int(DeckType.convert_value(data, DeckType.Types.NUMERIC)) + value = await resolve_input_port_value_async(InputPorts.VALUE) + InputPorts.VALUE: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + index = int(await resolve_input_port_value_async(InputPorts.INDEX)) + value = data + InputPorts.INSERT: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + index = int(await resolve_input_port_value_async(InputPorts.INDEX)) + value = await resolve_input_port_value_async(InputPorts.VALUE) + + var err := array.insert(index, value) + if err != OK: + DeckHolder.logger.log_node("Array insert: Couldn't insert: %s." % error_string(err), Logger.LogType.ERROR) + return + + send(0, array) diff --git a/classes/deck/nodes/general/array_pop.gd b/classes/deck/nodes/general/array_pop.gd new file mode 100644 index 0000000..9b2f76d --- /dev/null +++ b/classes/deck/nodes/general/array_pop.gd @@ -0,0 +1,75 @@ +# (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 + +enum InputPorts { + ARRAY, + INDEX, + POP, +} + + +func _init() -> void: + name = "Array Pop Element" + node_type = "array_pop" + description = "Removes an element from an array and returns it. A negative index will remove from the end." + + aliases = ["remove", "erase"] + + add_input_port( + DeckType.Types.ARRAY, + "Array", + ) + + add_input_port( + DeckType.Types.NUMERIC, + "Element index", + "spinbox:unbounded:1", + ).set_value(-1) + + add_input_port( + DeckType.Types.ANY, + "Pop", + "button", + Port.UsageType.TRIGGER, + ).button_pressed.connect(_receive.bind(InputPorts.POP, null)) + + add_output_port( + DeckType.Types.ARRAY, + "Array", + "", + Port.UsageType.TRIGGER, + ) + + add_output_port( + DeckType.Types.ANY, + "Removed element", + "", + Port.UsageType.TRIGGER, + ) + + +func _pop(array: Array, index: int) -> Variant: + return array.pop_at(index) + + +func _receive(to_input_port: int, data: Variant) -> void: + var array: Array + var index: int + + match to_input_port: + InputPorts.ARRAY: + array = data + index = await resolve_input_port_value_async(InputPorts.INDEX) + InputPorts.INDEX: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + index = data + InputPorts.POP: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + index = await resolve_input_port_value_async(InputPorts.INDEX) + + var send_id := UUID.v4() + var value = _pop(array, index) + send(0, array, send_id) + send(1, value, send_id) diff --git a/classes/deck/nodes/general/array_push.gd b/classes/deck/nodes/general/array_push.gd new file mode 100644 index 0000000..af36354 --- /dev/null +++ b/classes/deck/nodes/general/array_push.gd @@ -0,0 +1,65 @@ +# (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 + +enum InputPorts { + ARRAY, + VALUE, + APPEND, +} + + +func _init() -> void: + name = "Array Append Element" + node_type = "array_push" + description = "Inserts an element at the end of an array." + aliases = ["push"] + + add_input_port( + DeckType.Types.ARRAY, + "Array", + ) + + add_input_port( + DeckType.Types.ANY, + "Value", + "field", + ) + + add_input_port( + DeckType.Types.ANY, + "Append", + "button", + Port.UsageType.TRIGGER, + ).button_pressed.connect(_receive.bind(InputPorts.APPEND, null)) + + add_output_port( + DeckType.Types.ARRAY, + "Array", + "", + Port.UsageType.TRIGGER, + ) + + +func _do(array: Array, element: Variant) -> Array: + array.append(element) + return array + + +func _receive(to_input_port: int, data: Variant) -> void: + var array: Array + var element: Variant + + match to_input_port: + InputPorts.ARRAY: + array = data + element = await resolve_input_port_value_async(InputPorts.VALUE) + InputPorts.VALUE: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + element = data + InputPorts.APPEND: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + element = await resolve_input_port_value_async(InputPorts.VALUE) + + send(0, _do(array, element)) diff --git a/classes/deck/nodes/general/array_set.gd b/classes/deck/nodes/general/array_set.gd new file mode 100644 index 0000000..9ff031b --- /dev/null +++ b/classes/deck/nodes/general/array_set.gd @@ -0,0 +1,80 @@ +# (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 + +enum InputPorts { + ARRAY, + INDEX, + VALUE, + SET, +} + + +func _init() -> void: + name = "Array Set At" + node_type = "array_set" + description = "Sets the value at an index in an array." + + add_input_port( + DeckType.Types.ARRAY, + "Array", + "", + ) + + add_input_port( + DeckType.Types.NUMERIC, + "Index", + "spinbox:unbounded", + ) + + add_input_port( + DeckType.Types.ANY, + "Value", + "", + ) + + add_input_port( + DeckType.Types.ANY, + "Set", + "button", + Port.UsageType.TRIGGER, + ).button_pressed.connect(_receive.bind(InputPorts.SET, null)) + + add_output_port( + DeckType.Types.ARRAY, + "Array", + "", + Port.UsageType.TRIGGER, + ) + + +func _receive(to_input_port: int, data: Variant) -> void: + var array: Array + var value: Variant + var index: int + + match to_input_port: + InputPorts.ARRAY: + array = data + index = int(await resolve_input_port_value_async(InputPorts.INDEX)) + value = await resolve_input_port_value_async(InputPorts.VALUE) + InputPorts.INDEX: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + index = int(DeckType.convert_value(data, DeckType.Types.NUMERIC)) + value = await resolve_input_port_value_async(InputPorts.VALUE) + InputPorts.VALUE: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + index = int(await resolve_input_port_value_async(InputPorts.INDEX)) + value = data + InputPorts.SET: + array = await resolve_input_port_value_async(InputPorts.ARRAY) + index = int(await resolve_input_port_value_async(InputPorts.INDEX)) + value = await resolve_input_port_value_async(InputPorts.VALUE) + + if index >= array.size(): + DeckHolder.logger.log_node("Array set: Index is too big.", Logger.LogType.ERROR) + return + + array[index] = value + send(0, array) diff --git a/classes/deck/nodes/general/array_size.gd b/classes/deck/nodes/general/array_size.gd new file mode 100644 index 0000000..b8cfd15 --- /dev/null +++ b/classes/deck/nodes/general/array_size.gd @@ -0,0 +1,32 @@ +# (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 + + +func _init() -> void: + name = "Array Size" + node_type = "array_size" + description = "Returns the size of an array." + + aliases = ["length"] + + add_input_port( + DeckType.Types.ARRAY, + "Array", + ) + + add_output_port( + DeckType.Types.NUMERIC, + "Size", + ) + + +func _value_request(_on_output_port: int) -> Variant: + var array: Array = await resolve_input_port_value_async(0) + return array.size() + + +func _receive(_to_input_port: int, data: Variant) -> void: + var array: Array = DeckType.convert_value(data, DeckType.Types.ARRAY) + send(0, array.size()) diff --git a/graph_node_renderer/descriptors/spin_box_descriptor.gd b/graph_node_renderer/descriptors/spin_box_descriptor.gd index 6711ba2..4934763 100644 --- a/graph_node_renderer/descriptors/spin_box_descriptor.gd +++ b/graph_node_renderer/descriptors/spin_box_descriptor.gd @@ -8,10 +8,8 @@ extends DescriptorContainer func _setup(port: Port, node: DeckNode) -> void: spin_box.tooltip_text = port.label - if port.value != null: - spin_box.value = float(port.value) + if "unbounded" in descriptor: - spin_box.max_value = 99999 spin_box.allow_greater = true spin_box.allow_lesser = true if descriptor.size() > 2: @@ -24,6 +22,9 @@ func _setup(port: Port, node: DeckNode) -> void: spin_box.max_value = float(descriptor[2]) if descriptor.size() > 3: spin_box.step = float(descriptor[3]) + + if port.value != null: + spin_box.value = float(port.value) port.value_callback = spin_box.get_value spin_box.value_changed.connect(port.set_value) spin_box.editable = not node._belonging_to.is_library diff --git a/graph_node_renderer/variable_viewer.gd b/graph_node_renderer/variable_viewer.gd index c46d7c4..e8998c4 100644 --- a/graph_node_renderer/variable_viewer.gd +++ b/graph_node_renderer/variable_viewer.gd @@ -39,7 +39,9 @@ func _ready() -> void: if item != null: commit_item_change(item) - item.deselect(variable_tree.get_selected_column()) + #item.deselect(variable_tree.get_selected_column()) + for i in variable_tree.get_columns(): + item.deselect(i) ) variable_tree.button_clicked.connect(_on_variable_tree_button_clicked)