Animation¶
The Tick UI animation context drives per-widget enter, leave,
and event-based transitions. You open a context with
PushAnimate("id"), chain a fluent definition (Init, Enter,
Leave, and event hooks), and read the animated values back via
GetColor, GetFloat, GetRect, or GetInt. Drawing calls
render the animated values.
The model¶
An animation context owns the values that interpolate over time: colour, scale, rect, and int. Your draw code reads the current value each frame; the context blends from start to target based on elapsed time and a curve.
State on the context is keyed by the string ID you pass to
PushAnimate, the same way widget state is keyed by widget ID. Two
contexts with the same ID share state. Nesting two PushAnimate
scopes with different IDs creates two independent contexts.
For the underlying stack contract, refer to Stacks.
The lifecycle¶
A typical context goes through four phases per frame:
- Open.
PushAnimate("id")pushes the context onto the animation stack and returns the fluent builder. - Define. Chain
.Init(),.Enter(),.Leave(), and any event-driven states (.BoolWhileTrue). - Apply. Call
.Apply()to finalise. The returned context holds the animated values for the current frame. - Read and pop. Read values via
GetColor,GetFloat, and so on while drawing. Callui.PopAnimate()to close the context.
Reading from the context before .Apply() returns the default
values, not the animated ones. Forgetting PopAnimate leaves the
animation stack imbalanced; the next push nests unintentionally.
States and transitions¶
Three built-in states define the context's lifecycle:
- Init. The value at the moment the widget first appears. Default state when no other applies.
- Enter. The forward transition into the active state.
- Leave. The reverse transition out of the active state.
Four event hooks drive the active state:
.BoolWhileTrue(string id, bool condition). The named state is active for as long asconditionis true..BoolWhileFalse(string id, bool condition). The named state is active whileconditionis false. Useful for "show this when the dialog is hidden" patterns..BoolBecomesTrue(string id, bool condition). Fires on the frameconditionflips from false to true. Useful for one-shot animations..BoolBecomesFalse(string id, bool condition). Fires on the frameconditionflips from true to false.
Each state defines its own animated values per property. .Color(),
.Scale(), .Float(), .Rect(), and .Int() return per-property
fluent operators. .Set(value) pins a value. .Blend(from, to,
duration) interpolates over time.
For the per-state authoring procedure, refer to Add an animation. For full workflows with multiple animated widgets, refer to the Animation guide.
Read animated values¶
The context returned by .Apply() exposes typed getters:
ctx.GetColor()returns the context's primary colour. The context also exposes its primary float, int, and rect values viactx.GetFloat(),ctx.GetInt(), andctx.GetRect(), and its primary scale and rotation (in degrees) viactx.GetScale()andctx.GetRotate().ctx.GetColor(string id),ctx.GetFloat(string id),ctx.GetRect(string id),ctx.GetInt(string id)look up a named animated property by string ID. Use these when a context drives multiple animated values that share an enter/leave shape.ctx.TryGetColor(...),ctx.TryGetFloat(...),ctx.TryGetInt(...),ctx.TryGetRect(...)returnfalsewhen the named property is missing instead of returning a default.
Each call returns the blended value for the current frame, sampled against the active state and the configured curve. Pass the result into the matching draw call:
var ctx = ui.PushAnimate("hover_anim")
.Init().Color().Set(restColor).Done()
.Enter().Color().Blend(restColor, hoverColor, 0.2f).Done()
.Leave().Color().Blend(hoverColor, restColor, 0.2f).Done()
.Apply();
ui.FillRounded(ctx.GetColor(), 6);
ui.PopAnimate();
Curves and timing¶
Every blend takes its duration as an explicit argument, so timing is
set per call rather than from a shared default. .Blend(from, to,
duration) eases with a linear curve; the overload .Blend(from, to,
duration, Curves.Curve.EaseOutCubic) selects an easing curve from
the Curves.Curve catalogue. The BlendUnscaled variants measure
their duration in unscaled time, ignoring Time.timeScale.
The animation stack¶
m_animationStack carries open contexts so nested animations work.
A nested PushAnimate inside an open context runs on top of it;
PopAnimate returns to the parent. Mismatched push and pop fires
the same kind of leak that other stacks do.
For the per-stack push and pop contract, refer to Stacks.
Source file name¶
The class is named AnimationContext, and the file that contains it
is Source/Interface/Animation/AnimationContext.cs. The fluent event
types (AnimationContextEnter, AnimationContextLeave,
AnimationContextEvent, and the rest) live alongside it in the same
Source/Interface/Animation/ directory.
Pitfalls¶
GetColor returns the default, not the animated value.
: You called the getter before .Apply(). Apply first, then
read.
The animation stack leaks at end of frame.
: A PushAnimate was not paired with a PopAnimate. Audit the
body that opened the context.
Hover state never enters.
: The BoolWhileTrue condition is reading stale state. Confirm
the condition (ui.IsHovered(), for example) is read inside
the same rect the visual occupies.
Additional resources¶
- Stacks: the animation stack contract.
- Frame lifecycle: when contexts open and close relative to draw recording.
- Add an animation: the single-widget recipe.
- Animation guide: multi-widget workflows.