fix(instrument-ui): raise Disabled-cue contrast, fix stale 1.2 MASTER row, close hover/focus minors

This commit is contained in:
2026-08-03 14:04:00 -04:00
parent 73c69f689c
commit 84905e6bd1
5 changed files with 21 additions and 11 deletions
+3 -3
View File
@@ -97,8 +97,8 @@ contours are row 2's first two groups.
> **Updated for Ω-W1-T4's filter-mod move and toggle conversion.** The table below was
> re-measured against the shipped `deck_groups.cpp`/`knob_deck.cpp` after two changes this
> track made: the filter's mod-depth cell moved from FILTER to FILTER ENV (one cell each
> way), and the four toggles that used to be two-segment (`Off\|On`, `Staged\|Spline` on
> PITCH ENV/FILTER ENV/AMP ENVELOPE, `Off\|On` on FILTER) are now the single-button
> way), and the six toggles that used to be two-segment (`Off\|On` on PITCH ENV/FILTER/MASTER,
> `Staged\|Spline` on PITCH ENV/FILTER ENV/AMP ENVELOPE) are now the single-button
> `kEnable`/`kMode` styles — see `knob_deck.h`'s `DeckToggleStyle`. The per-deck corner
> radio these three envelope decks carried is gone (superseded by the click-to-focus
> overlay border, `core/instrument/CLAUDE.md`'s envelope-overlay section); MASTER alone
@@ -123,7 +123,7 @@ draws the whole span as one button. Metrics: `kDeckCellW 60`, `kDeckCellH 74`, `
| **PITCH ENV** | 2 | 58 + 4 + 52 + 4 + 46 = 164 | 4 × 60 = **240** | **252** | 0 | 4 cells (A, H, D, Depth); caption toggle `Envelope` (52, single-button ENABLE — was `Off\|On`); caption toggle 2 reads `Stage`/`Spline` (46, single-button MODE — was `Staged\|Spline`); **no corner radio** |
| **FILTER ENV** | 2 | 66 + 4 + 46 = 116 | 6 × 60 = **360** | **372** | +60 vs Γ | 6 slots (Gate: A,H,D,S,R,**Mod** / Trigger: A,H,D + 2 reserves,**Mod**) — **mod amt arrives from FILTER**; caption toggle 2 reads `Stage`/`Spline` (46, single-button MODE); **no corner radio**; no enable toggle of its own (FILTER's governs both) |
| **AMP ENVELOPE** | 2 | 78 + 4 + 88 + 4 + 46 = 220 | 5 × 60 = **300** | **312** | 0 | 5 slots (Gate: A,H,D,S,R / Trigger: Len,A,H,D + 1 reserve); caption toggle `Gate\|Trig` (88, segmented); caption toggle 2 reads `Stage`/`Spline` (46, single-button MODE — was `Staged\|Spline`); **no corner radio** |
| **MASTER** | **1+2** | 46 + 4 + 2·32 + 4 + 12 = **130** | 60 + 8 + 62 = **130** | **142** | +70 | 1 cell (gain, upper-left); 1 **reserved** lower-left slot; caption toggle `Limiter Off\|On` (32); corner **bubble** (12, passive); **meter column 62 px, full double height** |
| **MASTER** | **1+2** | 46 + 4 + 52 + 4 + 12 = **118** | 60 + 8 + 62 = **130** | **142** | +70 | 1 cell (gain, upper-left); 1 **reserved** lower-left slot; caption toggle `Limiter` (52, single-button ENABLE — was `Off\|On`); corner **bubble** (12, passive); **meter column 62 px, full double height** |
**Row totals.**
+3 -1
View File
@@ -37,7 +37,9 @@ void ReaSamplerEditor::onMouseDown(int x, int y) {
// The overlay focus follows the deck (mouseDownDeck sets it), and clicking a control
// surface OUTSIDE the envelope decks clears it. The waveform band is deliberately not one
// of those surfaces: it IS the overlay, so editing what you selected must not deselect it.
if (drag_ == DragKind::kNone && contains(fl.bands.chrome, x, y) &&
// Chrome's own dead space (the title band, the gaps between its controls) is not a control
// surface either — hoverChrome answers only for chrome's actual interactive elements.
if (drag_ == DragKind::kNone && hoverChrome(fl, x, y).kind != HoverKind::kNone &&
overlayEnv_ != OverlayEnv::kNone) {
overlayEnv_ = OverlayEnv::kNone;
invalidate(); // the chrome branches below repaint only what THEY changed
+5 -3
View File
@@ -32,9 +32,11 @@ bool ReaSamplerEditor::mouseDownDeck(const FaceLayout& fl, int x, int y) {
// The deck IS the overlay's click target: anywhere inside an envelope group — panel
// background, knob or button — focuses that envelope, and any other group clears it. Set
// BEFORE the kind switch and it consumes nothing, so every grab and commit below still
// runs. A drag in flight owns the surface, so it refuses the change.
// Repaints HERE rather than leaning on the branches below: a click on a group's bare
// padding, or on an inert knob, changes the focus and reaches no other invalidate.
// runs. A drag in flight owns the surface, so it refuses the change — always true at this
// call site today (mouse capture makes a real WM_LBUTTONDOWN-while-dragging unreachable;
// WM_CAPTURECHANGED and WM_LBUTTONUP both reset drag_ before another down can land), but
// left explicit rather than assumed so a future capture-handling change fails loud, not
// by silently letting a drag's own surface steal its own focus mid-gesture.
if (drag_ == DragKind::kNone) {
const OverlayEnv focus = overlayEnvForGroup(hit.group);
if (focus != overlayEnv_) {
+3 -1
View File
@@ -230,9 +230,11 @@ void ReaSamplerEditor::paintChrome(LICE_IBitmap* bmp, const FaceLayout& fl, bool
// its own mark, not just a slightly-quieter fill, so it draws the one outline this
// control ever gets. See PLAN.md's Off-vs-Disabled ruling: Off is live and
// clickable, Disabled is not, and the two must not read as the same thing.
// Outlined in text/dim rather than line/hairline: hairline over this fill composites
// to ~1.36:1, under the 3:1 state-indicator floor; text/dim clears it at ~5:1.
if (disabled) {
LICE_DrawRect(bmp, r.x, r.y, r.width - 1, r.height - 1,
toLice(roleColor(Role::LineHairline)), 1.0f, 0);
toLice(roleColor(Role::TextDim)), 1.0f, 0);
}
kitTextCentered(bmp, r, label, kToolbarFont,
active && !disabled ? Role::BgBase
+7 -3
View File
@@ -145,11 +145,15 @@ void ReaSamplerEditor::paintDeck(LICE_IBitmap* bmp, const FaceLayout& fl) {
const auto drawButtonToggle = [&](const DeckToggleLayout& t, const char* label, bool active,
bool disabled) {
const bool hov = !disabled && isHovered(HoverKind::kControl, t.id);
// Hover outranks Active here (the reverse of the old order) so an enabled button still
// gets a hover cue — same gap drawModeToggle's comment above explains, just on the
// ENABLE form's own base role: mixing toward accent/hot FROM accent/primary (rather
// than bg/cell) is what makes the already-lit button visibly brighten on hover.
const InteractionState st =
disabled ? InteractionState::Disabled
: (active ? InteractionState::Active
: (hov ? InteractionState::Hover : InteractionState::Rest));
fillSurface(bmp, toKitBox(t.seg0), Role::BgCell, st);
: (hov ? InteractionState::Hover
: (active ? InteractionState::Active : InteractionState::Rest));
fillSurface(bmp, toKitBox(t.seg0), active ? Role::AccentPrimary : Role::BgCell, st);
kitTextCentered(bmp, t.seg0, label, Font::Micro,
active && !disabled ? Role::BgBase
: (hov ? Role::TextPrimary : Role::TextDim));