/** * @module nodeUtils * Utilities to process scene nodes. */ /** * @typedef {Object} SceneNode * @property {String} label Required * @property {String} model * @property {Boolean} isMain * @property {Number|null} opacity * @property {SceneNode[]|null} children */ /** * @typedef {Object} NormalizedSceneNode * @property {String} label Required * @property {String} id * @property {String} model * @property {Boolean} isMain * @property {Number|null} opacity * @property {Boolean} active */ /** * * @param {SceneNode} node * @param {Array} flatList * @param {Number} depth */ function traverseTree(node, flatList, depth = 1, inheritedColor = null) { if (!node.label) { console.error("Node missing label:", node); return; } const color = node.color ?? inheritedColor; const normNode = { ...node, id: node.id ?? node.label, isMain: node.isMain ?? false, active: true, color: color ?? null, depth, children: [], }; if (node.model) { normNode.model = node.model; } flatList.push(normNode); if (node.children && Array.isArray(node.children)) { for(const child of node.children) { normNode.children.push( traverseTree(child, flatList, depth + 1, color) ); } } return normNode; } /** * Create a flat list of nodes from * the nested structure in config * @param {Array} nodes * @returns {{flat: NormalizedSceneNode[], tree: NormalizedSceneNode[]}} A flat list of nodes **/ export function normalizeNodes (nodes) { let flatList = []; const normNode = traverseTree(nodes, flatList); return {flat: flatList, tree: normNode.children}; }