feat(engine): per-subtree time remapping#64
Merged
Conversation
time_scale/time_offset on containers (flex/grid/card/div/positioned) remap time for their whole subtree: t_local = (t - offset) * scale, composed in cascade as an affine (scale, shift) transform threaded through the builder recursion. The animation ctx stays GLOBAL down the recursion — each node derives its local time from the composed remap (a pre-remapped ctx double-applies; caught in review). Animations, timeline states, audio-reactive bindings and motion-blur ghosts follow the local time; start_at/end_at windows convert back to global after local stagger shifting; BuiltScene.time_params feeds the dispatcher so internal animations and PaintCtx.time advance at local time (scene_duration stays global, documented). validate rejects time_scale <= 0; builder clamps defensively. Skill rule added.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #53.
Goal: slow-motion/replay of a group without touching each child —
time_scale/time_offseton containers remap time for their whole subtree.t_local = (t_global − time_offset) × time_scale, composed in cascade as an affine(scale, shift)transform. The animation ctx stays global through the recursion; each node derives its local time from the composed remap — the pre-remapped-ctx variant double-applies the transform (a sub-agent introduced exactly that bug; caught and fixed during the workstream).start_at/end_atwindows are shifted by stagger in local time, then converted back to global ((t_local − shift)/scale) for the paint-pass check.BuiltScene.time_params(per-node, stagger_delays pattern) feeds the dispatcher: internal animations (counter, draw_in, typewriter) andPaintCtx.timeadvance at local time;scene_durationstays global (documented in code + skill).validaterejectstime_scale ≤ 0; the builder clamps defensively. HTML:<rm-flex time_scale="0.5">already works via the generic rm-* mapping (snake_case attrs; documented in the new skill rule).Tests: 7 new — five pixel tests (slowed fade, delayed start, window under scale, 0.5×0.5 cascade, internal draw_in through the dispatcher path) + two validator tests. 339 total, all green. Process caveat recorded: tests were written alongside the implementation (parallel sub-agents), not observed red against the final code — they did catch the double-remap bug.
Verify:
cargo test --workspace→ 339 passed ✓ ·cargo fmt --check✓ · clippy gated ≤1 ✓