one_fpga/inputs/
gamepad.rs

1use serde::{Deserialize, Serialize};
2use static_assertions::const_assert;
3use strum::{Display, EnumCount, EnumIter, EnumString, FromRepr, IntoEnumIterator};
4
5/// Gamepad buttons.
6#[derive(
7    Copy,
8    Clone,
9    Eq,
10    PartialEq,
11    Hash,
12    Debug,
13    Serialize,
14    Deserialize,
15    EnumIter,
16    EnumString,
17    Display,
18    EnumCount,
19    FromRepr,
20)]
21#[repr(u8)]
22pub enum Button {
23    A = sdl3::gamepad::Button::A as u8,
24    B = sdl3::gamepad::Button::B as u8,
25    X = sdl3::gamepad::Button::X as u8,
26    Y = sdl3::gamepad::Button::Y as u8,
27    Back = sdl3::gamepad::Button::Back as u8,
28    Guide = sdl3::gamepad::Button::Guide as u8,
29    Start = sdl3::gamepad::Button::Start as u8,
30    LeftStick = sdl3::gamepad::Button::LeftStick as u8,
31    RightStick = sdl3::gamepad::Button::RightStick as u8,
32    LeftShoulder = sdl3::gamepad::Button::LeftShoulder as u8,
33    RightShoulder = sdl3::gamepad::Button::RightShoulder as u8,
34    DPadUp = sdl3::gamepad::Button::DPadUp as u8,
35    DPadDown = sdl3::gamepad::Button::DPadDown as u8,
36    DPadLeft = sdl3::gamepad::Button::DPadLeft as u8,
37    DPadRight = sdl3::gamepad::Button::DPadRight as u8,
38    Misc1 = sdl3::gamepad::Button::Misc1 as u8,
39    Paddle1 = sdl3::gamepad::Button::Paddle1 as u8,
40    Paddle2 = sdl3::gamepad::Button::Paddle2 as u8,
41    Paddle3 = sdl3::gamepad::Button::Paddle3 as u8,
42    Paddle4 = sdl3::gamepad::Button::Paddle4 as u8,
43    Touchpad = sdl3::gamepad::Button::Touchpad as u8,
44}
45
46impl Button {
47    pub fn as_sdl(&self) -> sdl3::gamepad::Button {
48        sdl3::gamepad::Button::from(*self)
49    }
50
51    pub fn as_repr(&self) -> u8 {
52        *self as u8
53    }
54}
55
56impl From<sdl3::gamepad::Button> for Button {
57    fn from(button: sdl3::gamepad::Button) -> Self {
58        match button {
59            sdl3::gamepad::Button::A => Button::A,
60            sdl3::gamepad::Button::B => Button::B,
61            sdl3::gamepad::Button::X => Button::X,
62            sdl3::gamepad::Button::Y => Button::Y,
63            sdl3::gamepad::Button::Back => Button::Back,
64            sdl3::gamepad::Button::Guide => Button::Guide,
65            sdl3::gamepad::Button::Start => Button::Start,
66            sdl3::gamepad::Button::LeftStick => Button::LeftStick,
67            sdl3::gamepad::Button::RightStick => Button::RightStick,
68            sdl3::gamepad::Button::LeftShoulder => Button::LeftShoulder,
69            sdl3::gamepad::Button::RightShoulder => Button::RightShoulder,
70            sdl3::gamepad::Button::DPadUp => Button::DPadUp,
71            sdl3::gamepad::Button::DPadDown => Button::DPadDown,
72            sdl3::gamepad::Button::DPadLeft => Button::DPadLeft,
73            sdl3::gamepad::Button::DPadRight => Button::DPadRight,
74            sdl3::gamepad::Button::Misc1 => Button::Misc1,
75            sdl3::gamepad::Button::Paddle1 => Button::Paddle1,
76            sdl3::gamepad::Button::Paddle2 => Button::Paddle2,
77            sdl3::gamepad::Button::Paddle3 => Button::Paddle3,
78            sdl3::gamepad::Button::Paddle4 => Button::Paddle4,
79            sdl3::gamepad::Button::Touchpad => Button::Touchpad,
80        }
81    }
82}
83
84impl From<Button> for sdl3::gamepad::Button {
85    fn from(button: Button) -> Self {
86        button.as_sdl()
87    }
88}
89
90/// A set of pressed buttons.
91#[derive(Copy, Clone, Eq, PartialEq, Hash, Default)]
92pub struct ButtonSet(u32);
93
94// Make sure we don't have more than 32 buttons (or u32 might overflow).
95const_assert!(Button::COUNT <= 32);
96
97impl ButtonSet {
98    pub fn new() -> Self {
99        Self(0)
100    }
101
102    pub fn contains(&self, button: Button) -> bool {
103        self.0 & (1 << button.as_repr()) != 0
104    }
105
106    pub fn insert(&mut self, button: Button) {
107        self.0 |= 1 << button.as_repr();
108    }
109
110    pub fn remove(&mut self, button: Button) {
111        self.0 &= !(1 << button.as_repr());
112    }
113}
114
115impl std::fmt::Debug for ButtonSet {
116    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117        let mut f = f.debug_tuple("ButtonSet");
118
119        for b in Button::iter() {
120            if self.contains(b) {
121                f.field(&b.to_string());
122            }
123        }
124
125        f.finish()
126    }
127}
128
129/// Gamepad axes. We reuse the SDL3 type for simplicity, as it is well maintained and complete.
130#[derive(Copy, Clone, Debug, PartialEq)]
131#[repr(transparent)]
132pub struct Axis(sdl3::gamepad::Axis);
133
134impl From<sdl3::gamepad::Axis> for Axis {
135    fn from(axis: sdl3::gamepad::Axis) -> Self {
136        Self(axis)
137    }
138}
139
140impl From<Axis> for sdl3::gamepad::Axis {
141    fn from(axis: Axis) -> Self {
142        axis.0
143    }
144}