Add D5 Design-View mode switch to bank panel
New pure mode_switch module (header-rect -> N equal segment rects + point hit-test, unit-tested) plus a segmented switch in the bank_panel header: one lit segment per registered mode, click activates via view::applyMode. Grid offset below the header.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
// mode_switch — pure implementation. See mode_switch.h. NO REAPER / SWELL / vendor.
|
||||
|
||||
#include "mode_switch.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace reasampler {
|
||||
|
||||
namespace {
|
||||
|
||||
// The left edge of segment i in a header of the given x-origin and width divided
|
||||
// into `count` segments. Boundary i is x + (i * width) / count, so segment i spans
|
||||
// [edge(i), edge(i+1)). Because every boundary is derived from the same formula,
|
||||
// consecutive segments share an exact edge (no gap, no overlap) and edge(count)
|
||||
// == x + width precisely. count assumed >= 1 by callers.
|
||||
int segmentEdge(int x, int width, int i, int count) {
|
||||
return x + (i * width) / count;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<SegmentRect> computeSegmentRects(const HeaderRect& header,
|
||||
int segmentCount) {
|
||||
std::vector<SegmentRect> rects;
|
||||
if (segmentCount <= 0 || header.width <= 0) return rects;
|
||||
|
||||
rects.reserve(static_cast<std::size_t>(segmentCount));
|
||||
for (int i = 0; i < segmentCount; ++i) {
|
||||
const int left = segmentEdge(header.x, header.width, i, segmentCount);
|
||||
const int right = segmentEdge(header.x, header.width, i + 1, segmentCount);
|
||||
SegmentRect r;
|
||||
r.x = left;
|
||||
r.y = header.y;
|
||||
r.width = right - left; // absorbs rounding; adjacent segments abut exactly
|
||||
r.height = header.height;
|
||||
rects.push_back(r);
|
||||
}
|
||||
return rects;
|
||||
}
|
||||
|
||||
int hitTestSegment(int px, int py, const HeaderRect& header, int segmentCount) {
|
||||
if (segmentCount <= 0 || header.width <= 0 || header.height <= 0) return -1;
|
||||
|
||||
// Reject anything outside the header band first (half-open bounds match the
|
||||
// segment rects). Below the header is where the grid lives — the panel falls
|
||||
// through to grid handling on a -1.
|
||||
if (px < header.x || px >= header.x + header.width ||
|
||||
py < header.y || py >= header.y + header.height)
|
||||
return -1;
|
||||
|
||||
// Inside the band: find the segment whose [edge(i), edge(i+1)) contains px.
|
||||
// Linear over N (N is tiny — one per mode); mirrors the boundary formula so the
|
||||
// hit matches the drawn segment exactly.
|
||||
for (int i = 0; i < segmentCount; ++i) {
|
||||
const int left = segmentEdge(header.x, header.width, i, segmentCount);
|
||||
const int right = segmentEdge(header.x, header.width, i + 1, segmentCount);
|
||||
if (px >= left && px < right) return i;
|
||||
}
|
||||
// Guard: px == header.x + header.width would fail the < above but was already
|
||||
// excluded by the band check. Any residual falls to -1 (defensive, unreachable).
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace reasampler
|
||||
Reference in New Issue
Block a user