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(HasSchema, Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
68#[repr(C, u8)]
69pub enum GamepadButton {
70 #[default]
71 South,
72 East,
73 North,
74 West,
75 C,
76 Z,
77 LeftTrigger,
78 LeftTrigger2,
79 RightTrigger,
80 RightTrigger2,
81 Select,
82 Start,
83 Mode,
84 LeftThumb,
85 RightThumb,
86 DPadUp,
87 DPadDown,
88 DPadLeft,
89 DPadRight,
90 Other(u8),
91}
92
93impl std::fmt::Display for GamepadButton {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 write!(
96 f,
97 "{}",
98 match self {
99 GamepadButton::South => "South",
100 GamepadButton::East => "East",
101 GamepadButton::North => "North",
102 GamepadButton::West => "West",
103 GamepadButton::C => "C",
104 GamepadButton::Z => "Z",
105 GamepadButton::LeftTrigger => "Left Trigger",
106 GamepadButton::LeftTrigger2 => "Left Trigger 2",
107 GamepadButton::RightTrigger => "Right Trigger",
108 GamepadButton::RightTrigger2 => "Right Trigger 2",
109 GamepadButton::Select => "Select",
110 GamepadButton::Start => "Start",
111 GamepadButton::Mode => "Mode",
112 GamepadButton::LeftThumb => "Left Thumb",
113 GamepadButton::RightThumb => "Right Thumb",
114 GamepadButton::DPadUp => "DPad Up",
115 GamepadButton::DPadDown => "DPad Down",
116 GamepadButton::DPadLeft => "DPad Left",
117 GamepadButton::DPadRight => "DPad Right",
118 GamepadButton::Other(n) => return write!(f, "Button {n}"),
119 }
120 )
121 }
122}
123
124#[derive(HasSchema, Clone, Copy, Debug)]
126#[schema(no_default)]
127#[repr(C)]
128pub struct GamepadAxisEvent {
129 pub gamepad: u32,
131 pub axis: GamepadAxis,
133 pub value: f32,
135}
136
137#[derive(HasSchema, Clone, Copy, Debug, PartialEq, Eq, Hash)]
139#[schema(no_default)]
140#[allow(missing_docs)]
141#[repr(C, u8)]
142pub enum GamepadAxis {
143 LeftStickX,
144 LeftStickY,
145 LeftZ,
146 RightStickX,
147 RightStickY,
148 RightZ,
149 Other(u8),
150}
151
152impl std::fmt::Display for GamepadAxis {
153 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
154 write!(
155 f,
156 "{}",
157 match self {
158 GamepadAxis::LeftStickX => "Left Stick X",
159 GamepadAxis::LeftStickY => "Left Stick Y",
160 GamepadAxis::LeftZ => "Left Z",
161 GamepadAxis::RightStickX => "Right Stick X",
162 GamepadAxis::RightStickY => "Right Stick Y",
163 GamepadAxis::RightZ => "Right Z",
164 GamepadAxis::Other(n) => return write!(f, "Axis {n}"),
165 }
166 )
167 }
168}
169
170#[derive(HasSchema, Default, Clone, Copy, Debug)]
172pub struct GamepadRumbleIntensity {
173 strong_motor: f32,
175 weak_motor: f32,
177}
178
179impl GamepadRumbleIntensity {
180 pub const ZERO: Self = Self {
182 strong_motor: 0.0,
183 weak_motor: 0.0,
184 };
185 pub const MAX_BOTH: Self = Self {
187 strong_motor: 1.0,
188 weak_motor: 1.0,
189 };
190 pub const MAX_STRONG: Self = Self {
192 strong_motor: 1.0,
193 weak_motor: 0.0,
194 };
195 pub const MAX_WEAK: Self = Self {
197 strong_motor: 0.0,
198 weak_motor: 1.0,
199 };
200 pub const MEDIUM_BOTH: Self = Self {
202 strong_motor: 0.5,
203 weak_motor: 0.5,
204 };
205 pub const MEDIUM_STRONG: Self = Self {
207 strong_motor: 0.5,
208 weak_motor: 0.0,
209 };
210 pub const MEDIUM_WEAK: Self = Self {
212 strong_motor: 0.0,
213 weak_motor: 0.5,
214 };
215 pub const LIGHT_BOTH: Self = Self {
217 strong_motor: 0.25,
218 weak_motor: 0.25,
219 };
220 pub const LIGHT_STRONG: Self = Self {
222 strong_motor: 0.25,
223 weak_motor: 0.0,
224 };
225 pub const LIGHT_WEAK: Self = Self {
227 strong_motor: 0.0,
228 weak_motor: 0.25,
229 };
230 pub const VERY_LIGHT_BOTH: Self = Self {
232 strong_motor: 0.1,
233 weak_motor: 0.1,
234 };
235 pub const VERY_LIGHT_STRONG: Self = Self {
237 strong_motor: 0.1,
238 weak_motor: 0.0,
239 };
240 pub const VERY_LIGHT_WEAK: Self = Self {
242 strong_motor: 0.0,
243 weak_motor: 0.1,
244 };
245
246 pub fn strong_motor(&self) -> f32 {
248 self.strong_motor
249 }
250
251 pub fn set_strong_motor(&mut self, value: f32) {
253 self.strong_motor = value.clamp(0.0, 1.0);
254 }
255
256 pub fn weak_motor(&self) -> f32 {
258 self.weak_motor
259 }
260
261 pub fn set_weak_motor(&mut self, value: f32) {
263 self.weak_motor = value.clamp(0.0, 1.0);
264 }
265}
266
267#[derive(HasSchema, Clone, Debug)]
269pub enum GamepadRumbleRequest {
270 AddRumble {
272 gamepad: u32,
274 intensity: GamepadRumbleIntensity,
276 duration: f32,
278 },
279 SetRumble {
281 gamepad: u32,
283 intensity: GamepadRumbleIntensity,
285 duration: f32,
287 },
288 Stop {
290 gamepad: u32,
292 },
293}
294
295impl Default for GamepadRumbleRequest {
296 fn default() -> Self {
297 GamepadRumbleRequest::Stop { gamepad: 0 }
298 }
299}
300
301#[derive(HasSchema, Clone)]
303pub struct GamepadsRumble {
304 pub requests: VecDeque<GamepadRumbleRequest>,
306 enabled_gamepads: SVec<bool>,
308}
309
310impl GamepadsRumble {
311 pub fn add_rumble(&mut self, gamepad: u32, intensity: GamepadRumbleIntensity, duration: f32) {
313 if self.is_enabled(gamepad) {
314 self.requests.push_back(GamepadRumbleRequest::AddRumble {
315 gamepad,
316 intensity,
317 duration,
318 });
319 }
320 }
321
322 pub fn set_rumble(&mut self, gamepad: u32, intensity: GamepadRumbleIntensity, duration: f32) {
324 if self.is_enabled(gamepad) {
325 self.requests.push_back(GamepadRumbleRequest::SetRumble {
326 gamepad,
327 intensity,
328 duration,
329 });
330 }
331 }
332
333 pub fn stop(&mut self, gamepad: u32) {
335 if self.is_enabled(gamepad) {
336 self.requests
337 .push_back(GamepadRumbleRequest::Stop { gamepad });
338 }
339 }
340
341 pub fn add_rumble_all(&mut self, intensity: GamepadRumbleIntensity, duration: f32) {
343 for gamepad in 0..self.enabled_gamepads.len() {
344 if self.is_enabled(gamepad as u32) {
345 self.add_rumble(gamepad as u32, intensity, duration);
346 }
347 }
348 }
349
350 pub fn set_rumble_all(&mut self, intensity: GamepadRumbleIntensity, duration: f32) {
352 for gamepad in 0..self.enabled_gamepads.len() {
353 if self.is_enabled(gamepad as u32) {
354 self.set_rumble(gamepad as u32, intensity, duration);
355 }
356 }
357 }
358
359 pub fn stop_all(&mut self) {
361 for gamepad in 0..self.enabled_gamepads.len() {
362 if self.is_enabled(gamepad as u32) {
363 self.stop(gamepad as u32);
364 }
365 }
366 }
367
368 pub fn is_enabled(&self, gamepad: u32) -> bool {
370 let gamepad_index = gamepad as usize;
371 if gamepad_index < self.enabled_gamepads.len() {
372 self.enabled_gamepads[gamepad_index]
373 } else {
374 false
375 }
376 }
377
378 pub fn is_disabled(&self, gamepad: u32) -> bool {
380 !self.is_enabled(gamepad)
381 }
382
383 pub fn enable(&mut self, gamepad: u32) {
385 if let Some(enabled) = self.enabled_gamepads.get_mut(gamepad as usize) {
386 *enabled = true;
387 }
388 }
389
390 pub fn disable(&mut self, gamepad: u32) {
392 self.stop(gamepad);
393 if let Some(enabled) = self.enabled_gamepads.get_mut(gamepad as usize) {
394 *enabled = false;
395 }
396 }
397
398 pub fn enable_all(&mut self) {
400 for gamepad in 0..self.enabled_gamepads.len() {
401 self.enable(gamepad as u32);
402 }
403 }
404
405 pub fn disable_all(&mut self) {
407 for gamepad in 0..self.enabled_gamepads.len() {
408 self.disable(gamepad as u32);
409 }
410 }
411}
412
413impl Default for GamepadsRumble {
414 fn default() -> Self {
415 GamepadsRumble {
416 requests: VecDeque::new(),
417 enabled_gamepads: vec![true; 4].into(),
418 }
419 }
420}