mirror of
https://codeberg.org/StreamGraph/StreamGraph.git
synced 2024-11-13 19:49:55 +01:00
store connections inside the deck (#147)
- node/port connections are now stored in the deck they belong to - share the connections object between group instances for free syncing - add compatibility code to allow loading decks made before this change - disabled the ability to open multiple decks in the renderer for now since it'd cause problems when opening multiple decks and one of them is incompatible; to be redesigned later closes #140 Reviewed-on: https://codeberg.org/StreamGraph/StreamGraph/pulls/147 Co-authored-by: Lera Elvoé <yagich@poto.cafe> Co-committed-by: Lera Elvoé <yagich@poto.cafe>
This commit is contained in:
parent
1ce3cd0367
commit
f24906715d
10 changed files with 521 additions and 252 deletions
|
@ -16,6 +16,9 @@ var variable_stack: Dictionary = {}
|
||||||
## The path to save this deck on the file system.
|
## The path to save this deck on the file system.
|
||||||
var save_path: String = ""
|
var save_path: String = ""
|
||||||
|
|
||||||
|
## The connections graph.
|
||||||
|
var connections := NodeConnections.new()
|
||||||
|
|
||||||
var is_group: bool = false
|
var is_group: bool = false
|
||||||
## List of groups belonging to this deck, in the format of[br]
|
## List of groups belonging to this deck, in the format of[br]
|
||||||
## [code]Dictionary[String -> Deck.id, Deck][/code]
|
## [code]Dictionary[String -> Deck.id, Deck][/code]
|
||||||
|
@ -25,6 +28,7 @@ var id: String = ""
|
||||||
## If this is a group, this is the local ID of this instance of the group.
|
## If this is a group, this is the local ID of this instance of the group.
|
||||||
var instance_id: String = ""
|
var instance_id: String = ""
|
||||||
## The parent deck of this deck, if this is a group.
|
## The parent deck of this deck, if this is a group.
|
||||||
|
@warning_ignore("unused_private_class_variable")
|
||||||
var _belonging_to: String = "" # for groups
|
var _belonging_to: String = "" # for groups
|
||||||
## The ID of this group's input node. Used only if [member is_group] is [code]true[/code].
|
## The ID of this group's input node. Used only if [member is_group] is [code]true[/code].
|
||||||
var group_input_node: String
|
var group_input_node: String
|
||||||
|
@ -52,8 +56,6 @@ signal variables_updated()
|
||||||
#region group signals
|
#region group signals
|
||||||
signal node_added_to_group(node: DeckNode, assign_id: String, assign_to_self: bool, deck: Deck)
|
signal node_added_to_group(node: DeckNode, assign_id: String, assign_to_self: bool, deck: Deck)
|
||||||
signal node_removed_from_group(node_id: String, remove_connections: bool, deck: Deck)
|
signal node_removed_from_group(node_id: String, remove_connections: bool, deck: Deck)
|
||||||
signal nodes_connected_in_group(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int, deck: Deck)
|
|
||||||
signal nodes_disconnected_in_group(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int, deck: Deck)
|
|
||||||
signal node_port_value_updated(node_id: String, port_idx: int, new_value: Variant, deck: Deck)
|
signal node_port_value_updated(node_id: String, port_idx: int, new_value: Variant, deck: Deck)
|
||||||
signal node_renamed(node_id: String, new_name: String, deck: Deck)
|
signal node_renamed(node_id: String, new_name: String, deck: Deck)
|
||||||
signal node_moved(node_id: String, new_position: Dictionary, deck: Deck)
|
signal node_moved(node_id: String, new_position: Dictionary, deck: Deck)
|
||||||
|
@ -129,6 +131,10 @@ func get_node(uuid: String) -> DeckNode:
|
||||||
return nodes.get(uuid)
|
return nodes.get(uuid)
|
||||||
|
|
||||||
|
|
||||||
|
func get_connections_dict() -> Dictionary:
|
||||||
|
return connections.data
|
||||||
|
|
||||||
|
|
||||||
## Returns [code]true[/code] if the connection between two nodes is legal.
|
## Returns [code]true[/code] if the connection between two nodes is legal.
|
||||||
func is_valid_connection(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> bool:
|
func is_valid_connection(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> bool:
|
||||||
# do not connect to self
|
# do not connect to self
|
||||||
|
@ -152,7 +158,7 @@ func is_valid_connection(from_node_id: String, to_node_id: String, from_output_p
|
||||||
return false
|
return false
|
||||||
|
|
||||||
# duplicate connection
|
# duplicate connection
|
||||||
if from_node.has_outgoing_connection_exact(from_output_port, to_node_id, to_input_port):
|
if connections.has_outgoing_connection_exact(from_node_id, from_output_port, to_node_id, to_input_port):
|
||||||
return false
|
return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -166,30 +172,26 @@ func connect_nodes(from_node_id: String, to_node_id: String, from_output_port: i
|
||||||
var from_node := get_node(from_node_id)
|
var from_node := get_node(from_node_id)
|
||||||
var to_node := get_node(to_node_id)
|
var to_node := get_node(to_node_id)
|
||||||
|
|
||||||
if to_node.has_incoming_connection(to_input_port):
|
if connections.has_incoming_connection(to_node_id, to_input_port):
|
||||||
var connection: Dictionary = to_node.incoming_connections[to_input_port]
|
var connection := connections.get_incoming_connection(to_node_id, to_input_port)
|
||||||
var node_id: String = connection.keys()[0]
|
disconnect_nodes(connection.from_node, to_node_id, connection.from_port, to_input_port)
|
||||||
var node_out_port: int = connection.values()[0]
|
|
||||||
disconnect_nodes(node_id, to_node_id, node_out_port, to_input_port)
|
|
||||||
|
|
||||||
if is_group and emit_group_signals:
|
connections.add_connection(from_node_id, to_node_id, from_output_port, to_input_port)
|
||||||
nodes_connected_in_group.emit(from_node_id, to_node_id, from_output_port, to_input_port, self)
|
|
||||||
|
|
||||||
from_node.add_outgoing_connection(from_output_port, to_node._id, to_input_port)
|
|
||||||
nodes_connected.emit(from_node_id, to_node_id, from_output_port, to_input_port)
|
nodes_connected.emit(from_node_id, to_node_id, from_output_port, to_input_port)
|
||||||
|
from_node.outgoing_connection_added.emit(from_output_port)
|
||||||
|
to_node.incoming_connection_added.emit(to_input_port)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
## Remove a connection from two nodes.
|
## Remove a connection from two nodes.
|
||||||
func disconnect_nodes(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> void:
|
func disconnect_nodes(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> void:
|
||||||
|
connections.remove_connection(from_node_id, to_node_id, from_output_port, to_input_port)
|
||||||
|
nodes_disconnected.emit(from_node_id, to_node_id, from_output_port, to_input_port)
|
||||||
|
|
||||||
var from_node := get_node(from_node_id)
|
var from_node := get_node(from_node_id)
|
||||||
var to_node := get_node(to_node_id)
|
var to_node := get_node(to_node_id)
|
||||||
from_node.remove_outgoing_connection(from_output_port, to_node_id, to_input_port)
|
from_node.outgoing_connection_removed.emit(from_output_port)
|
||||||
to_node.remove_incoming_connection(to_input_port)
|
to_node.incoming_connection_removed.emit(to_input_port)
|
||||||
if is_group and emit_group_signals:
|
|
||||||
nodes_disconnected_in_group.emit(from_node_id, to_node_id, from_output_port, to_input_port, self)
|
|
||||||
|
|
||||||
nodes_disconnected.emit(from_node_id, to_node_id, from_output_port, to_input_port)
|
|
||||||
|
|
||||||
|
|
||||||
## Returns true if this deck has no nodes and no variables.
|
## Returns true if this deck has no nodes and no variables.
|
||||||
|
@ -210,18 +212,16 @@ func remove_node(uuid: String, remove_connections: bool = false, force: bool = f
|
||||||
DeckHolder.close_group_instance(node.group_id, node.group_instance_id)
|
DeckHolder.close_group_instance(node.group_id, node.group_instance_id)
|
||||||
|
|
||||||
if remove_connections:
|
if remove_connections:
|
||||||
var outgoing_connections := node.outgoing_connections.duplicate(true)
|
var outgoing_connections := connections.get_all_outgoing_connections(uuid)
|
||||||
|
for from_port: int in outgoing_connections:
|
||||||
|
for outgoing: OutgoingConnection in outgoing_connections[from_port]:
|
||||||
|
var incoming := outgoing.counterpart.get_ref() as IncomingConnection
|
||||||
|
disconnect_nodes(uuid, outgoing.to_node, incoming.from_port, outgoing.to_port)
|
||||||
|
|
||||||
for output_port: int in outgoing_connections:
|
var incoming_connections := connections.get_all_incoming_connections(uuid)
|
||||||
for to_node: String in outgoing_connections[output_port]:
|
for to_port: int in incoming_connections:
|
||||||
for to_port: int in outgoing_connections[output_port][to_node]:
|
var incoming := connections.get_incoming_connection(uuid, to_port)
|
||||||
disconnect_nodes(uuid, to_node, output_port, to_port)
|
disconnect_nodes(incoming.from_node, uuid, incoming.from_port, to_port)
|
||||||
|
|
||||||
var incoming_connections := node.incoming_connections.duplicate(true)
|
|
||||||
|
|
||||||
for input_port: int in incoming_connections:
|
|
||||||
for from_node: String in incoming_connections[input_port]:
|
|
||||||
disconnect_nodes(from_node, uuid, incoming_connections[input_port][from_node], input_port)
|
|
||||||
|
|
||||||
nodes.erase(uuid)
|
nodes.erase(uuid)
|
||||||
|
|
||||||
|
@ -265,6 +265,10 @@ func group_nodes(nodes_to_group: Array) -> Deck:
|
||||||
)
|
)
|
||||||
|
|
||||||
var group := DeckHolder.add_empty_group(id)
|
var group := DeckHolder.add_empty_group(id)
|
||||||
|
var connection_pairs := connections.filter_pairs(node_ids_to_keep)
|
||||||
|
|
||||||
|
for pair in connection_pairs:
|
||||||
|
group.connections.add_pair(pair)
|
||||||
|
|
||||||
var midpoint := Vector2()
|
var midpoint := Vector2()
|
||||||
|
|
||||||
|
@ -283,20 +287,31 @@ func group_nodes(nodes_to_group: Array) -> Deck:
|
||||||
if node.position.x < leftmost:
|
if node.position.x < leftmost:
|
||||||
leftmost = node.position.x
|
leftmost = node.position.x
|
||||||
|
|
||||||
var outgoing_connections := node.outgoing_connections.duplicate(true)
|
#var outgoing_connections := node.outgoing_connections.duplicate(true)
|
||||||
|
#
|
||||||
|
#for from_port: int in outgoing_connections:
|
||||||
|
#for to_node: String in outgoing_connections[from_port]:
|
||||||
|
#for to_port: int in outgoing_connections[from_port][to_node]:
|
||||||
|
#if to_node not in node_ids_to_keep:
|
||||||
|
#disconnect_nodes(node._id, to_node, from_port, to_port)
|
||||||
|
|
||||||
|
var outgoing_connections := connections.get_all_outgoing_connections(node._id)
|
||||||
for from_port: int in outgoing_connections:
|
for from_port: int in outgoing_connections:
|
||||||
for to_node: String in outgoing_connections[from_port]:
|
for outgoing: OutgoingConnection in outgoing_connections[from_port]:
|
||||||
for to_port: int in outgoing_connections[from_port][to_node]:
|
var incoming := outgoing.counterpart.get_ref() as IncomingConnection
|
||||||
if to_node not in node_ids_to_keep:
|
disconnect_nodes(node._id, outgoing.to_node, incoming.from_port, outgoing.to_port)
|
||||||
disconnect_nodes(node._id, to_node, from_port, to_port)
|
|
||||||
|
|
||||||
var incoming_connections := node.incoming_connections.duplicate(true)
|
#var incoming_connections := node.incoming_connections.duplicate(true)
|
||||||
|
#
|
||||||
|
#for to_port: int in incoming_connections:
|
||||||
|
#for from_node: String in incoming_connections[to_port]:
|
||||||
|
#if from_node not in node_ids_to_keep:
|
||||||
|
#disconnect_nodes(from_node, node._id, incoming_connections[to_port][from_node], to_port)
|
||||||
|
|
||||||
|
var incoming_connections := connections.get_all_incoming_connections(node._id)
|
||||||
for to_port: int in incoming_connections:
|
for to_port: int in incoming_connections:
|
||||||
for from_node: String in incoming_connections[to_port]:
|
var incoming := connections.get_incoming_connection(node._id, to_port)
|
||||||
if from_node not in node_ids_to_keep:
|
disconnect_nodes(incoming.from_node, node._id, incoming.from_port, to_port)
|
||||||
disconnect_nodes(from_node, node._id, incoming_connections[to_port][from_node], to_port)
|
|
||||||
|
|
||||||
midpoint += node.position_as_vector2()
|
midpoint += node.position_as_vector2()
|
||||||
remove_node(node._id, false, true)
|
remove_node(node._id, false, true)
|
||||||
|
@ -344,7 +359,10 @@ func group_nodes(nodes_to_group: Array) -> Deck:
|
||||||
|
|
||||||
|
|
||||||
func copy_nodes(nodes_to_copy: Array[String]) -> Dictionary:
|
func copy_nodes(nodes_to_copy: Array[String]) -> Dictionary:
|
||||||
var d := {"nodes": {}}
|
var d := {
|
||||||
|
"nodes": {},
|
||||||
|
"connections": connections.filter_pairs(nodes_to_copy),
|
||||||
|
}
|
||||||
|
|
||||||
for node_id: String in nodes_to_copy:
|
for node_id: String in nodes_to_copy:
|
||||||
d.nodes[node_id] = get_node(node_id).to_dict()
|
d.nodes[node_id] = get_node(node_id).to_dict()
|
||||||
|
@ -392,7 +410,12 @@ func copy_nodes(nodes_to_copy: Array[String]) -> Dictionary:
|
||||||
|
|
||||||
|
|
||||||
func copy_nodes_json(nodes_to_copy: Array[String]) -> String:
|
func copy_nodes_json(nodes_to_copy: Array[String]) -> String:
|
||||||
return JSON.stringify(copy_nodes(nodes_to_copy))
|
var res := copy_nodes(nodes_to_copy)
|
||||||
|
res.connections = res.connections.map(
|
||||||
|
func(x: ConnectionPair):
|
||||||
|
return x.to_dict()
|
||||||
|
)
|
||||||
|
return JSON.stringify(res)
|
||||||
|
|
||||||
|
|
||||||
func allocate_ids(count: int) -> Array[String]:
|
func allocate_ids(count: int) -> Array[String]:
|
||||||
|
@ -406,35 +429,30 @@ func paste_nodes_from_dict(nodes_to_paste: Dictionary, position: Vector2 = Vecto
|
||||||
if not nodes_to_paste.get("nodes"):
|
if not nodes_to_paste.get("nodes"):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
var pairs = (nodes_to_paste.connections as Array).map(
|
||||||
|
func(x: Dictionary):
|
||||||
|
return ConnectionPair.from_dict(x)
|
||||||
|
)
|
||||||
|
|
||||||
var new_ids := allocate_ids(nodes_to_paste.nodes.size())
|
var new_ids := allocate_ids(nodes_to_paste.nodes.size())
|
||||||
var ids_map := {}
|
var ids_map := {}
|
||||||
for i: int in nodes_to_paste.nodes.keys().size():
|
for i: int in nodes_to_paste.nodes.keys().size():
|
||||||
var node_id: String = nodes_to_paste.nodes.keys()[i]
|
var node_id: String = nodes_to_paste.nodes.keys()[i]
|
||||||
ids_map[node_id] = new_ids[i]
|
ids_map[node_id] = new_ids[i]
|
||||||
|
|
||||||
|
for old_id: String in ids_map:
|
||||||
|
for pair: ConnectionPair in pairs:
|
||||||
|
pair.remap_id(old_id, ids_map[old_id])
|
||||||
|
|
||||||
|
for pair: ConnectionPair in pairs:
|
||||||
|
connections.add_pair(pair)
|
||||||
|
|
||||||
for node_id: String in nodes_to_paste.nodes:
|
for node_id: String in nodes_to_paste.nodes:
|
||||||
nodes_to_paste.nodes[node_id]._id = ids_map[node_id]
|
nodes_to_paste.nodes[node_id]._id = ids_map[node_id]
|
||||||
|
|
||||||
nodes_to_paste.nodes[node_id].position.x += position.x
|
nodes_to_paste.nodes[node_id].position.x += position.x
|
||||||
nodes_to_paste.nodes[node_id].position.y += position.y
|
nodes_to_paste.nodes[node_id].position.y += position.y
|
||||||
|
|
||||||
var outgoing_connections: Dictionary = nodes_to_paste.nodes[node_id].outgoing_connections as Dictionary
|
|
||||||
var outgoing_connections_res := {}
|
|
||||||
for from_port in outgoing_connections:
|
|
||||||
outgoing_connections_res[from_port] = {}
|
|
||||||
for to_node_id in outgoing_connections[from_port]:
|
|
||||||
outgoing_connections_res[from_port][ids_map[to_node_id]] = outgoing_connections[from_port][to_node_id]
|
|
||||||
|
|
||||||
var incoming_connections: Dictionary = nodes_to_paste.nodes[node_id].incoming_connections as Dictionary
|
|
||||||
var incoming_connections_res := {}
|
|
||||||
for to_port in incoming_connections:
|
|
||||||
incoming_connections_res[to_port] = {}
|
|
||||||
for from_node_id in incoming_connections[to_port]:
|
|
||||||
incoming_connections_res[to_port][ids_map[from_node_id]] = incoming_connections[to_port][from_node_id]
|
|
||||||
|
|
||||||
nodes_to_paste.nodes[node_id].outgoing_connections = outgoing_connections_res
|
|
||||||
nodes_to_paste.nodes[node_id].incoming_connections = incoming_connections_res
|
|
||||||
|
|
||||||
var node := DeckNode.from_dict(nodes_to_paste.nodes[node_id])
|
var node := DeckNode.from_dict(nodes_to_paste.nodes[node_id])
|
||||||
var group_needs_unique := false
|
var group_needs_unique := false
|
||||||
if node.node_type == "group_node":
|
if node.node_type == "group_node":
|
||||||
|
@ -465,6 +483,29 @@ func duplicate_nodes(nodes_to_copy: Array[String]) -> void:
|
||||||
paste_nodes_from_dict(d, position)
|
paste_nodes_from_dict(d, position)
|
||||||
|
|
||||||
|
|
||||||
|
## Send [param data] from [param from_node_id] to all outgoing connections on port [param from_output_port].[br]
|
||||||
|
## See [method DeckNode.send].
|
||||||
|
func send(from_node_id: String, from_output_port: int, data: Variant, send_id: String) -> void:
|
||||||
|
var outgoing_connections := connections.get_outgoing_connections(from_node_id, from_output_port)
|
||||||
|
for connection in outgoing_connections:
|
||||||
|
var node := get_node(connection.to_node)
|
||||||
|
node.handle_receive(connection.to_port, data, send_id)
|
||||||
|
|
||||||
|
|
||||||
|
## Asynchronously request a value from an incoming connection on the node at [param node_id]'s input port at [param on_input_port].
|
||||||
|
## Returns [code]null[/code] if no incoming connection exists on that port.
|
||||||
|
## The connected node may also return [code]null[/code].[br]
|
||||||
|
## See [method DeckNode.request_value_async].
|
||||||
|
func request_value_async(node_id: String, on_input_port: int) -> Variant:
|
||||||
|
var connection := connections.get_incoming_connection(node_id, on_input_port)
|
||||||
|
if connection == null:
|
||||||
|
return null
|
||||||
|
|
||||||
|
var other_node := get_node(connection.from_node)
|
||||||
|
|
||||||
|
return await other_node._value_request(connection.from_port)
|
||||||
|
|
||||||
|
|
||||||
func send_event(event_name: StringName, event_data: Dictionary = {}) -> void:
|
func send_event(event_name: StringName, event_data: Dictionary = {}) -> void:
|
||||||
for node: DeckNode in nodes.values():
|
for node: DeckNode in nodes.values():
|
||||||
node._event_received(event_name, event_data)
|
node._event_received(event_name, event_data)
|
||||||
|
@ -512,7 +553,8 @@ func to_dict(with_meta: bool = true, group_ids: Array = []) -> Dictionary:
|
||||||
"nodes": {},
|
"nodes": {},
|
||||||
"variable_stack": variable_stack,
|
"variable_stack": variable_stack,
|
||||||
"id": id,
|
"id": id,
|
||||||
"groups": {}
|
"groups": {},
|
||||||
|
"connections": connections.to_dict(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for node_id: String in nodes.keys():
|
for node_id: String in nodes.keys():
|
||||||
|
@ -545,6 +587,7 @@ static func from_dict(data: Dictionary, path: String = "") -> Deck:
|
||||||
deck.save_path = path
|
deck.save_path = path
|
||||||
deck.variable_stack = data.deck.variable_stack
|
deck.variable_stack = data.deck.variable_stack
|
||||||
deck.id = data.deck.id
|
deck.id = data.deck.id
|
||||||
|
deck.connections = NodeConnections.from_dict(data.deck.connections)
|
||||||
|
|
||||||
for key in data.meta:
|
for key in data.meta:
|
||||||
deck.set_meta(key, str_to_var(data.meta[key]))
|
deck.set_meta(key, str_to_var(data.meta[key]))
|
||||||
|
@ -581,3 +624,269 @@ static func from_dict(data: Dictionary, path: String = "") -> Deck:
|
||||||
|
|
||||||
|
|
||||||
return deck
|
return deck
|
||||||
|
|
||||||
|
|
||||||
|
class NodeConnections:
|
||||||
|
# Dictionary[String -> node id, Dictionary["incoming": Dictionary[int -> input port idx, IncomingConnection], "outgoing": Dictionary[int - > output port idx, Array[OutgoingConnection]]]
|
||||||
|
var data := {}
|
||||||
|
|
||||||
|
|
||||||
|
func add_connection(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> void:
|
||||||
|
var from_connection: Dictionary = data.get(from_node_id, _create_empty_connection())
|
||||||
|
var to_connection: Dictionary = data.get(to_node_id, _create_empty_connection())
|
||||||
|
var pair := ConnectionPair.new(from_node_id, to_node_id, from_output_port, to_input_port)
|
||||||
|
|
||||||
|
var out_list: Array = (from_connection.outgoing as Dictionary).get(from_output_port, [])
|
||||||
|
out_list.append(pair.outgoing)
|
||||||
|
(from_connection.outgoing as Dictionary)[from_output_port] = out_list
|
||||||
|
|
||||||
|
(to_connection.incoming as Dictionary)[to_input_port] = pair.incoming
|
||||||
|
|
||||||
|
data[from_node_id] = from_connection
|
||||||
|
data[to_node_id] = to_connection
|
||||||
|
|
||||||
|
|
||||||
|
func remove_connection(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> void:
|
||||||
|
var from_connection: Dictionary = data.get(from_node_id, {})
|
||||||
|
if from_connection.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var out_list: Array = (from_connection.outgoing as Dictionary).get(from_output_port, [])
|
||||||
|
if out_list.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var comp := ConnectionPair.new(from_node_id, to_node_id, from_output_port, to_input_port)
|
||||||
|
|
||||||
|
for i in out_list.size():
|
||||||
|
var out: OutgoingConnection = out_list[i]
|
||||||
|
var pair := ConnectionPair.from_outgoing(out)
|
||||||
|
if pair.is_equivalent(comp):
|
||||||
|
var to_connection: Dictionary = data.get(to_node_id).incoming
|
||||||
|
to_connection.erase(to_input_port)
|
||||||
|
out_list.erase(out)
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
func has_incoming_connection(node_id: String, on_port: int) -> bool:
|
||||||
|
return data.get(node_id, _create_empty_connection()).incoming.has(on_port)
|
||||||
|
|
||||||
|
|
||||||
|
func get_incoming_connection(node_id: String, on_port: int) -> IncomingConnection:
|
||||||
|
return data.get(node_id, _create_empty_connection()).incoming.get(on_port)
|
||||||
|
|
||||||
|
|
||||||
|
func has_outgoing_connection_exact(node_id: String, from_port: int, to_node: String, to_port: int) -> bool:
|
||||||
|
if not data.get(node_id, _create_empty_connection()).outgoing.has(from_port):
|
||||||
|
return false
|
||||||
|
|
||||||
|
var has = false
|
||||||
|
for connection: OutgoingConnection in data.get(node_id, _create_empty_connection()).outgoing.get(from_port):
|
||||||
|
var inc := connection.counterpart.get_ref() as IncomingConnection
|
||||||
|
if connection.to_node == to_node \
|
||||||
|
and connection.to_port == to_port\
|
||||||
|
and inc.from_port == from_port:
|
||||||
|
has = true
|
||||||
|
|
||||||
|
return has
|
||||||
|
|
||||||
|
|
||||||
|
func get_outgoing_connections(node_id: String, from_port: int) -> Array[OutgoingConnection]:
|
||||||
|
if data.get(node_id, _create_empty_connection()).outgoing.is_empty():
|
||||||
|
return []
|
||||||
|
|
||||||
|
var res: Array[OutgoingConnection] = []
|
||||||
|
|
||||||
|
res.assign(data[node_id].outgoing[from_port])
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
func get_all_outgoing_connections(node_id: String) -> Dictionary:
|
||||||
|
return data.get(node_id, _create_empty_connection()).outgoing
|
||||||
|
|
||||||
|
|
||||||
|
func get_all_incoming_connections(node_id: String) -> Dictionary:
|
||||||
|
return data.get(node_id, _create_empty_connection()).incoming
|
||||||
|
|
||||||
|
|
||||||
|
func filter_pairs(nodes: Array) -> Array[ConnectionPair]:
|
||||||
|
var res: Array[ConnectionPair] = []
|
||||||
|
|
||||||
|
for node_id: String in nodes:
|
||||||
|
var connections: Dictionary = data.get(node_id, _create_empty_connection())
|
||||||
|
for to_port: int in connections.outgoing:
|
||||||
|
for outgoing: OutgoingConnection in connections.outgoing[to_port]:
|
||||||
|
if outgoing.to_node in nodes:
|
||||||
|
res.append(ConnectionPair.from_outgoing(outgoing))
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
func add_pair(pair: ConnectionPair) -> void:
|
||||||
|
var outgoing := pair.outgoing
|
||||||
|
var incoming := pair.incoming
|
||||||
|
add_connection(incoming.from_node, outgoing.to_node, incoming.from_port, outgoing.to_port)
|
||||||
|
|
||||||
|
|
||||||
|
func _create_empty_connection() -> Dictionary:
|
||||||
|
return {
|
||||||
|
"incoming": {},
|
||||||
|
"outgoing": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func to_dict() -> Dictionary:
|
||||||
|
var res := {}
|
||||||
|
for node_id: String in data:
|
||||||
|
res[node_id] = _create_empty_connection()
|
||||||
|
for to_port: int in data[node_id].incoming:
|
||||||
|
res[node_id].incoming[to_port] = (data[node_id].incoming[to_port] as IncomingConnection).to_dict()
|
||||||
|
|
||||||
|
for from_port: int in data[node_id].outgoing:
|
||||||
|
for i: OutgoingConnection in data[node_id].outgoing[from_port]:
|
||||||
|
var arr: Array = res[node_id].outgoing.get(from_port, [])
|
||||||
|
arr.append(i.to_dict())
|
||||||
|
res[node_id].outgoing[from_port] = arr
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
static func from_dict(d: Dictionary) -> NodeConnections:
|
||||||
|
var res := NodeConnections.new()
|
||||||
|
for node_id: String in d:
|
||||||
|
for from_port in d[node_id].outgoing:
|
||||||
|
for connection: Dictionary in d[node_id].outgoing[from_port]:
|
||||||
|
res.add_connection(node_id, connection.to_node, int(from_port), int(connection.to_port))
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectionPair:
|
||||||
|
var from_node_id: String
|
||||||
|
var to_node_id: String
|
||||||
|
var from_output_port: int
|
||||||
|
var to_input_port: int
|
||||||
|
|
||||||
|
var incoming: IncomingConnection
|
||||||
|
var outgoing: OutgoingConnection
|
||||||
|
|
||||||
|
|
||||||
|
func _init(
|
||||||
|
p_from_node_id: String,
|
||||||
|
p_to_node_id: String,
|
||||||
|
p_from_output_port: int,
|
||||||
|
p_to_input_port: int,
|
||||||
|
p_outgoing: OutgoingConnection = null,
|
||||||
|
p_incoming: IncomingConnection = null
|
||||||
|
) -> void:
|
||||||
|
from_node_id = p_from_node_id
|
||||||
|
to_node_id = p_to_node_id
|
||||||
|
from_output_port = p_from_output_port
|
||||||
|
to_input_port = p_to_input_port
|
||||||
|
|
||||||
|
if not p_outgoing:
|
||||||
|
outgoing = OutgoingConnection.new()
|
||||||
|
outgoing.to_node = to_node_id
|
||||||
|
outgoing.to_port = to_input_port
|
||||||
|
|
||||||
|
incoming = IncomingConnection.new()
|
||||||
|
incoming.from_port = from_output_port
|
||||||
|
incoming.from_node = from_node_id
|
||||||
|
|
||||||
|
incoming.counterpart = weakref(outgoing)
|
||||||
|
outgoing.counterpart = weakref(incoming)
|
||||||
|
else:
|
||||||
|
outgoing = p_outgoing
|
||||||
|
incoming = p_incoming
|
||||||
|
|
||||||
|
|
||||||
|
func remap_id(old_id: String, new_id: String) -> void:
|
||||||
|
if old_id == from_node_id:
|
||||||
|
from_node_id = new_id
|
||||||
|
incoming.from_node = new_id
|
||||||
|
elif old_id == to_node_id:
|
||||||
|
to_node_id = new_id
|
||||||
|
outgoing.to_node = new_id
|
||||||
|
|
||||||
|
|
||||||
|
func is_equivalent(other: ConnectionPair) -> bool:
|
||||||
|
if from_node_id == other.from_node_id and \
|
||||||
|
to_node_id == other.to_node_id and \
|
||||||
|
from_output_port == other.from_output_port and \
|
||||||
|
to_input_port == other.to_input_port:
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func to_dict() -> Dictionary:
|
||||||
|
return {
|
||||||
|
"incoming": incoming.to_dict(),
|
||||||
|
"outgoing": outgoing.to_dict(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static func from_incoming(p_incoming: IncomingConnection) -> ConnectionPair:
|
||||||
|
@warning_ignore("shadowed_variable")
|
||||||
|
var outgoing := p_incoming.counterpart.get_ref() as OutgoingConnection
|
||||||
|
|
||||||
|
return ConnectionPair.new(
|
||||||
|
p_incoming.from_node, outgoing.to_node,
|
||||||
|
p_incoming.from_port, outgoing.to_port,
|
||||||
|
outgoing, p_incoming
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
static func from_outgoing(p_outgoing: OutgoingConnection) -> ConnectionPair:
|
||||||
|
@warning_ignore("shadowed_variable")
|
||||||
|
var incoming := p_outgoing.counterpart.get_ref() as IncomingConnection
|
||||||
|
|
||||||
|
return ConnectionPair.new(
|
||||||
|
incoming.from_node, p_outgoing.to_node,
|
||||||
|
incoming.from_port, p_outgoing.to_port,
|
||||||
|
p_outgoing, incoming
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
static func from_dict(d: Dictionary) -> ConnectionPair:
|
||||||
|
@warning_ignore("shadowed_variable")
|
||||||
|
var outgoing := OutgoingConnection.new()
|
||||||
|
outgoing.to_node = d.outgoing.to_node
|
||||||
|
outgoing.to_port = d.outgoing.to_port
|
||||||
|
|
||||||
|
@warning_ignore("shadowed_variable")
|
||||||
|
var incoming := IncomingConnection.new()
|
||||||
|
incoming.from_node = d.incoming.from_node
|
||||||
|
incoming.from_port = d.incoming.from_port
|
||||||
|
|
||||||
|
outgoing.counterpart = weakref(incoming)
|
||||||
|
incoming.counterpart = weakref(outgoing)
|
||||||
|
|
||||||
|
return from_incoming(incoming)
|
||||||
|
|
||||||
|
|
||||||
|
class IncomingConnection:
|
||||||
|
var from_node: String
|
||||||
|
var from_port: int
|
||||||
|
|
||||||
|
var counterpart: WeakRef # OutgoingConnection
|
||||||
|
|
||||||
|
|
||||||
|
func _to_string() -> String:
|
||||||
|
return str({"from_node": from_node, "from_port": from_port})
|
||||||
|
|
||||||
|
|
||||||
|
func to_dict() -> Dictionary:
|
||||||
|
return {"from_node": from_node, "from_port": from_port}
|
||||||
|
|
||||||
|
|
||||||
|
class OutgoingConnection:
|
||||||
|
var to_node: String
|
||||||
|
var to_port: int
|
||||||
|
|
||||||
|
var counterpart: WeakRef # IncomingConnection
|
||||||
|
|
||||||
|
|
||||||
|
func _to_string() -> String:
|
||||||
|
return str({"to_node": to_node, "to_port": to_port})
|
||||||
|
|
||||||
|
|
||||||
|
func to_dict() -> Dictionary:
|
||||||
|
return {"to_node": to_node, "to_port": to_port}
|
||||||
|
|
|
@ -14,6 +14,10 @@ static var groups_emitted: Array[String]
|
||||||
static var logger := Logger.new()
|
static var logger := Logger.new()
|
||||||
static var signals := Signals.new()
|
static var signals := Signals.new()
|
||||||
|
|
||||||
|
enum Compat {
|
||||||
|
CONNECTIONS_IN_DECK = 1 << 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static func _static_init() -> void:
|
static func _static_init() -> void:
|
||||||
signals.deck_added.connect(RPCSignalLayer._on_deck_added)
|
signals.deck_added.connect(RPCSignalLayer._on_deck_added)
|
||||||
|
@ -31,6 +35,28 @@ static func add_empty_deck() -> Deck:
|
||||||
return deck
|
return deck
|
||||||
|
|
||||||
|
|
||||||
|
static func get_deck_compat(data: Dictionary) -> int:
|
||||||
|
var res := 0
|
||||||
|
|
||||||
|
if not data.deck.has("connections"):
|
||||||
|
res |= Compat.CONNECTIONS_IN_DECK
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
static func apply_compat_patches(data: Dictionary, compat: int) -> void:
|
||||||
|
if compat & Compat.CONNECTIONS_IN_DECK:
|
||||||
|
# convert pre-0.0.6 connections to be stored in the deck instead
|
||||||
|
var connections := Deck.NodeConnections.new()
|
||||||
|
for node: String in data.deck.nodes:
|
||||||
|
for from_port in data.deck.nodes[node].outgoing_connections:
|
||||||
|
for to_node: String in data.deck.nodes[node].outgoing_connections[from_port]:
|
||||||
|
for to_port: int in data.deck.nodes[node].outgoing_connections[from_port][to_node]:
|
||||||
|
connections.add_connection(node, to_node, int(from_port), to_port)
|
||||||
|
|
||||||
|
data.deck.connections = connections.to_dict()
|
||||||
|
|
||||||
|
|
||||||
## Opens a deck from the [param path].
|
## Opens a deck from the [param path].
|
||||||
static func open_deck_from_file(path: String) -> Deck:
|
static func open_deck_from_file(path: String) -> Deck:
|
||||||
var f := FileAccess.open(path, FileAccess.READ)
|
var f := FileAccess.open(path, FileAccess.READ)
|
||||||
|
@ -42,6 +68,8 @@ static func open_deck_from_file(path: String) -> Deck:
|
||||||
|
|
||||||
|
|
||||||
static func open_deck_from_dict(data: Dictionary, path := "") -> Deck:
|
static func open_deck_from_dict(data: Dictionary, path := "") -> Deck:
|
||||||
|
if get_deck_compat(data) != 0:
|
||||||
|
apply_compat_patches(data, get_deck_compat(data))
|
||||||
var deck := Deck.from_dict(data, path)
|
var deck := Deck.from_dict(data, path)
|
||||||
decks[deck.id] = deck
|
decks[deck.id] = deck
|
||||||
deck.connect_rpc_signals()
|
deck.connect_rpc_signals()
|
||||||
|
@ -72,7 +100,10 @@ static func add_group_from_dict(data: Dictionary, deck_id: String, instance_id:
|
||||||
static func make_new_group_instance(group_id: String, parent: String = "") -> Deck:
|
static func make_new_group_instance(group_id: String, parent: String = "") -> Deck:
|
||||||
var group := get_deck(group_id)
|
var group := get_deck(group_id)
|
||||||
var data := group.to_dict()
|
var data := group.to_dict()
|
||||||
return add_group_from_dict(data, group_id, UUID.v4(), parent)
|
var inst := add_group_from_dict(data, group_id, UUID.v4(), parent)
|
||||||
|
# copy connections
|
||||||
|
inst.connections = group.connections
|
||||||
|
return inst
|
||||||
|
|
||||||
|
|
||||||
static func make_group_instance_unique(group_id: String, instance_id: String, parent_deck_id: String, group_node_id: String) -> Deck:
|
static func make_group_instance_unique(group_id: String, instance_id: String, parent_deck_id: String, group_node_id: String) -> Deck:
|
||||||
|
@ -119,8 +150,6 @@ static func add_empty_group(parent: String = "") -> Deck:
|
||||||
static func connect_group_signals(group: Deck) -> void:
|
static func connect_group_signals(group: Deck) -> void:
|
||||||
group.node_added_to_group.connect(DeckHolder._on_node_added_to_group)
|
group.node_added_to_group.connect(DeckHolder._on_node_added_to_group)
|
||||||
group.node_removed_from_group.connect(DeckHolder._on_node_removed_from_group)
|
group.node_removed_from_group.connect(DeckHolder._on_node_removed_from_group)
|
||||||
group.nodes_connected_in_group.connect(DeckHolder._on_nodes_connected_in_group)
|
|
||||||
group.nodes_disconnected_in_group.connect(DeckHolder._on_nodes_disconnected_in_group)
|
|
||||||
group.node_port_value_updated.connect(DeckHolder._on_node_port_value_updated)
|
group.node_port_value_updated.connect(DeckHolder._on_node_port_value_updated)
|
||||||
group.node_renamed.connect(DeckHolder._on_node_renamed)
|
group.node_renamed.connect(DeckHolder._on_node_renamed)
|
||||||
group.node_moved.connect(DeckHolder._on_node_moved)
|
group.node_moved.connect(DeckHolder._on_node_moved)
|
||||||
|
@ -216,30 +245,6 @@ static func _on_node_removed_from_group(node_id: String, remove_connections: boo
|
||||||
instance.emit_group_signals = true
|
instance.emit_group_signals = true
|
||||||
|
|
||||||
|
|
||||||
static func _on_nodes_connected_in_group(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int, deck: Deck) -> void:
|
|
||||||
var group_id := deck.id
|
|
||||||
for instance_id: String in decks[group_id]:
|
|
||||||
if instance_id == deck.instance_id:
|
|
||||||
continue
|
|
||||||
|
|
||||||
var instance: Deck = get_group_instance(group_id, instance_id)
|
|
||||||
instance.emit_group_signals = false
|
|
||||||
instance.connect_nodes(from_node_id, to_node_id, from_output_port, to_input_port)
|
|
||||||
instance.emit_group_signals = true
|
|
||||||
|
|
||||||
|
|
||||||
static func _on_nodes_disconnected_in_group(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int, deck: Deck) -> void:
|
|
||||||
var group_id := deck.id
|
|
||||||
for instance_id: String in decks[group_id]:
|
|
||||||
if instance_id == deck.instance_id:
|
|
||||||
continue
|
|
||||||
|
|
||||||
var instance: Deck = get_group_instance(group_id, instance_id)
|
|
||||||
instance.emit_group_signals = false
|
|
||||||
instance.disconnect_nodes(from_node_id, to_node_id, from_output_port, to_input_port)
|
|
||||||
instance.emit_group_signals = true
|
|
||||||
|
|
||||||
|
|
||||||
static func _on_node_port_value_updated(node_id: String, port_idx: int, new_value: Variant, deck: Deck) -> void:
|
static func _on_node_port_value_updated(node_id: String, port_idx: int, new_value: Variant, deck: Deck) -> void:
|
||||||
var group_id := deck.id
|
var group_id := deck.id
|
||||||
for instance_id: String in decks[group_id]:
|
for instance_id: String in decks[group_id]:
|
||||||
|
|
|
@ -10,12 +10,6 @@ class_name DeckNode
|
||||||
## The name initially shown to a renderer.
|
## The name initially shown to a renderer.
|
||||||
var name: String
|
var name: String
|
||||||
|
|
||||||
## A map of outgoing connections from this node, in the format[br]
|
|
||||||
## [code]Dictionary[int -> output port, Dictionary[String -> DeckNode#_id, Array[int -> input port]]][/code]
|
|
||||||
var outgoing_connections: Dictionary
|
|
||||||
## A map of incoming connections to this node, in the format[br]
|
|
||||||
## [code]Dictionary[int -> input port, Dictionary[String -> DeckNode#_id, int -> output port][/code]
|
|
||||||
var incoming_connections: Dictionary
|
|
||||||
|
|
||||||
## A list of [Port]s on this node.
|
## A list of [Port]s on this node.
|
||||||
var ports: Array[Port]
|
var ports: Array[Port]
|
||||||
|
@ -127,23 +121,9 @@ func add_port(type: DeckType.Types,
|
||||||
return port
|
return port
|
||||||
|
|
||||||
|
|
||||||
## Remove a port from this node.
|
|
||||||
## @deprecated
|
|
||||||
func remove_port(port_idx: int) -> void:
|
|
||||||
outgoing_connections.erase(port_idx)
|
|
||||||
incoming_connections.erase(port_idx)
|
|
||||||
ports.remove_at(port_idx)
|
|
||||||
port_removed.emit(port_idx)
|
|
||||||
|
|
||||||
|
|
||||||
## Send data to all outgoing connections on port [param from_output_port].
|
## Send data to all outgoing connections on port [param from_output_port].
|
||||||
func send(from_output_port: int, data: Variant, send_id: String = UUID.v4()) -> void:
|
func send(from_output_port: int, data: Variant, send_id: String = UUID.v4()) -> void:
|
||||||
if outgoing_connections.get(from_output_port) == null:
|
_belonging_to.send(_id, from_output_port, data, send_id)
|
||||||
return
|
|
||||||
|
|
||||||
for node: String in outgoing_connections[from_output_port]:
|
|
||||||
for input_port: int in outgoing_connections[from_output_port][node]:
|
|
||||||
get_node(node).handle_receive(input_port, data, send_id)
|
|
||||||
|
|
||||||
|
|
||||||
func handle_receive(to_input_port: int, data: Variant, send_id: String) -> void:
|
func handle_receive(to_input_port: int, data: Variant, send_id: String) -> void:
|
||||||
|
@ -160,36 +140,11 @@ func _receive(to_input_port: int, data: Variant) -> void:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
## Add a connection from the output port at [param from_port] to [param to_node]'s input port
|
|
||||||
## at [param to_port].
|
|
||||||
func add_outgoing_connection(from_port: int, to_node: String, to_port: int) -> void:
|
|
||||||
var inner: Dictionary = outgoing_connections.get(from_port, {}) as Dictionary
|
|
||||||
var inner_ports: Array = inner.get(to_node, []) as Array
|
|
||||||
inner_ports.append(to_port)
|
|
||||||
inner[to_node] = inner_ports
|
|
||||||
outgoing_connections[from_port] = inner
|
|
||||||
get_node(to_node).add_incoming_connection(to_port, _id, from_port)
|
|
||||||
outgoing_connection_added.emit(from_port)
|
|
||||||
|
|
||||||
|
|
||||||
## Add an incoming connection from [param from_node]'s output port at [param from_port] to this node's
|
|
||||||
## input port at [param to_port].
|
|
||||||
func add_incoming_connection(to_port: int, from_node: String, from_port: int) -> void:
|
|
||||||
var connection := {from_node: from_port}
|
|
||||||
incoming_connections[to_port] = connection
|
|
||||||
incoming_connection_added.emit(to_port)
|
|
||||||
|
|
||||||
|
|
||||||
## Asynchronously request a value from an incoming connection on this node's input port at [param on_port].
|
## Asynchronously request a value from an incoming connection on this node's input port at [param on_port].
|
||||||
## Returns [code]null[/code] if no incoming connection exists on that port.
|
## Returns [code]null[/code] if no incoming connection exists on that port.
|
||||||
## The connected node may also return [code]null[/code].
|
## The connected node may also return [code]null[/code].
|
||||||
func request_value_async(on_port: int) -> Variant:
|
func request_value_async(on_port: int) -> Variant:
|
||||||
if not incoming_connections.has(on_port):
|
return await _belonging_to.request_value_async(_id, on_port)
|
||||||
return null
|
|
||||||
|
|
||||||
var connection: Dictionary = incoming_connections[on_port]
|
|
||||||
var node := get_node(connection.keys()[0])
|
|
||||||
return await node._value_request(connection.values()[0])
|
|
||||||
|
|
||||||
|
|
||||||
## Virtual function that's called when this node has been requested a value from the output port
|
## Virtual function that's called when this node has been requested a value from the output port
|
||||||
|
@ -199,52 +154,6 @@ func _value_request(from_port: int) -> Variant:
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
|
||||||
## Remove an outgoing connection from this node.
|
|
||||||
## Does [b]not[/b] remove the other node's incoming connection equivalent.
|
|
||||||
func remove_outgoing_connection(from_port: int, to_node: String, to_port: int) -> void:
|
|
||||||
var connections: Dictionary = outgoing_connections.get(from_port, {}) as Dictionary
|
|
||||||
if connections.is_empty():
|
|
||||||
return
|
|
||||||
|
|
||||||
var inner_ports: Array = connections.get(to_node, []) as Array
|
|
||||||
inner_ports.erase(to_port)
|
|
||||||
|
|
||||||
if inner_ports.is_empty():
|
|
||||||
(outgoing_connections[from_port] as Dictionary).erase(to_node)
|
|
||||||
if (outgoing_connections[from_port] as Dictionary).is_empty():
|
|
||||||
outgoing_connections.erase(from_port)
|
|
||||||
|
|
||||||
outgoing_connection_removed.emit(from_port)
|
|
||||||
|
|
||||||
|
|
||||||
## Remove an incoming connection to this node on the input port at [param to_port].
|
|
||||||
## Does [b]not[/b] remove the other node's outgoing connection equivalent.
|
|
||||||
func remove_incoming_connection(to_port: int) -> void:
|
|
||||||
incoming_connections.erase(to_port)
|
|
||||||
incoming_connection_removed.emit(to_port)
|
|
||||||
|
|
||||||
|
|
||||||
## Returns [code]true[/code] if the exact connection from this node exists.
|
|
||||||
func has_outgoing_connection_exact(from_port: int, to_node: String, to_port: int) -> bool:
|
|
||||||
if not outgoing_connections.has(from_port):
|
|
||||||
return false
|
|
||||||
|
|
||||||
var connection: Dictionary = outgoing_connections[from_port]
|
|
||||||
if not connection.has(to_node):
|
|
||||||
return false
|
|
||||||
|
|
||||||
var connections_to_node: Array = connection[to_node]
|
|
||||||
if to_port not in connections_to_node:
|
|
||||||
return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
|
||||||
|
|
||||||
## Returns [code]true[/code] if the node has an incoming connection at input port [param on_port].
|
|
||||||
func has_incoming_connection(on_port: int) -> bool:
|
|
||||||
return incoming_connections.has(on_port)
|
|
||||||
|
|
||||||
|
|
||||||
func rename(new_name: String) -> void:
|
func rename(new_name: String) -> void:
|
||||||
name = new_name
|
name = new_name
|
||||||
renamed.emit(new_name)
|
renamed.emit(new_name)
|
||||||
|
@ -324,8 +233,8 @@ func get_node(uuid: String) -> DeckNode:
|
||||||
return _belonging_to.get_node(uuid)
|
return _belonging_to.get_node(uuid)
|
||||||
|
|
||||||
|
|
||||||
## Virtual function that's called during deserialization before connections are loaded in.
|
## Virtual function that's called during deserialization before connections are loaded in.[br]
|
||||||
func _pre_connection() -> void:
|
func _pre_port_load() -> void:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -357,8 +266,8 @@ func to_dict(with_meta: bool = true) -> Dictionary:
|
||||||
var d := {
|
var d := {
|
||||||
"_id": _id,
|
"_id": _id,
|
||||||
"name": name,
|
"name": name,
|
||||||
"outgoing_connections": outgoing_connections.duplicate(true),
|
#"outgoing_connections": outgoing_connections.duplicate(true),
|
||||||
"incoming_connections": incoming_connections.duplicate(true),
|
#"incoming_connections": incoming_connections.duplicate(true),
|
||||||
"props": {},
|
"props": {},
|
||||||
"node_type": node_type,
|
"node_type": node_type,
|
||||||
"port_values": [],
|
"port_values": [],
|
||||||
|
@ -389,22 +298,22 @@ static func from_dict(data: Dictionary) -> DeckNode:
|
||||||
for prop in data.props:
|
for prop in data.props:
|
||||||
node.set(prop, data.props[prop])
|
node.set(prop, data.props[prop])
|
||||||
|
|
||||||
node._pre_connection()
|
node._pre_port_load()
|
||||||
|
|
||||||
for from_port in data.outgoing_connections:
|
#for from_port in data.outgoing_connections:
|
||||||
var connection_data: Dictionary = data.outgoing_connections[from_port]
|
#var connection_data: Dictionary = data.outgoing_connections[from_port]
|
||||||
node.outgoing_connections[int(from_port)] = {}
|
#node.outgoing_connections[int(from_port)] = {}
|
||||||
for to_node in connection_data:
|
#for to_node in connection_data:
|
||||||
var input_ports: Array = connection_data[to_node]
|
#var input_ports: Array = connection_data[to_node]
|
||||||
node.outgoing_connections[int(from_port)][to_node] = []
|
#node.outgoing_connections[int(from_port)][to_node] = []
|
||||||
for to_input_port in input_ports:
|
#for to_input_port in input_ports:
|
||||||
node.outgoing_connections[int(from_port)][to_node].append(int(to_input_port))
|
#node.outgoing_connections[int(from_port)][to_node].append(int(to_input_port))
|
||||||
|
#
|
||||||
for to_port in data.incoming_connections:
|
#for to_port in data.incoming_connections:
|
||||||
var connection_data = data.incoming_connections[to_port]
|
#var connection_data = data.incoming_connections[to_port]
|
||||||
for connection in connection_data:
|
#for connection in connection_data:
|
||||||
connection_data[connection] = int(connection_data[connection])
|
#connection_data[connection] = int(connection_data[connection])
|
||||||
node.incoming_connections[int(to_port)] = connection_data
|
#node.incoming_connections[int(to_port)] = connection_data
|
||||||
|
|
||||||
for i in node.ports.size():
|
for i in node.ports.size():
|
||||||
var port_value: Variant
|
var port_value: Variant
|
||||||
|
|
|
@ -37,13 +37,10 @@ func _on_outgoing_connection_added(port_idx: int) -> void:
|
||||||
|
|
||||||
func _on_outgoing_connection_removed(port_idx: int) -> void:
|
func _on_outgoing_connection_removed(port_idx: int) -> void:
|
||||||
var last_connected_port := 0
|
var last_connected_port := 0
|
||||||
#for port: int in outgoing_connections.keys().slice(1):
|
var outgoing_connections = _belonging_to.connections.get_all_outgoing_connections(_id)
|
||||||
#if !(outgoing_connections[port] as Array).is_empty():
|
for port: int in outgoing_connections:
|
||||||
#last_connected_port = port
|
if not (outgoing_connections[port] as Array).is_empty():
|
||||||
for port: int in outgoing_connections.keys().slice(1):
|
|
||||||
if not (outgoing_connections.get(port, {}) as Dictionary).is_empty():
|
|
||||||
last_connected_port = port
|
last_connected_port = port
|
||||||
|
|
||||||
#prints("l:", last_connected_port, "p:", port_idx)
|
#prints("l:", last_connected_port, "p:", port_idx)
|
||||||
|
|
||||||
if port_idx < last_connected_port:
|
if port_idx < last_connected_port:
|
||||||
|
@ -54,7 +51,7 @@ func _on_outgoing_connection_removed(port_idx: int) -> void:
|
||||||
ports_updated.emit()
|
ports_updated.emit()
|
||||||
|
|
||||||
|
|
||||||
func _pre_connection() -> void:
|
func _pre_port_load() -> void:
|
||||||
for i in output_count + 1:
|
for i in output_count + 1:
|
||||||
add_output_port(
|
add_output_port(
|
||||||
DeckType.Types.ANY,
|
DeckType.Types.ANY,
|
||||||
|
@ -65,6 +62,7 @@ func _pre_connection() -> void:
|
||||||
func _post_load() -> void:
|
func _post_load() -> void:
|
||||||
# ensure we have enough ports after connections
|
# ensure we have enough ports after connections
|
||||||
var last_connected_port := 0
|
var last_connected_port := 0
|
||||||
|
var outgoing_connections = _belonging_to.connections.get_all_outgoing_connections(_id)
|
||||||
for port: int in outgoing_connections:
|
for port: int in outgoing_connections:
|
||||||
last_connected_port = port if outgoing_connections.has(port) else last_connected_port
|
last_connected_port = port if outgoing_connections.has(port) else last_connected_port
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ func _init() -> void:
|
||||||
appears_in_search = false
|
appears_in_search = false
|
||||||
|
|
||||||
|
|
||||||
func _pre_connection() -> void:
|
func _pre_port_load() -> void:
|
||||||
for port_type: PortType in extra_ports:
|
for port_type: PortType in extra_ports:
|
||||||
match port_type:
|
match port_type:
|
||||||
PortType.OUTPUT:
|
PortType.OUTPUT:
|
||||||
|
|
|
@ -38,9 +38,9 @@ func _on_incoming_connection_added(port_idx: int) -> void:
|
||||||
|
|
||||||
func _on_incoming_connection_removed(port_idx: int) -> void:
|
func _on_incoming_connection_removed(port_idx: int) -> void:
|
||||||
var last_connected_port := 0
|
var last_connected_port := 0
|
||||||
for port: int in incoming_connections.keys().slice(1):
|
var incoming_connections := _belonging_to.connections.get_all_incoming_connections(_id)
|
||||||
if not (incoming_connections[port] as Dictionary).is_empty():
|
if not incoming_connections.is_empty():
|
||||||
last_connected_port = port
|
last_connected_port = incoming_connections.keys()[-1]
|
||||||
|
|
||||||
#prints("l:", last_connected_port, "p:", port_idx)
|
#prints("l:", last_connected_port, "p:", port_idx)
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ func _on_incoming_connection_removed(port_idx: int) -> void:
|
||||||
ports_updated.emit()
|
ports_updated.emit()
|
||||||
|
|
||||||
|
|
||||||
func _pre_connection() -> void:
|
func _pre_port_load() -> void:
|
||||||
for i in input_count + 1:
|
for i in input_count + 1:
|
||||||
add_input_port(
|
add_input_port(
|
||||||
DeckType.Types.ANY,
|
DeckType.Types.ANY,
|
||||||
|
@ -63,6 +63,7 @@ func _pre_connection() -> void:
|
||||||
func _post_load() -> void:
|
func _post_load() -> void:
|
||||||
# ensure we have enough ports after connections
|
# ensure we have enough ports after connections
|
||||||
var last_connected_port := 0
|
var last_connected_port := 0
|
||||||
|
var incoming_connections := _belonging_to.connections.get_all_incoming_connections(_id)
|
||||||
for port: int in incoming_connections:
|
for port: int in incoming_connections:
|
||||||
last_connected_port = port if incoming_connections.has(port) else last_connected_port
|
last_connected_port = port if incoming_connections.has(port) else last_connected_port
|
||||||
|
|
||||||
|
|
18
graph_node_renderer/compat_dialog.tscn
Normal file
18
graph_node_renderer/compat_dialog.tscn
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
[gd_scene format=3 uid="uid://cd1t0gvi022gx"]
|
||||||
|
|
||||||
|
[node name="CompatDialog" type="ConfirmationDialog"]
|
||||||
|
initial_position = 1
|
||||||
|
size = Vector2i(440, 175)
|
||||||
|
ok_button_text = "Open"
|
||||||
|
dialog_autowrap = true
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="."]
|
||||||
|
offset_left = 8.0
|
||||||
|
offset_top = 8.0
|
||||||
|
offset_right = 432.0
|
||||||
|
offset_bottom = 129.0
|
||||||
|
text = "Warning: This deck was last saved with an earlier version of StreamGraph.
|
||||||
|
|
||||||
|
Open anyway? The file will be modified, and opening it in the version it was saved with may lead to errors."
|
||||||
|
horizontal_alignment = 1
|
||||||
|
autowrap_mode = 2
|
|
@ -77,6 +77,8 @@ var _deck_to_save: WeakRef
|
||||||
@onready var sidebar_split: HSplitContainer = %SidebarSplit
|
@onready var sidebar_split: HSplitContainer = %SidebarSplit
|
||||||
@onready var sidebar: Sidebar = %Sidebar as Sidebar
|
@onready var sidebar: Sidebar = %Sidebar as Sidebar
|
||||||
|
|
||||||
|
@onready var compat_dialog: ConfirmationDialog = %CompatDialog
|
||||||
|
|
||||||
signal quit_completed()
|
signal quit_completed()
|
||||||
signal rpc_start_requested(port: int)
|
signal rpc_start_requested(port: int)
|
||||||
signal rpc_stop_requested()
|
signal rpc_stop_requested()
|
||||||
|
@ -330,6 +332,7 @@ func close_tab(tab: int) -> void:
|
||||||
if tab_container.get_tab_count() == 0:
|
if tab_container.get_tab_count() == 0:
|
||||||
bottom_dock.variable_viewer.disable_new_button()
|
bottom_dock.variable_viewer.disable_new_button()
|
||||||
|
|
||||||
|
|
||||||
## Opens [member file_dialog] with the mode [member FileDialog.FILE_MODE_SAVE_FILE]
|
## Opens [member file_dialog] with the mode [member FileDialog.FILE_MODE_SAVE_FILE]
|
||||||
## as well as getting a weakref to the active [Deck]
|
## as well as getting a weakref to the active [Deck]
|
||||||
func open_save_dialog(path: String) -> void:
|
func open_save_dialog(path: String) -> void:
|
||||||
|
@ -340,14 +343,20 @@ func open_save_dialog(path: String) -> void:
|
||||||
file_dialog.popup_centered()
|
file_dialog.popup_centered()
|
||||||
file_dialog.file_selected.connect(_on_file_dialog_save_file, CONNECT_ONE_SHOT)
|
file_dialog.file_selected.connect(_on_file_dialog_save_file, CONNECT_ONE_SHOT)
|
||||||
|
|
||||||
|
|
||||||
## Opens [member file_dialog] with the mode [FileDialog.FILE_MODE_OPEN_FILES]
|
## Opens [member file_dialog] with the mode [FileDialog.FILE_MODE_OPEN_FILES]
|
||||||
## with the supplied [param path]
|
## with the supplied [param path]
|
||||||
func open_open_dialog(path: String) -> void:
|
func open_open_dialog(path: String) -> void:
|
||||||
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILES
|
#file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILES
|
||||||
file_dialog.title = "Open Deck(s)"
|
# TODO: disabled opening multiple for now until better compat dialog method is found
|
||||||
|
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
|
||||||
|
#file_dialog.title = "Open Deck(s)"
|
||||||
|
file_dialog.title = "Open Deck"
|
||||||
file_dialog.current_path = path + "/"
|
file_dialog.current_path = path + "/"
|
||||||
file_dialog.popup_centered()
|
file_dialog.popup_centered()
|
||||||
file_dialog.files_selected.connect(_on_file_dialog_open_files, CONNECT_ONE_SHOT)
|
#file_dialog.files_selected.connect(_on_file_dialog_open_files, CONNECT_ONE_SHOT)
|
||||||
|
file_dialog.file_selected.connect(open_deck_at_path, CONNECT_ONE_SHOT)
|
||||||
|
|
||||||
|
|
||||||
## Connected to [signal FileDialog.save_file] on [member file_dialog].
|
## Connected to [signal FileDialog.save_file] on [member file_dialog].
|
||||||
## Saves the selected [Deck] if it still exists.
|
## Saves the selected [Deck] if it still exists.
|
||||||
|
@ -382,7 +391,22 @@ func open_deck_at_path(path: String) -> void:
|
||||||
tab_container.set_current_tab(tab)
|
tab_container.set_current_tab(tab)
|
||||||
return
|
return
|
||||||
|
|
||||||
var deck := DeckHolder.open_deck_from_file(path)
|
var f := FileAccess.open(path, FileAccess.READ)
|
||||||
|
if f.get_error() != OK:
|
||||||
|
return
|
||||||
|
|
||||||
|
var deck_data: Dictionary = JSON.parse_string(f.get_as_text())
|
||||||
|
if DeckHolder.get_deck_compat(deck_data) != 0:
|
||||||
|
compat_dialog.set_meta(&"path", path)
|
||||||
|
file_dialog.hide()
|
||||||
|
compat_dialog.popup_centered()
|
||||||
|
return
|
||||||
|
|
||||||
|
open_deck_from_dict(deck_data, path)
|
||||||
|
|
||||||
|
|
||||||
|
func open_deck_from_dict(data: Dictionary, path: String) -> void:
|
||||||
|
var deck := DeckHolder.open_deck_from_dict(data, path)
|
||||||
var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
||||||
inst.deck = deck
|
inst.deck = deck
|
||||||
var tab := tab_container.add_content(inst, path.get_file())
|
var tab := tab_container.add_content(inst, path.get_file())
|
||||||
|
@ -451,6 +475,10 @@ func disconnect_file_dialog_signals() -> void:
|
||||||
if file_dialog.files_selected.is_connected(_on_file_dialog_open_files):
|
if file_dialog.files_selected.is_connected(_on_file_dialog_open_files):
|
||||||
file_dialog.files_selected.disconnect(_on_file_dialog_open_files)
|
file_dialog.files_selected.disconnect(_on_file_dialog_open_files)
|
||||||
|
|
||||||
|
if file_dialog.file_selected.is_connected(open_deck_at_path):
|
||||||
|
file_dialog.file_selected.disconnect(open_deck_at_path)
|
||||||
|
|
||||||
|
|
||||||
## Connected to [signal DeckRenderGraphEdit.group_entered_request] to allow entering
|
## Connected to [signal DeckRenderGraphEdit.group_entered_request] to allow entering
|
||||||
## groups based off the given [param group_id] and [param deck]. As well as adding
|
## groups based off the given [param group_id] and [param deck]. As well as adding
|
||||||
## a corresponding tab to [member tab_container]
|
## a corresponding tab to [member tab_container]
|
||||||
|
@ -652,3 +680,19 @@ func _on_help_id_pressed(id: int) -> void:
|
||||||
HelpMenuId.DOCS:
|
HelpMenuId.DOCS:
|
||||||
OS.shell_open("https://codeberg.org/Eroax/StreamGraph/wiki")
|
OS.shell_open("https://codeberg.org/Eroax/StreamGraph/wiki")
|
||||||
|
|
||||||
|
|
||||||
|
func _on_compat_dialog_confirmed() -> void:
|
||||||
|
var path: String = compat_dialog.get_meta(&"path", "")
|
||||||
|
var f := FileAccess.open(path, FileAccess.READ)
|
||||||
|
if f.get_error() != OK:
|
||||||
|
return
|
||||||
|
|
||||||
|
# save a backup
|
||||||
|
if path.split(".")[-2] != "old":
|
||||||
|
var backup_path := "%s.old.deck" % path.trim_suffix(".deck")
|
||||||
|
DirAccess.copy_absolute(path, backup_path)
|
||||||
|
|
||||||
|
var deck_data: Dictionary = JSON.parse_string(f.get_as_text())
|
||||||
|
open_deck_from_dict(deck_data, path)
|
||||||
|
# set it as dirty to make sure the user resaves
|
||||||
|
get_active_deck_renderer().dirty = true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=17 format=3 uid="uid://duaah5x0jhkn6"]
|
[gd_scene load_steps=18 format=3 uid="uid://duaah5x0jhkn6"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://graph_node_renderer/deck_holder_renderer.gd" id="1_67g2g"]
|
[ext_resource type="Script" path="res://graph_node_renderer/deck_holder_renderer.gd" id="1_67g2g"]
|
||||||
[ext_resource type="PackedScene" uid="uid://b84f2ngtcm5b8" path="res://graph_node_renderer/tab_container_custom.tscn" id="1_s3ug2"]
|
[ext_resource type="PackedScene" uid="uid://b84f2ngtcm5b8" path="res://graph_node_renderer/tab_container_custom.tscn" id="1_s3ug2"]
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
[ext_resource type="PackedScene" uid="uid://bu466w2w3q08c" path="res://graph_node_renderer/about_dialog.tscn" id="11_6ln7n"]
|
[ext_resource type="PackedScene" uid="uid://bu466w2w3q08c" path="res://graph_node_renderer/about_dialog.tscn" id="11_6ln7n"]
|
||||||
[ext_resource type="PackedScene" uid="uid://brfrufvkjwcor" path="res://graph_node_renderer/rpc_setup_dialog.tscn" id="12_1xrfk"]
|
[ext_resource type="PackedScene" uid="uid://brfrufvkjwcor" path="res://graph_node_renderer/rpc_setup_dialog.tscn" id="12_1xrfk"]
|
||||||
[ext_resource type="PackedScene" uid="uid://dodqetbke5wji" path="res://graph_node_renderer/settings_dialog.tscn" id="16_rktri"]
|
[ext_resource type="PackedScene" uid="uid://dodqetbke5wji" path="res://graph_node_renderer/settings_dialog.tscn" id="16_rktri"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cd1t0gvi022gx" path="res://graph_node_renderer/compat_dialog.tscn" id="17_2ndnq"]
|
||||||
|
|
||||||
[node name="DeckHolderRenderer" type="Control"]
|
[node name="DeckHolderRenderer" type="Control"]
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
|
@ -170,6 +171,9 @@ unique_name_in_owner = true
|
||||||
[node name="SettingsDialog" parent="." instance=ExtResource("16_rktri")]
|
[node name="SettingsDialog" parent="." instance=ExtResource("16_rktri")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|
||||||
|
[node name="CompatDialog" parent="." instance=ExtResource("17_2ndnq")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
|
||||||
[connection signal="id_pressed" from="MarginContainer/SidebarSplit/BottomSplit/VBoxContainer/MenuBar/File" to="." method="_on_file_id_pressed"]
|
[connection signal="id_pressed" from="MarginContainer/SidebarSplit/BottomSplit/VBoxContainer/MenuBar/File" to="." method="_on_file_id_pressed"]
|
||||||
[connection signal="about_to_popup" from="MarginContainer/SidebarSplit/BottomSplit/VBoxContainer/MenuBar/Edit" to="." method="_on_edit_about_to_popup"]
|
[connection signal="about_to_popup" from="MarginContainer/SidebarSplit/BottomSplit/VBoxContainer/MenuBar/Edit" to="." method="_on_edit_about_to_popup"]
|
||||||
[connection signal="id_pressed" from="MarginContainer/SidebarSplit/BottomSplit/VBoxContainer/MenuBar/Edit" to="." method="_on_edit_id_pressed"]
|
[connection signal="id_pressed" from="MarginContainer/SidebarSplit/BottomSplit/VBoxContainer/MenuBar/Edit" to="." method="_on_edit_id_pressed"]
|
||||||
|
@ -180,3 +184,4 @@ unique_name_in_owner = true
|
||||||
[connection signal="confirmed" from="UnsavedChangesDialogSingleDeck" to="." method="_on_unsaved_changes_dialog_single_deck_confirmed"]
|
[connection signal="confirmed" from="UnsavedChangesDialogSingleDeck" to="." method="_on_unsaved_changes_dialog_single_deck_confirmed"]
|
||||||
[connection signal="custom_action" from="UnsavedChangesDialogSingleDeck" to="." method="_on_unsaved_changes_dialog_single_deck_custom_action"]
|
[connection signal="custom_action" from="UnsavedChangesDialogSingleDeck" to="." method="_on_unsaved_changes_dialog_single_deck_custom_action"]
|
||||||
[connection signal="confirmed" from="UnsavedChangesDialog" to="." method="_on_unsaved_changes_dialog_confirmed"]
|
[connection signal="confirmed" from="UnsavedChangesDialog" to="." method="_on_unsaved_changes_dialog_confirmed"]
|
||||||
|
[connection signal="confirmed" from="CompatDialog" to="." method="_on_compat_dialog_confirmed"]
|
||||||
|
|
|
@ -119,11 +119,7 @@ func attempt_disconnect(from_node_name: StringName, from_port: int, to_node_name
|
||||||
## Returns the associated [DeckNodeRendererGraphNode] for the supplied [DeckNode].
|
## Returns the associated [DeckNodeRendererGraphNode] for the supplied [DeckNode].
|
||||||
## Or [code]null[/code] if none is found.
|
## Or [code]null[/code] if none is found.
|
||||||
func get_node_renderer(node: DeckNode) -> DeckNodeRendererGraphNode:
|
func get_node_renderer(node: DeckNode) -> DeckNodeRendererGraphNode:
|
||||||
for i: DeckNodeRendererGraphNode in get_children():
|
return get_node_or_null(NodePath(node._id))
|
||||||
if i.node == node:
|
|
||||||
return i
|
|
||||||
|
|
||||||
return null
|
|
||||||
|
|
||||||
|
|
||||||
func focus_node(node: DeckNodeRendererGraphNode) -> void:
|
func focus_node(node: DeckNodeRendererGraphNode) -> void:
|
||||||
|
@ -162,7 +158,8 @@ func initialize_from_deck() -> void:
|
||||||
is_group = deck.is_group
|
is_group = deck.is_group
|
||||||
for node_id in deck.nodes:
|
for node_id in deck.nodes:
|
||||||
var node_renderer: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
var node_renderer: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
||||||
node_renderer.node = deck.nodes[node_id]
|
node_renderer.node = deck.get_node(node_id)
|
||||||
|
node_renderer.name = node_id
|
||||||
add_child(node_renderer)
|
add_child(node_renderer)
|
||||||
node_renderer.position_offset = node_renderer.node.position_as_vector2()
|
node_renderer.position_offset = node_renderer.node.position_as_vector2()
|
||||||
change_dirty = true
|
change_dirty = true
|
||||||
|
@ -178,28 +175,15 @@ func initialize_from_deck() -> void:
|
||||||
## [method GraphEdit.connect_node] for all the connections that exist in each
|
## [method GraphEdit.connect_node] for all the connections that exist in each
|
||||||
func refresh_connections() -> void:
|
func refresh_connections() -> void:
|
||||||
for node_id in deck.nodes:
|
for node_id in deck.nodes:
|
||||||
var node: DeckNode = deck.nodes[node_id]
|
if not deck.get_connections_dict().has(node_id):
|
||||||
var from_node: DeckNodeRendererGraphNode = get_children().filter(
|
continue
|
||||||
func(c: DeckNodeRendererGraphNode):
|
for from_port: int in deck.get_connections_dict()[node_id].outgoing:
|
||||||
return c.node._id == node_id
|
for outgoing: Deck.OutgoingConnection in deck.get_connections_dict()[node_id].outgoing[from_port]:
|
||||||
)[0]
|
|
||||||
|
|
||||||
for from_port in node.outgoing_connections:
|
|
||||||
for to_node_id: String in node.outgoing_connections[from_port]:
|
|
||||||
var to_node_ports = node.outgoing_connections[from_port][to_node_id]
|
|
||||||
var renderer: Array = get_children().filter(
|
|
||||||
func(c: DeckNodeRendererGraphNode):
|
|
||||||
return c.node._id == to_node_id
|
|
||||||
)
|
|
||||||
if renderer.is_empty():
|
|
||||||
break
|
|
||||||
var to_node: DeckNodeRendererGraphNode = renderer[0]
|
|
||||||
for to_node_port: int in to_node_ports:
|
|
||||||
connect_node(
|
connect_node(
|
||||||
from_node.name,
|
node_id,
|
||||||
from_port,
|
from_port,
|
||||||
to_node.name,
|
outgoing.to_node,
|
||||||
to_node_port
|
outgoing.to_port
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,6 +192,7 @@ func refresh_connections() -> void:
|
||||||
func _on_deck_node_added(node: DeckNode) -> void:
|
func _on_deck_node_added(node: DeckNode) -> void:
|
||||||
var inst: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
var inst: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
||||||
inst.node = node
|
inst.node = node
|
||||||
|
inst.name = node._id
|
||||||
add_child(inst)
|
add_child(inst)
|
||||||
inst.position_offset = inst.node.position_as_vector2()
|
inst.position_offset = inst.node.position_as_vector2()
|
||||||
dirty = true
|
dirty = true
|
||||||
|
@ -236,8 +221,6 @@ func get_selected_nodes() -> Array:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
## Executes functionality based off hotkey inputs. Specifically handles creating groups
|
|
||||||
## based off the action "group_nodes".
|
|
||||||
func _gui_input(event: InputEvent) -> void:
|
func _gui_input(event: InputEvent) -> void:
|
||||||
if RendererShortcuts.check_shortcut("group_nodes", event) and get_selected_nodes().size() > 0:
|
if RendererShortcuts.check_shortcut("group_nodes", event) and get_selected_nodes().size() > 0:
|
||||||
clear_connections()
|
clear_connections()
|
||||||
|
@ -293,8 +276,6 @@ func _gui_input(event: InputEvent) -> void:
|
||||||
focus_selection()
|
focus_selection()
|
||||||
|
|
||||||
|
|
||||||
## Handles entering groups with action "enter_group". Done here to bypass neighbor
|
|
||||||
## functionality.
|
|
||||||
func _input(event: InputEvent) -> void:
|
func _input(event: InputEvent) -> void:
|
||||||
if not has_focus():
|
if not has_focus():
|
||||||
return
|
return
|
||||||
|
@ -343,7 +324,6 @@ func _on_add_node_menu_node_selected(type: String) -> void:
|
||||||
|
|
||||||
|
|
||||||
func _on_deck_nodes_disconnected(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> void:
|
func _on_deck_nodes_disconnected(from_node_id: String, to_node_id: String, from_output_port: int, to_input_port: int) -> void:
|
||||||
print("1")
|
|
||||||
var from_node: DeckNodeRendererGraphNode = get_children().filter(
|
var from_node: DeckNodeRendererGraphNode = get_children().filter(
|
||||||
func(x: DeckNodeRendererGraphNode):
|
func(x: DeckNodeRendererGraphNode):
|
||||||
return x.node._id == from_node_id
|
return x.node._id == from_node_id
|
||||||
|
|
Loading…
Reference in a new issue