Merge Ω-W2-T5: bound the waveform zero-crossing snap to a pixel radius

Single-cycle loop marks stop teleporting to the one interior crossing. Ctrl on a
marker drag defeats the snap, and no longer loses the grab to a coincident node.
This commit is contained in:
2026-08-03 16:09:27 -04:00
11 changed files with 316 additions and 33 deletions
+15 -1
View File
@@ -1,6 +1,6 @@
# DAW verification — post-1.0 work on `dev`
Checks for Θ, Ξ, Ψ, Ε, Ρ, and Γ work that no unit test can close. Build **Release**, install into
Checks for Θ, Ξ, Ψ, Ε, Ρ, Γ, and Ω work that no unit test can close. Build **Release**, install into
`UserPlugins/`, restart REAPER. Panel tail toggle = **None**, project rate 48000, unless a check says otherwise.
## Precision invariants
@@ -167,6 +167,20 @@ Checks for Θ, Ξ, Ψ, Ε, Ρ, and Γ work that no unit test can close. Build **
- [ ] Open a project saved before the zone retirement — the instance reopens on its first zone and sounds the same (`docs/COMPLETED.md` §"Θ-W1-T1")
- [ ] Such an instance with implicit channel mode + a stereo capture reopens **Stereo** — confirm that is acceptable by ear (`docs/COMPLETED.md` §"Θ-W1-T1")
## Waveform marker zero-crossing snap (Ω-W2-T5)
- [ ] `[verify — DAW]` Drag a Gate loop mark on a single-cycle capture — the felt radius the mark
may be pulled to reach a crossing genuinely reads as imperceptible, i.e. a displacement inside
the pointer's own grab neighbourhood is not one the eye catches (`src/core/instrument/ui/waveform_view.h`'s
`kZeroCrossingSnapPx` comment)
- [ ] `[verify — DAW]` Hold Ctrl, then drag a waveform marker (start/loop start/loop end) off a
zero crossing — confirm it lands exactly where dropped, with no snap, in a live editor window
(`editor_input_waveform.cpp`'s `dragWaveform`, `GetKeyState`-driven, no CI test target)
- [ ] `[verify — DAW]` Press and hold Ctrl BEFORE mouse-down on a mark that coincides with a
contour node or another mark's cap — confirm the mark is grabbed (not the node dragged, not a
hard/smooth toggle fired), matching the fix in `resolveWaveformClaim`
(`src/core/instrument/ui/spline_edit.cpp`)
## Look and feel
- [ ] Sign off by eye in a live editor window: knob arcs, needles, envelope splines, waveform outline (`docs/COMPLETED.md` §"Θ-W7-T1", `docs/COMPLETED.md` §"Θ-W6-T1" — "Antialiasing pass")
@@ -829,6 +829,19 @@ model"* — a snap available on one and not the others would be a divergence.
> "whole number" above the frame. Overloading Shift there would collide with a shipped
> gesture. Recorded as a deliberate exclusion.
> **AMENDED (Ω-W2-T5, Daniel 2026-08-03) — Ctrl now has a marker meaning too, and it is not
> this table's Ctrl row.** Dragging a waveform marker snaps it to the nearest zero crossing
> within a small pixel radius (`core/instrument/ui/waveform_view`'s `snapToZeroCrossing`);
> holding Ctrl defeats that snap outright rather than scaling the drag by 0.05. This does not
> reopen the exclusion above or the Shift question it answers: the exclusion is about **Shift**
> colliding with the shipped zero-crossing gesture on a domain with no meaningful whole number
> to snap to, and that reasoning is untouched — Ctrl's marker meaning is a different modifier
> defeating a different gesture (an existing snap, not this section's taper), not a second
> "whole number" law for frames. The two Ctrl meanings (defeat-the-snap here, fine-drag in
> §4.1's own table) do not collide in practice because they land on disjoint control families —
> a marker is never also a unit-valued knob — but the marker's own Ctrl is a genuinely separate
> semantic and is recorded as such, not folded into the row above.
### 4.2 The snap unit, by category
| Unit category | Controls | Shift snaps to |