use std::collections::VecDeque;
use crate::prelude::*;
#[derive(HasSchema, Clone, Default, Debug)]
pub struct GamepadInputs {
pub gamepad_events: SVec<GamepadEvent>,
}
#[derive(HasSchema, Clone, Debug)]
#[repr(C, u8)]
pub enum GamepadEvent {
Connection(GamepadConnectionEvent),
Button(GamepadButtonEvent),
Axis(GamepadAxisEvent),
}
impl Default for GamepadEvent {
fn default() -> Self {
Self::Connection(default())
}
}
#[derive(HasSchema, Clone, Debug, Default)]
#[repr(C)]
pub struct GamepadConnectionEvent {
pub gamepad: u32,
pub event: GamepadConnectionEventKind,
}
#[derive(HasSchema, Clone, Debug, Default)]
#[repr(u8)]
pub enum GamepadConnectionEventKind {
#[default]
Connected,
Disconnected,
}
#[derive(HasSchema, Clone, Debug, Default)]
#[repr(C)]
pub struct GamepadButtonEvent {
pub gamepad: u32,
pub button: GamepadButton,
pub value: f32,
}
#[allow(missing_docs)]
#[derive(HasSchema, Clone, Debug, Default, PartialEq, Eq, Hash)]
#[repr(C, u8)]
pub enum GamepadButton {
#[default]
South,
East,
North,
West,
C,
Z,
LeftTrigger,
LeftTrigger2,
RightTrigger,
RightTrigger2,
Select,
Start,
Mode,
LeftThumb,
RightThumb,
DPadUp,
DPadDown,
DPadLeft,
DPadRight,
Other(u8),
}
impl std::fmt::Display for GamepadButton {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
GamepadButton::South => "South",
GamepadButton::East => "East",
GamepadButton::North => "North",
GamepadButton::West => "West",
GamepadButton::C => "C",
GamepadButton::Z => "Z",
GamepadButton::LeftTrigger => "Left Trigger",
GamepadButton::LeftTrigger2 => "Left Trigger 2",
GamepadButton::RightTrigger => "Right Trigger",
GamepadButton::RightTrigger2 => "Right Trigger 2",
GamepadButton::Select => "Select",
GamepadButton::Start => "Start",
GamepadButton::Mode => "Mode",
GamepadButton::LeftThumb => "Left Thumb",
GamepadButton::RightThumb => "Right Thumb",
GamepadButton::DPadUp => "DPad Up",
GamepadButton::DPadDown => "DPad Down",
GamepadButton::DPadLeft => "DPad Left",
GamepadButton::DPadRight => "DPad Right",
GamepadButton::Other(n) => return write!(f, "Button {n}"),
}
)
}
}
#[derive(HasSchema, Clone, Debug)]
#[schema(no_default)]
#[repr(C)]
pub struct GamepadAxisEvent {
pub gamepad: u32,
pub axis: GamepadAxis,
pub value: f32,
}
#[derive(HasSchema, Clone, Debug, PartialEq, Eq, Hash)]
#[schema(no_default)]
#[allow(missing_docs)]
#[repr(C, u8)]
pub enum GamepadAxis {
LeftStickX,
LeftStickY,
LeftZ,
RightStickX,
RightStickY,
RightZ,
Other(u8),
}
impl std::fmt::Display for GamepadAxis {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
GamepadAxis::LeftStickX => "Left Stick X",
GamepadAxis::LeftStickY => "Left Stick Y",
GamepadAxis::LeftZ => "Left Z",
GamepadAxis::RightStickX => "Right Stick X",
GamepadAxis::RightStickY => "Right Stick Y",
GamepadAxis::RightZ => "Right Z",
GamepadAxis::Other(n) => return write!(f, "Axis {n}"),
}
)
}
}
#[derive(HasSchema, Default, Clone, Debug, Copy)]
pub struct GamepadRumbleIntensity {
strong_motor: f32,
weak_motor: f32,
}
impl GamepadRumbleIntensity {
pub const ZERO: Self = Self {
strong_motor: 0.0,
weak_motor: 0.0,
};
pub const MAX_BOTH: Self = Self {
strong_motor: 1.0,
weak_motor: 1.0,
};
pub const MAX_STRONG: Self = Self {
strong_motor: 1.0,
weak_motor: 0.0,
};
pub const MAX_WEAK: Self = Self {
strong_motor: 0.0,
weak_motor: 1.0,
};
pub const MEDIUM_BOTH: Self = Self {
strong_motor: 0.5,
weak_motor: 0.5,
};
pub const MEDIUM_STRONG: Self = Self {
strong_motor: 0.5,
weak_motor: 0.0,
};
pub const MEDIUM_WEAK: Self = Self {
strong_motor: 0.0,
weak_motor: 0.5,
};
pub const LIGHT_BOTH: Self = Self {
strong_motor: 0.25,
weak_motor: 0.25,
};
pub const LIGHT_STRONG: Self = Self {
strong_motor: 0.25,
weak_motor: 0.0,
};
pub const LIGHT_WEAK: Self = Self {
strong_motor: 0.0,
weak_motor: 0.25,
};
pub const VERY_LIGHT_BOTH: Self = Self {
strong_motor: 0.1,
weak_motor: 0.1,
};
pub const VERY_LIGHT_STRONG: Self = Self {
strong_motor: 0.1,
weak_motor: 0.0,
};
pub const VERY_LIGHT_WEAK: Self = Self {
strong_motor: 0.0,
weak_motor: 0.1,
};
pub fn strong_motor(&self) -> f32 {
self.strong_motor
}
pub fn set_strong_motor(&mut self, value: f32) {
self.strong_motor = value.clamp(0.0, 1.0);
}
pub fn weak_motor(&self) -> f32 {
self.weak_motor
}
pub fn set_weak_motor(&mut self, value: f32) {
self.weak_motor = value.clamp(0.0, 1.0);
}
}
#[derive(HasSchema, Clone, Debug)]
pub enum GamepadRumbleRequest {
AddRumble {
gamepad: u32,
intensity: GamepadRumbleIntensity,
duration: f32,
},
SetRumble {
gamepad: u32,
intensity: GamepadRumbleIntensity,
duration: f32,
},
Stop {
gamepad: u32,
},
}
impl Default for GamepadRumbleRequest {
fn default() -> Self {
GamepadRumbleRequest::Stop { gamepad: 0 }
}
}
#[derive(HasSchema, Clone)]
pub struct GamepadsRumble {
pub requests: VecDeque<GamepadRumbleRequest>,
enabled_gamepads: SVec<bool>,
}
impl GamepadsRumble {
pub fn add_rumble(&mut self, gamepad: u32, intensity: GamepadRumbleIntensity, duration: f32) {
if self.is_enabled(gamepad) {
self.requests.push_back(GamepadRumbleRequest::AddRumble {
gamepad,
intensity,
duration,
});
}
}
pub fn set_rumble(&mut self, gamepad: u32, intensity: GamepadRumbleIntensity, duration: f32) {
if self.is_enabled(gamepad) {
self.requests.push_back(GamepadRumbleRequest::SetRumble {
gamepad,
intensity,
duration,
});
}
}
pub fn stop(&mut self, gamepad: u32) {
if self.is_enabled(gamepad) {
self.requests
.push_back(GamepadRumbleRequest::Stop { gamepad });
}
}
pub fn add_rumble_all(&mut self, intensity: GamepadRumbleIntensity, duration: f32) {
for gamepad in 0..self.enabled_gamepads.len() {
if self.is_enabled(gamepad as u32) {
self.add_rumble(gamepad as u32, intensity, duration);
}
}
}
pub fn set_rumble_all(&mut self, intensity: GamepadRumbleIntensity, duration: f32) {
for gamepad in 0..self.enabled_gamepads.len() {
if self.is_enabled(gamepad as u32) {
self.set_rumble(gamepad as u32, intensity, duration);
}
}
}
pub fn stop_all(&mut self) {
for gamepad in 0..self.enabled_gamepads.len() {
if self.is_enabled(gamepad as u32) {
self.stop(gamepad as u32);
}
}
}
pub fn is_enabled(&self, gamepad: u32) -> bool {
let gamepad_index = gamepad as usize;
if gamepad_index < self.enabled_gamepads.len() {
self.enabled_gamepads[gamepad_index]
} else {
false
}
}
pub fn is_disabled(&self, gamepad: u32) -> bool {
!self.is_enabled(gamepad)
}
pub fn enable(&mut self, gamepad: u32) {
if let Some(enabled) = self.enabled_gamepads.get_mut(gamepad as usize) {
*enabled = true;
}
}
pub fn disable(&mut self, gamepad: u32) {
self.stop(gamepad);
if let Some(enabled) = self.enabled_gamepads.get_mut(gamepad as usize) {
*enabled = false;
}
}
pub fn enable_all(&mut self) {
for gamepad in 0..self.enabled_gamepads.len() {
self.enable(gamepad as u32);
}
}
pub fn disable_all(&mut self) {
for gamepad in 0..self.enabled_gamepads.len() {
self.disable(gamepad as u32);
}
}
}
impl Default for GamepadsRumble {
fn default() -> Self {
GamepadsRumble {
requests: VecDeque::new(),
enabled_gamepads: vec![true; 4].into(),
}
}
}