Default starting blur sigma (px) for char_blur_in when
CharAnimationTiming.blur is not set. Tuned against rendered output at
120px display type (see issue #118’s render proof): low enough that
individual letterforms stay ghost-legible at the start of a unit’s
reveal (this is a reveal, not a smoke effect), high enough that the
blur is unmistakable next to the settled, sharp frame.
Default rest_threshold (fraction of the 0→1 travel) used by
spring_rest_time/the duration remap in spring_value when a
SpringConfig does not set one explicitly. 0.5% is tight enough that
“at rest” reads as visually still, without demanding the numeric search
chase an asymptote that (for a critically- or over-damped spring) is
never reached exactly.
Hard cap, in seconds, on how far into the future spring_settle_time
searches for a rest point. A very lightly damped spring can take an
arbitrarily long time to decay under rest_threshold — in the limit
(damping == 0) it never does, oscillating forever at constant
amplitude — so the search needs a bound or it would not terminate. When
the cap is hit, the spring is reported as resting at the cap itself: a
defined, tested “has not settled by then” answer (see
spring_duration_tests::undamped_spring_is_capped_not_infinite and
spring_duration_tests::very_lightly_damped_spring_is_also_capped_when_beyond_the_bound)
rather than an unbounded loop.
Below this measured path length (in px), a motion_path is treated as
the “zero length” degenerate case: the component holds at its single
point instead of travelling, and orient contributes no rotation (a
tangent is undefined at zero length). Not 0.0 exactly — PathMeasure
is a numeric approximation, and a path whose segments collapse onto one
point within float precision (e.g. two near-coincident cubic control
points) should degrade the same defined way a literal single-point path
does, rather than pass through as a very short, jittery “real” travel.
Apply every motion_path effect additively to props.translate_x/
translate_y (and, when orient is set, props.rotation) — the same
treatment apply_orbits/apply_wiggles already give their own
continuous effects, and critically, fields css::animation:: apply_animated_props already bridges into css.transform’s
translate/rotate functions. That bridge — not a new one — is what
makes a motion_path excursion past the viewport visible to
--strict-anim (rustmotion::cli::commands::geometry:: apply_static_node_transform, which folds css.transform to detect
overflow): this function must never write position/orientation anywhere
else, or that detection silently stops seeing it.
Parse path_data and measure its length, in px — the shared primitive
apply_motion_paths (render time) and validate_schema.rs’s advisory
zero-length check (author time) both build on, so the two never
disagree about what “degenerate” means.
Public wrapper around resolve_animation_value_full for callers outside
this module that want to reuse the exact segment/easing/spring
interpolation math (ordering, per-keyframe easing override, clamping at
the ends) on a synthetic Animation they built themselves, without
routing the result through AnimatedProperties/apply_property.
High-level helper: extract effects, resolve presets/keyframes/wiggles/orbits,
and propagate the char animation. Returns the resolved AnimatedProperties
at time within a scene of scene_duration seconds.
Safe division that returns fallback when the denominator is too small to
produce a meaningful result (within 1e-9). Use this for any calculation
where a zero-or-near-zero duration could otherwise produce NaN/∞ that
silently propagates into transforms or opacity.
Public “measure du repos” (issue #167 lot E): the instant, in seconds,
at which this spring settles within rest_threshold of its target and
stays there — what rustmotion info surfaces so an author can size a
scene/preset duration around a spring instead of discovering it by
trial and error.