mirror of
https://codeberg.org/StreamGraph/StreamGraph.git
synced 2024-11-13 19:49:55 +01:00
merge groups (#2)
here we go Reviewed-on: https://codeberg.org/Eroax/Re-DotDeck/pulls/2 Co-authored-by: Lera Elvoé <yagich@poto.cafe> Co-committed-by: Lera Elvoé <yagich@poto.cafe>
This commit is contained in:
parent
b25f6ce6c7
commit
fa5e9997ef
19 changed files with 1109 additions and 181 deletions
|
@ -22,21 +22,24 @@ static var type_assoc: Dictionary = {
|
||||||
}
|
}
|
||||||
|
|
||||||
var variable_stack: Dictionary = {}
|
var variable_stack: Dictionary = {}
|
||||||
|
var save_path: String = ""
|
||||||
|
|
||||||
|
var is_group: bool = false
|
||||||
|
var groups: Dictionary = {} #Dictionary[String -> Deck.id, Deck]
|
||||||
|
var id: String = ""
|
||||||
|
var _belonging_to: Deck # for groups
|
||||||
|
var group_input_node: String
|
||||||
|
var group_output_node: String
|
||||||
|
var group_node: String
|
||||||
|
|
||||||
|
signal node_added(node: DeckNode)
|
||||||
|
signal node_removed(node: DeckNode)
|
||||||
|
|
||||||
|
|
||||||
func add_node(node: GDScript, meta: Dictionary = {}) -> DeckNode:
|
func add_node_type(type: String, assign_id: String = "", assign_to_self: bool = true) -> DeckNode:
|
||||||
# TODO: accept instances of DeckNode instead of instancing here?
|
var node_inst: DeckNode = NodeDB.instance_node(type)
|
||||||
var uuid := UUID.v4()
|
|
||||||
var node_inst: DeckNode = node.new() as DeckNode
|
|
||||||
nodes[uuid] = node_inst
|
|
||||||
node_inst._belonging_to = self
|
|
||||||
node_inst._id = uuid
|
|
||||||
|
|
||||||
if !meta.is_empty():
|
return add_node_inst(node_inst, assign_id, assign_to_self)
|
||||||
for k in meta:
|
|
||||||
node_inst.set_meta(k, meta[k])
|
|
||||||
|
|
||||||
return node_inst
|
|
||||||
|
|
||||||
|
|
||||||
func add_node_inst(node: DeckNode, assign_id: String = "", assign_to_self: bool = true) -> DeckNode:
|
func add_node_inst(node: DeckNode, assign_id: String = "", assign_to_self: bool = true) -> DeckNode:
|
||||||
|
@ -50,10 +53,7 @@ func add_node_inst(node: DeckNode, assign_id: String = "", assign_to_self: bool
|
||||||
else:
|
else:
|
||||||
nodes[assign_id] = node
|
nodes[assign_id] = node
|
||||||
|
|
||||||
|
node_added.emit(node)
|
||||||
# if !meta.is_empty():
|
|
||||||
# for k in meta:
|
|
||||||
# node.set_meta(k, meta[k])
|
|
||||||
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
@ -62,10 +62,10 @@ func get_node(uuid: String) -> DeckNode:
|
||||||
return nodes.get(uuid)
|
return nodes.get(uuid)
|
||||||
|
|
||||||
|
|
||||||
func connect_nodes(from_node: DeckNode, to_node: DeckNode, from_port: int, to_port: int) -> bool:
|
func connect_nodes(from_node: DeckNode, to_node: DeckNode, from_output_port: int, to_input_port: int) -> bool:
|
||||||
# first, check that we can do the type conversion.
|
# first, check that we can do the type conversion.
|
||||||
var type_a: Types = from_node.ports[from_port].type
|
var type_a: Types = from_node.get_output_ports()[from_output_port].type
|
||||||
var type_b: Types = to_node.ports[to_port].type
|
var type_b: Types = to_node.get_input_ports()[to_input_port].type
|
||||||
var err: DeckType = (type_assoc[type_b]).from(type_assoc[type_a].new())
|
var err: DeckType = (type_assoc[type_b]).from(type_assoc[type_a].new())
|
||||||
if err is DeckType.DeckTypeError:
|
if err is DeckType.DeckTypeError:
|
||||||
print(err.error_message)
|
print(err.error_message)
|
||||||
|
@ -73,32 +73,106 @@ func connect_nodes(from_node: DeckNode, to_node: DeckNode, from_port: int, to_po
|
||||||
|
|
||||||
# TODO: prevent duplicate connections
|
# TODO: prevent duplicate connections
|
||||||
|
|
||||||
from_node.add_outgoing_connection(from_port, to_node._id, to_port)
|
from_node.add_outgoing_connection(from_output_port, to_node._id, to_input_port)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
func disconnect_nodes(from_node: DeckNode, to_node: DeckNode, from_port: int, to_port: int) -> void:
|
func disconnect_nodes(from_node: DeckNode, to_node: DeckNode, from_output_port: int, to_input_port: int) -> void:
|
||||||
var hash = {to_node._id: to_port}.hash()
|
var hash = {to_node._id: to_input_port}.hash()
|
||||||
# prints({to_node._id: to_port}, "-", {to_node._id: to_port}.hash())
|
|
||||||
# prints(from_node.outgoing_connections[0][0], "-", from_node.outgoing_connections[0][0].hash())
|
|
||||||
#
|
|
||||||
# var a = {to_node._id: to_port}
|
|
||||||
# var b = from_node.outgoing_connections[0][0]
|
|
||||||
#
|
|
||||||
# print(typeof(a.values()[0]))
|
|
||||||
# print(typeof(b.values()[0]))
|
|
||||||
#
|
|
||||||
# prints(a, b)
|
|
||||||
|
|
||||||
from_node.remove_outgoing_connection(from_port, hash)
|
from_node.remove_outgoing_connection(from_output_port, hash)
|
||||||
to_node.remove_incoming_connection(to_port)
|
to_node.remove_incoming_connection(to_input_port)
|
||||||
|
|
||||||
|
|
||||||
func to_json(with_meta: bool = true) -> String:
|
func is_empty() -> bool:
|
||||||
var inner := {"nodes": {}, "variable_stack": variable_stack}
|
return nodes.is_empty() && variable_stack.is_empty()
|
||||||
|
|
||||||
for id in nodes.keys():
|
|
||||||
inner["nodes"][id] = nodes[id].to_dict(with_meta)
|
func remove_node(uuid: String) -> void:
|
||||||
|
var node = nodes.get(uuid)
|
||||||
|
nodes.erase(uuid)
|
||||||
|
|
||||||
|
node_removed.emit(node)
|
||||||
|
|
||||||
|
|
||||||
|
func group_nodes(nodes_to_group: Array) -> Deck:
|
||||||
|
if nodes_to_group.is_empty():
|
||||||
|
return null
|
||||||
|
|
||||||
|
var node_ids_to_keep := nodes_to_group.map(
|
||||||
|
func(x: DeckNode):
|
||||||
|
return x._id
|
||||||
|
)
|
||||||
|
|
||||||
|
var group := Deck.new()
|
||||||
|
group.is_group = true
|
||||||
|
group._belonging_to = self
|
||||||
|
var group_id := UUID.v4()
|
||||||
|
group.id = group_id
|
||||||
|
|
||||||
|
var midpoint := Vector2()
|
||||||
|
for node: DeckNode in nodes_to_group:
|
||||||
|
if node.node_type == "group_node": # for recursive grouping
|
||||||
|
var _group_id: String = node.group_id
|
||||||
|
var _group: Deck = groups[_group_id]
|
||||||
|
groups.erase(_group)
|
||||||
|
group.groups[_group_id] = _group
|
||||||
|
_group._belonging_to = group
|
||||||
|
|
||||||
|
for from_port: int in node.outgoing_connections:
|
||||||
|
for connection: Dictionary in node.outgoing_connections[from_port]:
|
||||||
|
if !(connection.keys()[0] in node_ids_to_keep):
|
||||||
|
disconnect_nodes(node, get_node(connection.keys()[0]), from_port, connection.values()[0])
|
||||||
|
|
||||||
|
midpoint += node.position_as_vector2()
|
||||||
|
remove_node(node._id)
|
||||||
|
group.add_node_inst(node, node._id)
|
||||||
|
|
||||||
|
midpoint /= nodes_to_group.size()
|
||||||
|
|
||||||
|
var _group_node := add_node_type("group_node")
|
||||||
|
_group_node.group_id = group_id
|
||||||
|
_group_node.position.x = midpoint.x
|
||||||
|
_group_node.position.y = midpoint.y
|
||||||
|
_group_node.position_updated.emit(_group_node.position)
|
||||||
|
group.group_node = _group_node._id
|
||||||
|
|
||||||
|
var input_node := group.add_node_type("group_input")
|
||||||
|
var output_node := group.add_node_type("group_output")
|
||||||
|
group.group_input_node = input_node._id
|
||||||
|
group.group_output_node = output_node._id
|
||||||
|
|
||||||
|
_group_node.input_node = input_node
|
||||||
|
_group_node.output_node = output_node
|
||||||
|
_group_node.setup_connections()
|
||||||
|
|
||||||
|
groups[group_id] = group
|
||||||
|
|
||||||
|
return group
|
||||||
|
|
||||||
|
|
||||||
|
func get_group(uuid: String) -> Deck:
|
||||||
|
return groups.get(uuid)
|
||||||
|
|
||||||
|
|
||||||
|
func to_dict(with_meta: bool = true) -> Dictionary:
|
||||||
|
var inner := {
|
||||||
|
"nodes": {},
|
||||||
|
"variable_stack": variable_stack,
|
||||||
|
"id": id,
|
||||||
|
"groups": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for node_id in nodes.keys():
|
||||||
|
inner["nodes"][node_id] = nodes[node_id].to_dict(with_meta)
|
||||||
|
|
||||||
|
for group_id in groups.keys():
|
||||||
|
inner["groups"][group_id] = groups[group_id].to_dict(with_meta)
|
||||||
|
|
||||||
|
if is_group:
|
||||||
|
inner["group_node"] = group_node
|
||||||
|
inner["group_input_node"] = group_input_node
|
||||||
|
inner["group_output_node"] = group_output_node
|
||||||
|
|
||||||
var d := {"deck": inner}
|
var d := {"deck": inner}
|
||||||
|
|
||||||
|
@ -106,14 +180,14 @@ func to_json(with_meta: bool = true) -> String:
|
||||||
d["meta"] = {}
|
d["meta"] = {}
|
||||||
for meta in get_meta_list():
|
for meta in get_meta_list():
|
||||||
d["meta"][meta] = var_to_str(get_meta(meta))
|
d["meta"][meta] = var_to_str(get_meta(meta))
|
||||||
return JSON.stringify(d, "\t", false)
|
return d
|
||||||
|
|
||||||
|
|
||||||
static func from_json(json: String) -> Deck:
|
static func from_dict(data: Dictionary, path: String = "") -> Deck:
|
||||||
var data: Dictionary = JSON.parse_string(json) as Dictionary
|
|
||||||
var deck := Deck.new()
|
var deck := Deck.new()
|
||||||
|
deck.save_path = path
|
||||||
deck.variable_stack = data.deck.variable_stack
|
deck.variable_stack = data.deck.variable_stack
|
||||||
|
deck.id = data.deck.id
|
||||||
|
|
||||||
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]))
|
||||||
|
@ -121,12 +195,17 @@ static func from_json(json: String) -> Deck:
|
||||||
var nodes_data: Dictionary = data.deck.nodes as Dictionary
|
var nodes_data: Dictionary = data.deck.nodes as Dictionary
|
||||||
|
|
||||||
for node_id in nodes_data:
|
for node_id in nodes_data:
|
||||||
var node := deck.add_node_inst(NodeDB.instance_node(nodes_data[node_id].node_type), node_id, false)
|
var node := deck.add_node_type(nodes_data[node_id].node_type, node_id, false)
|
||||||
node._id = node_id
|
node._id = node_id
|
||||||
node.name = nodes_data[node_id].name
|
node.name = nodes_data[node_id].name
|
||||||
node._belonging_to = deck
|
node._belonging_to = deck
|
||||||
# node.outgoing_connections = nodes_data[node_id].outgoing_connections
|
node.position = nodes_data[node_id].position
|
||||||
# node.incoming_connections = nodes_data[node_id].incoming_connections
|
|
||||||
|
for prop in nodes_data[node_id].props:
|
||||||
|
node.set(prop, nodes_data[node_id].props[prop])
|
||||||
|
|
||||||
|
node._pre_connection()
|
||||||
|
|
||||||
for connection_id in nodes_data[node_id].outgoing_connections:
|
for connection_id in nodes_data[node_id].outgoing_connections:
|
||||||
var connection_data = nodes_data[node_id].outgoing_connections[connection_id]
|
var connection_data = nodes_data[node_id].outgoing_connections[connection_id]
|
||||||
for connection in connection_data:
|
for connection in connection_data:
|
||||||
|
@ -139,14 +218,29 @@ static func from_json(json: String) -> Deck:
|
||||||
connection_data[connection] = int(connection_data[connection])
|
connection_data[connection] = int(connection_data[connection])
|
||||||
node.incoming_connections[int(connection_id)] = connection_data
|
node.incoming_connections[int(connection_id)] = connection_data
|
||||||
|
|
||||||
for i in nodes_data[node_id].port_values.size():
|
for i in node.ports.size():
|
||||||
var port_value = nodes_data[node_id].port_values[i]
|
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
|
node.ports[i].value = port_value
|
||||||
|
|
||||||
for key in nodes_data[node_id].meta:
|
for key in nodes_data[node_id].meta:
|
||||||
node.set_meta(key, str_to_var(nodes_data[node_id].meta[key]))
|
node.set_meta(key, str_to_var(nodes_data[node_id].meta[key]))
|
||||||
|
|
||||||
for prop in nodes_data[node_id].props:
|
node._post_load()
|
||||||
node.set(prop, nodes_data[node_id].props[prop])
|
|
||||||
|
var groups_data: Dictionary = data.deck.groups as Dictionary
|
||||||
|
|
||||||
|
for group_id: String in groups_data:
|
||||||
|
var group := Deck.from_dict(groups_data[group_id])
|
||||||
|
group._belonging_to = deck
|
||||||
|
group.is_group = true
|
||||||
|
deck.groups[group_id] = group
|
||||||
|
group.group_node = groups_data[group_id]["deck"]["group_node"]
|
||||||
|
group.group_input_node = groups_data[group_id]["deck"]["group_input_node"]
|
||||||
|
group.group_output_node = groups_data[group_id]["deck"]["group_output_node"]
|
||||||
|
deck.get_node(group.group_node).init_io()
|
||||||
|
|
||||||
return deck
|
return deck
|
||||||
|
|
27
classes/deck/deck_holder.gd
Normal file
27
classes/deck/deck_holder.gd
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
class_name DeckHolder
|
||||||
|
|
||||||
|
|
||||||
|
static var decks: Array[Deck]
|
||||||
|
|
||||||
|
|
||||||
|
static func add_empty_deck() -> Deck:
|
||||||
|
var deck := Deck.new()
|
||||||
|
DeckHolder.decks.append(deck)
|
||||||
|
var uuid := UUID.v4()
|
||||||
|
deck.id = uuid
|
||||||
|
return deck
|
||||||
|
|
||||||
|
|
||||||
|
static func open_deck_from_file(path: String) -> Deck:
|
||||||
|
var f := FileAccess.open(path, FileAccess.READ)
|
||||||
|
if f.get_error() != OK:
|
||||||
|
return null
|
||||||
|
|
||||||
|
var deck := Deck.from_dict(JSON.parse_string(f.get_as_text()), path)
|
||||||
|
DeckHolder.decks.append(deck)
|
||||||
|
|
||||||
|
return deck
|
||||||
|
|
||||||
|
|
||||||
|
static func close_deck(deck: Deck) -> void:
|
||||||
|
DeckHolder.decks.erase(deck)
|
|
@ -1,9 +1,10 @@
|
||||||
class_name DeckNode
|
class_name DeckNode
|
||||||
|
|
||||||
var name: String
|
var name: String
|
||||||
var input_ports: Array[Port]
|
|
||||||
var output_ports: Array[Port]
|
## [code]Dictionary[int -> output port, Array[Dictionary[String -> DeckNode#_id, int -> input port]]]
|
||||||
var outgoing_connections: Dictionary
|
var outgoing_connections: Dictionary
|
||||||
|
## [code]Dictionary[int -> input port, [Dictionary[String -> DeckNode#_id, int -> output port]]
|
||||||
var incoming_connections: Dictionary
|
var incoming_connections: Dictionary
|
||||||
|
|
||||||
var ports: Array[Port]
|
var ports: Array[Port]
|
||||||
|
@ -17,49 +18,63 @@ var aliases: Array[String]
|
||||||
|
|
||||||
var props_to_serialize: Array[StringName]
|
var props_to_serialize: Array[StringName]
|
||||||
|
|
||||||
|
var position: Dictionary = {"x": 0.0, "y": 0.0}
|
||||||
|
|
||||||
enum PortType{
|
enum PortType{
|
||||||
INPUT, ## Input port type (slot on the left).
|
INPUT, ## Input port type (slot on the left).
|
||||||
OUTPUT, ## Output port type (slot on the right).
|
OUTPUT, ## Output port type (slot on the right).
|
||||||
VIRTUAL, ## Virtual port type (no slot on left [i]or[/i] right).
|
VIRTUAL, ## Virtual port type (no slot on left [i]or[/i] right).
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal position_updated(new_position: Dictionary)
|
||||||
|
signal port_added(port: int)
|
||||||
|
signal port_removed(port: int)
|
||||||
|
signal ports_updated()
|
||||||
|
signal outgoing_connection_added(from_port: int)
|
||||||
|
signal outgoing_connection_removed(from_port: int)
|
||||||
|
signal incoming_connection_added(from_port: int)
|
||||||
|
signal incoming_connection_removed(from_port: int)
|
||||||
|
|
||||||
|
|
||||||
func add_input_port(type: Deck.Types, label: String, descriptor: String = "") -> void:
|
func add_input_port(type: Deck.Types, label: String, descriptor: String = "") -> void:
|
||||||
var port := Port.new(type, label, ports.size(), PortType.INPUT, get_input_ports().size(), descriptor)
|
add_port(type, label, PortType.INPUT, get_input_ports().size(), descriptor)
|
||||||
ports.append(port)
|
|
||||||
|
|
||||||
|
|
||||||
func add_output_port(type: Deck.Types, label: String, descriptor: String = "") -> void:
|
func add_output_port(type: Deck.Types, label: String, descriptor: String = "") -> void:
|
||||||
var port := Port.new(type, label, ports.size(), PortType.OUTPUT, get_output_ports().size(), descriptor)
|
add_port(type, label, PortType.OUTPUT, get_output_ports().size(), descriptor)
|
||||||
ports.append(port)
|
|
||||||
|
|
||||||
|
|
||||||
func add_virtual_port(type: Deck.Types, label: String, descriptor: String = "") -> void:
|
func add_virtual_port(type: Deck.Types, label: String, descriptor: String = "") -> void:
|
||||||
var port := Port.new(type, label, ports.size(), PortType.VIRTUAL, get_virtual_ports().size(), descriptor)
|
add_port(type, label, PortType.VIRTUAL, get_virtual_ports().size(), descriptor)
|
||||||
|
|
||||||
|
|
||||||
|
func add_port(type: Deck.Types, label: String, port_type: PortType, index_of_type: int, descriptor: String = "") -> void:
|
||||||
|
var port := Port.new(type, label, ports.size(), port_type, index_of_type, descriptor)
|
||||||
ports.append(port)
|
ports.append(port)
|
||||||
|
port_added.emit(ports.size() - 1)
|
||||||
|
ports_updated.emit()
|
||||||
|
|
||||||
|
|
||||||
func send_from_output_port(output_port: int, data: DeckType, extra_data: Array = []) -> void:
|
func remove_port(port_idx: int) -> void:
|
||||||
var global_port := get_global_port_idx_from_output(output_port)
|
outgoing_connections.erase(port_idx)
|
||||||
if global_port == -1:
|
incoming_connections.erase(port_idx)
|
||||||
|
ports.remove_at(port_idx)
|
||||||
|
port_removed.emit(port_idx)
|
||||||
|
|
||||||
|
|
||||||
|
func send(from_output_port: int, data: DeckType, extra_data: Array = []) -> void:
|
||||||
|
if outgoing_connections.get(from_output_port) == null:
|
||||||
return
|
return
|
||||||
|
|
||||||
send(global_port, data, extra_data)
|
for connection in outgoing_connections[from_output_port]:
|
||||||
|
|
||||||
|
|
||||||
func send(from_port: int, data: DeckType, extra_data: Array = []) -> void:
|
|
||||||
if outgoing_connections.get(from_port) == null:
|
|
||||||
return
|
|
||||||
|
|
||||||
for connection in outgoing_connections[from_port]:
|
|
||||||
connection = connection as Dictionary
|
connection = connection as Dictionary
|
||||||
# key is node uuid
|
# key is node uuid
|
||||||
# value is input port on destination node
|
# value is GLOBAL port on destination node
|
||||||
for node in connection:
|
for node in connection:
|
||||||
get_node(node)._receive(connection[node], data, extra_data)
|
get_node(node)._receive(connection[node], data, extra_data)
|
||||||
|
|
||||||
|
|
||||||
func _receive(to_port: int, data: DeckType, extra_data: Array = []) -> void:
|
func _receive(to_input_port: int, data: DeckType, extra_data: Array = []) -> void:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,11 +91,13 @@ func add_outgoing_connection(from_port: int, to_node: String, to_port: int) -> v
|
||||||
port_connections.append({to_node: to_port})
|
port_connections.append({to_node: to_port})
|
||||||
outgoing_connections[from_port] = port_connections
|
outgoing_connections[from_port] = port_connections
|
||||||
get_node(to_node).add_incoming_connection(to_port, _id, from_port)
|
get_node(to_node).add_incoming_connection(to_port, _id, from_port)
|
||||||
|
outgoing_connection_added.emit(from_port)
|
||||||
|
|
||||||
|
|
||||||
func add_incoming_connection(to_port: int, from_node: String, from_port: int) -> void:
|
func add_incoming_connection(to_port: int, from_node: String, from_port: int) -> void:
|
||||||
var connection := {from_node: from_port}
|
var connection := {from_node: from_port}
|
||||||
incoming_connections[to_port] = connection
|
incoming_connections[to_port] = connection
|
||||||
|
incoming_connection_added.emit(to_port)
|
||||||
|
|
||||||
|
|
||||||
func request_value(on_port: int) -> Variant:
|
func request_value(on_port: int) -> Variant:
|
||||||
|
@ -116,10 +133,12 @@ func remove_outgoing_connection(from_port: int, connection_hash: int) -> void:
|
||||||
|
|
||||||
port_connections.remove_at(to_remove)
|
port_connections.remove_at(to_remove)
|
||||||
outgoing_connections[from_port] = port_connections
|
outgoing_connections[from_port] = port_connections
|
||||||
|
outgoing_connection_removed.emit(from_port)
|
||||||
|
|
||||||
|
|
||||||
func remove_incoming_connection(to_port: int) -> void:
|
func remove_incoming_connection(to_port: int) -> void:
|
||||||
incoming_connections.erase(to_port)
|
incoming_connections.erase(to_port)
|
||||||
|
incoming_connection_removed.emit(to_port)
|
||||||
|
|
||||||
|
|
||||||
func remove_outgoing_connection_from_port(output_port: int, connection_hash: int) -> void:
|
func remove_outgoing_connection_from_port(output_port: int, connection_hash: int) -> void:
|
||||||
|
@ -168,6 +187,26 @@ func get_global_port_idx_from_virtual(idx: int) -> int:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
func get_port_type_idx_from_global(idx: int) -> int:
|
||||||
|
return ports[idx].index_of_type
|
||||||
|
|
||||||
|
|
||||||
|
func get_outgoing_connection_count(port: int) -> int:
|
||||||
|
return (outgoing_connections[port] as Array).size()
|
||||||
|
|
||||||
|
|
||||||
|
func get_outgoing_connection_count_on_output(port: int) -> int:
|
||||||
|
return get_outgoing_connection_count(get_global_port_idx_from_output(port))
|
||||||
|
|
||||||
|
|
||||||
|
func has_incoming_connection(port: int) -> bool:
|
||||||
|
return incoming_connections.has(port)
|
||||||
|
|
||||||
|
|
||||||
|
func has_incoming_connection_on_input(port: int) -> bool:
|
||||||
|
return has_incoming_connection(get_global_port_idx_from_input(port))
|
||||||
|
|
||||||
|
|
||||||
func get_all_ports() -> Array[Port]:
|
func get_all_ports() -> Array[Port]:
|
||||||
return ports
|
return ports
|
||||||
|
|
||||||
|
@ -176,6 +215,16 @@ func get_node(uuid: String) -> DeckNode:
|
||||||
return _belonging_to.get_node(uuid)
|
return _belonging_to.get_node(uuid)
|
||||||
|
|
||||||
|
|
||||||
|
# override this to do setup before connections are loaded but after props were set
|
||||||
|
func _pre_connection() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# override this to do extra setup after it's done loading from dictionary
|
||||||
|
func _post_load() -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
func to_dict(with_meta: bool = true) -> Dictionary:
|
func to_dict(with_meta: bool = true) -> Dictionary:
|
||||||
var d := {
|
var d := {
|
||||||
"_id": _id,
|
"_id": _id,
|
||||||
|
@ -184,7 +233,8 @@ func to_dict(with_meta: bool = true) -> Dictionary:
|
||||||
"incoming_connections": incoming_connections,
|
"incoming_connections": incoming_connections,
|
||||||
"props": {},
|
"props": {},
|
||||||
"node_type": node_type,
|
"node_type": node_type,
|
||||||
"port_values": []
|
"port_values": [],
|
||||||
|
"position": position,
|
||||||
}
|
}
|
||||||
|
|
||||||
for prop in props_to_serialize:
|
for prop in props_to_serialize:
|
||||||
|
@ -200,3 +250,7 @@ func to_dict(with_meta: bool = true) -> Dictionary:
|
||||||
for meta in get_meta_list():
|
for meta in get_meta_list():
|
||||||
d["meta"][meta] = var_to_str(get_meta(meta))
|
d["meta"][meta] = var_to_str(get_meta(meta))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
func position_as_vector2() -> Vector2:
|
||||||
|
return Vector2(position.x, position.y)
|
||||||
|
|
|
@ -8,8 +8,8 @@ var nodes: Dictionary = {}
|
||||||
|
|
||||||
|
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
if load_node_index():
|
#if load_node_index():
|
||||||
return
|
#return
|
||||||
|
|
||||||
var dir := DirAccess.open(BASE_NODE_PATH)
|
var dir := DirAccess.open(BASE_NODE_PATH)
|
||||||
dir.list_dir_begin()
|
dir.list_dir_begin()
|
||||||
|
|
71
classes/deck/nodes/group_input_node.gd
Normal file
71
classes/deck/nodes/group_input_node.gd
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
extends DeckNode
|
||||||
|
|
||||||
|
var output_count: int:
|
||||||
|
get:
|
||||||
|
return get_all_ports().size() - 1
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
name = "Group input"
|
||||||
|
node_type = "group_input"
|
||||||
|
props_to_serialize = [&"output_count"]
|
||||||
|
|
||||||
|
add_output_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Input 0"
|
||||||
|
)
|
||||||
|
outgoing_connection_added.connect(_on_outgoing_connection_added)
|
||||||
|
outgoing_connection_removed.connect(_on_outgoing_connection_removed)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_outgoing_connection_added(port_idx: int) -> void:
|
||||||
|
if port_idx + 1 < get_all_ports().size():
|
||||||
|
return
|
||||||
|
|
||||||
|
add_output_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Input %s" % (get_all_ports().size())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_outgoing_connection_removed(port_idx: int) -> void:
|
||||||
|
var last_connected_port := 0
|
||||||
|
for port: int in outgoing_connections.keys().slice(1):
|
||||||
|
if !(outgoing_connections[port] as Array).is_empty():
|
||||||
|
last_connected_port = port
|
||||||
|
|
||||||
|
prints("l:", last_connected_port, "p:", port_idx)
|
||||||
|
|
||||||
|
if port_idx < last_connected_port:
|
||||||
|
return
|
||||||
|
|
||||||
|
var s := get_all_ports().slice(0, last_connected_port + 2)
|
||||||
|
ports.assign(s)
|
||||||
|
ports_updated.emit()
|
||||||
|
|
||||||
|
|
||||||
|
func _pre_connection() -> void:
|
||||||
|
for i in output_count + 1:
|
||||||
|
add_output_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Input %s" % (i + 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _post_load() -> void:
|
||||||
|
# ensure we have enough ports after connections
|
||||||
|
var last_connected_port := 0
|
||||||
|
for port: int in outgoing_connections:
|
||||||
|
last_connected_port = port if outgoing_connections.has(port) else last_connected_port
|
||||||
|
|
||||||
|
if ports.size() <= last_connected_port:
|
||||||
|
for i in last_connected_port:
|
||||||
|
add_output_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Input %s" % get_output_ports().size()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _value_request(from_port: int) -> Variant:
|
||||||
|
var group_node := _belonging_to._belonging_to.get_node(_belonging_to.group_node)
|
||||||
|
return group_node.request_value(group_node.get_input_ports()[from_port].index_of_type)
|
68
classes/deck/nodes/group_node.gd
Normal file
68
classes/deck/nodes/group_node.gd
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
extends DeckNode
|
||||||
|
|
||||||
|
var group_id: String
|
||||||
|
var input_node: DeckNode
|
||||||
|
var output_node: DeckNode
|
||||||
|
|
||||||
|
var extra_ports: Array
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
name = "Group"
|
||||||
|
node_type = "group_node"
|
||||||
|
props_to_serialize = [&"group_id", &"extra_ports"]
|
||||||
|
|
||||||
|
|
||||||
|
func _pre_connection() -> void:
|
||||||
|
for port_type: PortType in extra_ports:
|
||||||
|
var index_of_type: int
|
||||||
|
match port_type:
|
||||||
|
PortType.OUTPUT:
|
||||||
|
add_output_port(Deck.Types.STRING, "Output %s" % get_output_ports().size())
|
||||||
|
PortType.INPUT:
|
||||||
|
add_input_port(Deck.Types.STRING, "Input %s" % get_input_ports().size())
|
||||||
|
|
||||||
|
|
||||||
|
func init_io() -> void:
|
||||||
|
var group: Deck = _belonging_to.groups.get(group_id) as Deck
|
||||||
|
if !group:
|
||||||
|
return
|
||||||
|
|
||||||
|
input_node = group.get_node(group.group_input_node)
|
||||||
|
output_node = group.get_node(group.group_output_node)
|
||||||
|
|
||||||
|
recalculate_ports()
|
||||||
|
setup_connections()
|
||||||
|
|
||||||
|
|
||||||
|
func setup_connections() -> void:
|
||||||
|
input_node.ports_updated.connect(recalculate_ports)
|
||||||
|
output_node.ports_updated.connect(recalculate_ports)
|
||||||
|
|
||||||
|
|
||||||
|
func recalculate_ports() -> void:
|
||||||
|
ports.clear()
|
||||||
|
|
||||||
|
for output_port: Port in output_node.get_input_ports():
|
||||||
|
add_output_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Output %s" % output_port.index
|
||||||
|
)
|
||||||
|
|
||||||
|
for input_port: Port in input_node.get_output_ports():
|
||||||
|
add_input_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Input %s" % input_port.index
|
||||||
|
)
|
||||||
|
|
||||||
|
extra_ports.clear()
|
||||||
|
for port in ports:
|
||||||
|
extra_ports.append(port.port_type)
|
||||||
|
|
||||||
|
|
||||||
|
func _receive(to_input_port: int, data: DeckType, extra_data: Array = []):
|
||||||
|
input_node.send(get_input_ports()[to_input_port].index_of_type, data, extra_data)
|
||||||
|
|
||||||
|
|
||||||
|
func _value_request(from_port: int) -> Variant:
|
||||||
|
return output_node.request_value(from_port)
|
72
classes/deck/nodes/group_output_node.gd
Normal file
72
classes/deck/nodes/group_output_node.gd
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
extends DeckNode
|
||||||
|
|
||||||
|
var input_count: int:
|
||||||
|
get:
|
||||||
|
return get_all_ports().size() - 1
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
name = "Group output"
|
||||||
|
node_type = "group_output"
|
||||||
|
props_to_serialize = [&"input_count"]
|
||||||
|
|
||||||
|
add_input_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Output 0"
|
||||||
|
)
|
||||||
|
|
||||||
|
incoming_connection_added.connect(_on_incoming_connection_added)
|
||||||
|
incoming_connection_removed.connect(_on_incoming_connection_removed)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_incoming_connection_added(port_idx: int) -> void:
|
||||||
|
if port_idx + 1 < get_all_ports().size():
|
||||||
|
return
|
||||||
|
|
||||||
|
add_input_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Output %s" % (get_all_ports().size())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_incoming_connection_removed(port_idx: int) -> void:
|
||||||
|
var last_connected_port := 0
|
||||||
|
for port: int in incoming_connections.keys().slice(1):
|
||||||
|
if !(incoming_connections[port] as Dictionary).is_empty():
|
||||||
|
last_connected_port = port
|
||||||
|
|
||||||
|
prints("l:", last_connected_port, "p:", port_idx)
|
||||||
|
|
||||||
|
if port_idx < last_connected_port:
|
||||||
|
return
|
||||||
|
|
||||||
|
var s := get_all_ports().slice(0, last_connected_port + 2)
|
||||||
|
ports.assign(s)
|
||||||
|
ports_updated.emit()
|
||||||
|
|
||||||
|
|
||||||
|
func _pre_connection() -> void:
|
||||||
|
for i in input_count + 1:
|
||||||
|
add_input_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Output %s" % (i + 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _post_load() -> void:
|
||||||
|
# ensure we have enough ports after connections
|
||||||
|
var last_connected_port := 0
|
||||||
|
for port: int in incoming_connections:
|
||||||
|
last_connected_port = port if incoming_connections.has(port) else last_connected_port
|
||||||
|
|
||||||
|
if ports.size() <= last_connected_port:
|
||||||
|
for i in last_connected_port:
|
||||||
|
add_input_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Output %s" % get_input_ports().size()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _receive(to_input_port: int, data: DeckType, extra_data: Array = []) -> void:
|
||||||
|
var group_node := _belonging_to._belonging_to.get_node(_belonging_to.group_node)
|
||||||
|
group_node.send(group_node.get_output_ports()[to_input_port].index_of_type, data, extra_data)
|
|
@ -29,15 +29,15 @@ func _init() -> void:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func _receive(to_port: int, data: DeckType, extra_data: Array = []) -> void:
|
func _receive(to_input_port: int, data: DeckType, extra_data: Array = []) -> void:
|
||||||
if to_port != 1:
|
if to_input_port != 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
var data_to_print
|
var data_to_print
|
||||||
if request_value(0) != null:
|
if request_value(0) != null:
|
||||||
data_to_print = request_value(0)
|
data_to_print = request_value(0)
|
||||||
elif ports[0].value_callback.call() != "":
|
elif get_input_ports()[0].value_callback.get_object() && get_input_ports()[0].value_callback.call() != "":
|
||||||
data_to_print = ports[0].value_callback.call()
|
data_to_print = get_input_ports()[0].value_callback.call()
|
||||||
else:
|
else:
|
||||||
data_to_print = data.get_value()
|
data_to_print = data.get_value()
|
||||||
|
|
||||||
|
@ -46,4 +46,4 @@ func _receive(to_port: int, data: DeckType, extra_data: Array = []) -> void:
|
||||||
# var data_to_print = input_ports[0].value_callback.call()
|
# var data_to_print = input_ports[0].value_callback.call()
|
||||||
print(data_to_print)
|
print(data_to_print)
|
||||||
print("extra data: ", extra_data)
|
print("extra data: ", extra_data)
|
||||||
send(2, DeckType.DeckTypeBool.new(true))
|
send(0, DeckType.DeckTypeBool.new(true))
|
||||||
|
|
|
@ -31,8 +31,8 @@ func _init() -> void:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func _receive(to_port: int, data: DeckType, extra_data: Array = []) -> void:
|
func _receive(to_input_port: int, data: DeckType, extra_data: Array = []) -> void:
|
||||||
if to_port != 2:
|
if to_input_port != 2:
|
||||||
return
|
return
|
||||||
|
|
||||||
var var_name: String = get_value_for_port(0, data)
|
var var_name: String = get_value_for_port(0, data)
|
||||||
|
@ -41,7 +41,7 @@ func _receive(to_port: int, data: DeckType, extra_data: Array = []) -> void:
|
||||||
|
|
||||||
_belonging_to.variable_stack[var_name] = var_value
|
_belonging_to.variable_stack[var_name] = var_value
|
||||||
|
|
||||||
send(3, DeckType.DeckTypeString.new(var_value))
|
send(0, DeckType.DeckTypeString.new(var_value))
|
||||||
|
|
||||||
# this can probably go into DeckNode with a different name that makes it clear
|
# this can probably go into DeckNode with a different name that makes it clear
|
||||||
# that it prioritizes call-time resolution
|
# that it prioritizes call-time resolution
|
||||||
|
|
17
classes/deck/nodes/string_constant.gd
Normal file
17
classes/deck/nodes/string_constant.gd
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
extends DeckNode
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
node_type = "string_constant"
|
||||||
|
name = "String Constant"
|
||||||
|
add_output_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Text",
|
||||||
|
"field"
|
||||||
|
)
|
||||||
|
|
||||||
|
func _value_request(from_port: int) -> Variant:
|
||||||
|
if ports[0].value_callback.get_object():
|
||||||
|
return ports[0].value_callback.call()
|
||||||
|
else:
|
||||||
|
return ports[0].value
|
16
classes/deck/nodes/test_interleaved_node.gd
Normal file
16
classes/deck/nodes/test_interleaved_node.gd
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
extends DeckNode
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
node_type = "test_interleaved"
|
||||||
|
name = "Test Interleaved"
|
||||||
|
|
||||||
|
for i in 4:
|
||||||
|
add_output_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Test"
|
||||||
|
)
|
||||||
|
add_input_port(
|
||||||
|
Deck.Types.STRING,
|
||||||
|
"Test"
|
||||||
|
)
|
127
graph_node_renderer/deck_holder_renderer.gd
Normal file
127
graph_node_renderer/deck_holder_renderer.gd
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
const DECK_SCENE := preload("res://graph_node_renderer/deck_renderer_graph_edit.tscn")
|
||||||
|
|
||||||
|
@onready var tab_container: TabContainerCustom = %TabContainerCustom as TabContainerCustom
|
||||||
|
@onready var file_dialog: FileDialog = $FileDialog
|
||||||
|
|
||||||
|
enum FileMenuId {
|
||||||
|
NEW,
|
||||||
|
OPEN,
|
||||||
|
SAVE = 3,
|
||||||
|
SAVE_AS,
|
||||||
|
CLOSE = 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
var _deck_to_save: WeakRef
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
tab_container.add_button_pressed.connect(add_empty_deck)
|
||||||
|
|
||||||
|
tab_container.tab_close_requested.connect(
|
||||||
|
func(tab: int):
|
||||||
|
DeckHolder.close_deck(tab_container.get_tab_metadata(tab))
|
||||||
|
tab_container.close_tab(tab)
|
||||||
|
)
|
||||||
|
|
||||||
|
file_dialog.canceled.connect(disconnect_file_dialog_signals)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_file_id_pressed(id: int) -> void:
|
||||||
|
match id:
|
||||||
|
FileMenuId.NEW:
|
||||||
|
add_empty_deck()
|
||||||
|
FileMenuId.OPEN:
|
||||||
|
open_open_dialog("res://")
|
||||||
|
FileMenuId.SAVE:
|
||||||
|
save_active_deck()
|
||||||
|
FileMenuId.SAVE_AS:
|
||||||
|
open_save_dialog("res://")
|
||||||
|
FileMenuId.CLOSE:
|
||||||
|
close_current_tab()
|
||||||
|
|
||||||
|
|
||||||
|
func add_empty_deck() -> void:
|
||||||
|
var deck := DeckHolder.add_empty_deck()
|
||||||
|
var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
||||||
|
inst.deck = deck
|
||||||
|
tab_container.add_content(inst, "Deck %s" % (tab_container.get_tab_count() + 1))
|
||||||
|
tab_container.set_tab_metadata(tab_container.get_current_tab(), deck)
|
||||||
|
inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested.bind(deck))
|
||||||
|
|
||||||
|
|
||||||
|
func close_current_tab() -> void:
|
||||||
|
tab_container.close_tab(tab_container.get_current_tab())
|
||||||
|
|
||||||
|
|
||||||
|
func open_save_dialog(path: String) -> void:
|
||||||
|
file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE
|
||||||
|
file_dialog.title = "Save a Deck"
|
||||||
|
file_dialog.current_path = path
|
||||||
|
_deck_to_save = weakref(get_active_deck())
|
||||||
|
file_dialog.popup_centered()
|
||||||
|
file_dialog.file_selected.connect(_on_file_dialog_save_file, CONNECT_ONE_SHOT)
|
||||||
|
|
||||||
|
|
||||||
|
func open_open_dialog(path: String) -> void:
|
||||||
|
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILES
|
||||||
|
file_dialog.title = "Open Deck(s)"
|
||||||
|
file_dialog.current_path = path
|
||||||
|
file_dialog.popup_centered()
|
||||||
|
file_dialog.files_selected.connect(_on_file_dialog_open_files, CONNECT_ONE_SHOT)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_file_dialog_save_file(path: String) -> void:
|
||||||
|
var deck: Deck = _deck_to_save.get_ref() as Deck
|
||||||
|
if !deck:
|
||||||
|
return
|
||||||
|
|
||||||
|
deck.save_path = path
|
||||||
|
var json := JSON.stringify(deck.to_dict(), "\t")
|
||||||
|
var f := FileAccess.open(path, FileAccess.WRITE)
|
||||||
|
f.store_string(json)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_file_dialog_open_files(paths: PackedStringArray) -> void:
|
||||||
|
for path in paths:
|
||||||
|
var deck := DeckHolder.open_deck_from_file(path)
|
||||||
|
var inst: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
||||||
|
inst.deck = deck
|
||||||
|
tab_container.add_content(inst, "Deck %s" % (tab_container.get_tab_count() + 1))
|
||||||
|
inst.initialize_from_deck()
|
||||||
|
inst.group_enter_requested.connect(_on_deck_renderer_group_enter_requested.bind(deck))
|
||||||
|
|
||||||
|
|
||||||
|
func get_active_deck() -> Deck:
|
||||||
|
if tab_container.is_empty():
|
||||||
|
return null
|
||||||
|
|
||||||
|
return (tab_container.get_content(tab_container.get_current_tab()) as DeckRendererGraphEdit).deck
|
||||||
|
|
||||||
|
|
||||||
|
func save_active_deck() -> void:
|
||||||
|
if get_active_deck().save_path.is_empty():
|
||||||
|
open_save_dialog("res://")
|
||||||
|
else:
|
||||||
|
var json := JSON.stringify(get_active_deck().to_dict(), "\t")
|
||||||
|
var f := FileAccess.open(get_active_deck().save_path, FileAccess.WRITE)
|
||||||
|
f.store_string(json)
|
||||||
|
|
||||||
|
|
||||||
|
func disconnect_file_dialog_signals() -> void:
|
||||||
|
if file_dialog.file_selected.is_connected(_on_file_dialog_save_file):
|
||||||
|
file_dialog.file_selected.disconnect(_on_file_dialog_save_file)
|
||||||
|
|
||||||
|
if file_dialog.files_selected.is_connected(_on_file_dialog_open_files):
|
||||||
|
file_dialog.files_selected.disconnect(_on_file_dialog_open_files)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_deck_renderer_group_enter_requested(group_id: String, deck: Deck) -> void:
|
||||||
|
var group_deck := deck.get_group(group_id)
|
||||||
|
var deck_renderer: DeckRendererGraphEdit = DECK_SCENE.instantiate()
|
||||||
|
deck_renderer.deck = group_deck
|
||||||
|
deck_renderer.initialize_from_deck()
|
||||||
|
tab_container.add_content(deck_renderer, "Group %s" % (tab_container.get_tab_count() + 1))
|
||||||
|
tab_container.set_tab_metadata(tab_container.get_current_tab(), group_deck)
|
||||||
|
deck_renderer.group_enter_requested.connect(_on_deck_renderer_group_enter_requested.bind(deck_renderer.deck))
|
73
graph_node_renderer/deck_holder_renderer.tscn
Normal file
73
graph_node_renderer/deck_holder_renderer.tscn
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
[gd_scene load_steps=4 format=3 uid="uid://duaah5x0jhkn6"]
|
||||||
|
|
||||||
|
[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="Theme" uid="uid://dqqdqscid2iem" path="res://graph_node_renderer/default_theme.tres" id="1_tgul2"]
|
||||||
|
|
||||||
|
[node name="DeckHolderRenderer" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme = ExtResource("1_tgul2")
|
||||||
|
script = ExtResource("1_67g2g")
|
||||||
|
|
||||||
|
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/margin_left = 2
|
||||||
|
theme_override_constants/margin_top = 2
|
||||||
|
theme_override_constants/margin_right = 2
|
||||||
|
theme_override_constants/margin_bottom = 2
|
||||||
|
|
||||||
|
[node name="VSplitContainer" type="VSplitContainer" parent="MarginContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
split_offset = 677
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VSplitContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="MenuBar" type="MenuBar" parent="MarginContainer/VSplitContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="File" type="PopupMenu" parent="MarginContainer/VSplitContainer/VBoxContainer/MenuBar"]
|
||||||
|
item_count = 7
|
||||||
|
item_0/text = "New Deck"
|
||||||
|
item_0/id = 0
|
||||||
|
item_1/text = "Open Deck"
|
||||||
|
item_1/id = 1
|
||||||
|
item_2/text = ""
|
||||||
|
item_2/id = 2
|
||||||
|
item_2/separator = true
|
||||||
|
item_3/text = "Save Deck"
|
||||||
|
item_3/id = 3
|
||||||
|
item_4/text = "Save Deck As"
|
||||||
|
item_4/id = 4
|
||||||
|
item_5/text = ""
|
||||||
|
item_5/id = 5
|
||||||
|
item_5/separator = true
|
||||||
|
item_6/text = "Close Deck"
|
||||||
|
item_6/id = 6
|
||||||
|
|
||||||
|
[node name="Edit" type="PopupMenu" parent="MarginContainer/VSplitContainer/VBoxContainer/MenuBar"]
|
||||||
|
|
||||||
|
[node name="TabContainerCustom" parent="MarginContainer/VSplitContainer/VBoxContainer" instance=ExtResource("1_s3ug2")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ConsoleContainer" type="PanelContainer" parent="MarginContainer/VSplitContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="FileDialog" type="FileDialog" parent="."]
|
||||||
|
size = Vector2i(776, 447)
|
||||||
|
mode_overrides_title = false
|
||||||
|
access = 2
|
||||||
|
use_native_dialog = true
|
||||||
|
|
||||||
|
[connection signal="id_pressed" from="MarginContainer/VSplitContainer/VBoxContainer/MenuBar/File" to="." method="_on_file_id_pressed"]
|
|
@ -6,7 +6,10 @@ var node: DeckNode
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
title = node.name
|
title = node.name
|
||||||
|
node.position_updated.connect(_on_node_position_updated)
|
||||||
|
#node.port_added.connect(_on_node_port_added)
|
||||||
|
#node.port_removed.connect(_on_node_port_removed)
|
||||||
|
node.ports_updated.connect(_on_node_ports_updated)
|
||||||
for port in node.get_all_ports():
|
for port in node.get_all_ports():
|
||||||
var descriptor_split := port.descriptor.split(":")
|
var descriptor_split := port.descriptor.split(":")
|
||||||
match descriptor_split[0]:
|
match descriptor_split[0]:
|
||||||
|
@ -17,12 +20,12 @@ func _ready() -> void:
|
||||||
if port.port_type == DeckNode.PortType.OUTPUT:
|
if port.port_type == DeckNode.PortType.OUTPUT:
|
||||||
button.pressed.connect(
|
button.pressed.connect(
|
||||||
func():
|
func():
|
||||||
node.send(port.index, DeckType.DeckTypeBool.new(true))
|
node.send(port.index_of_type, DeckType.DeckTypeBool.new(true))
|
||||||
)
|
)
|
||||||
elif port.port_type == DeckNode.PortType.INPUT:
|
elif port.port_type == DeckNode.PortType.INPUT:
|
||||||
button.pressed.connect(
|
button.pressed.connect(
|
||||||
func():
|
func():
|
||||||
node._receive(port.index, DeckType.DeckTypeBool.new(true))
|
node._receive(port.index_of_type, DeckType.DeckTypeBool.new(true))
|
||||||
)
|
)
|
||||||
"field":
|
"field":
|
||||||
var line_edit := LineEdit.new()
|
var line_edit := LineEdit.new()
|
||||||
|
@ -49,4 +52,113 @@ func _ready() -> void:
|
||||||
|
|
||||||
|
|
||||||
func _on_position_offset_changed() -> void:
|
func _on_position_offset_changed() -> void:
|
||||||
node.set_meta("position_offset", position_offset)
|
node.position.x = position_offset.x
|
||||||
|
node.position.y = position_offset.y
|
||||||
|
|
||||||
|
|
||||||
|
func _on_node_position_updated(new_position: Dictionary) -> void:
|
||||||
|
position_offset.x = new_position.x
|
||||||
|
position_offset.y = new_position.y
|
||||||
|
|
||||||
|
|
||||||
|
func _on_node_port_added(port_idx: int) -> void:
|
||||||
|
var port := node.get_all_ports()[port_idx]
|
||||||
|
|
||||||
|
var descriptor_split := port.descriptor.split(":")
|
||||||
|
match descriptor_split[0]:
|
||||||
|
"button":
|
||||||
|
var button := Button.new()
|
||||||
|
add_child(button)
|
||||||
|
button.text = port.label
|
||||||
|
if port.port_type == DeckNode.PortType.OUTPUT:
|
||||||
|
button.pressed.connect(
|
||||||
|
func():
|
||||||
|
node.send(port.index_of_type, DeckType.DeckTypeBool.new(true))
|
||||||
|
)
|
||||||
|
elif port.port_type == DeckNode.PortType.INPUT:
|
||||||
|
button.pressed.connect(
|
||||||
|
func():
|
||||||
|
node._receive(port.index_of_type, DeckType.DeckTypeBool.new(true))
|
||||||
|
)
|
||||||
|
"field":
|
||||||
|
var line_edit := LineEdit.new()
|
||||||
|
add_child(line_edit)
|
||||||
|
if port.value:
|
||||||
|
line_edit.text = str(port.value)
|
||||||
|
line_edit.placeholder_text = port.label
|
||||||
|
port.value_callback = line_edit.get_text
|
||||||
|
line_edit.text_changed.connect(port.set_value)
|
||||||
|
_:
|
||||||
|
var label := Label.new()
|
||||||
|
add_child(label)
|
||||||
|
label.text = port.label
|
||||||
|
|
||||||
|
set_slot(
|
||||||
|
port.index,
|
||||||
|
port.port_type == DeckNode.PortType.INPUT,
|
||||||
|
0,
|
||||||
|
Color.WHITE,
|
||||||
|
port.port_type == DeckNode.PortType.OUTPUT,
|
||||||
|
0,
|
||||||
|
Color.WHITE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_node_port_removed(port_idx: int) -> void:
|
||||||
|
set_slot(
|
||||||
|
port_idx,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
Color.WHITE,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
Color.WHITE,
|
||||||
|
)
|
||||||
|
|
||||||
|
get_child(port_idx).queue_free()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_node_ports_updated() -> void:
|
||||||
|
clear_all_slots()
|
||||||
|
for c in get_children():
|
||||||
|
c.queue_free()
|
||||||
|
|
||||||
|
for port in node.get_all_ports():
|
||||||
|
var descriptor_split := port.descriptor.split(":")
|
||||||
|
match descriptor_split[0]:
|
||||||
|
"button":
|
||||||
|
var button := Button.new()
|
||||||
|
add_child(button)
|
||||||
|
button.text = port.label
|
||||||
|
if port.port_type == DeckNode.PortType.OUTPUT:
|
||||||
|
button.pressed.connect(
|
||||||
|
func():
|
||||||
|
node.send(port.index_of_type, DeckType.DeckTypeBool.new(true))
|
||||||
|
)
|
||||||
|
elif port.port_type == DeckNode.PortType.INPUT:
|
||||||
|
button.pressed.connect(
|
||||||
|
func():
|
||||||
|
node._receive(port.index_of_type, DeckType.DeckTypeBool.new(true))
|
||||||
|
)
|
||||||
|
"field":
|
||||||
|
var line_edit := LineEdit.new()
|
||||||
|
add_child(line_edit)
|
||||||
|
if port.value:
|
||||||
|
line_edit.text = str(port.value)
|
||||||
|
line_edit.placeholder_text = port.label
|
||||||
|
port.value_callback = line_edit.get_text
|
||||||
|
line_edit.text_changed.connect(port.set_value)
|
||||||
|
_:
|
||||||
|
var label := Label.new()
|
||||||
|
add_child(label)
|
||||||
|
label.text = port.label
|
||||||
|
|
||||||
|
set_slot(
|
||||||
|
port.index,
|
||||||
|
port.port_type == DeckNode.PortType.INPUT,
|
||||||
|
0,
|
||||||
|
Color.WHITE,
|
||||||
|
port.port_type == DeckNode.PortType.OUTPUT,
|
||||||
|
0,
|
||||||
|
Color.WHITE,
|
||||||
|
)
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
extends GraphEdit
|
extends GraphEdit
|
||||||
|
class_name DeckRendererGraphEdit
|
||||||
|
|
||||||
const NODE_SCENE := preload("res://graph_node_renderer/deck_node_renderer_graph_node.tscn")
|
const NODE_SCENE := preload("res://graph_node_renderer/deck_node_renderer_graph_node.tscn")
|
||||||
|
|
||||||
var deck: Deck = Deck.new()
|
var deck: Deck:
|
||||||
#var button_node = preload("res://classes/deck/nodes/button.gd")
|
set(v):
|
||||||
#var print_node = preload("res://classes/deck/nodes/print.gd")
|
deck = v
|
||||||
#var get_var_node = preload("res://classes/deck/nodes/get_deck_var.gd")
|
deck.node_added.connect(_on_deck_node_added)
|
||||||
#var set_var_node = preload("res://classes/deck/nodes/set_deck_var.gd")
|
deck.node_removed.connect(_on_deck_node_removed)
|
||||||
|
|
||||||
|
signal group_enter_requested(group_id: String)
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
var add_button := Button.new()
|
var add_button := Button.new()
|
||||||
|
@ -17,100 +21,51 @@ func _ready() -> void:
|
||||||
get_var.text = "Get Var"
|
get_var.text = "Get Var"
|
||||||
var set_var := Button.new()
|
var set_var := Button.new()
|
||||||
set_var.text = "Set Var"
|
set_var.text = "Set Var"
|
||||||
get_zoom_hbox().add_child(add_button)
|
var test := Button.new()
|
||||||
get_zoom_hbox().add_child(add_print)
|
test.text = "Interleaved"
|
||||||
get_zoom_hbox().add_child(get_var)
|
var str_const := Button.new()
|
||||||
get_zoom_hbox().add_child(set_var)
|
str_const.text = "String"
|
||||||
|
get_menu_hbox().add_child(add_button)
|
||||||
var save_btn := Button.new()
|
get_menu_hbox().add_child(add_print)
|
||||||
save_btn.text = "Save"
|
get_menu_hbox().add_child(get_var)
|
||||||
get_zoom_hbox().add_child(save_btn)
|
get_menu_hbox().add_child(set_var)
|
||||||
var load_btn := Button.new()
|
get_menu_hbox().add_child(test)
|
||||||
load_btn.text = "Load"
|
get_menu_hbox().add_child(str_const)
|
||||||
get_zoom_hbox().add_child(load_btn)
|
|
||||||
|
|
||||||
save_btn.pressed.connect(
|
|
||||||
func():
|
|
||||||
var t = deck.to_json()
|
|
||||||
var f := FileAccess.open("user://save_test.json", FileAccess.WRITE)
|
|
||||||
f.store_string(t)
|
|
||||||
)
|
|
||||||
|
|
||||||
load_btn.pressed.connect(
|
|
||||||
func():
|
|
||||||
var f := FileAccess.open("user://save_test.json", FileAccess.READ)
|
|
||||||
for i in get_children():
|
|
||||||
i.queue_free()
|
|
||||||
|
|
||||||
deck = Deck.from_json(f.get_as_text())
|
|
||||||
scroll_offset = str_to_vector2(deck.get_meta("offset", ""))
|
|
||||||
|
|
||||||
for node_id in deck.nodes:
|
|
||||||
var node_renderer: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
|
||||||
node_renderer.node = deck.nodes[node_id]
|
|
||||||
add_child(node_renderer)
|
|
||||||
node_renderer.position_offset = str_to_vector2(deck.nodes[node_id].get_meta("position_offset", ""))
|
|
||||||
|
|
||||||
for node_id in deck.nodes:
|
|
||||||
var node: DeckNode = deck.nodes[node_id]
|
|
||||||
var from_node_name = get_children().filter(
|
|
||||||
func(c: DeckNodeRendererGraphNode):
|
|
||||||
return c.node._id == node_id
|
|
||||||
)[0].name
|
|
||||||
# "outgoing_connections": {
|
|
||||||
# "0": [
|
|
||||||
# {
|
|
||||||
# "c8cc7dce-2a86-461c-a24f-0a4dbd06f379": 1
|
|
||||||
# }
|
|
||||||
# ]
|
|
||||||
# },
|
|
||||||
for from_port in node.outgoing_connections:
|
|
||||||
for connection in node.outgoing_connections[from_port]:
|
|
||||||
var to_node_id = connection.keys()[0]
|
|
||||||
var to_node_port = connection.values()[0]
|
|
||||||
var to_node_name = get_children().filter(
|
|
||||||
func(c: DeckNodeRendererGraphNode):
|
|
||||||
return c.node._id == to_node_id
|
|
||||||
)[0].name
|
|
||||||
prints(from_node_name, to_node_name)
|
|
||||||
connect_node(from_node_name, from_port, to_node_name, to_node_port)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
add_button.pressed.connect(
|
add_button.pressed.connect(
|
||||||
func():
|
func():
|
||||||
var node := NodeDB.instance_node("button")
|
var node := NodeDB.instance_node("button")
|
||||||
deck.add_node_inst(node)
|
deck.add_node_inst(node)
|
||||||
var node_renderer: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
|
||||||
node_renderer.node = node
|
|
||||||
add_child(node_renderer)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
add_print.pressed.connect(
|
add_print.pressed.connect(
|
||||||
func():
|
func():
|
||||||
var node := NodeDB.instance_node("print")
|
var node := NodeDB.instance_node("print")
|
||||||
deck.add_node_inst(node)
|
deck.add_node_inst(node)
|
||||||
var node_renderer: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
|
||||||
node_renderer.node = node
|
|
||||||
add_child(node_renderer)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
get_var.pressed.connect(
|
get_var.pressed.connect(
|
||||||
func():
|
func():
|
||||||
var node := NodeDB.instance_node("get_deck_var")
|
var node := NodeDB.instance_node("get_deck_var")
|
||||||
deck.add_node_inst(node)
|
deck.add_node_inst(node)
|
||||||
var node_renderer: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
|
||||||
node_renderer.node = node
|
|
||||||
add_child(node_renderer)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set_var.pressed.connect(
|
set_var.pressed.connect(
|
||||||
func():
|
func():
|
||||||
var node := NodeDB.instance_node("set_deck_var")
|
var node := NodeDB.instance_node("set_deck_var")
|
||||||
deck.add_node_inst(node)
|
deck.add_node_inst(node)
|
||||||
var node_renderer: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
)
|
||||||
node_renderer.node = node
|
|
||||||
add_child(node_renderer)
|
test.pressed.connect(
|
||||||
|
func():
|
||||||
|
var node := NodeDB.instance_node("test_interleaved")
|
||||||
|
deck.add_node_inst(node)
|
||||||
|
)
|
||||||
|
|
||||||
|
str_const.pressed.connect(
|
||||||
|
func():
|
||||||
|
var node := NodeDB.instance_node("string_constant")
|
||||||
|
deck.add_node_inst(node)
|
||||||
)
|
)
|
||||||
|
|
||||||
connection_request.connect(attempt_connection)
|
connection_request.connect(attempt_connection)
|
||||||
|
@ -118,37 +73,140 @@ func _ready() -> void:
|
||||||
|
|
||||||
|
|
||||||
func attempt_connection(from_node_name: StringName, from_port: int, to_node_name: StringName, to_port: int) -> void:
|
func attempt_connection(from_node_name: StringName, from_port: int, to_node_name: StringName, to_port: int) -> void:
|
||||||
var from_node: DeckNode = get_node(NodePath(from_node_name)).node
|
var from_node_renderer: DeckNodeRendererGraphNode = get_node(NodePath(from_node_name))
|
||||||
var to_node: DeckNode = get_node(NodePath(to_node_name)).node
|
var to_node_renderer: DeckNodeRendererGraphNode = get_node(NodePath(to_node_name))
|
||||||
|
|
||||||
var from_output := from_node.get_global_port_idx_from_output(from_port)
|
#var from_output := from_node_renderer.node.get_global_port_idx_from_output(from_port)
|
||||||
var to_input := to_node.get_global_port_idx_from_input(to_port)
|
#var to_input := to_node_renderer.node.get_global_port_idx_from_input(to_port)
|
||||||
|
|
||||||
if deck.connect_nodes(from_node, to_node, from_output, to_input):
|
if deck.connect_nodes(from_node_renderer.node, to_node_renderer.node, from_port, to_port):
|
||||||
connect_node(from_node_name, from_port, to_node_name, to_port)
|
connect_node(
|
||||||
|
from_node_renderer.name,
|
||||||
|
from_port,
|
||||||
|
to_node_renderer.name,
|
||||||
|
to_port
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func attempt_disconnect(from_node_name: StringName, from_port: int, to_node_name: StringName, to_port: int) -> void:
|
func attempt_disconnect(from_node_name: StringName, from_port: int, to_node_name: StringName, to_port: int) -> void:
|
||||||
var from_node: DeckNode = get_node(NodePath(from_node_name)).node
|
var from_node_renderer: DeckNodeRendererGraphNode = get_node(NodePath(from_node_name))
|
||||||
var to_node: DeckNode = get_node(NodePath(to_node_name)).node
|
var to_node_renderer: DeckNodeRendererGraphNode = get_node(NodePath(to_node_name))
|
||||||
|
|
||||||
var from_output := from_node.get_global_port_idx_from_output(from_port)
|
#var from_output := from_node_renderer.node.get_global_port_idx_from_output(from_port)
|
||||||
var to_input := to_node.get_global_port_idx_from_input(to_port)
|
#var to_input := to_node_renderer.node.get_global_port_idx_from_input(to_port)
|
||||||
|
|
||||||
deck.disconnect_nodes(from_node, to_node, from_output, to_input)
|
deck.disconnect_nodes(from_node_renderer.node, to_node_renderer.node, from_port, to_port)
|
||||||
|
|
||||||
disconnect_node(from_node_name, from_port, to_node_name, to_port)
|
disconnect_node(
|
||||||
|
from_node_renderer.name,
|
||||||
|
from_port,
|
||||||
|
to_node_renderer.name,
|
||||||
|
to_port
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func _on_scroll_offset_changed(offset: Vector2) -> void:
|
func _on_scroll_offset_changed(offset: Vector2) -> void:
|
||||||
deck.set_meta("offset", offset)
|
deck.set_meta("offset", offset)
|
||||||
|
|
||||||
|
|
||||||
func str_to_vector2(s: String) -> Vector2:
|
func initialize_from_deck() -> void:
|
||||||
if s.is_empty():
|
# TODO: wait for https://github.com/godotengine/godot/issues/85005 to get merged
|
||||||
return Vector2()
|
# until it is, all calls to GraphEdit#get_children will need to slice off the first element
|
||||||
|
for i in get_children().slice(1):
|
||||||
|
i.queue_free()
|
||||||
|
|
||||||
var san := s.trim_prefix("(").trim_suffix(")").split(",")
|
scroll_offset = deck.get_meta("offset", Vector2())
|
||||||
var x := float(san[0])
|
|
||||||
var y := float(san[1])
|
for node_id in deck.nodes:
|
||||||
return Vector2(x, y)
|
var node_renderer: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
||||||
|
node_renderer.node = deck.nodes[node_id]
|
||||||
|
add_child(node_renderer)
|
||||||
|
node_renderer.position_offset = node_renderer.node.position_as_vector2()
|
||||||
|
|
||||||
|
for node_id in deck.nodes:
|
||||||
|
var node: DeckNode = deck.nodes[node_id]
|
||||||
|
var from_node = get_children().slice(1).filter(
|
||||||
|
func(c: DeckNodeRendererGraphNode):
|
||||||
|
return c.node._id == node_id
|
||||||
|
)[0]
|
||||||
|
|
||||||
|
refresh_connections()
|
||||||
|
|
||||||
|
|
||||||
|
func refresh_connections() -> void:
|
||||||
|
for node_id in deck.nodes:
|
||||||
|
var node: DeckNode = deck.nodes[node_id]
|
||||||
|
var from_node: DeckNodeRendererGraphNode = get_children().slice(1).filter(
|
||||||
|
func(c: DeckNodeRendererGraphNode):
|
||||||
|
return c.node._id == node_id
|
||||||
|
)[0]
|
||||||
|
|
||||||
|
for from_port in node.outgoing_connections:
|
||||||
|
for connection in node.outgoing_connections[from_port]:
|
||||||
|
var to_node_id = connection.keys()[0]
|
||||||
|
var to_node_port = connection.values()[0]
|
||||||
|
var to_node: DeckNodeRendererGraphNode = get_children().slice(1).filter(
|
||||||
|
func(c: DeckNodeRendererGraphNode):
|
||||||
|
return c.node._id == to_node_id
|
||||||
|
)[0]
|
||||||
|
#print("***")
|
||||||
|
#print("calling connect_node with:")
|
||||||
|
#print(from_node.node.name)
|
||||||
|
#print(from_node.node.get_port_type_idx_from_global(from_port))
|
||||||
|
#print(to_node.node.name)
|
||||||
|
#print(to_node.node.get_port_type_idx_from_global(to_node_port))
|
||||||
|
#print("***")
|
||||||
|
connect_node(
|
||||||
|
from_node.name,
|
||||||
|
from_port,
|
||||||
|
to_node.name,
|
||||||
|
to_node_port
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_deck_node_added(node: DeckNode) -> void:
|
||||||
|
var inst: DeckNodeRendererGraphNode = NODE_SCENE.instantiate()
|
||||||
|
inst.node = node
|
||||||
|
add_child(inst)
|
||||||
|
inst.position_offset = inst.node.position_as_vector2()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_deck_node_removed(node: DeckNode) -> void:
|
||||||
|
for renderer: DeckNodeRendererGraphNode in get_children().slice(1):
|
||||||
|
if renderer.node != node:
|
||||||
|
continue
|
||||||
|
|
||||||
|
renderer.queue_free()
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
func get_selected_nodes() -> Array:
|
||||||
|
return get_children().slice(1).filter(
|
||||||
|
func(x: DeckNodeRendererGraphNode):
|
||||||
|
return x.selected
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func _gui_input(event: InputEvent) -> void:
|
||||||
|
if event.is_action_pressed("group_nodes") && get_selected_nodes().size() > 0:
|
||||||
|
print("?")
|
||||||
|
clear_connections()
|
||||||
|
var nodes = get_selected_nodes().map(
|
||||||
|
func(x: DeckNodeRendererGraphNode):
|
||||||
|
return x.node
|
||||||
|
)
|
||||||
|
deck.group_nodes(nodes)
|
||||||
|
refresh_connections()
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
|
||||||
|
|
||||||
|
func _input(event: InputEvent) -> void:
|
||||||
|
if !has_focus():
|
||||||
|
return
|
||||||
|
|
||||||
|
if event.is_action_pressed("enter_group") && get_selected_nodes().size() == 1:
|
||||||
|
if !((get_selected_nodes()[0] as DeckNodeRendererGraphNode).node.node_type == "group_node"):
|
||||||
|
return
|
||||||
|
print("tried to enter group")
|
||||||
|
group_enter_requested.emit((get_selected_nodes()[0] as DeckNodeRendererGraphNode).node.group_id)
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
|
4
graph_node_renderer/default_theme.tres
Normal file
4
graph_node_renderer/default_theme.tres
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
[gd_resource type="Theme" format=3 uid="uid://dqqdqscid2iem"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
default_font_size = 14
|
84
graph_node_renderer/tab_container_custom.gd
Normal file
84
graph_node_renderer/tab_container_custom.gd
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
extends VBoxContainer
|
||||||
|
class_name TabContainerCustom
|
||||||
|
|
||||||
|
@onready var tab_bar: TabBar = %TabBar
|
||||||
|
@onready var add_tab_button: Button = %Button
|
||||||
|
@onready var content_container: MarginContainer = %ContentContainer
|
||||||
|
|
||||||
|
|
||||||
|
signal add_button_pressed
|
||||||
|
signal tab_changed(tab: int)
|
||||||
|
signal tab_closed(tab: int)
|
||||||
|
signal tab_close_requested(tab: int)
|
||||||
|
signal tab_rearranged(old: int, new: int)
|
||||||
|
|
||||||
|
var _previous_active_tab: int = -1
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
tab_bar.tab_selected.connect(
|
||||||
|
func(tab: int):
|
||||||
|
if _previous_active_tab == tab:
|
||||||
|
return
|
||||||
|
|
||||||
|
if _previous_active_tab > -1:
|
||||||
|
content_container.get_child(_previous_active_tab).visible = false
|
||||||
|
content_container.get_child(tab).visible = true
|
||||||
|
|
||||||
|
tab_changed.emit(tab)
|
||||||
|
_previous_active_tab = tab
|
||||||
|
)
|
||||||
|
|
||||||
|
tab_bar.tab_close_pressed.connect(func(tab: int): tab_close_requested.emit(tab))
|
||||||
|
|
||||||
|
add_tab_button.pressed.connect(
|
||||||
|
func():
|
||||||
|
add_button_pressed.emit()
|
||||||
|
)
|
||||||
|
|
||||||
|
tab_bar.active_tab_rearranged.connect(
|
||||||
|
func(idx_to: int):
|
||||||
|
tab_rearranged.emit(_previous_active_tab, idx_to)
|
||||||
|
content_container.move_child(content_container.get_child(_previous_active_tab), idx_to)
|
||||||
|
_previous_active_tab = idx_to
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func add_content(c: Node, tab_title: String) -> void:
|
||||||
|
tab_bar.add_tab(tab_title)
|
||||||
|
content_container.add_child(c)
|
||||||
|
tab_bar.set_current_tab(tab_bar.tab_count - 1)
|
||||||
|
|
||||||
|
|
||||||
|
func get_tab_count() -> int:
|
||||||
|
return tab_bar.tab_count
|
||||||
|
|
||||||
|
|
||||||
|
func is_empty() -> bool:
|
||||||
|
return get_tab_count() == 0
|
||||||
|
|
||||||
|
|
||||||
|
func close_tab(tab: int) -> void:
|
||||||
|
content_container.get_child(tab).queue_free()
|
||||||
|
if !tab_bar.select_previous_available():
|
||||||
|
tab_bar.select_next_available()
|
||||||
|
tab_bar.remove_tab(tab)
|
||||||
|
tab_closed.emit(tab)
|
||||||
|
if tab_bar.tab_count == 0:
|
||||||
|
_previous_active_tab = -1
|
||||||
|
|
||||||
|
|
||||||
|
func get_current_tab() -> int:
|
||||||
|
return tab_bar.current_tab
|
||||||
|
|
||||||
|
|
||||||
|
func get_content(idx: int) -> Control:
|
||||||
|
return content_container.get_child(idx)
|
||||||
|
|
||||||
|
|
||||||
|
func set_tab_metadata(tab: int, metadata: Variant) -> void:
|
||||||
|
tab_bar.set_tab_metadata(tab, metadata)
|
||||||
|
|
||||||
|
|
||||||
|
func get_tab_metadata(tab: int) -> Variant:
|
||||||
|
return tab_bar.get_tab_metadata(tab)
|
34
graph_node_renderer/tab_container_custom.tscn
Normal file
34
graph_node_renderer/tab_container_custom.tscn
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://b84f2ngtcm5b8"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://graph_node_renderer/tab_container_custom.gd" id="1_63wbq"]
|
||||||
|
|
||||||
|
[node name="TabContainerCustom" type="VBoxContainer"]
|
||||||
|
offset_right = 22.0
|
||||||
|
offset_bottom = 35.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
script = ExtResource("1_63wbq")
|
||||||
|
metadata/_edit_use_anchors_ = true
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TabBar" type="TabBar" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
clip_tabs = false
|
||||||
|
tab_close_display_policy = 1
|
||||||
|
drag_to_rearrange_enabled = true
|
||||||
|
|
||||||
|
[node name="Button" type="Button" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
text = "+"
|
||||||
|
|
||||||
|
[node name="ContentContainer" type="MarginContainer" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
|
@ -12,10 +12,10 @@ config_version=5
|
||||||
|
|
||||||
config/name="Re-DotDeck"
|
config/name="Re-DotDeck"
|
||||||
config/tags=PackedStringArray("dot_deck")
|
config/tags=PackedStringArray("dot_deck")
|
||||||
run/main_scene="res://graph_node_renderer/deck_renderer_graph_edit.tscn"
|
run/main_scene="res://graph_node_renderer/deck_holder_renderer.tscn"
|
||||||
config/use_custom_user_dir=true
|
config/use_custom_user_dir=true
|
||||||
config/custom_user_dir_name="dotdeck"
|
config/custom_user_dir_name="dotdeck"
|
||||||
config/features=PackedStringArray("4.1", "Forward Plus")
|
config/features=PackedStringArray("4.2", "Forward Plus")
|
||||||
run/low_processor_mode=true
|
run/low_processor_mode=true
|
||||||
config/icon="res://icon.svg"
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
|
@ -23,6 +23,23 @@ config/icon="res://icon.svg"
|
||||||
|
|
||||||
NodeDB="*res://classes/deck/node_db.gd"
|
NodeDB="*res://classes/deck/node_db.gd"
|
||||||
|
|
||||||
|
[display]
|
||||||
|
|
||||||
|
window/subwindows/embed_subwindows=false
|
||||||
|
|
||||||
|
[input]
|
||||||
|
|
||||||
|
group_nodes={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":71,"physical_keycode":0,"key_label":0,"unicode":103,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
enter_group={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
renderer/rendering_method="gl_compatibility"
|
renderer/rendering_method="gl_compatibility"
|
||||||
|
|
Loading…
Reference in a new issue