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, QueryState, ReadOnlyWorldQuery, WorldQuery,
},
system::{CommandQueue, Commands, Query, SystemMeta},
world::{FromWorld, World},
};
pub use bevy_ecs_macros::Resource;
pub use bevy_ecs_macros::SystemParam;
use bevy_ecs_macros::{all_tuples, impl_param_set};
use bevy_ptr::UnsafeCellDeref;
use bevy_utils::synccell::SyncCell;
use std::{
borrow::Cow,
fmt::Debug,
marker::PhantomData,
ops::{Deref, DerefMut},
};
pub trait SystemParam: Sized {
type Fetch: for<'w, 's> SystemParamFetch<'w, 's>;
}
pub type SystemParamItem<'w, 's, P> = <<P as SystemParam>::Fetch as SystemParamFetch<'w, 's>>::Item;
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) {}
}
pub unsafe trait ReadOnlySystemParamFetch {}
pub trait SystemParamFetch<'world, 'state>: SystemParamState {
type Item: SystemParam<Fetch = Self>;
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: ReadOnlyWorldQuery + 'static> SystemParam
for Query<'w, 's, Q, F>
{
type Fetch = QueryState<Q, F>;
}
unsafe impl<Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery> ReadOnlySystemParamFetch
for QueryState<Q, F>
{
}
unsafe impl<Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemParamState
for QueryState<Q, F>
{
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::<Q>(),
std::any::type_name::<F>(),
&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: ReadOnlyWorldQuery + 'static> SystemParamFetch<'w, 's>
for QueryState<Q, F>
{
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<ComponentId>,
current: &FilteredAccess<ComponentId>,
world: &World,
) {
let conflicts = system_access.get_conflicts_single(current);
if conflicts.is_empty() {
return;
}
let conflicting_components = conflicts
.into_iter()
.map(|component_id| world.components.get_info(component_id).unwrap().name())
.collect::<Vec<&str>>();
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<T>` 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,
}
pub struct ParamSetState<T: for<'w, 's> SystemParamFetch<'w, 's>>(T);
impl_param_set!();
pub trait Resource: Send + Sync + 'static {}
pub struct Res<'w, T: Resource> {
value: &'w T,
ticks: &'w ComponentTicks,
last_change_tick: u32,
change_tick: u32,
}
unsafe impl<T: Resource> ReadOnlySystemParamFetch for ResState<T> {}
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> {
#[allow(clippy::should_implement_trait)]
pub fn clone(this: &Self) -> Self {
Self {
value: this.value,
ticks: this.ticks,
last_change_tick: this.last_change_tick,
change_tick: this.change_tick,
}
}
pub fn is_added(&self) -> bool {
self.ticks.is_added(self.last_change_tick, self.change_tick)
}
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<T> for Res<'w, T> {
#[inline]
fn as_ref(&self) -> &T {
self.deref()
}
}
impl<'w, T: Resource> From<ResMut<'w, T>> 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,
}
}
}
impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T>
where
&'a T: IntoIterator,
{
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.value.into_iter()
}
}
#[doc(hidden)]
pub struct ResState<T> {
component_id: ComponentId,
marker: PhantomData<T>,
}
impl<'a, T: Resource> SystemParam for Res<'a, T> {
type Fetch = ResState<T>;
}
unsafe impl<T: Resource> SystemParamState for ResState<T> {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
let component_id = world.initialize_resource::<T>();
let combined_access = system_meta.component_access_set.combined_access();
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::<T>(),
system_meta.name,
);
system_meta
.component_access_set
.add_unfiltered_read(component_id);
let archetype_component_id = world
.get_resource_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<T> {
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 (ptr, ticks) = world
.get_resource_with_ticks(state.component_id)
.unwrap_or_else(|| {
panic!(
"Resource requested by {} does not exist: {}",
system_meta.name,
std::any::type_name::<T>()
)
});
Res {
value: ptr.deref(),
ticks: ticks.deref(),
last_change_tick: system_meta.last_change_tick,
change_tick,
}
}
}
#[doc(hidden)]
pub struct OptionResState<T>(ResState<T>);
impl<'a, T: Resource> SystemParam for Option<Res<'a, T>> {
type Fetch = OptionResState<T>;
}
unsafe impl<T: Resource> ReadOnlySystemParamFetch for OptionResState<T> {}
unsafe impl<T: Resource> SystemParamState for OptionResState<T> {
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<T> {
type Item = Option<Res<'w, T>>;
#[inline]
unsafe fn get_param(
state: &'s mut Self,
system_meta: &SystemMeta,
world: &'w World,
change_tick: u32,
) -> Self::Item {
world
.get_resource_with_ticks(state.0.component_id)
.map(|(ptr, ticks)| Res {
value: ptr.deref(),
ticks: ticks.deref(),
last_change_tick: system_meta.last_change_tick,
change_tick,
})
}
}
#[doc(hidden)]
pub struct ResMutState<T> {
component_id: ComponentId,
marker: PhantomData<T>,
}
impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
type Fetch = ResMutState<T>;
}
unsafe impl<T: Resource> SystemParamState for ResMutState<T> {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
let component_id = world.initialize_resource::<T>();
let combined_access = system_meta.component_access_set.combined_access();
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::<T>(), 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::<T>(), system_meta.name);
}
system_meta
.component_access_set
.add_unfiltered_write(component_id);
let archetype_component_id = world
.get_resource_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<T> {
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::<T>()
)
});
ResMut {
value: value.value,
ticks: Ticks {
component_ticks: value.ticks.component_ticks,
last_change_tick: system_meta.last_change_tick,
change_tick,
},
}
}
}
#[doc(hidden)]
pub struct OptionResMutState<T>(ResMutState<T>);
impl<'a, T: Resource> SystemParam for Option<ResMut<'a, T>> {
type Fetch = OptionResMutState<T>;
}
unsafe impl<T: Resource> SystemParamState for OptionResMutState<T> {
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<T> {
type Item = Option<ResMut<'w, T>>;
#[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;
}
unsafe impl ReadOnlySystemParamFetch for CommandQueue {}
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)
}
}
unsafe impl ReadOnlySystemParamFetch for WorldState {}
#[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
}
}
pub struct Local<'a, T: FromWorld + Send + 'static>(pub(crate) &'a mut T);
unsafe impl<T: Send + 'static> ReadOnlySystemParamFetch for LocalState<T> {}
impl<'a, T: FromWorld + Send + Sync + 'static> 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: FromWorld + Send + Sync + 'static> Deref for Local<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
self.0
}
}
impl<'a, T: FromWorld + Send + Sync + 'static> DerefMut for Local<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.0
}
}
impl<'w, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'w, T>
where
&'a T: IntoIterator,
{
type Item = <&'a T as IntoIterator>::Item;
type IntoIter = <&'a T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'w, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'w, T>
where
&'a mut T: IntoIterator,
{
type Item = <&'a mut T as IntoIterator>::Item;
type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[doc(hidden)]
pub struct LocalState<T: Send + 'static>(pub(crate) SyncCell<T>);
impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {
type Fetch = LocalState<T>;
}
unsafe impl<T: FromWorld + Send + 'static> SystemParamState for LocalState<T> {
fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self {
Self(SyncCell::new(T::from_world(world)))
}
}
impl<'w, 's, T: FromWorld + Send + 'static> SystemParamFetch<'w, 's> for LocalState<T> {
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(state.0.get())
}
}
pub struct RemovedComponents<'a, T: Component> {
world: &'a World,
component_id: ComponentId,
marker: PhantomData<T>,
}
impl<'a, T: Component> RemovedComponents<'a, T> {
pub fn iter(&self) -> std::iter::Cloned<std::slice::Iter<'_, Entity>> {
self.world.removed_with_id(self.component_id)
}
}
impl<'a, T: Component> IntoIterator for &'a RemovedComponents<'a, T> {
type Item = Entity;
type IntoIter = std::iter::Cloned<std::slice::Iter<'a, Entity>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
unsafe impl<T: Component> ReadOnlySystemParamFetch for RemovedComponentsState<T> {}
#[doc(hidden)]
pub struct RemovedComponentsState<T> {
component_id: ComponentId,
marker: PhantomData<T>,
}
impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> {
type Fetch = RemovedComponentsState<T>;
}
unsafe impl<T: Component> SystemParamState for RemovedComponentsState<T> {
fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self {
Self {
component_id: world.init_component::<T>(),
marker: PhantomData,
}
}
}
impl<'w, 's, T: Component> SystemParamFetch<'w, 's> for RemovedComponentsState<T> {
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,
}
}
}
pub struct NonSend<'w, T: 'static> {
pub(crate) value: &'w T,
ticks: ComponentTicks,
last_change_tick: u32,
change_tick: u32,
}
unsafe impl<T> ReadOnlySystemParamFetch for NonSendState<T> {}
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> {
pub fn is_added(&self) -> bool {
self.ticks.is_added(self.last_change_tick, self.change_tick)
}
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<NonSendMut<'a, T>> 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,
}
}
}
#[doc(hidden)]
pub struct NonSendState<T> {
component_id: ComponentId,
marker: PhantomData<fn() -> T>,
}
impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
type Fetch = NonSendState<T>;
}
unsafe impl<T: 'static> SystemParamState for NonSendState<T> {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
system_meta.set_non_send();
let component_id = world.initialize_non_send_resource::<T>();
let combined_access = system_meta.component_access_set.combined_access();
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::<T>(),
system_meta.name,
);
system_meta
.component_access_set
.add_unfiltered_read(component_id);
let archetype_component_id = world
.get_resource_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<T> {
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::<T>();
let (ptr, ticks) = world
.get_resource_with_ticks(state.component_id)
.unwrap_or_else(|| {
panic!(
"Non-send resource requested by {} does not exist: {}",
system_meta.name,
std::any::type_name::<T>()
)
});
NonSend {
value: ptr.deref(),
ticks: ticks.read(),
last_change_tick: system_meta.last_change_tick,
change_tick,
}
}
}
#[doc(hidden)]
pub struct OptionNonSendState<T>(NonSendState<T>);
impl<'w, T: 'static> SystemParam for Option<NonSend<'w, T>> {
type Fetch = OptionNonSendState<T>;
}
unsafe impl<T: 'static> ReadOnlySystemParamFetch for OptionNonSendState<T> {}
unsafe impl<T: 'static> SystemParamState for OptionNonSendState<T> {
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<T> {
type Item = Option<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::<T>();
world
.get_resource_with_ticks(state.0.component_id)
.map(|(ptr, ticks)| NonSend {
value: ptr.deref(),
ticks: ticks.read(),
last_change_tick: system_meta.last_change_tick,
change_tick,
})
}
}
#[doc(hidden)]
pub struct NonSendMutState<T> {
component_id: ComponentId,
marker: PhantomData<fn() -> T>,
}
impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
type Fetch = NonSendMutState<T>;
}
unsafe impl<T: 'static> SystemParamState for NonSendMutState<T> {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
system_meta.set_non_send();
let component_id = world.initialize_non_send_resource::<T>();
let combined_access = system_meta.component_access_set.combined_access();
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::<T>(), 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::<T>(), system_meta.name);
}
system_meta
.component_access_set
.add_unfiltered_write(component_id);
let archetype_component_id = world
.get_resource_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<T> {
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::<T>();
let (ptr, ticks) = world
.get_resource_with_ticks(state.component_id)
.unwrap_or_else(|| {
panic!(
"Non-send resource requested by {} does not exist: {}",
system_meta.name,
std::any::type_name::<T>()
)
});
NonSendMut {
value: ptr.assert_unique().deref_mut(),
ticks: Ticks {
component_ticks: ticks.deref_mut(),
last_change_tick: system_meta.last_change_tick,
change_tick,
},
}
}
}
#[doc(hidden)]
pub struct OptionNonSendMutState<T>(NonSendMutState<T>);
impl<'a, T: 'static> SystemParam for Option<NonSendMut<'a, T>> {
type Fetch = OptionNonSendMutState<T>;
}
unsafe impl<T: 'static> SystemParamState for OptionNonSendMutState<T> {
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<T> {
type Item = Option<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::<T>();
world
.get_resource_with_ticks(state.0.component_id)
.map(|(ptr, ticks)| NonSendMut {
value: ptr.assert_unique().deref_mut(),
ticks: Ticks {
component_ticks: ticks.deref_mut(),
last_change_tick: system_meta.last_change_tick,
change_tick,
},
})
}
}
impl<'a> SystemParam for &'a Archetypes {
type Fetch = ArchetypesState;
}
unsafe impl ReadOnlySystemParamFetch for ArchetypesState {}
#[doc(hidden)]
pub struct ArchetypesState;
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;
}
unsafe impl ReadOnlySystemParamFetch for ComponentsState {}
#[doc(hidden)]
pub struct ComponentsState;
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;
}
unsafe impl ReadOnlySystemParamFetch for EntitiesState {}
#[doc(hidden)]
pub struct EntitiesState;
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;
}
unsafe impl ReadOnlySystemParamFetch for BundlesState {}
#[doc(hidden)]
pub struct BundlesState;
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()
}
}
#[derive(Debug)]
pub struct SystemChangeTick {
last_change_tick: u32,
change_tick: u32,
}
impl SystemChangeTick {
#[inline]
pub fn change_tick(&self) -> u32 {
self.change_tick
}
#[inline]
pub fn last_change_tick(&self) -> u32 {
self.last_change_tick
}
}
unsafe impl ReadOnlySystemParamFetch for SystemChangeTickState {}
impl SystemParam for SystemChangeTick {
type Fetch = SystemChangeTickState;
}
#[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,
}
}
}
pub struct SystemName<'s> {
name: &'s str,
}
impl<'s> SystemName<'s> {
pub fn name(&self) -> &str {
self.name
}
}
impl<'s> Deref for SystemName<'s> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.name()
}
}
impl<'s> AsRef<str> for SystemName<'s> {
fn as_ref(&self) -> &str {
self.name()
}
}
impl<'s> From<SystemName<'s>> for &'s str {
fn from(name: SystemName<'s>) -> &'s str {
name.name
}
}
impl<'s> std::fmt::Debug for SystemName<'s> {
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_tuple("SystemName").field(&self.name()).finish()
}
}
impl<'s> std::fmt::Display for SystemName<'s> {
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Display::fmt(&self.name(), f)
}
}
impl<'s> SystemParam for SystemName<'s> {
type Fetch = SystemNameState;
}
unsafe impl ReadOnlySystemParamFetch for SystemNameState {}
#[doc(hidden)]
pub struct SystemNameState {
name: Cow<'static, str>,
}
unsafe impl SystemParamState for SystemNameState {
fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self {
Self {
name: system_meta.name.clone(),
}
}
}
impl<'w, 's> SystemParamFetch<'w, 's> for SystemNameState {
type Item = SystemName<'s>;
#[inline]
unsafe fn get_param(
state: &'s mut Self,
_system_meta: &SystemMeta,
_world: &'w World,
_change_tick: u32,
) -> Self::Item {
SystemName {
name: state.name.as_ref(),
}
}
}
macro_rules! impl_system_param_tuple {
($($param: ident),*) => {
impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
type Fetch = ($($param::Fetch,)*);
}
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),)*)
}
}
#[allow(clippy::undocumented_unsafe_blocks)] #[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<Q, F = ()> = super::Query<'static, 'static, Q, F>;
pub type Read<T> = &'static T;
pub type Write<T> = &'static mut T;
pub type SRes<T> = super::Res<'static, T>;
pub type SResMut<T> = super::ResMut<'static, T>;
pub type SCommands = crate::system::Commands<'static, 'static>;
}
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> {
pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {
self.0
}
}
#[doc(hidden)]
pub struct StaticSystemParamState<S, P>(S, PhantomData<fn() -> P>);
unsafe impl<S: ReadOnlySystemParamFetch, P> ReadOnlySystemParamFetch
for StaticSystemParamState<S, P>
{
}
impl<'world, 'state, P: SystemParam + 'static> SystemParam
for StaticSystemParam<'world, 'state, P>
{
type Fetch = StaticSystemParamState<P::Fetch, P>;
}
impl<'world, 'state, S: SystemParamFetch<'world, 'state>, P: SystemParam + 'static>
SystemParamFetch<'world, 'state> for StaticSystemParamState<S, P>
where
P: SystemParam<Fetch = S>,
{
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 {
StaticSystemParam(S::get_param(&mut state.0, system_meta, world, change_tick))
}
}
unsafe impl<S: SystemParamState, P: SystemParam + 'static> SystemParamState
for StaticSystemParamState<S, P>
{
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, query::{ReadOnlyWorldQuery, WorldQuery},
system::Query,
};
#[derive(SystemParam)]
pub struct SpecialQuery<
'w,
's,
Q: WorldQuery + Send + Sync + 'static,
F: ReadOnlyWorldQuery + Send + Sync + 'static = (),
> {
_query: Query<'w, 's, Q, F>,
}
}