feat: ctrl+click dim note selects it and focuses its MIDI item

This commit is contained in:
2026-07-31 10:10:32 +07:00
parent be8430fbd9
commit ee39dda5b9
2 changed files with 29 additions and 5 deletions
+27 -3
View File
@@ -6280,10 +6280,11 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
var isSameTrackLayer = layer.isSameTrack;
layer.notes.forEach(function(note) {
var isFocusedNote = isSameTrackLayer && note.item_id === focusedItemId;
var isGhostSelected = selectedNoteIds.indexOf(note.id) !== -1;
if (isSameTrackLayer) {
ctx.globalAlpha = isFocusedNote ? 0.7 : 0.3;
ctx.fillStyle = isFocusedNote ? 'rgba(253, 224, 71, 0.7)' : 'rgba(251, 191, 36, 0.3)';
ctx.strokeStyle = isFocusedNote ? '#fde047' : 'rgba(245, 158, 11, 0.6)';
ctx.fillStyle = isGhostSelected ? 'rgba(96, 165, 250, 0.65)' : (isFocusedNote ? 'rgba(253, 224, 71, 0.7)' : 'rgba(251, 191, 36, 0.3)');
ctx.strokeStyle = isGhostSelected ? '#60a5fa' : (isFocusedNote ? '#fde047' : 'rgba(245, 158, 11, 0.6)');
} else {
ctx.globalAlpha = 0.25;
ctx.fillStyle = layer.track_color || '#888';
@@ -6297,7 +6298,7 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
var w = Math.max(2, (snapEnd - snapStart) * pixelsPerBeat);
var h = NoteHeight - 1;
ctx.fillRect(x, y, w, h);
if (isSameTrackLayer && isFocusedNote) ctx.strokeRect(x + 0.5, y + 0.5, w - 1, h - 1);
if (isSameTrackLayer && (isFocusedNote || isGhostSelected)) ctx.strokeRect(x + 0.5, y + 0.5, w - 1, h - 1);
});
ctx.restore();
});
@@ -6527,6 +6528,29 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
}
return;
} else {
// Ctrl+click on a dim (same-track) MIDI note select it and focus its MIDI item
var ctrlGhostHit = null;
for (var cgi = 0; cgi < ghostLayers.length; cgi++) {
var cgl = ghostLayers[cgi];
if (!cgl.isSameTrack || !cgl.notes) continue;
for (var cgn = 0; cgn < cgl.notes.length; cgn++) {
var cgnote = cgl.notes[cgn];
if (pitch === cgnote.pitch && beat >= cgnote.relative_start_beat && beat < cgnote.relative_start_beat + (cgnote.duration_beats || 1)) {
ctrlGhostHit = cgnote;
break;
}
}
if (ctrlGhostHit) break;
}
if (ctrlGhostHit) {
setFocusItemId(ctrlGhostHit.item_id || st.target_id);
if (selectedNoteIds.includes(ctrlGhostHit.id)) {
setSelectedNoteIds(prev => prev.filter(id => id !== ctrlGhostHit.id));
} else {
setSelectedNoteIds(prev => [...prev, ctrlGhostHit.id]);
}
return;
}
// Ctrl+click on empty space: start selection marquee
setSelectedNoteIds([]);
const snapStart = getSnapBeat(beat, snapValue);