bevy_ecs/schedule/
pass.rs1use alloc::{boxed::Box, vec::Vec};
2use core::{
3 any::{Any, TypeId},
4 fmt::Debug,
5 ops::Deref,
6};
7
8use bevy_platform::{collections::HashSet, hash::FixedHasher};
9use bevy_utils::TypeIdMap;
10use indexmap::IndexSet;
11
12use super::{DiGraph, NodeId, ScheduleBuildError, ScheduleGraph};
13use crate::{
14 schedule::{
15 graph::{Dag, DagAnalysis, DiGraphToposortError},
16 SystemKey, SystemSetKey,
17 },
18 world::World,
19};
20
21pub trait ScheduleBuildPass: Send + Sync + Debug + 'static {
23 type EdgeOptions: 'static;
25
26 fn add_dependency(&mut self, from: NodeId, to: NodeId, options: Option<&Self::EdgeOptions>);
28
29 fn collapse_set(
33 &mut self,
34 set: SystemSetKey,
35 systems: &IndexSet<SystemKey, FixedHasher>,
36 dependency_flattening: &DiGraph<NodeId>,
37 ) -> impl Iterator<Item = (NodeId, NodeId)>;
38
39 fn build(
41 &mut self,
42 world: &mut World,
43 graph: &mut ScheduleGraph,
44 dependency_flattened: FlattenedDependencies<'_>,
45 ) -> Result<(), ScheduleBuildError>;
46}
47
48pub struct FlattenedDependencies<'a> {
52 pub(crate) dag: &'a mut Dag<SystemKey>,
54 pub(crate) added_edges: &'a mut HashSet<(SystemKey, SystemKey)>,
56}
57
58impl Deref for FlattenedDependencies<'_> {
59 type Target = Dag<SystemKey>;
60
61 fn deref(&self) -> &Self::Target {
62 self.dag
63 }
64}
65
66impl FlattenedDependencies<'_> {
67 pub fn add_edge(&mut self, system_1: SystemKey, system_2: SystemKey) {
69 self.dag.add_edge(system_1, system_2);
70 self.added_edges.insert((system_1, system_2));
71 }
72
73 pub fn remove_edge(&mut self, system_1: SystemKey, system_2: SystemKey) {
81 self.dag.remove_edge(system_1, system_2);
82 }
88
89 pub fn toposort(&mut self) -> Result<&[SystemKey], DiGraphToposortError<SystemKey>> {
93 self.dag.toposort()
94 }
95
96 pub fn toposort_and_graph(
101 &mut self,
102 ) -> Result<(&[SystemKey], &DiGraph<SystemKey>), DiGraphToposortError<SystemKey>> {
103 self.dag.toposort_and_graph()
104 }
105
106 pub fn analyze(&mut self) -> Result<DagAnalysis<SystemKey>, DiGraphToposortError<SystemKey>> {
110 self.dag.analyze()
111 }
112}
113
114pub(super) trait ScheduleBuildPassObj: Send + Sync + Debug {
116 fn build(
117 &mut self,
118 world: &mut World,
119 graph: &mut ScheduleGraph,
120 dependency_flattened: FlattenedDependencies<'_>,
121 ) -> Result<(), ScheduleBuildError>;
122
123 fn collapse_set(
124 &mut self,
125 set: SystemSetKey,
126 systems: &IndexSet<SystemKey, FixedHasher>,
127 dependency_flattening: &DiGraph<NodeId>,
128 dependencies_to_add: &mut Vec<(NodeId, NodeId)>,
129 );
130 fn add_dependency(&mut self, from: NodeId, to: NodeId, all_options: &TypeIdMap<Box<dyn Any>>);
131}
132
133impl<T: ScheduleBuildPass> ScheduleBuildPassObj for T {
134 fn build(
135 &mut self,
136 world: &mut World,
137 graph: &mut ScheduleGraph,
138 dependency_flattened: FlattenedDependencies<'_>,
139 ) -> Result<(), ScheduleBuildError> {
140 self.build(world, graph, dependency_flattened)
141 }
142 fn collapse_set(
143 &mut self,
144 set: SystemSetKey,
145 systems: &IndexSet<SystemKey, FixedHasher>,
146 dependency_flattening: &DiGraph<NodeId>,
147 dependencies_to_add: &mut Vec<(NodeId, NodeId)>,
148 ) {
149 let iter = self.collapse_set(set, systems, dependency_flattening);
150 dependencies_to_add.extend(iter);
151 }
152 fn add_dependency(&mut self, from: NodeId, to: NodeId, all_options: &TypeIdMap<Box<dyn Any>>) {
153 let option = all_options
154 .get(&TypeId::of::<T::EdgeOptions>())
155 .and_then(|x| x.downcast_ref::<T::EdgeOptions>());
156 self.add_dependency(from, to, option);
157 }
158}