diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-18 17:28:38 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-18 17:28:38 +0100 |
| commit | 37d7601ab64e0dd22ca3e579c3b8332d32c41b9a (patch) | |
| tree | acd5ac5889af6ba3a644bbfb23d381a3e4f32843 /tools/mq_editor/editor.js | |
| parent | 1eb7f1d06798b3a3455817dfcd1876febd3eca89 (diff) | |
feat(mq_editor): add new partial, undo/redo
- '+ Partial' button (N key): insert 440Hz/max-amp partial at front
- Undo/Redo buttons (Ctrl+Z/Y): JSON snapshot stack, 50 levels
- Hooks in delete, mute, curve edits, amp drag, freq drag
handoff(Gemini): undo/redo + new-partial added to mq_editor
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.js | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/tools/mq_editor/editor.js b/tools/mq_editor/editor.js index 3c07877..0854ec0 100644 --- a/tools/mq_editor/editor.js +++ b/tools/mq_editor/editor.js @@ -20,6 +20,8 @@ class PartialEditor { // Callback: called after a partial is deleted so the host can update keepCount this.onPartialDeleted = null; + // Callback: called before any mutation (for undo/redo) + this.onBeforeChange = null; // Private state this._selectedIndex = -1; @@ -355,6 +357,7 @@ class PartialEditor { if (!this.partials) return; const val = parseFloat(e.target.value); if (isNaN(val)) return; + if (this.onBeforeChange) this.onBeforeChange(); this.partials[partialIndex][curveKey][field + pointIndex] = val; if (this.viewer) this.viewer.render(); }; @@ -363,6 +366,7 @@ class PartialEditor { _setupButtons() { document.getElementById('mutePartialBtn').addEventListener('click', () => { if (this._selectedIndex < 0 || !this.partials) return; + if (this.onBeforeChange) this.onBeforeChange(); const p = this.partials[this._selectedIndex]; p.muted = !p.muted; if (this.viewer) this.viewer.render(); @@ -371,6 +375,7 @@ class PartialEditor { document.getElementById('deletePartialBtn').addEventListener('click', () => { if (this._selectedIndex < 0 || !this.partials || !this.viewer) return; + if (this.onBeforeChange) this.onBeforeChange(); this.partials.splice(this._selectedIndex, 1); this.viewer.selectPartial(-1); if (this.onPartialDeleted) this.onPartialDeleted(); @@ -490,6 +495,7 @@ class PartialEditor { const curve = partial.freqCurve; for (let i = 0; i < 4; ++i) { if (Math.hypot(this._tToX(curve['t' + i]) - x, this._ampToY(curve['a' + i]) - y) <= 8) { + if (this.onBeforeChange) this.onBeforeChange(); this._dragPointIndex = i; this._dragCompanionOff = null; if (i === 0) |
