UNPKG

polygonjs-engine

Version:

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

346 lines (314 loc) 12.2 kB
import {PolyScene} from '../scene/PolyScene'; import {CoreGraphNode} from '../../core/graph/CoreGraphNode'; import {UIData} from './utils/UIData'; import {FlagsController, FlagsControllerD} from './utils/FlagsController'; import {StatesController} from './utils/StatesController'; import {HierarchyParentController} from './utils/hierarchy/ParentController'; import {HierarchyChildrenController} from './utils/hierarchy/ChildrenController'; import {LifeCycleController} from './utils/LifeCycleController'; import {TypedContainerController} from './utils/ContainerController'; import {NodeCookController} from './utils/CookController'; import {NameController} from './utils/NameController'; import {NodeSerializer, NodeSerializerData} from './utils/Serializer'; import {ParamsController} from './utils/params/ParamsController'; import {ParamConstructorMap} from '../params/types/ParamConstructorMap'; import {ParamInitValuesTypeMap} from '../params/types/ParamInitValuesTypeMap'; import {NodeParamsConfig} from './utils/params/ParamsConfig'; import {ParamsValueAccessor, ParamsValueAccessorType} from './utils/params/ParamsValueAccessor'; // import {ProcessingContext} from './utils/ProcessingContext'; import {IOController, ParamsInitData} from './utils/io/IOController'; import {NodeEvent} from '../poly/NodeEvent'; import {NodeContext} from '../poly/NodeContext'; import {ParamsAccessorType, ParamsAccessor} from './utils/params/ParamsAccessor'; export interface NodeDeletedEmitData { parent_id: CoreGraphNodeId; } export interface NodeCreatedEmitData { child_node_json: NodeSerializerData; } type EmitDataByNodeEventMapGeneric = {[key in NodeEvent]: any}; export interface EmitDataByNodeEventMap extends EmitDataByNodeEventMapGeneric { [NodeEvent.CREATED]: NodeCreatedEmitData; [NodeEvent.DELETED]: NodeDeletedEmitData; [NodeEvent.ERROR_UPDATED]: undefined; } export interface IntegrationData { name: string; data: PolyDictionary<string>; } // import {ContainerMap, ContainerType} from '../containers/utils/ContainerMap'; import {ContainableMap} from '../containers/utils/ContainableMap'; import {ParamOptions} from '../params/utils/OptionsController'; import {ParamType} from '../poly/ParamType'; import {DisplayNodeController} from './utils/DisplayNodeController'; import {NodeTypeMap} from '../containers/utils/ContainerMap'; import {ParamInitValueSerialized} from '../params/types/ParamInitValueSerialized'; import {ModuleName} from '../poly/registers/modules/_BaseRegister'; import {BasePersistedConfig} from './utils/PersistedConfig'; import {AssemblerName} from '../poly/registers/assemblers/_BaseRegister'; import {PolyNodeController} from './utils/poly/PolyNodeController'; import {CoreGraphNodeId} from '../../core/graph/CoreGraph'; import {PolyDictionary} from '../../types/GlobalTypes'; export class TypedNode<NC extends NodeContext, K extends NodeParamsConfig> extends CoreGraphNode { container_controller: TypedContainerController<NC> = new TypedContainerController<NC>(this); private _parent_controller: HierarchyParentController | undefined; private _ui_data: UIData | undefined; private _states: StatesController | undefined; private _lifecycle: LifeCycleController | undefined; private _serializer: NodeSerializer | undefined; private _cook_controller: NodeCookController<NC> | undefined; public readonly flags: FlagsController | undefined; public readonly display_node_controller: DisplayNodeController | undefined; public readonly persisted_config: BasePersistedConfig | undefined; private _params_controller: ParamsController | undefined; readonly params_config: K | undefined; readonly pv: ParamsValueAccessorType<K> = (<unknown>new ParamsValueAccessor<K>()) as ParamsValueAccessorType<K>; // readonly pv: ParamsValueAccessor<K> = new ParamsValueAccessor<K>(this); readonly p: ParamsAccessorType<K> = (<unknown>new ParamsAccessor<K>()) as ParamsAccessorType<K>; copy_param_values(node: TypedNode<NC, K>) { const non_spare = this.params.non_spare; for (let param of non_spare) { const other_param = node.params.get(param.name()); if (other_param) { param.copy_value(other_param); } } } private _name_controller: NameController | undefined; get parentController(): HierarchyParentController { return (this._parent_controller = this._parent_controller || new HierarchyParentController(this)); } static displayedInputNames(): string[] { return []; } private _children_controller: HierarchyChildrenController | undefined; protected _children_controller_context: NodeContext | undefined; get childrenControllerContext() { return this._children_controller_context; } private _create_children_controller(): HierarchyChildrenController | undefined { if (this._children_controller_context) { return new HierarchyChildrenController(this, this._children_controller_context); } } get childrenController(): HierarchyChildrenController | undefined { return (this._children_controller = this._children_controller || this._create_children_controller()); } childrenAllowed(): boolean { return this._children_controller_context != null; } get uiData(): UIData { return (this._ui_data = this._ui_data || new UIData(this)); } get states(): StatesController { return (this._states = this._states || new StatesController(this)); } get lifecycle(): LifeCycleController { return (this._lifecycle = this._lifecycle || new LifeCycleController(this)); } get serializer(): NodeSerializer { return (this._serializer = this._serializer || new NodeSerializer(this)); } get cookController(): NodeCookController<NC> { return (this._cook_controller = this._cook_controller || new NodeCookController(this)); } protected _io: IOController<NC> | undefined; get io(): IOController<NC> { return (this._io = this._io || new IOController(this)); } get nameController(): NameController { return (this._name_controller = this._name_controller || new NameController(this)); } setName(name: string) { this.nameController.setName(name); } _set_core_name(name: string) { this._name = name; } get params(): ParamsController { return (this._params_controller = this._params_controller || new ParamsController(this)); } // get processing_context(): ProcessingContext { // return (this._processing_context = this._processing_context || new ProcessingContext(this)); // } constructor(scene: PolyScene, name: string = 'BaseNode', public params_init_value_overrides?: ParamsInitData) { super(scene, name); } private _initialized: boolean = false; public initialize_base_and_node() { if (!this._initialized) { this._initialized = true; this.display_node_controller?.initializeNode(); this.initializeBaseNode(); // for base classes of Sop, Obj... this.initializeNode(); // for Derivated node clases, like BoxSop, TransformSop... if (this.polyNodeController) { this.polyNodeController.initializeNode(); } } else { console.warn('node already initialized'); } } protected initializeBaseNode() {} protected initializeNode() {} static type(): string { throw 'type to be overriden'; } type() { const c = this.constructor as typeof BaseNodeClass; return c.type(); } static nodeContext(): NodeContext { console.error('node has no node_context', this); throw 'node_context requires override'; } nodeContext(): NodeContext { const c = this.constructor as typeof BaseNodeClass; return c.nodeContext(); } static require_webgl2(): boolean { return false; } require_webgl2(): boolean { const c = this.constructor as typeof BaseNodeClass; return c.require_webgl2(); } setParent(parent: BaseNodeType | null) { this.parentController.setParent(parent); } parent() { return this.parentController.parent(); } root() { return this._scene.root(); } fullPath(relative_to_parent?: BaseNodeType): string { return this.parentController.fullPath(relative_to_parent); } // params create_params() {} addParam<T extends ParamType>( type: T, name: string, default_value: ParamInitValuesTypeMap[T], options?: ParamOptions ): ParamConstructorMap[T] | undefined { return this._params_controller?.addParam(type, name, default_value, options); } param_default_value(name: string): ParamInitValueSerialized { return null; } // cook cook(input_contents: any[]): any { return null; } // container async requestContainer() { if (!this.isDirty()) { return this.container_controller.container; } else { return await this.container_controller.requestContainer(); } } setContainer(content: ContainableMap[NC], message: string | null = null) { // TODO: typescript: why is this a type of never this.container_controller.container.set_content(content as never); //, this.self.cook_eval_key()); if (content != null) { if (!(content as any).name) { (content as any).name = this.fullPath(); } if (!(content as any).node) { (content as any).node = this; } } this.cookController.end_cook(message); } // hierarchy createNode(node_class: any, params_init_value_overrides?: ParamsInitData) { return this.childrenController?.createNode(node_class, params_init_value_overrides); } create_operation_container( type: string, operation_container_name: string, params_init_value_overrides?: ParamsInitData ) { return this.childrenController?.create_operation_container( type, operation_container_name, params_init_value_overrides ); } removeNode(node: BaseNodeType) { this.childrenController?.removeNode(node); } dispose() { super.dispose(); this.setParent(null); this.io.inputs.dispose(); this.lifecycle.dispose(); this.display_node_controller?.dispose(); this.nameController.dispose(); this.childrenController?.dispose(); this.params.dispose(); } children() { return this.childrenController?.children() || []; } node(path: string) { return this.parentController?.find_node(path) || null; } nodeSibbling(name: string): NodeTypeMap[NC] | null { const parent = this.parent(); if (parent) { const node = parent.childrenController?.child_by_name(name); if (node) { return node as NodeTypeMap[NC]; } } return null; } nodesByType(type: string) { return this.childrenController?.nodesByType(type) || []; } // inputs setInput( input_index_or_name: number | string, node: NodeTypeMap[NC] | null, output_index_or_name: number | string = 0 ) { this.io.inputs.setInput(input_index_or_name, node, output_index_or_name); } // emit emit(event_name: NodeEvent.CREATED, data: EmitDataByNodeEventMap[NodeEvent.CREATED]): void; emit(event_name: NodeEvent.DELETED, data: EmitDataByNodeEventMap[NodeEvent.DELETED]): void; emit(event_name: NodeEvent.NAME_UPDATED): void; emit(event_name: NodeEvent.OVERRIDE_CLONABLE_STATE_UPDATE): void; emit(event_name: NodeEvent.NAMED_INPUTS_UPDATED): void; emit(event_name: NodeEvent.NAMED_OUTPUTS_UPDATED): void; emit(event_name: NodeEvent.INPUTS_UPDATED): void; emit(event_name: NodeEvent.PARAMS_UPDATED): void; emit(event_name: NodeEvent.UI_DATA_POSITION_UPDATED): void; emit(event_name: NodeEvent.UI_DATA_COMMENT_UPDATED): void; emit(event_name: NodeEvent.ERROR_UPDATED): void; emit(event_name: NodeEvent.FLAG_BYPASS_UPDATED): void; emit(event_name: NodeEvent.FLAG_DISPLAY_UPDATED): void; emit(event_name: NodeEvent.FLAG_OPTIMIZE_UPDATED): void; emit(event_name: NodeEvent.SELECTION_UPDATED): void; emit(event_name: NodeEvent, data: object | null = null): void { this.scene().dispatchController.dispatch(this, event_name, data); } // serializer toJSON(include_param_components: boolean = false) { return this.serializer.toJSON(include_param_components); } // modules public async requiredModules(): Promise<ModuleName[] | void> {} public usedAssembler(): AssemblerName | void {} public integrationData(): IntegrationData | void {} // poly nodes public readonly polyNodeController: PolyNodeController | undefined; } export type BaseNodeType = TypedNode<any, any>; export class BaseNodeClass extends TypedNode<any, any> {} export class BaseNodeClassWithDisplayFlag extends TypedNode<any, any> { public readonly flags: FlagsControllerD = new FlagsControllerD(this); }