UNPKG

polygonjs-engine

Version:

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

256 lines (246 loc) 8.42 kB
/** * Updates the param of specific node * * * */ import {Number2, Number3, Number4} from '../../../types/GlobalTypes'; import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; import {TypedEventNode} from './_Base'; import {EventContext} from '../../scene/utils/events/_BaseEventsController'; import {TypeAssert} from '../../poly/Assert'; import {BaseParamType} from '../../params/_Base'; import {ParamType} from '../../poly/ParamType'; import {FloatParam} from '../../params/Float'; import {Vector2Param} from '../../params/Vector2'; import {Vector3Param} from '../../params/Vector3'; import {Vector4Param} from '../../params/Vector4'; import {EventConnectionPoint, EventConnectionPointType} from '../utils/io/connections/Event'; import {BaseNodeType} from '../_Base'; import {Vector2} from 'three/src/math/Vector2'; import {Vector3} from 'three/src/math/Vector3'; import {Vector4} from 'three/src/math/Vector4'; import {IntegerParam} from '../../params/Integer'; enum SetParamParamType { BOOLEAN = 'boolean', BUTTON = 'button', NUMBER = 'number', VECTOR2 = 'vector2', VECTOR3 = 'vector3', VECTOR4 = 'vector4', STRING = 'string', } const SET_PARAM_PARAM_TYPE: Array<SetParamParamType> = [ SetParamParamType.BOOLEAN, SetParamParamType.BUTTON, SetParamParamType.NUMBER, SetParamParamType.VECTOR2, SetParamParamType.VECTOR3, SetParamParamType.VECTOR4, SetParamParamType.STRING, ]; const TYPE_BOOLEAN = SET_PARAM_PARAM_TYPE.indexOf(SetParamParamType.BOOLEAN); // const TYPE_BUTTON = SET_PARAM_PARAM_TYPE.indexOf(SetParamParamType.BUTTON); const TYPE_NUMBER = SET_PARAM_PARAM_TYPE.indexOf(SetParamParamType.NUMBER); const TYPE_VECTOR2 = SET_PARAM_PARAM_TYPE.indexOf(SetParamParamType.VECTOR2); const TYPE_VECTOR3 = SET_PARAM_PARAM_TYPE.indexOf(SetParamParamType.VECTOR3); const TYPE_VECTOR4 = SET_PARAM_PARAM_TYPE.indexOf(SetParamParamType.VECTOR4); const TYPE_STRING = SET_PARAM_PARAM_TYPE.indexOf(SetParamParamType.STRING); const OUTPUT_NAME = 'output'; class SetParamParamsConfig extends NodeParamsConfig { /** @param the parameter to update */ param = ParamConfig.PARAM_PATH('/geo1/display', { paramSelection: true, computeOnDirty: true, }); // param = ParamConfig.STRING('display'); /** @param type of the parameter to update */ type = ParamConfig.INTEGER(TYPE_NUMBER, { menu: { entries: SET_PARAM_PARAM_TYPE.map((name, value) => { return {name, value}; }), }, }); /** @param for a boolean parameter, sets to toggle its value */ toggle = ParamConfig.BOOLEAN(0, { visibleIf: {type: TYPE_BOOLEAN}, }); /** @param if toggle is set to off, this will set the value of the parameter */ boolean = ParamConfig.BOOLEAN(0, { visibleIf: { type: TYPE_BOOLEAN, toggle: 0, }, }); /** @param param value for a float parameter */ number = ParamConfig.FLOAT(0, { visibleIf: {type: TYPE_NUMBER}, }); /** @param param value for a vector2 parameter */ vector2 = ParamConfig.VECTOR2([0, 0], { visibleIf: {type: TYPE_VECTOR2}, }); /** @param param value for a vector3 parameter */ vector3 = ParamConfig.VECTOR3([0, 0, 0], { visibleIf: {type: TYPE_VECTOR3}, }); /** @param param value for a vector4 parameter */ vector4 = ParamConfig.VECTOR4([0, 0, 0, 0], { visibleIf: {type: TYPE_VECTOR4}, }); /** @param if on, the value will be incremented by the value, as opposed to be set to the value */ increment = ParamConfig.BOOLEAN(0, { visibleIf: [{type: TYPE_NUMBER}, {type: TYPE_VECTOR2}, {type: TYPE_VECTOR3}, {type: TYPE_VECTOR4}], }); /** @param param value for a string parameter */ string = ParamConfig.STRING('', { visibleIf: {type: TYPE_STRING}, }); /** @param execute button to test the node */ execute = ParamConfig.BUTTON(null, { callback: (node: BaseNodeType) => { SetParamEventNode.PARAM_CALLBACK_execute(node as SetParamEventNode); }, }); } const ParamsConfig = new SetParamParamsConfig(); export class SetParamEventNode extends TypedEventNode<SetParamParamsConfig> { params_config = ParamsConfig; static type() { return 'setParam'; } initializeNode() { this.io.inputs.setNamedInputConnectionPoints([ new EventConnectionPoint('trigger', EventConnectionPointType.BASE), ]); this.io.outputs.setNamedOutputConnectionPoints([ new EventConnectionPoint(OUTPUT_NAME, EventConnectionPointType.BASE), ]); this.scene().dispatchController.onAddListener(() => { this.params.onParamsCreated('params_label', () => { this.params.label.init([this.p.param]); }); }); } async process_event(event_context: EventContext<Event>) { if (this.p.param.isDirty()) { // TODO: investigate occasions // where the referenced param is recomputed // (such as in a material builder) // and this node refers to an old param await this.p.param.compute(); } const param = this.p.param.value.param(); if (param) { const new_value = await this._new_param_value(param); if (new_value != null) { param.set(new_value); } } else { this.states.error.set('target param not found'); } this.dispatch_event_to_output(OUTPUT_NAME, event_context); } private _tmp_vector2 = new Vector2(); private _tmp_vector3 = new Vector3(); private _tmp_vector4 = new Vector4(); private _tmp_array2: Number2 = [0, 0]; private _tmp_array3: Number3 = [0, 0, 0]; private _tmp_array4: Number4 = [0, 0, 0, 0]; private async _new_param_value(param: BaseParamType) { const type = SET_PARAM_PARAM_TYPE[this.pv.type]; switch (type) { case SetParamParamType.BOOLEAN: { await this._compute_params_if_dirty([this.p.toggle]); // use 1 and 0, so we can also use it on integer params, such as for a switch node if (this.pv.toggle) { return param.value ? 0 : 1; } else { return this.pv.boolean ? 1 : 0; } } case SetParamParamType.BUTTON: { return param.options.execute_callback(); } case SetParamParamType.NUMBER: { await this._compute_params_if_dirty([this.p.increment, this.p.number]); if (this.pv.increment) { if (param.type() == ParamType.FLOAT) { return (param as FloatParam).value + this.pv.number; } else { return (param as IntegerParam).value; } } else { return this.pv.number; } } case SetParamParamType.VECTOR2: { await this._compute_params_if_dirty([this.p.increment, this.p.vector2]); if (this.pv.increment) { if (param.type() == ParamType.VECTOR2) { this._tmp_vector2.copy((param as Vector2Param).value); this._tmp_vector2.add(this.pv.vector2); this._tmp_vector2.toArray(this._tmp_array2); } else { (param as Vector2Param).value.toArray(this._tmp_array2); } } else { this.pv.vector2.toArray(this._tmp_array2); } return this._tmp_array2; } case SetParamParamType.VECTOR3: { await this._compute_params_if_dirty([this.p.increment, this.p.vector3]); if (this.pv.increment) { if (param.type() == ParamType.VECTOR3) { this._tmp_vector3.copy((param as Vector3Param).value); this._tmp_vector3.add(this.pv.vector3); this._tmp_vector3.toArray(this._tmp_array3); } else { (param as Vector3Param).value.toArray(this._tmp_array3); } } else { this.pv.vector3.toArray(this._tmp_array3); } return this._tmp_array3; } case SetParamParamType.VECTOR4: { await this._compute_params_if_dirty([this.p.increment, this.p.vector4]); if (this.pv.increment) { if (param.type() == ParamType.VECTOR4) { this._tmp_vector4.copy((param as Vector4Param).value); this._tmp_vector4.add(this.pv.vector4); this._tmp_vector4.toArray(this._tmp_array4); } else { (param as Vector4Param).value.toArray(this._tmp_array4); } } else { this.pv.vector4.toArray(this._tmp_array4); } return this._tmp_array4; } case SetParamParamType.STRING: { await this._compute_params_if_dirty([this.p.string]); return this.pv.string; } } TypeAssert.unreachable(type); } static PARAM_CALLBACK_execute(node: SetParamEventNode) { node.process_event({}); } private async _compute_params_if_dirty(params: BaseParamType[]) { const dirty_params = []; for (let param of params) { if (param.isDirty()) { dirty_params.push(param); } } const promises: Promise<void>[] = []; for (let param of dirty_params) { promises.push(param.compute()); } return await Promise.all(promises); } }