miggor-StreamGraph/classes/deck/deck_node.gd
Lera Elvoé fa5e9997ef 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>
2023-11-22 04:26:11 +00:00

256 lines
6.9 KiB
GDScript

class_name DeckNode
var name: String
## [code]Dictionary[int -> output port, Array[Dictionary[String -> DeckNode#_id, int -> input port]]]
var outgoing_connections: Dictionary
## [code]Dictionary[int -> input port, [Dictionary[String -> DeckNode#_id, int -> output port]]
var incoming_connections: Dictionary
var ports: Array[Port]
var _belonging_to: Deck
var _id: String
var node_type: String
var description: String
var aliases: Array[String]
var props_to_serialize: Array[StringName]
var position: Dictionary = {"x": 0.0, "y": 0.0}
enum PortType{
INPUT, ## Input port type (slot on the left).
OUTPUT, ## Output port type (slot on the 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:
add_port(type, label, PortType.INPUT, get_input_ports().size(), descriptor)
func add_output_port(type: Deck.Types, label: String, descriptor: String = "") -> void:
add_port(type, label, PortType.OUTPUT, get_output_ports().size(), descriptor)
func add_virtual_port(type: Deck.Types, label: String, descriptor: String = "") -> void:
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)
port_added.emit(ports.size() - 1)
ports_updated.emit()
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)
func send(from_output_port: int, data: DeckType, extra_data: Array = []) -> void:
if outgoing_connections.get(from_output_port) == null:
return
for connection in outgoing_connections[from_output_port]:
connection = connection as Dictionary
# key is node uuid
# value is GLOBAL port on destination node
for node in connection:
get_node(node)._receive(connection[node], data, extra_data)
func _receive(to_input_port: int, data: DeckType, extra_data: Array = []) -> void:
pass
func add_outgoing_connection_to_port(output_port: int, to_node: String, to_input_port: int) -> void:
add_outgoing_connection(
get_global_port_idx_from_output(output_port),
to_node,
get_node(to_node).get_global_port_idx_from_input(to_input_port)
)
func add_outgoing_connection(from_port: int, to_node: String, to_port: int) -> void:
var port_connections: Array = outgoing_connections.get(from_port, [])
port_connections.append({to_node: to_port})
outgoing_connections[from_port] = port_connections
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:
var connection := {from_node: from_port}
incoming_connections[to_port] = connection
incoming_connection_added.emit(to_port)
func request_value(on_port: int) -> Variant:
if !incoming_connections.has(on_port):
return null
var connection: Dictionary = incoming_connections[on_port]
var node := get_node(connection.keys()[0])
return node._value_request(connection.values()[0])
# override this
func _value_request(from_port: int) -> Variant:
return null
func remove_outgoing_connection(from_port: int, connection_hash: int) -> void:
var port_connections: Array = (outgoing_connections.get(from_port, []) as Array).duplicate(true)
if port_connections.is_empty():
return
var incoming_connection := {}
var to_remove: int = -1
for i in port_connections.size():
if port_connections[i].hash() == connection_hash:
to_remove = i
if to_remove == -1:
print('nothing to remove')
return
port_connections.remove_at(to_remove)
outgoing_connections[from_port] = port_connections
outgoing_connection_removed.emit(from_port)
func remove_incoming_connection(to_port: int) -> void:
incoming_connections.erase(to_port)
incoming_connection_removed.emit(to_port)
func remove_outgoing_connection_from_port(output_port: int, connection_hash: int) -> void:
remove_outgoing_connection(get_global_port_idx_from_output(output_port), connection_hash)
func get_input_ports() -> Array[Port]:
return ports.filter(
func(port: Port) -> bool:
return port.port_type == PortType.INPUT
)
func get_output_ports() -> Array[Port]:
return ports.filter(
func(port: Port) -> bool:
return port.port_type == PortType.OUTPUT
)
func get_virtual_ports() -> Array[Port]:
return ports.filter(
func(port: Port) -> bool:
return port.port_type == PortType.VIRTUAL
)
func get_global_port_idx_from_input(idx: int) -> int:
if get_input_ports().size() > idx:
return get_input_ports()[idx].index
else:
return -1
func get_global_port_idx_from_output(idx: int) -> int:
if get_output_ports().size() > idx:
return get_output_ports()[idx].index
else:
return -1
func get_global_port_idx_from_virtual(idx: int) -> int:
if get_virtual_ports().size() > idx:
return get_virtual_ports()[idx].index
else:
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]:
return ports
func get_node(uuid: String) -> DeckNode:
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:
var d := {
"_id": _id,
"name": name,
"outgoing_connections": outgoing_connections,
"incoming_connections": incoming_connections,
"props": {},
"node_type": node_type,
"port_values": [],
"position": position,
}
for prop in props_to_serialize:
d.props[prop] = get(prop)
ports.map(
func(port: Port) -> void:
d.port_values.append(port.value)
)
if with_meta:
d["meta"] = {}
for meta in get_meta_list():
d["meta"][meta] = var_to_str(get_meta(meta))
return d
func position_as_vector2() -> Vector2:
return Vector2(position.x, position.y)