fix: map scope grid and cursor through the visible time window

DrawScopeView's waveform envelope already drew only viewStart..viewEnd,
but TimeToX ignored both and mapped 0-1 across the full widget width. The
grid lines and the playback cursor were therefore laid out against the
whole signal while the trace beneath them showed a zoomed sub-range, so
the two drifted out of register the moment the view was zoomed or panned —
and out of register with the spectrogram directly above, which shares the
same time axis.

Map through the visible window in TimeToX, space the ten divisions across
that window rather than the whole signal, and keep the existing bounds
check so a cursor outside the current view is dropped instead of clamped
to an edge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8ZWfr5XZyyDttvkhJUgHN
This commit is contained in:
2026-08-12 00:19:14 -07:00
parent c4687ce80d
commit 0f9ad03fc5
+14 -4
View File
@@ -33,9 +33,16 @@ static int AmplitudeToY(ScopeView* view, float amp)
return view->y + view->height - (int)((amp - view->ampMin) / (view->ampMax - view->ampMin) * view->height);
}
// Map a signal-space time (0-1 over the WHOLE signal) to a screen X, honoring
// the visible window. The waveform envelope below already draws only
// viewStart..viewEnd, so grid lines and the cursor have to use the same mapping
// or they drift out of register with the trace (and with the spectrogram above)
// as soon as the user zooms or pans.
static int TimeToX(ScopeView* view, float t)
{
return view->x + (int)(t * view->width);
float span = view->viewEnd - view->viewStart;
if (span <= 0.0f) span = 1.0f;
return view->x + (int)((t - view->viewStart) / span * view->width);
}
void DrawScopeView(ScopeView* view, float cursorT)
@@ -56,9 +63,11 @@ void DrawScopeView(ScopeView* view, float cursorT)
if (view->showGrid) {
Color gridColor = (Color){ view->gridR, view->gridG, view->gridB, (int)(view->gridAlpha * 255) };
// Vertical time divisions
// Vertical time divisions — ten evenly spaced lines across the VISIBLE
// window, so the grid stays put under zoom instead of sliding off.
for (int i = 0; i <= 10; i++) {
int x = TimeToX(view, (float)i / 10.0f);
float t = view->viewStart + (float)i / 10.0f * (view->viewEnd - view->viewStart);
int x = TimeToX(view, t);
DrawLineV((Vector2){ x, view->y }, (Vector2){ x, view->y + view->height }, gridColor);
}
@@ -119,7 +128,8 @@ void DrawScopeView(ScopeView* view, float cursorT)
DrawLine(px + view->x, yTop, px + view->x, yBot, waveColor);
}
// Cursor
// Cursor. cursorT is signal-space; TimeToX maps it into the visible window,
// and the bounds check below drops it when it falls outside the current view.
if (cursorT >= 0.0f && cursorT <= 1.0f) {
int cursorX = TimeToX(view, cursorT);
if (cursorX >= view->x && cursorX <= view->x + view->width) {