be more lenient with using triggers and value requests on the same node on general and obs nodes (#78)

addresses part of #59

Reviewed-on: https://codeberg.org/StreamGraph/StreamGraph/pulls/78
Co-authored-by: Lera Elvoé <yagich@poto.cafe>
Co-committed-by: Lera Elvoé <yagich@poto.cafe>
This commit is contained in:
Lera Elvoé 2024-02-26 05:34:00 +00:00 committed by yagich
parent 215af7232a
commit c07d810bcf
18 changed files with 296 additions and 99 deletions

View file

@ -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: func _value_request(_on_port: int) -> Variant:
var arr = await request_value_async(0) var arr = await request_value_async(0)
if arr == null: if arr == null:
@ -34,11 +45,35 @@ func _value_request(_on_port: int) -> Variant:
var idx := int(await resolve_input_port_value_async(1)) var idx := int(await resolve_input_port_value_async(1))
if idx < 0: return _arr_index(arr, idx)
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] 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)

View file

@ -12,7 +12,8 @@ func _init() -> void:
add_output_port( add_output_port(
DeckType.Types.BOOL, DeckType.Types.BOOL,
"Value", "Value",
"checkbox" "checkbox",
Port.UsageType.VALUE_REQUEST,
) )

View file

@ -36,3 +36,23 @@ func _value_request(_on_port: int) -> Variant:
return null return null
return d.get(key) 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))

View file

@ -17,19 +17,17 @@ func _init():
# when it's fixed, switch it back # when it's fixed, switch it back
add_input_port( add_input_port(
DeckType.Types.DICTIONARY, DeckType.Types.DICTIONARY,
"Expression Input" "Expression Input",
) )
add_output_port( add_output_port(
DeckType.Types.ANY, DeckType.Types.ANY,
"Expression Text", "Expression Text",
"codeblock" "codeblock",
) )
func parse(input: Dictionary) -> Variant:
func _value_request(_from_port : int) -> Variant:
var text = get_output_ports()[0].value_callback.call() var text = get_output_ports()[0].value_callback.call()
var err = expr.parse(text, ["deck_var", "input"]) var err = expr.parse(text, ["deck_var", "input"])
@ -39,13 +37,18 @@ func _value_request(_from_port : int) -> Variant:
printerr(err) printerr(err)
return null return null
var res = expr.execute([_belonging_to.variable_stack, input])
var res = expr.execute([_belonging_to.variable_stack, await request_value_async(0)])
if expr.has_execute_failed(): if expr.has_execute_failed():
DeckHolder.logger.log_node("Expression Execution Failed: %s" % text, Logger.LogType.ERROR) DeckHolder.logger.log_node("Expression Execution Failed: %s" % text, Logger.LogType.ERROR)
return null return null
return res 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))

View file

@ -12,16 +12,21 @@ func _init() -> void:
add_input_port( add_input_port(
DeckType.Types.BOOL, DeckType.Types.BOOL,
"Condition", "Condition",
"checkbox" "checkbox",
Port.UsageType.VALUE_REQUEST,
) )
add_input_port( add_input_port(
DeckType.Types.ANY, DeckType.Types.ANY,
"Input" "Input",
"",
Port.UsageType.TRIGGER,
) )
add_output_port( add_output_port(
DeckType.Types.ANY, DeckType.Types.ANY,
"Output" "Output",
"",
Port.UsageType.TRIGGER,
) )

View file

@ -37,9 +37,7 @@ func _value_request(_on_port: int) -> Variant:
func _receive(on_port: int, data: Variant) -> void: func _receive(on_port: int, data: Variant) -> void:
if on_port == 0: if on_port == 0:
var b = await resolve_input_port_value_async(1) var b = await resolve_input_port_value_async(1)
if data == b: send(0, data == b)
send(0, true)
else: else:
var b = await resolve_input_port_value_async(0) var b = await resolve_input_port_value_async(0)
if data == b: send(0, data == b)
send(0, true)

View file

@ -37,7 +37,7 @@ func _receive(to_input_port: int, data: Variant) -> void:
return return
var data_to_print = str(await resolve_input_port_value_async(0)) 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) data_to_print = str(data)
if (data_to_print as String).is_empty(): if (data_to_print as String).is_empty():
data_to_print = "<nothing>" data_to_print = "<nothing>"

View file

