1pub mod filter;
11pub mod state;
12
13use std::{
14 fmt::{Display, Formatter, Result as FmtResult},
15 time::SystemTime,
16};
17
18use crate::{constants::*, gamepad::GamepadId, utils};
19
20#[cfg(feature = "serde-serialize")]
21use serde::{Deserialize, Serialize};
22
23#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
33#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
34pub struct Code(pub(crate) gilrs_core::EvCode);
35
36impl Display for Code {
37 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
38 self.0.fmt(f)
39 }
40}
41
42impl Code {
43 pub fn into_u32(&self) -> u32 {
45 self.0.into_u32()
46 }
47}
48
49#[derive(Copy, Clone, PartialEq, Debug)]
51#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
52#[non_exhaustive]
53pub struct Event {
54 pub id: GamepadId,
56 pub event: EventType,
58 pub time: SystemTime,
60}
61
62impl Event {
63 pub fn new(id: GamepadId, event: EventType) -> Self {
65 Event {
66 id,
67 event,
68 time: utils::time_now(),
69 }
70 }
71
72 pub fn drop(mut self) -> Event {
74 self.event = EventType::Dropped;
75
76 self
77 }
78
79 pub fn is_dropped(&self) -> bool {
81 self.event == EventType::Dropped
82 }
83}
84
85#[derive(Debug, Clone, Copy, PartialEq)]
86#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
87#[non_exhaustive]
88pub enum EventType {
90 ButtonPressed(Button, Code),
92 ButtonRepeated(Button, Code),
94 ButtonReleased(Button, Code),
96 ButtonChanged(Button, f32, Code),
98 AxisChanged(Axis, f32, Code),
100 Connected,
103 Disconnected,
105 Dropped,
107 ForceFeedbackEffectCompleted,
109}
110
111#[repr(u16)]
112#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
113#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
114pub enum Button {
118 South = BTN_SOUTH,
120 East = BTN_EAST,
121 North = BTN_NORTH,
122 West = BTN_WEST,
123 C = BTN_C,
124 Z = BTN_Z,
125 LeftTrigger = BTN_LT,
127 LeftTrigger2 = BTN_LT2,
128 RightTrigger = BTN_RT,
129 RightTrigger2 = BTN_RT2,
130 Select = BTN_SELECT,
132 Start = BTN_START,
133 Mode = BTN_MODE,
134 LeftThumb = BTN_LTHUMB,
136 RightThumb = BTN_RTHUMB,
137 DPadUp = BTN_DPAD_UP,
139 DPadDown = BTN_DPAD_DOWN,
140 DPadLeft = BTN_DPAD_LEFT,
141 DPadRight = BTN_DPAD_RIGHT,
142
143 #[default]
144 Unknown = BTN_UNKNOWN,
145}
146
147impl Button {
148 pub fn is_action(self) -> bool {
149 use crate::Button::*;
150 matches!(self, South | East | North | West | C | Z)
151 }
152
153 pub fn is_trigger(self) -> bool {
154 use crate::Button::*;
155 matches!(
156 self,
157 LeftTrigger | LeftTrigger2 | RightTrigger | RightTrigger2
158 )
159 }
160
161 pub fn is_menu(self) -> bool {
162 use crate::Button::*;
163 matches!(self, Select | Start | Mode)
164 }
165
166 pub fn is_stick(self) -> bool {
167 use crate::Button::*;
168 matches!(self, LeftThumb | RightThumb)
169 }
170
171 pub fn is_dpad(self) -> bool {
172 use crate::Button::*;
173 matches!(self, DPadUp | DPadDown | DPadLeft | DPadRight)
174 }
175
176 pub fn to_nec(self) -> Option<Code> {
177 use gilrs_core::native_ev_codes as necs;
178
179 match self {
180 Button::South => Some(necs::BTN_SOUTH),
181 Button::East => Some(necs::BTN_EAST),
182 Button::North => Some(necs::BTN_NORTH),
183 Button::West => Some(necs::BTN_WEST),
184 Button::C => Some(necs::BTN_C),
185 Button::Z => Some(necs::BTN_Z),
186 Button::LeftTrigger => Some(necs::BTN_LT),
187 Button::LeftTrigger2 => Some(necs::BTN_LT2),
188 Button::RightTrigger => Some(necs::BTN_RT),
189 Button::RightTrigger2 => Some(necs::BTN_RT2),
190 Button::Select => Some(necs::BTN_SELECT),
191 Button::Start => Some(necs::BTN_START),
192 Button::Mode => Some(necs::BTN_MODE),
193 Button::LeftThumb => Some(necs::BTN_LTHUMB),
194 Button::RightThumb => Some(necs::BTN_RTHUMB),
195 Button::DPadUp => Some(necs::BTN_DPAD_UP),
196 Button::DPadDown => Some(necs::BTN_DPAD_DOWN),
197 Button::DPadLeft => Some(necs::BTN_DPAD_LEFT),
198 Button::DPadRight => Some(necs::BTN_DPAD_RIGHT),
199 _ => None,
200 }
201 .map(Code)
202 }
203}
204
205#[repr(u16)]
206#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
207#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
208pub enum Axis {
212 LeftStickX = AXIS_LSTICKX,
213 LeftStickY = AXIS_LSTICKY,
214 LeftZ = AXIS_LEFTZ,
215 RightStickX = AXIS_RSTICKX,
216 RightStickY = AXIS_RSTICKY,
217 RightZ = AXIS_RIGHTZ,
218 DPadX = AXIS_DPADX,
219 DPadY = AXIS_DPADY,
220 Unknown = AXIS_UNKNOWN,
221}
222
223impl Axis {
224 pub fn is_stick(self) -> bool {
226 use crate::Axis::*;
227 matches!(self, LeftStickX | LeftStickY | RightStickX | RightStickY)
228 }
229
230 pub fn second_axis(self) -> Option<Self> {
242 use crate::Axis::*;
243 match self {
244 LeftStickX => Some(LeftStickY),
245 LeftStickY => Some(LeftStickX),
246 RightStickX => Some(RightStickY),
247 RightStickY => Some(RightStickX),
248 DPadX => Some(DPadY),
249 DPadY => Some(DPadX),
250 _ => None,
251 }
252 }
253}
254
255#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
257#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
258pub enum AxisOrBtn {
259 Axis(Axis),
260 Btn(Button),
261}
262
263impl AxisOrBtn {
264 pub(crate) fn is_button(&self) -> bool {
265 matches!(self, AxisOrBtn::Btn(_))
266 }
267}