use bevy::prelude::*;
use super::DEFAULT_ACTUATION;
use crate::prelude::*;
#[derive(Component, Debug, Clone)]
#[cfg_attr(feature = "reflect", derive(Reflect), reflect(Clone, Component, Debug))]
pub struct Tap {
pub actuation: f32,
pub time_kind: TimeKind,
timer: Timer,
actuated: bool,
}
impl Tap {
#[must_use]
pub fn new(release_time: f32) -> Self {
Self {
actuation: DEFAULT_ACTUATION,
time_kind: Default::default(),
timer: Timer::from_seconds(release_time, TimerMode::Once),
actuated: false,
}
}
#[must_use]
pub fn with_actuation(mut self, actuation: f32) -> Self {
self.actuation = actuation;
self
}
#[must_use]
pub fn with_time_kind(mut self, kind: TimeKind) -> Self {
self.time_kind = kind;
self
}
#[must_use]
pub fn timer(&self) -> &Timer {
&self.timer
}
}
impl InputCondition for Tap {
fn evaluate(
&mut self,
_actions: &ActionsQuery,
time: &ContextTime,
value: ActionValue,
) -> TriggerState {
let last_actuated = self.actuated;
let finished = self.timer.is_finished();
self.actuated = value.is_actuated(self.actuation);
if self.actuated {
self.timer.tick(time.delta_kind(self.time_kind));
} else {
self.timer.reset();
}
if last_actuated && !self.actuated && !finished {
TriggerState::Fired
} else if self.timer.is_finished() {
TriggerState::None
} else if self.actuated {
TriggerState::Ongoing
} else {
TriggerState::None
}
}
}
#[cfg(test)]
mod tests {
use core::time::Duration;
use super::*;
use crate::context;
#[test]
fn tap() {
let (mut world, mut state) = context::init_world();
let (time, actions) = state.get(&world);
let mut condition = Tap::new(1.0);
assert_eq!(
condition.evaluate(&actions, &time, 1.0.into()),
TriggerState::Ongoing,
);
world
.resource_mut::<Time<Real>>()
.advance_by(Duration::from_secs(1));
let (time, actions) = state.get(&world);
assert_eq!(
condition.evaluate(&actions, &time, 0.0.into()),
TriggerState::Fired,
);
world
.resource_mut::<Time<Real>>()
.advance_by(Duration::ZERO);
let (time, actions) = state.get(&world);
assert_eq!(
condition.evaluate(&actions, &time, 0.0.into()),
TriggerState::None
);
world
.resource_mut::<Time<Real>>()
.advance_by(Duration::from_secs(2));
let (time, actions) = state.get(&world);
assert_eq!(
condition.evaluate(&actions, &time, 1.0.into()),
TriggerState::None
);
}
}