pub use crate::change_detection::{NonSendMut, ResMut}; use crate::{ archetype::{Archetype, Archetypes}, bundle::Bundles, change_detection::Ticks, component::{Component, ComponentId, ComponentTicks, Components}, entity::{Entities, Entity}, query::{ Access, FilteredAccess, FilteredAccessSet, QueryFetch, QueryState, ReadOnlyFetch, WorldQuery, }, system::{CommandQueue, Commands, Query, SystemMeta}, world::{FromWorld, World}, }; pub use bevy_ecs_macros::SystemParam; use bevy_ecs_macros::{all_tuples, impl_param_set}; use bevy_ptr::UnsafeCellDeref; use std::{ fmt::Debug, marker::PhantomData, ops::{Deref, DerefMut}, }; /// A parameter that can be used in a [`System`](super::System). /// /// # Derive /// /// This trait can be derived with the [`derive@super::SystemParam`] macro. /// This macro only works if each field on the derived struct implements [`SystemParam`]. /// Note: There are additional requirements on the field types. /// See the *Generic `SystemParam`s* section for details and workarounds of the probable /// cause if this derive causes an error to be emitted. /// /// /// The struct for which `SystemParam` is derived must (currently) have exactly /// two lifetime parameters. /// The first is the lifetime of the world, and the second the lifetime /// of the parameter's state. /// /// ## Attributes /// /// `#[system_param(ignore)]`: /// Can be added to any field in the struct. Fields decorated with this attribute /// will created with the default value upon realisation. /// This is most useful for `PhantomData` fields, to ensure that the required lifetimes are /// used, as shown in the example. /// /// # Example /// /// ``` /// # use bevy_ecs::prelude::*; /// use std::marker::PhantomData; /// use bevy_ecs::system::SystemParam; /// /// #[derive(SystemParam)] /// struct MyParam<'w, 's> { /// foo: Res<'w, usize>, /// #[system_param(ignore)] /// marker: PhantomData<&'s usize>, /// } /// /// fn my_system(param: MyParam) { /// // Access the resource through `param.foo` /// } /// /// # bevy_ecs::system::assert_is_system(my_system); /// ``` /// /// # Generic `SystemParam`s /// /// When using the derive macro, you may see an error in the form of: /// /// ```text /// expected ... [ParamType] /// found associated type `<<[ParamType] as SystemParam>::Fetch as SystemParamFetch<'_, '_>>::Item` /// ``` /// where `[ParamType]` is the type of one of your fields. /// To solve this error, you can wrap the field of type `[ParamType]` with [`StaticSystemParam`] /// (i.e. `StaticSystemParam<[ParamType]>`). /// /// ## Details /// /// The derive macro requires that the [`SystemParam`] implementation of /// each field `F`'s [`Fetch`](`SystemParam::Fetch`)'s [`Item`](`SystemParamFetch::Item`) is itself `F` /// (ignoring lifetimes for simplicity). /// This assumption is due to type inference reasons, so that the derived [`SystemParam`] can be /// used as an argument to a function system. /// If the compiler cannot validate this property for `[ParamType]`, it will error in the form shown above. /// /// This will most commonly occur when working with `SystemParam`s generically, as the requirement /// has not been proven to the compiler. pub trait SystemParam: Sized { type Fetch: for<'w, 's> SystemParamFetch<'w, 's>; } pub type SystemParamItem<'w, 's, P> = <

