@@ -7,9 +7,9 @@ use crate::{
7
7
component:: ComponentId ,
8
8
entity:: { Entities , Entity } ,
9
9
system:: { RunSystemWithInput , SystemId } ,
10
+ world:: command_queue:: RawCommandQueue ,
10
11
world:: { Command , CommandQueue , EntityWorldMut , FromWorld , World } ,
11
12
} ;
12
- use bevy_ecs_macros:: SystemParam ;
13
13
use bevy_utils:: tracing:: { error, info} ;
14
14
pub use parallel_scope:: * ;
15
15
use std:: marker:: PhantomData ;
@@ -65,12 +65,84 @@ use std::marker::PhantomData;
65
65
/// ```
66
66
///
67
67
/// [`apply_deferred`]: crate::schedule::apply_deferred
68
- #[ derive( SystemParam ) ]
69
68
pub struct Commands < ' w , ' s > {
70
- queue : Deferred < ' s , CommandQueue > ,
69
+ queue : InternalQueue < ' s > ,
71
70
entities : & ' w Entities ,
72
71
}
73
72
73
+ const _: ( ) = {
74
+ type __StructFieldsAlias < ' w , ' s > = ( Deferred < ' s , CommandQueue > , & ' w Entities ) ;
75
+ #[ doc( hidden) ]
76
+ pub struct FetchState {
77
+ state : <__StructFieldsAlias < ' static , ' static > as bevy_ecs:: system:: SystemParam >:: State ,
78
+ }
79
+ // SAFETY: Only reads Entities
80
+ unsafe impl bevy_ecs:: system:: SystemParam for Commands < ' _ , ' _ > {
81
+ type State = FetchState ;
82
+ type Item < ' w , ' s > = Commands < ' w , ' s > ;
83
+ fn init_state (
84
+ world : & mut bevy_ecs:: world:: World ,
85
+ system_meta : & mut bevy_ecs:: system:: SystemMeta ,
86
+ ) -> Self :: State {
87
+ FetchState {
88
+ state : <__StructFieldsAlias < ' _ , ' _ > as bevy_ecs:: system:: SystemParam >:: init_state (
89
+ world,
90
+ system_meta,
91
+ ) ,
92
+ }
93
+ }
94
+ unsafe fn new_archetype (
95
+ state : & mut Self :: State ,
96
+ archetype : & bevy_ecs:: archetype:: Archetype ,
97
+ system_meta : & mut bevy_ecs:: system:: SystemMeta ,
98
+ ) {
99
+ // SAFETY: Caller guarantees the archetype is from the world used in `init_state`
100
+ unsafe {
101
+ <__StructFieldsAlias < ' _ , ' _ > as bevy_ecs:: system:: SystemParam >:: new_archetype (
102
+ & mut state. state ,
103
+ archetype,
104
+ system_meta,
105
+ ) ;
106
+ } ;
107
+ }
108
+ fn apply (
109
+ state : & mut Self :: State ,
110
+ system_meta : & bevy_ecs:: system:: SystemMeta ,
111
+ world : & mut bevy_ecs:: world:: World ,
112
+ ) {
113
+ <__StructFieldsAlias < ' _ , ' _ > as bevy_ecs:: system:: SystemParam >:: apply (
114
+ & mut state. state ,
115
+ system_meta,
116
+ world,
117
+ ) ;
118
+ }
119
+ unsafe fn get_param < ' w , ' s > (
120
+ state : & ' s mut Self :: State ,
121
+ system_meta : & bevy_ecs:: system:: SystemMeta ,
122
+ world : bevy_ecs:: world:: unsafe_world_cell:: UnsafeWorldCell < ' w > ,
123
+ change_tick : bevy_ecs:: component:: Tick ,
124
+ ) -> Self :: Item < ' w , ' s > {
125
+ let ( f0, f1, ) = <( Deferred < ' s , CommandQueue > , & ' w Entities , ) as bevy_ecs:: system:: SystemParam > :: get_param ( & mut state. state , system_meta, world, change_tick) ;
126
+ Commands {
127
+ queue : InternalQueue :: CommandQueue ( f0) ,
128
+ entities : f1,
129
+ }
130
+ }
131
+ }
132
+ // SAFETY: Only reads Entities
133
+ unsafe impl < ' w , ' s > bevy_ecs:: system:: ReadOnlySystemParam for Commands < ' w , ' s >
134
+ where
135
+ Deferred < ' s , CommandQueue > : bevy_ecs:: system:: ReadOnlySystemParam ,
136
+ & ' w Entities : bevy_ecs:: system:: ReadOnlySystemParam ,
137
+ {
138
+ }
139
+ } ;
140
+
141
+ enum InternalQueue < ' s > {
142
+ CommandQueue ( Deferred < ' s , CommandQueue > ) ,
143
+ RawCommandQueue ( RawCommandQueue ) ,
144
+ }
145
+
74
146
impl < ' w , ' s > Commands < ' w , ' s > {
75
147
/// Returns a new `Commands` instance from a [`CommandQueue`] and a [`World`].
76
148
///
@@ -88,7 +160,24 @@ impl<'w, 's> Commands<'w, 's> {
88
160
/// [system parameter]: crate::system::SystemParam
89
161
pub fn new_from_entities ( queue : & ' s mut CommandQueue , entities : & ' w Entities ) -> Self {
90
162
Self {
91
- queue : Deferred ( queue) ,
163
+ queue : InternalQueue :: CommandQueue ( Deferred ( queue) ) ,
164
+ entities,
165
+ }
166
+ }
167
+
168
+ /// Returns a new `Commands` instance from a [`RawCommandQueue`] and an [`Entities`] reference.
169
+ ///
170
+ /// This is used when constructing [`Commands`] from a [`DeferredWorld`](crate::world::DeferredWorld).
171
+ ///
172
+ /// # Safety
173
+ ///
174
+ /// * Caller ensures that `queue` must outlive 'w
175
+ pub ( crate ) unsafe fn new_raw_from_entities (
176
+ queue : RawCommandQueue ,
177
+ entities : & ' w Entities ,
178
+ ) -> Self {
179
+ Self {
180
+ queue : InternalQueue :: RawCommandQueue ( queue) ,
92
181
entities,
93
182
}
94
183
}
@@ -113,14 +202,25 @@ impl<'w, 's> Commands<'w, 's> {
113
202
/// ```
114
203
pub fn reborrow ( & mut self ) -> Commands < ' w , ' _ > {
115
204
Commands {
116
- queue : self . queue . reborrow ( ) ,
205
+ queue : match & mut self . queue {
206
+ InternalQueue :: CommandQueue ( queue) => InternalQueue :: CommandQueue ( queue. reborrow ( ) ) ,
207
+ InternalQueue :: RawCommandQueue ( queue) => {
208
+ InternalQueue :: RawCommandQueue ( queue. clone ( ) )
209
+ }
210
+ } ,
117
211
entities : self . entities ,
118
212
}
119
213
}
120
214
121
215
/// Take all commands from `other` and append them to `self`, leaving `other` empty
122
216
pub fn append ( & mut self , other : & mut CommandQueue ) {
123
- self . queue . append ( other) ;
217
+ match & mut self . queue {
218
+ InternalQueue :: CommandQueue ( queue) => queue. bytes . append ( & mut other. bytes ) ,
219
+ InternalQueue :: RawCommandQueue ( queue) => {
220
+ // SAFETY: Pointers in `RawCommandQueue` are never null
221
+ unsafe { queue. bytes . as_mut ( ) } . append ( & mut other. bytes ) ;
222
+ }
223
+ }
124
224
}
125
225
126
226
/// Pushes a [`Command`] to the queue for creating a new empty [`Entity`],
@@ -381,7 +481,23 @@ impl<'w, 's> Commands<'w, 's> {
381
481
I : IntoIterator + Send + Sync + ' static ,
382
482
I :: Item : Bundle ,
383
483
{
384
- self . queue . push ( spawn_batch ( bundles_iter) ) ;
484
+ self . push ( spawn_batch ( bundles_iter) ) ;
485
+ }
486
+
487
+ /// Push a [`Command`] onto the queue.
488
+ pub fn push < C : Command > ( & mut self , command : C ) {
489
+ match & mut self . queue {
490
+ InternalQueue :: CommandQueue ( queue) => {
491
+ queue. push ( command) ;
492
+ }
493
+ InternalQueue :: RawCommandQueue ( queue) => {
494
+ // SAFETY: `RawCommandQueue` is only every constructed in `Commands::new_raw_from_entities`
495
+ // where the caller of that has ensured that `queue` outlives `self`
496
+ unsafe {
497
+ queue. push ( command) ;
498
+ }
499
+ }
500
+ }
385
501
}
386
502
387
503
/// Pushes a [`Command`] to the queue for creating entities, if needed,
@@ -410,7 +526,7 @@ impl<'w, 's> Commands<'w, 's> {
410
526
I : IntoIterator < Item = ( Entity , B ) > + Send + Sync + ' static ,
411
527
B : Bundle ,
412
528
{
413
- self . queue . push ( insert_or_spawn_batch ( bundles_iter) ) ;
529
+ self . push ( insert_or_spawn_batch ( bundles_iter) ) ;
414
530
}
415
531
416
532
/// Pushes a [`Command`] to the queue for inserting a [`Resource`] in the [`World`] with an inferred value.
@@ -438,7 +554,7 @@ impl<'w, 's> Commands<'w, 's> {
438
554
/// # bevy_ecs::system::assert_is_system(initialise_scoreboard);
439
555
/// ```
440
556
pub fn init_resource < R : Resource + FromWorld > ( & mut self ) {
441
- self . queue . push ( init_resource :: < R > ) ;
557
+ self . push ( init_resource :: < R > ) ;
442
558
}
443
559
444
560
/// Pushes a [`Command`] to the queue for inserting a [`Resource`] in the [`World`] with a specific value.
@@ -467,7 +583,7 @@ impl<'w, 's> Commands<'w, 's> {
467
583
/// # bevy_ecs::system::assert_is_system(system);
468
584
/// ```
469
585
pub fn insert_resource < R : Resource > ( & mut self , resource : R ) {
470
- self . queue . push ( insert_resource ( resource) ) ;
586
+ self . push ( insert_resource ( resource) ) ;
471
587
}
472
588
473
589
/// Pushes a [`Command`] to the queue for removing a [`Resource`] from the [`World`].
@@ -491,7 +607,7 @@ impl<'w, 's> Commands<'w, 's> {
491
607
/// # bevy_ecs::system::assert_is_system(system);
492
608
/// ```
493
609
pub fn remove_resource < R : Resource > ( & mut self ) {
494
- self . queue . push ( remove_resource :: < R > ) ;
610
+ self . push ( remove_resource :: < R > ) ;
495
611
}
496
612
497
613
/// Runs the system corresponding to the given [`SystemId`].
@@ -517,8 +633,7 @@ impl<'w, 's> Commands<'w, 's> {
517
633
/// execution of the system happens later. To get the output of a system, use
518
634
/// [`World::run_system`] or [`World::run_system_with_input`] instead of running the system as a command.
519
635
pub fn run_system_with_input < I : ' static + Send > ( & mut self , id : SystemId < I > , input : I ) {
520
- self . queue
521
- . push ( RunSystemWithInput :: new_with_input ( id, input) ) ;
636
+ self . push ( RunSystemWithInput :: new_with_input ( id, input) ) ;
522
637
}
523
638
524
639
/// Registers a system and returns a [`SystemId`] so it can later be called by [`World::run_system`].
@@ -580,7 +695,7 @@ impl<'w, 's> Commands<'w, 's> {
580
695
system : S ,
581
696
) -> SystemId < I , O > {
582
697
let entity = self . spawn_empty ( ) . id ( ) ;
583
- self . queue . push ( RegisterSystem :: new ( system, entity) ) ;
698
+ self . push ( RegisterSystem :: new ( system, entity) ) ;
584
699
SystemId :: from_entity ( entity)
585
700
}
586
701
@@ -618,7 +733,7 @@ impl<'w, 's> Commands<'w, 's> {
618
733
/// # bevy_ecs::system::assert_is_system(add_twenty_five_to_counter_system);
619
734
/// ```
620
735
pub fn add < C : Command > ( & mut self , command : C ) {
621
- self . queue . push ( command) ;
736
+ self . push ( command) ;
622
737
}
623
738
}
624
739
0 commit comments