S12: editor scale + S15/S16 control surfaces

Pure browser_scroll/note_entry/param_slider modules (+ CTest) for scroll,
type-to-filter search, numeric note entry, and the AHDSR/Trigger/pitch-engine/
pitch-env control panel. Editor shell draws + routes through them; params edit
the selected zone's ZonePlayParams via commitAndReload.
This commit is contained in:
2026-07-27 01:09:19 -04:00
parent ddc2ec1e75
commit 4f30124ef7
13 changed files with 1667 additions and 31 deletions
+24 -9
View File
@@ -581,19 +581,34 @@ into the voice engine; today they are fixed defaults), S5 (the map the numeric f
> control, Trigger %-length/fade controls, Varispeed/Preserve engine toggle, and the AD pitch
> envelope depth/shape controls) — deferred here from S15 and S16 per spec.
- [ ] Scrollable, searchable capture browser: a scroll offset (wheel + scrollbar drag) so a
- [x] Scrollable, searchable capture browser: a scroll offset (wheel + scrollbar drag) so a
bank longer than the panel is fully reachable; a **type-to-filter search** that narrows
the drawn cards to matching display names, **composing with S10's bank filter** (bank
filter selects the bank; search narrows within it). Scroll/search layout + hit-test is
pure geometry (visible-card window, scrollbar thumb rect, search-box rect), layered over
S10's `capture_browser` module; filter/scroll state is transient UI state.
- [ ] Direct numeric entry for zone low/high/root: a click-to-edit field over the strip
(LICE text-entry idiom or a SWELL edit control on the child HWND) so a precise note can be
typed, not only dragged. Commits via `commitMapAndReload` like every other edit.
- [ ] ADSR editor: four draggable controls (attack/decay/sustain/release) over the S3
`AdsrParams`; per-instance component state (additive to the map/selection blob, version-
bumped, back-compat defaults to the current fixed envelope). Slider layout/hit-test pure;
the audible envelope change goes through the same off-thread reload.
S10's `capture_browser` module; filter/scroll state is transient UI state. **Landed:**
pure `browser_scroll` module (`browser_scroll_tests`) — scrollContentHeight / max / clamp,
visibleCardRange window, scrolledCardCellRect, scrollThumbRect + thumbDragToOffset inverse,
searchBoxRect, nameMatchesQuery + filterNameIndices. Editor shell wires wheel (`WM_MOUSEWHEEL`),
thumb-drag (`DragKind::kScrollThumb`), and the search box (`WM_CHAR` -> `onSearchChar`,
composed into `rebuildVisible`). Scroll/search are transient (never persisted).
- [x] Direct numeric entry for zone low/high/root: a click-to-edit field over the strip
(LICE text-entry idiom) so a precise note can be typed, not only dragged. Commits via
`commitAndReload` like every other edit. **Landed:** pure `note_entry` module
(`note_entry_tests`) — `parseNoteEntry` accepts a decimal integer OR a note name (C4==60),
clamps to [0,127], rejects garbage. Editor shell hosts three focusable fields (low/high/root)
on the Zones legend, committing on Enter through `commitAndReload`.
- [x] ADSR/AHDSR editor + S15/S16 control surfaces: draggable sliders over the S3 `AdsrParams`
(attack/**hold**/decay/sustain/release — hold is the S15 addition) plus the deferred S15/S16
controls — per-zone Gate|Trigger mode toggle, Trigger %-length/fade-in/fade-out, Varispeed|
Preserve engine toggle, and the AD pitch-envelope enable/attack/decay/±semitone depth. All
edit the SELECTED zone's `ZonePlayParams` (instrument-owned, D-B; never the bank), round-trip
through the existing v3 component-state blob (no new persistence — the S15/S16 payload already
landed in the core pass), and commit off-thread via `commitAndReload`. **Landed:** pure
`param_slider` module (`param_slider_tests`) — control-panel stack layout, toggle-segment
split + hit-test, slider value<->pixel round-trip + clamping, point->control routing. The
shell owns the control-id -> engine-param binding + the value DOMAIN mapping (frames/fraction/
semitones); the module stays engine-free.
## S13 — drop-to-load: the S8 ingest story, folded into the editor UX (UX overhaul, part 4)
**Goal:** Make "load a sample into the sampler" **one gesture from the editor**: dropping