viewport_lib/interaction/input/binding.rs
1//! Input binding types: triggers, modifiers, and bindings that map actions to physical inputs.
2
3use super::action::Action;
4use super::mode::InputMode;
5
6/// Modifier key state — exact-match semantics (all must match).
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub struct Modifiers {
10 /// Alt/Option key held.
11 pub alt: bool,
12 /// Shift key held.
13 pub shift: bool,
14 /// Ctrl/Cmd key held.
15 pub ctrl: bool,
16}
17
18impl Modifiers {
19 /// No modifier keys held.
20 pub const NONE: Self = Self {
21 alt: false,
22 shift: false,
23 ctrl: false,
24 };
25 /// Only Alt held.
26 pub const ALT: Self = Self {
27 alt: true,
28 shift: false,
29 ctrl: false,
30 };
31 /// Only Shift held.
32 pub const SHIFT: Self = Self {
33 alt: false,
34 shift: true,
35 ctrl: false,
36 };
37 /// Only Ctrl held.
38 pub const CTRL: Self = Self {
39 alt: false,
40 shift: false,
41 ctrl: true,
42 };
43 /// Ctrl + Shift held.
44 pub const CTRL_SHIFT: Self = Self {
45 alt: false,
46 shift: true,
47 ctrl: true,
48 };
49}
50
51/// Keyboard key codes — subset covering keys used in the default bindings.
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
54pub enum KeyCode {
55 /// Letter key A.
56 A,
57 /// Letter key B.
58 B,
59 /// Letter key C.
60 C,
61 /// Letter key D.
62 D,
63 /// Letter key E.
64 E,
65 /// Letter key F.
66 F,
67 /// Letter key G.
68 G,
69 /// Letter key H.
70 H,
71 /// Letter key I.
72 I,
73 /// Letter key J.
74 J,
75 /// Letter key K.
76 K,
77 /// Letter key L.
78 L,
79 /// Letter key M.
80 M,
81 /// Letter key N.
82 N,
83 /// Letter key O.
84 O,
85 /// Letter key P.
86 P,
87 /// Letter key Q.
88 Q,
89 /// Letter key R.
90 R,
91 /// Letter key S.
92 S,
93 /// Letter key T.
94 T,
95 /// Letter key U.
96 U,
97 /// Letter key V.
98 V,
99 /// Letter key W.
100 W,
101 /// Letter key X.
102 X,
103 /// Letter key Y.
104 Y,
105 /// Letter key Z.
106 Z,
107 /// Tab key.
108 Tab,
109 /// Enter/Return key.
110 Enter,
111 /// Escape key.
112 Escape,
113 /// Backtick/grave-accent key.
114 Backtick,
115}
116
117/// Mouse buttons.
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
119#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
120pub enum MouseButton {
121 /// Primary (left) mouse button.
122 Left,
123 /// Secondary (right) mouse button.
124 Right,
125 /// Middle mouse button (scroll wheel click).
126 Middle,
127}
128
129/// What physical input fires the trigger.
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
131#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
132pub enum TriggerKind {
133 /// A keyboard key.
134 Key(KeyCode),
135 /// A mouse button.
136 MouseButton(MouseButton),
137 /// The scroll wheel (used with `OnScroll` activation).
138 Scroll,
139}
140
141/// How the trigger activates the action.
142#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
143#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
144pub enum ActivationMode {
145 /// Fires once on key/button press.
146 OnPress,
147 /// Active every frame while held.
148 WhileHeld,
149 /// Active while dragging (mouse button held + moved).
150 OnDrag,
151 /// Active when scroll wheel moves.
152 OnScroll,
153}
154
155/// A physical trigger that can activate an action.
156#[derive(Debug, Clone)]
157#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
158pub struct Trigger {
159 /// The physical input kind (key, mouse button, or scroll).
160 pub kind: TriggerKind,
161 /// Required modifier state (exact match unless `ignore_modifiers` is set).
162 pub modifiers: Modifiers,
163 /// How the trigger fires relative to the input event.
164 pub activation: ActivationMode,
165 /// When true, modifier keys are not checked. Useful for fly-mode WASD
166 /// so that holding Shift for speed boost doesn't break movement keys.
167 pub ignore_modifiers: bool,
168}
169
170/// Maps an action to a physical trigger, optionally restricted to specific modes.
171#[derive(Debug, Clone)]
172#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
173pub struct Binding {
174 /// The semantic action this binding fires.
175 pub action: Action,
176 /// The physical trigger that fires the action.
177 pub trigger: Trigger,
178 /// Which input modes this binding is active in. Empty = all modes.
179 pub active_modes: Vec<InputMode>,
180}
181
182impl Binding {
183 /// Convenience: create a binding active in all modes.
184 pub fn global(action: Action, trigger: Trigger) -> Self {
185 Self {
186 action,
187 trigger,
188 active_modes: Vec::new(),
189 }
190 }
191
192 /// Convenience: create a binding active only in the given modes.
193 pub fn in_modes(action: Action, trigger: Trigger, modes: &[InputMode]) -> Self {
194 Self {
195 action,
196 trigger,
197 active_modes: modes.to_vec(),
198 }
199 }
200}