use bevy::input::gamepad::{Gamepad, GamepadAxis, GamepadButton};
use bevy::reflect::Reflect;
use std::time::Duration;
use crate::repeat::Repeat;
pub trait TriggerTrait {
fn is_triggered(&mut self, gamepad: &Gamepad, dt: &Duration) -> bool;
}
#[derive(Clone, Debug, Reflect)]
pub struct ButtonPressed {
button: GamepadButton,
repeat: Option<Repeat>,
}
impl ButtonPressed {
pub fn new(button: GamepadButton) -> Self {
Self {
button,
repeat: None,
}
}
pub fn with_repeat(
mut self,
duration_before_first_repeat: Duration,
duration_between_repeat: Duration,
) -> Self {
self.repeat = Some(Repeat::new(duration_before_first_repeat, duration_between_repeat));
self
}
}
impl TriggerTrait for ButtonPressed {
fn is_triggered(&mut self, gamepad: &Gamepad, dt: &Duration) -> bool {
let Some(repeat) = &mut self.repeat else {
return gamepad.just_pressed(self.button);
};
if gamepad.just_pressed(self.button) {
repeat.reset();
return true;
}
let signal = gamepad.pressed(self.button);
return repeat.is_triggered(signal, dt);
}
}
#[derive(Clone, Debug, Reflect)]
pub struct ButtonJustReleased {
button: GamepadButton,
}
impl ButtonJustReleased {
pub fn new(button: GamepadButton) -> Self {
Self {
button,
}
}
}
impl TriggerTrait for ButtonJustReleased {
fn is_triggered(&mut self, gamepad: &Gamepad, _dt: &Duration) -> bool {
gamepad.just_released(self.button)
}
}
#[derive(Clone, Debug, Reflect)]
pub struct Hysteresis {
axis: GamepadAxis,
above: bool,
lower: f32,
higher: f32,
active: bool,
repeat: Option<Repeat>,
}
impl Hysteresis {
pub fn new_above(axis: GamepadAxis, lower: f32, higher: f32) -> Self {
Self {
axis,
above: true,
lower,
higher,
active: false,
repeat: None,
}
}
pub fn new_below(axis: GamepadAxis, lower: f32, higher: f32) -> Self {
Self {
axis,
above: false,
lower,
higher,
active: false,
repeat: None,
}
}
pub fn with_repeat(
mut self,
duration_before_first_repeat: Duration,
duration_between_repeat: Duration,
) -> Self {
self.repeat = Some(Repeat::new(duration_before_first_repeat, duration_between_repeat));
self
}
}
impl TriggerTrait for Hysteresis {
fn is_triggered(&mut self, gamepad: &Gamepad, dt: &Duration) -> bool {
let value = gamepad.get(self.axis.clone()).unwrap_or(0.0);
let last_active = self.active.clone();
if self.above {
if self.active && value < self.lower {
self.active = false;
} else if !self.active && value > self.higher {
self.active = true;
}
} else {
if self.active && value > self.lower {
self.active = false;
} else if !self.active && value < self.higher {
self.active = true;
}
}
if let Some(repeat) = &mut self.repeat {
if last_active != self.active {
repeat.reset();
return self.active;
}
return repeat.is_triggered(self.active, dt);
}
if last_active != self.active {
return self.active;
} else {
return false;
}
}
}