use crate::prelude::*;
use beet_core::prelude::*;
#[action(repeat)]
#[derive(Debug, Clone, PartialEq, Component, Reflect)]
#[reflect(Default, Component)]
#[require(PreventPropagateEnd)]
pub struct Repeat {
pub if_result_matches: Option<Outcome>,
}
impl Repeat {
pub fn if_success() -> Self {
Self {
if_result_matches: Some(Outcome::Pass),
}
}
pub fn if_failure() -> Self {
Self {
if_result_matches: Some(Outcome::Fail),
}
}
}
impl Default for Repeat {
fn default() -> Self {
Self {
if_result_matches: None,
}
}
}
fn repeat(
ev: On<Outcome>,
query: Query<&Repeat>,
mut commands: Commands,
) -> Result {
let target = ev.target();
let repeat = query.get(target)?;
if let Some(check) = &repeat.if_result_matches {
if *ev != *check {
ChildEnd::trigger(commands, target, ev.event().clone());
return Ok(());
}
}
commands
.entity(target)
.insert(TriggerDeferred::get_outcome());
Ok(())
}
#[cfg(test)]
mod test {
use crate::prelude::*;
use beet_core::prelude::*;
#[test]
fn repeat_always() {
let mut world = ControlFlowPlugin::world();
let on_result = collect_on_result(&mut world);
world
.spawn((Repeat::default(), SucceedTimes::new(2)))
.trigger_target(GetOutcome)
.flush();
on_result.get().len().xpect_eq(1);
world.run_schedule(Update);
on_result.get().len().xpect_eq(2);
world.run_schedule(Update);
on_result.get().len().xpect_eq(3);
world.run_schedule(Update);
on_result.get().len().xpect_eq(4);
world.run_schedule(Update);
on_result.get().len().xpect_eq(5);
}
#[test]
fn repeat_if() {
let mut world = ControlFlowPlugin::world();
let on_result = collect_on_result(&mut world);
world
.spawn((Repeat::if_success(), SucceedTimes::new(2)))
.trigger_target(GetOutcome)
.flush();
on_result.get().len().xpect_eq(1);
world.run_schedule(Update);
on_result.get().len().xpect_eq(2);
world.run_schedule(Update);
on_result.get().len().xpect_eq(3);
world.run_schedule(Update);
on_result.get().len().xpect_eq(3);
world.run_schedule(Update);
on_result.get().len().xpect_eq(3);
}
#[test]
fn repeat_child() {
let mut world = ControlFlowPlugin::world();
let on_result = collect_on_result(&mut world);
world
.spawn((Sequence, children![(
Repeat::if_success(),
SucceedTimes::new(2)
)]))
.trigger_target(GetOutcome)
.flush();
on_result.get().len().xpect_eq(2);
world.run_schedule(Update);
on_result.get().len().xpect_eq(4);
world.run_schedule(Update);
on_result.get().len().xpect_eq(7);
world.run_schedule(Update);
on_result.get().len().xpect_eq(7);
world.run_schedule(Update);
on_result.get().len().xpect_eq(7);
}
}