summaryrefslogtreecommitdiff
path: root/src/types/controller.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/types/controller.rs')
-rw-r--r--src/types/controller.rs160
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
+ }
+}