feat: legible ReaSampler 9000 editor — bigger knobs, ms time constants, per-ring double-click reset, and an antialiased draw pass

This commit is contained in:
2026-08-01 09:16:30 -04:00
parent 213ecfafe6
commit 7f74b11dce
27 changed files with 859 additions and 285 deletions
+21 -6
View File
@@ -22,11 +22,13 @@
namespace reasampler::instrument::ui {
// Fixed deck metrics, exposed so the shell and tests agree.
inline constexpr int kDeckCellW = 48; // one knob cell
inline constexpr int kDeckCellH = 58;
inline constexpr int kDeckKnobSize = 28; // knob diameter inside the cell
inline constexpr int kDeckCellLabelH = 12; // the Micro label band under the knob
// Fixed deck metrics, exposed so the shell and tests agree. The cell/knob/label sizes were
// raised together for legibility at high pixel densities; the editor's floor width
// (sample_bands) is what absorbs the wider cells, so the two move as a pair.
inline constexpr int kDeckCellW = 60; // one knob cell
inline constexpr int kDeckCellH = 74;
inline constexpr int kDeckKnobSize = 40; // knob diameter inside the cell
inline constexpr int kDeckCellLabelH = 16; // the label band under the knob
inline constexpr int kDeckCaptionH = 20; // the group caption row
inline constexpr int kDeckToggleH = 18; // compact toggle segment height
inline constexpr int kDeckGroupPadX = 6; // group box horizontal inner padding
@@ -39,7 +41,7 @@ inline constexpr int kDeckRadioSize = 12; // the caption-row corner radio sq
// The knob cell's INNER dial: a concentric sub-disc that edits a second, related value while
// the outer ring keeps editing the cell's own. Geometry only — WHICH cells carry one is
// deck_groups' call, so a cell without an inner value simply resolves an inner hit as a knob.
inline constexpr int kDeckInnerDialSize = 14;
inline constexpr int kDeckInnerDialSize = 20;
// One group box: padding + caption + gap + cell row + padding.
inline constexpr int kDeckGroupH =
kDeckGroupPadY + kDeckCaptionH + kDeckCaptionGap + kDeckCellH + kDeckGroupPadY;
@@ -145,4 +147,17 @@ struct DeckHit {
// the caption-row corner radio. Everything else — fence, padding, outside — misses.
DeckHit hitTestDeck(const DeckLayout& layout, int x, int y);
// The knob FACE a point lands on. id -1 is a miss.
struct DeckFaceHit {
int id = -1;
bool inner = false; // inside the concentric inner disc
};
// Resolved against the drawn CIRCLES, not the cell: a reset is aimed at a dial, so the label
// band and the cell margins must miss where a drag grab deliberately does not. Both radii are
// boundary-EXCLUSIVE, one rule for both rings — a point exactly on the inner radius is an
// outer-ring hit, one exactly on the outer radius is a miss. Whether a cell actually carries an
// inner value is deck_groups' call, exactly as with DeckHit::inner.
DeckFaceHit hitTestKnobFace(const DeckLayout& layout, int x, int y);
} // namespace reasampler::instrument::ui