mirror of
https://codeberg.org/StreamGraph/StreamGraph.git
synced 2024-11-13 19:49:55 +01:00
add copying and pasting nodes
This commit is contained in:
parent
d3bf258ba9
commit
8520f240d0
4 changed files with 161 additions and 44 deletions
|
@ -59,6 +59,7 @@ func add_node_inst(node: DeckNode, assign_id: String = "", assign_to_self: bool
|
|||
node._id = uuid
|
||||
else:
|
||||
nodes[assign_id] = node
|
||||
node._id = assign_id
|
||||
|
||||
node_added.emit(node)
|
||||
|
||||
|
@ -197,6 +198,86 @@ func get_group(uuid: String) -> Deck:
|
|||
return groups.get(uuid)
|
||||
|
||||
|
||||
func copy_nodes_json(nodes_to_copy: Array[String]) -> String:
|
||||
var d := {"nodes": {}}
|
||||
|
||||
for node_id: String in nodes_to_copy:
|
||||
d.nodes[node_id] = get_node(node_id).to_dict()
|
||||
|
||||
for node: String in d.nodes:
|
||||
var outgoing_connections: Dictionary = d.nodes[node].outgoing_connections.duplicate(true)
|
||||
|
||||
for from_port: int in outgoing_connections:
|
||||
for to_node: String in outgoing_connections[from_port]:
|
||||
if !(to_node in nodes_to_copy):
|
||||
(d.nodes[node].outgoing_connections[from_port] as Dictionary).erase(to_node)
|
||||
|
||||
var incoming_connections: Dictionary = d.nodes[node].incoming_connections.duplicate(true)
|
||||
|
||||
for to_port: int in incoming_connections:
|
||||
for from_node: String in incoming_connections[to_port]:
|
||||
if !(from_node in nodes_to_copy):
|
||||
(d.nodes[node].incoming_connections[to_port] as Dictionary).erase(from_node)
|
||||
|
||||
for node: Dictionary in d.nodes.values().slice(1):
|
||||
node.position.x = node.position.x - d.nodes.values()[0].position.x
|
||||
node.position.y = node.position.y - d.nodes.values()[0].position.y
|
||||
|
||||
d.nodes.values()[0].position.x = 0
|
||||
d.nodes.values()[0].position.y = 0
|
||||
|
||||
return JSON.stringify(d)
|
||||
|
||||
|
||||
func allocate_ids(count: int) -> Array[String]:
|
||||
var res: Array[String]
|
||||
for i in count:
|
||||
res.append(UUID.v4())
|
||||
return res
|
||||
|
||||
|
||||
func paste_nodes_from_json(json: String, position: Vector2 = Vector2()) -> void:
|
||||
var d: Dictionary = JSON.parse_string(json) as Dictionary
|
||||
if !d.get("nodes"):
|
||||
return
|
||||
|
||||
var new_ids := allocate_ids(d.nodes.size())
|
||||
var ids_map := {}
|
||||
for i: int in d.nodes.keys().size():
|
||||
var node_id: String = d.nodes.keys()[i]
|
||||
ids_map[node_id] = new_ids[i]
|
||||
|
||||
var new_json := json
|
||||
for old_id: String in ids_map:
|
||||
new_json = new_json.replace(old_id, ids_map[old_id])
|
||||
|
||||
for node_id: String in d.nodes:
|
||||
d.nodes[node_id]._id = ids_map[node_id]
|
||||
|
||||
d.nodes[node_id].position.x += position.x
|
||||
d.nodes[node_id].position.y += position.y
|
||||
|
||||
var outgoing_connections: Dictionary = d.nodes[node_id].outgoing_connections as Dictionary
|
||||
var outgoing_connections_res := {}
|
||||
for from_port: String in outgoing_connections:
|
||||
outgoing_connections_res[from_port] = {}
|
||||
for to_node_id: String 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 = d.nodes[node_id].incoming_connections as Dictionary
|
||||
var incoming_connections_res := {}
|
||||
for to_port: String in incoming_connections:
|
||||
incoming_connections_res[to_port] = {}
|
||||
for from_node_id: String in incoming_connections[to_port]:
|
||||
incoming_connections_res[to_port][ids_map[from_node_id]] = incoming_connections[to_port][from_node_id]
|
||||
|
||||
d.nodes[node_id].outgoing_connections = outgoing_connections_res
|
||||
d.nodes[node_id].incoming_connections = incoming_connections_res
|
||||
|
||||
var node := DeckNode.from_dict(d.nodes[node_id])
|
||||
add_node_inst(node, ids_map[node_id])
|
||||
|
||||
|
||||
## Returns a [Dictionary] representation of this deck.
|
||||
func to_dict(with_meta: bool = true) -> Dictionary:
|
||||
var inner := {
|
||||
|
@ -239,44 +320,8 @@ static func from_dict(data: Dictionary, path: String = "") -> Deck:
|
|||
var nodes_data: Dictionary = data.deck.nodes as Dictionary
|
||||
|
||||
for node_id in nodes_data:
|
||||
var node := deck.add_node_type(nodes_data[node_id].node_type, node_id, false)
|
||||
node._id = node_id
|
||||
node.name = nodes_data[node_id].name
|
||||
node._belonging_to = deck
|
||||
node.position = nodes_data[node_id].position
|
||||
|
||||
for prop in nodes_data[node_id].props:
|
||||
node.set(prop, nodes_data[node_id].props[prop])
|
||||
|
||||
node._pre_connection()
|
||||
|
||||
for from_port: String in nodes_data[node_id].outgoing_connections:
|
||||
var connection_data: Dictionary = nodes_data[node_id].outgoing_connections[from_port]
|
||||
node.outgoing_connections[int(from_port)] = {}
|
||||
for to_node: String in connection_data:
|
||||
var input_ports: Array = connection_data[to_node]
|
||||
node.outgoing_connections[int(from_port)][to_node] = []
|
||||
for to_input_port in input_ports:
|
||||
node.outgoing_connections[int(from_port)][to_node].append(int(to_input_port))
|
||||
|
||||
for to_port: String in nodes_data[node_id].incoming_connections:
|
||||
var connection_data = nodes_data[node_id].incoming_connections[to_port]
|
||||
for connection in connection_data:
|
||||
connection_data[connection] = int(connection_data[connection])
|
||||
node.incoming_connections[int(to_port)] = connection_data
|
||||
|
||||
for i in node.ports.size():
|
||||
var port_value: Variant
|
||||
if (nodes_data[node_id].port_values as Array).size() <= i:
|
||||
port_value = null
|
||||
else:
|
||||
port_value = (nodes_data[node_id].port_values as Array)[i]
|
||||
node.ports[i].value = port_value
|
||||
|
||||
for key in nodes_data[node_id].meta:
|
||||
node.set_meta(key, str_to_var(nodes_data[node_id].meta[key]))
|
||||
|
||||
node._post_load()
|
||||
var node := DeckNode.from_dict(nodes_data[node_id])
|
||||
deck.add_node_inst(node, node_id)
|
||||
|
||||
var groups_data: Dictionary = data.deck.groups as Dictionary
|
||||
|
||||
|
|
|
@ -250,12 +250,12 @@ func to_dict(with_meta: bool = true) -> Dictionary:
|
|||
var d := {
|
||||
"_id": _id,
|
||||
"name": name,
|
||||
"outgoing_connections": outgoing_connections,
|
||||
"incoming_connections": incoming_connections,
|
||||
"outgoing_connections": outgoing_connections.duplicate(true),
|
||||
"incoming_connections": incoming_connections.duplicate(true),
|
||||
"props": {},
|
||||
"node_type": node_type,
|
||||
"port_values": [],
|
||||
"position": position,
|
||||
"position": position.duplicate(),
|
||||
}
|
||||
|
||||
for prop in props_to_serialize:
|
||||
|
@ -273,6 +273,48 @@ func to_dict(with_meta: bool = true) -> Dictionary:
|
|||
return d
|
||||
|
||||
|
||||
static func from_dict(data: Dictionary) -> DeckNode:
|
||||
var node := NodeDB.instance_node(data.node_type)
|
||||
#node._id = data._id
|
||||
node.name = data.name
|
||||
node.position = data.position
|
||||
|
||||
for prop in data.props:
|
||||
node.set(prop, data.props[prop])
|
||||
|
||||
node._pre_connection()
|
||||
|
||||
for from_port: String in data.outgoing_connections:
|
||||
var connection_data: Dictionary = data.outgoing_connections[from_port]
|
||||
node.outgoing_connections[int(from_port)] = {}
|
||||
for to_node: String in connection_data:
|
||||
var input_ports: Array = connection_data[to_node]
|
||||
node.outgoing_connections[int(from_port)][to_node] = []
|
||||
for to_input_port in input_ports:
|
||||
node.outgoing_connections[int(from_port)][to_node].append(int(to_input_port))
|
||||
|
||||
for to_port: String in data.incoming_connections:
|
||||
var connection_data = data.incoming_connections[to_port]
|
||||
for connection in connection_data:
|
||||
connection_data[connection] = int(connection_data[connection])
|
||||
node.incoming_connections[int(to_port)] = connection_data
|
||||
|
||||
for i in node.ports.size():
|
||||
var port_value: Variant
|
||||
if (data.port_values as Array).size() <= i:
|
||||
port_value = null
|
||||
else:
|
||||
port_value = (data.port_values as Array)[i]
|
||||
node.ports[i].value = port_value
|
||||
|
||||
for key in data.meta:
|
||||
node.set_meta(key, str_to_var(data.meta[key]))
|
||||
|
||||
node._post_load()
|
||||
|
||||
return node
|
||||
|
||||
|
||||
## Returns the node's [member position] as a [Vector2].
|
||||
func position_as_vector2() -> Vector2:
|
||||
return Vector2(position.x, position.y)
|
||||
|
|
|
@ -129,10 +129,13 @@ func refresh_connections() -> void:
|
|||
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 to_node: DeckNodeRendererGraphNode = get_children().filter(
|
||||
var renderer: Array = get_children().filter(
|
||||
func(c: DeckNodeRendererGraphNode):
|
||||
return c.node._id == to_node_id
|
||||
)[0]
|
||||
)
|
||||
if renderer.is_empty():
|
||||
break
|
||||
var to_node: DeckNodeRendererGraphNode = renderer[0]
|
||||
for to_node_port: int in to_node_ports:
|
||||
connect_node(
|
||||
from_node.name,
|
||||
|
@ -148,6 +151,8 @@ func _on_deck_node_added(node: DeckNode) -> void:
|
|||
inst.node = node
|
||||
add_child(inst)
|
||||
inst.position_offset = inst.node.position_as_vector2()
|
||||
clear_connections()
|
||||
refresh_connections()
|
||||
|
||||
## Connected to [signal Deck.node_added], used to remove the specified
|
||||
## [DeckNodeRendererGraphNode] and queue_free it.
|
||||
|
@ -229,5 +234,28 @@ func _on_delete_nodes_request(nodes: Array[StringName]) -> void:
|
|||
for node_id in node_ids:
|
||||
deck.remove_node(node_id, true)
|
||||
|
||||
#await get_tree().process_frame
|
||||
refresh_connections()
|
||||
|
||||
|
||||
func _on_copy_nodes_request() -> void:
|
||||
var selected := get_selected_nodes()
|
||||
if selected.is_empty():
|
||||
return
|
||||
|
||||
var selected_ids: Array[String]
|
||||
selected_ids.assign(selected.map(
|
||||
func(x: DeckNodeRendererGraphNode):
|
||||
return x.node._id
|
||||
))
|
||||
|
||||
DisplayServer.clipboard_set(deck.copy_nodes_json(selected_ids))
|
||||
|
||||
|
||||
func _on_paste_nodes_request() -> void:
|
||||
var clip := DisplayServer.clipboard_get()
|
||||
var node_pos := (get_local_mouse_position() + scroll_offset - (Vector2(75.0, 0.0) * zoom)) / zoom
|
||||
|
||||
if snapping_enabled:
|
||||
node_pos = node_pos.snapped(Vector2(snapping_distance, snapping_distance))
|
||||
|
||||
deck.paste_nodes_from_json(clip, node_pos)
|
||||
|
|
|
@ -12,6 +12,8 @@ right_disconnects = true
|
|||
show_arrange_button = false
|
||||
script = ExtResource("1_pojfs")
|
||||
|
||||
[connection signal="copy_nodes_request" from="." to="." method="_on_copy_nodes_request"]
|
||||
[connection signal="delete_nodes_request" from="." to="." method="_on_delete_nodes_request"]
|
||||
[connection signal="paste_nodes_request" from="." to="." method="_on_paste_nodes_request"]
|
||||
[connection signal="popup_request" from="." to="." method="_on_popup_request"]
|
||||
[connection signal="scroll_offset_changed" from="." to="." method="_on_scroll_offset_changed"]
|
||||
|
|
Loading…
Reference in a new issue