UNPKG

@polygonjs/polygonjs

Version:

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

242 lines (224 loc) 8.12 kB
import {PolyDictionary} from '../../../types/GlobalTypes'; import {PolyScene} from '../PolyScene'; import {RootManagerNode, ROOT_NODE_NAME} from '../../nodes/manager/Root'; import {stringMatchMask} from '../../../core/String'; import {BaseNodeType} from '../../nodes/_Base'; import {NodeContext} from '../../poly/NodeContext'; import {NodeChildrenMapByContext} from '../../poly/registers/nodes/All'; import {CoreGraphNodeId} from '../../../core/graph/CoreGraph'; import {NodeCreateOptions} from '../../nodes/utils/hierarchy/ChildrenController'; type NodeByNodeId = Map<CoreGraphNodeId, BaseNodeType>; type NodeMapByType<NC extends NodeContext> = Map<keyof NodeChildrenMapByContext[NC], NodeByNodeId>; export class NodesController { constructor(private scene: PolyScene) {} _root!: RootManagerNode; _nodeContextSignatures: PolyDictionary<boolean> = {}; _instanciatedNodesByContextAndType: Map<NodeContext, NodeMapByType<NodeContext>> = new Map(); createRoot(options?: NodeCreateOptions) { this._root = new RootManagerNode(this.scene, ROOT_NODE_NAME, options); this._root.initializeBaseAndNode(); this._root.params.init(); } root() { return this._root; } private _traverseNode(parent: BaseNodeType, callback: (node: BaseNodeType) => void) { const nodes = parent.children(); if (!nodes || nodes.length == 0) { return; } for (const node of nodes) { if (node.childrenController) { this._traverseNode(node, callback); } callback(node); } } traverseNodes(callback: (node: BaseNodeType) => void) { this._traverseNode(this._root, callback); } // objectsFromMask(mask: string): Object3D[] { // const masks = mask.split(' '); // const child_nodes = this.root.children() as BaseObjNodeType[]; // const objects: Object3D[] = []; // for (let child_node of child_nodes) { // if (CoreString.matchesOneMask(child_node.name, masks)) { // if (child_node.object) { // objects.push(child_node.object); // } // } // } // return objects; // } clear() { const children = this.root().children(); for (const child of children) { this.root().childrenController?.removeNode(child); } // return children.forEach(child=> { // return this.root().removeNode(child); // }); } node(path: string) { if (path === '/') { return this.root(); } else { return this.root().node(path); } } allNodes() { let nodes: BaseNodeType[] = [this.root()]; let current_parents: BaseNodeType[] = [this.root()]; let cmptr = 0; while (current_parents.length > 0 && cmptr < 10) { const children = current_parents .map((current_parent) => { if (current_parent.childrenAllowed()) { return current_parent.children(); } else { return []; } }) .flat(); nodes = nodes.concat(children); current_parents = children; cmptr += 1; } return nodes.flat(); } nodesFromMask(mask: string) { const nodes = this.allNodes(); const matching_nodes: BaseNodeType[] = []; for (const node of nodes) { const path = node.path(); if (stringMatchMask(path, mask)) { matching_nodes.push(node); } } return matching_nodes; } resetNodeContextSignatures() { this._nodeContextSignatures = {}; } registerNodeContextSignature(node: BaseNodeType) { if (node.childrenAllowed() && node.childrenController) { this._nodeContextSignatures[node.childrenController.nodeContextSignature()] = true; } } nodeContextSignatures() { return Object.keys(this._nodeContextSignatures) .sort() .map((s) => s.toLowerCase()); } addToInstanciatedNode<NC extends NodeContext>(node: BaseNodeType) { const context = node.context() as NC; const nodeType = node.type() as keyof NodeChildrenMapByContext[NC]; let mapForContext: NodeMapByType<NC> | undefined = this._instanciatedNodesByContextAndType.get(context); if (!mapForContext) { mapForContext = new Map() as NodeMapByType<NC>; this._instanciatedNodesByContextAndType.set(context, mapForContext as any); } let mapForType = mapForContext.get(nodeType); if (!mapForType) { mapForType = new Map() as NodeByNodeId; mapForContext.set(nodeType, mapForType); } mapForType.set(node.graphNodeId(), node); // this._instanciated_nodes_by_context_and_type[context] = // this._instanciated_nodes_by_context_and_type[context] || {}; // this._instanciated_nodes_by_context_and_type[context][node_type] = // this._instanciated_nodes_by_context_and_type[context][node_type] || {}; // this._instanciated_nodes_by_context_and_type[context][node_type][node.graphNodeId()] = node; } removeFromInstanciatedNode<NC extends NodeContext>(node: BaseNodeType) { const context = node.context() as NC; const nodeType = node.type() as keyof NodeChildrenMapByContext[NC]; const mapForContext: NodeMapByType<NC> | undefined = this._instanciatedNodesByContextAndType.get(context); if (!mapForContext) { return; } const mapForType = mapForContext.get(nodeType); if (!mapForType) { return; } mapForType.delete(node.graphNodeId()); // delete this._instanciated_nodes_by_context_and_type[context][node_type][node.graphNodeId()]; } nodesByType(type: string): BaseNodeType[] { const list: BaseNodeType[] = []; this._traverseNode(this.scene.root(), (node) => { if (node.type() == type) { list.push(node); } }); return list; } nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.ANIM]>( context: NodeContext.ANIM, node_type: T ): NodeChildrenMapByContext[NodeContext.ANIM][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.AUDIO]>( context: NodeContext.AUDIO, node_type: T ): NodeChildrenMapByContext[NodeContext.AUDIO][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.COP]>( context: NodeContext.COP, node_type: T ): NodeChildrenMapByContext[NodeContext.COP][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.EVENT]>( context: NodeContext.EVENT, node_type: T ): NodeChildrenMapByContext[NodeContext.EVENT][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.GL]>( context: NodeContext.GL, node_type: T ): NodeChildrenMapByContext[NodeContext.GL][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.JS]>( context: NodeContext.JS, node_type: T ): NodeChildrenMapByContext[NodeContext.JS][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.MAT]>( context: NodeContext.MAT, node_type: T ): NodeChildrenMapByContext[NodeContext.MAT][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.OBJ]>( context: NodeContext.OBJ, node_type: T ): NodeChildrenMapByContext[NodeContext.OBJ][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.POST]>( context: NodeContext.POST, node_type: T ): NodeChildrenMapByContext[NodeContext.POST][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.ROP]>( context: NodeContext.ROP, node_type: T ): NodeChildrenMapByContext[NodeContext.ROP][T][]; nodesByContextAndType<T extends keyof NodeChildrenMapByContext[NodeContext.SOP]>( context: NodeContext.SOP, node_type: T ): NodeChildrenMapByContext[NodeContext.SOP][T][]; nodesByContextAndType<NC extends NodeContext>(context: NC, nodeType: string) { const nodes: BaseNodeType[] = []; const mapForContext: NodeMapByType<NC> | undefined = this._instanciatedNodesByContextAndType.get(context); if (mapForContext) { const mapForType = mapForContext.get(nodeType as any); if (mapForType) { mapForType.forEach((node) => { nodes.push(node); }); } } return nodes; } hasNodesByContextAndType<NC extends NodeContext>(context: NC, nodeType: string) { const mapForContext: NodeMapByType<NC> | undefined = this._instanciatedNodesByContextAndType.get(context); if (!mapForContext) { return false; } const mapForType = mapForContext.get(nodeType as any); if (!mapForType) { return false; } return mapForType.size != 0; } }