UNPKG

@polygonjs/polygonjs

Version:

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

118 lines (108 loc) 3.84 kB
/** * Merge animation properties * * @remarks * Animation properties can be set to either run at the same time, or one after the other. */ import {TypedAnimNode} from './_Base'; import {TimelineBuilder} from '../../../core/animation/TimelineBuilder'; import {TypeAssert} from '../../poly/Assert'; import {AnimationPosition, AnimationPositionMode, AnimationPositionRelativeTo} from '../../../core/animation/Position'; import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig'; import {isBooleanTrue} from '../../../core/BooleanValue'; import {BaseNodeType} from '../_Base'; import {NodeEvent} from '../../poly/NodeEvent'; enum MergeMode { ALL_TOGETHER = 'play all together', ONE_AT_A_TIME = 'play one at a time', } export const EASING_ANIM_MERGE_MODES: MergeMode[] = [MergeMode.ALL_TOGETHER, MergeMode.ONE_AT_A_TIME]; const DEFAULT_INPUTS_COUNT = 4; class MergeAnimParamsConfig extends NodeParamsConfig { /** @param mode (at the same time or one after the other) */ mode = ParamConfig.INTEGER(0, { menu: { entries: EASING_ANIM_MERGE_MODES.map((name, value) => { return {name, value}; }), }, }); /** @param offset if run one after the other */ offset = ParamConfig.FLOAT(0, { range: [-1, 1], }); /** @param override the position */ overridePositions = ParamConfig.BOOLEAN(0); /** @param number of inputs that this node can merge animations from */ inputsCount = ParamConfig.INTEGER(DEFAULT_INPUTS_COUNT, { range: [1, 32], rangeLocked: [true, false], callback: (node: BaseNodeType) => { MergeAnimNode.PARAM_CALLBACK_setInputsCount(node as MergeAnimNode); }, }); } const ParamsConfig = new MergeAnimParamsConfig(); export class MergeAnimNode extends TypedAnimNode<MergeAnimParamsConfig> { override readonly paramsConfig = ParamsConfig; static override type() { return 'merge'; } override initializeNode() { this.io.inputs.setCount(0, 4); this.params.onParamsCreated('pdateInputsEvaluation', () => { this._callbackUpdateInputsCount(); }); } override cook(inputContents: TimelineBuilder[]) { const mergedTimelineBuilder = new TimelineBuilder(); let i = 0; for (const timelineBuilder of inputContents) { if (timelineBuilder) { if (i > 0) { this._updateTimelineBuilder(timelineBuilder); } mergedTimelineBuilder.addTimelineBuilder(timelineBuilder); i++; } } this.setTimelineBuilder(mergedTimelineBuilder); } private _updateTimelineBuilder(timelineBuilder: TimelineBuilder) { const mode = EASING_ANIM_MERGE_MODES[this.pv.mode]; switch (mode) { case MergeMode.ALL_TOGETHER: return this._setPlayAllTogether(timelineBuilder); case MergeMode.ONE_AT_A_TIME: return this._setPlayOneAtATime(timelineBuilder); } TypeAssert.unreachable(mode); } private _setPlayAllTogether(timelineBuilder: TimelineBuilder) { let position = timelineBuilder.position(); if (!position || isBooleanTrue(this.pv.overridePositions)) { position = new AnimationPosition(); position.setMode(AnimationPositionMode.RELATIVE); position.setRelativeTo(AnimationPositionRelativeTo.START); position.setOffset(this.pv.offset); timelineBuilder.setPosition(position); } } private _setPlayOneAtATime(timelineBuilder: TimelineBuilder) { let position = timelineBuilder.position(); if (!position || isBooleanTrue(this.pv.overridePositions)) { position = new AnimationPosition(); position.setMode(AnimationPositionMode.RELATIVE); position.setRelativeTo(AnimationPositionRelativeTo.END); position.setOffset(this.pv.offset); timelineBuilder.setPosition(position); } } private _callbackUpdateInputsCount() { this.io.inputs.setCount(1, this.pv.inputsCount); this.emit(NodeEvent.INPUTS_UPDATED); } static PARAM_CALLBACK_setInputsCount(node: MergeAnimNode) { node._callbackUpdateInputsCount(); } }