Editor Shortcuts

#include <safi/editor/editor_shortcuts.h>

A small system that listens for the handful of keyboard shortcuts every editor build wants:

KeyAction
F1Toggle Edit ↔ Play. Writes SafiEditorState.mode. Keyboard alternative to the toolbar.
F6safi_scene_snapshot_all(world) — stashes a cJSON blob in a scratchpad.
F7safi_scene_restore_snapshot(world, blob) — resets components to the last snapshot. Entity ids stay stable.
QPick the Select tool (pure click-to-pick, no gizmo handles).
WPick the Translate tool.
EPick the Rotate tool.
RPick the Scale tool.

The system runs on EcsOnUpdate so it works in both Edit and Play (flipping mode freezes gameplay — not keybinds). Input is skipped when a MicroUI widget has focus, so typing into an Inspector field never fires a shortcut.

RMB guard on tool shortcuts

Q / W / E / R only fire when the right mouse button is not held. The editor fly-cam uses RMB + WASD as its flight gesture, so while the user is flying the viewport those keys belong to the camera. Without the guard, pressing W to move the camera forward would also snap the tool to Translate on every press.

Scene-file shortcuts (F5 save / F9 load) are app-specific because cached entity handles in user code (like the gltf_viewer demo's g_demo struct) need refreshing after a load. Those stay in user code; the engine provides safi_scene_save / safi_scene_load / safi_scene_find_entity_by_name for the plumbing.

API

void safi_editor_shortcuts_install(ecs_world_t *world);

Installed automatically by safi_app_init when enable_debug_ui is set. Idempotent.

Relationship to the toolbar

F1 / Q / W / E / R each have a button equivalent in the editor toolbar. Both writers converge on the same SafiEditorState singleton, so the toolbar's highlight always agrees with the last keystroke. F6 / F7 stay keyboard-only for now — they're developer scratchpads that M6 (undo/redo) will supersede with a bounded ring buffer.

See also