@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
154 lines (153 loc) • 4.53 kB
JavaScript
;
import { TypedAnimNode } from "./_Base";
import { TimelineBuilder } from "../../../core/animation/TimelineBuilder";
import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig";
import { isBooleanTrue } from "../../../core/BooleanValue";
import { Poly } from "../../Poly";
import { gsapLib, gsapTimeline } from "../../../core/thirdParty/gsap/gsapFactory";
import { AnimType } from "../../poly/registers/nodes/types/Anim";
class PlayAnimParamsConfig extends NodeParamsConfig {
constructor() {
super(...arguments);
/** @param play the animations */
this.play = ParamConfig.BUTTON(null, {
callback: (node) => {
PlayAnimNode.PARAM_CALLBACK_play(node);
},
hidden: true
});
/** @param pause the animations */
this.pause = ParamConfig.BUTTON(null, {
callback: (node) => {
PlayAnimNode.PARAM_CALLBACK_pause(node);
},
hidden: true
});
/** @param reset the animations */
this.reset = ParamConfig.BUTTON(null, {
callback: (node) => {
PlayAnimNode.PARAM_CALLBACK_reset(node);
},
hidden: true
});
/** @param sets if the animations created can be stopped when a new animation in generated on the same property */
this.stoppable = ParamConfig.BOOLEAN(1);
/** @param toggle to see debug infos printed in the console */
this.debug = ParamConfig.BOOLEAN(0);
/** @param seek */
this.seek = ParamConfig.FLOAT(0, {
range: [0, 1],
rangeLocked: [true, true],
cook: false,
callback: (node) => {
PlayAnimNode.PARAM_CALLBACK_seek(node);
}
});
}
}
const ParamsConfig = new PlayAnimParamsConfig();
export class PlayAnimNode extends TypedAnimNode {
constructor() {
super(...arguments);
this.paramsConfig = ParamsConfig;
this.gsap = gsapLib();
}
// give access to gsap to external scripts
static type() {
return AnimType.PLAY;
}
initializeNode() {
this.io.inputs.setCount(2);
}
cook(inputContents) {
const timelineBuilder = inputContents[0] || new TimelineBuilder();
this.setTimelineBuilder(timelineBuilder);
}
async timelineBuilder(inputIndex) {
const inputNode = this.io.inputs.input(inputIndex);
if (!inputNode) {
return;
}
const container = await inputNode.compute();
if (!container) {
return;
}
const timelineBuilder = container.coreContentCloned();
if (!timelineBuilder) {
return;
}
timelineBuilder.setDebug(isBooleanTrue(this.pv.debug));
timelineBuilder.setStoppable(this.pv.stoppable);
return timelineBuilder;
}
async _playFromInput(inputIndex) {
return new Promise(async (playResolve) => {
let resolved = false;
function resolveOnce() {
if (!resolved) {
resolved = true;
playResolve();
}
}
const timelineBuilder = await this.timelineBuilder(inputIndex);
if (!timelineBuilder) {
return;
}
this._timeline = gsapTimeline({ onComplete: resolveOnce });
if (!this._timeline) {
return;
}
timelineBuilder.populate(this._timeline, { registerproperties: true });
});
}
async play() {
if (isBooleanTrue(this.pv.debug)) {
Poly.log(`play from '${this.path()}'`);
}
return await this._playFromInput(1);
}
async reset() {
if (isBooleanTrue(this.pv.debug)) {
Poly.log(`reset from '${this.path()}'`);
}
return await this._playFromInput(0);
}
async pause() {
if (this._timeline) {
this._timeline.pause();
}
}
async seek() {
const timelineBuilder0 = await this.timelineBuilder(0);
const timelineBuilder1 = await this.timelineBuilder(1);
if (!(timelineBuilder0 && timelineBuilder1)) {
return;
}
const timeline0 = gsapTimeline({ paused: true });
if (!timeline0) {
return;
}
timelineBuilder0.populate(timeline0, { registerproperties: false });
timeline0.seek(timeline0.duration());
timeline0.kill();
const timeline1 = gsapTimeline({ paused: true });
if (!timeline1) {
return;
}
timelineBuilder1.populate(timeline1, { registerproperties: false });
timeline1.seek(this.pv.seek * timeline1.duration(), false);
timeline1.kill();
}
static PARAM_CALLBACK_play(node) {
node.play();
}
static PARAM_CALLBACK_pause(node) {
node.pause();
}
static PARAM_CALLBACK_reset(node) {
node.reset();
}
static PARAM_CALLBACK_seek(node) {
node.seek();
}
}