feat: Snap to Scale toggle + remove tool buttons + no menu on erase sweep
- Added snapToScale state + toggle switch in piano roll toolbar - snapPitchToScale only applies when snapToScale is true - Removed Select/Pen/Eraser tool buttons - Right-click drag erase sweep sets swallowContextMenuRef=true so context menu won't appear during sweep
This commit is contained in:
+16
-10
@@ -5068,12 +5068,12 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
mode: 'draw',
|
mode: 'draw',
|
||||||
idx: -1,
|
idx: -1,
|
||||||
startOffsetBeat: start,
|
startOffsetBeat: start,
|
||||||
startOffsetPitch: snapPitchToScale(pitch, selectedScale),
|
startOffsetPitch: snapToScale ? snapPitchToScale(pitch, selectedScale) : pitch,
|
||||||
drawNoteId: noteId,
|
drawNoteId: noteId,
|
||||||
drawDuration: initialDur,
|
drawDuration: initialDur,
|
||||||
visitedPitches: [snapPitchToScale(pitch, selectedScale)],
|
visitedPitches: snapToScale ? [snapPitchToScale(pitch, selectedScale)] : [pitch],
|
||||||
initialBeat: start,
|
initialBeat: start,
|
||||||
initialPitch: snapPitchToScale(pitch, selectedScale)
|
initialPitch: snapToScale ? snapPitchToScale(pitch, selectedScale) : pitch
|
||||||
});
|
});
|
||||||
// Play the note with SoundFont
|
// Play the note with SoundFont
|
||||||
if (window.SonicSF) {
|
if (window.SonicSF) {
|
||||||
@@ -5118,6 +5118,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
const rc = rightClickDragRef.current;
|
const rc = rightClickDragRef.current;
|
||||||
if (rc.active && (Math.abs(e.clientX - rc.startX) > 5 || Math.abs(e.clientY - rc.startY) > 5)) {
|
if (rc.active && (Math.abs(e.clientX - rc.startX) > 5 || Math.abs(e.clientY - rc.startY) > 5)) {
|
||||||
rc.active = false;
|
rc.active = false;
|
||||||
|
swallowContextMenuRef.current = true;
|
||||||
notesBeforeDragRef.current = JSON.parse(JSON.stringify(notes));
|
notesBeforeDragRef.current = JSON.parse(JSON.stringify(notes));
|
||||||
setDraggedNote({ mode: 'erase_sweep', visitedPitches: [] });
|
setDraggedNote({ mode: 'erase_sweep', visitedPitches: [] });
|
||||||
return;
|
return;
|
||||||
@@ -5155,7 +5156,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
return { ...n, duration_beats: newDur };
|
return { ...n, duration_beats: newDur };
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
const snappedPitch = snapPitchToScale(pitch, selectedScale);
|
const snappedPitch = snapToScale ? snapPitchToScale(pitch, selectedScale) : pitch;
|
||||||
if (!visited.includes(snappedPitch)) {
|
if (!visited.includes(snappedPitch)) {
|
||||||
const newPitches = [...visited, snappedPitch];
|
const newPitches = [...visited, snappedPitch];
|
||||||
const totalSpan = Math.max(0.125, beat - draggedNote.initialBeat);
|
const totalSpan = Math.max(0.125, beat - draggedNote.initialBeat);
|
||||||
@@ -5461,6 +5462,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const [selectedScale, setSelectedScale] = React.useState(null);
|
const [selectedScale, setSelectedScale] = React.useState(null);
|
||||||
|
const [snapToScale, setSnapToScale] = React.useState(true);
|
||||||
const [scaleMenuPos, setScaleMenuPos] = React.useState(null);
|
const [scaleMenuPos, setScaleMenuPos] = React.useState(null);
|
||||||
const scaleMenuOriginRef = React.useRef(null);
|
const scaleMenuOriginRef = React.useRef(null);
|
||||||
const [aiPrompt, setAiPrompt] = React.useState('');
|
const [aiPrompt, setAiPrompt] = React.useState('');
|
||||||
@@ -5616,12 +5618,16 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNot
|
|||||||
"data-lucide": "music",
|
"data-lucide": "music",
|
||||||
className: "w-3.5 h-3.5"
|
className: "w-3.5 h-3.5"
|
||||||
}), st.label), /*#__PURE__*/React.createElement("div", {
|
}), st.label), /*#__PURE__*/React.createElement("div", {
|
||||||
className: "flex bg-zinc-800 p-0.5 rounded border border-zinc-700 text-xs"
|
className: "flex items-center gap-1 text-xs"
|
||||||
}, ['select', 'pen', 'eraser'].map(tool => /*#__PURE__*/React.createElement("button", {
|
}, /*#__PURE__*/React.createElement("span", {
|
||||||
key: tool,
|
className: "text-zinc-500 font-semibold"
|
||||||
onClick: () => setActiveRollTool(tool),
|
}, "Snap to Scale"), /*#__PURE__*/React.createElement("button", {
|
||||||
className: `px-2.5 py-1 rounded capitalize ${activeRollTool === tool ? 'bg-yellow-600 text-white font-bold' : 'text-zinc-400 hover:text-zinc-200'}`
|
onClick: () => setSnapToScale(!snapToScale),
|
||||||
}, tool))), /*#__PURE__*/React.createElement("div", {
|
className: `w-7 h-4 rounded-full transition-colors relative ${snapToScale ? 'bg-yellow-600' : 'bg-zinc-700'}`,
|
||||||
|
style: { padding: 0 }
|
||||||
|
}, /*#__PURE__*/React.createElement("div", {
|
||||||
|
className: `w-3 h-3 rounded-full bg-white absolute top-0.5 transition-transform ${snapToScale ? 'translate-x-3.5' : 'translate-x-0.5'}`
|
||||||
|
}))), /*#__PURE__*/React.createElement("div", {
|
||||||
className: "flex items-center gap-1 text-xs"
|
className: "flex items-center gap-1 text-xs"
|
||||||
}, /*#__PURE__*/React.createElement("span", {
|
}, /*#__PURE__*/React.createElement("span", {
|
||||||
className: "text-zinc-500 font-semibold"
|
className: "text-zinc-500 font-semibold"
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user