@ -14,17 +14,22 @@ func _init() -> void:
add_input_port( add_input_port(
DeckType.Types.BOOL, DeckType.Types.BOOL,
"Enabled", "Enabled",
"checkbox" "checkbox",
Port.UsageType.VALUE_REQUEST,
) )
add_output_port( add_output_port(
DeckType.Types.BOOL, DeckType.Types.BOOL,
"Trigger" "Trigger",
"",
Port.UsageType.TRIGGER
) )
add_output_port( add_output_port(
DeckType.Types.NUMERIC, DeckType.Types.NUMERIC,
"Delta" "Delta",
"",
Port.UsageType.TRIGGER
) )
@ -38,7 +43,9 @@ func _event_received(event_name: StringName, event_data: Dictionary = {}) -> voi
return return
delta = event_data.delta 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: func _value_request(on_output_port: int) -> Variant:

View file

@ -24,21 +24,37 @@ func _init() -> void:
add_input_port( add_input_port(
DeckType.Types.BOOL, DeckType.Types.BOOL,
"Set", "Set",
"button" "button",
Port.UsageType.TRIGGER,
) )
add_output_port( add_output_port(
DeckType.Types.ANY, DeckType.Types.ANY,
"Value", "Value",
"label" "label",
Port.UsageType.TRIGGER,
) )
func _receive(to_input_port: int, _data: Variant) -> void: func _receive(to_input_port: int, data: Variant) -> void:
if to_input_port != 2: 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 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_name: String = await resolve_input_port_value_async(0)
var var_value: Variant = await resolve_input_port_value_async(1) var var_value: Variant = await resolve_input_port_value_async(1)
#_belonging_to.variable_stack[var_name] = var_value #_belonging_to.variable_stack[var_name] = var_value

View file

@ -12,7 +12,8 @@ func _init() -> void:
add_output_port( add_output_port(
DeckType.Types.STRING, DeckType.Types.STRING,
"Text", "Text",
"field" "field",
Port.UsageType.VALUE_REQUEST,
) )
func _value_request(_from_port: int) -> Variant: func _value_request(_from_port: int) -> Variant:

View file

@ -36,3 +36,21 @@ func _value_request(_on_port: int) -> Variant:
var string = await resolve_input_port_value_async(0) var string = await resolve_input_port_value_async(0)
return Array(string.split(delimiter)) 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)))

View file

@ -43,3 +43,13 @@ func _value_request(on_port: int) -> Variant:
return (t as Dictionary).get("position_y") return (t as Dictionary).get("position_y")
_: _:
return null 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)

View file

@ -16,7 +16,8 @@ func _init() -> void:
add_output_port( add_output_port(
DeckType.Types.STRING, DeckType.Types.STRING,
"Select a scene", "Select a scene",
"singlechoice" "singlechoice",
Port.UsageType.VALUE_REQUEST,
) )
add_virtual_port( add_virtual_port(

View file

@ -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: if noobs == null:
noobs = Connections.obs_websocket 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: if cached_scene_name == scene_name and cached_source_name == scene_name:
return cached_id return cached_id
@ -70,3 +59,35 @@ func _value_request(_on_output_port: int) -> Variant:
return data.response_data.scene_item_id 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))

View file

@ -42,55 +42,78 @@ func _init() -> void:
add_input_port( add_input_port(
DeckType.Types.BOOL, DeckType.Types.BOOL,
"Set", "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 }} #{ "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: if noobs == null:
noobs = Connections.obs_websocket noobs = Connections.obs_websocket
if lock: var scene_name
var source_id
var xform
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)
if scene_name == null or str(scene_name).is_empty():
return return
var scene_name_req = await resolve_input_port_value_async(InputPorts.SCENE_NAME, "") if source_id == null or not source_id is float:
if scene_name_req == null:
return return
var scene_name: String if xform == null or not xform is Dictionary:
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 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 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) var b := noobs.make_batch_request(false, NoOBSWS.Enums.RequestBatchExecutionType.SERIAL_FRAME)
b.add_request( b.add_request(
"SetSceneItemTransform", "SetSceneItemTransform",

View file

@ -21,22 +21,20 @@ func _init() -> void:
add_input_port( add_input_port(
DeckType.Types.BOOL, DeckType.Types.BOOL,
"Switch", "Switch",
"button" "button",
Port.UsageType.TRIGGER,
) )
func _receive(on_input_port: int, _data: Variant) -> void: func _receive(on_input_port: int, data: Variant) -> void:
if on_input_port != 1:
return
if noobs == null: if noobs == null:
noobs = Connections.obs_websocket noobs = Connections.obs_websocket
var scene_name_req = await resolve_input_port_value_async(0, "") var scene_name: String
if scene_name_req == null: if on_input_port == 1:
return scene_name = await resolve_input_port_value_async(0, "")
else:
var scene_name: String = scene_name_req scene_name = data as String
if scene_name.is_empty(): if scene_name.is_empty():
return return

View file

@ -28,3 +28,13 @@ func _value_request(_on_port: int) -> Variant:
return null return null
return {"position_x": v.x, "position_y": v.y} 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})

View file

@ -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)