Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/schedule/node.rs
6849 views
1
use alloc::{boxed::Box, vec::Vec};
2
use bevy_utils::prelude::DebugName;
3
use core::{
4
any::TypeId,
5
fmt::{self, Debug},
6
ops::{Index, IndexMut, Range},
7
};
8
9
use bevy_platform::collections::HashMap;
10
use slotmap::{new_key_type, Key, KeyData, SecondaryMap, SlotMap};
11
12
use 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
27
/// A [`SystemWithAccess`] stored in a [`ScheduleGraph`](crate::schedule::ScheduleGraph).
28
pub(crate) struct SystemNode {
29
pub(crate) inner: Option<SystemWithAccess>,
30
}
31
32
/// A [`ScheduleSystem`] stored alongside the access returned from [`System::initialize`].
33
pub struct SystemWithAccess {
34
/// The system itself.
35
pub system: ScheduleSystem,
36
/// The access returned by [`System::initialize`].
37
/// This will be empty if the system has not been initialized yet.
38
pub access: FilteredAccessSet,
39
}
40
41
impl SystemWithAccess {
42
/// Constructs a new [`SystemWithAccess`] from a [`ScheduleSystem`].
43
/// The `access` will initially be empty.
44
pub fn new(system: ScheduleSystem) -> Self {
45
Self {
46
system,
47
access: FilteredAccessSet::new(),
48
}
49
}
50
}
51
52
impl 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
// SAFETY: Caller ensures the same safety requirements.
78
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
// SAFETY: Caller ensures the same safety requirements.
103
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
132
/// A [`BoxedCondition`] stored alongside the access returned from [`System::initialize`].
133
pub struct ConditionWithAccess {
134
/// The condition itself.
135
pub condition: BoxedCondition,
136
/// The access returned by [`System::initialize`].
137
/// This will be empty if the system has not been initialized yet.
138
pub access: FilteredAccessSet,
139
}
140
141
impl ConditionWithAccess {
142
/// Constructs a new [`ConditionWithAccess`] from a [`BoxedCondition`].
143
/// The `access` will initially be empty.
144
pub const fn new(condition: BoxedCondition) -> Self {
145
Self {
146
condition,
147
access: FilteredAccessSet::new(),
148
}
149
}
150
}
151
152
impl 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
// SAFETY: Caller ensures the same safety requirements.
178
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
// SAFETY: Caller ensures the same safety requirements.
203
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
232
impl SystemNode {
233
/// Create a new [`SystemNode`]
234
pub fn new(system: ScheduleSystem) -> Self {
235
Self {
236
inner: Some(SystemWithAccess::new(system)),
237
}
238
}
239
240
/// Obtain a reference to the [`SystemWithAccess`] represented by this node.
241
pub fn get(&self) -> Option<&SystemWithAccess> {
242
self.inner.as_ref()
243
}
244
245
/// Obtain a mutable reference to the [`SystemWithAccess`] represented by this node.
246
pub fn get_mut(&mut self) -> Option<&mut SystemWithAccess> {
247
self.inner.as_mut()
248
}
249
}
250
251
new_key_type! {
252
/// A unique identifier for a system in a [`ScheduleGraph`].
253
pub struct SystemKey;
254
/// A unique identifier for a system set in a [`ScheduleGraph`].
255
pub struct SystemSetKey;
256
}
257
258
impl 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
267
impl 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
276
impl 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
287
impl 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
/// Unique identifier for a system or system set stored in a [`ScheduleGraph`].
299
///
300
/// [`ScheduleGraph`]: crate::schedule::ScheduleGraph
301
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
302
pub enum NodeId {
303
/// Identifier for a system.
304
System(SystemKey),
305
/// Identifier for a system set.
306
Set(SystemSetKey),
307
}
308
309
impl NodeId {
310
/// Returns `true` if the identified node is a system.
311
pub const fn is_system(&self) -> bool {
312
matches!(self, NodeId::System(_))
313
}
314
315
/// Returns `true` if the identified node is a system set.
316
pub const fn is_set(&self) -> bool {
317
matches!(self, NodeId::Set(_))
318
}
319
320
/// Returns the system key if the node is a system, otherwise `None`.
321
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
/// Returns the system set key if the node is a system set, otherwise `None`.
329
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
337
impl 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
349
impl From<SystemKey> for NodeId {
350
fn from(system: SystemKey) -> Self {
351
NodeId::System(system)
352
}
353
}
354
355
impl From<SystemSetKey> for NodeId {
356
fn from(set: SystemSetKey) -> Self {
357
NodeId::Set(set)
358
}
359
}
360
361
/// Compact storage of a [`NodeId`] and a [`Direction`].
362
#[derive(Clone, Copy)]
363
pub struct CompactNodeIdAndDirection {
364
key: KeyData,
365
is_system: bool,
366
direction: Direction,
367
}
368
369
impl 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
376
impl 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
392
impl 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
/// Compact storage of a [`NodeId`] pair.
404
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
405
pub struct CompactNodeIdPair {
406
key_a: KeyData,
407
key_b: KeyData,
408
is_system_a: bool,
409
is_system_b: bool,
410
}
411
412
impl 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
419
impl 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
442
impl 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
/// Container for systems in a schedule.
459
#[derive(Default)]
460
pub struct Systems {
461
/// List of systems in the schedule.
462
nodes: SlotMap<SystemKey, SystemNode>,
463
/// List of conditions for each system, in the same order as `nodes`.
464
conditions: SecondaryMap<SystemKey, Vec<ConditionWithAccess>>,
465
/// Systems and their conditions that have not been initialized yet.
466
uninit: Vec<SystemKey>,
467
}
468
469
impl Systems {
470
/// Returns the number of systems in this container.
471
pub fn len(&self) -> usize {
472
self.nodes.len()
473
}
474
475
/// Returns `true` if this container is empty.
476
pub fn is_empty(&self) -> bool {
477
self.nodes.is_empty()
478
}
479
480
/// Returns a reference to the system with the given key, if it exists.
481
pub fn get(&self, key: SystemKey) -> Option<&SystemWithAccess> {
482
self.nodes.get(key).and_then(|node| node.get())
483
}
484
485
/// Returns a mutable reference to the system with the given key, if it exists.
486
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
/// Returns a mutable reference to the system with the given key, panicking
491
/// if it does not exist.
492
///
493
/// # Panics
494
///
495
/// If the system with the given key does not exist in this container.
496
pub(crate) fn node_mut(&mut self, key: SystemKey) -> &mut SystemNode {
497
&mut self.nodes[key]
498
}
499
500
/// Returns `true` if the system with the given key has conditions.
501
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
/// Returns a reference to the conditions for the system with the given key, if it exists.
508
pub fn get_conditions(&self, key: SystemKey) -> Option<&[ConditionWithAccess]> {
509
self.conditions.get(key).map(Vec::as_slice)
510
}
511
512
/// Returns a mutable reference to the conditions for the system with the given key, if it exists.
513
pub fn get_conditions_mut(&mut self, key: SystemKey) -> Option<&mut Vec<ConditionWithAccess>> {
514
self.conditions.get_mut(key)
515
}
516
517
/// Returns an iterator over all systems and their conditions in this
518
/// container.
519
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
/// Inserts a new system into the container, along with its conditions,
534
/// and queues it to be initialized later in [`Systems::initialize`].
535
///
536
/// We have to defer initialization of systems in the container until we have
537
/// `&mut World` access, so we store these in a list until
538
/// [`Systems::initialize`] is called. This is usually done upon the first
539
/// run of the schedule.
540
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
/// Returns `true` if all systems in this container have been initialized.
558
pub fn is_initialized(&self) -> bool {
559
self.uninit.is_empty()
560
}
561
562
/// Initializes all systems and their conditions that have not been
563
/// initialized yet.
564
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
580
impl 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
590
impl 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
/// Container for system sets in a schedule.
599
#[derive(Default)]
600
pub struct SystemSets {
601
/// List of system sets in the schedule.
602
sets: SlotMap<SystemSetKey, InternedSystemSet>,
603
/// List of conditions for each system set, in the same order as `sets`.
604
conditions: SecondaryMap<SystemSetKey, Vec<ConditionWithAccess>>,
605
/// Map from system sets to their keys.
606
ids: HashMap<InternedSystemSet, SystemSetKey>,
607
/// System sets that have not been initialized yet.
608
uninit: Vec<UninitializedSet>,
609
}
610
611
/// A system set's conditions that have not been initialized yet.
612
struct UninitializedSet {
613
key: SystemSetKey,
614
/// The range of indices in [`SystemSets::conditions`] that correspond
615
/// to conditions that have not been initialized yet.
616
///
617
/// [`SystemSets::conditions`] for a given set may be appended to
618
/// multiple times (e.g. when `configure_sets` is called multiple with
619
/// the same set), so we need to track which conditions in that list
620
/// are newly added and not yet initialized.
621
///
622
/// Systems don't need this tracking because each `add_systems` call
623
/// creates separate nodes in the graph with their own conditions,
624
/// so all conditions are initialized together.
625
uninitialized_conditions: Range<usize>,
626
}
627
628
impl SystemSets {
629
/// Returns the number of system sets in this container.
630
pub fn len(&self) -> usize {
631
self.sets.len()
632
}
633
634
/// Returns `true` if this container is empty.
635
pub fn is_empty(&self) -> bool {
636
self.sets.is_empty()
637
}
638
639
/// Returns `true` if the given set is present in this container.
640
pub fn contains(&self, set: impl SystemSet) -> bool {
641
self.ids.contains_key(&set.intern())
642
}
643
644
/// Returns a reference to the system set with the given key, if it exists.
645
pub fn get(&self, key: SystemSetKey) -> Option<&dyn SystemSet> {
646
self.sets.get(key).map(|set| &**set)
647
}
648
649
/// Returns the key for the given system set, inserting it into this
650
/// container if it does not already exist.
651
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
/// Returns `true` if the system set with the given key has conditions.
660
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
/// Returns a reference to the conditions for the system set with the given
667
/// key, if it exists.
668
pub fn get_conditions(&self, key: SystemSetKey) -> Option<&[ConditionWithAccess]> {
669
self.conditions.get(key).map(Vec::as_slice)
670
}
671
672
/// Returns a mutable reference to the conditions for the system set with
673
/// the given key, if it exists.
674
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
/// Returns an iterator over all system sets in this container, along with
682
/// their conditions.
683
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
/// Inserts conditions for a system set into the container, and queues the
693
/// newly added conditions to be initialized later in [`SystemSets::initialize`].
694
///
695
/// If the set was not already present in the container, it is added automatically.
696
///
697
/// We have to defer initialization of system set conditions in the container
698
/// until we have `&mut World` access, so we store these in a list until
699
/// [`SystemSets::initialize`] is called. This is usually done upon the
700
/// first run of the schedule.
701
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
/// Returns `true` if all system sets' conditions in this container have
720
/// been initialized.
721
pub fn is_initialized(&self) -> bool {
722
self.uninit.is_empty()
723
}
724
725
/// Initializes all system sets' conditions that have not been
726
/// initialized yet. Because a system set's conditions may be appended to
727
/// multiple times, we track which conditions were added since the last
728
/// initialization and only initialize those.
729
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
741
impl 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)]
756
mod 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
}
820
821