Type-enforce the waveform overlay contract, narrow waveformLanes to LaneSplit, fix laneCount/cache/path-fallback bugs

This commit is contained in:
2026-07-30 09:35:11 -04:00
parent 2a0d10fab5
commit fb12c53522
19 changed files with 233 additions and 174 deletions
+7 -5
View File
@@ -63,7 +63,8 @@ bool nodeInMode(EnvNode n, EnvMode m) {
} // namespace
NodeHit nodeAtPoint(const AmpEnvelope& env, const Rect& area, double totalSeconds, int x, int y) {
NodeHit nodeAtPoint(const AmpEnvelope& env, const OverlayArea& area, double totalSeconds, int x,
int y) {
const std::vector<EnvVertex> poly = buildEnvelopePolyline(env, area, totalSeconds);
// Nearest draggable, mode-matching node within the pick radius wins (Chebyshev distance);
// ties go to the earlier draw-order node. Only matters for Trigger's zero-fade-out
@@ -81,16 +82,17 @@ NodeHit nodeAtPoint(const AmpEnvelope& env, const Rect& area, double totalSecond
return best;
}
AmpEnvelope resolveNodeDrag(const AmpEnvelope& grabEnv, EnvNode node, const Rect& area,
AmpEnvelope resolveNodeDrag(const AmpEnvelope& grabEnv, EnvNode node, const OverlayArea& area,
double totalSeconds, const EnvClampBounds& bounds,
int dxPixels, int dyPixels) {
AmpEnvelope out = grabEnv;
if (!isDraggable(node) || !nodeInMode(node, grabEnv.mode)) return out;
const double secPerPx = secondsPerPixel(area, totalSeconds);
const Rect& rect = area.rect;
const double secPerPx = secondsPerPixel(rect, totalSeconds);
if (secPerPx <= 0.0) return out; // degenerate area / duration — no motion
const double dSec = static_cast<double>(dxPixels) * secPerPx;
const double gateDSec = static_cast<double>(dxPixels) * gateSecondsPerPixel(area);
const double gateDSec = static_cast<double>(dxPixels) * gateSecondsPerPixel(rect);
switch (node) {
// Gate: each cumulative-time node edits its own segment duration. Non-negative durations
@@ -106,7 +108,7 @@ AmpEnvelope resolveNodeDrag(const AmpEnvelope& grabEnv, EnvNode node, const Rect
case EnvNode::DecayEnd: {
// X sets decay time, Y sets sustain level (drag down = higher y = lower level).
out.decaySeconds = std::clamp(grabEnv.decaySeconds + gateDSec, 0.0, bounds.maxDecaySeconds);
const double lvlPerPx = levelPerPixel(area);
const double lvlPerPx = levelPerPixel(rect);
const double dLevel = -static_cast<double>(dyPixels) * lvlPerPx;
out.sustainLevel = std::clamp(grabEnv.sustainLevel + dLevel, 0.0, 1.0);
break;