fix: ruler range drag/move, default cursor, SonicSF smooth stopAll
This commit is contained in:
+36
-13
@@ -5852,21 +5852,13 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
|||||||
}), React.createElement("div", {
|
}), React.createElement("div", {
|
||||||
ref: rulerScrollRef,
|
ref: rulerScrollRef,
|
||||||
className: "flex-1 overflow-hidden",
|
className: "flex-1 overflow-hidden",
|
||||||
|
style: { cursor: 'default' },
|
||||||
onMouseDown: (e) => {
|
onMouseDown: (e) => {
|
||||||
const rect = e.currentTarget.getBoundingClientRect();
|
const rect = e.currentTarget.getBoundingClientRect();
|
||||||
const x = e.clientX - rect.left + e.currentTarget.scrollLeft;
|
const x = e.clientX - rect.left + e.currentTarget.scrollLeft;
|
||||||
const clickBeat = x / pixelsPerBeat;
|
const clickBeat = x / pixelsPerBeat;
|
||||||
const clickTime = clickBeat * beatSec;
|
const clickTime = clickBeat * beatSec;
|
||||||
if (clickTime >= 0) {
|
const clickInRange = loopStartBeat !== null && loopEndBeat !== null && clickBeat >= loopStartBeat && clickBeat <= loopEndBeat;
|
||||||
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime, isPlaying: false } : s));
|
|
||||||
if (isPlaying) {
|
|
||||||
onStop();
|
|
||||||
setTimeout(() => {
|
|
||||||
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s));
|
|
||||||
onPlayPause();
|
|
||||||
}, 40);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e.ctrlKey || e.metaKey) {
|
if (e.ctrlKey || e.metaKey) {
|
||||||
setLoopStartBeat(null);
|
setLoopStartBeat(null);
|
||||||
setLoopEndBeat(null);
|
setLoopEndBeat(null);
|
||||||
@@ -5883,9 +5875,40 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (clickTime >= 0) {
|
||||||
|
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime, isPlaying: false } : s));
|
||||||
|
if (isPlaying) {
|
||||||
|
onStop();
|
||||||
|
setTimeout(() => {
|
||||||
|
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, currentTime: clickTime } : s));
|
||||||
|
onPlayPause();
|
||||||
|
}, 40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (clickInRange) {
|
||||||
|
const rangeWidth = loopEndBeat - loopStartBeat;
|
||||||
|
const offset = clickBeat - loopStartBeat;
|
||||||
|
rulerDragRef.current = { mode: 'move', startX: e.clientX, offset, rangeWidth, startBeat: loopStartBeat };
|
||||||
|
const onMove = (ev) => {
|
||||||
|
const r = rulerScrollRef.current;
|
||||||
|
if (!r || !rulerDragRef.current || rulerDragRef.current.mode !== 'move') return;
|
||||||
|
const rRect = r.getBoundingClientRect();
|
||||||
|
const bx = ev.clientX - rRect.left + r.scrollLeft;
|
||||||
|
const rawBeat = Math.max(0, bx / pixelsPerBeat);
|
||||||
|
const centerBeat = getSnapBeat(rawBeat - rulerDragRef.current.offset, snapVal);
|
||||||
|
const halfRange = rulerDragRef.current.rangeWidth / 2;
|
||||||
|
const newStart = Math.max(0, centerBeat - halfRange);
|
||||||
|
setLoopStartBeat(newStart);
|
||||||
|
setLoopEndBeat(newStart + rulerDragRef.current.rangeWidth);
|
||||||
|
setSubTabs(prev => prev.map(s => s.id === st.id ? { ...s, selectionStart: newStart * beatSec, selectionEnd: (newStart + rulerDragRef.current.rangeWidth) * beatSec } : s));
|
||||||
|
};
|
||||||
|
const onUp = () => { rulerDragRef.current = null; document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); };
|
||||||
|
document.addEventListener('mousemove', onMove);
|
||||||
|
document.addEventListener('mouseup', onUp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const snappedStartBeat = getSnapBeat(clickBeat, snapVal);
|
const snappedStartBeat = getSnapBeat(clickBeat, snapVal);
|
||||||
const startData = { startX: e.clientX, startBeat: snappedStartBeat, scrollLeft: e.currentTarget.scrollLeft };
|
rulerDragRef.current = { startX: e.clientX, startBeat: snappedStartBeat, scrollLeft: e.currentTarget.scrollLeft };
|
||||||
rulerDragRef.current = startData;
|
|
||||||
const onMove = (ev) => {
|
const onMove = (ev) => {
|
||||||
const r = rulerScrollRef.current;
|
const r = rulerScrollRef.current;
|
||||||
if (!r || !rulerDragRef.current) return;
|
if (!r || !rulerDragRef.current) return;
|
||||||
@@ -5958,7 +5981,7 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
|
|||||||
document.addEventListener('mouseup', onUp);
|
document.addEventListener('mouseup', onUp);
|
||||||
}
|
}
|
||||||
}), React.createElement("div", {
|
}), React.createElement("div", {
|
||||||
style: { position: 'absolute', left: '4px', right: '4px', top: 0, bottom: 0, cursor: 'grab' },
|
style: { position: 'absolute', left: '4px', right: '4px', top: 0, bottom: 0, cursor: 'move' },
|
||||||
onMouseDown: (e) => {
|
onMouseDown: (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const startBeat = loopStartBeat;
|
const startBeat = loopStartBeat;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -153,7 +153,7 @@
|
|||||||
osc.stop(stopAt);
|
osc.stop(stopAt);
|
||||||
|
|
||||||
const oscId = `${note}_${Date.now()}_${Math.random()}`;
|
const oscId = `${note}_${Date.now()}_${Math.random()}`;
|
||||||
activeOscillators[oscId] = osc;
|
activeOscillators[oscId] = { osc, gain: noteGain };
|
||||||
|
|
||||||
// Clean up active oscillator reference after it stops
|
// Clean up active oscillator reference after it stops
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -164,8 +164,16 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
stopAll: function () {
|
stopAll: function () {
|
||||||
Object.values(activeOscillators).forEach(osc => {
|
const ctx = getCtx();
|
||||||
try { osc.stop(); } catch (e) { }
|
Object.values(activeOscillators).forEach(entry => {
|
||||||
|
try {
|
||||||
|
if (entry.gain) {
|
||||||
|
entry.gain.gain.cancelScheduledValues(ctx.currentTime);
|
||||||
|
entry.gain.gain.setValueAtTime(entry.gain.gain.value || 1, ctx.currentTime);
|
||||||
|
entry.gain.gain.linearRampToValueAtTime(0.001, ctx.currentTime + 0.008);
|
||||||
|
}
|
||||||
|
if (entry.osc) entry.osc.stop(ctx.currentTime + 0.01);
|
||||||
|
} catch (e) { }
|
||||||
});
|
});
|
||||||
Object.keys(activeOscillators).forEach(k => delete activeOscillators[k]);
|
Object.keys(activeOscillators).forEach(k => delete activeOscillators[k]);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user