1use crate::{ButtonId, ModifierFilterMask, ModifierId};
2use std::collections::HashMap;
3
4#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
5pub enum InputMapping {
6 ScanCodeKey(winit::ScanCode),
7 VirtualKey(winit::VirtualKeyCode),
8 MouseAxis(u32),
9 MouseAxisWithDevice(winit::DeviceId, u32),
10 Gamepad(gilrs::ev::Axis),
11 GamepadWithDevice(gilrs::GamepadId, gilrs::ev::Axis),
12}
13
14pub struct Mapping {
15 axis_mapping: HashMap<InputMapping, (ButtonId, ModifierFilterMask, f32)>,
16 modifier_mapping: HashMap<InputMapping, ModifierId>,
17}
18
19impl Mapping {
20 pub fn new() -> Mapping {
21 Mapping {
22 axis_mapping: HashMap::new(),
23 modifier_mapping: HashMap::new(),
24 }
25 }
26
27 pub fn add_modifier_mapping(&mut self, input_event: InputMapping, modifier_id: ModifierId) {
28 if self.modifier_mapping.values().any(|m| *m == modifier_id) {
29 log::warn!("Multiple mapping for {:?}", modifier_id);
30 }
31 self.modifier_mapping.insert(input_event, modifier_id);
32 }
33
34 pub fn add_button_mapping(
35 &mut self,
36 input_event: InputMapping,
37 input_modifiers: Option<ModifierFilterMask>,
38 button_id: ButtonId,
39 sensitivity: f32,
40 ) {
41 if self.axis_mapping.values().any(|b| b.0 == button_id) {
42 log::warn!("Multiple mapping for {:?}", button_id);
43 }
44
45 let mask = input_modifiers.unwrap_or_default();
46 self.axis_mapping.insert(input_event, (button_id, mask, sensitivity));
47 }
48
49 pub fn map_winit_axis_to_modifier(&self, device_id: winit::DeviceId, axis: u32) -> Option<ModifierId> {
50 let mapping = &self.modifier_mapping;
51
52 if let Some(res) = mapping.get(&InputMapping::MouseAxisWithDevice(device_id.to_owned(), axis)) {
53 return Some(res.to_owned());
54 }
55
56 if let Some(res) = mapping.get(&InputMapping::MouseAxis(axis)) {
57 return Some(res.to_owned());
58 }
59
60 None
61 }
62
63 pub fn map_winit_key_to_modifier(&self, key_input: &winit::KeyboardInput) -> Option<ModifierId> {
64 let mapping = &self.modifier_mapping;
65
66 if let Some(res) = mapping.get(&InputMapping::ScanCodeKey(key_input.scancode)) {
67 return Some(res.to_owned());
68 }
69
70 if let Some(vk) = key_input.virtual_keycode {
71 if let Some(res) = mapping.get(&InputMapping::VirtualKey(vk)) {
72 return Some(res.to_owned());
73 }
74 }
75
76 None
77 }
78
79 pub fn map_winit_axis_to_button(&self, device_id: winit::DeviceId, axis: u32) -> Option<(ButtonId, ModifierFilterMask, f32)> {
80 let mapping = &self.axis_mapping;
81
82 if let Some(res) = mapping.get(&InputMapping::MouseAxisWithDevice(device_id.to_owned(), axis)) {
83 return Some(res.to_owned());
84 }
85
86 if let Some(res) = mapping.get(&InputMapping::MouseAxis(axis)) {
87 return Some(res.to_owned());
88 }
89
90 None
91 }
92
93 pub fn map_winit_key_to_button(&self, key_input: &winit::KeyboardInput) -> Option<(ButtonId, ModifierFilterMask, f32)> {
94 let mapping = &self.axis_mapping;
95
96 if let Some(res) = mapping.get(&InputMapping::ScanCodeKey(key_input.scancode)) {
97 return Some(res.to_owned());
98 }
99
100 if let Some(vk) = key_input.virtual_keycode {
101 if let Some(res) = mapping.get(&InputMapping::VirtualKey(vk)) {
102 return Some(res.to_owned());
103 }
104 }
105
106 None
107 }
108
109 pub fn map_gil_axis_to_modifier(&self, device_id: gilrs::GamepadId, axis: gilrs::ev::Axis) -> Option<ModifierId> {
110 let mapping = &self.modifier_mapping;
111
112 if let Some(res) = mapping.get(&InputMapping::GamepadWithDevice(device_id.to_owned(), axis.to_owned())) {
113 return Some(res.to_owned());
114 }
115
116 if let Some(res) = mapping.get(&InputMapping::Gamepad(axis.to_owned())) {
117 return Some(res.to_owned());
118 }
119
120 None
121 }
122
123 pub fn map_gil_axis_to_button(
124 &self,
125 device_id: gilrs::GamepadId,
126 axis: gilrs::ev::Axis,
127 ) -> Option<(ButtonId, ModifierFilterMask, f32)> {
128 let mapping = &self.axis_mapping;
129
130 if let Some(res) = mapping.get(&InputMapping::GamepadWithDevice(device_id.to_owned(), axis.to_owned())) {
131 return Some(res.to_owned());
132 }
133
134 if let Some(res) = mapping.get(&InputMapping::Gamepad(axis.to_owned())) {
135 return Some(res.to_owned());
136 }
137
138 None
139 }
140}