Files
feuerwerk/src/editor/shortcuts.ts
T

71 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { RemoveAnimationKeysCommand, RemoveAnimationTracksCommand } from '../core/commands/animationCommands';
import { RemoveFrameCommand } from '../core/commands/frameCommands';
import { ui } from '../ui';
import { confirmDeleteAsset, createContainer, removeGraphSelection, removeObjects } from './actions';
import type { EditorState } from './state';
export interface ShortcutActions {
play(): void;
stop(): void;
togglePause(): void;
/** Copy and paste of timeline keys (#102); false when nothing to do there, so the key falls through. */
copyKeys(): boolean;
pasteKeys(): boolean;
}
/**
* Global keyboard shortcuts (see the wiki page "Keyboard"). Text fields keep their own key handling;
* these only run when no focused widget consumed the key. Returns the call that takes them away
* again – signing out tears the editor down while the page stays up (#177).
*/
export function installShortcuts(state: EditorState, actions: ShortcutActions): () => void {
return ui().focus.onGlobalKey((event) => {
const mod = event.ctrlKey || event.metaKey;
const key = event.key.toLowerCase();
if (event.key === 'Escape' && state.mode === 'play') {
actions.stop();
return true;
}
if (mod && key === 'z') {
if (event.shiftKey) state.redo();
else state.undo();
return true;
}
if (mod && key === 'y') {
state.redo();
return true;
}
if (mod && key === 'c') return actions.copyKeys();
if (mod && key === 'v') return actions.pasteKeys();
if (mod && key === 'g') {
const s = state.selection;
if (s?.kind === 'object') createContainer(state, s.holderId, s.objectIds);
return true;
}
if (event.key === 'Delete' || event.key === 'Backspace') {
const s = state.selection;
if (s?.kind === 'object') removeObjects(state, s.holderId, s.objectIds);
else if (s?.kind === 'node') removeGraphSelection(state, s.assetId, s.nodeIds, s.annotationIds);
else if (s?.kind === 'frame') state.execute(new RemoveFrameCommand(s.assetId, s.frameId));
else if (s?.kind === 'annotation') removeGraphSelection(state, s.assetId, [], s.annotationIds);
// The keys when some are picked, else the row itself – like a frame of a texture.
else if (s?.kind === 'track')
state.execute(
s.keys.length > 0
? new RemoveAnimationKeysCommand(s.assetId, s.keys)
: new RemoveAnimationTracksCommand(s.assetId, [s.trackId]),
);
else if (s?.kind === 'asset') confirmDeleteAsset(state, s.assetId);
return s !== null;
}
// Ctrl+Enter starts play and then holds/resumes it. A plain letter would be taken away from
// the game, which owns the keyboard while playing.
if (mod && event.key === 'Enter') {
if (state.mode === 'edit') actions.play();
else actions.togglePause();
return true;
}
return false;
});
}