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 {
44 self.0.into_u32()
45 }
46}
47
48#[derive(Copy, Clone, PartialEq, Debug)]
50#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
51#[non_exhaustive]
52pub struct Event {
53 pub id: GamepadId,
55 pub event: EventType,
57 pub time: SystemTime,
59}
60
61impl Event {
62 pub fn new(id: GamepadId, event: EventType) -> Self {
64 Event {
65 id,
66 event,
67 time: utils::time_now(),
68 }
69 }
70
71 pub fn drop(mut self) -> Event {
73 self.event = EventType::Dropped;
74
75 self
76 }
77
78 pub fn is_dropped(&self) -> bool {
80 self.event == EventType::Dropped
81 }
82}
83
84#[derive(Debug, Clone, Copy, PartialEq)]
85#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
86#[non_exhaustive]
87pub enum EventType {
89 ButtonPressed(Button, Code),
91 ButtonRepeated(Button, Code),
93 ButtonReleased(Button, Code),
95 ButtonChanged(Button, f32, Code),
97 AxisChanged(Axis, f32, Code),
99 Connected,
102 Disconnected,
104 Dropped,
106 ForceFeedbackEffectCompleted,
108}
109
110#[repr(u16)]
111#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
112#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
113pub enum Button {
117 South = BTN_SOUTH,
119 East = BTN_EAST,
120 North = BTN_NORTH,
121 West = BTN_WEST,
122 C = BTN_C,
123 Z = BTN_Z,
124 LeftTrigger = BTN_LT,
126 LeftTrigger2 = BTN_LT2,
127 RightTrigger = BTN_RT,
128 RightTrigger2 = BTN_RT2,
129 Select = BTN_SELECT,
131 Start = BTN_START,
132 Mode = BTN_MODE,
133 LeftThumb = BTN_LTHUMB,
135 RightThumb = BTN_RTHUMB,
136 DPadUp = BTN_DPAD_UP,
138 DPadDown = BTN_DPAD_DOWN,
139 DPadLeft = BTN_DPAD_LEFT,
140 DPadRight = BTN_DPAD_RIGHT,
141
142 #[default]
143 Unknown = BTN_UNKNOWN,
144}
145
146impl Button {
147 pub fn is_action(self) -> bool {
148 use crate::Button::*;
149 matches!(self, South | East | North | West | C | Z)
150 }
151
152 pub fn is_trigger(self) -> bool {
153 use crate::Button::*;
154 matches!(
155 self,
156 LeftTrigger | LeftTrigger2 | RightTrigger | RightTrigger2
157 )
158 }
159
160 pub fn is_menu(self) -> bool {
161 use crate::Button::*;
162 matches!(self, Select | Start | Mode)
163 }
164
165 pub fn is_stick(self) -> bool {
166 use crate::Button::*;
167 matches!(self, LeftThumb | RightThumb)
168 }
169
170 pub fn is_dpad(self) -> bool {
171 use crate::Button::*;
172 matches!(self, DPadUp | DPadDown | DPadLeft | DPadRight)
173 }
174
175 pub fn to_nec(self) -> Option<Code> {
176 use gilrs_core::native_ev_codes as necs;
177
178 match self {
179 Button::South => Some(necs::BTN_SOUTH),
180 Button::East => Some(necs::BTN_EAST),
181 Button::North => Some(necs::BTN_NORTH),
182 Button::West => Some(necs::BTN_WEST),
183 Button::C => Some(necs::BTN_C),
184 Button::Z => Some(necs::BTN_Z),
185 Button::LeftTrigger => Some(necs::BTN_LT),
186 Button::LeftTrigger2 => Some(necs::BTN_LT2),
187 Button::RightTrigger => Some(necs::BTN_RT),
188 Button::RightTrigger2 => Some(necs::BTN_RT2),
189 Button::Select => Some(necs::BTN_SELECT),
190 Button::Start => Some(necs::BTN_START),
191 Button::Mode => Some(necs::BTN_MODE),
192 Button::LeftThumb => Some(necs::BTN_LTHUMB),
193 Button::RightThumb => Some(necs::BTN_RTHUMB),
194 Button::DPadUp => Some(necs::BTN_DPAD_UP),
195 Button::DPadDown => Some(necs::BTN_DPAD_DOWN),
196 Button::DPadLeft => Some(necs::BTN_DPAD_LEFT),
197 Button::DPadRight => Some(necs::BTN_DPAD_RIGHT),
198 _ => None,
199 }
200 .map(Code)
201 }
202}
203
204#[repr(u16)]
205#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
206#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
207pub enum Axis {
211 LeftStickX = AXIS_LSTICKX,
212 LeftStickY = AXIS_LSTICKY,
213 LeftZ = AXIS_LEFTZ,
214 RightStickX = AXIS_RSTICKX,
215 RightStickY = AXIS_RSTICKY,
216 RightZ = AXIS_RIGHTZ,
217 DPadX = AXIS_DPADX,
218 DPadY = AXIS_DPADY,
219 Unknown = AXIS_UNKNOWN,
220}
221
222impl Axis {
223 pub fn is_stick(self) -> bool {
225 use crate::Axis::*;
226 matches!(self, LeftStickX | LeftStickY | RightStickX | RightStickY)
227 }
228
229 pub fn second_axis(self) -> Option<Self> {
241 use crate::Axis::*;
242 match self {
243 LeftStickX => Some(LeftStickY),
244 LeftStickY => Some(LeftStickX),
245 RightStickX => Some(RightStickY),
246 RightStickY => Some(RightStickX),
247 DPadX => Some(DPadY),
248 DPadY => Some(DPadX),
249 _ => None,
250 }
251 }
252}
253
254#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
256#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
257pub enum AxisOrBtn {
258 Axis(Axis),
259 Btn(Button),
260}
261
262impl AxisOrBtn {
263 pub(crate) fn is_button(&self) -> bool {
264 matches!(self, AxisOrBtn::Btn(_))
265 }
266}