1use std::collections::VecDeque;
3
4use crate::prelude::*;
5
6#[derive(HasSchema, Clone, Default, Debug)]
8pub struct GamepadInputs {
9 pub gamepad_events: SVec<GamepadEvent>,
11}
12
13#[derive(HasSchema, Clone, Copy, Debug)]
15#[repr(C, u8)]
16pub enum GamepadEvent {
17 Connection(GamepadConnectionEvent),
19 Button(GamepadButtonEvent),
21 Axis(GamepadAxisEvent),
23}
24
25impl Default for GamepadEvent {
26 fn default() -> Self {
27 Self::Connection(default())
28 }
29}
30
31#[derive(HasSchema, Clone, Copy, Debug, Default)]
33#[repr(C)]
34pub struct GamepadConnectionEvent {
35 pub gamepad: u32,
37 pub event: GamepadConnectionEventKind,
39}
40
41#[derive(HasSchema, Clone, Copy, Debug, Default)]
43#[repr(u8)]
44pub enum GamepadConnectionEventKind {
45 #[default]
46 Connected,
48 Disconnected,
50}
51
52#[derive(HasSchema, Clone, Copy, Debug, Default)]
54#[repr(C)]
55pub struct GamepadButtonEvent {
56 pub gamepad: u32,
58 pub button: GamepadButton,
60 pub value: f32,
63}
64
65#[allow(missing_docs)]
67#[derive(
68 HasSchema,
69 Clone,
70 Copy,
71 Debug,
72 Default,
73 PartialEq,
74 Eq,
75 Hash,
76 serde::Deserialize,
77 serde::Serialize,
78)]
79#[schema(hash, eq)]
80#[repr(C, u8)]
81pub enum GamepadButton {
82 #[default]
83 South,
84 East,
85 North,
86 West,
87 C,
88 Z,
89 LeftTrigger,
90 LeftTrigger2,
91 RightTrigger,
92 RightTrigger2,
93 Select,
94 Start,
95 Mode,
96 LeftThumb,
97 RightThumb,
98 DPadUp,
99 DPadDown,
100 DPadLeft,
101 DPadRight,
102 Other(u8),
103}
104
105impl std::fmt::Display for GamepadButton {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 write!(
108 f,
109 "{}",
110 match self {
111 GamepadButton::South => "South",
112 GamepadButton::East => "East",
113 GamepadButton::North => "North",
114 GamepadButton::West => "West",
115 GamepadButton::C => "C",
116 GamepadButton::Z => "Z",
117 GamepadButton::LeftTrigger => "Left Trigger",
118 GamepadButton::LeftTrigger2 => "Left Trigger 2",
119 GamepadButton::RightTrigger => "Right Trigger",
120 GamepadButton::RightTrigger2 => "Right Trigger 2",
121 GamepadButton::Select => "Select",
122 GamepadButton::Start => "Start",
123 GamepadButton::Mode => "Mode",
124 GamepadButton::LeftThumb => "Left Thumb",
125 GamepadButton::RightThumb => "Right Thumb",
126 GamepadButton::DPadUp => "DPad Up",
127 GamepadButton::DPadDown => "DPad Down",
128 GamepadButton::DPadLeft => "DPad Left",
129 GamepadButton::DPadRight => "DPad Right",
130 GamepadButton::Other(n) => return write!(f, "Button {n}"),
131 }
132 )
133 }
134}
135
136#[derive(HasSchema, Clone, Copy, Debug)]
138#[schema(no_default)]
139#[repr(C)]
140pub struct GamepadAxisEvent {
141 pub gamepad: u32,
143 pub axis: GamepadAxis,
145 pub value: f32,
147}
148
149#[derive(
151 HasSchema, Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize,
152)]
153#[schema(no_default, hash, eq)]
154#[allow(missing_docs)]
155#[repr(C, u8)]
156pub enum GamepadAxis {
157 LeftStickX,
158 LeftStickY,
159 LeftZ,
160 RightStickX,
161 RightStickY,
162 RightZ,
163 Other(u8),
164}
165
166impl std::fmt::Display for GamepadAxis {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 write!(
169 f,
170 "{}",
171 match self {
172 GamepadAxis::LeftStickX => "Left Stick X",
173 GamepadAxis::LeftStickY => "Left Stick Y",
174 GamepadAxis::LeftZ => "Left Z",
175 GamepadAxis::RightStickX => "Right Stick X",
176 GamepadAxis::RightStickY => "Right Stick Y",
177 GamepadAxis::RightZ => "Right Z",
178 GamepadAxis::Other(n) => return write!(f, "Axis {n}"),
179 }
180 )
181 }
182}
183
184#[derive(HasSchema, Default, Clone, Copy, Debug)]
186pub struct GamepadRumbleIntensity {
187 strong_motor: f32,
189 weak_motor: f32,
191}
192
193impl GamepadRumbleIntensity {
194 pub const ZERO: Self = Self {
196 strong_motor: 0.0,
197 weak_motor: 0.0,
198 };
199 pub const MAX_BOTH: Self = Self {
201 strong_motor: 1.0,
202 weak_motor: 1.0,
203 };
204 pub const MAX_STRONG: Self = Self {
206 strong_motor: 1.0,
207 weak_motor: 0.0,
208 };
209 pub const MAX_WEAK: Self = Self {
211 strong_motor: 0.0,
212 weak_motor: 1.0,
213 };
214 pub const MEDIUM_BOTH: Self = Self {
216 strong_motor: 0.5,
217 weak_motor: 0.5,
218 };
219 pub const MEDIUM_STRONG: Self = Self {
221 strong_motor: 0.5,
222 weak_motor: 0.0,
223 };
224 pub const MEDIUM_WEAK: Self = Self {
226 strong_motor: 0.0,
227 weak_motor: 0.5,
228 };
229 pub const LIGHT_BOTH: Self = Self {
231 strong_motor: 0.25,
232 weak_motor: 0.25,
233 };
234 pub const LIGHT_STRONG: Self = Self {
236 strong_motor: 0.25,
237 weak_motor: 0.0,
238 };
239 pub const LIGHT_WEAK: Self = Self {
241 strong_motor: 0.0,
242 weak_motor: 0.25,
243 };
244 pub const VERY_LIGHT_BOTH: Self = Self {
246 strong_motor: 0.1,
247 weak_motor: 0.1,
248 };
249 pub const VERY_LIGHT_STRONG: Self = Self {
251 strong_motor: 0.1,
252 weak_motor: 0.0,
253 };
254 pub const VERY_LIGHT_WEAK: Self = Self {
256 strong_motor: 0.0,
257 weak_motor: 0.1,
258 };
259
260 pub fn strong_motor(&self) -> f32 {
262 self.strong_motor
263 }
264
265 pub fn set_strong_motor(&mut self, value: f32) {
267 self.strong_motor = value.clamp(0.0, 1.0);
268 }
269
270 pub fn weak_motor(&self) -> f32 {
272 self.weak_motor
273 }
274
275 pub fn set_weak_motor(&mut self, value: f32) {
277 self.weak_motor = value.clamp(0.0, 1.0);
278 }
279}
280
281#[derive(HasSchema, Clone, Debug)]
283pub enum GamepadRumbleRequest {
284 AddRumble {
286 gamepad: u32,
288 intensity: GamepadRumbleIntensity,
290 duration: f32,
292 },
293 SetRumble {
295 gamepad: u32,
297 intensity: GamepadRumbleIntensity,
299 duration: f32,
301 },
302 Stop {
304 gamepad: u32,
306 },
307}
308
309impl Default for GamepadRumbleRequest {
310 fn default() -> Self {
311 GamepadRumbleRequest::Stop { gamepad: 0 }
312 }
313}
314
315#[derive(HasSchema, Clone)]
317pub struct GamepadsRumble {
318 pub requests: VecDeque<GamepadRumbleRequest>,
320 enabled_gamepads: SVec<bool>,
322}
323
324impl GamepadsRumble {
325 pub fn add_rumble(&mut self, gamepad: u32, intensity: GamepadRumbleIntensity, duration: f32) {
327 if self.is_enabled(gamepad) {
328 self.requests.push_back(GamepadRumbleRequest::AddRumble {
329 gamepad,
330 intensity,
331 duration,
332 });
333 }
334 }
335
336 pub fn set_rumble(&mut self, gamepad: u32, intensity: GamepadRumbleIntensity, duration: f32) {
338 if self.is_enabled(gamepad) {
339 self.requests.push_back(GamepadRumbleRequest::SetRumble {
340 gamepad,
341 intensity,
342 duration,
343 });
344 }
345 }
346
347 pub fn stop(&mut self, gamepad: u32) {
349 if self.is_enabled(gamepad) {
350 self.requests
351 .push_back(GamepadRumbleRequest::Stop { gamepad });
352 }
353 }
354
355 pub fn add_rumble_all(&mut self, intensity: GamepadRumbleIntensity, duration: f32) {
357 for gamepad in 0..self.enabled_gamepads.len() {
358 if self.is_enabled(gamepad as u32) {
359 self.add_rumble(gamepad as u32, intensity, duration);
360 }
361 }
362 }
363
364 pub fn set_rumble_all(&mut self, intensity: GamepadRumbleIntensity, duration: f32) {
366 for gamepad in 0..self.enabled_gamepads.len() {
367 if self.is_enabled(gamepad as u32) {
368 self.set_rumble(gamepad as u32, intensity, duration);
369 }
370 }
371 }
372
373 pub fn stop_all(&mut self) {
375 for gamepad in 0..self.enabled_gamepads.len() {
376 if self.is_enabled(gamepad as u32) {
377 self.stop(gamepad as u32);
378 }
379 }
380 }
381
382 pub fn is_enabled(&self, gamepad: u32) -> bool {
384 let gamepad_index = gamepad as usize;
385 if gamepad_index < self.enabled_gamepads.len() {
386 self.enabled_gamepads[gamepad_index]
387 } else {
388 false
389 }
390 }
391
392 pub fn is_disabled(&self, gamepad: u32) -> bool {
394 !self.is_enabled(gamepad)
395 }
396
397 pub fn enable(&mut self, gamepad: u32) {
399 if let Some(enabled) = self.enabled_gamepads.get_mut(gamepad as usize) {
400 *enabled = true;
401 }
402 }
403
404 pub fn disable(&mut self, gamepad: u32) {
406 self.stop(gamepad);
407 if let Some(enabled) = self.enabled_gamepads.get_mut(gamepad as usize) {
408 *enabled = false;
409 }
410 }
411
412 pub fn enable_all(&mut self) {
414 for gamepad in 0..self.enabled_gamepads.len() {
415 self.enable(gamepad as u32);
416 }
417 }
418
419 pub fn disable_all(&mut self) {
421 for gamepad in 0..self.enabled_gamepads.len() {
422 self.disable(gamepad as u32);
423 }
424 }
425}
426
427impl Default for GamepadsRumble {
428 fn default() -> Self {
429 GamepadsRumble {
430 requests: VecDeque::new(),
431 enabled_gamepads: vec![true; 4].into(),
432 }
433 }
434}