bevy_ecs/schedule/
pass.rs

1use alloc::{boxed::Box, vec::Vec};
2use core::{
3    any::{Any, TypeId},
4    fmt::Debug,
5};
6
7use bevy_platform::hash::FixedHasher;
8use bevy_utils::TypeIdMap;
9use indexmap::IndexSet;
10
11use super::{DiGraph, NodeId, ScheduleBuildError, ScheduleGraph};
12use crate::{
13    schedule::{graph::Dag, SystemKey, SystemSetKey},
14    world::World,
15};
16
17/// A pass for modular modification of the dependency graph.
18pub trait ScheduleBuildPass: Send + Sync + Debug + 'static {
19    /// Custom options for dependencies between sets or systems.
20    type EdgeOptions: 'static;
21
22    /// Called when a dependency between sets or systems was explicitly added to the graph.
23    fn add_dependency(&mut self, from: NodeId, to: NodeId, options: Option<&Self::EdgeOptions>);
24
25    /// Called while flattening the dependency graph. For each `set`, this method is called
26    /// with the `systems` associated with the set as well as an immutable reference to the current graph.
27    /// Instead of modifying the graph directly, this method should return an iterator of edges to add to the graph.
28    fn collapse_set(
29        &mut self,
30        set: SystemSetKey,
31        systems: &IndexSet<SystemKey, FixedHasher>,
32        dependency_flattening: &DiGraph<NodeId>,
33    ) -> impl Iterator<Item = (NodeId, NodeId)>;
34
35    /// The implementation will be able to modify the `ScheduleGraph` here.
36    fn build(
37        &mut self,
38        world: &mut World,
39        graph: &mut ScheduleGraph,
40        dependency_flattened: &mut Dag<SystemKey>,
41    ) -> Result<(), ScheduleBuildError>;
42}
43
44/// Object safe version of [`ScheduleBuildPass`].
45pub(super) trait ScheduleBuildPassObj: Send + Sync + Debug {
46    fn build(
47        &mut self,
48        world: &mut World,
49        graph: &mut ScheduleGraph,
50        dependency_flattened: &mut Dag<SystemKey>,
51    ) -> Result<(), ScheduleBuildError>;
52
53    fn collapse_set(
54        &mut self,
55        set: SystemSetKey,
56        systems: &IndexSet<SystemKey, FixedHasher>,
57        dependency_flattening: &DiGraph<NodeId>,
58        dependencies_to_add: &mut Vec<(NodeId, NodeId)>,
59    );
60    fn add_dependency(&mut self, from: NodeId, to: NodeId, all_options: &TypeIdMap<Box<dyn Any>>);
61}
62
63impl<T: ScheduleBuildPass> ScheduleBuildPassObj for T {
64    fn build(
65        &mut self,
66        world: &mut World,
67        graph: &mut ScheduleGraph,
68        dependency_flattened: &mut Dag<SystemKey>,
69    ) -> Result<(), ScheduleBuildError> {
70        self.build(world, graph, dependency_flattened)
71    }
72    fn collapse_set(
73        &mut self,
74        set: SystemSetKey,
75        systems: &IndexSet<SystemKey, FixedHasher>,
76        dependency_flattening: &DiGraph<NodeId>,
77        dependencies_to_add: &mut Vec<(NodeId, NodeId)>,
78    ) {
79        let iter = self.collapse_set(set, systems, dependency_flattening);
80        dependencies_to_add.extend(iter);
81    }
82    fn add_dependency(&mut self, from: NodeId, to: NodeId, all_options: &TypeIdMap<Box<dyn Any>>) {
83        let option = all_options
84            .get(&TypeId::of::<T::EdgeOptions>())
85            .and_then(|x| x.downcast_ref::<T::EdgeOptions>());
86        self.add_dependency(from, to, option);
87    }
88}