Skip to main content

repame_input/
remap.rs

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}