Files
Oxide/editor/src/bindings.rs
T
Homer Simpson 9eead719b0 Import Oxide engine (Stages 0–10) under MIT license
Full project snapshot migrated to new Gitea remote without history:
engine, editor, physics, script, examples, tests, docs, and assets.
Relicensed from GPLv3 to MIT and updated repo URLs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 20:41:02 +02:00

119 lines
5.0 KiB
Rust
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.
//! Default editor input bindings + the action-name constants the bindings
//! UI and any debug overlay address.
//!
//! Living in the editor library (not the binary) so the Stage-7
//! [`InputBindings`](crate::shell::Shell) preferences page and any future
//! editor module can re-register or remap the same actions without
//! depending on the binary's private module.
use oxide_engine::input::{ActionMap, AxisBinding, Binding};
use oxide_engine::winit::keyboard::KeyCode;
/// The settings-section name under which the editor's
/// [`ActionOverrides`](oxide_engine::input::ActionOverrides) are persisted.
///
/// The shell registers this section automatically in
/// [`EditorState::new`](crate::state::EditorState::new); UI code that wants
/// to refresh the section after a binding change addresses it by this name.
pub const SETTINGS_SECTION: &str = "input.bindings";
/// Stable action names addressed throughout the editor — the bindings
/// preferences page, the camera input poll in the runner, and any future
/// debug overlay all reference these strings.
pub mod action {
/// Button: toggle between orbit and flythrough viewport cameras.
pub const TOGGLE_FLYTHROUGH: &str = "editor.camera.toggle_flythrough";
/// Button (held): accelerate flythrough translation while engaged.
pub const SPRINT: &str = "editor.camera.sprint";
/// 1D axis: strafe right (+) / strafe left () in flythrough mode.
pub const MOVE_RIGHT: &str = "editor.camera.move_right";
/// 1D axis: forward (+) / back () in flythrough mode.
pub const MOVE_FORWARD: &str = "editor.camera.move_forward";
/// 1D axis: ascend (+) / descend () in flythrough mode.
pub const MOVE_UP: &str = "editor.camera.move_up";
/// Button: switch the transform gizmo to Translate mode (orbit camera only).
pub const GIZMO_TRANSLATE: &str = "editor.gizmo.translate";
/// Button: switch the transform gizmo to Rotate mode (orbit camera only).
pub const GIZMO_ROTATE: &str = "editor.gizmo.rotate";
/// Button: switch the transform gizmo to Scale mode (orbit camera only).
pub const GIZMO_SCALE: &str = "editor.gizmo.scale";
}
/// Registers the editor's default action set on `actions`. Defaults follow
/// the DCC-tools convention (WASD + QE, Shift sprint, F toggles the
/// flythrough camera) so users coming from Blender / Maya / Unity feel at
/// home.
///
/// Idempotent on the action names — re-registering preserves any user-
/// remapped current bindings while refreshing the defaults that the
/// "Restore defaults" button reverts to.
pub fn register_defaults(actions: &mut ActionMap) {
actions
.register(action::TOGGLE_FLYTHROUGH, [Binding::Key(KeyCode::KeyF)])
.register(
action::SPRINT,
[
Binding::Key(KeyCode::ShiftLeft),
Binding::Key(KeyCode::ShiftRight),
],
)
.register_axis(
action::MOVE_RIGHT,
AxisBinding::new([Binding::Key(KeyCode::KeyD)], [Binding::Key(KeyCode::KeyA)]),
)
.register_axis(
action::MOVE_FORWARD,
AxisBinding::new([Binding::Key(KeyCode::KeyW)], [Binding::Key(KeyCode::KeyS)]),
)
.register_axis(
action::MOVE_UP,
AxisBinding::new([Binding::Key(KeyCode::KeyE)], [Binding::Key(KeyCode::KeyQ)]),
)
// Gizmo tool hotkeys (W/E/R). These share physical keys with
// flythrough movement, so the host gates them on the camera being
// in orbit mode — in flythrough W/E move the camera, in orbit
// they switch the gizmo tool.
.register(action::GIZMO_TRANSLATE, [Binding::Key(KeyCode::KeyW)])
.register(action::GIZMO_ROTATE, [Binding::Key(KeyCode::KeyE)])
.register(action::GIZMO_SCALE, [Binding::Key(KeyCode::KeyR)]);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_register_every_advertised_action() {
let mut actions = ActionMap::new();
register_defaults(&mut actions);
assert!(actions.has(action::TOGGLE_FLYTHROUGH));
assert!(actions.has(action::SPRINT));
assert!(actions.has_axis(action::MOVE_RIGHT));
assert!(actions.has_axis(action::MOVE_FORWARD));
assert!(actions.has_axis(action::MOVE_UP));
}
#[test]
fn defaults_are_idempotent_and_preserve_remaps() {
let mut actions = ActionMap::new();
register_defaults(&mut actions);
// User remaps Toggle to Tab.
actions.set_bindings(action::TOGGLE_FLYTHROUGH, vec![Binding::Key(KeyCode::Tab)]);
// Re-running register_defaults must not stomp the user's remap.
register_defaults(&mut actions);
assert_eq!(
actions.bindings(action::TOGGLE_FLYTHROUGH),
&[Binding::Key(KeyCode::Tab)]
);
// But the defaults — what "Restore defaults" reverts to — are still F.
assert_eq!(
actions.defaults(action::TOGGLE_FLYTHROUGH),
&[Binding::Key(KeyCode::KeyF)]
);
}
}