fix: close review findings on the velocity-curve deck and bipolar curves

Cancels the curve-node drag whenever the popup closes so Esc mid-drag can't alias the amp curve; generalizes CurveTarget routing to one switch; fixes stale/overstated comments; clamps a pre-v12 depth fold; adds deck-inertness and filter-fold test coverage.
This commit is contained in:
2026-07-31 19:46:37 -04:00
parent 9d38f87a2d
commit cfb53aade3
22 changed files with 223 additions and 99 deletions
+15 -7
View File
@@ -8,6 +8,7 @@
#include "../src/core/instrument/engine/velocity_curve.h"
#include <algorithm>
#include <cstdio>
using namespace reasampler;
@@ -89,10 +90,14 @@ static void testOutsideSheetDismissTest() {
// the popup's real geometry, because that is what makes one popup code path legitimate.
static void testTheSameCurveBoxHostsBothDomains() {
const CurvePopupLayout pl = computeCurvePopup(840, 620);
// The shell insets this rect before mapping; the inset is uniform, so any box inside the
// curveBox exercises the same relationship. Use the rect itself.
const VelocityCurve::Box box{pl.curveBox.x, pl.curveBox.y, pl.curveBox.width,
pl.curveBox.height};
// The editor never maps against the raw curveBox — shell/instrument/editor_internal.h's
// curveBoxFromRect insets it first (kVelCurveInset == 14, mirrored here since this pure
// target cannot link the shell). Applying it, not the raw rect, is what exercises the
// actual box shape paint/hit-test/drag agree on.
constexpr int kInset = 14;
const VelocityCurve::Box box{pl.curveBox.x + kInset, pl.curveBox.y + kInset,
std::max(0, pl.curveBox.width - 2 * kInset),
std::max(0, pl.curveBox.height - 2 * kInset)};
CHECK(box.width > 1 && box.height > 1);
const VelocityCurve amp = VelocityCurve::flat();
@@ -105,12 +110,15 @@ static void testTheSameCurveBoxHostsBothDomains() {
CHECK(amp.pixelFromPoint(box, {0.0, 0.0}).y == bottom);
CHECK(mod.pixelFromPoint(box, {0.0, 1.0}).y == top);
CHECK(mod.pixelFromPoint(box, {0.0, -1.0}).y == bottom);
// ...so value 0 is the FLOOR for the amp curve and the MIDLINE for a modulation curve.
CHECK(mod.pixelFromPoint(box, {0.0, 0.0}).y == (top + bottom) / 2);
// ...so value 0 is the FLOOR for the amp curve and the MIDLINE for a modulation curve. The
// expected row replicates valueToY's own HALF-UP rounding on the inverted fraction (velocity_
// curve.cpp) rather than a plain integer bisection of top/bottom: the two agree only when
// box.height-1 is even, so a naive (top+bottom)/2 silently depends on this box's parity.
const int midY = top + static_cast<int>(0.5 * static_cast<double>(box.height - 1) + 0.5);
CHECK(mod.pixelFromPoint(box, {0.0, 0.0}).y == midY);
// And a click at the vertical centre adds a point at 0 in the bipolar editor, at 0.5 in
// the unipolar one — one hit-test path, two correct answers.
const int midY = (top + bottom) / 2;
CHECK(mod.pointFromPixel(box, box.left, midY).value == 0.0);
CHECK(amp.pointFromPixel(box, box.left, midY).value > 0.49);
CHECK(amp.pointFromPixel(box, box.left, midY).value < 0.51);