summaryrefslogtreecommitdiff
path: root/tools/mq_editor/editor.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mq_editor/editor.js')
-rw-r--r--tools/mq_editor/editor.js55
1 files changed, 54 insertions, 1 deletions
diff --git a/tools/mq_editor/editor.js b/tools/mq_editor/editor.js
index 9cfcdf1..b767534 100644
--- a/tools/mq_editor/editor.js
+++ b/tools/mq_editor/editor.js
@@ -146,8 +146,15 @@ class PartialEditor {
if (this.viewer) this.viewer.render();
});
inputs[p.key] = inp;
+
+ const jog = this._makeJogSlider(inp, partial, index, p, defaults);
+ const wrap = document.createElement('div');
+ wrap.className = 'synth-field-wrap';
+ wrap.appendChild(inp);
+ wrap.appendChild(jog);
+
grid.appendChild(lbl);
- grid.appendChild(inp);
+ grid.appendChild(wrap);
}
// Auto-detect spread button
@@ -173,6 +180,52 @@ class PartialEditor {
grid.appendChild(autoBtn);
}
+ _makeJogSlider(inp, partial, index, p, defaults) {
+ const slider = document.createElement('div');
+ slider.className = 'jog-slider';
+ const thumb = document.createElement('div');
+ thumb.className = 'jog-thumb';
+ slider.appendChild(thumb);
+
+ const sensitivity = parseFloat(p.step) * 5;
+ let startX = 0, startVal = 0, dragging = false;
+
+ const onMove = (e) => {
+ if (!dragging) return;
+ const dx = e.clientX - startX;
+ const half = slider.offsetWidth / 2;
+ const clamped = Math.max(-half, Math.min(half, dx));
+ thumb.style.transition = 'none';
+ thumb.style.left = `calc(50% - 3px + ${clamped}px)`;
+ const newVal = Math.max(0, startVal + dx * sensitivity);
+ inp.value = newVal.toFixed(3);
+ if (!this.partials || !this.partials[index]) return;
+ if (!this.partials[index].replicas) this.partials[index].replicas = { ...defaults };
+ this.partials[index].replicas[p.key] = newVal;
+ if (this.viewer) this.viewer.render();
+ };
+
+ const onUp = () => {
+ if (!dragging) return;
+ dragging = false;
+ thumb.style.transition = '';
+ thumb.style.left = 'calc(50% - 3px)';
+ document.removeEventListener('mousemove', onMove);
+ document.removeEventListener('mouseup', onUp);
+ };
+
+ slider.addEventListener('mousedown', (e) => {
+ dragging = true;
+ startX = e.clientX;
+ startVal = Math.max(0, parseFloat(inp.value) || 0);
+ document.addEventListener('mousemove', onMove);
+ document.addEventListener('mouseup', onUp);
+ e.preventDefault();
+ });
+
+ return slider;
+ }
+
_makeCurveUpdater(partialIndex, curveKey, field, pointIndex) {
return (e) => {
if (!this.partials) return;