UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

105 lines (104 loc) 5.49 kB
import { FlowGraphBlock } from "../../../flowGraphBlock.js"; import { getRichTypeByAnimationType, getRichTypeByFlowGraphType, RichTypeAny, RichTypeNumber } from "../../../flowGraphRichTypes.js"; import { Animation } from "../../../../Animations/animation.js"; import { RegisterClass } from "../../../../Misc/typeStore.js"; /** * This block is responsible for interpolating between two values. * The babylon concept used is Animation, and it is the output of this block. * * Note that values will be parsed when the in connection is triggered. until then changing the value will not trigger a new interpolation. * * Internally this block uses the Animation class. * * Note that if the interpolation is already running a signal will be sent to stop the animation group running it. */ export class FlowGraphInterpolationBlock extends FlowGraphBlock { constructor(config = {}) { super(config); /** * The keyframes to interpolate between. * Each keyframe has a duration input and a value input. */ this.keyFrames = []; const type = typeof config?.animationType === "string" ? getRichTypeByFlowGraphType(config.animationType) : getRichTypeByAnimationType(config?.animationType ?? 0); const numberOfKeyFrames = config?.keyFramesCount ?? 1; const duration = this.registerDataInput(`duration_0`, RichTypeNumber, 0); const value = this.registerDataInput(`value_0`, type); this.keyFrames.push({ duration, value }); for (let i = 1; i < numberOfKeyFrames + 1; i++) { const duration = this.registerDataInput(`duration_${i}`, RichTypeNumber, i === numberOfKeyFrames ? config.duration : undefined); const value = this.registerDataInput(`value_${i}`, type); this.keyFrames.push({ duration, value }); } this.initialValue = this.keyFrames[0].value; this.endValue = this.keyFrames[numberOfKeyFrames].value; this.easingFunction = this.registerDataInput("easingFunction", RichTypeAny); this.animation = this.registerDataOutput("animation", RichTypeAny); this.propertyName = this.registerDataInput("propertyName", RichTypeAny, config?.propertyName); this.customBuildAnimation = this.registerDataInput("customBuildAnimation", RichTypeAny); } _updateOutputs(context) { const interpolationAnimations = context._getGlobalContextVariable("interpolationAnimations", []); const propertyName = this.propertyName.getValue(context); const easingFunction = this.easingFunction.getValue(context); const animation = this._createAnimation(context, propertyName, easingFunction); // If an old animation exists, it will be ignored here. // This is because if the animation is running and they both have the same target, the old will be stopped. // This doesn't happen here, it happens in the play animation block. this.animation.setValue(animation, context); // to make sure no 2 interpolations are running on the same target, we will mark the animation in the context if (Array.isArray(animation)) { for (const anim of animation) { interpolationAnimations.push(anim.uniqueId); } } else { interpolationAnimations.push(animation.uniqueId); } context._setGlobalContextVariable("interpolationAnimations", interpolationAnimations); } _createAnimation(context, propertyName, easingFunction) { const type = this.initialValue.richType; const keys = []; // add initial value const currentValue = this.initialValue.getValue(context) || type.defaultValue; keys.push({ frame: 0, value: currentValue }); const numberOfKeyFrames = this.config?.numberOfKeyFrames ?? 1; for (let i = 1; i < numberOfKeyFrames + 1; i++) { const duration = this.keyFrames[i].duration?.getValue(context); let value = this.keyFrames[i].value?.getValue(context); if (i === numberOfKeyFrames - 1) { value = value || type.defaultValue; } if (duration !== undefined && value) { // convert duration to frames, based on 60 fps keys.push({ frame: duration * 60, value }); } } const customBuildAnimation = this.customBuildAnimation.getValue(context); if (customBuildAnimation) { return customBuildAnimation(null, null, context)(keys, 60, type.animationType, easingFunction); } if (typeof propertyName === "string") { const animation = Animation.CreateAnimation(propertyName, type.animationType, 60, easingFunction); animation.setKeys(keys); return [animation]; } else { const animations = propertyName.map((name) => { const animation = Animation.CreateAnimation(name, type.animationType, 60, easingFunction); animation.setKeys(keys); return animation; }); return animations; } } getClassName() { return "FlowGraphInterpolationBlock" /* FlowGraphBlockNames.ValueInterpolation */; } } RegisterClass("FlowGraphInterpolationBlock" /* FlowGraphBlockNames.ValueInterpolation */, FlowGraphInterpolationBlock); // #L54P2C //# sourceMappingURL=flowGraphInterpolationBlock.js.map