2 Animation
Flaig edited this page 2026-10-08 16:22:28 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Animation

Any numeric filter parameter can be animated, except construction options (see Filter Specs). Animations are part of the saved spec, under animated, keyed by parameter name:

await leanFX.addUpdateFiltersOnSelected([{
  filterType: "glow", filterId: "pulse", color: 0xff3300, distance: 12,
  animated: {
    outerStrength: {animType: "cosOscillation", loopDuration: 2000, val1: 1, val2: 6},
    color: {animType: "colorOscillation", loopDuration: 4000, val1: 0xff3300, val2: 0xffcc00}
  }
}]);

A filter can animate up to 16 parameters. Colors need a color mode (colorOscillation, halfColorOscillation, syncColorOscillation, randomColor, randomColorPerLoop). Booleans and stack fields (padding, gridPadding, zOrder) cannot be animated.

Options

Option Default Meaning
animType required The mode, see below.
active true false pauses this animation and leaves the parameter at its spec value.
loopDuration 3000 Length of one loop in milliseconds (16 ms to 24 h).
loops null Number of loops; null repeats forever. A finite animation stops on its last value and stays there.
pauseBetweenDuration 0 Pause after each loop, in milliseconds.
val1, val2 0 The two values oscillations and random modes move between.
speed 0 For move: units per millisecond (negative values count down).
syncShift 0 Phase offset as a fraction of a loop: 0.5 is half a loop ahead.
clockWise true Rotation direction.
chaosFactor 0.25 Irregularity of the chaotic modes, 0–1.
wantInteger false Round the value down to an integer.

Modes

Mode Value over time
move The parameter's spec value plus speed × elapsed milliseconds. The usual way to run a shader's time.
moveToward From val1 to val2 within each loop, linearly.
cosOscillation Smoothly from val1 to val2 and back, once per loop. Starts at val1.
sinOscillation The same, starting halfway between the two values.
halfCosOscillation, halfSinOscillation Half a wave per loop: val1 to val2 in one loop, back in the next. With loops: 1 it is a one-way transition.
colorOscillation Like cosOscillation, blending each RGB channel.
halfColorOscillation Like halfCosOscillation, for colors.
chaoticOscillation cosOscillation with an irregular phase set by chaosFactor.
rotation Degrees through a full turn per loop (0→360); counter-clockwise gives 360→0.
randomNumber A new random value between val1 and val2 thirty times a second.
randomNumberPerLoop A new random value between val1 and val2 once per loop.
randomColor A random color thirty times a second.
randomColorPerLoop A random color once per loop.
syncCosOscillation, syncSinOscillation, syncColorOscillation, syncChaoticOscillation, syncRotation The same as the modes without sync, but the phase comes from a shared clock instead of the filter's start time: all filters with the same loopDuration move in step, even when created at different times. Use syncShift to offset one.

Random values are the same on every client.

Timing

Each filter remembers when it was created. Every client computes the current value from that moment and the active GM's shared clock, so animations stay in step between players and continue after a reload or a late join; a slow frame catches up instead of drifting. The GM republishes the server-start offset on ready and election, including short restarts. Players trust the published offset despite their own wall-clock skew; without a GM, clients estimate time locally. Finite animations show their final value by default. No per-frame document writes occur.

  • Updating a filter's other parameters (or enabled) keeps its timeline.
  • Updating animated replaces all of the filter's animations and starts them from the beginning.
  • animated: {} stops all animations; the parameters return to their spec values.

One-shot completion

Add onComplete: "delete" at the filter-spec level to dispose the rendered filter and delete its saved entry after the last active animation ends. "hold" is the default. Delete-on-completion requires at least one active animation and finite loops on every active property; inactive properties do not delay removal.

Each property's end is (loops - 1) * (loopDuration + pauseBetweenDuration) + loopDuration milliseconds after creation. The longest decides the filter's deadline. enabled: false does not pause it.

The active GM cleans up saved entries across all scenes, even with no canvas viewed, and catches up on ready/reconnect. Clients skip expired filters on redraw and dispose late-arriving textures. With no GM, rendering still expires locally while saved entries wait for the next GM. Background throttling may delay the saved write. Cleanup re-reads the current spec/start inside the document queue, so an old deadline cannot delete a newly replayed effect with the same ID.

Use addUpdateFilters to replay a one-shot. Replacing animated restarts its lifetime; other edits retain it. To turn it into a static filter, update with onComplete: "hold" and animated: {}. One-shot previews restore saved effects when their last filter expires. See the hit flash example.

Units to keep in mind

rotation produces degrees, which fits rotation parameters in degrees (transform, sprite, spriteMask, bevel, drop shadow). Some parameters take radians instead (twist angle, twAngle, distortion maskSpriteRotation, dot angle); animate those with an oscillation between radian values. The filter pages give each parameter's unit.

Disabling animations

Each user can turn on Disable effect animations in the module settings. Animated effects then show a still frame on that client: finite animations at their end state, endless ones at the moment they were drawn. Other players are not affected.

One-shots retain deadline checking and still disappear at their normal end time.