From c07d810bcf8a395c44716e1d64037c0b3de63ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lera=20Elvo=C3=A9?= Date: Mon, 26 Feb 2024 05:34:00 +0000 Subject: [PATCH] be more lenient with using triggers and value requests on the same node on general and obs nodes (#78) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit addresses part of #59 Reviewed-on: https://codeberg.org/StreamGraph/StreamGraph/pulls/78 Co-authored-by: Lera ElvoƩ Co-committed-by: Lera ElvoƩ --- classes/deck/nodes/general/array_get_index.gd | 51 ++++++++-- classes/deck/nodes/general/bool_constant.gd | 3 +- .../deck/nodes/general/dictionary_get_key.gd | 20 ++++ classes/deck/nodes/general/expression_node.gd | 19 ++-- classes/deck/nodes/general/if_true.gd | 11 ++- classes/deck/nodes/general/is_equal.gd | 6 +- classes/deck/nodes/general/print.gd | 2 +- classes/deck/nodes/general/process_node.gd | 15 ++- classes/deck/nodes/general/set_deck_var.gd | 38 +++++--- classes/deck/nodes/general/string_constant.gd | 3 +- classes/deck/nodes/general/string_split.gd | 18 ++++ .../deck/nodes/obs/obs_decompose_transform.gd | 10 ++ classes/deck/nodes/obs/obs_scene_list.gd | 3 +- classes/deck/nodes/obs/obs_search_source.gd | 45 ++++++--- .../nodes/obs/obs_set_source_transform.gd | 93 ++++++++++++------- classes/deck/nodes/obs/obs_switch_scene.gd | 18 ++-- .../deck/nodes/obs/obs_vector_to_position.gd | 10 ++ classes/deck/nodes/test/test_type_sends.gd | 30 ++++++ 18 files changed, 296 insertions(+), 99 deletions(-) create mode 100644 classes/deck/nodes/test/test_type_sends.gd diff --git a/classes/deck/nodes/general/array_get_index.gd b/classes/deck/nodes/general/array_get_index.gd index 46c746d..6dc07d2 100644 --- a/classes/deck/nodes/general/array_get_index.gd +++ b/classes/deck/nodes/general/array_get_index.gd @@ -26,6 +26,17 @@ func _init() -> void: ) +func _arr_index(arr: Array, index: int) -> Variant: + if index < 0: + index = (arr as Array).size() + index + + if index >= (arr as Array).size(): + DeckHolder.logger.log_node("Array index: Index is too big. Returning null.", Logger.LogType.ERROR) + return null + + return arr[index] + + func _value_request(_on_port: int) -> Variant: var arr = await request_value_async(0) if arr == null: @@ -33,12 +44,36 @@ func _value_request(_on_port: int) -> Variant: return null var idx := int(await resolve_input_port_value_async(1)) - - if idx < 0: - idx = (arr as Array).size() + idx - if idx >= (arr as Array).size(): - DeckHolder.logger.log_node("Array index: Index > size. Returning null.", Logger.LogType.ERROR) - return null - - return arr[idx] + return _arr_index(arr, idx) + + +func _receive(on_input_port: int, data: Variant) -> void: + if on_input_port == 0: + if not data is Array: + DeckHolder.logger.log_node("Array Index: Received non-array on port 0.", Logger.LogType.ERROR) + return + + var idx := int(await resolve_input_port_value_async(1)) + + var res = _arr_index(data, idx) + if res == null: + return + + send(0, res) + + else: + if (not data is int) or (not data is float): + DeckHolder.logger.log_node("Array Index: Received non-number on port 1.", Logger.LogType.ERROR) + return + + var arr = await request_value_async(0) + if arr == null: + DeckHolder.logger.log_node("Array index: Input array is null. Returning null.", Logger.LogType.ERROR) + return + + var res = _arr_index(arr, int(data)) + if res == null: + return + + send(0, res) diff --git a/classes/deck/nodes/general/bool_constant.gd b/classes/deck/nodes/general/bool_constant.gd index 6a95033..099a6d3 100644 --- a/classes/deck/nodes/general/bool_constant.gd +++ b/classes/deck/nodes/general/bool_constant.gd @@ -12,7 +12,8 @@ func _init() -> void: add_output_port( DeckType.Types.BOOL, "Value", - "checkbox" + "checkbox", + Port.UsageType.VALUE_REQUEST, ) diff --git a/classes/deck/nodes/general/dictionary_get_key.gd b/classes/deck/nodes/general/dictionary_get_key.gd index 8d4ef23..831e8c1 100644 --- a/classes/deck/nodes/general/dictionary_get_key.gd +++ b/classes/deck/nodes/general/dictionary_get_key.gd @@ -36,3 +36,23 @@ func _value_request(_on_port: int) -> Variant: return null return d.get(key) + + +func _receive(on_input_port: int, data: Variant) -> void: + if on_input_port == 0: + if not data is Dictionary: + DeckHolder.logger.log_node("Get Dictionary Key: Received data that's not dictionary on port 0.", Logger.LogType.ERROR) + return + var key = await resolve_input_port_value_async(1) + if key == null: + return + + send(0, (data as Dictionary).get(key)) + + else: + var d = await request_value_async(0) + if d == null or (not d is Dictionary): + DeckHolder.logger.log_node("Get Dictionary Key: Received data that's not dictionary on port 0.", Logger.LogType.ERROR) + return + + send(0, d.get(data)) diff --git a/classes/deck/nodes/general/expression_node.gd b/classes/deck/nodes/general/expression_node.gd index 2c3f605..0ce78c8 100644 --- a/classes/deck/nodes/general/expression_node.gd +++ b/classes/deck/nodes/general/expression_node.gd @@ -17,19 +17,17 @@ func _init(): # when it's fixed, switch it back add_input_port( DeckType.Types.DICTIONARY, - "Expression Input" + "Expression Input", ) add_output_port( DeckType.Types.ANY, "Expression Text", - "codeblock" + "codeblock", ) - -func _value_request(_from_port : int) -> Variant: - +func parse(input: Dictionary) -> Variant: var text = get_output_ports()[0].value_callback.call() var err = expr.parse(text, ["deck_var", "input"]) @@ -39,13 +37,18 @@ func _value_request(_from_port : int) -> Variant: printerr(err) return null - - var res = expr.execute([_belonging_to.variable_stack, await request_value_async(0)]) + var res = expr.execute([_belonging_to.variable_stack, input]) if expr.has_execute_failed(): DeckHolder.logger.log_node("Expression Execution Failed: %s" % text, Logger.LogType.ERROR) return null - return res +func _value_request(_from_port : int) -> Variant: + var input = await request_value_async(0) + return parse(input) + + +func _receive(_on_input_port: int, data: Variant) -> void: + send(0, parse(data)) diff --git a/classes/deck/nodes/general/if_true.gd b/classes/deck/nodes/general/if_true.gd index 4bffcde..ca30524 100644 --- a/classes/deck/nodes/general/if_true.gd +++ b/classes/deck/nodes/general/if_true.gd @@ -12,16 +12,21 @@ func _init() -> void: add_input_port( DeckType.Types.BOOL, "Condition", - "checkbox" + "checkbox", + Port.UsageType.VALUE_REQUEST, ) add_input_port( DeckType.Types.ANY, - "Input" + "Input", + "", + Port.UsageType.TRIGGER, ) add_output_port( DeckType.Types.ANY, - "Output" + "Output", + "", + Port.UsageType.TRIGGER, ) diff --git a/classes/deck/nodes/general/is_equal.gd b/classes/deck/nodes/general/is_equal.gd index 8bb5a6d..64a053e 100644 --- a/classes/deck/nodes/general/is_equal.gd +++ b/classes/deck/nodes/general/is_equal.gd @@ -37,9 +37,7 @@ func _value_request(_on_port: int) -> Variant: func _receive(on_port: int, data: Variant) -> void: if on_port == 0: var b = await resolve_input_port_value_async(1) - if data == b: - send(0, true) + send(0, data == b) else: var b = await resolve_input_port_value_async(0) - if data == b: - send(0, true) + send(0, data == b) diff --git a/classes/deck/nodes/general/print.gd b/classes/deck/nodes/general/print.gd index 89b1de4..2a2630c 100644 --- a/classes/deck/nodes/general/print.gd +++ b/classes/deck/nodes/general/print.gd @@ -37,7 +37,7 @@ func _receive(to_input_port: int, data: Variant) -> void: return var data_to_print = str(await resolve_input_port_value_async(0)) - if data_to_print == null: + if data_to_print == null or (data_to_print as String).is_empty(): data_to_print = str(data) if (data_to_print as String).is_empty(): data_to_print = "" diff --git a/classes/deck/nodes/general/process_node.gd b/classes/deck/nodes/general/process_node.gd index c509312..f19dfdf 100644 --- a/classes/deck/nodes/general/process_node.gd +++ b/classes/deck/nodes/general/process_node.gd @@ -14,17 +14,22 @@ func _init() -> void: add_input_port( DeckType.Types.BOOL, "Enabled", - "checkbox" + "checkbox", + Port.UsageType.VALUE_REQUEST, ) add_output_port( DeckType.Types.BOOL, - "Trigger" + "Trigger", + "", + Port.UsageType.TRIGGER ) add_output_port( DeckType.Types.NUMERIC, - "Delta" + "Delta", + "", + Port.UsageType.TRIGGER ) @@ -38,7 +43,9 @@ func _event_received(event_name: StringName, event_data: Dictionary = {}) -> voi return delta = event_data.delta - send(0, true) + var id := UUID.v4() + send(0, true, id) + send(1, delta, id) func _value_request(on_output_port: int) -> Variant: diff --git a/classes/deck/nodes/general/set_deck_var.gd b/classes/deck/nodes/general/set_deck_var.gd index 52646a9..a01ac8f 100644 --- a/classes/deck/nodes/general/set_deck_var.gd +++ b/classes/deck/nodes/general/set_deck_var.gd @@ -24,24 +24,40 @@ func _init() -> void: add_input_port( DeckType.Types.BOOL, "Set", - "button" + "button", + Port.UsageType.TRIGGER, ) add_output_port( DeckType.Types.ANY, "Value", - "label" + "label", + Port.UsageType.TRIGGER, ) -func _receive(to_input_port: int, _data: Variant) -> void: - if to_input_port != 2: - return +func _receive(to_input_port: int, data: Variant) -> void: + match to_input_port: + 0: + if (not data is String) or (data as String).is_empty(): + DeckHolder.logger.log_node("Set Deck Var: received variable name that's not String or is empty.", Logger.LogType.ERROR) + return + var value: Variant = await resolve_input_port_value_async(1) + _belonging_to.set_variable(data, value) + send(0, value) + 1: + var var_name = await resolve_input_port_value_async(0) + if (not var_name is String) or (var_name as String).is_empty(): + DeckHolder.logger.log_node("Set Deck Var: variable name is null.") + return + _belonging_to.set_variable(var_name, data) + send(0, data) + 2: + var var_name = await resolve_input_port_value_async(0) + + var var_value: Variant = await resolve_input_port_value_async(1) - var var_name: String = await resolve_input_port_value_async(0) - var var_value: Variant = await resolve_input_port_value_async(1) + #_belonging_to.variable_stack[var_name] = var_value + _belonging_to.set_variable(var_name, var_value) - #_belonging_to.variable_stack[var_name] = var_value - _belonging_to.set_variable(var_name, var_value) - - send(0, var_value) + send(0, var_value) diff --git a/classes/deck/nodes/general/string_constant.gd b/classes/deck/nodes/general/string_constant.gd index 95c2121..5cf1f13 100644 --- a/classes/deck/nodes/general/string_constant.gd +++ b/classes/deck/nodes/general/string_constant.gd @@ -12,7 +12,8 @@ func _init() -> void: add_output_port( DeckType.Types.STRING, "Text", - "field" + "field", + Port.UsageType.VALUE_REQUEST, ) func _value_request(_from_port: int) -> Variant: diff --git a/classes/deck/nodes/general/string_split.gd b/classes/deck/nodes/general/string_split.gd index 9aa3e3c..b632270 100644 --- a/classes/deck/nodes/general/string_split.gd +++ b/classes/deck/nodes/general/string_split.gd @@ -36,3 +36,21 @@ func _value_request(_on_port: int) -> Variant: var string = await resolve_input_port_value_async(0) return Array(string.split(delimiter)) + + +func _receive(on_input_port: int, data: Variant) -> void: + if on_input_port == 0: + if not data is String: + DeckHolder.logger.log_node("Split: Received a value that's not String on port 0.", Logger.LogType.ERROR) + return + var delimiter = await resolve_input_port_value_async(1) + + send(0, Array(data.split(delimiter))) + else: + if not data is String: + DeckHolder.logger.log_node("Split: Received a value that's not String on port 1 (delimiter).", Logger.LogType.ERROR) + return + + var string = await resolve_input_port_value_async(0) + + send(0, Array(string.split(data))) diff --git a/classes/deck/nodes/obs/obs_decompose_transform.gd b/classes/deck/nodes/obs/obs_decompose_transform.gd index 9af1163..70c4260 100644 --- a/classes/deck/nodes/obs/obs_decompose_transform.gd +++ b/classes/deck/nodes/obs/obs_decompose_transform.gd @@ -43,3 +43,13 @@ func _value_request(on_port: int) -> Variant: return (t as Dictionary).get("position_y") _: return null + + +func _receive(_on_input_port: int, data: Variant) -> void: + if not data is Dictionary: + return + + var id := UUID.v4() + send(0, data.get("rotation"), id) + send(1, data.get("position_x"), id) + send(2, data.get("position_y"), id) diff --git a/classes/deck/nodes/obs/obs_scene_list.gd b/classes/deck/nodes/obs/obs_scene_list.gd index c6c09af..4493929 100644 --- a/classes/deck/nodes/obs/obs_scene_list.gd +++ b/classes/deck/nodes/obs/obs_scene_list.gd @@ -16,7 +16,8 @@ func _init() -> void: add_output_port( DeckType.Types.STRING, "Select a scene", - "singlechoice" + "singlechoice", + Port.UsageType.VALUE_REQUEST, ) add_virtual_port( diff --git a/classes/deck/nodes/obs/obs_search_source.gd b/classes/deck/nodes/obs/obs_search_source.gd index 4e67508..2925c3a 100644 --- a/classes/deck/nodes/obs/obs_search_source.gd +++ b/classes/deck/nodes/obs/obs_search_source.gd @@ -33,21 +33,10 @@ func _init() -> void: ) -func _value_request(_on_output_port: int) -> Variant: +func _get_source_id(scene_name: String, source_name: String) -> Variant: if noobs == null: noobs = Connections.obs_websocket - var scene_name_req = await resolve_input_port_value_async(0, "") - if scene_name_req == null: - return null - - var source_name_req = await resolve_input_port_value_async(1, "") - if source_name_req == null: - return null - - var scene_name: String = scene_name_req - var source_name: String = source_name_req - if cached_scene_name == scene_name and cached_source_name == scene_name: return cached_id @@ -70,3 +59,35 @@ func _value_request(_on_output_port: int) -> Variant: return data.response_data.scene_item_id + +func _value_request(_on_output_port: int) -> Variant: + var scene_name_req = await resolve_input_port_value_async(0, "") + if scene_name_req == null: + return null + + var source_name_req = await resolve_input_port_value_async(1, "") + if source_name_req == null: + return null + + return await _get_source_id(scene_name_req, source_name_req) + + +func _receive(on_input_port: int, data: Variant) -> void: + if on_input_port == 0: + if not data is String: + return + + var source_name_req = await resolve_input_port_value_async(1, "") + if source_name_req == null: + return + + send(0, await _get_source_id(data, source_name_req)) + else: + if not data is String: + return + + var scene_name_req = await resolve_input_port_value_async(0, "") + if scene_name_req == null: + return + + send(0, await _get_source_id(scene_name_req, data)) diff --git a/classes/deck/nodes/obs/obs_set_source_transform.gd b/classes/deck/nodes/obs/obs_set_source_transform.gd index e2c1aff..8e963dc 100644 --- a/classes/deck/nodes/obs/obs_set_source_transform.gd +++ b/classes/deck/nodes/obs/obs_set_source_transform.gd @@ -42,55 +42,78 @@ func _init() -> void: add_input_port( DeckType.Types.BOOL, "Set", - "button" + "button", + Port.UsageType.TRIGGER ) -func _receive(to_input_port: int, _data: Variant) -> void: +func _receive(to_input_port: int, data: Variant) -> void: #{ "scene_item_transform": { "alignment": 5, "bounds_alignment": 0, "bounds_height": 0, "bounds_type": "OBS_BOUNDS_NONE", "bounds_width": 0, "crop_bottom": 0, "crop_left": 0, "crop_right": 0, "crop_top": 0, "height": 257, "position_x": 1800, "position_y": 414, "rotation": 0, "scale_x": 1, "scale_y": 1, "source_height": 257, "source_width": 146, "width": 146 }} - if to_input_port != 3: - return - if noobs == null: noobs = Connections.obs_websocket - if lock: - return - - var scene_name_req = await resolve_input_port_value_async(InputPorts.SCENE_NAME, "") - if scene_name_req == null: - return - - var scene_name: String - - if scene_name.is_empty(): - return - - var source_id_req = await resolve_input_port_value_async(InputPorts.SOURCE_ID) - if source_id_req == null: - return + var scene_name + var source_id + var xform - var source_id: float = source_id_req + match to_input_port: + InputPorts.SCENE_NAME: + scene_name = data + source_id = await resolve_input_port_value_async(InputPorts.SOURCE_ID) + xform = await resolve_input_port_value_async(InputPorts.XFORM) + InputPorts.SOURCE_ID: + source_id = data + scene_name = await resolve_input_port_value_async(InputPorts.SCENE_NAME) + xform = await resolve_input_port_value_async(InputPorts.XFORM) + InputPorts.XFORM: + xform = data + scene_name = await resolve_input_port_value_async(InputPorts.SCENE_NAME) + InputPorts.SET: + xform = await resolve_input_port_value_async(InputPorts.XFORM) + source_id = await resolve_input_port_value_async(InputPorts.SOURCE_ID) + scene_name = await resolve_input_port_value_async(InputPorts.SCENE_NAME) - var xform_req = await resolve_input_port_value_async(InputPorts.XFORM) - if xform_req == null: + if scene_name == null or str(scene_name).is_empty(): return - var xform: Dictionary = xform_req - - if xform.is_empty(): + if source_id == null or not source_id is float: return + if xform == null or not xform is Dictionary: + return + + #if to_input_port != 3: + #return +# +# + #if lock: + #return +# + #var scene_name_req = await resolve_input_port_value_async(InputPorts.SCENE_NAME, "") + #if scene_name_req == null: + #return +# + #var scene_name: String +# + #if scene_name.is_empty(): + #return +# + #var source_id_req = await resolve_input_port_value_async(InputPorts.SOURCE_ID) + #if source_id_req == null: + #return + # + #var source_id: float = source_id_req +# + #var xform_req = await resolve_input_port_value_async(InputPorts.XFORM) + #if xform_req == null: + #return +# + #var xform: Dictionary = xform_req +# + #if xform.is_empty(): + #return +# lock = true - - #noobs.make_generic_request("SetSceneItemTransform", - #{ - #"scene_name": scene_name, - #"scene_item_id": source_id, - #"scene_item_transform": xform, - #}) - #var sleep := noobs.make_generic_request("Sleep", {"sleep_frames": 1}) - #sleep.response_received.connect(func(): lock = false) var b := noobs.make_batch_request(false, NoOBSWS.Enums.RequestBatchExecutionType.SERIAL_FRAME) b.add_request( "SetSceneItemTransform", diff --git a/classes/deck/nodes/obs/obs_switch_scene.gd b/classes/deck/nodes/obs/obs_switch_scene.gd index f8b8d3b..325f98d 100644 --- a/classes/deck/nodes/obs/obs_switch_scene.gd +++ b/classes/deck/nodes/obs/obs_switch_scene.gd @@ -21,22 +21,20 @@ func _init() -> void: add_input_port( DeckType.Types.BOOL, "Switch", - "button" + "button", + Port.UsageType.TRIGGER, ) -func _receive(on_input_port: int, _data: Variant) -> void: - if on_input_port != 1: - return - +func _receive(on_input_port: int, data: Variant) -> void: if noobs == null: noobs = Connections.obs_websocket - var scene_name_req = await resolve_input_port_value_async(0, "") - if scene_name_req == null: - return - - var scene_name: String = scene_name_req + var scene_name: String + if on_input_port == 1: + scene_name = await resolve_input_port_value_async(0, "") + else: + scene_name = data as String if scene_name.is_empty(): return diff --git a/classes/deck/nodes/obs/obs_vector_to_position.gd b/classes/deck/nodes/obs/obs_vector_to_position.gd index 3b4cbd9..52ca5ea 100644 --- a/classes/deck/nodes/obs/obs_vector_to_position.gd +++ b/classes/deck/nodes/obs/obs_vector_to_position.gd @@ -28,3 +28,13 @@ func _value_request(_on_port: int) -> Variant: return null return {"position_x": v.x, "position_y": v.y} + + +func _receive(_on_input_port: int, data: Variant) -> void: + if not data is Dictionary: + return + + if not (data as Dictionary).has("x") or not (data as Dictionary).has("y"): + return + + send(0, {"position_x": data.x, "position_y": data.y}) diff --git a/classes/deck/nodes/test/test_type_sends.gd b/classes/deck/nodes/test/test_type_sends.gd new file mode 100644 index 0000000..3539865 --- /dev/null +++ b/classes/deck/nodes/test/test_type_sends.gd @@ -0,0 +1,30 @@ +# (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 = "Test Type Sends" + node_type = name.to_snake_case() + description = "" + + add_output_port(DeckType.Types.BOOL, "bool", "checkbox", Port.UsageType.TRIGGER) + add_output_port(DeckType.Types.STRING, "string", "field", Port.UsageType.TRIGGER) + add_output_port(DeckType.Types.NUMERIC, "numeric", "spinbox:unbounded", Port.UsageType.TRIGGER) + add_output_port(DeckType.Types.ARRAY, "array", "", Port.UsageType.TRIGGER) + add_output_port(DeckType.Types.DICTIONARY, "dictionary", "", Port.UsageType.TRIGGER) + add_output_port(DeckType.Types.DICTIONARY, "vector", "", Port.UsageType.TRIGGER) + + add_input_port(DeckType.Types.ANY, "Send", "button") + + +func _receive(_to_input_port: int, _data: Variant) -> void: + var id := UUID.v4() + send(0, get_output_ports()[0].value, id) + send(1, get_output_ports()[1].value, id) + send(2, get_output_ports()[2].value, id) + send(3, [1, 2, 3], id) + send(4, {"hello": "world"}, id) + send(5, {"x": 1, "y": 5}, id) +