@@ -15,6 +15,7 @@ use bevy_utils::{default, prelude::DebugName, TypeIdMap};
15
15
use core:: {
16
16
any:: { Any , TypeId } ,
17
17
fmt:: { Debug , Write } ,
18
+ ops:: Range ,
18
19
} ;
19
20
use fixedbitset:: FixedBitSet ;
20
21
use log:: { error, info, warn} ;
@@ -752,11 +753,31 @@ new_key_type! {
752
753
pub struct SystemSetKey ;
753
754
}
754
755
756
+ /// A node in a [`ScheduleGraph`] with a system or conditions that have not been
757
+ /// initialized yet.
758
+ ///
759
+ /// We have to defer initialization of nodes in the graph until we have
760
+ /// `&mut World` access, so we store these in a list ([`ScheduleGraph::uninit`])
761
+ /// until then. In most cases, initialization occurs upon the first run of the
762
+ /// schedule.
755
763
enum UninitializedId {
764
+ /// A system and its conditions that have not been initialized yet.
756
765
System ( SystemKey ) ,
766
+ /// A system set's conditions that have not been initialized yet.
757
767
Set {
758
768
key : SystemSetKey ,
759
- first_uninit_condition : usize ,
769
+ /// The range of indices in [`SystemSets::conditions`] that correspond
770
+ /// to conditions that have not been initialized yet.
771
+ ///
772
+ /// [`SystemSets::conditions`] for a given set may be appended to
773
+ /// multiple times (e.g. when `configure_sets` is called multiple with
774
+ /// the same set), so we need to track which conditions in that list
775
+ /// are newly added and not yet initialized.
776
+ ///
777
+ /// Systems don't need this tracking because each `add_systems` call
778
+ /// creates separate nodes in the graph with their own conditions,
779
+ /// so all conditions are initialized together.
780
+ uninitialized_conditions : Range < usize > ,
760
781
} ,
761
782
}
762
783
@@ -793,8 +814,8 @@ pub struct ScheduleGraph {
793
814
pub system_conditions : SecondaryMap < SystemKey , Vec < ConditionWithAccess > > ,
794
815
/// Data about system sets in the schedule
795
816
system_sets : SystemSets ,
796
- /// Systems that have not been initialized yet; for system sets, we store the index of the first uninitialized condition
797
- /// (all the conditions after that index still need to be initialized)
817
+ /// Systems, their conditions, and system set conditions that need to be
818
+ /// initialized before the schedule can be run.
798
819
uninit : Vec < UninitializedId > ,
799
820
/// Directed acyclic graph of the hierarchy (which systems/sets are children of which sets)
800
821
hierarchy : Dag ,
@@ -807,7 +828,6 @@ pub struct ScheduleGraph {
807
828
anonymous_sets : usize ,
808
829
changed : bool ,
809
830
settings : ScheduleBuildSettings ,
810
-
811
831
passes : BTreeMap < TypeId , Box < dyn ScheduleBuildPassObj > > ,
812
832
}
813
833
@@ -1101,9 +1121,10 @@ impl ScheduleGraph {
1101
1121
1102
1122
// system init has to be deferred (need `&mut World`)
1103
1123
let system_set_conditions = self . system_sets . conditions . entry ( key) . unwrap ( ) . or_default ( ) ;
1124
+ let start = system_set_conditions. len ( ) ;
1104
1125
self . uninit . push ( UninitializedId :: Set {
1105
1126
key,
1106
- first_uninit_condition : system_set_conditions . len ( ) ,
1127
+ uninitialized_conditions : start.. ( start + conditions . len ( ) ) ,
1107
1128
} ) ;
1108
1129
system_set_conditions. extend ( conditions. into_iter ( ) . map ( ConditionWithAccess :: new) ) ;
1109
1130
@@ -1189,11 +1210,9 @@ impl ScheduleGraph {
1189
1210
}
1190
1211
UninitializedId :: Set {
1191
1212
key,
1192
- first_uninit_condition ,
1213
+ uninitialized_conditions ,
1193
1214
} => {
1194
- for condition in self . system_sets . conditions [ key]
1195
- . iter_mut ( )
1196
- . skip ( first_uninit_condition)
1215
+ for condition in & mut self . system_sets . conditions [ key] [ uninitialized_conditions]
1197
1216
{
1198
1217
condition. access = condition. condition . initialize ( world) ;
1199
1218
}
0 commit comments