animation-unit

xod/core/animation-unit

Animates a number making it run from 0.0 to 1.0
animation-unit
@/animation-unit
Animates a number making it run from 0.0 to 1.0
REVpulse
Quickly rewind `OUT` to 0.0 and stop the animation
RATEnumber
Defines the animation speed: amount of `OUT` change per second
PLAYpulse
Set `OUT` to 0.0 and start animation. If the animation is in progress already it is cancelled, the new one is started.
FWDpulse
Quickly forward `OUT` to 1.0 and stop the animation.
animation-unit
OUT
REV
RATE
PLAY
FWD
ACT
DONE
DONEpulse
Pulses when the animation completes, that is the `OUT` value reaches 1.0. The pulse is not emitted when the animation is stopped with `REV` or `FWD`.
OUTnumber
The current value of number animation. Always in range [0, 1].
ACTboolean
Active. Outputs whether the animation is in progress.

C++ implementation

node {
    TimeMs prevTime;

    void evaluate(Context ctx) {
        auto now = transactionTime();
        auto rate = max((Number)0, getValue<input_RATE>(ctx));
        auto out = getValue<output_OUT>(ctx);

        if (isInputDirty<input_FWD>(ctx)) {
            // Fast forward to 1.0
            emitValue<output_OUT>(ctx, 1);
            emitValue<output_ACT>(ctx, false);
            clearTimeout(ctx);
            return;
        }

        if (isInputDirty<input_PLAY>(ctx)) {
            // Start animation from scratch
            emitValue<output_OUT>(ctx, 0);
            emitValue<output_ACT>(ctx, true);
            prevTime = now;
            setTimeout(ctx, 0);
            return;
        }

        if (isInputDirty<input_REV>(ctx)) {
            // Rewind to 0.0 and cancel animation
            emitValue<output_OUT>(ctx, 0);
            emitValue<output_ACT>(ctx, false);
            clearTimeout(ctx);
            return;
        }

        if (isTimedOut(ctx)) {
            // Continue animation
            auto dt = now - prevTime;
            out += dt / 1000.0 * rate;

            if (out >= 1) {
                emitValue<output_OUT>(ctx, 1);
                emitValue<output_ACT>(ctx, false);
                emitValue<output_DONE>(ctx, 1);
            } else {
                emitValue<output_OUT>(ctx, out);
                emitValue<output_ACT>(ctx, true);
                prevTime = now;
                setTimeout(ctx, 0);
            }
        }
    }
}