::Fetch as SystemParamFetch<'w, 's>>::Item; /// The state of a [`SystemParam`]. /// /// # Safety /// /// It is the implementor's responsibility to ensure `system_meta` is populated with the _exact_ /// [`World`] access used by the [`SystemParamState`] (and associated [`SystemParamFetch`]). /// Additionally, it is the implementor's responsibility to ensure there is no /// conflicting access across all [`SystemParam`]'s. pub unsafe trait SystemParamState: Send + Sync + 'static { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self; #[inline] fn new_archetype(&mut self, _archetype: &Archetype, _system_meta: &mut SystemMeta) {} #[inline] fn apply(&mut self, _world: &mut World) {} } /// A [`SystemParamFetch`] that only reads a given [`World`]. /// /// # Safety /// This must only be implemented for [`SystemParamFetch`] impls that exclusively read the World passed in to [`SystemParamFetch::get_param`] pub unsafe trait ReadOnlySystemParamFetch {} pub trait SystemParamFetch<'world, 'state>: SystemParamState { type Item: SystemParam; /// # Safety /// /// This call might access any of the input parameters in an unsafe way. Make sure the data /// access is safe in the context of the system scheduler. unsafe fn get_param( state: &'state mut Self, system_meta: &SystemMeta, world: &'world World, change_tick: u32, ) -> Self::Item; } impl<'w, 's, Q: WorldQuery + 'static, F: WorldQuery + 'static> SystemParam for Query<'w, 's, Q, F> { type Fetch = QueryState; } // SAFE: QueryState is constrained to read-only fetches, so it only reads World. unsafe impl ReadOnlySystemParamFetch for QueryState where for<'x> QueryFetch<'x, Q>: ReadOnlyFetch { } // SAFE: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If // this QueryState conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for QueryState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { let state = QueryState::new(world); assert_component_access_compatibility( &system_meta.name, std::any::type_name::(), std::any::type_name::(), &system_meta.component_access_set, &state.component_access, world, ); system_meta .component_access_set .add(state.component_access.clone()); system_meta .archetype_component_access .extend(&state.archetype_component_access); state } fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) { self.new_archetype(archetype); system_meta .archetype_component_access .extend(&self.archetype_component_access); } } impl<'w, 's, Q: WorldQuery + 'static, F: WorldQuery + 'static> SystemParamFetch<'w, 's> for QueryState { type Item = Query<'w, 's, Q, F>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { Query::new(world, state, system_meta.last_change_tick, change_tick) } } fn assert_component_access_compatibility( system_name: &str, query_type: &'static str, filter_type: &'static str, system_access: &FilteredAccessSet, current: &FilteredAccess, world: &World, ) { let mut conflicts = system_access.get_conflicts_single(current); if conflicts.is_empty() { return; } let conflicting_components = conflicts .drain(..) .map(|component_id| world.components.get_info(component_id).unwrap().name()) .collect::>(); let accesses = conflicting_components.join(", "); panic!("error[B0001]: Query<{}, {}> in system {} accesses component(s) {} in a way that conflicts with a previous system parameter. Consider using `Without` to create disjoint Queries or merging conflicting Queries into a `ParamSet`.", query_type, filter_type, system_name, accesses); } pub struct ParamSet<'w, 's, T: SystemParam> { param_states: &'s mut T::Fetch, world: &'w World, system_meta: SystemMeta, change_tick: u32, } /// The [`SystemParamState`] of [`ParamSet`]. pub struct ParamSetState SystemParamFetch<'w, 's>>(T); impl_param_set!(); pub trait Resource: Send + Sync + 'static {} impl Resource for T where T: Send + Sync + 'static {} /// Shared borrow of a resource. /// /// See the [`World`] documentation to see the usage of a resource. /// /// If you need a unique mutable borrow, use [`ResMut`] instead. /// /// # Panics /// /// Panics when used as a [`SystemParameter`](SystemParam) if the resource does not exist. /// /// Use `Option>` instead if the resource might not always exist. pub struct Res<'w, T: Resource> { value: &'w T, ticks: &'w ComponentTicks, last_change_tick: u32, change_tick: u32, } // SAFE: Res only reads a single World resource unsafe impl ReadOnlySystemParamFetch for ResState {} impl<'w, T: Resource> Debug for Res<'w, T> where T: Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Res").field(&self.value).finish() } } impl<'w, T: Resource> Res<'w, T> { /// Returns `true` if the resource was added after the system last ran. pub fn is_added(&self) -> bool { self.ticks.is_added(self.last_change_tick, self.change_tick) } /// Returns `true` if the resource was added or mutably dereferenced after the system last ran. pub fn is_changed(&self) -> bool { self.ticks .is_changed(self.last_change_tick, self.change_tick) } pub fn into_inner(self) -> &'w T { self.value } } impl<'w, T: Resource> Deref for Res<'w, T> { type Target = T; fn deref(&self) -> &Self::Target { self.value } } impl<'w, T: Resource> AsRef for Res<'w, T> { #[inline] fn as_ref(&self) -> &T { self.deref() } } impl<'w, T: Resource> From> for Res<'w, T> { fn from(res: ResMut<'w, T>) -> Self { Self { value: res.value, ticks: res.ticks.component_ticks, change_tick: res.ticks.change_tick, last_change_tick: res.ticks.last_change_tick, } } } /// The [`SystemParamState`] of [`Res`]. #[doc(hidden)] pub struct ResState { component_id: ComponentId, marker: PhantomData, } impl<'a, T: Resource> SystemParam for Res<'a, T> { type Fetch = ResState; } // SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for ResState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access_mut(); assert!( !combined_access.has_write(component_id), "error[B0002]: Res<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access.", std::any::type_name::(), system_meta.name, ); combined_access.add_read(component_id); let resource_archetype = world.archetypes.resource(); let archetype_component_id = resource_archetype .get_archetype_component_id(component_id) .unwrap(); system_meta .archetype_component_access .add_read(archetype_component_id); Self { component_id, marker: PhantomData, } } } impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState { type Item = Res<'w, T>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { let column = world .get_populated_resource_column(state.component_id) .unwrap_or_else(|| { panic!( "Resource requested by {} does not exist: {}", system_meta.name, std::any::type_name::() ) }); Res { value: column.get_data_ptr().deref::(), ticks: column.get_ticks_unchecked(0).deref(), last_change_tick: system_meta.last_change_tick, change_tick, } } } /// The [`SystemParamState`] of [`Option>`]. /// See: [`Res`] #[doc(hidden)] pub struct OptionResState(ResState); impl<'a, T: Resource> SystemParam for Option> { type Fetch = OptionResState; } // SAFE: Only reads a single World resource unsafe impl ReadOnlySystemParamFetch for OptionResState {} unsafe impl SystemParamState for OptionResState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(ResState::init(world, system_meta)) } } impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResState { type Item = Option>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { world .get_populated_resource_column(state.0.component_id) .map(|column| Res { value: column.get_data_ptr().deref::(), ticks: column.get_ticks_unchecked(0).deref(), last_change_tick: system_meta.last_change_tick, change_tick, }) } } /// The [`SystemParamState`] of [`ResMut`]. #[doc(hidden)] pub struct ResMutState { component_id: ComponentId, marker: PhantomData, } impl<'a, T: Resource> SystemParam for ResMut<'a, T> { type Fetch = ResMutState; } // SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for ResMutState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access_mut(); if combined_access.has_write(component_id) { panic!( "error[B0002]: ResMut<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access.", std::any::type_name::(), system_meta.name); } else if combined_access.has_read(component_id) { panic!( "error[B0002]: ResMut<{}> in system {} conflicts with a previous Res<{0}> access. Consider removing the duplicate access.", std::any::type_name::(), system_meta.name); } combined_access.add_write(component_id); let resource_archetype = world.archetypes.resource(); let archetype_component_id = resource_archetype .get_archetype_component_id(component_id) .unwrap(); system_meta .archetype_component_access .add_write(archetype_component_id); Self { component_id, marker: PhantomData, } } } impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResMutState { type Item = ResMut<'w, T>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { let value = world .get_resource_unchecked_mut_with_id(state.component_id) .unwrap_or_else(|| { panic!( "Resource requested by {} does not exist: {}", system_meta.name, std::any::type_name::() ) }); ResMut { value: value.value, ticks: Ticks { component_ticks: value.ticks.component_ticks, last_change_tick: system_meta.last_change_tick, change_tick, }, } } } /// The [`SystemParamState`] of [`Option>`]. /// See: [`ResMut`] #[doc(hidden)] pub struct OptionResMutState(ResMutState); impl<'a, T: Resource> SystemParam for Option> { type Fetch = OptionResMutState; } unsafe impl SystemParamState for OptionResMutState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(ResMutState::init(world, system_meta)) } } impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResMutState { type Item = Option>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { world .get_resource_unchecked_mut_with_id(state.0.component_id) .map(|value| ResMut { value: value.value, ticks: Ticks { component_ticks: value.ticks.component_ticks, last_change_tick: system_meta.last_change_tick, change_tick, }, }) } } impl<'w, 's> SystemParam for Commands<'w, 's> { type Fetch = CommandQueue; } // SAFE: Commands only accesses internal state unsafe impl ReadOnlySystemParamFetch for CommandQueue {} // SAFE: only local state is accessed unsafe impl SystemParamState for CommandQueue { fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Default::default() } fn apply(&mut self, world: &mut World) { self.apply(world); } } impl<'w, 's> SystemParamFetch<'w, 's> for CommandQueue { type Item = Commands<'w, 's>; #[inline] unsafe fn get_param( state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item { Commands::new(state, world) } } /// SAFE: only reads world unsafe impl ReadOnlySystemParamFetch for WorldState {} /// The [`SystemParamState`] of [`&World`](crate::world::World). #[doc(hidden)] pub struct WorldState; impl<'w> SystemParam for &'w World { type Fetch = WorldState; } unsafe impl SystemParamState for WorldState { fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self { let mut access = Access::default(); access.read_all(); if !system_meta .archetype_component_access .is_compatible(&access) { panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules"); } system_meta.archetype_component_access.extend(&access); let mut filtered_access = FilteredAccess::default(); filtered_access.read_all(); if !system_meta .component_access_set .get_conflicts_single(&filtered_access) .is_empty() { panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules"); } system_meta.component_access_set.add(filtered_access); WorldState } } impl<'w, 's> SystemParamFetch<'w, 's> for WorldState { type Item = &'w World; unsafe fn get_param( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item { world } } /// A system local [`SystemParam`]. /// /// A local may only be accessed by the system itself and is therefore not visible to other systems. /// If two or more systems specify the same local type each will have their own unique local. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// # let world = &mut World::default(); /// fn write_to_local(mut local: Local) { /// *local = 42; /// } /// fn read_from_local(local: Local) -> usize { /// *local /// } /// let mut write_system = IntoSystem::into_system(write_to_local); /// let mut read_system = IntoSystem::into_system(read_from_local); /// write_system.initialize(world); /// read_system.initialize(world); /// /// assert_eq!(read_system.run((), world), 0); /// write_system.run((), world); /// // Note how the read local is still 0 due to the locals not being shared. /// assert_eq!(read_system.run((), world), 0); /// ``` /// /// N.B. A [`Local`]s value cannot be read or written to outside of the containing system. /// To add configuration to a system, convert a capturing closure into the system instead: /// /// ``` /// # use bevy_ecs::prelude::*; /// # use bevy_ecs::system::assert_is_system; /// struct Config(u32); /// struct Myu32Wrapper(u32); /// fn reset_to_system(value: Config) -> impl FnMut(ResMut) { /// move |mut val| val.0 = value.0 /// } /// /// // .add_system(reset_to_system(my_config)) /// # assert_is_system(reset_to_system(Config(10))); /// ``` pub struct Local<'a, T: Resource>(&'a mut T); // SAFE: Local only accesses internal state unsafe impl ReadOnlySystemParamFetch for LocalState {} impl<'a, T: Resource> Debug for Local<'a, T> where T: Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Local").field(&self.0).finish() } } impl<'a, T: Resource> Deref for Local<'a, T> { type Target = T; #[inline] fn deref(&self) -> &Self::Target { self.0 } } impl<'a, T: Resource> DerefMut for Local<'a, T> { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.0 } } /// The [`SystemParamState`] of [`Local`]. #[doc(hidden)] pub struct LocalState(T); impl<'a, T: Resource + FromWorld> SystemParam for Local<'a, T> { type Fetch = LocalState; } // SAFE: only local state is accessed unsafe impl SystemParamState for LocalState { fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self(T::from_world(world)) } } impl<'w, 's, T: Resource + FromWorld> SystemParamFetch<'w, 's> for LocalState { type Item = Local<'s, T>; #[inline] unsafe fn get_param( state: &'s mut Self, _system_meta: &SystemMeta, _world: &'w World, _change_tick: u32, ) -> Self::Item { Local(&mut state.0) } } /// A [`SystemParam`] that grants access to the entities that had their `T` [`Component`] removed. /// /// Note that this does not allow you to see which data existed before removal. /// If you need this, you will need to track the component data value on your own, /// using a regularly scheduled system that requests `Query<(Entity, &T), Changed>` /// and stores the data somewhere safe to later cross-reference. /// /// If you are using `bevy_ecs` as a standalone crate, /// note that the `RemovedComponents` list will not be automatically cleared for you, /// and will need to be manually flushed using [`World::clear_trackers`] /// /// For users of `bevy` itself, this is automatically done in a system added by `MinimalPlugins` /// or `DefaultPlugins` at the end of each pass of the game loop during the `CoreStage::Last` /// stage. As such `RemovedComponents` systems should be scheduled after the stage where /// removal occurs but before `CoreStage::Last`. /// /// # Examples /// /// Basic usage: /// /// ``` /// # use bevy_ecs::component::Component; /// # use bevy_ecs::system::IntoSystem; /// # use bevy_ecs::system::RemovedComponents; /// # /// # #[derive(Component)] /// # struct MyComponent; /// /// fn react_on_removal(removed: RemovedComponents) { /// removed.iter().for_each(|removed_entity| println!("{:?}", removed_entity)); /// } /// /// # bevy_ecs::system::assert_is_system(react_on_removal); /// ``` pub struct RemovedComponents<'a, T: Component> { world: &'a World, component_id: ComponentId, marker: PhantomData, } impl<'a, T: Component> RemovedComponents<'a, T> { /// Returns an iterator over the entities that had their `T` [`Component`] removed. pub fn iter(&self) -> std::iter::Cloned> { self.world.removed_with_id(self.component_id) } } // SAFE: Only reads World components unsafe impl ReadOnlySystemParamFetch for RemovedComponentsState {} /// The [`SystemParamState`] of [`RemovedComponents`]. #[doc(hidden)] pub struct RemovedComponentsState { component_id: ComponentId, marker: PhantomData, } impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { type Fetch = RemovedComponentsState; } // SAFE: no component access. removed component entity collections can be read in parallel and are // never mutably borrowed during system execution unsafe impl SystemParamState for RemovedComponentsState { fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self { component_id: world.init_component::(), marker: PhantomData, } } } impl<'w, 's, T: Component> SystemParamFetch<'w, 's> for RemovedComponentsState { type Item = RemovedComponents<'w, T>; #[inline] unsafe fn get_param( state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item { RemovedComponents { world, component_id: state.component_id, marker: PhantomData, } } } /// Shared borrow of a non-[`Send`] resource. /// /// Only `Send` resources may be accessed with the [`Res`] [`SystemParam`]. In case that the /// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct /// the scheduler to instead run the system on the main thread so that it doesn't send the resource /// over to another thread. /// /// # Panics /// /// Panics when used as a `SystemParameter` if the resource does not exist. /// /// Use `Option>` instead if the resource might not always exist. pub struct NonSend<'w, T: 'static> { pub(crate) value: &'w T, ticks: ComponentTicks, last_change_tick: u32, change_tick: u32, } // SAFE: Only reads a single World non-send resource unsafe impl ReadOnlySystemParamFetch for NonSendState {} impl<'w, T> Debug for NonSend<'w, T> where T: Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("NonSend").field(&self.value).finish() } } impl<'w, T: 'static> NonSend<'w, T> { /// Returns `true` if the resource was added after the system last ran. pub fn is_added(&self) -> bool { self.ticks.is_added(self.last_change_tick, self.change_tick) } /// Returns `true` if the resource was added or mutably dereferenced after the system last ran. pub fn is_changed(&self) -> bool { self.ticks .is_changed(self.last_change_tick, self.change_tick) } } impl<'w, T> Deref for NonSend<'w, T> { type Target = T; fn deref(&self) -> &Self::Target { self.value } } impl<'a, T> From> for NonSend<'a, T> { fn from(nsm: NonSendMut<'a, T>) -> Self { Self { value: nsm.value, ticks: nsm.ticks.component_ticks.to_owned(), change_tick: nsm.ticks.change_tick, last_change_tick: nsm.ticks.last_change_tick, } } } /// The [`SystemParamState`] of [`NonSend`]. #[doc(hidden)] pub struct NonSendState { component_id: ComponentId, marker: PhantomData T>, } impl<'a, T: 'static> SystemParam for NonSend<'a, T> { type Fetch = NonSendState; } // SAFE: NonSendComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // NonSend conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for NonSendState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { system_meta.set_non_send(); let component_id = world.initialize_non_send_resource::(); let combined_access = system_meta.component_access_set.combined_access_mut(); assert!( !combined_access.has_write(component_id), "error[B0002]: NonSend<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access.", std::any::type_name::(), system_meta.name, ); combined_access.add_read(component_id); let resource_archetype = world.archetypes.resource(); let archetype_component_id = resource_archetype .get_archetype_component_id(component_id) .unwrap(); system_meta .archetype_component_access .add_read(archetype_component_id); Self { component_id, marker: PhantomData, } } } impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState { type Item = NonSend<'w, T>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { world.validate_non_send_access::(); let column = world .get_populated_resource_column(state.component_id) .unwrap_or_else(|| { panic!( "Non-send resource requested by {} does not exist: {}", system_meta.name, std::any::type_name::() ) }); NonSend { value: column.get_data_ptr().deref::(), ticks: column.get_ticks_unchecked(0).read(), last_change_tick: system_meta.last_change_tick, change_tick, } } } /// The [`SystemParamState`] of [`Option>`]. /// See: [`NonSend`] #[doc(hidden)] pub struct OptionNonSendState(NonSendState); impl<'w, T: 'static> SystemParam for Option> { type Fetch = OptionNonSendState; } // SAFE: Only reads a single non-send resource unsafe impl ReadOnlySystemParamFetch for OptionNonSendState {} unsafe impl SystemParamState for OptionNonSendState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(NonSendState::init(world, system_meta)) } } impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendState { type Item = Option>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { world.validate_non_send_access::(); world .get_populated_resource_column(state.0.component_id) .map(|column| NonSend { value: column.get_data_ptr().deref::(), ticks: column.get_ticks_unchecked(0).read(), last_change_tick: system_meta.last_change_tick, change_tick, }) } } /// The [`SystemParamState`] of [`NonSendMut`]. #[doc(hidden)] pub struct NonSendMutState { component_id: ComponentId, marker: PhantomData T>, } impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { type Fetch = NonSendMutState; } // SAFE: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // NonSendMut conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for NonSendMutState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { system_meta.set_non_send(); let component_id = world.initialize_non_send_resource::(); let combined_access = system_meta.component_access_set.combined_access_mut(); if combined_access.has_write(component_id) { panic!( "error[B0002]: NonSendMut<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access.", std::any::type_name::(), system_meta.name); } else if combined_access.has_read(component_id) { panic!( "error[B0002]: NonSendMut<{}> in system {} conflicts with a previous immutable resource access ({0}). Consider removing the duplicate access.", std::any::type_name::(), system_meta.name); } combined_access.add_write(component_id); let resource_archetype = world.archetypes.resource(); let archetype_component_id = resource_archetype .get_archetype_component_id(component_id) .unwrap(); system_meta .archetype_component_access .add_write(archetype_component_id); Self { component_id, marker: PhantomData, } } } impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendMutState { type Item = NonSendMut<'w, T>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { world.validate_non_send_access::(); let column = world .get_populated_resource_column(state.component_id) .unwrap_or_else(|| { panic!( "Non-send resource requested by {} does not exist: {}", system_meta.name, std::any::type_name::() ) }); NonSendMut { value: column.get_data_ptr().assert_unique().deref_mut::(), ticks: Ticks { component_ticks: column.get_ticks_unchecked(0).deref_mut(), last_change_tick: system_meta.last_change_tick, change_tick, }, } } } /// The [`SystemParamState`] of [`Option>`]. /// See: [`NonSendMut`] #[doc(hidden)] pub struct OptionNonSendMutState(NonSendMutState); impl<'a, T: 'static> SystemParam for Option> { type Fetch = OptionNonSendMutState; } unsafe impl SystemParamState for OptionNonSendMutState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(NonSendMutState::init(world, system_meta)) } } impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendMutState { type Item = Option>; #[inline] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { world.validate_non_send_access::(); world .get_populated_resource_column(state.0.component_id) .map(|column| NonSendMut { value: column.get_data_ptr().assert_unique().deref_mut::(), ticks: Ticks { component_ticks: column.get_ticks_unchecked(0).deref_mut(), last_change_tick: system_meta.last_change_tick, change_tick, }, }) } } impl<'a> SystemParam for &'a Archetypes { type Fetch = ArchetypesState; } // SAFE: Only reads World archetypes unsafe impl ReadOnlySystemParamFetch for ArchetypesState {} /// The [`SystemParamState`] of [`Archetypes`]. #[doc(hidden)] pub struct ArchetypesState; // SAFE: no component value access unsafe impl SystemParamState for ArchetypesState { fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self } } impl<'w, 's> SystemParamFetch<'w, 's> for ArchetypesState { type Item = &'w Archetypes; #[inline] unsafe fn get_param( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item { world.archetypes() } } impl<'a> SystemParam for &'a Components { type Fetch = ComponentsState; } // SAFE: Only reads World components unsafe impl ReadOnlySystemParamFetch for ComponentsState {} /// The [`SystemParamState`] of [`Components`]. #[doc(hidden)] pub struct ComponentsState; // SAFE: no component value access unsafe impl SystemParamState for ComponentsState { fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self } } impl<'w, 's> SystemParamFetch<'w, 's> for ComponentsState { type Item = &'w Components; #[inline] unsafe fn get_param( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item { world.components() } } impl<'a> SystemParam for &'a Entities { type Fetch = EntitiesState; } // SAFE: Only reads World entities unsafe impl ReadOnlySystemParamFetch for EntitiesState {} /// The [`SystemParamState`] of [`Entities`]. #[doc(hidden)] pub struct EntitiesState; // SAFE: no component value access unsafe impl SystemParamState for EntitiesState { fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self } } impl<'w, 's> SystemParamFetch<'w, 's> for EntitiesState { type Item = &'w Entities; #[inline] unsafe fn get_param( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item { world.entities() } } impl<'a> SystemParam for &'a Bundles { type Fetch = BundlesState; } // SAFE: Only reads World bundles unsafe impl ReadOnlySystemParamFetch for BundlesState {} /// The [`SystemParamState`] of [`Bundles`]. #[doc(hidden)] pub struct BundlesState; // SAFE: no component value access unsafe impl SystemParamState for BundlesState { fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self } } impl<'w, 's> SystemParamFetch<'w, 's> for BundlesState { type Item = &'w Bundles; #[inline] unsafe fn get_param( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item { world.bundles() } } /// A [`SystemParam`] that reads the previous and current change ticks of the system. /// /// A system's change ticks are updated each time it runs: /// - `last_change_tick` copies the previous value of `change_tick` /// - `change_tick` copies the current value of [`World::read_change_tick`] /// /// Component change ticks that are more recent than `last_change_tick` will be detected by the system. /// Those can be read by calling [`last_changed`](crate::change_detection::DetectChanges::last_changed) /// on a [`Mut`](crate::change_detection::Mut) or [`ResMut`](crate::change_detection::ResMut). #[derive(Debug)] pub struct SystemChangeTick { last_change_tick: u32, change_tick: u32, } impl SystemChangeTick { /// Returns the current [`World`] change tick seen by the system. #[inline] pub fn change_tick(&self) -> u32 { self.change_tick } /// Returns the [`World`] change tick seen by the system the previous time it ran. #[inline] pub fn last_change_tick(&self) -> u32 { self.last_change_tick } } // SAFE: Only reads internal system state unsafe impl ReadOnlySystemParamFetch for SystemChangeTickState {} impl SystemParam for SystemChangeTick { type Fetch = SystemChangeTickState; } /// The [`SystemParamState`] of [`SystemChangeTick`]. #[doc(hidden)] pub struct SystemChangeTickState {} unsafe impl SystemParamState for SystemChangeTickState { fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self {} } } impl<'w, 's> SystemParamFetch<'w, 's> for SystemChangeTickState { type Item = SystemChangeTick; unsafe fn get_param( _state: &'s mut Self, system_meta: &SystemMeta, _world: &'w World, change_tick: u32, ) -> Self::Item { SystemChangeTick { last_change_tick: system_meta.last_change_tick, change_tick, } } } macro_rules! impl_system_param_tuple { ($($param: ident),*) => { impl<$($param: SystemParam),*> SystemParam for ($($param,)*) { type Fetch = ($($param::Fetch,)*); } // SAFE: tuple consists only of ReadOnlySystemParamFetches unsafe impl<$($param: ReadOnlySystemParamFetch),*> ReadOnlySystemParamFetch for ($($param,)*) {} #[allow(unused_variables)] #[allow(non_snake_case)] impl<'w, 's, $($param: SystemParamFetch<'w, 's>),*> SystemParamFetch<'w, 's> for ($($param,)*) { type Item = ($($param::Item,)*); #[inline] #[allow(clippy::unused_unit)] unsafe fn get_param( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item { let ($($param,)*) = state; ($($param::get_param($param, system_meta, world, change_tick),)*) } } /// SAFE: implementors of each `SystemParamState` in the tuple have validated their impls #[allow(non_snake_case)] unsafe impl<$($param: SystemParamState),*> SystemParamState for ($($param,)*) { #[inline] fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { (($($param::init(_world, _system_meta),)*)) } #[inline] fn new_archetype(&mut self, _archetype: &Archetype, _system_meta: &mut SystemMeta) { let ($($param,)*) = self; $($param.new_archetype(_archetype, _system_meta);)* } #[inline] fn apply(&mut self, _world: &mut World) { let ($($param,)*) = self; $($param.apply(_world);)* } } }; } all_tuples!(impl_system_param_tuple, 0, 16, P); pub mod lifetimeless { pub type SQuery = super::Query<'static, 'static, Q, F>; pub type Read = &'static T; pub type Write = &'static mut T; pub type SRes = super::Res<'static, T>; pub type SResMut = super::ResMut<'static, T>; pub type SCommands = crate::system::Commands<'static, 'static>; } /// A helper for using system parameters in generic contexts /// /// This type is a [`SystemParam`] adapter which always has /// `Self::Fetch::Item == Self` (ignoring lifetimes for brevity), /// no matter the argument [`SystemParam`] (`P`) (other than /// that `P` must be `'static`) /// /// This makes it useful for having arbitrary [`SystemParam`] type arguments /// to function systems, or for generic types using the [`derive@SystemParam`] /// derive: /// /// ``` /// # use bevy_ecs::prelude::*; /// use bevy_ecs::system::{SystemParam, StaticSystemParam}; /// #[derive(SystemParam)] /// struct GenericParam<'w,'s, T: SystemParam + 'static> { /// field: StaticSystemParam<'w, 's, T>, /// } /// fn do_thing_generically(t: StaticSystemParam) {} /// /// fn check_always_is_system(){ /// bevy_ecs::system::assert_is_system(do_thing_generically::); /// } /// ``` /// Note that in a real case you'd generally want /// additional bounds on `P`, for your use of the parameter /// to have a reason to be generic. /// /// For example, using this would allow a type to be generic over /// whether a resource is accessed mutably or not, with /// impls being bounded on [`P: Deref`](Deref), and /// [`P: DerefMut`](DerefMut) depending on whether the /// method requires mutable access or not. /// /// The method which doesn't use this type will not compile: /// ```compile_fail /// # use bevy_ecs::prelude::*; /// # use bevy_ecs::system::{SystemParam, StaticSystemParam}; /// /// fn do_thing_generically(t: T) {} /// /// #[derive(SystemParam)] /// struct GenericParam<'w,'s, T: SystemParam> { /// field: T, /// #[system_param(ignore)] /// // Use the lifetimes, as the `SystemParam` derive requires them /// phantom: core::marker::PhantomData<&'w &'s ()> /// } /// # fn check_always_is_system(){ /// # bevy_ecs::system::assert_is_system(do_thing_generically::); /// # } /// ``` /// pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>); impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> { type Target = SystemParamItem<'w, 's, P>; fn deref(&self) -> &Self::Target { &self.0 } } impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> { /// Get the value of the parameter pub fn into_inner(self) -> SystemParamItem<'w, 's, P> { self.0 } } /// The [`SystemParamState`] of [`StaticSystemParam`]. #[doc(hidden)] pub struct StaticSystemParamState(S, PhantomData P>); // Safe: This doesn't add any more reads, and the delegated fetch confirms it unsafe impl ReadOnlySystemParamFetch for StaticSystemParamState { } impl<'world, 'state, P: SystemParam + 'static> SystemParam for StaticSystemParam<'world, 'state, P> { type Fetch = StaticSystemParamState; } impl<'world, 'state, S: SystemParamFetch<'world, 'state>, P: SystemParam + 'static> SystemParamFetch<'world, 'state> for StaticSystemParamState where P: SystemParam, { type Item = StaticSystemParam<'world, 'state, P>; unsafe fn get_param( state: &'state mut Self, system_meta: &SystemMeta, world: &'world World, change_tick: u32, ) -> Self::Item { // Safe: We properly delegate SystemParamState StaticSystemParam(S::get_param(&mut state.0, system_meta, world, change_tick)) } } unsafe impl SystemParamState for StaticSystemParamState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(S::init(world, system_meta), PhantomData) } fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) { self.0.new_archetype(archetype, system_meta) } fn apply(&mut self, world: &mut World) { self.0.apply(world) } } #[cfg(test)] mod tests { use super::SystemParam; use crate::{ self as bevy_ecs, // Necessary for the `SystemParam` Derive when used inside `bevy_ecs`. query::WorldQuery, system::Query, }; // Compile test for #2838 #[derive(SystemParam)] pub struct SpecialQuery< 'w, 's, Q: WorldQuery + Send + Sync + 'static, F: WorldQuery + Send + Sync + 'static = (), > { _query: Query<'w, 's, Q, F>, } }