class_name DeckNode var name: String var input_ports: Array[Port] var output_ports: Array[Port] var outgoing_connections: Dictionary 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] 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). } 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) ports.append(port) 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) ports.append(port) 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) ports.append(port) func send_from_output_port(output_port: int, data: DeckType, extra_data: Array = []) -> void: var global_port := get_global_port_idx_from_output(output_port) if global_port == -1: return send(global_port, data, extra_data) 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 # key is node uuid # value is input port on destination node for node in connection: get_node(node)._receive(connection[node], data, extra_data) func _receive(to_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) 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 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 func remove_incoming_connection(to_port: int) -> void: incoming_connections.erase(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_all_ports() -> Array[Port]: return ports func get_node(uuid: String) -> DeckNode: return _belonging_to.get_node(uuid) 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": [] } 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