UNPKG

@polygonjs/polygonjs

Version:

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

167 lines (157 loc) 6.42 kB
import type {TypedNode, BaseNodeType} from '../../../nodes/_Base'; import type {JsonImportDispatcher} from './Dispatcher'; import type {SceneJsonImporter} from '../../../io/json/import/Scene'; import {NodeContext} from '../../../poly/NodeContext'; import type {NodeJsonExporterData} from '../export/Node'; import {ParamJsonImporter} from './Param'; import {OptimizedNodesJsonImporter} from './OptimizedNodes'; import type {PolyNodeJsonImporter} from './nodes/Poly'; import {Poly} from '../../../Poly'; import type {NodeJsonImporter} from './Node'; import {CoreString} from '../../../../core/String'; import {PolyDictionary} from '../../../../types/GlobalTypes'; import type {NodeCreateOptions} from '../../../nodes/utils/hierarchy/ChildrenController'; type BaseNodeTypeWithIO = TypedNode<NodeContext, any>; export class NodesJsonImporter<T extends BaseNodeTypeWithIO> { constructor(protected _node: T, protected dispatcher: JsonImportDispatcher) {} process_data(sceneImporter: SceneJsonImporter, data?: PolyDictionary<NodeJsonExporterData>) { if (!data) { return; } if (!(this._node.childrenAllowed() && this._node.childrenController)) { return; } const {optimized_names, non_optimized_names} = OptimizedNodesJsonImporter.child_names_by_optimized_state(data); const nonOptimizedNodes: BaseNodeTypeWithIO[] = []; const migrateHelper = sceneImporter.migrateHelper(); for (let nodeName of non_optimized_names) { const node_data = data[nodeName]; const nodeType = migrateHelper ? migrateHelper.migrateNodeType(this._node, node_data) : node_data.type; migrateHelper?.migrateParams(this._node, node_data); const paramsInitValueOverrides = ParamJsonImporter.non_spare_params_data_value(node_data['params']); const nodeCreateOptions: NodeCreateOptions = { paramsInitValueOverrides, nodeName, }; const loadNodeAttempt = (nodeType: string, nodeCreateOptions: NodeCreateOptions) => { try { // try with current type const node = this._node.createNode(nodeType, nodeCreateOptions); if (node) { return node; } } catch (e) { console.error(`error importing node: cannot create with type ${nodeType}`, e); } }; let node = loadNodeAttempt(nodeType, nodeCreateOptions); if (!node) { // try with camelCased type const nodeTypeCamelCase = CoreString.camelCase(nodeType); node = loadNodeAttempt(nodeTypeCamelCase, nodeCreateOptions); } if (!node) { // add Network const nodeTypeWithNetwork = `${nodeType}Network`; node = loadNodeAttempt(nodeTypeWithNetwork, nodeCreateOptions); } if (node) { nonOptimizedNodes.push(node); } else { const message = `failed to create node with type '${nodeType}' (in '${this._node.path()}')`; sceneImporter.report.addWarning(message); Poly.warn(message); } // try { // // try with current type // const node = this._node.createNode(nodeType, nodeCreateOptions); // if (node) { // // node.setName(node_name); // nonOptimizedNodes.push(node); // } // } catch (e) { // // try with camelCased type // console.error(`error importing node: cannot create with type ${nodeType}`, e); // const nodeTypeCamelCase = CoreString.camelCase(nodeType); // try { // const node = this._node.createNode(nodeTypeCamelCase, nodeCreateOptions); // if (node) { // // node.setName(node_name); // nonOptimizedNodes.push(node); // } // } catch (e) { // // add Network // const nodeTypeWithNetwork = `${nodeType}Network`; // try { // const node = this._node.createNode(nodeTypeWithNetwork, nodeCreateOptions); // if (node) { // // node.setName(node_name); // nonOptimizedNodes.push(node); // } // } catch (e) { // const message = `failed to create node with type '${nodeType}', '${nodeTypeCamelCase}' or '${nodeTypeWithNetwork}'`; // scene_importer.report.addWarning(message); // Poly.warn(message, e); // } // } // } } if (optimized_names.length > 0) { const optimized_nodes_importer = new OptimizedNodesJsonImporter(this._node); optimized_nodes_importer.process_data(sceneImporter, data); // ensure that the display node is still created // as it may not be if the display flag is set to a node that will // be part of an optimized series of nodes // for instance // A -> B > C // D -> E // if A, B and C are optimized, // and D, E are not // And B has the display flag, // what will happen is that B will not exist anymore // and the display flag will end up in either C, D or E // which can lead to unexpected display in the player if (this._node.childrenController.context == NodeContext.SOP) { const nodeNames = Object.keys(data); let nodeNameWithDisplayFlag: string | undefined = undefined; for (let nodeName of nodeNames) { const nodeData = data[nodeName]; if (nodeData.flags?.display) { nodeNameWithDisplayFlag = nodeName; } } if (nodeNameWithDisplayFlag) { const existingNodeNames = nonOptimizedNodes.map((n) => n.name()); const optimizedNodes = optimized_nodes_importer.nodes(); for (let optimizedNode of optimizedNodes) { existingNodeNames.push(optimizedNode.name()); } if (!existingNodeNames.includes(nodeNameWithDisplayFlag)) { const parentFullPath = this._node.path(); const nodeFullPath = `${parentFullPath}/${nodeNameWithDisplayFlag}`; const message = `node '${nodeFullPath}' with display flag has been optimized and does not exist in player mode`; console.error(message); } } } } const importers_by_node_name: Map<string, PolyNodeJsonImporter | NodeJsonImporter<BaseNodeType>> = new Map(); for (let node of nonOptimizedNodes) { const child_data = data[node.name()]; if (child_data) { const importer = this.dispatcher.dispatchNode(node); importers_by_node_name.set(node.name(), importer); importer.process_data(sceneImporter, data[node.name()]); } else { Poly.warn(`possible import error for node ${node.name()}`); Poly.log('available names are', Object.keys(data).sort(), data); } } for (let node of nonOptimizedNodes) { const importer = importers_by_node_name.get(node.name()); if (importer) { importer.process_inputs_data(sceneImporter, data[node.name()]); } } } }