Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/system/system_param.rs
6604 views
1
pub use crate::change_detection::{NonSendMut, Res, ResMut};
2
use crate::{
3
archetype::Archetypes,
4
bundle::Bundles,
5
change_detection::{MaybeLocation, Ticks, TicksMut},
6
component::{ComponentId, ComponentTicks, Components, Tick},
7
entity::Entities,
8
query::{
9
Access, FilteredAccess, FilteredAccessSet, QueryData, QueryFilter, QuerySingleError,
10
QueryState, ReadOnlyQueryData,
11
},
12
resource::Resource,
13
storage::ResourceData,
14
system::{Query, Single, SystemMeta},
15
world::{
16
unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FilteredResources, FilteredResourcesMut,
17
FromWorld, World,
18
},
19
};
20
use alloc::{
21
borrow::{Cow, ToOwned},
22
boxed::Box,
23
vec::Vec,
24
};
25
pub use bevy_ecs_macros::SystemParam;
26
use bevy_platform::cell::SyncCell;
27
use bevy_ptr::UnsafeCellDeref;
28
use bevy_utils::prelude::DebugName;
29
use core::{
30
any::Any,
31
fmt::{Debug, Display},
32
marker::PhantomData,
33
ops::{Deref, DerefMut},
34
panic::Location,
35
};
36
use thiserror::Error;
37
38
use super::Populated;
39
use variadics_please::{all_tuples, all_tuples_enumerated};
40
41
/// A parameter that can be used in a [`System`](super::System).
42
///
43
/// # Derive
44
///
45
/// This trait can be derived with the [`derive@super::SystemParam`] macro.
46
/// This macro only works if each field on the derived struct implements [`SystemParam`].
47
/// Note: There are additional requirements on the field types.
48
/// See the *Generic `SystemParam`s* section for details and workarounds of the probable
49
/// cause if this derive causes an error to be emitted.
50
///
51
/// Derived `SystemParam` structs may have two lifetimes: `'w` for data stored in the [`World`],
52
/// and `'s` for data stored in the parameter's state.
53
///
54
/// The following list shows the most common [`SystemParam`]s and which lifetime they require
55
///
56
/// ```
57
/// # use bevy_ecs::prelude::*;
58
/// # #[derive(Component)]
59
/// # struct SomeComponent;
60
/// # #[derive(Resource)]
61
/// # struct SomeResource;
62
/// # #[derive(BufferedEvent)]
63
/// # struct SomeEvent;
64
/// # #[derive(Resource)]
65
/// # struct SomeOtherResource;
66
/// # use bevy_ecs::system::SystemParam;
67
/// # #[derive(SystemParam)]
68
/// # struct ParamsExample<'w, 's> {
69
/// # query:
70
/// Query<'w, 's, Entity>,
71
/// # query2:
72
/// Query<'w, 's, &'static SomeComponent>,
73
/// # res:
74
/// Res<'w, SomeResource>,
75
/// # res_mut:
76
/// ResMut<'w, SomeOtherResource>,
77
/// # local:
78
/// Local<'s, u8>,
79
/// # commands:
80
/// Commands<'w, 's>,
81
/// # eventreader:
82
/// EventReader<'w, 's, SomeEvent>,
83
/// # eventwriter:
84
/// EventWriter<'w, SomeEvent>
85
/// # }
86
/// ```
87
/// ## `PhantomData`
88
///
89
/// [`PhantomData`] is a special type of `SystemParam` that does nothing.
90
/// This is useful for constraining generic types or lifetimes.
91
///
92
/// # Example
93
///
94
/// ```
95
/// # use bevy_ecs::prelude::*;
96
/// # #[derive(Resource)]
97
/// # struct SomeResource;
98
/// use std::marker::PhantomData;
99
/// use bevy_ecs::system::SystemParam;
100
///
101
/// #[derive(SystemParam)]
102
/// struct MyParam<'w, Marker: 'static> {
103
/// foo: Res<'w, SomeResource>,
104
/// marker: PhantomData<Marker>,
105
/// }
106
///
107
/// fn my_system<T: 'static>(param: MyParam<T>) {
108
/// // Access the resource through `param.foo`
109
/// }
110
///
111
/// # bevy_ecs::system::assert_is_system(my_system::<()>);
112
/// ```
113
///
114
/// # Generic `SystemParam`s
115
///
116
/// When using the derive macro, you may see an error in the form of:
117
///
118
/// ```text
119
/// expected ... [ParamType]
120
/// found associated type `<[ParamType] as SystemParam>::Item<'_, '_>`
121
/// ```
122
/// where `[ParamType]` is the type of one of your fields.
123
/// To solve this error, you can wrap the field of type `[ParamType]` with [`StaticSystemParam`]
124
/// (i.e. `StaticSystemParam<[ParamType]>`).
125
///
126
/// ## Details
127
///
128
/// The derive macro requires that the [`SystemParam`] implementation of
129
/// each field `F`'s [`Item`](`SystemParam::Item`)'s is itself `F`
130
/// (ignoring lifetimes for simplicity).
131
/// This assumption is due to type inference reasons, so that the derived [`SystemParam`] can be
132
/// used as an argument to a function system.
133
/// If the compiler cannot validate this property for `[ParamType]`, it will error in the form shown above.
134
///
135
/// This will most commonly occur when working with `SystemParam`s generically, as the requirement
136
/// has not been proven to the compiler.
137
///
138
/// ## Custom Validation Messages
139
///
140
/// When using the derive macro, any [`SystemParamValidationError`]s will be propagated from the sub-parameters.
141
/// If you want to override the error message, add a `#[system_param(validation_message = "New message")]` attribute to the parameter.
142
///
143
/// ```
144
/// # use bevy_ecs::prelude::*;
145
/// # #[derive(Resource)]
146
/// # struct SomeResource;
147
/// # use bevy_ecs::system::SystemParam;
148
/// #
149
/// #[derive(SystemParam)]
150
/// struct MyParam<'w> {
151
/// #[system_param(validation_message = "Custom Message")]
152
/// foo: Res<'w, SomeResource>,
153
/// }
154
///
155
/// let mut world = World::new();
156
/// let err = world.run_system_cached(|param: MyParam| {}).unwrap_err();
157
/// let expected = "Parameter `MyParam::foo` failed validation: Custom Message";
158
/// # #[cfg(feature="Trace")] // Without debug_utils/debug enabled MyParam::foo is stripped and breaks the assert
159
/// assert!(err.to_string().contains(expected));
160
/// ```
161
///
162
/// ## Builders
163
///
164
/// If you want to use a [`SystemParamBuilder`](crate::system::SystemParamBuilder) with a derived [`SystemParam`] implementation,
165
/// add a `#[system_param(builder)]` attribute to the struct.
166
/// This will generate a builder struct whose name is the param struct suffixed with `Builder`.
167
/// The builder will not be `pub`, so you may want to expose a method that returns an `impl SystemParamBuilder<T>`.
168
///
169
/// ```
170
/// mod custom_param {
171
/// # use bevy_ecs::{
172
/// # prelude::*,
173
/// # system::{LocalBuilder, QueryParamBuilder, SystemParam},
174
/// # };
175
/// #
176
/// #[derive(SystemParam)]
177
/// #[system_param(builder)]
178
/// pub struct CustomParam<'w, 's> {
179
/// query: Query<'w, 's, ()>,
180
/// local: Local<'s, usize>,
181
/// }
182
///
183
/// impl<'w, 's> CustomParam<'w, 's> {
184
/// pub fn builder(
185
/// local: usize,
186
/// query: impl FnOnce(&mut QueryBuilder<()>),
187
/// ) -> impl SystemParamBuilder<Self> {
188
/// CustomParamBuilder {
189
/// local: LocalBuilder(local),
190
/// query: QueryParamBuilder::new(query),
191
/// }
192
/// }
193
/// }
194
/// }
195
///
196
/// use custom_param::CustomParam;
197
///
198
/// # use bevy_ecs::prelude::*;
199
/// # #[derive(Component)]
200
/// # struct A;
201
/// #
202
/// # let mut world = World::new();
203
/// #
204
/// let system = (CustomParam::builder(100, |builder| {
205
/// builder.with::<A>();
206
/// }),)
207
/// .build_state(&mut world)
208
/// .build_system(|param: CustomParam| {});
209
/// ```
210
///
211
/// # Safety
212
///
213
/// The implementor must ensure the following is true.
214
/// - [`SystemParam::init_access`] correctly registers all [`World`] accesses used
215
/// by [`SystemParam::get_param`] with the provided [`system_meta`](SystemMeta).
216
/// - None of the world accesses may conflict with any prior accesses registered
217
/// on `system_meta`.
218
pub unsafe trait SystemParam: Sized {
219
/// Used to store data which persists across invocations of a system.
220
type State: Send + Sync + 'static;
221
222
/// The item type returned when constructing this system param.
223
/// The value of this associated type should be `Self`, instantiated with new lifetimes.
224
///
225
/// You could think of [`SystemParam::Item<'w, 's>`] as being an *operation* that changes the lifetimes bound to `Self`.
226
type Item<'world, 'state>: SystemParam<State = Self::State>;
227
228
/// Creates a new instance of this param's [`State`](SystemParam::State).
229
fn init_state(world: &mut World) -> Self::State;
230
231
/// Registers any [`World`] access used by this [`SystemParam`]
232
fn init_access(
233
state: &Self::State,
234
system_meta: &mut SystemMeta,
235
component_access_set: &mut FilteredAccessSet,
236
world: &mut World,
237
);
238
239
/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
240
/// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
241
///
242
/// [`Commands`]: crate::prelude::Commands
243
#[inline]
244
#[expect(
245
unused_variables,
246
reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
247
)]
248
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}
249
250
/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
251
#[inline]
252
#[expect(
253
unused_variables,
254
reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
255
)]
256
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}
257
258
/// Validates that the param can be acquired by the [`get_param`](SystemParam::get_param).
259
///
260
/// Built-in executors use this to prevent systems with invalid params from running,
261
/// and any failures here will be bubbled up to the default error handler defined in [`bevy_ecs::error`],
262
/// with a value of type [`SystemParamValidationError`].
263
///
264
/// For nested [`SystemParam`]s validation will fail if any
265
/// delegated validation fails.
266
///
267
/// However calling and respecting [`SystemParam::validate_param`]
268
/// is not a strict requirement, [`SystemParam::get_param`] should
269
/// provide it's own safety mechanism to prevent undefined behavior.
270
///
271
/// The [`world`](UnsafeWorldCell) can only be used to read param's data
272
/// and world metadata. No data can be written.
273
///
274
/// When using system parameters that require `change_tick` you can use
275
/// [`UnsafeWorldCell::change_tick()`]. Even if this isn't the exact
276
/// same tick used for [`SystemParam::get_param`], the world access
277
/// ensures that the queried data will be the same in both calls.
278
///
279
/// This method has to be called directly before [`SystemParam::get_param`] with no other (relevant)
280
/// world mutations inbetween. Otherwise, while it won't lead to any undefined behavior,
281
/// the validity of the param may change.
282
///
283
/// [`System::validate_param`](super::system::System::validate_param),
284
/// calls this method for each supplied system param.
285
///
286
/// # Safety
287
///
288
/// - The passed [`UnsafeWorldCell`] must have read-only access to world data
289
/// registered in [`init_access`](SystemParam::init_access).
290
/// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state).
291
#[expect(
292
unused_variables,
293
reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
294
)]
295
unsafe fn validate_param(
296
state: &mut Self::State,
297
system_meta: &SystemMeta,
298
world: UnsafeWorldCell,
299
) -> Result<(), SystemParamValidationError> {
300
Ok(())
301
}
302
303
/// Creates a parameter to be passed into a [`SystemParamFunction`](super::SystemParamFunction).
304
///
305
/// # Safety
306
///
307
/// - The passed [`UnsafeWorldCell`] must have access to any world data registered
308
/// in [`init_access`](SystemParam::init_access).
309
/// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state).
310
unsafe fn get_param<'world, 'state>(
311
state: &'state mut Self::State,
312
system_meta: &SystemMeta,
313
world: UnsafeWorldCell<'world>,
314
change_tick: Tick,
315
) -> Self::Item<'world, 'state>;
316
}
317
318
/// A [`SystemParam`] that only reads a given [`World`].
319
///
320
/// # Safety
321
/// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParam::get_param`]
322
pub unsafe trait ReadOnlySystemParam: SystemParam {}
323
324
/// Shorthand way of accessing the associated type [`SystemParam::Item`] for a given [`SystemParam`].
325
pub type SystemParamItem<'w, 's, P> = <P as SystemParam>::Item<'w, 's>;
326
327
// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
328
unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
329
for Query<'w, 's, D, F>
330
{
331
}
332
333
// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
334
// this Query conflicts with any prior access, a panic will occur.
335
unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Query<'_, '_, D, F> {
336
type State = QueryState<D, F>;
337
type Item<'w, 's> = Query<'w, 's, D, F>;
338
339
fn init_state(world: &mut World) -> Self::State {
340
QueryState::new(world)
341
}
342
343
fn init_access(
344
state: &Self::State,
345
system_meta: &mut SystemMeta,
346
component_access_set: &mut FilteredAccessSet,
347
world: &mut World,
348
) {
349
assert_component_access_compatibility(
350
&system_meta.name,
351
DebugName::type_name::<D>(),
352
DebugName::type_name::<F>(),
353
component_access_set,
354
&state.component_access,
355
world,
356
);
357
component_access_set.add(state.component_access.clone());
358
}
359
360
#[inline]
361
unsafe fn get_param<'w, 's>(
362
state: &'s mut Self::State,
363
system_meta: &SystemMeta,
364
world: UnsafeWorldCell<'w>,
365
change_tick: Tick,
366
) -> Self::Item<'w, 's> {
367
// SAFETY: We have registered all of the query's world accesses,
368
// so the caller ensures that `world` has permission to access any
369
// world data that the query needs.
370
// The caller ensures the world matches the one used in init_state.
371
unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) }
372
}
373
}
374
375
fn assert_component_access_compatibility(
376
system_name: &DebugName,
377
query_type: DebugName,
378
filter_type: DebugName,
379
system_access: &FilteredAccessSet,
380
current: &FilteredAccess,
381
world: &World,
382
) {
383
let conflicts = system_access.get_conflicts_single(current);
384
if conflicts.is_empty() {
385
return;
386
}
387
let mut accesses = conflicts.format_conflict_list(world);
388
// Access list may be empty (if access to all components requested)
389
if !accesses.is_empty() {
390
accesses.push(' ');
391
}
392
panic!("error[B0001]: Query<{}, {}> in system {system_name} accesses component(s) {accesses}in a way that conflicts with a previous system parameter. Consider using `Without<T>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevy.org/learn/errors/b0001", query_type.shortname(), filter_type.shortname());
393
}
394
395
// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
396
// this Query conflicts with any prior access, a panic will occur.
397
unsafe impl<'a, 'b, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
398
for Single<'a, 'b, D, F>
399
{
400
type State = QueryState<D, F>;
401
type Item<'w, 's> = Single<'w, 's, D, F>;
402
403
fn init_state(world: &mut World) -> Self::State {
404
Query::init_state(world)
405
}
406
407
fn init_access(
408
state: &Self::State,
409
system_meta: &mut SystemMeta,
410
component_access_set: &mut FilteredAccessSet,
411
world: &mut World,
412
) {
413
Query::init_access(state, system_meta, component_access_set, world);
414
}
415
416
#[inline]
417
unsafe fn get_param<'w, 's>(
418
state: &'s mut Self::State,
419
system_meta: &SystemMeta,
420
world: UnsafeWorldCell<'w>,
421
change_tick: Tick,
422
) -> Self::Item<'w, 's> {
423
// SAFETY: State ensures that the components it accesses are not accessible somewhere elsewhere.
424
// The caller ensures the world matches the one used in init_state.
425
let query =
426
unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) };
427
let single = query
428
.single_inner()
429
.expect("The query was expected to contain exactly one matching entity.");
430
Single {
431
item: single,
432
_filter: PhantomData,
433
}
434
}
435
436
#[inline]
437
unsafe fn validate_param(
438
state: &mut Self::State,
439
system_meta: &SystemMeta,
440
world: UnsafeWorldCell,
441
) -> Result<(), SystemParamValidationError> {
442
// SAFETY: State ensures that the components it accesses are not mutably accessible elsewhere
443
// and the query is read only.
444
// The caller ensures the world matches the one used in init_state.
445
let query = unsafe {
446
state.query_unchecked_with_ticks(world, system_meta.last_run, world.change_tick())
447
};
448
match query.single_inner() {
449
Ok(_) => Ok(()),
450
Err(QuerySingleError::NoEntities(_)) => Err(
451
SystemParamValidationError::skipped::<Self>("No matching entities"),
452
),
453
Err(QuerySingleError::MultipleEntities(_)) => Err(
454
SystemParamValidationError::skipped::<Self>("Multiple matching entities"),
455
),
456
}
457
}
458
}
459
460
// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
461
unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
462
for Single<'a, 'b, D, F>
463
{
464
}
465
466
// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
467
// this Query conflicts with any prior access, a panic will occur.
468
unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
469
for Populated<'_, '_, D, F>
470
{
471
type State = QueryState<D, F>;
472
type Item<'w, 's> = Populated<'w, 's, D, F>;
473
474
fn init_state(world: &mut World) -> Self::State {
475
Query::init_state(world)
476
}
477
478
fn init_access(
479
state: &Self::State,
480
system_meta: &mut SystemMeta,
481
component_access_set: &mut FilteredAccessSet,
482
world: &mut World,
483
) {
484
Query::init_access(state, system_meta, component_access_set, world);
485
}
486
487
#[inline]
488
unsafe fn get_param<'w, 's>(
489
state: &'s mut Self::State,
490
system_meta: &SystemMeta,
491
world: UnsafeWorldCell<'w>,
492
change_tick: Tick,
493
) -> Self::Item<'w, 's> {
494
// SAFETY: Delegate to existing `SystemParam` implementations.
495
let query = unsafe { Query::get_param(state, system_meta, world, change_tick) };
496
Populated(query)
497
}
498
499
#[inline]
500
unsafe fn validate_param(
501
state: &mut Self::State,
502
system_meta: &SystemMeta,
503
world: UnsafeWorldCell,
504
) -> Result<(), SystemParamValidationError> {
505
// SAFETY:
506
// - We have read-only access to the components accessed by query.
507
// - The caller ensures the world matches the one used in init_state.
508
let query = unsafe {
509
state.query_unchecked_with_ticks(world, system_meta.last_run, world.change_tick())
510
};
511
if query.is_empty() {
512
Err(SystemParamValidationError::skipped::<Self>(
513
"No matching entities",
514
))
515
} else {
516
Ok(())
517
}
518
}
519
}
520
521
// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
522
unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
523
for Populated<'w, 's, D, F>
524
{
525
}
526
527
/// A collection of potentially conflicting [`SystemParam`]s allowed by disjoint access.
528
///
529
/// Allows systems to safely access and interact with up to 8 mutually exclusive [`SystemParam`]s, such as
530
/// two queries that reference the same mutable data or an event reader and writer of the same type.
531
///
532
/// Each individual [`SystemParam`] can be accessed by using the functions `p0()`, `p1()`, ..., `p7()`,
533
/// according to the order they are defined in the `ParamSet`. This ensures that there's either
534
/// only one mutable reference to a parameter at a time or any number of immutable references.
535
///
536
/// # Examples
537
///
538
/// The following system mutably accesses the same component two times,
539
/// which is not allowed due to rust's mutability rules.
540
///
541
/// ```should_panic
542
/// # use bevy_ecs::prelude::*;
543
/// #
544
/// # #[derive(Component)]
545
/// # struct Health;
546
/// #
547
/// # #[derive(Component)]
548
/// # struct Enemy;
549
/// #
550
/// # #[derive(Component)]
551
/// # struct Ally;
552
/// #
553
/// // This will panic at runtime when the system gets initialized.
554
/// fn bad_system(
555
/// mut enemies: Query<&mut Health, With<Enemy>>,
556
/// mut allies: Query<&mut Health, With<Ally>>,
557
/// ) {
558
/// // ...
559
/// }
560
/// #
561
/// # let mut bad_system_system = IntoSystem::into_system(bad_system);
562
/// # let mut world = World::new();
563
/// # bad_system_system.initialize(&mut world);
564
/// # bad_system_system.run((), &mut world);
565
/// ```
566
///
567
/// Conflicting `SystemParam`s like these can be placed in a `ParamSet`,
568
/// which leverages the borrow checker to ensure that only one of the contained parameters are accessed at a given time.
569
///
570
/// ```
571
/// # use bevy_ecs::prelude::*;
572
/// #
573
/// # #[derive(Component)]
574
/// # struct Health;
575
/// #
576
/// # #[derive(Component)]
577
/// # struct Enemy;
578
/// #
579
/// # #[derive(Component)]
580
/// # struct Ally;
581
/// #
582
/// // Given the following system
583
/// fn fancy_system(
584
/// mut set: ParamSet<(
585
/// Query<&mut Health, With<Enemy>>,
586
/// Query<&mut Health, With<Ally>>,
587
/// )>
588
/// ) {
589
/// // This will access the first `SystemParam`.
590
/// for mut health in set.p0().iter_mut() {
591
/// // Do your fancy stuff here...
592
/// }
593
///
594
/// // The second `SystemParam`.
595
/// // This would fail to compile if the previous parameter was still borrowed.
596
/// for mut health in set.p1().iter_mut() {
597
/// // Do even fancier stuff here...
598
/// }
599
/// }
600
/// # bevy_ecs::system::assert_is_system(fancy_system);
601
/// ```
602
///
603
/// Of course, `ParamSet`s can be used with any kind of `SystemParam`, not just [queries](Query).
604
///
605
/// ```
606
/// # use bevy_ecs::prelude::*;
607
/// #
608
/// # #[derive(BufferedEvent)]
609
/// # struct MyEvent;
610
/// # impl MyEvent {
611
/// # pub fn new() -> Self { Self }
612
/// # }
613
/// fn event_system(
614
/// mut set: ParamSet<(
615
/// // PROBLEM: `EventReader` and `EventWriter` cannot be used together normally,
616
/// // because they both need access to the same event queue.
617
/// // SOLUTION: `ParamSet` allows these conflicting parameters to be used safely
618
/// // by ensuring only one is accessed at a time.
619
/// EventReader<MyEvent>,
620
/// EventWriter<MyEvent>,
621
/// // PROBLEM: `&World` needs read access to everything, which conflicts with
622
/// // any mutable access in the same system.
623
/// // SOLUTION: `ParamSet` ensures `&World` is only accessed when we're not
624
/// // using the other mutable parameters.
625
/// &World,
626
/// )>,
627
/// ) {
628
/// for event in set.p0().read() {
629
/// // ...
630
/// # let _event = event;
631
/// }
632
/// set.p1().write(MyEvent::new());
633
///
634
/// let entities = set.p2().entities();
635
/// // ...
636
/// # let _entities = entities;
637
/// }
638
/// # bevy_ecs::system::assert_is_system(event_system);
639
/// ```
640
pub struct ParamSet<'w, 's, T: SystemParam> {
641
param_states: &'s mut T::State,
642
world: UnsafeWorldCell<'w>,
643
system_meta: SystemMeta,
644
change_tick: Tick,
645
}
646
647
macro_rules! impl_param_set {
648
($(($index: tt, $param: ident, $fn_name: ident)),*) => {
649
// SAFETY: All parameters are constrained to ReadOnlySystemParam, so World is only read
650
unsafe impl<'w, 's, $($param,)*> ReadOnlySystemParam for ParamSet<'w, 's, ($($param,)*)>
651
where $($param: ReadOnlySystemParam,)*
652
{ }
653
654
// SAFETY: Relevant parameter ComponentId access is applied to SystemMeta. If any ParamState conflicts
655
// with any prior access, a panic will occur.
656
unsafe impl<'_w, '_s, $($param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, ($($param,)*)>
657
{
658
type State = ($($param::State,)*);
659
type Item<'w, 's> = ParamSet<'w, 's, ($($param,)*)>;
660
661
#[expect(
662
clippy::allow_attributes,
663
reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
664
)]
665
#[allow(
666
non_snake_case,
667
reason = "Certain variable names are provided by the caller, not by us."
668
)]
669
fn init_state(world: &mut World) -> Self::State {
670
($($param::init_state(world),)*)
671
}
672
673
#[expect(
674
clippy::allow_attributes,
675
reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
676
)]
677
#[allow(
678
non_snake_case,
679
reason = "Certain variable names are provided by the caller, not by us."
680
)]
681
fn init_access(state: &Self::State, system_meta: &mut SystemMeta, component_access_set: &mut FilteredAccessSet, world: &mut World) {
682
let ($($param,)*) = state;
683
$(
684
// Call `init_access` on a clone of the original access set to check for conflicts
685
let component_access_set_clone = &mut component_access_set.clone();
686
$param::init_access($param, system_meta, component_access_set_clone, world);
687
)*
688
$(
689
// Pretend to add the param to the system alone to gather the new access,
690
// then merge its access into the system.
691
let mut access_set = FilteredAccessSet::new();
692
$param::init_access($param, system_meta, &mut access_set, world);
693
component_access_set.extend(access_set);
694
)*
695
}
696
697
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
698
<($($param,)*) as SystemParam>::apply(state, system_meta, world);
699
}
700
701
fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
702
<($($param,)*) as SystemParam>::queue(state, system_meta, world.reborrow());
703
}
704
705
#[inline]
706
unsafe fn validate_param<'w, 's>(
707
state: &'s mut Self::State,
708
system_meta: &SystemMeta,
709
world: UnsafeWorldCell<'w>,
710
) -> Result<(), SystemParamValidationError> {
711
<($($param,)*) as SystemParam>::validate_param(state, system_meta, world)
712
}
713
714
#[inline]
715
unsafe fn get_param<'w, 's>(
716
state: &'s mut Self::State,
717
system_meta: &SystemMeta,
718
world: UnsafeWorldCell<'w>,
719
change_tick: Tick,
720
) -> Self::Item<'w, 's> {
721
ParamSet {
722
param_states: state,
723
system_meta: system_meta.clone(),
724
world,
725
change_tick,
726
}
727
}
728
}
729
730
impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)>
731
{
732
$(
733
/// Gets exclusive access to the parameter at index
734
#[doc = stringify!($index)]
735
/// in this [`ParamSet`].
736
/// No other parameters may be accessed while this one is active.
737
pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> {
738
// SAFETY: systems run without conflicts with other systems.
739
// Conflicting params in ParamSet are not accessible at the same time
740
// ParamSets are guaranteed to not conflict with other SystemParams
741
unsafe {
742
$param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick)
743
}
744
}
745
)*
746
}
747
}
748
}
749
750
all_tuples_enumerated!(impl_param_set, 1, 8, P, p);
751
752
// SAFETY: Res only reads a single World resource
753
unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {}
754
755
// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res
756
// conflicts with any prior access, a panic will occur.
757
unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
758
type State = ComponentId;
759
type Item<'w, 's> = Res<'w, T>;
760
761
fn init_state(world: &mut World) -> Self::State {
762
world.components_registrator().register_resource::<T>()
763
}
764
765
fn init_access(
766
&component_id: &Self::State,
767
system_meta: &mut SystemMeta,
768
component_access_set: &mut FilteredAccessSet,
769
_world: &mut World,
770
) {
771
let combined_access = component_access_set.combined_access();
772
assert!(
773
!combined_access.has_resource_write(component_id),
774
"error[B0002]: Res<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
775
DebugName::type_name::<T>(),
776
system_meta.name,
777
);
778
779
component_access_set.add_unfiltered_resource_read(component_id);
780
}
781
782
#[inline]
783
unsafe fn validate_param(
784
&mut component_id: &mut Self::State,
785
_system_meta: &SystemMeta,
786
world: UnsafeWorldCell,
787
) -> Result<(), SystemParamValidationError> {
788
// SAFETY: Read-only access to resource metadata.
789
if unsafe { world.storages() }
790
.resources
791
.get(component_id)
792
.is_some_and(ResourceData::is_present)
793
{
794
Ok(())
795
} else {
796
Err(SystemParamValidationError::invalid::<Self>(
797
"Resource does not exist",
798
))
799
}
800
}
801
802
#[inline]
803
unsafe fn get_param<'w, 's>(
804
&mut component_id: &'s mut Self::State,
805
system_meta: &SystemMeta,
806
world: UnsafeWorldCell<'w>,
807
change_tick: Tick,
808
) -> Self::Item<'w, 's> {
809
let (ptr, ticks, caller) =
810
world
811
.get_resource_with_ticks(component_id)
812
.unwrap_or_else(|| {
813
panic!(
814
"Resource requested by {} does not exist: {}",
815
system_meta.name,
816
DebugName::type_name::<T>()
817
);
818
});
819
Res {
820
value: ptr.deref(),
821
ticks: Ticks {
822
added: ticks.added.deref(),
823
changed: ticks.changed.deref(),
824
last_run: system_meta.last_run,
825
this_run: change_tick,
826
},
827
changed_by: caller.map(|caller| caller.deref()),
828
}
829
}
830
}
831
832
// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res
833
// conflicts with any prior access, a panic will occur.
834
unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
835
type State = ComponentId;
836
type Item<'w, 's> = ResMut<'w, T>;
837
838
fn init_state(world: &mut World) -> Self::State {
839
world.components_registrator().register_resource::<T>()
840
}
841
842
fn init_access(
843
&component_id: &Self::State,
844
system_meta: &mut SystemMeta,
845
component_access_set: &mut FilteredAccessSet,
846
_world: &mut World,
847
) {
848
let combined_access = component_access_set.combined_access();
849
if combined_access.has_resource_write(component_id) {
850
panic!(
851
"error[B0002]: ResMut<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
852
DebugName::type_name::<T>(), system_meta.name);
853
} else if combined_access.has_resource_read(component_id) {
854
panic!(
855
"error[B0002]: ResMut<{}> in system {} conflicts with a previous Res<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
856
DebugName::type_name::<T>(), system_meta.name);
857
}
858
component_access_set.add_unfiltered_resource_write(component_id);
859
}
860
861
#[inline]
862
unsafe fn validate_param(
863
&mut component_id: &mut Self::State,
864
_system_meta: &SystemMeta,
865
world: UnsafeWorldCell,
866
) -> Result<(), SystemParamValidationError> {
867
// SAFETY: Read-only access to resource metadata.
868
if unsafe { world.storages() }
869
.resources
870
.get(component_id)
871
.is_some_and(ResourceData::is_present)
872
{
873
Ok(())
874
} else {
875
Err(SystemParamValidationError::invalid::<Self>(
876
"Resource does not exist",
877
))
878
}
879
}
880
881
#[inline]
882
unsafe fn get_param<'w, 's>(
883
&mut component_id: &'s mut Self::State,
884
system_meta: &SystemMeta,
885
world: UnsafeWorldCell<'w>,
886
change_tick: Tick,
887
) -> Self::Item<'w, 's> {
888
let value = world
889
.get_resource_mut_by_id(component_id)
890
.unwrap_or_else(|| {
891
panic!(
892
"Resource requested by {} does not exist: {}",
893
system_meta.name,
894
DebugName::type_name::<T>()
895
);
896
});
897
ResMut {
898
value: value.value.deref_mut::<T>(),
899
ticks: TicksMut {
900
added: value.ticks.added,
901
changed: value.ticks.changed,
902
last_run: system_meta.last_run,
903
this_run: change_tick,
904
},
905
changed_by: value.changed_by,
906
}
907
}
908
}
909
910
/// SAFETY: only reads world
911
unsafe impl<'w> ReadOnlySystemParam for &'w World {}
912
913
// SAFETY: `read_all` access is set and conflicts result in a panic
914
unsafe impl SystemParam for &'_ World {
915
type State = ();
916
type Item<'w, 's> = &'w World;
917
918
fn init_state(_world: &mut World) -> Self::State {}
919
920
fn init_access(
921
_state: &Self::State,
922
_system_meta: &mut SystemMeta,
923
component_access_set: &mut FilteredAccessSet,
924
_world: &mut World,
925
) {
926
let mut filtered_access = FilteredAccess::default();
927
928
filtered_access.read_all();
929
if !component_access_set
930
.get_conflicts_single(&filtered_access)
931
.is_empty()
932
{
933
panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");
934
}
935
component_access_set.add(filtered_access);
936
}
937
938
#[inline]
939
unsafe fn get_param<'w, 's>(
940
_state: &'s mut Self::State,
941
_system_meta: &SystemMeta,
942
world: UnsafeWorldCell<'w>,
943
_change_tick: Tick,
944
) -> Self::Item<'w, 's> {
945
// SAFETY: Read-only access to the entire world was registered in `init_state`.
946
unsafe { world.world() }
947
}
948
}
949
950
/// SAFETY: `DeferredWorld` can read all components and resources but cannot be used to gain any other mutable references.
951
unsafe impl<'w> SystemParam for DeferredWorld<'w> {
952
type State = ();
953
type Item<'world, 'state> = DeferredWorld<'world>;
954
955
fn init_state(_world: &mut World) -> Self::State {}
956
957
fn init_access(
958
_state: &Self::State,
959
system_meta: &mut SystemMeta,
960
component_access_set: &mut FilteredAccessSet,
961
_world: &mut World,
962
) {
963
assert!(
964
!component_access_set.combined_access().has_any_read(),
965
"DeferredWorld in system {} conflicts with a previous access.",
966
system_meta.name,
967
);
968
component_access_set.write_all();
969
}
970
971
unsafe fn get_param<'world, 'state>(
972
_state: &'state mut Self::State,
973
_system_meta: &SystemMeta,
974
world: UnsafeWorldCell<'world>,
975
_change_tick: Tick,
976
) -> Self::Item<'world, 'state> {
977
world.into_deferred()
978
}
979
}
980
981
/// A system local [`SystemParam`].
982
///
983
/// A local may only be accessed by the system itself and is therefore not visible to other systems.
984
/// If two or more systems specify the same local type each will have their own unique local.
985
/// If multiple [`SystemParam`]s within the same system each specify the same local type
986
/// each will get their own distinct data storage.
987
///
988
/// The supplied lifetime parameter is the [`SystemParam`]s `'s` lifetime.
989
///
990
/// # Examples
991
///
992
/// ```
993
/// # use bevy_ecs::prelude::*;
994
/// # let world = &mut World::default();
995
/// fn write_to_local(mut local: Local<usize>) {
996
/// *local = 42;
997
/// }
998
/// fn read_from_local(local: Local<usize>) -> usize {
999
/// *local
1000
/// }
1001
/// let mut write_system = IntoSystem::into_system(write_to_local);
1002
/// let mut read_system = IntoSystem::into_system(read_from_local);
1003
/// write_system.initialize(world);
1004
/// read_system.initialize(world);
1005
///
1006
/// assert_eq!(read_system.run((), world).unwrap(), 0);
1007
/// write_system.run((), world);
1008
/// // Note how the read local is still 0 due to the locals not being shared.
1009
/// assert_eq!(read_system.run((), world).unwrap(), 0);
1010
/// ```
1011
///
1012
/// A simple way to set a different default value for a local is by wrapping the value with an Option.
1013
///
1014
/// ```
1015
/// # use bevy_ecs::prelude::*;
1016
/// # let world = &mut World::default();
1017
/// fn counter_from_10(mut count: Local<Option<usize>>) -> usize {
1018
/// let count = count.get_or_insert(10);
1019
/// *count += 1;
1020
/// *count
1021
/// }
1022
/// let mut counter_system = IntoSystem::into_system(counter_from_10);
1023
/// counter_system.initialize(world);
1024
///
1025
/// // Counter is initialized at 10, and increases to 11 on first run.
1026
/// assert_eq!(counter_system.run((), world).unwrap(), 11);
1027
/// // Counter is only increased by 1 on subsequent runs.
1028
/// assert_eq!(counter_system.run((), world).unwrap(), 12);
1029
/// ```
1030
///
1031
/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.
1032
/// To add configuration to a system, convert a capturing closure into the system instead:
1033
///
1034
/// ```
1035
/// # use bevy_ecs::prelude::*;
1036
/// # use bevy_ecs::system::assert_is_system;
1037
/// struct Config(u32);
1038
/// #[derive(Resource)]
1039
/// struct MyU32Wrapper(u32);
1040
/// fn reset_to_system(value: Config) -> impl FnMut(ResMut<MyU32Wrapper>) {
1041
/// move |mut val| val.0 = value.0
1042
/// }
1043
///
1044
/// // .add_systems(reset_to_system(my_config))
1045
/// # assert_is_system(reset_to_system(Config(10)));
1046
/// ```
1047
#[derive(Debug)]
1048
pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T);
1049
1050
// SAFETY: Local only accesses internal state
1051
unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'s, T> {}
1052
1053
impl<'s, T: FromWorld + Send + 'static> Deref for Local<'s, T> {
1054
type Target = T;
1055
1056
#[inline]
1057
fn deref(&self) -> &Self::Target {
1058
self.0
1059
}
1060
}
1061
1062
impl<'s, T: FromWorld + Send + 'static> DerefMut for Local<'s, T> {
1063
#[inline]
1064
fn deref_mut(&mut self) -> &mut Self::Target {
1065
self.0
1066
}
1067
}
1068
1069
impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'s, T>
1070
where
1071
&'a T: IntoIterator,
1072
{
1073
type Item = <&'a T as IntoIterator>::Item;
1074
type IntoIter = <&'a T as IntoIterator>::IntoIter;
1075
1076
fn into_iter(self) -> Self::IntoIter {
1077
self.0.into_iter()
1078
}
1079
}
1080
1081
impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'s, T>
1082
where
1083
&'a mut T: IntoIterator,
1084
{
1085
type Item = <&'a mut T as IntoIterator>::Item;
1086
type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
1087
1088
fn into_iter(self) -> Self::IntoIter {
1089
self.0.into_iter()
1090
}
1091
}
1092
1093
// SAFETY: only local state is accessed
1094
unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {
1095
type State = SyncCell<T>;
1096
type Item<'w, 's> = Local<'s, T>;
1097
1098
fn init_state(world: &mut World) -> Self::State {
1099
SyncCell::new(T::from_world(world))
1100
}
1101
1102
fn init_access(
1103
_state: &Self::State,
1104
_system_meta: &mut SystemMeta,
1105
_component_access_set: &mut FilteredAccessSet,
1106
_world: &mut World,
1107
) {
1108
}
1109
1110
#[inline]
1111
unsafe fn get_param<'w, 's>(
1112
state: &'s mut Self::State,
1113
_system_meta: &SystemMeta,
1114
_world: UnsafeWorldCell<'w>,
1115
_change_tick: Tick,
1116
) -> Self::Item<'w, 's> {
1117
Local(state.get())
1118
}
1119
}
1120
1121
/// Types that can be used with [`Deferred<T>`] in systems.
1122
/// This allows storing system-local data which is used to defer [`World`] mutations.
1123
///
1124
/// Types that implement `SystemBuffer` should take care to perform as many
1125
/// computations up-front as possible. Buffers cannot be applied in parallel,
1126
/// so you should try to minimize the time spent in [`SystemBuffer::apply`].
1127
pub trait SystemBuffer: FromWorld + Send + 'static {
1128
/// Applies any deferred mutations to the [`World`].
1129
fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
1130
/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
1131
fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld) {}
1132
}
1133
1134
/// A [`SystemParam`] that stores a buffer which gets applied to the [`World`] during
1135
/// [`ApplyDeferred`](crate::schedule::ApplyDeferred).
1136
/// This is used internally by [`Commands`] to defer `World` mutations.
1137
///
1138
/// [`Commands`]: crate::system::Commands
1139
///
1140
/// # Examples
1141
///
1142
/// By using this type to defer mutations, you can avoid mutable `World` access within
1143
/// a system, which allows it to run in parallel with more systems.
1144
///
1145
/// Note that deferring mutations is *not* free, and should only be used if
1146
/// the gains in parallelization outweigh the time it takes to apply deferred mutations.
1147
/// In general, [`Deferred`] should only be used for mutations that are infrequent,
1148
/// or which otherwise take up a small portion of a system's run-time.
1149
///
1150
/// ```
1151
/// # use bevy_ecs::prelude::*;
1152
/// // Tracks whether or not there is a threat the player should be aware of.
1153
/// #[derive(Resource, Default)]
1154
/// pub struct Alarm(bool);
1155
///
1156
/// #[derive(Component)]
1157
/// pub struct Settlement {
1158
/// // ...
1159
/// }
1160
///
1161
/// // A threat from inside the settlement.
1162
/// #[derive(Component)]
1163
/// pub struct Criminal;
1164
///
1165
/// // A threat from outside the settlement.
1166
/// #[derive(Component)]
1167
/// pub struct Monster;
1168
///
1169
/// # impl Criminal { pub fn is_threat(&self, _: &Settlement) -> bool { true } }
1170
///
1171
/// use bevy_ecs::system::{Deferred, SystemBuffer, SystemMeta};
1172
///
1173
/// // Uses deferred mutations to allow signaling the alarm from multiple systems in parallel.
1174
/// #[derive(Resource, Default)]
1175
/// struct AlarmFlag(bool);
1176
///
1177
/// impl AlarmFlag {
1178
/// /// Sounds the alarm the next time buffers are applied via ApplyDeferred.
1179
/// pub fn flag(&mut self) {
1180
/// self.0 = true;
1181
/// }
1182
/// }
1183
///
1184
/// impl SystemBuffer for AlarmFlag {
1185
/// // When `AlarmFlag` is used in a system, this function will get
1186
/// // called the next time buffers are applied via ApplyDeferred.
1187
/// fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
1188
/// if self.0 {
1189
/// world.resource_mut::<Alarm>().0 = true;
1190
/// self.0 = false;
1191
/// }
1192
/// }
1193
/// }
1194
///
1195
/// // Sound the alarm if there are any criminals who pose a threat.
1196
/// fn alert_criminal(
1197
/// settlement: Single<&Settlement>,
1198
/// criminals: Query<&Criminal>,
1199
/// mut alarm: Deferred<AlarmFlag>
1200
/// ) {
1201
/// for criminal in &criminals {
1202
/// // Only sound the alarm if the criminal is a threat.
1203
/// // For this example, assume that this check is expensive to run.
1204
/// // Since the majority of this system's run-time is dominated
1205
/// // by calling `is_threat()`, we defer sounding the alarm to
1206
/// // allow this system to run in parallel with other alarm systems.
1207
/// if criminal.is_threat(*settlement) {
1208
/// alarm.flag();
1209
/// }
1210
/// }
1211
/// }
1212
///
1213
/// // Sound the alarm if there is a monster.
1214
/// fn alert_monster(
1215
/// monsters: Query<&Monster>,
1216
/// mut alarm: ResMut<Alarm>
1217
/// ) {
1218
/// if monsters.iter().next().is_some() {
1219
/// // Since this system does nothing except for sounding the alarm,
1220
/// // it would be pointless to defer it, so we sound the alarm directly.
1221
/// alarm.0 = true;
1222
/// }
1223
/// }
1224
///
1225
/// let mut world = World::new();
1226
/// world.init_resource::<Alarm>();
1227
/// world.spawn(Settlement {
1228
/// // ...
1229
/// });
1230
///
1231
/// let mut schedule = Schedule::default();
1232
/// // These two systems have no conflicts and will run in parallel.
1233
/// schedule.add_systems((alert_criminal, alert_monster));
1234
///
1235
/// // There are no criminals or monsters, so the alarm is not sounded.
1236
/// schedule.run(&mut world);
1237
/// assert_eq!(world.resource::<Alarm>().0, false);
1238
///
1239
/// // Spawn a monster, which will cause the alarm to be sounded.
1240
/// let m_id = world.spawn(Monster).id();
1241
/// schedule.run(&mut world);
1242
/// assert_eq!(world.resource::<Alarm>().0, true);
1243
///
1244
/// // Remove the monster and reset the alarm.
1245
/// world.entity_mut(m_id).despawn();
1246
/// world.resource_mut::<Alarm>().0 = false;
1247
///
1248
/// // Spawn a criminal, which will cause the alarm to be sounded.
1249
/// world.spawn(Criminal);
1250
/// schedule.run(&mut world);
1251
/// assert_eq!(world.resource::<Alarm>().0, true);
1252
/// ```
1253
pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T);
1254
1255
impl<'a, T: SystemBuffer> Deref for Deferred<'a, T> {
1256
type Target = T;
1257
#[inline]
1258
fn deref(&self) -> &Self::Target {
1259
self.0
1260
}
1261
}
1262
1263
impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {
1264
#[inline]
1265
fn deref_mut(&mut self) -> &mut Self::Target {
1266
self.0
1267
}
1268
}
1269
1270
impl<T: SystemBuffer> Deferred<'_, T> {
1271
/// Returns a [`Deferred<T>`] with a smaller lifetime.
1272
/// This is useful if you have `&mut Deferred<T>` but need `Deferred<T>`.
1273
pub fn reborrow(&mut self) -> Deferred<'_, T> {
1274
Deferred(self.0)
1275
}
1276
}
1277
1278
// SAFETY: Only local state is accessed.
1279
unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
1280
1281
// SAFETY: Only local state is accessed.
1282
unsafe impl<T: SystemBuffer> SystemParam for Deferred<'_, T> {
1283
type State = SyncCell<T>;
1284
type Item<'w, 's> = Deferred<'s, T>;
1285
1286
fn init_state(world: &mut World) -> Self::State {
1287
SyncCell::new(T::from_world(world))
1288
}
1289
1290
fn init_access(
1291
_state: &Self::State,
1292
system_meta: &mut SystemMeta,
1293
_component_access_set: &mut FilteredAccessSet,
1294
_world: &mut World,
1295
) {
1296
system_meta.set_has_deferred();
1297
}
1298
1299
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1300
state.get().apply(system_meta, world);
1301
}
1302
1303
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1304
state.get().queue(system_meta, world);
1305
}
1306
1307
#[inline]
1308
unsafe fn get_param<'w, 's>(
1309
state: &'s mut Self::State,
1310
_system_meta: &SystemMeta,
1311
_world: UnsafeWorldCell<'w>,
1312
_change_tick: Tick,
1313
) -> Self::Item<'w, 's> {
1314
Deferred(state.get())
1315
}
1316
}
1317
1318
/// A dummy type that is [`!Send`](Send), to force systems to run on the main thread.
1319
pub struct NonSendMarker(PhantomData<*mut ()>);
1320
1321
// SAFETY: No world access.
1322
unsafe impl SystemParam for NonSendMarker {
1323
type State = ();
1324
type Item<'w, 's> = Self;
1325
1326
#[inline]
1327
fn init_state(_world: &mut World) -> Self::State {}
1328
1329
fn init_access(
1330
_state: &Self::State,
1331
system_meta: &mut SystemMeta,
1332
_component_access_set: &mut FilteredAccessSet,
1333
_world: &mut World,
1334
) {
1335
system_meta.set_non_send();
1336
}
1337
1338
#[inline]
1339
unsafe fn get_param<'world, 'state>(
1340
_state: &'state mut Self::State,
1341
_system_meta: &SystemMeta,
1342
_world: UnsafeWorldCell<'world>,
1343
_change_tick: Tick,
1344
) -> Self::Item<'world, 'state> {
1345
Self(PhantomData)
1346
}
1347
}
1348
1349
// SAFETY: Does not read any world state
1350
unsafe impl ReadOnlySystemParam for NonSendMarker {}
1351
1352
/// Shared borrow of a non-[`Send`] resource.
1353
///
1354
/// Only `Send` resources may be accessed with the [`Res`] [`SystemParam`]. In case that the
1355
/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
1356
/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
1357
/// over to another thread.
1358
///
1359
/// This [`SystemParam`] fails validation if non-send resource doesn't exist.
1360
/// This will cause a panic, but can be configured to do nothing or warn once.
1361
///
1362
/// Use [`Option<NonSend<T>>`] instead if the resource might not always exist.
1363
pub struct NonSend<'w, T: 'static> {
1364
pub(crate) value: &'w T,
1365
ticks: ComponentTicks,
1366
last_run: Tick,
1367
this_run: Tick,
1368
changed_by: MaybeLocation<&'w &'static Location<'static>>,
1369
}
1370
1371
// SAFETY: Only reads a single World non-send resource
1372
unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {}
1373
1374
impl<'w, T> Debug for NonSend<'w, T>
1375
where
1376
T: Debug,
1377
{
1378
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1379
f.debug_tuple("NonSend").field(&self.value).finish()
1380
}
1381
}
1382
1383
impl<'w, T: 'static> NonSend<'w, T> {
1384
/// Returns `true` if the resource was added after the system last ran.
1385
pub fn is_added(&self) -> bool {
1386
self.ticks.is_added(self.last_run, self.this_run)
1387
}
1388
1389
/// Returns `true` if the resource was added or mutably dereferenced after the system last ran.
1390
pub fn is_changed(&self) -> bool {
1391
self.ticks.is_changed(self.last_run, self.this_run)
1392
}
1393
1394
/// The location that last caused this to change.
1395
pub fn changed_by(&self) -> MaybeLocation {
1396
self.changed_by.copied()
1397
}
1398
}
1399
1400
impl<'w, T> Deref for NonSend<'w, T> {
1401
type Target = T;
1402
1403
fn deref(&self) -> &Self::Target {
1404
self.value
1405
}
1406
}
1407
1408
impl<'a, T> From<NonSendMut<'a, T>> for NonSend<'a, T> {
1409
fn from(nsm: NonSendMut<'a, T>) -> Self {
1410
Self {
1411
value: nsm.value,
1412
ticks: ComponentTicks {
1413
added: nsm.ticks.added.to_owned(),
1414
changed: nsm.ticks.changed.to_owned(),
1415
},
1416
this_run: nsm.ticks.this_run,
1417
last_run: nsm.ticks.last_run,
1418
changed_by: nsm.changed_by.map(|changed_by| &*changed_by),
1419
}
1420
}
1421
}
1422
1423
// SAFETY: NonSendComponentId access is applied to SystemMeta. If this
1424
// NonSend conflicts with any prior access, a panic will occur.
1425
unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
1426
type State = ComponentId;
1427
type Item<'w, 's> = NonSend<'w, T>;
1428
1429
fn init_state(world: &mut World) -> Self::State {
1430
world.components_registrator().register_non_send::<T>()
1431
}
1432
1433
fn init_access(
1434
&component_id: &Self::State,
1435
system_meta: &mut SystemMeta,
1436
component_access_set: &mut FilteredAccessSet,
1437
_world: &mut World,
1438
) {
1439
system_meta.set_non_send();
1440
1441
let combined_access = component_access_set.combined_access();
1442
assert!(
1443
!combined_access.has_resource_write(component_id),
1444
"error[B0002]: NonSend<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
1445
DebugName::type_name::<T>(),
1446
system_meta.name,
1447
);
1448
component_access_set.add_unfiltered_resource_read(component_id);
1449
}
1450
1451
#[inline]
1452
unsafe fn validate_param(
1453
&mut component_id: &mut Self::State,
1454
_system_meta: &SystemMeta,
1455
world: UnsafeWorldCell,
1456
) -> Result<(), SystemParamValidationError> {
1457
// SAFETY: Read-only access to resource metadata.
1458
if unsafe { world.storages() }
1459
.non_send_resources
1460
.get(component_id)
1461
.is_some_and(ResourceData::is_present)
1462
{
1463
Ok(())
1464
} else {
1465
Err(SystemParamValidationError::invalid::<Self>(
1466
"Non-send resource does not exist",
1467
))
1468
}
1469
}
1470
1471
#[inline]
1472
unsafe fn get_param<'w, 's>(
1473
&mut component_id: &'s mut Self::State,
1474
system_meta: &SystemMeta,
1475
world: UnsafeWorldCell<'w>,
1476
change_tick: Tick,
1477
) -> Self::Item<'w, 's> {
1478
let (ptr, ticks, caller) =
1479
world
1480
.get_non_send_with_ticks(component_id)
1481
.unwrap_or_else(|| {
1482
panic!(
1483
"Non-send resource requested by {} does not exist: {}",
1484
system_meta.name,
1485
DebugName::type_name::<T>()
1486
)
1487
});
1488
1489
NonSend {
1490
value: ptr.deref(),
1491
ticks: ticks.read(),
1492
last_run: system_meta.last_run,
1493
this_run: change_tick,
1494
changed_by: caller.map(|caller| caller.deref()),
1495
}
1496
}
1497
}
1498
1499
// SAFETY: NonSendMut ComponentId access is applied to SystemMeta. If this
1500
// NonSendMut conflicts with any prior access, a panic will occur.
1501
unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
1502
type State = ComponentId;
1503
type Item<'w, 's> = NonSendMut<'w, T>;
1504
1505
fn init_state(world: &mut World) -> Self::State {
1506
world.components_registrator().register_non_send::<T>()
1507
}
1508
1509
fn init_access(
1510
&component_id: &Self::State,
1511
system_meta: &mut SystemMeta,
1512
component_access_set: &mut FilteredAccessSet,
1513
_world: &mut World,
1514
) {
1515
system_meta.set_non_send();
1516
1517
let combined_access = component_access_set.combined_access();
1518
if combined_access.has_component_write(component_id) {
1519
panic!(
1520
"error[B0002]: NonSendMut<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
1521
DebugName::type_name::<T>(), system_meta.name);
1522
} else if combined_access.has_component_read(component_id) {
1523
panic!(
1524
"error[B0002]: NonSendMut<{}> in system {} conflicts with a previous immutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
1525
DebugName::type_name::<T>(), system_meta.name);
1526
}
1527
component_access_set.add_unfiltered_resource_write(component_id);
1528
}
1529
1530
#[inline]
1531
unsafe fn validate_param(
1532
&mut component_id: &mut Self::State,
1533
_system_meta: &SystemMeta,
1534
world: UnsafeWorldCell,
1535
) -> Result<(), SystemParamValidationError> {
1536
// SAFETY: Read-only access to resource metadata.
1537
if unsafe { world.storages() }
1538
.non_send_resources
1539
.get(component_id)
1540
.is_some_and(ResourceData::is_present)
1541
{
1542
Ok(())
1543
} else {
1544
Err(SystemParamValidationError::invalid::<Self>(
1545
"Non-send resource does not exist",
1546
))
1547
}
1548
}
1549
1550
#[inline]
1551
unsafe fn get_param<'w, 's>(
1552
&mut component_id: &'s mut Self::State,
1553
system_meta: &SystemMeta,
1554
world: UnsafeWorldCell<'w>,
1555
change_tick: Tick,
1556
) -> Self::Item<'w, 's> {
1557
let (ptr, ticks, caller) =
1558
world
1559
.get_non_send_with_ticks(component_id)
1560
.unwrap_or_else(|| {
1561
panic!(
1562
"Non-send resource requested by {} does not exist: {}",
1563
system_meta.name,
1564
DebugName::type_name::<T>()
1565
);
1566
});
1567
NonSendMut {
1568
value: ptr.assert_unique().deref_mut(),
1569
ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
1570
changed_by: caller.map(|caller| caller.deref_mut()),
1571
}
1572
}
1573
}
1574
1575
// SAFETY: Only reads World archetypes
1576
unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}
1577
1578
// SAFETY: no component value access
1579
unsafe impl<'a> SystemParam for &'a Archetypes {
1580
type State = ();
1581
type Item<'w, 's> = &'w Archetypes;
1582
1583
fn init_state(_world: &mut World) -> Self::State {}
1584
1585
fn init_access(
1586
_state: &Self::State,
1587
_system_meta: &mut SystemMeta,
1588
_component_access_set: &mut FilteredAccessSet,
1589
_world: &mut World,
1590
) {
1591
}
1592
1593
#[inline]
1594
unsafe fn get_param<'w, 's>(
1595
_state: &'s mut Self::State,
1596
_system_meta: &SystemMeta,
1597
world: UnsafeWorldCell<'w>,
1598
_change_tick: Tick,
1599
) -> Self::Item<'w, 's> {
1600
world.archetypes()
1601
}
1602
}
1603
1604
// SAFETY: Only reads World components
1605
unsafe impl<'a> ReadOnlySystemParam for &'a Components {}
1606
1607
// SAFETY: no component value access
1608
unsafe impl<'a> SystemParam for &'a Components {
1609
type State = ();
1610
type Item<'w, 's> = &'w Components;
1611
1612
fn init_state(_world: &mut World) -> Self::State {}
1613
1614
fn init_access(
1615
_state: &Self::State,
1616
_system_meta: &mut SystemMeta,
1617
_component_access_set: &mut FilteredAccessSet,
1618
_world: &mut World,
1619
) {
1620
}
1621
1622
#[inline]
1623
unsafe fn get_param<'w, 's>(
1624
_state: &'s mut Self::State,
1625
_system_meta: &SystemMeta,
1626
world: UnsafeWorldCell<'w>,
1627
_change_tick: Tick,
1628
) -> Self::Item<'w, 's> {
1629
world.components()
1630
}
1631
}
1632
1633
// SAFETY: Only reads World entities
1634
unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}
1635
1636
// SAFETY: no component value access
1637
unsafe impl<'a> SystemParam for &'a Entities {
1638
type State = ();
1639
type Item<'w, 's> = &'w Entities;
1640
1641
fn init_state(_world: &mut World) -> Self::State {}
1642
1643
fn init_access(
1644
_state: &Self::State,
1645
_system_meta: &mut SystemMeta,
1646
_component_access_set: &mut FilteredAccessSet,
1647
_world: &mut World,
1648
) {
1649
}
1650
1651
#[inline]
1652
unsafe fn get_param<'w, 's>(
1653
_state: &'s mut Self::State,
1654
_system_meta: &SystemMeta,
1655
world: UnsafeWorldCell<'w>,
1656
_change_tick: Tick,
1657
) -> Self::Item<'w, 's> {
1658
world.entities()
1659
}
1660
}
1661
1662
// SAFETY: Only reads World bundles
1663
unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}
1664
1665
// SAFETY: no component value access
1666
unsafe impl<'a> SystemParam for &'a Bundles {
1667
type State = ();
1668
type Item<'w, 's> = &'w Bundles;
1669
1670
fn init_state(_world: &mut World) -> Self::State {}
1671
1672
fn init_access(
1673
_state: &Self::State,
1674
_system_meta: &mut SystemMeta,
1675
_component_access_set: &mut FilteredAccessSet,
1676
_world: &mut World,
1677
) {
1678
}
1679
1680
#[inline]
1681
unsafe fn get_param<'w, 's>(
1682
_state: &'s mut Self::State,
1683
_system_meta: &SystemMeta,
1684
world: UnsafeWorldCell<'w>,
1685
_change_tick: Tick,
1686
) -> Self::Item<'w, 's> {
1687
world.bundles()
1688
}
1689
}
1690
1691
/// A [`SystemParam`] that reads the previous and current change ticks of the system.
1692
///
1693
/// A system's change ticks are updated each time it runs:
1694
/// - `last_run` copies the previous value of `change_tick`
1695
/// - `this_run` copies the current value of [`World::read_change_tick`]
1696
///
1697
/// Component change ticks that are more recent than `last_run` will be detected by the system.
1698
/// Those can be read by calling [`last_changed`](crate::change_detection::DetectChanges::last_changed)
1699
/// on a [`Mut<T>`](crate::change_detection::Mut) or [`ResMut<T>`](ResMut).
1700
#[derive(Debug, Clone, Copy)]
1701
pub struct SystemChangeTick {
1702
last_run: Tick,
1703
this_run: Tick,
1704
}
1705
1706
impl SystemChangeTick {
1707
/// Returns the current [`World`] change tick seen by the system.
1708
#[inline]
1709
pub fn this_run(&self) -> Tick {
1710
self.this_run
1711
}
1712
1713
/// Returns the [`World`] change tick seen by the system the previous time it ran.
1714
#[inline]
1715
pub fn last_run(&self) -> Tick {
1716
self.last_run
1717
}
1718
}
1719
1720
// SAFETY: Only reads internal system state
1721
unsafe impl ReadOnlySystemParam for SystemChangeTick {}
1722
1723
// SAFETY: `SystemChangeTick` doesn't require any world access
1724
unsafe impl SystemParam for SystemChangeTick {
1725
type State = ();
1726
type Item<'w, 's> = SystemChangeTick;
1727
1728
fn init_state(_world: &mut World) -> Self::State {}
1729
1730
fn init_access(
1731
_state: &Self::State,
1732
_system_meta: &mut SystemMeta,
1733
_component_access_set: &mut FilteredAccessSet,
1734
_world: &mut World,
1735
) {
1736
}
1737
1738
#[inline]
1739
unsafe fn get_param<'w, 's>(
1740
_state: &'s mut Self::State,
1741
system_meta: &SystemMeta,
1742
_world: UnsafeWorldCell<'w>,
1743
change_tick: Tick,
1744
) -> Self::Item<'w, 's> {
1745
SystemChangeTick {
1746
last_run: system_meta.last_run,
1747
this_run: change_tick,
1748
}
1749
}
1750
}
1751
1752
// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1753
unsafe impl<T: SystemParam> SystemParam for Option<T> {
1754
type State = T::State;
1755
1756
type Item<'world, 'state> = Option<T::Item<'world, 'state>>;
1757
1758
fn init_state(world: &mut World) -> Self::State {
1759
T::init_state(world)
1760
}
1761
1762
fn init_access(
1763
state: &Self::State,
1764
system_meta: &mut SystemMeta,
1765
component_access_set: &mut FilteredAccessSet,
1766
world: &mut World,
1767
) {
1768
T::init_access(state, system_meta, component_access_set, world);
1769
}
1770
1771
#[inline]
1772
unsafe fn get_param<'world, 'state>(
1773
state: &'state mut Self::State,
1774
system_meta: &SystemMeta,
1775
world: UnsafeWorldCell<'world>,
1776
change_tick: Tick,
1777
) -> Self::Item<'world, 'state> {
1778
T::validate_param(state, system_meta, world)
1779
.ok()
1780
.map(|()| T::get_param(state, system_meta, world, change_tick))
1781
}
1782
1783
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1784
T::apply(state, system_meta, world);
1785
}
1786
1787
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1788
T::queue(state, system_meta, world);
1789
}
1790
}
1791
1792
// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1793
unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Option<T> {}
1794
1795
// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1796
unsafe impl<T: SystemParam> SystemParam for Result<T, SystemParamValidationError> {
1797
type State = T::State;
1798
1799
type Item<'world, 'state> = Result<T::Item<'world, 'state>, SystemParamValidationError>;
1800
1801
fn init_state(world: &mut World) -> Self::State {
1802
T::init_state(world)
1803
}
1804
1805
fn init_access(
1806
state: &Self::State,
1807
system_meta: &mut SystemMeta,
1808
component_access_set: &mut FilteredAccessSet,
1809
world: &mut World,
1810
) {
1811
T::init_access(state, system_meta, component_access_set, world);
1812
}
1813
1814
#[inline]
1815
unsafe fn get_param<'world, 'state>(
1816
state: &'state mut Self::State,
1817
system_meta: &SystemMeta,
1818
world: UnsafeWorldCell<'world>,
1819
change_tick: Tick,
1820
) -> Self::Item<'world, 'state> {
1821
T::validate_param(state, system_meta, world)
1822
.map(|()| T::get_param(state, system_meta, world, change_tick))
1823
}
1824
1825
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1826
T::apply(state, system_meta, world);
1827
}
1828
1829
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1830
T::queue(state, system_meta, world);
1831
}
1832
}
1833
1834
// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1835
unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Result<T, SystemParamValidationError> {}
1836
1837
/// A [`SystemParam`] that wraps another parameter and causes its system to skip instead of failing when the parameter is invalid.
1838
///
1839
/// # Example
1840
///
1841
/// ```
1842
/// # use bevy_ecs::prelude::*;
1843
/// # #[derive(Resource)]
1844
/// # struct SomeResource;
1845
/// // This system will fail if `SomeResource` is not present.
1846
/// fn fails_on_missing_resource(res: Res<SomeResource>) {}
1847
///
1848
/// // This system will skip without error if `SomeResource` is not present.
1849
/// fn skips_on_missing_resource(res: If<Res<SomeResource>>) {
1850
/// // The inner parameter is available using `Deref`
1851
/// let some_resource: &SomeResource = &res;
1852
/// }
1853
/// # bevy_ecs::system::assert_is_system(skips_on_missing_resource);
1854
/// ```
1855
#[derive(Debug)]
1856
pub struct If<T>(pub T);
1857
1858
impl<T> If<T> {
1859
/// Returns the inner `T`.
1860
///
1861
/// The inner value is `pub`, so you can also obtain it by destructuring the parameter:
1862
///
1863
/// ```
1864
/// # use bevy_ecs::prelude::*;
1865
/// # #[derive(Resource)]
1866
/// # struct SomeResource;
1867
/// fn skips_on_missing_resource(If(res): If<Res<SomeResource>>) {
1868
/// let some_resource: Res<SomeResource> = res;
1869
/// }
1870
/// # bevy_ecs::system::assert_is_system(skips_on_missing_resource);
1871
/// ```
1872
pub fn into_inner(self) -> T {
1873
self.0
1874
}
1875
}
1876
1877
impl<T> Deref for If<T> {
1878
type Target = T;
1879
fn deref(&self) -> &Self::Target {
1880
&self.0
1881
}
1882
}
1883
1884
impl<T> DerefMut for If<T> {
1885
fn deref_mut(&mut self) -> &mut Self::Target {
1886
&mut self.0
1887
}
1888
}
1889
1890
// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1891
unsafe impl<T: SystemParam> SystemParam for If<T> {
1892
type State = T::State;
1893
1894
type Item<'world, 'state> = If<T::Item<'world, 'state>>;
1895
1896
fn init_state(world: &mut World) -> Self::State {
1897
T::init_state(world)
1898
}
1899
1900
fn init_access(
1901
state: &Self::State,
1902
system_meta: &mut SystemMeta,
1903
component_access_set: &mut FilteredAccessSet,
1904
world: &mut World,
1905
) {
1906
T::init_access(state, system_meta, component_access_set, world);
1907
}
1908
1909
#[inline]
1910
unsafe fn validate_param(
1911
state: &mut Self::State,
1912
system_meta: &SystemMeta,
1913
world: UnsafeWorldCell,
1914
) -> Result<(), SystemParamValidationError> {
1915
T::validate_param(state, system_meta, world).map_err(|mut e| {
1916
e.skipped = true;
1917
e
1918
})
1919
}
1920
1921
#[inline]
1922
unsafe fn get_param<'world, 'state>(
1923
state: &'state mut Self::State,
1924
system_meta: &SystemMeta,
1925
world: UnsafeWorldCell<'world>,
1926
change_tick: Tick,
1927
) -> Self::Item<'world, 'state> {
1928
If(T::get_param(state, system_meta, world, change_tick))
1929
}
1930
1931
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1932
T::apply(state, system_meta, world);
1933
}
1934
1935
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1936
T::queue(state, system_meta, world);
1937
}
1938
}
1939
1940
// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1941
unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for If<T> {}
1942
1943
// SAFETY: Registers access for each element of `state`.
1944
// If any one conflicts, it will panic.
1945
unsafe impl<T: SystemParam> SystemParam for Vec<T> {
1946
type State = Vec<T::State>;
1947
1948
type Item<'world, 'state> = Vec<T::Item<'world, 'state>>;
1949
1950
fn init_state(_world: &mut World) -> Self::State {
1951
Vec::new()
1952
}
1953
1954
fn init_access(
1955
state: &Self::State,
1956
system_meta: &mut SystemMeta,
1957
component_access_set: &mut FilteredAccessSet,
1958
world: &mut World,
1959
) {
1960
for state in state {
1961
T::init_access(state, system_meta, component_access_set, world);
1962
}
1963
}
1964
1965
#[inline]
1966
unsafe fn validate_param(
1967
state: &mut Self::State,
1968
system_meta: &SystemMeta,
1969
world: UnsafeWorldCell,
1970
) -> Result<(), SystemParamValidationError> {
1971
for state in state {
1972
T::validate_param(state, system_meta, world)?;
1973
}
1974
Ok(())
1975
}
1976
1977
#[inline]
1978
unsafe fn get_param<'world, 'state>(
1979
state: &'state mut Self::State,
1980
system_meta: &SystemMeta,
1981
world: UnsafeWorldCell<'world>,
1982
change_tick: Tick,
1983
) -> Self::Item<'world, 'state> {
1984
state
1985
.iter_mut()
1986
// SAFETY:
1987
// - We initialized the access for each parameter in `init_access`, so the caller ensures we have access to any world data needed by each param.
1988
// - The caller ensures this was the world used to initialize our state, and we used that world to initialize parameter states
1989
.map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) })
1990
.collect()
1991
}
1992
1993
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1994
for state in state {
1995
T::apply(state, system_meta, world);
1996
}
1997
}
1998
1999
fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2000
for state in state {
2001
T::queue(state, system_meta, world.reborrow());
2002
}
2003
}
2004
}
2005
2006
// SAFETY: Registers access for each element of `state`.
2007
// If any one conflicts with a previous parameter,
2008
// the call passing a copy of the current access will panic.
2009
unsafe impl<T: SystemParam> SystemParam for ParamSet<'_, '_, Vec<T>> {
2010
type State = Vec<T::State>;
2011
2012
type Item<'world, 'state> = ParamSet<'world, 'state, Vec<T>>;
2013
2014
fn init_state(_world: &mut World) -> Self::State {
2015
Vec::new()
2016
}
2017
2018
fn init_access(
2019
state: &Self::State,
2020
system_meta: &mut SystemMeta,
2021
component_access_set: &mut FilteredAccessSet,
2022
world: &mut World,
2023
) {
2024
for state in state {
2025
// Call `init_access` on a clone of the original access set to check for conflicts
2026
let component_access_set_clone = &mut component_access_set.clone();
2027
T::init_access(state, system_meta, component_access_set_clone, world);
2028
}
2029
for state in state {
2030
// Pretend to add the param to the system alone to gather the new access,
2031
// then merge its access into the system.
2032
let mut access_set = FilteredAccessSet::new();
2033
T::init_access(state, system_meta, &mut access_set, world);
2034
component_access_set.extend(access_set);
2035
}
2036
}
2037
2038
#[inline]
2039
unsafe fn get_param<'world, 'state>(
2040
state: &'state mut Self::State,
2041
system_meta: &SystemMeta,
2042
world: UnsafeWorldCell<'world>,
2043
change_tick: Tick,
2044
) -> Self::Item<'world, 'state> {
2045
ParamSet {
2046
param_states: state,
2047
system_meta: system_meta.clone(),
2048
world,
2049
change_tick,
2050
}
2051
}
2052
2053
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2054
for state in state {
2055
T::apply(state, system_meta, world);
2056
}
2057
}
2058
2059
fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2060
for state in state {
2061
T::queue(state, system_meta, world.reborrow());
2062
}
2063
}
2064
}
2065
2066
impl<T: SystemParam> ParamSet<'_, '_, Vec<T>> {
2067
/// Accesses the parameter at the given index.
2068
/// No other parameters may be accessed while this one is active.
2069
pub fn get_mut(&mut self, index: usize) -> T::Item<'_, '_> {
2070
// SAFETY:
2071
// - We initialized the access for each parameter, so the caller ensures we have access to any world data needed by any param.
2072
// We have mutable access to the ParamSet, so no other params in the set are active.
2073
// - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states
2074
unsafe {
2075
T::get_param(
2076
&mut self.param_states[index],
2077
&self.system_meta,
2078
self.world,
2079
self.change_tick,
2080
)
2081
}
2082
}
2083
2084
/// Calls a closure for each parameter in the set.
2085
pub fn for_each(&mut self, mut f: impl FnMut(T::Item<'_, '_>)) {
2086
self.param_states.iter_mut().for_each(|state| {
2087
f(
2088
// SAFETY:
2089
// - We initialized the access for each parameter, so the caller ensures we have access to any world data needed by any param.
2090
// We have mutable access to the ParamSet, so no other params in the set are active.
2091
// - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states
2092
unsafe { T::get_param(state, &self.system_meta, self.world, self.change_tick) },
2093
);
2094
});
2095
}
2096
}
2097
2098
macro_rules! impl_system_param_tuple {
2099
($(#[$meta:meta])* $($param: ident),*) => {
2100
$(#[$meta])*
2101
// SAFETY: tuple consists only of ReadOnlySystemParams
2102
unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}
2103
2104
#[expect(
2105
clippy::allow_attributes,
2106
reason = "This is in a macro, and as such, the below lints may not always apply."
2107
)]
2108
#[allow(
2109
non_snake_case,
2110
reason = "Certain variable names are provided by the caller, not by us."
2111
)]
2112
#[allow(
2113
unused_variables,
2114
reason = "Zero-length tuples won't use some of the parameters."
2115
)]
2116
$(#[$meta])*
2117
// SAFETY: implementers of each `SystemParam` in the tuple have validated their impls
2118
unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
2119
type State = ($($param::State,)*);
2120
type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);
2121
2122
#[inline]
2123
fn init_state(world: &mut World) -> Self::State {
2124
(($($param::init_state(world),)*))
2125
}
2126
2127
fn init_access(state: &Self::State, _system_meta: &mut SystemMeta, _component_access_set: &mut FilteredAccessSet, _world: &mut World) {
2128
let ($($param,)*) = state;
2129
$($param::init_access($param, _system_meta, _component_access_set, _world);)*
2130
}
2131
2132
#[inline]
2133
fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2134
$($param::apply($param, system_meta, world);)*
2135
}
2136
2137
#[inline]
2138
#[allow(
2139
unused_mut,
2140
reason = "The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples."
2141
)]
2142
fn queue(($($param,)*): &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2143
$($param::queue($param, system_meta, world.reborrow());)*
2144
}
2145
2146
#[inline]
2147
unsafe fn validate_param(
2148
state: &mut Self::State,
2149
system_meta: &SystemMeta,
2150
world: UnsafeWorldCell,
2151
) -> Result<(), SystemParamValidationError> {
2152
let ($($param,)*) = state;
2153
$(
2154
$param::validate_param($param, system_meta, world)?;
2155
)*
2156
Ok(())
2157
}
2158
2159
#[inline]
2160
unsafe fn get_param<'w, 's>(
2161
state: &'s mut Self::State,
2162
system_meta: &SystemMeta,
2163
world: UnsafeWorldCell<'w>,
2164
change_tick: Tick,
2165
) -> Self::Item<'w, 's> {
2166
let ($($param,)*) = state;
2167
#[allow(
2168
clippy::unused_unit,
2169
reason = "Zero-length tuples won't have any params to get."
2170
)]
2171
($($param::get_param($param, system_meta, world, change_tick),)*)
2172
}
2173
}
2174
};
2175
}
2176
2177
all_tuples!(
2178
#[doc(fake_variadic)]
2179
impl_system_param_tuple,
2180
0,
2181
16,
2182
P
2183
);
2184
2185
/// Contains type aliases for built-in [`SystemParam`]s with `'static` lifetimes.
2186
/// This makes it more convenient to refer to these types in contexts where
2187
/// explicit lifetime annotations are required.
2188
///
2189
/// Note that this is entirely safe and tracks lifetimes correctly.
2190
/// This purely exists for convenience.
2191
///
2192
/// You can't instantiate a static `SystemParam`, you'll always end up with
2193
/// `Res<'w, T>`, `ResMut<'w, T>` or `&'w T` bound to the lifetime of the provided
2194
/// `&'w World`.
2195
///
2196
/// [`SystemParam`]: super::SystemParam
2197
pub mod lifetimeless {
2198
/// A [`Query`](super::Query) with `'static` lifetimes.
2199
pub type SQuery<D, F = ()> = super::Query<'static, 'static, D, F>;
2200
/// A shorthand for writing `&'static T`.
2201
pub type Read<T> = &'static T;
2202
/// A shorthand for writing `&'static mut T`.
2203
pub type Write<T> = &'static mut T;
2204
/// A [`Res`](super::Res) with `'static` lifetimes.
2205
pub type SRes<T> = super::Res<'static, T>;
2206
/// A [`ResMut`](super::ResMut) with `'static` lifetimes.
2207
pub type SResMut<T> = super::ResMut<'static, T>;
2208
/// [`Commands`](crate::system::Commands) with `'static` lifetimes.
2209
pub type SCommands = crate::system::Commands<'static, 'static>;
2210
}
2211
2212
/// A helper for using system parameters in generic contexts
2213
///
2214
/// This type is a [`SystemParam`] adapter which always has
2215
/// `Self::Item == Self` (ignoring lifetimes for brevity),
2216
/// no matter the argument [`SystemParam`] (`P`) (other than
2217
/// that `P` must be `'static`)
2218
///
2219
/// This makes it useful for having arbitrary [`SystemParam`] type arguments
2220
/// to function systems, or for generic types using the [`derive@SystemParam`]
2221
/// derive:
2222
///
2223
/// ```
2224
/// # use bevy_ecs::prelude::*;
2225
/// use bevy_ecs::system::{SystemParam, StaticSystemParam};
2226
/// #[derive(SystemParam)]
2227
/// struct GenericParam<'w,'s, T: SystemParam + 'static> {
2228
/// field: StaticSystemParam<'w, 's, T>,
2229
/// }
2230
/// fn do_thing_generically<T: SystemParam + 'static>(t: StaticSystemParam<T>) {}
2231
///
2232
/// fn check_always_is_system<T: SystemParam + 'static>(){
2233
/// bevy_ecs::system::assert_is_system(do_thing_generically::<T>);
2234
/// }
2235
/// ```
2236
/// Note that in a real case you'd generally want
2237
/// additional bounds on `P`, for your use of the parameter
2238
/// to have a reason to be generic.
2239
///
2240
/// For example, using this would allow a type to be generic over
2241
/// whether a resource is accessed mutably or not, with
2242
/// impls being bounded on [`P: Deref<Target=MyType>`](Deref), and
2243
/// [`P: DerefMut<Target=MyType>`](DerefMut) depending on whether the
2244
/// method requires mutable access or not.
2245
///
2246
/// The method which doesn't use this type will not compile:
2247
/// ```compile_fail
2248
/// # use bevy_ecs::prelude::*;
2249
/// # use bevy_ecs::system::{SystemParam, StaticSystemParam};
2250
///
2251
/// fn do_thing_generically<T: SystemParam + 'static>(t: T) {}
2252
///
2253
/// #[derive(SystemParam)]
2254
/// struct GenericParam<'w, 's, T: SystemParam> {
2255
/// field: T,
2256
/// // Use the lifetimes in this type, or they will be unbound.
2257
/// phantom: std::marker::PhantomData<&'w &'s ()>
2258
/// }
2259
/// # fn check_always_is_system<T: SystemParam + 'static>(){
2260
/// # bevy_ecs::system::assert_is_system(do_thing_generically::<T>);
2261
/// # }
2262
/// ```
2263
pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>);
2264
2265
impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> {
2266
type Target = SystemParamItem<'w, 's, P>;
2267
2268
fn deref(&self) -> &Self::Target {
2269
&self.0
2270
}
2271
}
2272
2273
impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {
2274
fn deref_mut(&mut self) -> &mut Self::Target {
2275
&mut self.0
2276
}
2277
}
2278
2279
impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {
2280
/// Get the value of the parameter
2281
pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {
2282
self.0
2283
}
2284
}
2285
2286
// SAFETY: This doesn't add any more reads, and the delegated fetch confirms it
2287
unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam
2288
for StaticSystemParam<'w, 's, P>
2289
{
2290
}
2291
2292
// SAFETY: all methods are just delegated to `P`'s `SystemParam` implementation
2293
unsafe impl<P: SystemParam + 'static> SystemParam for StaticSystemParam<'_, '_, P> {
2294
type State = P::State;
2295
type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;
2296
2297
fn init_state(world: &mut World) -> Self::State {
2298
P::init_state(world)
2299
}
2300
2301
fn init_access(
2302
state: &Self::State,
2303
system_meta: &mut SystemMeta,
2304
component_access_set: &mut FilteredAccessSet,
2305
world: &mut World,
2306
) {
2307
P::init_access(state, system_meta, component_access_set, world);
2308
}
2309
2310
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2311
P::apply(state, system_meta, world);
2312
}
2313
2314
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2315
P::queue(state, system_meta, world);
2316
}
2317
2318
#[inline]
2319
unsafe fn validate_param(
2320
state: &mut Self::State,
2321
system_meta: &SystemMeta,
2322
world: UnsafeWorldCell,
2323
) -> Result<(), SystemParamValidationError> {
2324
P::validate_param(state, system_meta, world)
2325
}
2326
2327
#[inline]
2328
unsafe fn get_param<'world, 'state>(
2329
state: &'state mut Self::State,
2330
system_meta: &SystemMeta,
2331
world: UnsafeWorldCell<'world>,
2332
change_tick: Tick,
2333
) -> Self::Item<'world, 'state> {
2334
// SAFETY: Defer to the safety of P::SystemParam
2335
StaticSystemParam(unsafe { P::get_param(state, system_meta, world, change_tick) })
2336
}
2337
}
2338
2339
// SAFETY: No world access.
2340
unsafe impl<T: ?Sized> SystemParam for PhantomData<T> {
2341
type State = ();
2342
type Item<'world, 'state> = Self;
2343
2344
fn init_state(_world: &mut World) -> Self::State {}
2345
2346
fn init_access(
2347
_state: &Self::State,
2348
_system_meta: &mut SystemMeta,
2349
_component_access_set: &mut FilteredAccessSet,
2350
_world: &mut World,
2351
) {
2352
}
2353
2354
#[inline]
2355
unsafe fn get_param<'world, 'state>(
2356
_state: &'state mut Self::State,
2357
_system_meta: &SystemMeta,
2358
_world: UnsafeWorldCell<'world>,
2359
_change_tick: Tick,
2360
) -> Self::Item<'world, 'state> {
2361
PhantomData
2362
}
2363
}
2364
2365
// SAFETY: No world access.
2366
unsafe impl<T: ?Sized> ReadOnlySystemParam for PhantomData<T> {}
2367
2368
/// A [`SystemParam`] with a type that can be configured at runtime.
2369
///
2370
/// To be useful, this must be configured using a [`DynParamBuilder`](crate::system::DynParamBuilder) to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).
2371
///
2372
/// # Examples
2373
///
2374
/// ```
2375
/// # use bevy_ecs::{prelude::*, system::*};
2376
/// #
2377
/// # #[derive(Default, Resource)]
2378
/// # struct A;
2379
/// #
2380
/// # #[derive(Default, Resource)]
2381
/// # struct B;
2382
/// #
2383
/// # let mut world = World::new();
2384
/// # world.init_resource::<A>();
2385
/// # world.init_resource::<B>();
2386
/// #
2387
/// // If the inner parameter doesn't require any special building, use `ParamBuilder`.
2388
/// // Either specify the type parameter on `DynParamBuilder::new()` ...
2389
/// let system = (DynParamBuilder::new::<Res<A>>(ParamBuilder),)
2390
/// .build_state(&mut world)
2391
/// .build_system(expects_res_a);
2392
/// # world.run_system_once(system);
2393
///
2394
/// // ... or use a factory method on `ParamBuilder` that returns a specific type.
2395
/// let system = (DynParamBuilder::new(ParamBuilder::resource::<A>()),)
2396
/// .build_state(&mut world)
2397
/// .build_system(expects_res_a);
2398
/// # world.run_system_once(system);
2399
///
2400
/// fn expects_res_a(mut param: DynSystemParam) {
2401
/// // Use the `downcast` methods to retrieve the inner parameter.
2402
/// // They will return `None` if the type does not match.
2403
/// assert!(param.is::<Res<A>>());
2404
/// assert!(!param.is::<Res<B>>());
2405
/// assert!(param.downcast_mut::<Res<B>>().is_none());
2406
/// let res = param.downcast_mut::<Res<A>>().unwrap();
2407
/// // The type parameter can be left out if it can be determined from use.
2408
/// let res: Res<A> = param.downcast().unwrap();
2409
/// }
2410
///
2411
/// let system = (
2412
/// // If the inner parameter also requires building,
2413
/// // pass the appropriate `SystemParamBuilder`.
2414
/// DynParamBuilder::new(LocalBuilder(10usize)),
2415
/// // `DynSystemParam` is just an ordinary `SystemParam`,
2416
/// // and can be combined with other parameters as usual!
2417
/// ParamBuilder::query(),
2418
/// )
2419
/// .build_state(&mut world)
2420
/// .build_system(|param: DynSystemParam, query: Query<()>| {
2421
/// let local: Local<usize> = param.downcast::<Local<usize>>().unwrap();
2422
/// assert_eq!(*local, 10);
2423
/// });
2424
/// # world.run_system_once(system);
2425
/// ```
2426
pub struct DynSystemParam<'w, 's> {
2427
/// A `ParamState<T>` wrapping the state for the underlying system param.
2428
state: &'s mut dyn Any,
2429
world: UnsafeWorldCell<'w>,
2430
system_meta: SystemMeta,
2431
change_tick: Tick,
2432
}
2433
2434
impl<'w, 's> DynSystemParam<'w, 's> {
2435
/// # Safety
2436
/// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.
2437
/// - The passed [`UnsafeWorldCell`] must have access to any world data registered
2438
/// in [`init_state`](SystemParam::init_state) for the inner system param.
2439
/// - `world` must be the same `World` that was used to initialize
2440
/// [`state`](SystemParam::init_state) for the inner system param.
2441
unsafe fn new(
2442
state: &'s mut dyn Any,
2443
world: UnsafeWorldCell<'w>,
2444
system_meta: SystemMeta,
2445
change_tick: Tick,
2446
) -> Self {
2447
Self {
2448
state,
2449
world,
2450
system_meta,
2451
change_tick,
2452
}
2453
}
2454
2455
/// Returns `true` if the inner system param is the same as `T`.
2456
pub fn is<T: SystemParam>(&self) -> bool
2457
// See downcast() function for an explanation of the where clause
2458
where
2459
T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2460
{
2461
self.state.is::<ParamState<T::Item<'static, 'static>>>()
2462
}
2463
2464
/// Returns the inner system param if it is the correct type.
2465
/// This consumes the dyn param, so the returned param can have its original world and state lifetimes.
2466
pub fn downcast<T: SystemParam>(self) -> Option<T>
2467
// See downcast() function for an explanation of the where clause
2468
where
2469
T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2470
{
2471
// SAFETY:
2472
// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2473
// and that it has access required by the inner system param.
2474
// - This consumes the `DynSystemParam`, so it is the only use of `world` with this access and it is available for `'w`.
2475
unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2476
}
2477
2478
/// Returns the inner system parameter if it is the correct type.
2479
/// This borrows the dyn param, so the returned param is only valid for the duration of that borrow.
2480
pub fn downcast_mut<'a, T: SystemParam>(&'a mut self) -> Option<T>
2481
// See downcast() function for an explanation of the where clause
2482
where
2483
T::Item<'static, 'static>: SystemParam<Item<'a, 'a> = T> + 'static,
2484
{
2485
// SAFETY:
2486
// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2487
// and that it has access required by the inner system param.
2488
// - This exclusively borrows the `DynSystemParam` for `'_`, so it is the only use of `world` with this access for `'_`.
2489
unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2490
}
2491
2492
/// Returns the inner system parameter if it is the correct type.
2493
/// This borrows the dyn param, so the returned param is only valid for the duration of that borrow,
2494
/// but since it only performs read access it can keep the original world lifetime.
2495
/// This can be useful with methods like [`Query::iter_inner()`] or [`Res::into_inner()`]
2496
/// to obtain references with the original world lifetime.
2497
pub fn downcast_mut_inner<'a, T: ReadOnlySystemParam>(&'a mut self) -> Option<T>
2498
// See downcast() function for an explanation of the where clause
2499
where
2500
T::Item<'static, 'static>: SystemParam<Item<'w, 'a> = T> + 'static,
2501
{
2502
// SAFETY:
2503
// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2504
// and that it has access required by the inner system param.
2505
// - The inner system param only performs read access, so it's safe to copy that access for the full `'w` lifetime.
2506
unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2507
}
2508
}
2509
2510
/// # Safety
2511
/// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.
2512
/// - The passed [`UnsafeWorldCell`] must have access to any world data registered
2513
/// in [`init_state`](SystemParam::init_state) for the inner system param.
2514
/// - `world` must be the same `World` that was used to initialize
2515
/// [`state`](SystemParam::init_state) for the inner system param.
2516
unsafe fn downcast<'w, 's, T: SystemParam>(
2517
state: &'s mut dyn Any,
2518
system_meta: &SystemMeta,
2519
world: UnsafeWorldCell<'w>,
2520
change_tick: Tick,
2521
) -> Option<T>
2522
// We need a 'static version of the SystemParam to use with `Any::downcast_mut()`,
2523
// and we need a <'w, 's> version to actually return.
2524
// The type parameter T must be the one we return in order to get type inference from the return value.
2525
// So we use `T::Item<'static, 'static>` as the 'static version, and require that it be 'static.
2526
// That means the return value will be T::Item<'static, 'static>::Item<'w, 's>,
2527
// so we constrain that to be equal to T.
2528
// Every actual `SystemParam` implementation has `T::Item == T` up to lifetimes,
2529
// so they should all work with this constraint.
2530
where
2531
T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2532
{
2533
state
2534
.downcast_mut::<ParamState<T::Item<'static, 'static>>>()
2535
.map(|state| {
2536
// SAFETY:
2537
// - The caller ensures the world has access for the underlying system param,
2538
// and since the downcast succeeded, the underlying system param is T.
2539
// - The caller ensures the `world` matches.
2540
unsafe { T::Item::get_param(&mut state.0, system_meta, world, change_tick) }
2541
})
2542
}
2543
2544
/// The [`SystemParam::State`] for a [`DynSystemParam`].
2545
pub struct DynSystemParamState(Box<dyn DynParamState>);
2546
2547
impl DynSystemParamState {
2548
pub(crate) fn new<T: SystemParam + 'static>(state: T::State) -> Self {
2549
Self(Box::new(ParamState::<T>(state)))
2550
}
2551
}
2552
2553
/// Allows a [`SystemParam::State`] to be used as a trait object for implementing [`DynSystemParam`].
2554
trait DynParamState: Sync + Send + Any {
2555
/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
2556
/// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
2557
///
2558
/// [`Commands`]: crate::prelude::Commands
2559
fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
2560
2561
/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
2562
fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);
2563
2564
/// Registers any [`World`] access used by this [`SystemParam`]
2565
fn init_access(
2566
&self,
2567
system_meta: &mut SystemMeta,
2568
component_access_set: &mut FilteredAccessSet,
2569
world: &mut World,
2570
);
2571
2572
/// Refer to [`SystemParam::validate_param`].
2573
///
2574
/// # Safety
2575
/// Refer to [`SystemParam::validate_param`].
2576
unsafe fn validate_param(
2577
&mut self,
2578
system_meta: &SystemMeta,
2579
world: UnsafeWorldCell,
2580
) -> Result<(), SystemParamValidationError>;
2581
}
2582
2583
/// A wrapper around a [`SystemParam::State`] that can be used as a trait object in a [`DynSystemParam`].
2584
struct ParamState<T: SystemParam>(T::State);
2585
2586
impl<T: SystemParam + 'static> DynParamState for ParamState<T> {
2587
fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
2588
T::apply(&mut self.0, system_meta, world);
2589
}
2590
2591
fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld) {
2592
T::queue(&mut self.0, system_meta, world);
2593
}
2594
2595
fn init_access(
2596
&self,
2597
system_meta: &mut SystemMeta,
2598
component_access_set: &mut FilteredAccessSet,
2599
world: &mut World,
2600
) {
2601
T::init_access(&self.0, system_meta, component_access_set, world);
2602
}
2603
2604
unsafe fn validate_param(
2605
&mut self,
2606
system_meta: &SystemMeta,
2607
world: UnsafeWorldCell,
2608
) -> Result<(), SystemParamValidationError> {
2609
T::validate_param(&mut self.0, system_meta, world)
2610
}
2611
}
2612
2613
// SAFETY: Delegates to the wrapped parameter, which ensures the safety requirements are met
2614
unsafe impl SystemParam for DynSystemParam<'_, '_> {
2615
type State = DynSystemParamState;
2616
2617
type Item<'world, 'state> = DynSystemParam<'world, 'state>;
2618
2619
fn init_state(_world: &mut World) -> Self::State {
2620
DynSystemParamState::new::<()>(())
2621
}
2622
2623
fn init_access(
2624
state: &Self::State,
2625
system_meta: &mut SystemMeta,
2626
component_access_set: &mut FilteredAccessSet,
2627
world: &mut World,
2628
) {
2629
state
2630
.0
2631
.init_access(system_meta, component_access_set, world);
2632
}
2633
2634
#[inline]
2635
unsafe fn validate_param(
2636
state: &mut Self::State,
2637
system_meta: &SystemMeta,
2638
world: UnsafeWorldCell,
2639
) -> Result<(), SystemParamValidationError> {
2640
state.0.validate_param(system_meta, world)
2641
}
2642
2643
#[inline]
2644
unsafe fn get_param<'world, 'state>(
2645
state: &'state mut Self::State,
2646
system_meta: &SystemMeta,
2647
world: UnsafeWorldCell<'world>,
2648
change_tick: Tick,
2649
) -> Self::Item<'world, 'state> {
2650
// SAFETY:
2651
// - `state.0` is a boxed `ParamState<T>`.
2652
// - `init_access` calls `DynParamState::init_access`, which calls `init_access` on the inner parameter,
2653
// so the caller ensures the world has the necessary access.
2654
// - The caller ensures that the provided world is the same and has the required access.
2655
unsafe { DynSystemParam::new(state.0.as_mut(), world, system_meta.clone(), change_tick) }
2656
}
2657
2658
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2659
state.0.apply(system_meta, world);
2660
}
2661
2662
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2663
state.0.queue(system_meta, world);
2664
}
2665
}
2666
2667
// SAFETY: Resource ComponentId access is applied to the access. If this FilteredResources
2668
// conflicts with any prior access, a panic will occur.
2669
unsafe impl SystemParam for FilteredResources<'_, '_> {
2670
type State = Access;
2671
2672
type Item<'world, 'state> = FilteredResources<'world, 'state>;
2673
2674
fn init_state(_world: &mut World) -> Self::State {
2675
Access::new()
2676
}
2677
2678
fn init_access(
2679
access: &Self::State,
2680
system_meta: &mut SystemMeta,
2681
component_access_set: &mut FilteredAccessSet,
2682
world: &mut World,
2683
) {
2684
let combined_access = component_access_set.combined_access();
2685
let conflicts = combined_access.get_conflicts(access);
2686
if !conflicts.is_empty() {
2687
let accesses = conflicts.format_conflict_list(world);
2688
let system_name = &system_meta.name;
2689
panic!("error[B0002]: FilteredResources in system {system_name} accesses resources(s){accesses} in a way that conflicts with a previous system parameter. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002");
2690
}
2691
2692
if access.has_read_all_resources() {
2693
component_access_set.add_unfiltered_read_all_resources();
2694
} else {
2695
for component_id in access.resource_reads_and_writes() {
2696
component_access_set.add_unfiltered_resource_read(component_id);
2697
}
2698
}
2699
}
2700
2701
unsafe fn get_param<'world, 'state>(
2702
state: &'state mut Self::State,
2703
system_meta: &SystemMeta,
2704
world: UnsafeWorldCell<'world>,
2705
change_tick: Tick,
2706
) -> Self::Item<'world, 'state> {
2707
// SAFETY: The caller ensures that `world` has access to anything registered in `init_access`,
2708
// and we registered all resource access in `state``.
2709
unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) }
2710
}
2711
}
2712
2713
// SAFETY: FilteredResources only reads resources.
2714
unsafe impl ReadOnlySystemParam for FilteredResources<'_, '_> {}
2715
2716
// SAFETY: Resource ComponentId access is applied to the access. If this FilteredResourcesMut
2717
// conflicts with any prior access, a panic will occur.
2718
unsafe impl SystemParam for FilteredResourcesMut<'_, '_> {
2719
type State = Access;
2720
2721
type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>;
2722
2723
fn init_state(_world: &mut World) -> Self::State {
2724
Access::new()
2725
}
2726
2727
fn init_access(
2728
access: &Self::State,
2729
system_meta: &mut SystemMeta,
2730
component_access_set: &mut FilteredAccessSet,
2731
world: &mut World,
2732
) {
2733
let combined_access = component_access_set.combined_access();
2734
let conflicts = combined_access.get_conflicts(access);
2735
if !conflicts.is_empty() {
2736
let accesses = conflicts.format_conflict_list(world);
2737
let system_name = &system_meta.name;
2738
panic!("error[B0002]: FilteredResourcesMut in system {system_name} accesses resources(s){accesses} in a way that conflicts with a previous system parameter. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002");
2739
}
2740
2741
if access.has_read_all_resources() {
2742
component_access_set.add_unfiltered_read_all_resources();
2743
} else {
2744
for component_id in access.resource_reads() {
2745
component_access_set.add_unfiltered_resource_read(component_id);
2746
}
2747
}
2748
2749
if access.has_write_all_resources() {
2750
component_access_set.add_unfiltered_write_all_resources();
2751
} else {
2752
for component_id in access.resource_writes() {
2753
component_access_set.add_unfiltered_resource_write(component_id);
2754
}
2755
}
2756
}
2757
2758
unsafe fn get_param<'world, 'state>(
2759
state: &'state mut Self::State,
2760
system_meta: &SystemMeta,
2761
world: UnsafeWorldCell<'world>,
2762
change_tick: Tick,
2763
) -> Self::Item<'world, 'state> {
2764
// SAFETY: The caller ensures that `world` has access to anything registered in `init_access`,
2765
// and we registered all resource access in `state``.
2766
unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) }
2767
}
2768
}
2769
2770
/// An error that occurs when a system parameter is not valid,
2771
/// used by system executors to determine what to do with a system.
2772
///
2773
/// Returned as an error from [`SystemParam::validate_param`],
2774
/// and handled using the unified error handling mechanisms defined in [`bevy_ecs::error`].
2775
#[derive(Debug, PartialEq, Eq, Clone, Error)]
2776
pub struct SystemParamValidationError {
2777
/// Whether the system should be skipped.
2778
///
2779
/// If `false`, the error should be handled.
2780
/// By default, this will result in a panic. See [`crate::error`] for more information.
2781
///
2782
/// This is the default behavior, and is suitable for system params that should *always* be valid,
2783
/// either because sensible fallback behavior exists (like [`Query`]) or because
2784
/// failures in validation should be considered a bug in the user's logic that must be immediately addressed (like [`Res`]).
2785
///
2786
/// If `true`, the system should be skipped.
2787
/// This is set by wrapping the system param in [`If`],
2788
/// and indicates that the system is intended to only operate in certain application states.
2789
pub skipped: bool,
2790
2791
/// A message describing the validation error.
2792
pub message: Cow<'static, str>,
2793
2794
/// A string identifying the invalid parameter.
2795
/// This is usually the type name of the parameter.
2796
pub param: DebugName,
2797
2798
/// A string identifying the field within a parameter using `#[derive(SystemParam)]`.
2799
/// This will be an empty string for other parameters.
2800
///
2801
/// This will be printed after `param` in the `Display` impl, and should include a `::` prefix if non-empty.
2802
pub field: Cow<'static, str>,
2803
}
2804
2805
impl SystemParamValidationError {
2806
/// Constructs a `SystemParamValidationError` that skips the system.
2807
/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2808
pub fn skipped<T>(message: impl Into<Cow<'static, str>>) -> Self {
2809
Self::new::<T>(true, message, Cow::Borrowed(""))
2810
}
2811
2812
/// Constructs a `SystemParamValidationError` for an invalid parameter that should be treated as an error.
2813
/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2814
pub fn invalid<T>(message: impl Into<Cow<'static, str>>) -> Self {
2815
Self::new::<T>(false, message, Cow::Borrowed(""))
2816
}
2817
2818
/// Constructs a `SystemParamValidationError` for an invalid parameter.
2819
/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2820
pub fn new<T>(
2821
skipped: bool,
2822
message: impl Into<Cow<'static, str>>,
2823
field: impl Into<Cow<'static, str>>,
2824
) -> Self {
2825
Self {
2826
skipped,
2827
message: message.into(),
2828
param: DebugName::type_name::<T>(),
2829
field: field.into(),
2830
}
2831
}
2832
2833
pub(crate) const EMPTY: Self = Self {
2834
skipped: false,
2835
message: Cow::Borrowed(""),
2836
param: DebugName::borrowed(""),
2837
field: Cow::Borrowed(""),
2838
};
2839
}
2840
2841
impl Display for SystemParamValidationError {
2842
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
2843
write!(
2844
fmt,
2845
"Parameter `{}{}` failed validation: {}",
2846
self.param.shortname(),
2847
self.field,
2848
self.message
2849
)?;
2850
if !self.skipped {
2851
write!(fmt, "\nIf this is an expected state, wrap the parameter in `Option<T>` and handle `None` when it happens, or wrap the parameter in `If<T>` to skip the system when it happens.")?;
2852
}
2853
Ok(())
2854
}
2855
}
2856
2857
#[cfg(test)]
2858
mod tests {
2859
use super::*;
2860
use crate::system::assert_is_system;
2861
use core::cell::RefCell;
2862
2863
// Compile test for https://github.com/bevyengine/bevy/pull/2838.
2864
#[test]
2865
fn system_param_generic_bounds() {
2866
#[derive(SystemParam)]
2867
pub struct SpecialQuery<
2868
'w,
2869
's,
2870
D: QueryData + Send + Sync + 'static,
2871
F: QueryFilter + Send + Sync + 'static = (),
2872
> {
2873
_query: Query<'w, 's, D, F>,
2874
}
2875
2876
fn my_system(_: SpecialQuery<(), ()>) {}
2877
assert_is_system(my_system);
2878
}
2879
2880
// Compile tests for https://github.com/bevyengine/bevy/pull/6694.
2881
#[test]
2882
fn system_param_flexibility() {
2883
#[derive(SystemParam)]
2884
pub struct SpecialRes<'w, T: Resource> {
2885
_res: Res<'w, T>,
2886
}
2887
2888
#[derive(SystemParam)]
2889
pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> {
2890
_local: Local<'s, T>,
2891
}
2892
2893
#[derive(Resource)]
2894
struct R;
2895
2896
fn my_system(_: SpecialRes<R>, _: SpecialLocal<u32>) {}
2897
assert_is_system(my_system);
2898
}
2899
2900
#[derive(Resource)]
2901
pub struct R<const I: usize>;
2902
2903
// Compile test for https://github.com/bevyengine/bevy/pull/7001.
2904
#[test]
2905
fn system_param_const_generics() {
2906
#[expect(
2907
dead_code,
2908
reason = "This struct is used to ensure that const generics are supported as a SystemParam; thus, the inner value never needs to be read."
2909
)]
2910
#[derive(SystemParam)]
2911
pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);
2912
2913
fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {}
2914
assert_is_system(my_system);
2915
}
2916
2917
// Compile test for https://github.com/bevyengine/bevy/pull/6867.
2918
#[test]
2919
fn system_param_field_limit() {
2920
#[derive(SystemParam)]
2921
pub struct LongParam<'w> {
2922
// Each field should be a distinct type so there will
2923
// be an error if the derive messes up the field order.
2924
_r0: Res<'w, R<0>>,
2925
_r1: Res<'w, R<1>>,
2926
_r2: Res<'w, R<2>>,
2927
_r3: Res<'w, R<3>>,
2928
_r4: Res<'w, R<4>>,
2929
_r5: Res<'w, R<5>>,
2930
_r6: Res<'w, R<6>>,
2931
_r7: Res<'w, R<7>>,
2932
_r8: Res<'w, R<8>>,
2933
_r9: Res<'w, R<9>>,
2934
_r10: Res<'w, R<10>>,
2935
_r11: Res<'w, R<11>>,
2936
_r12: Res<'w, R<12>>,
2937
_r13: Res<'w, R<13>>,
2938
_r14: Res<'w, R<14>>,
2939
_r15: Res<'w, R<15>>,
2940
_r16: Res<'w, R<16>>,
2941
}
2942
2943
fn long_system(_: LongParam) {}
2944
assert_is_system(long_system);
2945
}
2946
2947
// Compile test for https://github.com/bevyengine/bevy/pull/6919.
2948
// Regression test for https://github.com/bevyengine/bevy/issues/7447.
2949
#[test]
2950
fn system_param_phantom_data() {
2951
#[derive(SystemParam)]
2952
struct PhantomParam<'w, T: Resource, Marker: 'static> {
2953
_foo: Res<'w, T>,
2954
marker: PhantomData<&'w Marker>,
2955
}
2956
2957
fn my_system(_: PhantomParam<R<0>, ()>) {}
2958
assert_is_system(my_system);
2959
}
2960
2961
// Compile tests for https://github.com/bevyengine/bevy/pull/6957.
2962
#[test]
2963
fn system_param_struct_variants() {
2964
#[derive(SystemParam)]
2965
pub struct UnitParam;
2966
2967
#[expect(
2968
dead_code,
2969
reason = "This struct is used to ensure that tuple structs are supported as a SystemParam; thus, the inner values never need to be read."
2970
)]
2971
#[derive(SystemParam)]
2972
pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>(
2973
Res<'w, R>,
2974
Local<'s, L>,
2975
);
2976
2977
fn my_system(_: UnitParam, _: TupleParam<R<0>, u32>) {}
2978
assert_is_system(my_system);
2979
}
2980
2981
// Regression test for https://github.com/bevyengine/bevy/issues/4200.
2982
#[test]
2983
fn system_param_private_fields() {
2984
#[derive(Resource)]
2985
struct PrivateResource;
2986
2987
#[expect(
2988
dead_code,
2989
reason = "This struct is used to ensure that SystemParam's derive can't leak private fields; thus, the inner values never need to be read."
2990
)]
2991
#[derive(SystemParam)]
2992
pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>);
2993
2994
fn my_system(_: EncapsulatedParam) {}
2995
assert_is_system(my_system);
2996
}
2997
2998
// Regression test for https://github.com/bevyengine/bevy/issues/7103.
2999
#[test]
3000
fn system_param_where_clause() {
3001
#[derive(SystemParam)]
3002
pub struct WhereParam<'w, 's, D>
3003
where
3004
D: 'static + QueryData,
3005
{
3006
_q: Query<'w, 's, D, ()>,
3007
}
3008
3009
fn my_system(_: WhereParam<()>) {}
3010
assert_is_system(my_system);
3011
}
3012
3013
// Regression test for https://github.com/bevyengine/bevy/issues/1727.
3014
#[test]
3015
fn system_param_name_collision() {
3016
#[derive(Resource)]
3017
pub struct FetchState;
3018
3019
#[derive(SystemParam)]
3020
pub struct Collide<'w> {
3021
_x: Res<'w, FetchState>,
3022
}
3023
3024
fn my_system(_: Collide) {}
3025
assert_is_system(my_system);
3026
}
3027
3028
// Regression test for https://github.com/bevyengine/bevy/issues/8192.
3029
#[test]
3030
fn system_param_invariant_lifetime() {
3031
#[derive(SystemParam)]
3032
pub struct InvariantParam<'w, 's> {
3033
_set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,
3034
}
3035
3036
fn my_system(_: InvariantParam) {}
3037
assert_is_system(my_system);
3038
}
3039
3040
// Compile test for https://github.com/bevyengine/bevy/pull/9589.
3041
#[test]
3042
fn non_sync_local() {
3043
fn non_sync_system(cell: Local<RefCell<u8>>) {
3044
assert_eq!(*cell.borrow(), 0);
3045
}
3046
3047
let mut world = World::new();
3048
let mut schedule = crate::schedule::Schedule::default();
3049
schedule.add_systems(non_sync_system);
3050
schedule.run(&mut world);
3051
}
3052
3053
// Regression test for https://github.com/bevyengine/bevy/issues/10207.
3054
#[test]
3055
fn param_set_non_send_first() {
3056
fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) {
3057
let _ = p.p0();
3058
p.p1();
3059
}
3060
3061
let mut world = World::new();
3062
world.insert_non_send_resource(core::ptr::null_mut::<u8>());
3063
let mut schedule = crate::schedule::Schedule::default();
3064
schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
3065
schedule.run(&mut world);
3066
}
3067
3068
// Regression test for https://github.com/bevyengine/bevy/issues/10207.
3069
#[test]
3070
fn param_set_non_send_second() {
3071
fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) {
3072
p.p0();
3073
let _ = p.p1();
3074
}
3075
3076
let mut world = World::new();
3077
world.insert_non_send_resource(core::ptr::null_mut::<u8>());
3078
let mut schedule = crate::schedule::Schedule::default();
3079
schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
3080
schedule.run(&mut world);
3081
}
3082
3083
fn _dyn_system_param_type_inference(mut p: DynSystemParam) {
3084
// Make sure the downcast() methods are able to infer their type parameters from the use of the return type.
3085
// This is just a compilation test, so there is nothing to run.
3086
let _query: Query<()> = p.downcast_mut().unwrap();
3087
let _query: Query<()> = p.downcast_mut_inner().unwrap();
3088
let _query: Query<()> = p.downcast().unwrap();
3089
}
3090
3091
#[test]
3092
#[should_panic]
3093
fn missing_resource_error() {
3094
#[derive(Resource)]
3095
pub struct MissingResource;
3096
3097
let mut schedule = crate::schedule::Schedule::default();
3098
schedule.add_systems(res_system);
3099
let mut world = World::new();
3100
schedule.run(&mut world);
3101
3102
fn res_system(_: Res<MissingResource>) {}
3103
}
3104
3105
#[test]
3106
#[should_panic]
3107
fn missing_event_error() {
3108
use crate::prelude::{BufferedEvent, EventReader};
3109
3110
#[derive(BufferedEvent)]
3111
pub struct MissingEvent;
3112
3113
let mut schedule = crate::schedule::Schedule::default();
3114
schedule.add_systems(event_system);
3115
let mut world = World::new();
3116
schedule.run(&mut world);
3117
3118
fn event_system(_: EventReader<MissingEvent>) {}
3119
}
3120
}
3121
3122