sequence/
sequence.rs

1use bevy_app::{prelude::*, AppExit, ScheduleRunnerPlugin};
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.send_event(AppExit::Success);
23            true
24        }
25    ]));
26}
27
28struct ActionSequence<const N: usize> {
29    actions: [BoxedAction; N],
30    index: usize,
31    canceled: bool,
32}
33
34impl<const N: usize> ActionSequence<N> {
35    fn new(actions: [BoxedAction; N]) -> Self {
36        Self {
37            actions,
38            index: 0,
39            canceled: false,
40        }
41    }
42}
43
44impl<const N: usize> Action for ActionSequence<N> {
45    fn is_finished(&self, agent: Entity, world: &World) -> bool {
46        self.actions[self.index].is_finished(agent, world)
47    }
48
49    fn on_add(&mut self, agent: Entity, world: &mut World) {
50        self.actions
51            .iter_mut()
52            .for_each(|action| action.on_add(agent, world));
53    }
54
55    fn on_start(&mut self, agent: Entity, world: &mut World) -> bool {
56        self.actions[self.index].on_start(agent, world)
57    }
58
59    fn on_stop(&mut self, agent: Option<Entity>, world: &mut World, reason: StopReason) {
60        self.actions[self.index].on_stop(agent, world, reason);
61        self.canceled = reason == StopReason::Canceled;
62    }
63
64    fn on_remove(&mut self, agent: Option<Entity>, world: &mut World) {
65        self.actions[self.index].on_remove(agent, world);
66    }
67
68    fn on_drop(mut self: Box<Self>, agent: Option<Entity>, world: &mut World, reason: DropReason) {
69        self.index += 1;
70
71        if self.index >= N {
72            return;
73        }
74
75        if self.canceled || reason != DropReason::Done {
76            for i in self.index..N {
77                self.actions[i].on_remove(agent, world);
78            }
79            return;
80        }
81
82        let Some(agent) = agent else { return };
83
84        world
85            .actions(agent)
86            .start(false)
87            .order(AddOrder::Front)
88            .add(self as BoxedAction);
89    }
90}
91
92struct PrintAction(&'static str);
93
94impl Action for PrintAction {
95    fn is_finished(&self, _agent: Entity, _world: &World) -> bool {
96        true
97    }
98
99    fn on_start(&mut self, _agent: Entity, _world: &mut World) -> bool {
100        println!("{}", self.0);
101        false
102    }
103
104    fn on_stop(&mut self, _agent: Option<Entity>, _world: &mut World, _reason: StopReason) {}
105}