1use alloc::{boxed::Box, vec::Vec};
2use bevy_utils::prelude::DebugName;
3use core::{
4 any::TypeId,
5 fmt::{self, Debug},
6 ops::{Index, IndexMut, Range},
7};
8
9use bevy_platform::collections::HashMap;
10use slotmap::{new_key_type, Key, KeyData, SecondaryMap, SlotMap};
11
12use crate::{
13 component::{CheckChangeTicks, Tick},
14 prelude::{SystemIn, SystemSet},
15 query::FilteredAccessSet,
16 schedule::{
17 graph::{Direction, GraphNodeId},
18 BoxedCondition, InternedSystemSet,
19 },
20 system::{
21 ReadOnlySystem, RunSystemError, ScheduleSystem, System, SystemParamValidationError,
22 SystemStateFlags,
23 },
24 world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World},
25};
26
27pub(crate) struct SystemNode {
29 pub(crate) inner: Option<SystemWithAccess>,
30}
31
32pub struct SystemWithAccess {
34 pub system: ScheduleSystem,
36 pub access: FilteredAccessSet,
39}
40
41impl SystemWithAccess {
42 pub fn new(system: ScheduleSystem) -> Self {
45 Self {
46 system,
47 access: FilteredAccessSet::new(),
48 }
49 }
50}
51
52impl System for SystemWithAccess {
53 type In = ();
54 type Out = ();
55
56 #[inline]
57 fn name(&self) -> DebugName {
58 self.system.name()
59 }
60
61 #[inline]
62 fn type_id(&self) -> TypeId {
63 self.system.type_id()
64 }
65
66 #[inline]
67 fn flags(&self) -> SystemStateFlags {
68 self.system.flags()
69 }
70
71 #[inline]
72 unsafe fn run_unsafe(
73 &mut self,
74 input: SystemIn<'_, Self>,
75 world: UnsafeWorldCell,
76 ) -> Result<Self::Out, RunSystemError> {
77 unsafe { self.system.run_unsafe(input, world) }
79 }
80
81 #[cfg(feature = "hotpatching")]
82 #[inline]
83 fn refresh_hotpatch(&mut self) {
84 self.system.refresh_hotpatch();
85 }
86
87 #[inline]
88 fn apply_deferred(&mut self, world: &mut World) {
89 self.system.apply_deferred(world);
90 }
91
92 #[inline]
93 fn queue_deferred(&mut self, world: DeferredWorld) {
94 self.system.queue_deferred(world);
95 }
96
97 #[inline]
98 unsafe fn validate_param_unsafe(
99 &mut self,
100 world: UnsafeWorldCell,
101 ) -> Result<(), SystemParamValidationError> {
102 unsafe { self.system.validate_param_unsafe(world) }
104 }
105
106 #[inline]
107 fn initialize(&mut self, world: &mut World) -> FilteredAccessSet {
108 self.system.initialize(world)
109 }
110
111 #[inline]
112 fn check_change_tick(&mut self, check: CheckChangeTicks) {
113 self.system.check_change_tick(check);
114 }
115
116 #[inline]
117 fn default_system_sets(&self) -> Vec<InternedSystemSet> {
118 self.system.default_system_sets()
119 }
120
121 #[inline]
122 fn get_last_run(&self) -> Tick {
123 self.system.get_last_run()
124 }
125
126 #[inline]
127 fn set_last_run(&mut self, last_run: Tick) {
128 self.system.set_last_run(last_run);
129 }
130}
131
132pub struct ConditionWithAccess {
134 pub condition: BoxedCondition,
136 pub access: FilteredAccessSet,
139}
140
141impl ConditionWithAccess {
142 pub const fn new(condition: BoxedCondition) -> Self {
145 Self {
146 condition,
147 access: FilteredAccessSet::new(),
148 }
149 }
150}
151
152impl System for ConditionWithAccess {
153 type In = ();
154 type Out = bool;
155
156 #[inline]
157 fn name(&self) -> DebugName {
158 self.condition.name()
159 }
160
161 #[inline]
162 fn type_id(&self) -> TypeId {
163 self.condition.type_id()
164 }
165
166 #[inline]
167 fn flags(&self) -> SystemStateFlags {
168 self.condition.flags()
169 }
170
171 #[inline]
172 unsafe fn run_unsafe(
173 &mut self,
174 input: SystemIn<'_, Self>,
175 world: UnsafeWorldCell,
176 ) -> Result<Self::Out, RunSystemError> {
177 unsafe { self.condition.run_unsafe(input, world) }
179 }
180
181 #[cfg(feature = "hotpatching")]
182 #[inline]
183 fn refresh_hotpatch(&mut self) {
184 self.condition.refresh_hotpatch();
185 }
186
187 #[inline]
188 fn apply_deferred(&mut self, world: &mut World) {
189 self.condition.apply_deferred(world);
190 }
191
192 #[inline]
193 fn queue_deferred(&mut self, world: DeferredWorld) {
194 self.condition.queue_deferred(world);
195 }
196
197 #[inline]
198 unsafe fn validate_param_unsafe(
199 &mut self,
200 world: UnsafeWorldCell,
201 ) -> Result<(), SystemParamValidationError> {
202 unsafe { self.condition.validate_param_unsafe(world) }
204 }
205
206 #[inline]
207 fn initialize(&mut self, world: &mut World) -> FilteredAccessSet {
208 self.condition.initialize(world)
209 }
210
211 #[inline]
212 fn check_change_tick(&mut self, check: CheckChangeTicks) {
213 self.condition.check_change_tick(check);
214 }
215
216 #[inline]
217 fn default_system_sets(&self) -> Vec<InternedSystemSet> {
218 self.condition.default_system_sets()
219 }
220
221 #[inline]
222 fn get_last_run(&self) -> Tick {
223 self.condition.get_last_run()
224 }
225
226 #[inline]
227 fn set_last_run(&mut self, last_run: Tick) {
228 self.condition.set_last_run(last_run);
229 }
230}
231
232impl SystemNode {
233 pub fn new(system: ScheduleSystem) -> Self {
235 Self {
236 inner: Some(SystemWithAccess::new(system)),
237 }
238 }
239
240 pub fn get(&self) -> Option<&SystemWithAccess> {
242 self.inner.as_ref()
243 }
244
245 pub fn get_mut(&mut self) -> Option<&mut SystemWithAccess> {
247 self.inner.as_mut()
248 }
249}
250
251new_key_type! {
252 pub struct SystemKey;
254 pub struct SystemSetKey;
256}
257
258impl GraphNodeId for SystemKey {
259 type Adjacent = (SystemKey, Direction);
260 type Edge = (SystemKey, SystemKey);
261
262 fn kind(&self) -> &'static str {
263 "system"
264 }
265}
266
267impl GraphNodeId for SystemSetKey {
268 type Adjacent = (SystemSetKey, Direction);
269 type Edge = (SystemSetKey, SystemSetKey);
270
271 fn kind(&self) -> &'static str {
272 "system set"
273 }
274}
275
276impl TryFrom<NodeId> for SystemKey {
277 type Error = SystemSetKey;
278
279 fn try_from(value: NodeId) -> Result<Self, Self::Error> {
280 match value {
281 NodeId::System(key) => Ok(key),
282 NodeId::Set(key) => Err(key),
283 }
284 }
285}
286
287impl TryFrom<NodeId> for SystemSetKey {
288 type Error = SystemKey;
289
290 fn try_from(value: NodeId) -> Result<Self, Self::Error> {
291 match value {
292 NodeId::System(key) => Err(key),
293 NodeId::Set(key) => Ok(key),
294 }
295 }
296}
297
298#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
302pub enum NodeId {
303 System(SystemKey),
305 Set(SystemSetKey),
307}
308
309impl NodeId {
310 pub const fn is_system(&self) -> bool {
312 matches!(self, NodeId::System(_))
313 }
314
315 pub const fn is_set(&self) -> bool {
317 matches!(self, NodeId::Set(_))
318 }
319
320 pub const fn as_system(&self) -> Option<SystemKey> {
322 match self {
323 NodeId::System(system) => Some(*system),
324 NodeId::Set(_) => None,
325 }
326 }
327
328 pub const fn as_set(&self) -> Option<SystemSetKey> {
330 match self {
331 NodeId::System(_) => None,
332 NodeId::Set(set) => Some(*set),
333 }
334 }
335}
336
337impl GraphNodeId for NodeId {
338 type Adjacent = CompactNodeIdAndDirection;
339 type Edge = CompactNodeIdPair;
340
341 fn kind(&self) -> &'static str {
342 match self {
343 NodeId::System(n) => n.kind(),
344 NodeId::Set(n) => n.kind(),
345 }
346 }
347}
348
349impl From<SystemKey> for NodeId {
350 fn from(system: SystemKey) -> Self {
351 NodeId::System(system)
352 }
353}
354
355impl From<SystemSetKey> for NodeId {
356 fn from(set: SystemSetKey) -> Self {
357 NodeId::Set(set)
358 }
359}
360
361#[derive(Clone, Copy)]
363pub struct CompactNodeIdAndDirection {
364 key: KeyData,
365 is_system: bool,
366 direction: Direction,
367}
368
369impl Debug for CompactNodeIdAndDirection {
370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
371 let tuple: (_, _) = (*self).into();
372 tuple.fmt(f)
373 }
374}
375
376impl From<(NodeId, Direction)> for CompactNodeIdAndDirection {
377 fn from((id, direction): (NodeId, Direction)) -> Self {
378 let key = match id {
379 NodeId::System(key) => key.data(),
380 NodeId::Set(key) => key.data(),
381 };
382 let is_system = id.is_system();
383
384 Self {
385 key,
386 is_system,
387 direction,
388 }
389 }
390}
391
392impl From<CompactNodeIdAndDirection> for (NodeId, Direction) {
393 fn from(value: CompactNodeIdAndDirection) -> Self {
394 let node = match value.is_system {
395 true => NodeId::System(value.key.into()),
396 false => NodeId::Set(value.key.into()),
397 };
398
399 (node, value.direction)
400 }
401}
402
403#[derive(Clone, Copy, Hash, PartialEq, Eq)]
405pub struct CompactNodeIdPair {
406 key_a: KeyData,
407 key_b: KeyData,
408 is_system_a: bool,
409 is_system_b: bool,
410}
411
412impl Debug for CompactNodeIdPair {
413 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414 let tuple: (_, _) = (*self).into();
415 tuple.fmt(f)
416 }
417}
418
419impl From<(NodeId, NodeId)> for CompactNodeIdPair {
420 fn from((a, b): (NodeId, NodeId)) -> Self {
421 let key_a = match a {
422 NodeId::System(index) => index.data(),
423 NodeId::Set(index) => index.data(),
424 };
425 let is_system_a = a.is_system();
426
427 let key_b = match b {
428 NodeId::System(index) => index.data(),
429 NodeId::Set(index) => index.data(),
430 };
431 let is_system_b = b.is_system();
432
433 Self {
434 key_a,
435 key_b,
436 is_system_a,
437 is_system_b,
438 }
439 }
440}
441
442impl From<CompactNodeIdPair> for (NodeId, NodeId) {
443 fn from(value: CompactNodeIdPair) -> Self {
444 let a = match value.is_system_a {
445 true => NodeId::System(value.key_a.into()),
446 false => NodeId::Set(value.key_a.into()),
447 };
448
449 let b = match value.is_system_b {
450 true => NodeId::System(value.key_b.into()),
451 false => NodeId::Set(value.key_b.into()),
452 };
453
454 (a, b)
455 }
456}
457
458#[derive(Default)]
460pub struct Systems {
461 nodes: SlotMap<SystemKey, SystemNode>,
463 conditions: SecondaryMap<SystemKey, Vec<ConditionWithAccess>>,
465 uninit: Vec<SystemKey>,
467}
468
469impl Systems {
470 pub fn len(&self) -> usize {
472 self.nodes.len()
473 }
474
475 pub fn is_empty(&self) -> bool {
477 self.nodes.is_empty()
478 }
479
480 pub fn get(&self, key: SystemKey) -> Option<&SystemWithAccess> {
482 self.nodes.get(key).and_then(|node| node.get())
483 }
484
485 pub fn get_mut(&mut self, key: SystemKey) -> Option<&mut SystemWithAccess> {
487 self.nodes.get_mut(key).and_then(|node| node.get_mut())
488 }
489
490 pub(crate) fn node_mut(&mut self, key: SystemKey) -> &mut SystemNode {
497 &mut self.nodes[key]
498 }
499
500 pub fn has_conditions(&self, key: SystemKey) -> bool {
502 self.conditions
503 .get(key)
504 .is_some_and(|conditions| !conditions.is_empty())
505 }
506
507 pub fn get_conditions(&self, key: SystemKey) -> Option<&[ConditionWithAccess]> {
509 self.conditions.get(key).map(Vec::as_slice)
510 }
511
512 pub fn get_conditions_mut(&mut self, key: SystemKey) -> Option<&mut Vec<ConditionWithAccess>> {
514 self.conditions.get_mut(key)
515 }
516
517 pub fn iter(
520 &self,
521 ) -> impl Iterator<Item = (SystemKey, &ScheduleSystem, &[ConditionWithAccess])> + '_ {
522 self.nodes.iter().filter_map(|(key, node)| {
523 let system = &node.get()?.system;
524 let conditions = self
525 .conditions
526 .get(key)
527 .map(Vec::as_slice)
528 .unwrap_or_default();
529 Some((key, system, conditions))
530 })
531 }
532
533 pub fn insert(
541 &mut self,
542 system: ScheduleSystem,
543 conditions: Vec<Box<dyn ReadOnlySystem<In = (), Out = bool>>>,
544 ) -> SystemKey {
545 let key = self.nodes.insert(SystemNode::new(system));
546 self.conditions.insert(
547 key,
548 conditions
549 .into_iter()
550 .map(ConditionWithAccess::new)
551 .collect(),
552 );
553 self.uninit.push(key);
554 key
555 }
556
557 pub fn is_initialized(&self) -> bool {
559 self.uninit.is_empty()
560 }
561
562 pub fn initialize(&mut self, world: &mut World) {
565 for key in self.uninit.drain(..) {
566 let Some(system) = self.nodes.get_mut(key).and_then(|node| node.get_mut()) else {
567 continue;
568 };
569 system.access = system.system.initialize(world);
570 let Some(conditions) = self.conditions.get_mut(key) else {
571 continue;
572 };
573 for condition in conditions {
574 condition.access = condition.condition.initialize(world);
575 }
576 }
577 }
578}
579
580impl Index<SystemKey> for Systems {
581 type Output = SystemWithAccess;
582
583 #[track_caller]
584 fn index(&self, key: SystemKey) -> &Self::Output {
585 self.get(key)
586 .unwrap_or_else(|| panic!("System with key {:?} does not exist in the schedule", key))
587 }
588}
589
590impl IndexMut<SystemKey> for Systems {
591 #[track_caller]
592 fn index_mut(&mut self, key: SystemKey) -> &mut Self::Output {
593 self.get_mut(key)
594 .unwrap_or_else(|| panic!("System with key {:?} does not exist in the schedule", key))
595 }
596}
597
598#[derive(Default)]
600pub struct SystemSets {
601 sets: SlotMap<SystemSetKey, InternedSystemSet>,
603 conditions: SecondaryMap<SystemSetKey, Vec<ConditionWithAccess>>,
605 ids: HashMap<InternedSystemSet, SystemSetKey>,
607 uninit: Vec<UninitializedSet>,
609}
610
611struct UninitializedSet {
613 key: SystemSetKey,
614 uninitialized_conditions: Range<usize>,
626}
627
628impl SystemSets {
629 pub fn len(&self) -> usize {
631 self.sets.len()
632 }
633
634 pub fn is_empty(&self) -> bool {
636 self.sets.is_empty()
637 }
638
639 pub fn contains(&self, set: impl SystemSet) -> bool {
641 self.ids.contains_key(&set.intern())
642 }
643
644 pub fn get(&self, key: SystemSetKey) -> Option<&dyn SystemSet> {
646 self.sets.get(key).map(|set| &**set)
647 }
648
649 pub fn get_key_or_insert(&mut self, set: InternedSystemSet) -> SystemSetKey {
652 *self.ids.entry(set).or_insert_with(|| {
653 let key = self.sets.insert(set);
654 self.conditions.insert(key, Vec::new());
655 key
656 })
657 }
658
659 pub fn has_conditions(&self, key: SystemSetKey) -> bool {
661 self.conditions
662 .get(key)
663 .is_some_and(|conditions| !conditions.is_empty())
664 }
665
666 pub fn get_conditions(&self, key: SystemSetKey) -> Option<&[ConditionWithAccess]> {
669 self.conditions.get(key).map(Vec::as_slice)
670 }
671
672 pub fn get_conditions_mut(
675 &mut self,
676 key: SystemSetKey,
677 ) -> Option<&mut Vec<ConditionWithAccess>> {
678 self.conditions.get_mut(key)
679 }
680
681 pub fn iter(
684 &self,
685 ) -> impl Iterator<Item = (SystemSetKey, &dyn SystemSet, &[ConditionWithAccess])> {
686 self.sets.iter().filter_map(|(key, set)| {
687 let conditions = self.conditions.get(key)?.as_slice();
688 Some((key, &**set, conditions))
689 })
690 }
691
692 pub fn insert(
702 &mut self,
703 set: InternedSystemSet,
704 new_conditions: Vec<Box<dyn ReadOnlySystem<In = (), Out = bool>>>,
705 ) -> SystemSetKey {
706 let key = self.get_key_or_insert(set);
707 if !new_conditions.is_empty() {
708 let current_conditions = &mut self.conditions[key];
709 let start = current_conditions.len();
710 self.uninit.push(UninitializedSet {
711 key,
712 uninitialized_conditions: start..(start + new_conditions.len()),
713 });
714 current_conditions.extend(new_conditions.into_iter().map(ConditionWithAccess::new));
715 }
716 key
717 }
718
719 pub fn is_initialized(&self) -> bool {
722 self.uninit.is_empty()
723 }
724
725 pub fn initialize(&mut self, world: &mut World) {
730 for uninit in self.uninit.drain(..) {
731 let Some(conditions) = self.conditions.get_mut(uninit.key) else {
732 continue;
733 };
734 for condition in &mut conditions[uninit.uninitialized_conditions] {
735 condition.access = condition.initialize(world);
736 }
737 }
738 }
739}
740
741impl Index<SystemSetKey> for SystemSets {
742 type Output = dyn SystemSet;
743
744 #[track_caller]
745 fn index(&self, key: SystemSetKey) -> &Self::Output {
746 self.get(key).unwrap_or_else(|| {
747 panic!(
748 "System set with key {:?} does not exist in the schedule",
749 key
750 )
751 })
752 }
753}
754
755#[cfg(test)]
756mod tests {
757 use alloc::{boxed::Box, vec};
758
759 use crate::{
760 prelude::SystemSet,
761 schedule::{SystemSets, Systems},
762 system::IntoSystem,
763 world::World,
764 };
765
766 #[derive(SystemSet, Clone, Copy, PartialEq, Eq, Debug, Hash)]
767 pub struct TestSet;
768
769 #[test]
770 fn systems() {
771 fn empty_system() {}
772
773 let mut systems = Systems::default();
774 assert!(systems.is_empty());
775 assert_eq!(systems.len(), 0);
776
777 let system = Box::new(IntoSystem::into_system(empty_system));
778 let key = systems.insert(system, vec![]);
779
780 assert!(!systems.is_empty());
781 assert_eq!(systems.len(), 1);
782 assert!(systems.get(key).is_some());
783 assert!(systems.get_conditions(key).is_some());
784 assert!(systems.get_conditions(key).unwrap().is_empty());
785 assert!(systems.get_mut(key).is_some());
786 assert!(!systems.is_initialized());
787 assert!(systems.iter().next().is_some());
788
789 let mut world = World::new();
790 systems.initialize(&mut world);
791 assert!(systems.is_initialized());
792 }
793
794 #[test]
795 fn system_sets() {
796 fn always_true() -> bool {
797 true
798 }
799
800 let mut sets = SystemSets::default();
801 assert!(sets.is_empty());
802 assert_eq!(sets.len(), 0);
803
804 let condition = Box::new(IntoSystem::into_system(always_true));
805 let key = sets.insert(TestSet.intern(), vec![condition]);
806
807 assert!(!sets.is_empty());
808 assert_eq!(sets.len(), 1);
809 assert!(sets.get(key).is_some());
810 assert!(sets.get_conditions(key).is_some());
811 assert!(!sets.get_conditions(key).unwrap().is_empty());
812 assert!(!sets.is_initialized());
813 assert!(sets.iter().next().is_some());
814
815 let mut world = World::new();
816 sets.initialize(&mut world);
817 assert!(sets.is_initialized());
818 }
819}