UNPKG

@polygonjs/polygonjs

Version:

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

231 lines (230 loc) 8.37 kB
"use strict"; import { CoreFeaturesController } from "./../../../../../core/FeaturesController"; import { ParamConfig } from "../../../utils/params/ParamsConfig"; import { setToArray } from "../../../../../core/SetUtils"; import { Poly } from "../../../../Poly"; import { arrayUniq, arrayCompact, arrayToSet } from "../../../../../core/ArrayUtils"; class NodeGroup { constructor(nodes) { this.nodes = nodes; this._remaining = /* @__PURE__ */ new Set(); if (CoreFeaturesController.debugLoadProgress()) { console.log(nodes); } this.totalCount = nodes.length; this._processed = /* @__PURE__ */ new Set(); arrayToSet(nodes, this._remaining); } markNodeAsProcessed(node) { this._processed.add(node); this._remaining.delete(node); if (CoreFeaturesController.debugLoadProgress()) { console.log("markNodeAsProcessed", node.path(), { processed: setToArray(this._processed, []).map((n) => n.path()), remaining: setToArray(this._remaining, []).map((n) => n.path()) }); } } isNodeProcessed(node) { return this._processed.has(node); } processedCount() { return this._processed.size; } } export function RootLoadProgressParamConfig(Base) { return class Mixin extends Base { constructor() { super(...arguments); /** @param when the scene loads, nodes that match the mask will update the progress bar as they cook */ this.nodesMask = ParamConfig.STRING("*/image* */envMap*", { cook: false, separatorBefore: true, objectMask: false // do not use objectMask, since it is a node mask, not object }); /** @param prints which nodes match the mask in the console */ this.printNodes = ParamConfig.BUTTON(null, { cook: false, callback: (node) => { RootLoadProgressController.PARAM_CALLBACK_printResolve(node); } // objectMask: false // do not use objectMask, since it is a node mask, not object }); } }; } export class RootLoadProgressController { constructor(node) { this.node = node; } static async PARAM_CALLBACK_printResolve(node) { const nodes = await node.loadProgress.resolvedNodes(); console.log(nodes); const nodePaths = nodes.map((node2) => node2.path()).sort(); console.log(nodePaths); } async resolvedNodes() { const param = this.node.p.nodesMask; if (param.isDirty()) { await param.compute(); } const mask = param.value; const scene = this.node.scene(); const nodes = scene.nodesController.nodesFromMask(mask || ""); const nodeDisplayNodes = await this._loadDisplayNodes(); const uniqNodes = []; arrayUniq(nodes.concat(nodeDisplayNodes), uniqNodes); return uniqNodes; } async _loadDisplayNodes() { const scene = this.node.scene(); const cameraNodeTypes = Poly.camerasRegister.registeredNodeTypes(); const cameraNodes = cameraNodeTypes.map((type) => scene.nodesByType(type)).flat(); const displayNodes = this._displayNodes(); const nodes = cameraNodes.concat(displayNodes); const cameraCreatorNode = await this.cameraCreatorNode(); if (cameraCreatorNode) { nodes.push(cameraCreatorNode); } const uniqNodes = []; arrayUniq(nodes, uniqNodes); return uniqNodes; } _displayNodes() { const objNodesWithDisplayNodeController = this._objectNodesWithDisplayNodeController(); const displayNodes = []; arrayCompact( objNodesWithDisplayNodeController.map((node) => node.displayNodeController.firstNonBypassedDisplayNode()), displayNodes ); return displayNodes; } _objectNodesWithDisplayNodeController() { const scene = this.node.scene(); const objNodesWithDisplayNodeController = scene.root().children().filter((node) => node.displayNodeController != null).filter((node) => { var _a, _b; return (_b = (_a = node.flags) == null ? void 0 : _a.display) == null ? void 0 : _b.active(); }); return objNodesWithDisplayNodeController; } // private _getNodesWithSopGroup() { // return this._displayNodes().filter((node) => (node as GeoObjNode).childrenDisplayController != null); // } cameraCreatorNode() { return this.node.mainCameraController.cameraCreatorNode(); } _runCallback(progress, nodeTrigger) { this._debug2("_runCallback", { progress, nodeTrigger }); if (!(this._onProgressUpdateCallback && this._nodeGroups)) { return; } this._debug2("_onProgressUpdateCallback", this._nodeGroups); this._onProgressUpdateCallback(progress, { scene: this.node.scene(), triggerNode: void 0, groups: this._nodeGroups }); } _updateProgressAndRunCallback(nodeTrigger) { if (!(this._onProgressUpdateCallback && this._nodeGroups)) { return; } const totalNodesCount = this._nodeGroups.toCook.totalCount + this._nodeGroups.sopGroupToUpdate.totalCount; const processedNodesCount = this._nodeGroups.toCook.processedCount() + this._nodeGroups.sopGroupToUpdate.processedCount(); const progress = processedNodesCount / totalNodesCount; this._runCallback(progress, nodeTrigger); } async watchNodesProgress(callback) { this._onProgressUpdateCallback = callback; const resolvedNodes = await this.resolvedNodes(); const nodesToCook = resolvedNodes.filter((node) => node.isDirty()); this._debug({ nodesToCook }); const nodesToUpdateSopGroup = this._objectNodesWithDisplayNodeController().filter((node) => { var _a; const displayNode = node.displayNodeController.displayNode(); return displayNode != null && !((_a = displayNode.flags.bypass) == null ? void 0 : _a.active()); }).filter((node) => node.isDirty()); this._debug({ nodesToUpdateSopGroup }); this._nodeGroups = { toCook: new NodeGroup(nodesToCook), sopGroupToUpdate: new NodeGroup(nodesToUpdateSopGroup) }; const totalNodesCount = this._nodeGroups.toCook.totalCount + this._nodeGroups.sopGroupToUpdate.totalCount; this._debug({ totalNodesCount }); if (totalNodesCount == 0) { this._runCallback(1); return; } this._watchNodesWithSopGroup(); this._watchNodesToCook(); } async _watchNodesToCook() { var _a; const nodesGroup = (_a = this._nodeGroups) == null ? void 0 : _a.toCook; if (!nodesGroup) { return; } const callbackName = "RootLoadProgressController"; const onNodeCooked = (node) => { if (!nodesGroup.isNodeProcessed(node)) { nodesGroup.markNodeAsProcessed(node); this._updateProgressAndRunCallback(node); node.cookController.deregisterOnCookEnd(callbackName); } }; for (const node of nodesGroup.nodes) { node.cookController.registerOnCookEnd(callbackName, () => { this._debug2("nodeToCook - completed", node.path()); onNodeCooked(node); }); this._debug2("nodeToCook - start", node.path()); node.compute(); } } _watchNodesWithSopGroup() { var _a; const nodesGroup = (_a = this._nodeGroups) == null ? void 0 : _a.sopGroupToUpdate; if (!nodesGroup) { return; } const callbackName = "RootLoadProgressController"; const onNodeCooked = (node) => { if (!nodesGroup.isNodeProcessed(node)) { nodesGroup.markNodeAsProcessed(node); this._updateProgressAndRunCallback(node); const childrenDisplayController = node.childrenDisplayController; childrenDisplayController.deregisterOnSopGroupUpdated(callbackName); } }; for (const node of nodesGroup.nodes) { const childrenDisplayController = node.childrenDisplayController; this._debug2("nodeWithSopGroup - watch", node.path()); childrenDisplayController.registerOnSopGroupUpdated(callbackName, () => { this._debug2("nodeWithSopGroup - completed", node.path()); onNodeCooked(node); }); } } static debugActive() { return CoreFeaturesController.debugLoadProgress(); } static debug(arg0) { if (!this.debugActive()) { return; } console.log(arg0); } static debug2(arg0, arg1) { if (!this.debugActive()) { return; } console.log(arg0, arg1); } _debug(arg0) { RootLoadProgressController.debug(arg0); } _debug2(arg0, arg1) { RootLoadProgressController.debug2(arg0, arg1); } }