fix(param_slider): 7->5 o'clock arc (50% straight up), seam contract single-sourced, boundary/normDeg/wrap-boundary fixes
This commit is contained in:
@@ -89,6 +89,9 @@ constexpr double kPi = 3.14159265358979323846;
|
||||
double normDeg(double deg) {
|
||||
deg = std::fmod(deg, 360.0);
|
||||
if (deg < 0.0) deg += 360.0;
|
||||
// Guard: fmod can return exactly 360.0 on some implementations due to floating-point
|
||||
// rounding; fold it back to 0.
|
||||
if (deg >= 360.0) deg -= 360.0;
|
||||
return deg;
|
||||
}
|
||||
|
||||
@@ -109,7 +112,8 @@ bool knobHitTest(const KnobGeometry& knob, int x, int y) {
|
||||
if (knob.radius <= 0.0) return false;
|
||||
const double dx = x - knob.centerX;
|
||||
const double dy = y - knob.centerY;
|
||||
return dx * dx + dy * dy <= knob.radius * knob.radius;
|
||||
// Boundary exclusive: matches the module's half-open Rect convention.
|
||||
return dx * dx + dy * dy < knob.radius * knob.radius;
|
||||
}
|
||||
|
||||
double knobSweepDeg(const KnobArc& arc) {
|
||||
|
||||
+15
-11
@@ -105,17 +105,18 @@ double valueAtPoint(const Rect& control, int x);
|
||||
// (value 0) to endDeg (value 1); an endDeg at-or-behind startDeg wraps +360, so equal
|
||||
// angles mean a full 360° sweep.
|
||||
//
|
||||
// The DEFAULT arc encodes Daniel's "6 to 4 o'clock" spec: min at 6 o'clock (180°) sweeping
|
||||
// clockwise 300° around to max at 4 o'clock (120°), leaving a minimal 60° dead arc at the
|
||||
// bottom-right. The angles are PARAMETERS, not hardcoded — the shell sets the final sweep
|
||||
// when the parallel layout spec lands.
|
||||
inline constexpr double kKnobArcStartDeg = 180.0; // value 0 — 6 o'clock
|
||||
inline constexpr double kKnobArcEndDeg = 120.0; // value 1 — 4 o'clock (clockwise wrap)
|
||||
// The DEFAULT arc is the conventional 7→5 o'clock layout: min at 7 o'clock (210°) sweeping
|
||||
// clockwise 300° around to max at 5 o'clock (150°), leaving a symmetric 60° dead arc at the
|
||||
// bottom. The 50% (midpoint) value lands at 12 o'clock (0°/360°) — straight up. The angles
|
||||
// are PARAMETERS, not hardcoded — the shell sets the final sweep when the parallel layout
|
||||
// spec lands.
|
||||
inline constexpr double kKnobArcStartDeg = 210.0; // value 0 — 7 o'clock
|
||||
inline constexpr double kKnobArcEndDeg = 150.0; // value 1 — 5 o'clock (clockwise wrap)
|
||||
|
||||
// Default vertical-drag sensitivity: pixels of upward drag for one full 0->1 sweep.
|
||||
inline constexpr int kKnobDragRangePixels = 128;
|
||||
|
||||
// The configurable value arc of a knob. Defaults to the 6->4 o'clock reading above.
|
||||
// The configurable value arc of a knob. Defaults to the 7->5 o'clock reading above.
|
||||
struct KnobArc {
|
||||
double startDeg = kKnobArcStartDeg;
|
||||
double endDeg = kKnobArcEndDeg;
|
||||
@@ -136,12 +137,15 @@ struct KnobPoint {
|
||||
};
|
||||
|
||||
// The knob circle inscribed in `cell`, centered, radius = half the smaller dimension. A
|
||||
// degenerate cell yields radius 0. The shell passes whatever cell it wants the knob in
|
||||
// (the whole control column, or a square sub-cell from its own layout). Pure.
|
||||
// degenerate cell yields radius 0. CONTRACT: the shell MUST pass `row.control` (the full
|
||||
// control column) both when drawing and when hit-testing — `controlAtPoint` always uses
|
||||
// `r.control` as the cell, so the draw cell and hit cell must be the same. If the shell
|
||||
// wants to draw a smaller circle it must center it within `row.control` and accept that the
|
||||
// hit area is the larger column-inscribed circle. Pure.
|
||||
KnobGeometry computeKnob(const Rect& cell);
|
||||
|
||||
// True if (x, y) falls inside the knob circle (boundary inclusive). A degenerate knob
|
||||
// (radius <= 0) hits nothing. Pure.
|
||||
// True if (x, y) falls strictly inside the knob circle (boundary exclusive, matching the
|
||||
// module's half-open Rect convention). A degenerate knob (radius <= 0) hits nothing. Pure.
|
||||
bool knobHitTest(const KnobGeometry& knob, int x, int y);
|
||||
|
||||
// The clockwise sweep of `arc` in degrees, in (0, 360]: normalized end - start, wrapping
|
||||
|
||||
Reference in New Issue
Block a user