Type-enforce the waveform overlay contract, narrow waveformLanes to LaneSplit, fix laneCount/cache/path-fallback bugs
This commit is contained in:
@@ -26,6 +26,10 @@ static int g_fail = 0;
|
||||
#define CHECK(cond) do { if(!(cond)) { \
|
||||
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
|
||||
|
||||
// buildEnvelopePolyline takes the overlay type, not a bare Rect (the distinct-type
|
||||
// enforcement in editor_geometry.h) — this wraps a plain test Rect for it.
|
||||
static OverlayArea overlayOf(const Rect& r) { return OverlayArea{r}; }
|
||||
|
||||
// A comfortable overlay area: 1000px wide, 100px tall, offset so left/top != 0 (catches origin
|
||||
// bugs). Under levelToY the level span is height-1 = 99 rows.
|
||||
static Rect wideArea() { return Rect::ltrb(20, 10, 1020, 110); } // width 1000, height 100
|
||||
@@ -112,7 +116,7 @@ static void testGateNodeOrderAndLevels() {
|
||||
env.sustainLevel = 0.5;
|
||||
env.releaseSeconds = 0.4;
|
||||
const Rect a = wideArea();
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
|
||||
// Six vertices, in draw order.
|
||||
CHECK(poly.size() == 6);
|
||||
@@ -147,7 +151,7 @@ static void testGateSchematicPlacement() {
|
||||
env.sustainLevel = 0.5;
|
||||
env.releaseSeconds = 0.4;
|
||||
const Rect a = wideArea();
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
|
||||
EnvVertex v;
|
||||
CHECK(findNode(poly, EnvNode::AttackEnd, v) && v.x == a.x + 28);
|
||||
@@ -169,7 +173,7 @@ static void testGateLayoutIndependentOfSampleDuration() {
|
||||
env.sustainLevel = 0.5;
|
||||
env.releaseSeconds = 0.06;
|
||||
const Rect a = wideArea();
|
||||
CHECK(buildEnvelopePolyline(env, a, 0.3) == buildEnvelopePolyline(env, a, 10.0));
|
||||
CHECK(buildEnvelopePolyline(env, overlayOf(a), 0.3) == buildEnvelopePolyline(env, overlayOf(a), 10.0));
|
||||
}
|
||||
|
||||
static void testGateMinSeparationAtDefaults() {
|
||||
@@ -178,7 +182,7 @@ static void testGateMinSeparationAtDefaults() {
|
||||
// renders on top of its neighbour, so each is individually grabbable.
|
||||
const AmpEnvelope env; // struct defaults ARE the tier-0 Gate defaults
|
||||
const Rect a = wideArea();
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
CHECK(poly.size() == 6);
|
||||
for (size_t i = 1; i < poly.size(); ++i) {
|
||||
CHECK(poly[i].x - poly[i - 1].x >= kGateNodeSepPx);
|
||||
@@ -197,7 +201,7 @@ static void testGateSustainPlateauFixedWidth() {
|
||||
env.releaseSeconds = 0.3;
|
||||
const Rect a = wideArea();
|
||||
const int plateauPx = a.width - gateTimedWidth(a); // 150
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
|
||||
EnvVertex decay, plateauEnd;
|
||||
CHECK(findNode(poly, EnvNode::DecayEnd, decay));
|
||||
@@ -218,7 +222,7 @@ static void testGateReleaseVisibleInBounds() {
|
||||
env.sustainLevel = 0.5;
|
||||
env.releaseSeconds = 0.4;
|
||||
const Rect a = wideArea();
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
|
||||
EnvVertex plateauEnd, rel;
|
||||
CHECK(findNode(poly, EnvNode::ReleaseStart, plateauEnd));
|
||||
@@ -241,7 +245,7 @@ static void testGateOverrunCompressesFromRight() {
|
||||
env.sustainLevel = 0.7;
|
||||
env.releaseSeconds = 4.0;
|
||||
const Rect a = wideArea();
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
CHECK(poly.size() == 6);
|
||||
|
||||
EnvVertex plateauEnd, rel;
|
||||
@@ -279,7 +283,7 @@ static void testGateAllVerticesInBounds() {
|
||||
huge.releaseSeconds = 1e12;
|
||||
|
||||
for (const AmpEnvelope& env : {base, big, zero, trig, huge}) {
|
||||
for (const EnvVertex& v : buildEnvelopePolyline(env, a, 2.0)) {
|
||||
for (const EnvVertex& v : buildEnvelopePolyline(env, overlayOf(a), 2.0)) {
|
||||
CHECK(v.x >= a.x && v.x < a.right());
|
||||
CHECK(v.y >= a.y && v.y < a.bottom());
|
||||
}
|
||||
@@ -297,7 +301,7 @@ static void testTriggerShape() {
|
||||
env.fadeInFraction = 0.2;
|
||||
env.fadeOutFraction = 0.3;
|
||||
const Rect a = wideArea();
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
|
||||
CHECK(poly.size() == 4);
|
||||
CHECK(poly[0].node == EnvNode::Origin);
|
||||
@@ -319,7 +323,7 @@ static void testTriggerFadeOverlapClamp() {
|
||||
env.fadeInFraction = 0.8; // fade-in end at 0.8*2.0 = 1.6s -> x@800
|
||||
env.fadeOutFraction = 0.6; // would be 1.4s -> clamped to 1-0.8=0.2 -> begins at 0.8*2.0 too
|
||||
const Rect a = wideArea();
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
|
||||
EnvVertex fin, fout;
|
||||
CHECK(findNode(poly, EnvNode::FadeInEnd, fin));
|
||||
@@ -338,7 +342,7 @@ static void testTriggerFullLengthZeroFadeOutInBounds() {
|
||||
env.fadeInFraction = 0.1;
|
||||
env.fadeOutFraction = 0.0;
|
||||
const Rect a = wideArea();
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, a, 2.0);
|
||||
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, overlayOf(a), 2.0);
|
||||
|
||||
EnvVertex fout, lend;
|
||||
CHECK(findNode(poly, EnvNode::FadeOutStart, fout));
|
||||
@@ -353,12 +357,12 @@ static void testTriggerFullLengthZeroFadeOutInBounds() {
|
||||
static void testDegenerateFlatBaseline() {
|
||||
AmpEnvelope env; // any params
|
||||
const Rect zeroW = Rect::ltrb(0, 0, 0, 100);
|
||||
const std::vector<EnvVertex> p1 = buildEnvelopePolyline(env, zeroW, 2.0);
|
||||
const std::vector<EnvVertex> p1 = buildEnvelopePolyline(env, overlayOf(zeroW), 2.0);
|
||||
CHECK(p1.size() == 2); // always a drawable line
|
||||
CHECK(p1.front().level == 0.0 && p1.back().level == 0.0);
|
||||
|
||||
const Rect ok = wideArea();
|
||||
const std::vector<EnvVertex> p2 = buildEnvelopePolyline(env, ok, 0.0); // no duration
|
||||
const std::vector<EnvVertex> p2 = buildEnvelopePolyline(env, overlayOf(ok), 0.0); // no duration
|
||||
CHECK(p2.size() == 2);
|
||||
CHECK(p2.front().level == 0.0 && p2.back().level == 0.0);
|
||||
CHECK(p2.front().x == ok.x && p2.back().x == ok.right() - 1); // spans the area, in-bounds
|
||||
|
||||
Reference in New Issue
Block a user