repeat/
repeat.rs

1use bevy_app::{AppExit, ScheduleRunnerPlugin, prelude::*};
2use bevy_ecs::prelude::*;
3
4use bevy_sequential_actions::*;
5
6fn main() {
7    App::new()
8        .add_plugins((ScheduleRunnerPlugin::default(), SequentialActionsPlugin))
9        .add_systems(Startup, setup)
10        .run();
11}
12
13fn setup(mut commands: Commands) {
14    let agent = commands.spawn(SequentialActions).id();
15    commands.actions(agent).add((
16        RepeatAction {
17            action: PrintAction("hello"),
18            repeat: 3,
19        },
20        RepeatAction {
21            action: PrintAction("world"),
22            repeat: 1,
23        },
24        RepeatAction {
25            action: |agent, world: &mut World| {
26                // Exit app when action queue is empty
27                if world.get::<ActionQueue>(agent).unwrap().is_empty() {
28                    world.write_message(AppExit::Success);
29                }
30
31                // Do not advance action queue immediately,
32                // otherwise we get stuck in an infinite loop
33                // as we keep readding this action
34                false
35            },
36            repeat: u32::MAX,
37        },
38    ));
39}
40
41struct RepeatAction<A: Action> {
42    action: A,
43    repeat: u32,
44}
45
46impl<A: Action> Action for RepeatAction<A> {
47    fn is_finished(&self, agent: Entity, world: &World) -> bool {
48        self.action.is_finished(agent, world)
49    }
50
51    fn on_add(&mut self, agent: Entity, world: &mut World) {
52        self.action.on_add(agent, world);
53    }
54
55    fn on_start(&mut self, agent: Entity, world: &mut World) -> bool {
56        self.action.on_start(agent, world)
57    }
58
59    fn on_stop(&mut self, agent: Option<Entity>, world: &mut World, reason: StopReason) {
60        self.action.on_stop(agent, world, reason);
61    }
62
63    fn on_remove(&mut self, agent: Option<Entity>, world: &mut World) {
64        self.action.on_remove(agent, world);
65    }
66
67    fn on_drop(mut self: Box<Self>, agent: Option<Entity>, world: &mut World, reason: DropReason) {
68        if self.repeat == 0 || reason != DropReason::Done {
69            return;
70        }
71
72        let Some(agent) = agent else { return };
73
74        self.repeat -= 1;
75        world.actions(agent).start(false).add(self as BoxedAction);
76    }
77}
78
79struct PrintAction(&'static str);
80
81impl Action for PrintAction {
82    fn is_finished(&self, _agent: Entity, _world: &World) -> bool {
83        true
84    }
85
86    fn on_start(&mut self, _agent: Entity, _world: &mut World) -> bool {
87        println!("{}", self.0);
88        true
89    }
90
91    fn on_stop(&mut self, _agent: Option<Entity>, _world: &mut World, _reason: StopReason) {}
92}