summaryrefslogtreecommitdiff
path: root/tools/mq_editor/editor.js
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-18 21:36:07 +0100
committerskal <pascal.massimino@gmail.com>2026-02-18 21:36:07 +0100
commitf48397c58248ca338c258b1de762314926fe681f (patch)
tree219ddcc63f1600ae5604d655bb4c6faabd91ca33 /tools/mq_editor/editor.js
parenteeecb76eef15f684b7909ff22fd054680c2a3498 (diff)
feat(mq_editor): movable inner bezier control points + clamp() refactor
- P1/P2 in amp editor now draggable horizontally; t0<t1<t2<t3 enforced - Add clamp() to utils.js; replace all Math.max/min clamping patterns - Cursor hints: move for P1/P2, ns-resize for P0/P3 - Remove test_fft.html - Docs: Delete key, style.css/utils.js in architecture, bezier editor section handoff(Claude): inner control points done, clamp() adopted everywhere Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'tools/mq_editor/editor.js')
-rw-r--r--tools/mq_editor/editor.js19
1 files changed, 13 insertions, 6 deletions
diff --git a/tools/mq_editor/editor.js b/tools/mq_editor/editor.js
index a7d0879..6ea6d73 100644
--- a/tools/mq_editor/editor.js
+++ b/tools/mq_editor/editor.js
@@ -322,10 +322,10 @@ class PartialEditor {
if (!dragging) return;
const dx = e.clientX - startX;
const half = slider.offsetWidth / 2;
- const clamped = Math.max(-half, Math.min(half, dx));
+ const clamped = clamp(dx, -half, half);
thumb.style.transition = 'none';
thumb.style.left = `calc(50% - 3px + ${clamped}px)`;
- const newVal = Math.max(min, Math.min(max, startVal + dx * sensitivity));
+ const newVal = clamp(startVal + dx * sensitivity, min, max);
inp.value = newVal.toFixed(decimals);
onUpdate(newVal);
};
@@ -496,7 +496,7 @@ class PartialEditor {
if (Math.hypot(this._tToX(curve['t' + i]) - x, this._ampToY(curve['a' + i]) - y) <= 8) {
if (this.onBeforeChange) this.onBeforeChange();
this._dragPointIndex = i;
- canvas.style.cursor = 'grabbing';
+ canvas.style.cursor = (i === 1 || i === 2) ? 'move' : 'ns-resize';
e.preventDefault();
return;
}
@@ -510,6 +510,12 @@ class PartialEditor {
const curve = this.partials[this._selectedIndex].freqCurve;
const i = this._dragPointIndex;
curve['a' + i] = Math.max(0, this._yToAmp(y));
+ // Inner control points are also horizontally draggable
+ if (i === 1) {
+ curve.t1 = clamp(this._xToT(x), curve.t0 + 1e-4, curve.t2 - 1e-4);
+ } else if (i === 2) {
+ curve.t2 = clamp(this._xToT(x), curve.t1 + 1e-4, curve.t3 - 1e-4);
+ }
this._renderAmpEditor();
if (this.viewer) this.viewer.render();
e.preventDefault();
@@ -520,13 +526,14 @@ class PartialEditor {
if (this._selectedIndex >= 0 && this.partials) {
const curve = this.partials[this._selectedIndex]?.freqCurve;
if (curve) {
- let near = false;
+ let cursor = 'crosshair';
for (let i = 0; i < 4; ++i) {
if (Math.hypot(this._tToX(curve['t' + i]) - x, this._ampToY(curve['a' + i]) - y) <= 8) {
- near = true; break;
+ cursor = (i === 1 || i === 2) ? 'move' : 'ns-resize';
+ break;
}
}
- canvas.style.cursor = near ? 'grab' : 'crosshair';
+ canvas.style.cursor = cursor;
}
}
});