Fix envelope-overlay knot/trace disagreement on odd pixel spans
Generalize curveMidLevel/curveFromMidLevel to curveLevelAt/curveFromLevelAt at arbitrary phi; knotVtx and its drag inverse now read the phi a knot's truncated x actually implies, not always 0.5.
This commit is contained in:
@@ -373,6 +373,40 @@ static void testKnotOnANearLevelSegmentIsANoOp() {
|
||||
CHECK(out.decayCurve == 2.5);
|
||||
}
|
||||
|
||||
// The knot drag must read the SAME phi the draw used even off the segment midpoint (an odd
|
||||
// pixel span), not the fixed phi = 0.5 wideArea()'s AttackCurve span happens to land on above.
|
||||
// Checked two ways: a zero-delta grab reproduces the stored exponent, and a real one-pixel drag
|
||||
// moves the knot's own drawn y by the same one pixel every other node axis tracks 1:1.
|
||||
static void testKnotDragTracksTheDrawOnAnOddPixelSpan() {
|
||||
bool found = false;
|
||||
for (int width = 24; width <= 260 && !found; ++width) {
|
||||
const Rect a = Rect::ltrb(0, 0, width, 100);
|
||||
StageEnvelope e = ahdsrEnv();
|
||||
e.attackCurve = 3.0;
|
||||
EnvVertex origin, attackEnd, knot;
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(e, overlayOf(a), kTotal);
|
||||
if (!findNode(poly, EnvNode::Origin, origin)) continue;
|
||||
if (!findNode(poly, EnvNode::AttackEnd, attackEnd)) continue;
|
||||
if (!findNode(poly, EnvNode::AttackCurve, knot)) continue;
|
||||
const int span = attackEnd.x - origin.x;
|
||||
if (span <= 0 || span % 2 == 0) continue;
|
||||
found = true;
|
||||
|
||||
const StageEnvelope same =
|
||||
resolveNodeDrag(e, EnvNode::AttackCurve, overlayOf(a), kTotal, bounds(), 0, 0);
|
||||
CHECK(std::fabs(same.attackCurve - e.attackCurve) < 1e-9);
|
||||
|
||||
const StageEnvelope dragged =
|
||||
resolveNodeDrag(e, EnvNode::AttackCurve, overlayOf(a), kTotal, bounds(), 0, 1);
|
||||
EnvVertex knotAfter;
|
||||
CHECK(findNode(buildEnvelopePolyline(dragged, overlayOf(a), kTotal), EnvNode::AttackCurve,
|
||||
knotAfter));
|
||||
CHECK(knotAfter.x == knot.x); // a curve drag never moves the knot's x
|
||||
CHECK(std::abs(knotAfter.y - (knot.y + 1)) <= 1);
|
||||
}
|
||||
CHECK(found); // the sweep must actually land on an odd span
|
||||
}
|
||||
|
||||
// --- the interaction law on the overlay ----------------------------------------
|
||||
|
||||
// Ctrl scales the PIXEL delta, so it composes with every axis — the tapered schematic, the 1:1
|
||||
@@ -476,6 +510,7 @@ int main() {
|
||||
testKnotAndModelCannotDiverge();
|
||||
testKnotOnALevelSegmentIsANoOp();
|
||||
testKnotOnANearLevelSegmentIsANoOp();
|
||||
testKnotDragTracksTheDrawOnAnOddPixelSpan();
|
||||
|
||||
testDegenerateInputsAreNoOps();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user