UNPKG

@polygonjs/polygonjs

Version:

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

166 lines (165 loc) 6.27 kB
"use strict"; import { JsNodeFinder } from "../../engine/nodes/js/code/utils/NodeFinder"; import { ActorEvaluator } from "../../engine/nodes/js/code/assemblers/actor/ActorEvaluator"; import { ActorEvaluatorGenerator } from "../../engine/nodes/js/code/assemblers/actor/ActorEvaluatorGenerator"; import { computed, ref, watch } from "../reactivity/CoreReactivity"; import { Object3D } from "three"; import { FUNC_POINTS_COUNT_FROM_OBJECT, FUNC_CORE_PRIMITIVE_CLASS_FACTORY } from "../../engine/nodes/js/utils/Common"; import { pointsCountFromObject } from "../geometry/entities/point/CorePointUtils"; import { corePrimitiveClassFactory } from "../geometry/CoreObjectFactory"; import { arrayToSet } from "../ArrayUtils"; const FUNCTION_ARGS_DICT = { [FUNC_POINTS_COUNT_FROM_OBJECT]: pointsCountFromObject, [FUNC_CORE_PRIMITIVE_CLASS_FACTORY]: corePrimitiveClassFactory, ActorEvaluator, computed, ref, watch }; const FUNCTION_ARG_NAMES = Object.keys(FUNCTION_ARGS_DICT); const FUNCTION_ARGS = FUNCTION_ARG_NAMES.map((argName) => FUNCTION_ARGS_DICT[argName]); export const ACTOR_COMPILATION_CONTROLLER_DUMMY_OBJECT_NAME = "ActorCompilationController-DUMMY"; function _createDummyObject() { const object = new Object3D(); object.name = ACTOR_COMPILATION_CONTROLLER_DUMMY_OBJECT_NAME; return object; } export const ACTOR_COMPILATION_CONTROLLER_DUMMY_OBJECT = _createDummyObject(); export class ActorCompilationController { constructor(node) { this.node = node; this._evaluatorGenerator = new ActorEvaluatorGenerator( (object) => new ActorEvaluator(this.node, object) ); } compileIfRequired() { var _a; if ((_a = this.node.assemblerController()) == null ? void 0 : _a.compileRequired()) { this.compile(); } this._evaluatorGenerator.clearObjects(); } evaluatorGenerator() { return this._evaluatorGenerator; } functionData() { return this._functionData; } _resetFunctionData() { this._functionData = void 0; } updateFromFunctionData(functionData) { this._functionData = functionData; const { functionBody, variableNames, variablesByName, functionNames, functionsByName, paramConfigs, eventDatas } = this._functionData; const wrappedBody = ` try { ${functionBody} } catch(e) { console.log(e); _setErrorFromError(e) return null }`; const _setErrorFromError = (e) => { this.node.states.error.set(e.message); }; const variables = []; const functions = []; for (const variableName of variableNames) { const variable = variablesByName[variableName]; variables.push(variable); } for (const functionName of functionNames) { const _func = functionsByName[functionName]; functions.push(_func); } const paramConfigUniformNames = paramConfigs.map((pc) => pc.uniformName()); paramConfigs.forEach((p) => p.applyToNode(this.node)); const functionCreationArgs = [ ...FUNCTION_ARG_NAMES, "_setErrorFromError", ...variableNames, ...functionNames, // ...FUNCTION_UTILS.names, ...paramConfigUniformNames, wrappedBody ]; const functionEvalArgs = () => [ ...FUNCTION_ARGS, _setErrorFromError, // it is currently preferable to create a unique set of variables // for each evaluator ...variables.map((v) => v.clone()), ...functions // ...FUNCTION_UTILS.functions, ]; try { const _function = new Function(...functionCreationArgs); const _createEvaluator = (object) => { const evaluatorClass = _function(...functionEvalArgs()); const evaluator = new evaluatorClass(this.node, object); return evaluator; }; const evaluatorGenerator = new ActorEvaluatorGenerator((object) => { const evaluator = _createEvaluator(object); return this.node.scene().dispatchController.processActorEvaluator(evaluator) || evaluator; }); const dummyEvaluator = _createEvaluator(ACTOR_COMPILATION_CONTROLLER_DUMMY_OBJECT); evaluatorGenerator.setExpectedEvaluatorMethodNames(dummyEvaluator); evaluatorGenerator.eventDatas = evaluatorGenerator.eventDatas || /* @__PURE__ */ new Set(); arrayToSet(eventDatas, evaluatorGenerator.eventDatas); this._setEvaluatorGenerator(evaluatorGenerator); } catch (e) { console.warn(e); console.log(`failed to compile actor node ${this.node.path()}`); console.log({ functionData }); this.node.states.error.set("failed to compile"); } } _setEvaluatorGenerator(evaluatorGenerator) { this.node.scene().actorsManager.unregisterEvaluatorGenerator(this._evaluatorGenerator); this._evaluatorGenerator.clearObjects(); this._evaluatorGenerator = evaluatorGenerator; this.node.scene().actorsManager.registerEvaluatorGenerator(evaluatorGenerator); } compile() { const assemblerController = this.node.assemblerController(); if (!assemblerController) { return; } this.node.states.error.clear(); assemblerController.assembler.updateFunction(); const paramNodes = JsNodeFinder.findParamGeneratingNodes(this.node); try { const functionData = assemblerController.assembler.createFunctionData(paramNodes); if (!functionData) { this._resetFunctionData(); return; } this.updateFromFunctionData(functionData); assemblerController.post_compile(); } catch (err) { console.log(err); this._resetFunctionData(); } this._runOnCompilationCompletedCallbacks(); } addOnCompilationCompleted(callback) { this._onCompilationCompletedCallbacks = this._onCompilationCompletedCallbacks || /* @__PURE__ */ new Set(); this._onCompilationCompletedCallbacks.add(callback); } removeOnCompilationCompleted(callback) { if (!this._onCompilationCompletedCallbacks) { return; } this._onCompilationCompletedCallbacks.delete(callback); if (this._onCompilationCompletedCallbacks.size == 0) { this._onCompilationCompletedCallbacks = void 0; } } _runOnCompilationCompletedCallbacks() { if (!this._onCompilationCompletedCallbacks) { return; } this._onCompilationCompletedCallbacks.forEach((callback) => callback()); } }