@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
131 lines (119 loc) • 4.07 kB
text/typescript
/**
* Starts and pauses animations
*
*
*/
import {TypedEventNode} from './_Base';
import {EventConnectionPoint, EventConnectionPointType} from '../utils/io/connections/Event';
import {BaseNodeType} from '../_Base';
import {NodeContext} from '../../poly/NodeContext';
import {TimelineBuilder} from '../../../core/animation/TimelineBuilder';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {isBooleanTrue} from '../../../core/Type';
import {GsapCoreTimeline, gsapTimeline} from '../../../core/thirdParty/gsap/gsapFactory';
import {ModuleName} from '../../poly/registers/modules/Common';
import { EventContext } from '../../../core/event/EventContextType';
enum AnimationEventInput {
START = 'start',
STOP = 'stop',
UPDATE = 'update',
}
export enum AnimationEventOutput {
START = 'start',
COMPLETE = 'completed',
}
class AnimationEventParamsConfig extends NodeParamsConfig {
/** @parm animation node */
animation = ParamConfig.NODE_PATH('', {
nodeSelection: {context: NodeContext.ANIM},
dependentOnFoundNode: false,
});
/** @parm presses to play the animation */
play = ParamConfig.BUTTON(null, {
callback: (node: BaseNodeType) => {
AnimationEventNode.PARAM_CALLBACK_play(node as AnimationEventNode);
},
});
/** @parm presses to pause the animation */
pause = ParamConfig.BUTTON(null, {
callback: (node: BaseNodeType) => {
AnimationEventNode.PARAM_CALLBACK_pause(node as AnimationEventNode);
},
});
/** @param stops previous animations still in progress started by this node */
stopsPreviousAnim = ParamConfig.BOOLEAN(1);
}
const ParamsConfig = new AnimationEventParamsConfig();
export class AnimationEventNode extends TypedEventNode<AnimationEventParamsConfig> {
override paramsConfig = ParamsConfig;
static override type() {
return 'animation';
}
override requiredModules() {
return [ModuleName.GSAP];
}
private _timelineBuilder: TimelineBuilder | undefined;
private _timeline: GsapCoreTimeline | undefined;
override initializeNode() {
this.io.inputs.setNamedInputConnectionPoints([
new EventConnectionPoint(AnimationEventInput.START, EventConnectionPointType.BASE, this._play.bind(this)),
new EventConnectionPoint(AnimationEventInput.STOP, EventConnectionPointType.BASE, this._pause.bind(this)),
]);
this.io.outputs.setNamedOutputConnectionPoints([
new EventConnectionPoint(AnimationEventOutput.START, EventConnectionPointType.BASE),
new EventConnectionPoint(AnimationEventOutput.COMPLETE, EventConnectionPointType.BASE),
]);
}
override processEvent(event_context: EventContext<Event>) {
// this.dispatchEventToOutput(OUTPUT_NAME, event_context);
}
static PARAM_CALLBACK_play(node: AnimationEventNode) {
node._play({});
}
static PARAM_CALLBACK_pause(node: AnimationEventNode) {
node._pause();
}
private async _play(event_context: EventContext<Event>) {
const param = this.p.animation;
if (param.isDirty()) {
await param.compute();
}
const node = param.value.nodeWithContext(NodeContext.ANIM);
if (!node) {
return;
}
const container = await node.compute();
if (!container) {
return;
}
this._timelineBuilder = container.coreContent();
if (!this._timelineBuilder) {
return;
}
if (this._timeline && isBooleanTrue(this.pv.stopsPreviousAnim)) {
this._timeline.kill();
}
this._timeline = gsapTimeline();
if (!this._timeline) {
return;
}
this._timelineBuilder.populate(this._timeline, {registerproperties: true});
this._timeline.vars.onStart = () => {
this._triggerAnimationStarted(event_context);
};
this._timeline.vars.onComplete = () => {
this._triggerAnimationCompleted(event_context);
};
}
private _pause() {
if (this._timeline) {
this._timeline.pause();
}
}
private _triggerAnimationStarted(event_context: EventContext<Event>) {
this.dispatchEventToOutput(AnimationEventOutput.START, event_context);
}
private _triggerAnimationCompleted(event_context: EventContext<Event>) {
this.dispatchEventToOutput(AnimationEventOutput.COMPLETE, event_context);
}
}