sequence/
sequence.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(ActionSequence::new(actions![
16        PrintAction("see"),
17        PrintAction("you"),
18        PrintAction("in"),
19        PrintAction("space"),
20        PrintAction("cowboy"),
21        |_agent, world: &mut World| -> bool {
22            world.write_message(AppExit::Success);
23            true
24        }
25    ]));
26}
27
28struct ActionSequence<const N: usize> {
29    actions: [BoxedAction; N],
30    index: usize,
31}
32
33impl<const N: usize> ActionSequence<N> {
34    fn new(actions: [BoxedAction; N]) -> Self {
35        Self { actions, index: 0 }
36    }
37}
38
39impl<const N: usize> Action for ActionSequence<N> {
40    fn is_finished(&self, agent: Entity, world: &World) -> bool {
41        self.actions[self.index].is_finished(agent, world)
42    }
43
44    fn on_add(&mut self, agent: Entity, world: &mut World) {
45        self.actions
46            .iter_mut()
47            .for_each(|action| action.on_add(agent, world));
48    }
49
50    fn on_start(&mut self, agent: Entity, world: &mut World) -> bool {
51        self.actions[self.index].on_start(agent, world)
52    }
53
54    fn on_stop(&mut self, agent: Option<Entity>, world: &mut World, reason: StopReason) {
55        self.actions[self.index].on_stop(agent, world, reason);
56
57        if reason == StopReason::Canceled {
58            self.index = N;
59        }
60    }
61
62    fn on_drop(mut self: Box<Self>, agent: Option<Entity>, world: &mut World, reason: DropReason) {
63        self.index += 1;
64
65        if self.index >= N || reason != DropReason::Done {
66            self.actions
67                .iter_mut()
68                .for_each(|action| action.on_remove(agent, world));
69            return;
70        }
71
72        let Some(agent) = agent else { return };
73
74        world
75            .get_mut::<ActionQueue>(agent)
76            .unwrap()
77            .push_front(self);
78    }
79}
80
81struct PrintAction(&'static str);
82
83impl Action for PrintAction {
84    fn is_finished(&self, _agent: Entity, _world: &World) -> bool {
85        true
86    }
87
88    fn on_start(&mut self, _agent: Entity, _world: &mut World) -> bool {
89        println!("{}", self.0);
90        false
91    }
92
93    fn on_stop(&mut self, _agent: Option<Entity>, _world: &mut World, _reason: StopReason) {}
94}