use crate::prelude::*;
use beet_core::prelude::*;
#[derive(Debug, Clone, Component, Reflect)]
#[require(ContinueRun)]
pub struct EndInDuration<T> {
pub duration: Duration,
pub event: T,
}
impl<T> Default for EndInDuration<T>
where
T: Default,
{
fn default() -> Self { Self::new(default(), Duration::from_secs(1)) }
}
impl<T> EndInDuration<T> {
pub fn new(event: T, duration: Duration) -> Self {
Self { event, duration }
}
}
impl EndInDuration<Outcome> {
pub fn pass(duration: Duration) -> Self {
Self::new(Outcome::Pass, duration)
}
pub fn fail(duration: Duration) -> Self {
Self::new(Outcome::Fail, duration)
}
}
pub(crate) fn end_in_duration<T: EndEvent>(
mut commands: Commands,
mut query: Populated<
(Entity, &RunTimer, &mut EndInDuration<T>),
With<Running>,
>,
) {
for (entity, timer, action) in query.iter_mut() {
if timer.last_run.elapsed() >= action.duration {
commands.entity(entity).trigger_target(action.event.clone());
}
}
}
#[cfg(test)]
mod test {
use crate::prelude::*;
use beet_core::prelude::*;
#[test]
fn works() {
let mut app = App::new();
app.add_plugins(ControlFlowPlugin::default()).insert_time();
let on_result =
observer_ext::observe_triggers::<Outcome>(app.world_mut());
app.world_mut()
.spawn((Running, EndInDuration::pass(Duration::from_secs(2))));
app.update_with_secs(1);
on_result.is_empty().xpect_true();
app.update_with_secs(10);
on_result.is_empty().xpect_false();
}
}