diff options
Diffstat (limited to 'src/types/controller.rs')
-rw-r--r-- | src/types/controller.rs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/src/types/controller.rs b/src/types/controller.rs new file mode 100644 index 0000000..76b77e3 --- /dev/null +++ b/src/types/controller.rs @@ -0,0 +1,160 @@ +use crate::*; + +pub use gilrs::{Gilrs, GamepadId}; + + +pub struct OwnedGamepad { + tag: usize, + id: Option<GamepadId>, + gamepad: Gamepad, +} + +impl OwnedGamepad { + pub fn new(tag: usize) -> Self { + Self { tag, id: None, gamepad: Gamepad::new() } + } + + /// Returns Some if the ID owns this gamepad. + pub fn register(&mut self, new_id: GamepadId) -> Option<&mut Gamepad> { + if let Some(id) = self.id { + match id == new_id { + true => Some(&mut self.gamepad), + false => None, + } + } else { + self.id = Some(new_id); + info!("Registered gamepad {}", self.tag); + Some(&mut self.gamepad) + } + } + + pub fn state(&self) -> u8 { + self.gamepad.state + } + + pub fn reset(&mut self) { + self.gamepad.reset(); + } +} + + +pub struct Gamepad { + pub state: u8, + l_up: bool, + l_down: bool, + l_left: bool, + l_right: bool, + r_up: bool, + r_down: bool, + r_left: bool, + r_right: bool, + d_up: bool, + d_down: bool, + d_left: bool, + d_right: bool, + a: bool, + b: bool, + x: bool, + y: bool, +} + +impl Gamepad { + pub fn new() -> Self { + Self { + state: 0, + l_up: false, + l_down: false, + l_left: false, + l_right: false, + r_up: false, + r_down: false, + r_left: false, + r_right: false, + d_up: false, + d_down: false, + d_left: false, + d_right: false, + a: false, + b: false, + x: false, + y: false, + } + } + + pub fn reset(&mut self) { + self.state = 0; + self.l_up = false; + self.l_down = false; + self.l_left = false; + self.l_right = false; + self.r_up = false; + self.r_down = false; + self.r_left = false; + self.r_right = false; + self.d_up = false; + self.d_down = false; + self.d_left = false; + self.d_right = false; + self.a = false; + self.b = false; + self.x = false; + self.y = false; + } + + // Returns true if the state changed. + pub fn process_event(&mut self, event: &gilrs::Event) -> bool { + macro_rules! schmitt { + ($name_neg:ident, $name_pos:ident, $v:expr) => {{ + if self.$name_neg { if $v > -0.40 { self.$name_neg = false; } } + else { if $v < -0.50 { self.$name_neg = true; } } + if self.$name_pos { if $v < 0.40 { self.$name_pos = false; } } + else { if $v > 0.50 { self.$name_pos = true; } } + }}; + } + + match event.event { + gilrs::EventType::ButtonPressed(button, _) => match button { + gilrs::Button::South => self.a = true, + gilrs::Button::East => self.b = true, + gilrs::Button::West => self.x = true, + gilrs::Button::North => self.y = true, + gilrs::Button::DPadUp => self.d_up = true, + gilrs::Button::DPadDown => self.d_down = true, + gilrs::Button::DPadLeft => self.d_left = true, + gilrs::Button::DPadRight => self.d_right = true, + _ => (), + } + gilrs::EventType::ButtonReleased(button, _) => match button { + gilrs::Button::South => self.a = false, + gilrs::Button::East => self.b = false, + gilrs::Button::West => self.x = false, + gilrs::Button::North => self.y = false, + gilrs::Button::DPadUp => self.d_up = false, + gilrs::Button::DPadDown => self.d_down = false, + gilrs::Button::DPadLeft => self.d_left = false, + gilrs::Button::DPadRight => self.d_right = false, + _ => (), + } + gilrs::EventType::AxisChanged(axis, v, _) => match axis { + gilrs::Axis::LeftStickX => schmitt!(l_left, l_right, v), + gilrs::Axis::LeftStickY => schmitt!(l_down, l_up, v), + gilrs::Axis::RightStickX => schmitt!(r_left, r_right, v), + gilrs::Axis::RightStickY => schmitt!(r_down, r_up, v), + _ => (), + } + _ => (), + } + + let old_state = self.state; + self.state = 0; + if self.l_up | self.r_up | self.d_up { self.state |= 0x80; } + if self.l_down | self.r_down | self.d_down { self.state |= 0x40; } + if self.l_left | self.r_left | self.d_left { self.state |= 0x20; } + if self.l_right | self.r_right | self.d_right { self.state |= 0x10; } + if self.a { self.state |= 0x08; } + if self.b { self.state |= 0x04; } + if self.x { self.state |= 0x02; } + if self.y { self.state |= 0x01; } + old_state != self.state + } +} |