fix: dynamic sizing for sequencer and piano roll modules
Module width now adapts to step/bar count so extra steps are never hidden. Sequencer width scales with numSteps, piano roll width scales with bar count using a fixed BEAT_PX density. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,20 @@ import KeyboardWidget from './KeyboardWidget.jsx';
|
|||||||
import SequencerWidget from './SequencerWidget.jsx';
|
import SequencerWidget from './SequencerWidget.jsx';
|
||||||
import PianoRollWidget from './PianoRollWidget.jsx';
|
import PianoRollWidget from './PianoRollWidget.jsx';
|
||||||
|
|
||||||
|
// Dynamic module widths for sequencer/pianoroll based on step/bar count
|
||||||
|
function getModuleWidth(mod, type) {
|
||||||
|
if (type === 'sequencer') {
|
||||||
|
const numSteps = parseInt(mod?.params?.steps || '16');
|
||||||
|
return Math.max(200, numSteps * 18 + 20); // CELL_W=18 + padding
|
||||||
|
}
|
||||||
|
if (type === 'pianoroll') {
|
||||||
|
const bars = parseInt(mod?.params?.bars || '4');
|
||||||
|
const totalBeats = bars * 4;
|
||||||
|
return 24 + totalBeats * 30 + 20; // KEY_W + beats*BEAT_PX + padding
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
// Map input port names → the param name they modulate (for visual feedback)
|
// Map input port names → the param name they modulate (for visual feedback)
|
||||||
const PORT_TO_PARAM = {
|
const PORT_TO_PARAM = {
|
||||||
filter: { cutoff: 'frequency' },
|
filter: { cutoff: 'frequency' },
|
||||||
@@ -150,7 +164,7 @@ export default function ModuleNode({ mod, zoom, onStartConnect, onPortPosition }
|
|||||||
style={{
|
style={{
|
||||||
left: mod.x * zoom, top: mod.y * zoom,
|
left: mod.x * zoom, top: mod.y * zoom,
|
||||||
transform: `scale(${zoom})`, transformOrigin: 'top left',
|
transform: `scale(${zoom})`, transformOrigin: 'top left',
|
||||||
...(mod.type === 'pianoroll' ? { width: 520 } : mod.type === 'sequencer' ? { width: 310 } : {}),
|
...(mod.type === 'pianoroll' ? { width: getModuleWidth(mod, 'pianoroll') } : mod.type === 'sequencer' ? { width: getModuleWidth(mod, 'sequencer') } : {}),
|
||||||
}}
|
}}
|
||||||
data-module-id={mod.id}
|
data-module-id={mod.id}
|
||||||
onPointerDown={(e) => {
|
onPointerDown={(e) => {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ const MARIO_MELODY = [
|
|||||||
{ note: 71, start: 70*s, duration: 2*s }, // B4
|
{ note: 71, start: 70*s, duration: 2*s }, // B4
|
||||||
];
|
];
|
||||||
|
|
||||||
const ROLL_W = 500;
|
const BEAT_PX = 30; // pixels per beat — constant density regardless of bar count
|
||||||
const ROLL_H = 200;
|
const ROLL_H = 200;
|
||||||
const KEY_W = 24;
|
const KEY_W = 24;
|
||||||
const MIN_NOTE = 48; // C3
|
const MIN_NOTE = 48; // C3
|
||||||
@@ -110,7 +110,8 @@ export default function PianoRollWidget({ moduleId }) {
|
|||||||
const notesRef = useRef(notes);
|
const notesRef = useRef(notes);
|
||||||
notesRef.current = notes;
|
notesRef.current = notes;
|
||||||
|
|
||||||
const beatW = (ROLL_W - KEY_W) / totalBeats;
|
const rollW = KEY_W + totalBeats * BEAT_PX;
|
||||||
|
const beatW = BEAT_PX;
|
||||||
|
|
||||||
// Draw the piano roll
|
// Draw the piano roll
|
||||||
const draw = useCallback(() => {
|
const draw = useCallback(() => {
|
||||||
@@ -220,7 +221,7 @@ export default function PianoRollWidget({ moduleId }) {
|
|||||||
ctx.fillStyle = 'rgba(0,229,255,0.3)';
|
ctx.fillStyle = 'rgba(0,229,255,0.3)';
|
||||||
ctx.fillRect(x, row * ROW_H, Math.max(nw, 2), ROW_H);
|
ctx.fillRect(x, row * ROW_H, Math.max(nw, 2), ROW_H);
|
||||||
}
|
}
|
||||||
}, [totalBeats, beatW, playPos]);
|
}, [totalBeats, beatW, playPos, rollW]);
|
||||||
|
|
||||||
// Animation loop
|
// Animation loop
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -415,7 +416,7 @@ export default function PianoRollWidget({ moduleId }) {
|
|||||||
}, [mod]);
|
}, [mod]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: ROLL_W }}>
|
<div style={{ width: rollW }}>
|
||||||
{/* Mini toolbar */}
|
{/* Mini toolbar */}
|
||||||
<div style={{ display: 'flex', gap: 4, marginBottom: 3 }}>
|
<div style={{ display: 'flex', gap: 4, marginBottom: 3 }}>
|
||||||
<button
|
<button
|
||||||
@@ -453,9 +454,9 @@ export default function PianoRollWidget({ moduleId }) {
|
|||||||
</div>
|
</div>
|
||||||
<canvas
|
<canvas
|
||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
width={ROLL_W}
|
width={rollW}
|
||||||
height={ROLL_H}
|
height={ROLL_H}
|
||||||
style={{ width: ROLL_W, height: ROLL_H, borderRadius: 4, cursor: tool === 'draw' ? 'crosshair' : 'pointer' }}
|
style={{ width: rollW, height: ROLL_H, borderRadius: 4, cursor: tool === 'draw' ? 'crosshair' : 'pointer' }}
|
||||||
onPointerDown={handleMouseDown}
|
onPointerDown={handleMouseDown}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user