bevy_steering/
plugin.rs

1use bevy::prelude::*;
2use bitflags::bitflags;
3
4use crate::{
5    behaviors::{
6        alignment,
7        approach::{self, debug_approach},
8        avoid, cohesion,
9        evasion::{self as evasion_behavior, debug_evasion},
10        flee,
11        path_following::{self, debug_path_following},
12        pursuit::{self, debug_pursuit},
13        seek,
14        separation::{self, debug_separation},
15        wander,
16    },
17    control::{
18        combine_steering_targets, debug_combined_steering, debug_forward_dir, temporal_smoothing,
19        update_forward_dir, update_previous_steering_outputs,
20    },
21    movement::{debug_movement, move_agent},
22    neighbors::{debug_neighborhoods, update_neighborhoods},
23    obstacles::{
24        debug_obstacles, setup_obstacle_tracking, update_nearby_obstacles, update_obstacle_tracking,
25    },
26    speed::{debug_speed, reset_speed_override, speed_control},
27};
28
29#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
30pub struct BehaviorSystemSet;
31
32#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
33pub struct SteeringSystemSet;
34
35pub struct SteeringPlugin;
36
37impl Plugin for SteeringPlugin {
38    fn build(&self, app: &mut App) {
39        let behavior_systems = (
40            alignment::run,
41            approach::run,
42            avoid::run,
43            cohesion::run,
44            evasion_behavior::run,
45            flee::run,
46            path_following::run,
47            pursuit::run,
48            seek::run,
49            separation::run,
50            wander::run,
51        )
52            .in_set(BehaviorSystemSet);
53        let update_systems = (
54            update_forward_dir,
55            setup_obstacle_tracking,
56            update_obstacle_tracking,
57            update_nearby_obstacles,
58            update_neighborhoods,
59            behavior_systems,
60            speed_control,
61            temporal_smoothing,
62            update_previous_steering_outputs,
63            combine_steering_targets,
64            move_agent,
65        )
66            .chain()
67            .in_set(SteeringSystemSet);
68        app.add_systems(FixedPreUpdate, reset_speed_override);
69        app.add_systems(FixedUpdate, update_systems);
70    }
71}
72
73#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
74pub struct DebugSteeringSystem;
75
76bitflags! {
77    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
78    pub struct DebugSteeringFlags: u32 {
79        const APPROACH          = 1 << 0;
80        const FORWARD_DIR       = 1 << 1;
81        const OBSTACLES         = 1 << 2;
82        const NEIGHBORHOODS     = 1 << 3;
83        const SEPARATION        = 1 << 4;
84        const EVASION           = 1 << 5;
85        const PURSUIT           = 1 << 6;
86        const PATH_FOLLOWING    = 1 << 7;
87        const SPEED             = 1 << 8;
88        const COMBINED_STEERING = 1 << 9;
89        const MOVEMENT          = 1 << 10;
90    }
91}
92
93#[derive(Resource, Debug, Clone)]
94pub struct DebugSteeringConfig {
95    pub flags: DebugSteeringFlags,
96}
97
98impl Default for DebugSteeringConfig {
99    fn default() -> Self {
100        Self {
101            flags: DebugSteeringFlags::all(),
102        }
103    }
104}
105
106fn flag_enabled(flag: DebugSteeringFlags) -> impl Fn(Res<DebugSteeringConfig>) -> bool {
107    move |config: Res<DebugSteeringConfig>| config.flags.contains(flag)
108}
109
110pub struct DebugSteeringPlugin;
111
112impl Plugin for DebugSteeringPlugin {
113    fn build(&self, app: &mut App) {
114        app.init_resource::<DebugSteeringConfig>();
115
116        app.add_systems(
117            FixedUpdate,
118            (
119                debug_approach.run_if(flag_enabled(DebugSteeringFlags::APPROACH)),
120                debug_forward_dir.run_if(flag_enabled(DebugSteeringFlags::FORWARD_DIR)),
121                debug_obstacles.run_if(flag_enabled(DebugSteeringFlags::OBSTACLES)),
122                debug_neighborhoods.run_if(flag_enabled(DebugSteeringFlags::NEIGHBORHOODS)),
123                debug_separation.run_if(flag_enabled(DebugSteeringFlags::SEPARATION)),
124                debug_evasion.run_if(flag_enabled(DebugSteeringFlags::EVASION)),
125                debug_pursuit.run_if(flag_enabled(DebugSteeringFlags::PURSUIT)),
126                debug_path_following.run_if(flag_enabled(DebugSteeringFlags::PATH_FOLLOWING)),
127                debug_speed.run_if(flag_enabled(DebugSteeringFlags::SPEED)),
128                debug_combined_steering.run_if(flag_enabled(DebugSteeringFlags::COMBINED_STEERING)),
129                debug_movement.run_if(flag_enabled(DebugSteeringFlags::MOVEMENT)),
130            )
131                .in_set(DebugSteeringSystem),
132        );
133    }
134}