small size update with tons of rendering modes, palettes and keybindings
This commit is contained in:
@ -9,7 +9,7 @@ import { WelcomePopup } from './WelcomePopup';
|
||||
import { ShaderCanvas } from './ShaderCanvas';
|
||||
import { PerformanceWarning } from './PerformanceWarning';
|
||||
import { uiState, showUI } from '../stores/ui';
|
||||
import { $appSettings } from '../stores/appSettings';
|
||||
import { $appSettings, updateAppSettings, cycleValueMode, cycleRenderMode, handleTapTempo } from '../stores/appSettings';
|
||||
import { $shader } from '../stores/shader';
|
||||
import { loadShaders } from '../stores/library';
|
||||
import { Storage } from '../Storage';
|
||||
@ -43,6 +43,82 @@ export function App() {
|
||||
);
|
||||
}, [settings.uiOpacity]);
|
||||
|
||||
// Keyboard controls for hue shift and value mode when editor not focused
|
||||
useEffect(() => {
|
||||
let lastKeyTime = 0;
|
||||
const DEBOUNCE_DELAY = 150; // ms between key presses
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
// Only activate if editor is not focused and no control/meta/alt keys are pressed
|
||||
const editorElement = document.getElementById('editor') as HTMLTextAreaElement;
|
||||
const isEditorFocused = editorElement && document.activeElement === editorElement;
|
||||
|
||||
if (isEditorFocused || e.ctrlKey || e.metaKey || e.altKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce rapid key repeats
|
||||
const now = Date.now();
|
||||
if (now - lastKeyTime < DEBOUNCE_DELAY) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
lastKeyTime = now;
|
||||
|
||||
switch (e.key) {
|
||||
case 'ArrowLeft':
|
||||
e.preventDefault();
|
||||
// Decrease hue shift by 10 degrees (wrapping at 0)
|
||||
const currentHue = settings.hueShift ?? 0;
|
||||
const newHueLeft = currentHue - 10;
|
||||
updateAppSettings({ hueShift: newHueLeft < 0 ? 360 + newHueLeft : newHueLeft });
|
||||
break;
|
||||
|
||||
case 'ArrowRight':
|
||||
e.preventDefault();
|
||||
// Increase hue shift by 10 degrees (wrapping at 360)
|
||||
const currentHueRight = settings.hueShift ?? 0;
|
||||
const newHueRight = (currentHueRight + 10) % 360;
|
||||
updateAppSettings({ hueShift: newHueRight });
|
||||
break;
|
||||
|
||||
case 'ArrowUp':
|
||||
e.preventDefault();
|
||||
if (e.shiftKey) {
|
||||
// Shift + Up: Cycle to previous render mode (color palette)
|
||||
cycleRenderMode('backward');
|
||||
} else {
|
||||
// Up: Cycle to previous value mode
|
||||
cycleValueMode('backward');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ArrowDown':
|
||||
e.preventDefault();
|
||||
if (e.shiftKey) {
|
||||
// Shift + Down: Cycle to next render mode (color palette)
|
||||
cycleRenderMode('forward');
|
||||
} else {
|
||||
// Down: Cycle to next value mode
|
||||
cycleValueMode('forward');
|
||||
}
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
e.preventDefault();
|
||||
// Spacebar: Tap tempo to control time speed
|
||||
handleTapTempo();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [settings.hueShift]);
|
||||
|
||||
// Save settings changes to localStorage
|
||||
useEffect(() => {
|
||||
Storage.saveSettings({
|
||||
@ -51,6 +127,8 @@ export function App() {
|
||||
renderMode: settings.renderMode,
|
||||
valueMode: settings.valueMode,
|
||||
uiOpacity: settings.uiOpacity,
|
||||
hueShift: settings.hueShift,
|
||||
timeSpeed: settings.timeSpeed,
|
||||
lastShaderCode: shader.code,
|
||||
});
|
||||
}, [settings, shader.code]);
|
||||
|
||||
Reference in New Issue
Block a user