UNPKG

polygonjs-engine

Version:

node-based webgl 3D engine https://polygonjs.com

343 lines (342 loc) 11.2 kB
import {TypedNodeConnection} from "./NodeConnection"; import {CoreGraphNode as CoreGraphNode2} from "../../../../core/graph/CoreGraphNode"; import {NodeEvent as NodeEvent2} from "../../../poly/NodeEvent"; import {ClonedStatesController as ClonedStatesController2} from "./utils/ClonedStatesController"; import {CoreType} from "../../../../core/Type"; export class InputsController { constructor(node) { this.node = node; this._graph_node_inputs = []; this._inputs = []; this._has_named_inputs = false; this._min_inputs_count = 0; this._max_inputs_count = 0; this._depends_on_inputs = true; } dispose() { if (this._graph_node) { this._graph_node.dispose(); } for (let graph_node of this._graph_node_inputs) { if (graph_node) { graph_node.dispose(); } } this._on_update_hooks = void 0; this._on_update_hook_names = void 0; } set_depends_on_inputs(depends_on_inputs) { this._depends_on_inputs = depends_on_inputs; } set_min_inputs_count(min_inputs_count) { this._min_inputs_count = min_inputs_count; } set_max_inputs_count(max_inputs_count) { this._max_inputs_count = max_inputs_count; this.init_graph_node_inputs(); } named_input_connection_points_by_name(name) { if (this._named_input_connection_points) { for (let connection_point of this._named_input_connection_points) { if (connection_point && connection_point.name() == name) { return connection_point; } } } } setNamedInputConnectionPoints(connection_points) { this._has_named_inputs = true; const connections = this.node.io.connections.input_connections(); if (connections) { for (let connection of connections) { if (connection) { if (connection.input_index >= connection_points.length) { connection.disconnect({setInput: true}); } } } } this._named_input_connection_points = connection_points; this.set_min_inputs_count(0); this.set_max_inputs_count(connection_points.length); this.init_graph_node_inputs(); this.node.emit(NodeEvent2.NAMED_INPUTS_UPDATED); } get has_named_inputs() { return this._has_named_inputs; } get named_input_connection_points() { return this._named_input_connection_points || []; } init_graph_node_inputs() { for (let i = 0; i < this._max_inputs_count; i++) { this._graph_node_inputs[i] = this._graph_node_inputs[i] || this._create_graph_node_input(i); } } _create_graph_node_input(index) { const graph_input_node = new CoreGraphNode2(this.node.scene(), `input_${index}`); if (!this._graph_node) { this._graph_node = new CoreGraphNode2(this.node.scene(), "inputs"); this.node.addGraphInput(this._graph_node, false); } this._graph_node.addGraphInput(graph_input_node, false); return graph_input_node; } get max_inputs_count() { return this._max_inputs_count || 0; } input_graph_node(input_index) { return this._graph_node_inputs[input_index]; } setCount(min, max) { if (max == null) { max = min; } this.set_min_inputs_count(min); this.set_max_inputs_count(max); this.init_connections_controller_inputs(); } init_connections_controller_inputs() { this.node.io.connections.init_inputs(); } is_any_input_dirty() { return this._graph_node?.isDirty() || false; } async containers_without_evaluation() { const containers = []; for (let i = 0; i < this._inputs.length; i++) { const input_node = this._inputs[i]; let container = void 0; if (input_node) { container = await input_node.requestContainer(); } containers.push(container); } return containers; } existing_input_indices() { const existing_input_indices = []; if (this._max_inputs_count > 0) { for (let i = 0; i < this._inputs.length; i++) { if (this._inputs[i]) { existing_input_indices.push(i); } } } return existing_input_indices; } async eval_required_inputs() { let containers = []; if (this._max_inputs_count > 0) { const existing_input_indices = this.existing_input_indices(); if (existing_input_indices.length < this._min_inputs_count) { this.node.states.error.set("inputs are missing"); } else { if (existing_input_indices.length > 0) { const promises = []; let input; for (let i = 0; i < this._inputs.length; i++) { input = this._inputs[i]; if (input) { promises.push(this.eval_required_input(i)); } } containers = await Promise.all(promises); this._graph_node?.removeDirtyState(); } } } return containers; } async eval_required_input(input_index) { let container = void 0; const input_node = this.input(input_index); if (input_node) { container = await input_node.requestContainer(); this._graph_node_inputs[input_index].removeDirtyState(); } if (container && container.coreContent()) { } else { const input_node2 = this.input(input_index); if (input_node2) { const input_error_message = input_node2.states.error.message(); if (input_error_message) { this.node.states.error.set(`input ${input_index} is invalid (error: ${input_error_message})`); } } } return container; } get_named_input_index(name) { if (this._named_input_connection_points) { for (let i = 0; i < this._named_input_connection_points.length; i++) { if (this._named_input_connection_points[i]?.name() == name) { return i; } } } return -1; } get_input_index(input_index_or_name) { if (CoreType.isString(input_index_or_name)) { if (this.has_named_inputs) { return this.get_named_input_index(input_index_or_name); } else { throw new Error(`node ${this.node.fullPath()} has no named inputs`); } } else { return input_index_or_name; } } setInput(input_index_or_name, node, output_index_or_name = 0) { const input_index = this.get_input_index(input_index_or_name) || 0; if (input_index < 0) { const message = `invalid input (${input_index_or_name}) for node ${this.node.fullPath()}`; console.warn(message); throw new Error(message); } let output_index = 0; if (node) { if (node.io.outputs.has_named_outputs) { output_index = node.io.outputs.get_output_index(output_index_or_name); if (output_index == null || output_index < 0) { const connection_points = node.io.outputs.named_output_connection_points; const names = connection_points.map((cp) => cp.name()); console.warn(`node ${node.fullPath()} does not have an output named ${output_index_or_name}. inputs are: ${names.join(", ")}`); return; } } } const graph_input_node = this._graph_node_inputs[input_index]; if (graph_input_node == null) { const message = `graph_input_node not found at index ${input_index}`; console.warn(message); throw new Error(message); } if (node && this.node.parent() != node.parent()) { return; } const old_input_node = this._inputs[input_index]; let old_output_index = null; let old_connection = void 0; if (this.node.io.connections) { old_connection = this.node.io.connections.input_connection(input_index); } if (old_connection) { old_output_index = old_connection.output_index; } if (node !== old_input_node || output_index != old_output_index) { if (old_input_node != null) { if (this._depends_on_inputs) { graph_input_node.removeGraphInput(old_input_node); } } if (node != null) { if (graph_input_node.addGraphInput(node)) { if (!this._depends_on_inputs) { graph_input_node.removeGraphInput(node); } if (old_connection) { old_connection.disconnect({setInput: false}); } this._inputs[input_index] = node; new TypedNodeConnection(node, this.node, output_index, input_index); } else { console.warn(`cannot connect ${node.fullPath()} to ${this.node.fullPath()}`); } } else { this._inputs[input_index] = null; if (old_connection) { old_connection.disconnect({setInput: false}); } } this._run_on_set_input_hooks(); graph_input_node.setSuccessorsDirty(); this.node.emit(NodeEvent2.INPUTS_UPDATED); } } remove_input(node) { const inputs = this.inputs(); let input; for (let i = 0; i < inputs.length; i++) { input = inputs[i]; if (input != null && node != null) { if (input.graphNodeId() === node.graphNodeId()) { this.setInput(i, null); } } } } input(input_index) { return this._inputs[input_index]; } named_input(input_name) { if (this.has_named_inputs) { const input_index = this.get_input_index(input_name); return this._inputs[input_index]; } else { return null; } } named_input_connection_point(input_name) { if (this.has_named_inputs && this._named_input_connection_points) { const input_index = this.get_input_index(input_name); return this._named_input_connection_points[input_index]; } } has_named_input(name) { return this.get_named_input_index(name) >= 0; } has_input(input_index) { return this._inputs[input_index] != null; } inputs() { return this._inputs; } initInputsClonedState(states) { if (!this._cloned_states_controller) { this._cloned_states_controller = new ClonedStatesController2(this); this._cloned_states_controller.init_inputs_cloned_state(states); } } override_cloned_state_allowed() { return this._cloned_states_controller?.override_cloned_state_allowed() || false; } override_cloned_state(state) { this._cloned_states_controller?.override_cloned_state(state); } cloned_state_overriden() { return this._cloned_states_controller?.overriden() || false; } clone_required(index) { const state = this._cloned_states_controller?.clone_required_state(index); if (state != null) { return state; } return true; } clone_required_states() { const states = this._cloned_states_controller?.clone_required_states(); if (states != null) { return states; } return true; } add_on_set_input_hook(name, hook) { this._on_update_hooks = this._on_update_hooks || []; this._on_update_hook_names = this._on_update_hook_names || []; if (!this._on_update_hook_names.includes(name)) { this._on_update_hooks.push(hook); this._on_update_hook_names.push(name); } else { console.warn(`hook with name ${name} already exists`, this.node); } } _run_on_set_input_hooks() { if (this._on_update_hooks) { for (let hook of this._on_update_hooks) { hook(); } } } }