+#[derive(Debug, Default)]
+pub struct Button {
+ id: u8,
+ pub time_pressed: Duration,
+ pub time_released: Duration,
+ pub is_pressed: bool,
+ pub was_pressed: bool,
+ pub toggle: bool,
+}
+
+impl Button {
+ fn update(&mut self, device: &Joystick, dt: Duration) {
+ self.was_pressed = self.is_pressed;
+ self.is_pressed = match device.button(self.id as u32) {
+ Ok(true) => {
+ if !self.was_pressed {
+ self.time_pressed = 0.seconds();
+ self.toggle = !self.toggle;
+ }
+ self.time_pressed += dt;
+ true
+ }
+ Ok(false) => {
+ if self.was_pressed {
+ self.time_released = 0.seconds();
+ }
+ self.time_released += dt;
+ false
+ }
+ Err(_) => { panic!("invalid button {}", self.id) }
+ }
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct Axis {
+ id: u8,
+ pub val: f32,
+}
+
+impl Axis {
+ #[allow(dead_code)]
+ fn update(&mut self, device: &Joystick, _dt: Duration) {
+ self.val = match device.axis(self.id as u32) {
+ Ok(val) => val as f32 / 32768.0,
+ Err(_) => panic!("invalid axis {}", self.id),
+ }
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct Stick {
+ idx: u8,
+ idy: u8,
+ pub x: f32,
+ pub y: f32,
+ pub a: Radians,
+ pub len: f32,
+}
+
+impl Stick {
+ fn update(&mut self, device: &Joystick, _dt: Duration) {
+ self.x = match device.axis(self.idx as u32) {
+ Ok(val) => val as f32 / 32768.0,
+ Err(_) => panic!("invalid x axis {}", self.idx),
+ };
+ self.y = match device.axis(self.idy as u32) {
+ Ok(val) => val as f32 / 32768.0,
+ Err(_) => panic!("invalid y axis {}", self.idy),
+ };
+ self.a = Radians(self.y.atan2(self.x) as f64);
+ self.len = {
+ let x = (self.x / self.y).abs().min(1.0);
+ let y = (self.y / self.x).abs().min(1.0);
+ (self.x.powi(2) + self.y.powi(2)).sqrt() / (x.powi(2) + y.powi(2)).sqrt()
+ }
+ }
+
+ #[inline(always)] #[allow(dead_code)] fn up(&self) -> bool { self.y > 0.99 }
+ #[inline(always)] #[allow(dead_code)] fn down(&self) -> bool { self.y < -0.99 }
+ #[inline(always)] #[allow(dead_code)] fn left(&self) -> bool { self.x < -0.99 }
+ #[inline(always)] #[allow(dead_code)] fn right(&self) -> bool { self.x > 0.99 }
+
+ pub fn to_point(&self) -> Point2D<f64> {
+ Point2D {
+ x: self.x as f64,
+ y: self.y as f64,
+ }
+ }
+
+ pub fn to_adjusted_point(&self) -> Point2D<f64> {
+ Point2D::from(self.a) * self.len as f64
+ }
+}
+
+impl From<&Stick> for Point2D<f64> {
+ fn from(item: &Stick) -> Self {
+ Self {
+ x: item.x as f64,
+ y: item.y as f64,
+ }
+ }
+}
+
+impl From<&Stick> for (f64, f64) {
+ fn from(item: &Stick) -> Self {
+ (item.x as f64, item.y as f64)
+ }
+}
+
+#[allow(dead_code)]
+struct Axes {
+ left_x: u8,
+ left_y: u8,
+ right_x: u8,
+ right_y: u8,
+ trigger_left: u8,
+ trigger_right: u8,
+}
+
+#[allow(dead_code)]
+struct Buttons {
+ a: u8,
+ b: u8,
+ x: u8,
+ y: u8,
+ select: u8,
+ start: u8,
+ left_stick: u8,
+ right_stick: u8,
+ left_shoulder: u8,
+ right_shoulder: u8,
+ left_trigger: u8,
+ right_trigger: u8,
+ d_pad_up: u8,
+ d_pad_down: u8,
+ d_pad_left: u8,
+ d_pad_right: u8,
+}
+
+struct Mapping {
+ axis: Axes,
+ btn: Buttons,