Skip to main content

blinds/event/
gamepad.rs

1use std::cmp::Ordering;
2
3#[derive(Clone, Debug)]
4/// See [`Event::GamepadConnected`]
5///
6/// [`Event::GamepadConnected`]: crate::event::Event::GamepadConnected
7pub struct GamepadConnectedEvent(pub(crate) GamepadId);
8
9impl GamepadConnectedEvent {
10    pub fn gamepad(&self) -> &GamepadId {
11        &self.0
12    }
13}
14
15#[derive(Clone, Debug)]
16/// See [`Event::GamepadDisconnected`]
17///
18/// [`Event::GamepadDisconnected`]: crate::event::Event::GamepadDisconnected
19pub struct GamepadDisconnectedEvent(pub(crate) GamepadId);
20
21impl GamepadDisconnectedEvent {
22    pub fn gamepad(&self) -> &GamepadId {
23        &self.0
24    }
25}
26
27#[derive(Clone, Debug)]
28/// See [`Event::GamepadButton`]
29///
30/// [`Event::GamepadButton`]: crate::event::Event::GamepadButton
31pub struct GamepadButtonEvent {
32    pub(crate) id: GamepadId,
33    pub(crate) button: GamepadButton,
34    pub(crate) is_down: bool,
35    pub(crate) is_repeat: bool,
36}
37
38impl GamepadButtonEvent {
39    /// Which gamepad generated the event
40    pub fn gamepad(&self) -> &GamepadId {
41        &self.id
42    }
43
44    pub fn button(&self) -> GamepadButton {
45        self.button
46    }
47
48    /// If the button is now down, either repeating or down for the first time
49    pub fn is_down(&self) -> bool {
50        self.is_down
51    }
52
53    /// If this event is a repeat of a previous down event
54    pub fn is_repeat(&self) -> bool {
55        self.is_repeat
56    }
57}
58
59#[derive(Clone, Debug)]
60/// See [`Event::GamepadAxis`]
61///
62/// [`Event::GamepadAxis`]: crate::event::Event::GamepadAxis
63pub struct GamepadAxisEvent {
64    pub(crate) id: GamepadId,
65    pub(crate) axis: GamepadAxis,
66    pub(crate) value: f32,
67}
68
69impl GamepadAxisEvent {
70    /// Which gamepad generated the event
71    pub fn gamepad(&self) -> &GamepadId {
72        &self.id
73    }
74
75    pub fn axis(&self) -> GamepadAxis {
76        self.axis
77    }
78
79    pub fn value(&self) -> f32 {
80        self.value
81    }
82}
83
84#[derive(Clone, PartialEq, Eq, Debug, Hash)]
85/// A unique ID for a gamepad that persists after the device is unplugged
86pub struct GamepadId(
87    #[cfg(feature = "gilrs")] pub(crate) gilrs::GamepadId,
88    #[cfg(not(feature = "gilrs"))] usize,
89);
90
91impl PartialOrd for GamepadId {
92    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
93        Some(self.cmp(other))
94    }
95}
96
97impl Ord for GamepadId {
98    fn cmp(&self, other: &Self) -> Ordering {
99        let a: usize = self.0.into();
100        let b: usize = other.0.into();
101        a.cmp(&b)
102    }
103}
104
105#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
106#[cfg_attr(feature = "enum-map", derive(enum_map::Enum))]
107/// A button on a standard (d-pad, 2-stick, 4-button, 4-trigger) gamepad
108pub enum GamepadButton {
109    Start,
110    Select,
111
112    /// The north face button.
113    ///
114    /// * Nintendo: X
115    /// * Playstation: Triangle
116    /// * XBox: Y
117    North,
118    /// The south face button.
119    ///
120    /// * Nintendo: B
121    /// * Playstation: X
122    /// * XBox: A
123    South,
124    /// The east face button.
125    ///
126    /// * Nintendo: A
127    /// * Playstation: Circle
128    /// * XBox: B
129    East,
130    /// The west face button.
131    ///
132    /// * Nintendo: Y
133    /// * Playstation: Square
134    /// * XBox: X
135    West,
136
137    /// The left stick was pressed in as a button
138    LeftStick,
139    /// The right stick was pressed in as a button
140    RightStick,
141
142    LeftTrigger,
143    RightTrigger,
144
145    LeftShoulder,
146    RightShoulder,
147
148    DPadUp,
149    DPadDown,
150    DPadLeft,
151    DPadRight,
152}
153
154#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
155#[cfg_attr(feature = "enum-map", derive(enum_map::Enum))]
156/// The stick axes of a gamepad
157pub enum GamepadAxis {
158    LeftStickX,
159    LeftStickY,
160
161    RightStickX,
162    RightStickY,
163}
164
165#[cfg(feature = "gilrs")]
166pub(crate) fn convert_gilrs_button(event: gilrs::ev::Button) -> Option<GamepadButton> {
167    use gilrs::ev::Button::*;
168    Some(match event {
169        South => GamepadButton::South,
170        East => GamepadButton::East,
171        North => GamepadButton::North,
172        West => GamepadButton::West,
173        LeftTrigger => GamepadButton::LeftShoulder,
174        LeftTrigger2 => GamepadButton::LeftShoulder,
175        RightTrigger => GamepadButton::RightShoulder,
176        RightTrigger2 => GamepadButton::RightTrigger,
177        Select => GamepadButton::Select,
178        Start => GamepadButton::Start,
179        LeftThumb => GamepadButton::LeftStick,
180        RightThumb => GamepadButton::RightStick,
181        DPadUp => GamepadButton::DPadUp,
182        DPadDown => GamepadButton::DPadDown,
183        DPadLeft => GamepadButton::DPadLeft,
184        DPadRight => GamepadButton::DPadRight,
185
186        C | Z | Unknown | Mode => return None,
187    })
188}
189
190#[cfg(feature = "gilrs")]
191pub(crate) fn convert_gilrs_axis(axis: gilrs::ev::Axis) -> Option<GamepadAxis> {
192    use gilrs::ev::Axis::*;
193
194    Some(match axis {
195        LeftStickX => GamepadAxis::LeftStickX,
196        LeftStickY => GamepadAxis::LeftStickY,
197        RightStickX => GamepadAxis::RightStickX,
198        RightStickY => GamepadAxis::RightStickY,
199
200        LeftZ | RightZ | DPadX | DPadY | Unknown => return None,
201    })
202}