Skip to content

fix(paint): give the audio-reactive painters the scenario's clock - #203

Merged
LeadcodeDev merged 1 commit into
mainfrom
fix/scenario-time-in-paint-ctx
Aug 12, 2026
Merged

fix(paint): give the audio-reactive painters the scenario's clock#203
LeadcodeDev merged 1 commit into
mainfrom
fix/scenario-time-in-paint-ctx

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Closes #201. Unblocks #202.

What

A waveform in a scene starting at t=73 s drew the analysis at 73 s into that scene. Same scene, same track, same build — only its position in the scenario differs:

scene position trace height
first scene 42 px
starting at t≈73 s 0 px (flat)

PaintCtx carried no scenario-global time: time restarts at every scene, and frame_index is documented as "frames elapsed since this scene started". So waveform, audio_spectrum and the audio-reactive binding had nothing else to read, while AudioAnalysis is indexed on the scenario's own timeline. The two only agreed for a track at 0 and a scene at 0.

How

FrameTask carries global_frame — its index in the schedule, known at build time — and that becomes scenario_time on PaintFrame/PaintCtx and BuildAnimationCtx.

Deliberate boundaries:

  • Everything else stays on time. A delay, a stagger, a reveal, a preset are all written against the scene. Only the three audio consumers move.
  • A container's time_scale/time_offset does not remap it. That remaps the animation clock of a subtree; the audio plays at wall-clock speed regardless, so the scenario clock passes through untouched.
  • The hit-map keeps the scene clock. It is a geometry probe for the studio overlay, never an encoded frame, and no painter reads the audio clock on that path.
  • render_scene_bg_scaled did not get the parameter — the background layer paints no component.

The incremental encoder builds slots in isolation, so build_slot_frame_tasks takes the slot's start and renumbers rather than using the local Vec's length. slot_tasks_reproduce_the_full_builder_exactly caught that on the first run — exactly what it exists for.

Test

a_waveform_reads_the_scenario_clock_not_the_scene_clock: 3 s of sine then 1 s of silence, behind a 2 s filler scene. At frame 105 the scenario is at 3.5 s (silence) while the scene is 1.5 s old (still sine), so the two clocks disagree by construction.

Checked that it discriminates: reverting waveform.rs to ctx.time makes it fail, restoring the fix makes it pass. My first attempt at this test passed in both states — it was worthless, and I only found that out by trying to break it.

cargo test --workspace green, cargo fmt --check and cargo clippy --all-targets -- -D warnings clean.

A waveform in a scene starting at t=73 s drew the analysis at 73 s *into that
scene*. With a uniform track nobody notices; with any track whose level varies
over the timeline the visualisation is simply wrong, and it goes flat when the
scene's own window falls in a silent region.

Measured on the same scene, same track, same build — only its position in the
scenario differs: 42 px of trace as the first scene, 0 px starting at t~73 s.

PaintCtx carried no scenario-global time: `time` restarts at every scene and
frame_index is documented as "frames elapsed since this scene started". So
waveform, audio_spectrum and the audio-reactive binding had nothing else to
read, while AudioAnalysis is indexed on the scenario's own timeline.

Carry the position on the FrameTask — it is the index in the schedule, known
at build time — and thread it through PaintFrame/PaintCtx and
BuildAnimationCtx as `scenario_time`. Everything else stays on `time`, which
is what a delay, a stagger or a preset is written against. A container's
time_scale/time_offset remaps the animation clock of its subtree; the audio is
not part of that subtree and passes through unremapped.

The incremental encoder builds slots in isolation, so it renumbers each slot
from its own start rather than taking the local Vec's length — the existing
slot_tasks_reproduce_the_full_builder_exactly caught that immediately.
@LeadcodeDev LeadcodeDev added the bug Something isn't working label Aug 12, 2026
@LeadcodeDev LeadcodeDev self-assigned this Aug 12, 2026
@LeadcodeDev
LeadcodeDev merged commit 3085968 into main Aug 12, 2026
3 checks passed
@LeadcodeDev
LeadcodeDev deleted the fix/scenario-time-in-paint-ctx branch August 12, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Audio-reactive components read scene-local time against a scenario-time analysis

1 participant