Support rebinding gamepad inputs
This commit is contained in:
+76
-14
@@ -19,6 +19,11 @@ pub struct GamepadInfo {
|
||||
pub bound_to: Option<SimId>,
|
||||
}
|
||||
|
||||
pub trait Mappings {
|
||||
fn mapping_names(&self) -> HashMap<VBKey, Vec<String>>;
|
||||
fn clear_mappings(&mut self, key: VBKey);
|
||||
}
|
||||
|
||||
pub struct GamepadMapping {
|
||||
buttons: HashMap<Code, VBKey>,
|
||||
axes: HashMap<Code, (VBKey, VBKey)>,
|
||||
@@ -54,6 +59,59 @@ impl GamepadMapping {
|
||||
|
||||
Self { buttons, axes }
|
||||
}
|
||||
|
||||
pub fn add_button_mapping(&mut self, key: VBKey, code: Code) {
|
||||
let entry = self.buttons.entry(code).or_insert(VBKey::empty());
|
||||
*entry = entry.union(key);
|
||||
}
|
||||
|
||||
pub fn add_axis_neg_mapping(&mut self, key: VBKey, code: Code) {
|
||||
let entry = self
|
||||
.axes
|
||||
.entry(code)
|
||||
.or_insert((VBKey::empty(), VBKey::empty()));
|
||||
entry.0 = entry.0.union(key);
|
||||
}
|
||||
|
||||
pub fn add_axis_pos_mapping(&mut self, key: VBKey, code: Code) {
|
||||
let entry = self
|
||||
.axes
|
||||
.entry(code)
|
||||
.or_insert((VBKey::empty(), VBKey::empty()));
|
||||
entry.1 = entry.1.union(key);
|
||||
}
|
||||
}
|
||||
|
||||
impl Mappings for GamepadMapping {
|
||||
fn mapping_names(&self) -> HashMap<VBKey, Vec<String>> {
|
||||
let mut results: HashMap<VBKey, Vec<String>> = HashMap::new();
|
||||
for (axis, (left_keys, right_keys)) in &self.axes {
|
||||
for key in left_keys.iter() {
|
||||
results.entry(key).or_default().push(format!("-{axis}"));
|
||||
}
|
||||
for key in right_keys.iter() {
|
||||
results.entry(key).or_default().push(format!("+{axis}"));
|
||||
}
|
||||
}
|
||||
for (button, keys) in &self.buttons {
|
||||
for key in keys.iter() {
|
||||
results.entry(key).or_default().push(format!("{button}"));
|
||||
}
|
||||
}
|
||||
results
|
||||
}
|
||||
|
||||
fn clear_mappings(&mut self, key: VBKey) {
|
||||
self.axes.retain(|_, (left, right)| {
|
||||
*left = left.difference(key);
|
||||
*right = right.difference(key);
|
||||
!(left.is_empty() && right.is_empty())
|
||||
});
|
||||
self.buttons.retain(|_, keys| {
|
||||
*keys = keys.difference(key);
|
||||
!keys.is_empty()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -81,15 +139,10 @@ impl InputMapping {
|
||||
let entry = self.keys.entry(keyboard_key).or_insert(VBKey::empty());
|
||||
*entry = entry.union(key);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_keyboard_mappings(&mut self, key: VBKey) {
|
||||
self.keys.retain(|_, keys| {
|
||||
*keys = keys.difference(key);
|
||||
*keys != VBKey::empty()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn keyboard_mapping_names(&self) -> HashMap<VBKey, String> {
|
||||
impl Mappings for InputMapping {
|
||||
fn mapping_names(&self) -> HashMap<VBKey, Vec<String>> {
|
||||
let mut results: HashMap<VBKey, Vec<String>> = HashMap::new();
|
||||
for (keyboard_key, keys) in &self.keys {
|
||||
let name = match keyboard_key {
|
||||
@@ -101,12 +154,13 @@ impl InputMapping {
|
||||
}
|
||||
}
|
||||
results
|
||||
.into_iter()
|
||||
.map(|(k, mut v)| {
|
||||
v.sort();
|
||||
(k, v.join(", "))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn clear_mappings(&mut self, key: VBKey) {
|
||||
self.keys.retain(|_, keys| {
|
||||
*keys = keys.difference(key);
|
||||
!keys.is_empty()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +208,14 @@ impl MappingProvider {
|
||||
self.sim_mappings.get(&sim_id).unwrap()
|
||||
}
|
||||
|
||||
pub fn for_gamepad(&self, gamepad_id: GamepadId) -> Option<Arc<RwLock<GamepadMapping>>> {
|
||||
let lock = self.gamepad_info.read().unwrap();
|
||||
let device_id = lock.get(&gamepad_id)?.device_id;
|
||||
drop(lock);
|
||||
let lock = self.device_mappings.read().unwrap();
|
||||
lock.get(&device_id).cloned()
|
||||
}
|
||||
|
||||
pub fn handle_gamepad_connect(&self, gamepad: &Gamepad) {
|
||||
let device_id = DeviceId(
|
||||
gamepad.vendor_id().unwrap_or_default(),
|
||||
|
||||
Reference in New Issue
Block a user