feat: add scale highlighting to Piano Roll grid
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useMemo } from 'react';
|
||||
import type { MutableRefObject } from 'react';
|
||||
import { Playhead } from '../common';
|
||||
import SelectionBox from './SelectionBox';
|
||||
import { isModifierKeyPressed } from '../../util/osUtil';
|
||||
import { generatePianoGridBackground } from '../../util/scaleUtil';
|
||||
import type { KeySignature } from '../../core/KGProject';
|
||||
|
||||
interface PianoGridProps {
|
||||
gridRef: MutableRefObject<HTMLDivElement | null>;
|
||||
@@ -18,6 +20,8 @@ interface PianoGridProps {
|
||||
endY: number;
|
||||
};
|
||||
regionStartBeat?: number;
|
||||
selectedMode: string;
|
||||
keySignature: KeySignature;
|
||||
}
|
||||
|
||||
interface CursorPosition {
|
||||
@@ -35,11 +39,18 @@ const PianoGrid: React.FC<PianoGridProps> = ({
|
||||
onMouseDown,
|
||||
isBoxSelecting,
|
||||
selectionBox,
|
||||
regionStartBeat = 0
|
||||
regionStartBeat = 0,
|
||||
selectedMode,
|
||||
keySignature
|
||||
}) => {
|
||||
const [cursorPosition, setCursorPosition] = useState<CursorPosition | null>(null);
|
||||
const [isModifierPressed, setIsModifierPressed] = useState(false);
|
||||
|
||||
// Generate background with scale highlighting - only regenerate when mode or key changes
|
||||
const backgroundImage = useMemo(() => {
|
||||
return generatePianoGridBackground(selectedMode, keySignature);
|
||||
}, [selectedMode, keySignature]);
|
||||
|
||||
// Track modifier key state
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
@@ -116,9 +127,10 @@ const PianoGrid: React.FC<PianoGridProps> = ({
|
||||
|
||||
return (
|
||||
<div className="piano-grid-container">
|
||||
<div
|
||||
<div
|
||||
className={`piano-grid ${isModifierPressed ? 'pencil-cursor' : ''}`}
|
||||
ref={gridRef}
|
||||
style={{ backgroundImage }}
|
||||
onDoubleClick={onDoubleClick}
|
||||
onClick={onClick}
|
||||
onMouseDown={(e) => onMouseDown(e)}
|
||||
|
||||
@@ -27,7 +27,7 @@ const PianoRoll: React.FC<PianoRollProps> = ({
|
||||
initialPosition,
|
||||
initialSize
|
||||
}) => {
|
||||
const { maxBars, tracks, updateTrack, timeSignature, showChatBox, showInstrumentSelection } = useProjectStore();
|
||||
const { maxBars, tracks, updateTrack, timeSignature, showChatBox, showInstrumentSelection, keySignature } = useProjectStore();
|
||||
|
||||
// Tool state for piano roll
|
||||
const [activeTool, setActiveTool] = useState<'pointer' | 'pencil'>('pointer');
|
||||
@@ -792,6 +792,8 @@ const PianoRoll: React.FC<PianoRollProps> = ({
|
||||
tracks={tracks}
|
||||
onSetNoteUpdateTrigger={handleSetNoteUpdateTrigger}
|
||||
onSetDeleteNotesTrigger={handleSetDeleteNotesTrigger}
|
||||
selectedMode={selectedMode}
|
||||
keySignature={keySignature}
|
||||
/>
|
||||
|
||||
<div
|
||||
|
||||
@@ -10,6 +10,7 @@ import PianoGridHeader from './PianoGridHeader';
|
||||
import PianoGrid from './PianoGrid';
|
||||
import { useNoteOperations } from '../../hooks/useNoteOperations';
|
||||
import { useNoteSelection } from '../../hooks/useNoteSelection';
|
||||
import type { KeySignature } from '../../core/KGProject';
|
||||
|
||||
interface PianoRollContentProps {
|
||||
contentRef: React.MutableRefObject<HTMLDivElement | null>;
|
||||
@@ -21,6 +22,8 @@ interface PianoRollContentProps {
|
||||
tracks: KGTrack[];
|
||||
onSetNoteUpdateTrigger?: (setNoteFn: React.Dispatch<React.SetStateAction<number>>) => void;
|
||||
onSetDeleteNotesTrigger?: (deleteFn: () => boolean) => void;
|
||||
selectedMode: string;
|
||||
keySignature: KeySignature;
|
||||
}
|
||||
|
||||
const PianoRollContent: React.FC<PianoRollContentProps> = ({
|
||||
@@ -32,7 +35,9 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
|
||||
updateTrack,
|
||||
tracks,
|
||||
onSetNoteUpdateTrigger,
|
||||
onSetDeleteNotesTrigger
|
||||
onSetDeleteNotesTrigger,
|
||||
selectedMode,
|
||||
keySignature
|
||||
}) => {
|
||||
// Get KGCore instance
|
||||
const core = KGCore.instance();
|
||||
@@ -227,6 +232,8 @@ const PianoRollContent: React.FC<PianoRollContentProps> = ({
|
||||
isBoxSelecting={isBoxSelectingRef.current}
|
||||
selectionBox={selectionBoxRef.current}
|
||||
regionStartBeat={activeRegion?.getStartFromBeat() || 0}
|
||||
selectedMode={selectedMode}
|
||||
keySignature={keySignature}
|
||||
>
|
||||
{memoizedNotes}
|
||||
</PianoGrid>
|
||||
|
||||
@@ -33,7 +33,7 @@ const PianoRollToolbar: React.FC<PianoRollToolbarProps> = ({
|
||||
<div className="toolbar-left">
|
||||
{/* Left section with mode dropdown */}
|
||||
<KGDropdown
|
||||
options={KGPianoRollState.MODE_OPTIONS}
|
||||
options={KGPianoRollState.MODE_DATA.map(m => ({ label: m.name, value: m.id }))}
|
||||
value={selectedMode}
|
||||
onChange={(value) => onModeChange(value)}
|
||||
label="Mode"
|
||||
|
||||
Reference in New Issue
Block a user