+#[derive(Debug, Default)]
+pub struct Button {
+ pub time_pressed: Nanoseconds,
+ pub time_released: Nanoseconds,
+ pub is_pressed: bool,
+ pub was_pressed: bool,
+ pub toggle: bool,
+}
+
+impl Button {
+ fn update(&mut self, device: &Joystick, dt: Nanoseconds, btn: u8) {
+ self.was_pressed = self.is_pressed;
+ self.is_pressed = match device.button(btn as u32) {
+ Ok(true) => {
+ if !self.was_pressed {
+ self.time_pressed = 0;
+ self.toggle = !self.toggle;
+ }
+ self.time_pressed += dt;
+ true
+ }
+ Ok(false) => {
+ if self.was_pressed {
+ self.time_released = 0;
+ }
+ self.time_released += dt;
+ false
+ }
+ Err(_) => { panic!("invalid button {}", btn) }
+ }
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct Axis {
+ pub val: f32,
+}
+
+impl Axis {
+ #[allow(dead_code)]
+ fn update(&mut self, device: &Joystick, _dt: Nanoseconds, axis: u8) {
+ self.val = match device.axis(axis as u32) {
+ Ok(val) => val as f32 / 32768.0,
+ Err(_) => panic!("invalid axis {}", axis),
+ }
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct Stick {
+ pub x: f32,
+ pub y: f32,
+ pub a: Radians,
+ pub len: f32,
+}
+
+impl Stick {
+ fn update(&mut self, device: &Joystick, _dt: Nanoseconds, x_axis: u8, y_axis: u8) {
+ self.x = match device.axis(x_axis as u32) {
+ Ok(val) => val as f32 / 32768.0,
+ Err(_) => panic!("invalid x axis {}", x_axis),
+ };
+ self.y = match device.axis(y_axis as u32) {
+ Ok(val) => val as f32 / 32768.0,
+ Err(_) => panic!("invalid y axis {}", y_axis),
+ };
+ 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)
+ }