UNPKG

@polygonjs/polygonjs

Version:

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

229 lines (228 loc) 7.51 kB
"use strict"; import { Poly } from "../../Poly"; import { NodeCookPerformanceformanceController } from "./cook/PerformanceController"; import { touchNodeRef } from "../../../core/reactivity/NodeReactivity"; var ErrorType = /* @__PURE__ */ ((ErrorType2) => { ErrorType2["FROM_INPUTS"] = "node inputs error"; ErrorType2["INTERNAL"] = "node internal error"; return ErrorType2; })(ErrorType || {}); export class NodeCookController { constructor(node) { this.node = node; this._cooking = false; this._performanceController = new NodeCookPerformanceformanceController( this ); this._inputContainers = []; this._inputContents = []; this._EMPTY_ARRAY = []; // Disallowing inputs evaluation is important for switch nodes (such as SOP and COP) // that should not evaluate all inputs, but only a single one, depending on a param value // currently only for switch SOP and COP this._inputsEvaluationRequired = true; this._corePerformance = this.node.scene().performance; } performanceRecordStarted() { return this._corePerformance.started(); } dispose() { this._clearHooks(); } disallowInputsEvaluation() { this._inputsEvaluationRequired = false; } isCooking() { return this._cooking === true; } _startCookIfNoErrors(inputContents) { if (this.node.states.error.active() || this.node.disposed() == true) { this.endCook(); } else { try { this._performanceController.recordCookStart(); const promise = this.node.cook(inputContents); if (promise != null) { promise.catch((e) => { this._onError(e, "node internal error" /* INTERNAL */, false); }); } } catch (e) { this._onError(e, "node internal error" /* INTERNAL */); } } } async cookMain() { if (this.isCooking()) { return; } if (this.node.disposed() == true) { return; } this._initCookingState(); this.node.states.error.clear(); this.node.scene().cookController.addNode(this.node); try { this._inputContents.length = 0; if (this._inputsEvaluationRequired) { await this._evaluateInputs(this._inputContents); } if (this.node.params.paramsEvalRequired()) { await this._evaluateParams(); } this._startCookIfNoErrors(this._inputContents); } catch (e) { this._onError(e, "node inputs error" /* FROM_INPUTS */); } } _onError(e, errorType, alwaysSet = true) { if (alwaysSet || !this.node.states.error.active()) { const processedError = this.node.processError(e); this.node.states.error.set(`${errorType}: '${processedError}'.`); Poly.warn(e); } this.endCook(); } async cookMainWithoutInputs() { this.node.scene().cookController.addNode(this.node); if (this.isCooking()) { Poly.warn("cook_main_without_inputs already cooking", this.node.path()); return; } this._initCookingState(); this.node.states.error.clear(); if (this.node.params.paramsEvalRequired()) { await this._evaluateParams(); } this._startCookIfNoErrors(this._EMPTY_ARRAY); } endCook() { var _a, _b; this._finalizeCookPerformance(); const dirtyTimestamp = this.node.dirtyController.dirtyTimestamp(); const timestampUnchangedSinceCookStarted = dirtyTimestamp == null || dirtyTimestamp === this._cookingDirtyTimestamp; if (timestampUnchangedSinceCookStarted || ((_b = (_a = this.node.flags) == null ? void 0 : _a.bypass) == null ? void 0 : _b.active())) { this.node.removeDirtyState(); this._terminateCookProcess(); } else { if (this.node.disposed() == true) { return; } Poly.log("COOK AGAIN", dirtyTimestamp, this._cookingDirtyTimestamp, this.node.path()); this._cooking = false; this.cookMain(); } } // private _lastFrameCooked: number | undefined; // private _scenePlayingAndNodeAlreadyCookedForCurrentFrame() { // if (this.node.scene().timeController.playing()) { // return this._lastFrameCooked == this.node.scene().frame(); // } // return false; // } _initCookingState() { this._cooking = true; this._cookingDirtyTimestamp = this.node.dirtyController.dirtyTimestamp(); } _terminateCookProcess() { var _a, _b; if (this.isCooking() || ((_b = (_a = this.node.flags) == null ? void 0 : _a.bypass) == null ? void 0 : _b.active())) { this._cooking = false; this.node.containerController.notifyRequesters(); this._runOnCookCompleteHooks(); if (this.node.disposed() == true) { return; } touchNodeRef(this.node.path()); } } async _evaluateInputs(inputContents) { this._performanceController.recordInputsStart(); const ioOnputs = this.node.io.inputs; this._inputContainers.length = 0; if (this._inputsEvaluationRequired) { if (ioOnputs.isGraphNodeDirty()) { await ioOnputs.evalRequiredInputs(this._inputContainers); } else { ioOnputs.containersWithoutEvaluation(this._inputContainers); } } const inputs = ioOnputs.inputs(); let inputContainer; for (let i = 0; i < inputs.length; i++) { inputContainer = this._inputContainers[i]; if (inputContainer) { if (ioOnputs.cloneRequired(i)) { inputContents[i] = inputContainer.coreContentCloned(); } else { inputContents[i] = inputContainer.coreContent(); } } } this._performanceController.recordInputsEnd(); return inputContents; } async _evaluateParams() { this._performanceController.recordParamsStart(); await this.node.params.evalAll(); this._performanceController.recordParamsEnd(); } // // // PERFORMANCE // // cooksCount() { return this._performanceController.cooksCount(); } cookTime() { return this._performanceController.data().cookTime; } _finalizeCookPerformance() { if (!this._corePerformance.started()) { return; } this._performanceController.recordCookEnd(); this._corePerformance.recordNodeCookData(this.node, this._performanceController.data()); } registerOnCookEnd(callbackName, callback) { this._onCookCompleteHookNames = this._onCookCompleteHookNames || []; this._onCookCompleteHooks = this._onCookCompleteHooks || []; this._onCookCompleteHookNames.push(callbackName); this._onCookCompleteHooks.push(callback); } _clearHooks() { if (!this._onCookCompleteHookNames || !this._onCookCompleteHooks) { return; } for (const hookName of this._onCookCompleteHookNames) { this.deregisterOnCookEnd(hookName); } } deregisterOnCookEnd(callbackName) { var _a; if (!this._onCookCompleteHookNames || !this._onCookCompleteHooks) { return; } const index = (_a = this._onCookCompleteHookNames) == null ? void 0 : _a.indexOf(callbackName); this._onCookCompleteHookNames.splice(index, 1); this._onCookCompleteHooks.splice(index, 1); if (this._onCookCompleteHookNames.length == 0) { this._onCookCompleteHookNames = void 0; } if (this._onCookCompleteHooks.length == 0) { this._onCookCompleteHooks = void 0; } } _runOnCookCompleteHooks() { if (this._onCookCompleteHooks) { const hooks = [...this._onCookCompleteHooks]; for (let hook of hooks) { hook(); } } } onCookEndCallbackNames() { return this._onCookCompleteHookNames; } }