tween API

← tween · version 0.1.2

23 public items, in source order. Generated from the registry index, which re-derives them from the package source at publish time — so a signature here is the one that version actually ships.

pub enum Curve { Linear, Quad, Cubic, Quart, Quint, Sine, Expo, Circ, Back, Elastic, Bounce }

Which shape the curve has.

⚠ Back and Elastic leave [0, 1] on purpose — they overshoot and come back — so a consumer clamping the RESULT of an ease is undoing the effect it asked for. Every other curve stays inside.

pub enum Shape { In, Out, InOut }

Which direction the curve runs: slow at the start, slow at the end, or both.

pub fn ease(c: Curve, s: Shape, t: float) -> float

Ease t — the entry point, and the three reflections of the header's rule 2.

⚠ There is no clamp HERE on purpose; every arm reads the curve through curve_at, which is where the endpoints are decided. See the header for why in front of the reflections is the wrong side of them.

pub fn curve_at(c: Curve, t: float) -> float

The curve, clamped — **the one place all thirty-three combinations get their endpoints from.**

⚠ **Clamped, not trusted.** t <= 0 answers exactly 0.0 and t >= 1 exactly 1.0 without consulting the curve, which is what makes the endpoints exact — including for the two curves whose textbook definitions miss them.

⚠ A null progress (a NaN) is neither <= 0.0 nor >= 1.0, so it reaches the curve and comes back null. That is deliberate: an unanswerable progress must not silently read as "finished".

pub fn curve_in(c: Curve, t: float) -> float

The **In** direction of each curve, raw — the eleven definitions everything else is reflected from.

⚠ **Public so it can be gated, not because it is the door.** It is NOT clamped: curve_in(Sine, 1.0) is 0.9999999999999999, which is exactly the hole ease exists to close. Reach for ease.

pub fn lerp(a: float, b: float, t: float) -> float

A linear interpolation that lands EXACTLY on both endpoints.

⚠ **a·(1−t) + b·t, and the other spelling is not equivalent** — see the header: a + (b−a)·t answers 0.0 for lerp(1e17, 1.0, 1.0). Reach for this one whenever an endpoint has to be hit rather than approached.

t outside [0, 1] extrapolates, which is what makes the overshooting curves (Back, Elastic) work.

pub struct Tween { from: float, to: float, duration: integer, elapsed: integer, lead: integer, curve: Curve = Curve.Linear, shape: Shape = Shape.In }

One value moving from from to to over duration base units.

⚠ **duration <= 0 means INSTANT, not unarmed** — it reads to and is done immediately. That is the opposite of fixstep's Timer, where a zero total means nothing is running, and it is deliberate: "move there over no time" is a step, and a chain built from one must pass straight through it rather than stall.

pub fn tween_new(from: float, to: float, duration: integer, c: Curve = Curve.Linear, s: Shape = Shape.In) -> Tween

A tween ready to run.

pub fn delay(self: Tween, units: integer)

Wait units before starting.

⚠ A door rather than a sixth parameter, for fixstep's reason: a delay is a case some callers have and most do not. During the wait the tween reads from and is not done.

pub fn advance(self: Tween, units: integer) -> integer

Spend units of time on it, and answer how many were LEFT OVER — the time past its end, which is what the next link of a chain must already have run for. Zero while it is still running.

⚠ Non-positive time is dropped rather than owed (fixstep's rule 2), so a paused consumer may call this every frame.

pub fn progress(self: const Tween) -> float

How far through it is, before easing — the exact ratio elapsed / duration, in [0, 1].

⚠ **It reaches 1.0 and STAYS there**, which is the difference from fixstep's timer_fraction (documented [0, 1), and 0.0 again once the timer fires — a tween built on one would snap back to its start the instant it finished).

pub fn value(self: const Tween) -> float

What it reads right now.

⚠ Exactly from before it starts and exactly to once it has finished — see the header for why that needs the interpolation to be written one way and not the other.

pub fn done(self: const Tween) -> boolean

Has it finished? A tween still waiting out its delay has not.

pub fn rewind(self: Tween, lead: integer = 0)

Put it back at the start, delay and all — the same tween, run again.

pub enum Play { Chain, Parallel }

How several tweens share one stream of time.

pub struct Track { steps: vector<Tween>, mode: Play = Play.Chain, at: integer }

Several tweens driven together.

⚠ **It is a rule about time, not a scheduler** — there is no queue, no priority and no callback. Chain hands each link's leftover to the next, which is the entire reason advance answers one.

pub fn track_new(mode: Play = Play.Chain) -> Track

An empty track.

pub fn add(self: Track, tw: Tween)

Add a link. For Chain the order of the calls is the order they run in.

pub fn advance(self: Track, units: integer) -> integer

Spend units on the track, and answer the leftover — the same contract one tween has, so a track composes into a chain exactly like a tween does.

pub fn done(self: const Track) -> boolean

Have all its links finished?

pub fn active(self: const Track) -> integer

Which link is running, for Chain — len(steps) once it has finished.

pub fn value_at(self: const Track, i: integer) -> float

What the link at i reads right now.

⚠ A door rather than making a consumer index steps itself, because an out-of-range index there reads null and this answers 0.0.

pub fn rewind(self: Track)

Put every link back at its start.