1use super::keymap::{Keymap, KeymapCapture, KeymapDevice, KeymapEntry};
2use bevy_ecs::prelude::*;
3use repose_core::input::{Key, Modifiers};
4use repose_core::shortcuts::KeyChord;
5
6#[derive(Resource, Clone, Debug)]
7pub struct RemapSession<A> {
8 pub map: Keymap<A>,
9 pub capture: Option<KeymapCapture<A>>,
10}
11
12impl<A: Clone + Eq + std::hash::Hash> Default for RemapSession<A> {
13 fn default() -> Self {
14 Self {
15 map: Keymap::new(),
16 capture: None,
17 }
18 }
19}
20
21impl<A: Clone + Eq + std::hash::Hash> RemapSession<A> {
22 pub fn armed(&self) -> bool {
23 self.capture.is_some()
24 }
25
26 pub fn begin(&mut self, action: A, device: KeymapDevice) {
27 self.capture = Some(self.map.begin_capture(action, device));
28 }
29
30 pub fn cancel(&mut self) {
31 self.capture = None;
32 }
33
34 pub fn resolve(&mut self, pressed: Option<KeymapEntry>) -> bool {
35 if let Some(capture) = self.capture.take() {
36 self.map.resolve_capture(&capture, pressed);
37 true
38 } else {
39 false
40 }
41 }
42
43 pub fn resolve_physical(&mut self, key: repose_core::input::PhysicalKey) -> bool {
44 self.resolve(Some(KeymapEntry::Physical(key)))
45 }
46
47 pub fn resolve_key(&mut self, key: &Key) -> bool {
48 let chord = match key {
49 Key::Space => KeyChord::new(Key::Space, Modifiers::default()),
50 Key::Tab => KeyChord::new(Key::Tab, Modifiers::default()),
51 Key::Enter => KeyChord::new(Key::Enter, Modifiers::default()),
52 Key::Escape => KeyChord::new(Key::Escape, Modifiers::default()),
53 Key::ShiftLeft => KeyChord::new(Key::ShiftLeft, Modifiers::default()),
54 Key::ShiftRight => KeyChord::new(Key::ShiftRight, Modifiers::default()),
55 Key::Character(c) => {
56 KeyChord::new(Key::Character(c.to_ascii_lowercase()), Modifiers::default())
57 }
58 _ => return false,
59 };
60 self.resolve(Some(KeymapEntry::Key(chord)))
61 }
62
63 pub fn resolve_mouse(&mut self, left: bool) -> bool {
64 let entry = if left {
65 KeymapEntry::Mouse(repose_core::input::PointerButton::Primary)
66 } else {
67 KeymapEntry::Mouse(repose_core::input::PointerButton::Secondary)
68 };
69 if self
70 .capture
71 .as_ref()
72 .is_some_and(|c| c.device == KeymapDevice::KeyboardMouse)
73 {
74 self.resolve(Some(entry))
75 } else {
76 false
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn resolve_clears_capture() {
87 let mut s: RemapSession<&str> = RemapSession::default();
88 s.begin("north", KeymapDevice::KeyboardMouse);
89 assert!(s.armed());
90 assert!(s.resolve_physical(repose_core::input::PhysicalKey::KeyZ));
91 assert!(!s.armed());
92 }
93}