mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 15:14:50 +00:00
Simplify trait hierarchy for SystemParam
(#6865)
# Objective * Implementing a custom `SystemParam` by hand requires implementing three traits -- four if it is read-only. * The trait `SystemParamFetch<'w, 's>` is a workaround from before we had generic associated types, and is no longer necessary. ## Solution * Combine the trait `SystemParamFetch` with `SystemParamState`. * I decided to remove the `Fetch` name and keep the `State` name, since the former was consistently conflated with the latter. * Replace the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`, which simplifies trait bounds in generic code. --- ## Changelog - Removed the trait `SystemParamFetch`, moving its functionality to `SystemParamState`. - Replaced the trait `ReadOnlySystemParamFetch` with `ReadOnlySystemParam`. ## Migration Guide The trait `SystemParamFetch` has been removed, and its functionality has been transferred to `SystemParamState`. ```rust // Before impl SystemParamState for MyParamState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... } } impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState { type Item = MyParam<'w, 's>; fn get_param(...) -> Self::Item; } // After impl SystemParamState for MyParamState { type Item<'w, 's> = MyParam<'w, 's>; // Generic associated types! fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... } fn get_param<'w, 's>(...) -> Self::Item<'w, 's>; } ``` The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`. ```rust // Before unsafe impl ReadOnlySystemParamFetch for MyParamState {} // After unsafe impl<'w, 's> ReadOnlySystemParam for MyParam<'w, 's> {} ```
This commit is contained in:
parent
c16791ce67
commit
1af73624fa
10 changed files with 318 additions and 386 deletions
|
@ -209,19 +209,19 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
|
|||
let mut tokens = TokenStream::new();
|
||||
let max_params = 8;
|
||||
let params = get_idents(|i| format!("P{i}"), max_params);
|
||||
let params_fetch = get_idents(|i| format!("PF{i}"), max_params);
|
||||
let params_state = get_idents(|i| format!("PF{i}"), max_params);
|
||||
let metas = get_idents(|i| format!("m{i}"), max_params);
|
||||
let mut param_fn_muts = Vec::new();
|
||||
for (i, param) in params.iter().enumerate() {
|
||||
let fn_name = Ident::new(&format!("p{i}"), Span::call_site());
|
||||
let index = Index::from(i);
|
||||
param_fn_muts.push(quote! {
|
||||
pub fn #fn_name<'a>(&'a mut self) -> <#param::Fetch as SystemParamFetch<'a, 'a>>::Item {
|
||||
pub fn #fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, #param> {
|
||||
// SAFETY: systems run without conflicts with other systems.
|
||||
// Conflicting params in ParamSet are not accessible at the same time
|
||||
// ParamSets are guaranteed to not conflict with other SystemParams
|
||||
unsafe {
|
||||
<#param::Fetch as SystemParamFetch<'a, 'a>>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick)
|
||||
<#param::State as SystemParamState>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -229,34 +229,36 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
|
|||
|
||||
for param_count in 1..=max_params {
|
||||
let param = ¶ms[0..param_count];
|
||||
let param_fetch = ¶ms_fetch[0..param_count];
|
||||
let param_state = ¶ms_state[0..param_count];
|
||||
let meta = &metas[0..param_count];
|
||||
let param_fn_mut = ¶m_fn_muts[0..param_count];
|
||||
tokens.extend(TokenStream::from(quote! {
|
||||
impl<'w, 's, #(#param: SystemParam,)*> SystemParam for ParamSet<'w, 's, (#(#param,)*)>
|
||||
{
|
||||
type Fetch = ParamSetState<(#(#param::Fetch,)*)>;
|
||||
type State = ParamSetState<(#(#param::State,)*)>;
|
||||
}
|
||||
|
||||
// SAFETY: All parameters are constrained to ReadOnlyFetch, so World is only read
|
||||
// SAFETY: All parameters are constrained to ReadOnlyState, so World is only read
|
||||
|
||||
unsafe impl<#(#param_fetch: for<'w1, 's1> SystemParamFetch<'w1, 's1>,)*> ReadOnlySystemParamFetch for ParamSetState<(#(#param_fetch,)*)>
|
||||
where #(#param_fetch: ReadOnlySystemParamFetch,)*
|
||||
unsafe impl<'w, 's, #(#param,)*> ReadOnlySystemParam for ParamSet<'w, 's, (#(#param,)*)>
|
||||
where #(#param: ReadOnlySystemParam,)*
|
||||
{ }
|
||||
|
||||
// SAFETY: Relevant parameter ComponentId and ArchetypeComponentId access is applied to SystemMeta. If any ParamState conflicts
|
||||
// with any prior access, a panic will occur.
|
||||
|
||||
unsafe impl<#(#param_fetch: for<'w1, 's1> SystemParamFetch<'w1, 's1>,)*> SystemParamState for ParamSetState<(#(#param_fetch,)*)>
|
||||
unsafe impl<#(#param_state: SystemParamState,)*> SystemParamState for ParamSetState<(#(#param_state,)*)>
|
||||
{
|
||||
type Item<'w, 's> = ParamSet<'w, 's, (#(<#param_state as SystemParamState>::Item::<'w, 's>,)*)>;
|
||||
|
||||
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
|
||||
#(
|
||||
// Pretend to add each param to the system alone, see if it conflicts
|
||||
let mut #meta = system_meta.clone();
|
||||
#meta.component_access_set.clear();
|
||||
#meta.archetype_component_access.clear();
|
||||
#param_fetch::init(world, &mut #meta);
|
||||
let #param = #param_fetch::init(world, &mut system_meta.clone());
|
||||
#param_state::init(world, &mut #meta);
|
||||
let #param = #param_state::init(world, &mut system_meta.clone());
|
||||
)*
|
||||
#(
|
||||
system_meta
|
||||
|
@ -279,21 +281,14 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
|
|||
fn apply(&mut self, world: &mut World) {
|
||||
self.0.apply(world)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<'w, 's, #(#param_fetch: for<'w1, 's1> SystemParamFetch<'w1, 's1>,)*> SystemParamFetch<'w, 's> for ParamSetState<(#(#param_fetch,)*)>
|
||||
{
|
||||
type Item = ParamSet<'w, 's, (#(<#param_fetch as SystemParamFetch<'w, 's>>::Item,)*)>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_param(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
ParamSet {
|
||||
param_states: &mut state.0,
|
||||
system_meta: system_meta.clone(),
|
||||
|
@ -414,34 +409,48 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
|||
_ => unreachable!(),
|
||||
}));
|
||||
|
||||
// Create a where clause for the `ReadOnlySystemParam` impl.
|
||||
// Ensure that each field implements `ReadOnlySystemParam`.
|
||||
let mut read_only_generics = generics.clone();
|
||||
let read_only_where_clause = read_only_generics.make_where_clause();
|
||||
for field_type in &field_types {
|
||||
read_only_where_clause
|
||||
.predicates
|
||||
.push(syn::parse_quote!(#field_type: #path::system::ReadOnlySystemParam));
|
||||
}
|
||||
|
||||
let struct_name = &ast.ident;
|
||||
let fetch_struct_visibility = &ast.vis;
|
||||
let state_struct_visibility = &ast.vis;
|
||||
|
||||
TokenStream::from(quote! {
|
||||
// We define the FetchState struct in an anonymous scope to avoid polluting the user namespace.
|
||||
// The struct can still be accessed via SystemParam::Fetch, e.g. EventReaderState can be accessed via
|
||||
// <EventReader<'static, 'static, T> as SystemParam>::Fetch
|
||||
// The struct can still be accessed via SystemParam::State, e.g. EventReaderState can be accessed via
|
||||
// <EventReader<'static, 'static, T> as SystemParam>::State
|
||||
const _: () = {
|
||||
impl<'w, 's, #punctuated_generics> #path::system::SystemParam for #struct_name #ty_generics #where_clause {
|
||||
type Fetch = State<'w, 's, #punctuated_generic_idents>;
|
||||
type State = State<'w, 's, #punctuated_generic_idents>;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
type State<'w, 's, #punctuated_generic_idents> = FetchState<
|
||||
(#(<#field_types as #path::system::SystemParam>::Fetch,)*),
|
||||
(#(<#field_types as #path::system::SystemParam>::State,)*),
|
||||
#punctuated_generic_idents
|
||||
>;
|
||||
|
||||
#[doc(hidden)]
|
||||
#fetch_struct_visibility struct FetchState <TSystemParamState, #punctuated_generic_idents> {
|
||||
#state_struct_visibility struct FetchState <TSystemParamState, #punctuated_generic_idents> {
|
||||
state: TSystemParamState,
|
||||
marker: std::marker::PhantomData<fn()->(#punctuated_generic_idents)>
|
||||
}
|
||||
|
||||
unsafe impl<TSystemParamState: #path::system::SystemParamState, #punctuated_generics> #path::system::SystemParamState for FetchState <TSystemParamState, #punctuated_generic_idents> #where_clause {
|
||||
unsafe impl<'__w, '__s, #punctuated_generics> #path::system::SystemParamState for
|
||||
State<'__w, '__s, #punctuated_generic_idents>
|
||||
#where_clause {
|
||||
type Item<'w, 's> = #struct_name #ty_generics;
|
||||
|
||||
fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self {
|
||||
Self {
|
||||
state: TSystemParamState::init(world, system_meta),
|
||||
state: #path::system::SystemParamState::init(world, system_meta),
|
||||
marker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -453,25 +462,22 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
|
|||
fn apply(&mut self, world: &mut #path::world::World) {
|
||||
self.state.apply(world)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's, #punctuated_generics> #path::system::SystemParamFetch<'w, 's> for State<'w, 's, #punctuated_generic_idents> #where_clause {
|
||||
type Item = #struct_name #ty_generics;
|
||||
unsafe fn get_param(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &#path::system::SystemMeta,
|
||||
world: &'w #path::world::World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
#struct_name {
|
||||
#(#fields: <<#field_types as #path::system::SystemParam>::Fetch as #path::system::SystemParamFetch>::get_param(&mut state.state.#field_indices, system_meta, world, change_tick),)*
|
||||
#(#fields: <<#field_types as #path::system::SystemParam>::State as #path::system::SystemParamState>::get_param(&mut state.state.#field_indices, system_meta, world, change_tick),)*
|
||||
#(#ignored_fields: <#ignored_field_types>::default(),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Safety: The `ParamState` is `ReadOnlySystemParamFetch`, so this can only read from the `World`
|
||||
unsafe impl<TSystemParamState: #path::system::SystemParamState + #path::system::ReadOnlySystemParamFetch, #punctuated_generics> #path::system::ReadOnlySystemParamFetch for FetchState <TSystemParamState, #punctuated_generic_idents> #where_clause {}
|
||||
// Safety: Each field is `ReadOnlySystemParam`, so this can only read from the `World`
|
||||
unsafe impl<'w, 's, #punctuated_generics> #path::system::ReadOnlySystemParam for #struct_name #ty_generics #read_only_where_clause {}
|
||||
};
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use thread_local::ThreadLocal;
|
|||
use crate::{
|
||||
entity::Entities,
|
||||
prelude::World,
|
||||
system::{SystemParam, SystemParamFetch, SystemParamState},
|
||||
system::{SystemParam, SystemParamState},
|
||||
};
|
||||
|
||||
use super::{CommandQueue, Commands};
|
||||
|
@ -49,27 +49,13 @@ pub struct ParallelCommands<'w, 's> {
|
|||
}
|
||||
|
||||
impl SystemParam for ParallelCommands<'_, '_> {
|
||||
type Fetch = ParallelCommandsState;
|
||||
}
|
||||
|
||||
impl<'w, 's> SystemParamFetch<'w, 's> for ParallelCommandsState {
|
||||
type Item = ParallelCommands<'w, 's>;
|
||||
|
||||
unsafe fn get_param(
|
||||
state: &'s mut Self,
|
||||
_: &crate::system::SystemMeta,
|
||||
world: &'w World,
|
||||
_: u32,
|
||||
) -> Self::Item {
|
||||
ParallelCommands {
|
||||
state,
|
||||
entities: world.entities(),
|
||||
}
|
||||
}
|
||||
type State = ParallelCommandsState;
|
||||
}
|
||||
|
||||
// SAFETY: no component or resource access to report
|
||||
unsafe impl SystemParamState for ParallelCommandsState {
|
||||
type Item<'w, 's> = ParallelCommands<'w, 's>;
|
||||
|
||||
fn init(_: &mut World, _: &mut crate::system::SystemMeta) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
@ -79,6 +65,18 @@ unsafe impl SystemParamState for ParallelCommandsState {
|
|||
cq.get_mut().apply(world);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
_: &crate::system::SystemMeta,
|
||||
world: &'w World,
|
||||
_: u32,
|
||||
) -> Self::Item<'w, 's> {
|
||||
ParallelCommands {
|
||||
state,
|
||||
entities: world.entities(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's> ParallelCommands<'w, 's> {
|
||||
|
|
|
@ -5,9 +5,8 @@ use crate::{
|
|||
query::Access,
|
||||
schedule::{SystemLabel, SystemLabelId},
|
||||
system::{
|
||||
check_system_change_tick, AsSystemLabel, ExclusiveSystemParam, ExclusiveSystemParamFetch,
|
||||
ExclusiveSystemParamItem, ExclusiveSystemParamState, IntoSystem, System, SystemMeta,
|
||||
SystemTypeIdLabel,
|
||||
check_system_change_tick, AsSystemLabel, ExclusiveSystemParam, ExclusiveSystemParamItem,
|
||||
ExclusiveSystemParamState, IntoSystem, System, SystemMeta, SystemTypeIdLabel,
|
||||
},
|
||||
world::{World, WorldId},
|
||||
};
|
||||
|
@ -25,7 +24,7 @@ where
|
|||
Param: ExclusiveSystemParam,
|
||||
{
|
||||
func: F,
|
||||
param_state: Option<Param::Fetch>,
|
||||
param_state: Option<Param::State>,
|
||||
system_meta: SystemMeta,
|
||||
world_id: Option<WorldId>,
|
||||
// NOTE: PhantomData<fn()-> T> gives this safe Send/Sync impls
|
||||
|
@ -95,7 +94,7 @@ where
|
|||
let saved_last_tick = world.last_change_tick;
|
||||
world.last_change_tick = self.system_meta.last_change_tick;
|
||||
|
||||
let params = <Param as ExclusiveSystemParam>::Fetch::get_param(
|
||||
let params = <Param as ExclusiveSystemParam>::State::get_param(
|
||||
self.param_state.as_mut().expect(PARAM_MESSAGE),
|
||||
&self.system_meta,
|
||||
);
|
||||
|
@ -130,7 +129,7 @@ where
|
|||
fn initialize(&mut self, world: &mut World) {
|
||||
self.world_id = Some(world.id());
|
||||
self.system_meta.last_change_tick = world.change_tick().wrapping_sub(MAX_CHANGE_AGE);
|
||||
self.param_state = Some(<Param::Fetch as ExclusiveSystemParamState>::init(
|
||||
self.param_state = Some(<Param::State as ExclusiveSystemParamState>::init(
|
||||
world,
|
||||
&mut self.system_meta,
|
||||
));
|
||||
|
|
|
@ -8,111 +8,86 @@ use bevy_ecs_macros::all_tuples;
|
|||
use bevy_utils::synccell::SyncCell;
|
||||
|
||||
pub trait ExclusiveSystemParam: Sized {
|
||||
type Fetch: for<'s> ExclusiveSystemParamFetch<'s>;
|
||||
type State: ExclusiveSystemParamState;
|
||||
}
|
||||
|
||||
pub type ExclusiveSystemParamItem<'s, P> =
|
||||
<<P as ExclusiveSystemParam>::Fetch as ExclusiveSystemParamFetch<'s>>::Item;
|
||||
<<P as ExclusiveSystemParam>::State as ExclusiveSystemParamState>::Item<'s>;
|
||||
|
||||
/// The state of a [`SystemParam`].
|
||||
pub trait ExclusiveSystemParamState: Send + Sync {
|
||||
pub trait ExclusiveSystemParamState: Send + Sync + 'static {
|
||||
type Item<'s>: ExclusiveSystemParam<State = Self>;
|
||||
|
||||
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self;
|
||||
#[inline]
|
||||
fn apply(&mut self, _world: &mut World) {}
|
||||
}
|
||||
|
||||
pub trait ExclusiveSystemParamFetch<'state>: ExclusiveSystemParamState {
|
||||
type Item: ExclusiveSystemParam<Fetch = Self>;
|
||||
fn get_param(state: &'state mut Self, system_meta: &SystemMeta) -> Self::Item;
|
||||
fn get_param<'s>(state: &'s mut Self, system_meta: &SystemMeta) -> Self::Item<'s>;
|
||||
}
|
||||
|
||||
impl<'a, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParam
|
||||
for &'a mut QueryState<Q, F>
|
||||
{
|
||||
type Fetch = QueryState<Q, F>;
|
||||
}
|
||||
|
||||
impl<'s, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParamFetch<'s>
|
||||
for QueryState<Q, F>
|
||||
{
|
||||
type Item = &'s mut QueryState<Q, F>;
|
||||
|
||||
fn get_param(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item {
|
||||
state
|
||||
}
|
||||
type State = QueryState<Q, F>;
|
||||
}
|
||||
|
||||
impl<Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParamState
|
||||
for QueryState<Q, F>
|
||||
{
|
||||
type Item<'s> = &'s mut QueryState<Q, F>;
|
||||
|
||||
fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self {
|
||||
QueryState::new(world)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: SystemParam + 'static> ExclusiveSystemParam for &'a mut SystemState<P> {
|
||||
type Fetch = SystemState<P>;
|
||||
}
|
||||
|
||||
impl<'s, P: SystemParam + 'static> ExclusiveSystemParamFetch<'s> for SystemState<P> {
|
||||
type Item = &'s mut SystemState<P>;
|
||||
|
||||
fn get_param(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item {
|
||||
fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> {
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P: SystemParam + 'static> ExclusiveSystemParam for &'a mut SystemState<P> {
|
||||
type State = SystemState<P>;
|
||||
}
|
||||
|
||||
impl<P: SystemParam> ExclusiveSystemParamState for SystemState<P> {
|
||||
type Item<'s> = &'s mut SystemState<P>;
|
||||
|
||||
fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self {
|
||||
SystemState::new(world)
|
||||
}
|
||||
|
||||
fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> {
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, T: FromWorld + Send + Sync + 'static> ExclusiveSystemParam for Local<'s, T> {
|
||||
type Fetch = LocalState<T>;
|
||||
}
|
||||
|
||||
impl<'s, T: FromWorld + Send + Sync + 'static> ExclusiveSystemParamFetch<'s> for LocalState<T> {
|
||||
type Item = Local<'s, T>;
|
||||
|
||||
fn get_param(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item {
|
||||
Local(state.0.get())
|
||||
}
|
||||
type State = LocalState<T>;
|
||||
}
|
||||
|
||||
impl<T: FromWorld + Send + Sync> ExclusiveSystemParamState for LocalState<T> {
|
||||
type Item<'s> = Local<'s, T>;
|
||||
|
||||
fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self {
|
||||
Self(SyncCell::new(T::from_world(world)))
|
||||
}
|
||||
|
||||
fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> {
|
||||
Local(state.0.get())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_exclusive_system_param_tuple {
|
||||
($($param: ident),*) => {
|
||||
impl<$($param: ExclusiveSystemParam),*> ExclusiveSystemParam for ($($param,)*) {
|
||||
type Fetch = ($($param::Fetch,)*);
|
||||
type State = ($($param::State,)*);
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
#[allow(non_snake_case)]
|
||||
impl<'s, $($param: ExclusiveSystemParamFetch<'s>),*> ExclusiveSystemParamFetch<'s> for ($($param,)*) {
|
||||
type Item = ($($param::Item,)*);
|
||||
|
||||
#[inline]
|
||||
#[allow(clippy::unused_unit)]
|
||||
fn get_param(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
) -> Self::Item {
|
||||
|
||||
let ($($param,)*) = state;
|
||||
($($param::get_param($param, system_meta),)*)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: implementors of each `ExclusiveSystemParamState` in the tuple have validated their impls
|
||||
#[allow(clippy::undocumented_unsafe_blocks)] // false positive by clippy
|
||||
#[allow(non_snake_case)]
|
||||
impl<$($param: ExclusiveSystemParamState),*> ExclusiveSystemParamState for ($($param,)*) {
|
||||
type Item<'s> = ($($param::Item<'s>,)*);
|
||||
|
||||
#[inline]
|
||||
fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
|
||||
(($($param::init(_world, _system_meta),)*))
|
||||
|
@ -123,7 +98,19 @@ macro_rules! impl_exclusive_system_param_tuple {
|
|||
let ($($param,)*) = self;
|
||||
$($param.apply(_world);)*
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(clippy::unused_unit)]
|
||||
fn get_param<'s>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
) -> Self::Item<'s> {
|
||||
|
||||
let ($($param,)*) = state;
|
||||
($($param::get_param($param, system_meta),)*)
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ use crate::{
|
|||
query::{Access, FilteredAccessSet},
|
||||
schedule::{SystemLabel, SystemLabelId},
|
||||
system::{
|
||||
check_system_change_tick, ReadOnlySystemParamFetch, System, SystemParam, SystemParamFetch,
|
||||
SystemParamItem, SystemParamState,
|
||||
check_system_change_tick, ReadOnlySystemParam, System, SystemParam, SystemParamItem,
|
||||
SystemParamState,
|
||||
},
|
||||
world::{World, WorldId},
|
||||
};
|
||||
|
@ -135,7 +135,7 @@ impl SystemMeta {
|
|||
/// ```
|
||||
pub struct SystemState<Param: SystemParam + 'static> {
|
||||
meta: SystemMeta,
|
||||
param_state: <Param as SystemParam>::Fetch,
|
||||
param_state: <Param as SystemParam>::State,
|
||||
world_id: WorldId,
|
||||
archetype_generation: ArchetypeGeneration,
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ impl<Param: SystemParam> SystemState<Param> {
|
|||
pub fn new(world: &mut World) -> Self {
|
||||
let mut meta = SystemMeta::new::<Param>();
|
||||
meta.last_change_tick = world.change_tick().wrapping_sub(MAX_CHANGE_AGE);
|
||||
let param_state = <Param::Fetch as SystemParamState>::init(world, &mut meta);
|
||||
let param_state = <Param::State as SystemParamState>::init(world, &mut meta);
|
||||
Self {
|
||||
meta,
|
||||
param_state,
|
||||
|
@ -160,12 +160,9 @@ impl<Param: SystemParam> SystemState<Param> {
|
|||
|
||||
/// Retrieve the [`SystemParam`] values. This can only be called when all parameters are read-only.
|
||||
#[inline]
|
||||
pub fn get<'w, 's>(
|
||||
&'s mut self,
|
||||
world: &'w World,
|
||||
) -> <Param::Fetch as SystemParamFetch<'w, 's>>::Item
|
||||
pub fn get<'w, 's>(&'s mut self, world: &'w World) -> SystemParamItem<'w, 's, Param>
|
||||
where
|
||||
Param::Fetch: ReadOnlySystemParamFetch,
|
||||
Param: ReadOnlySystemParam,
|
||||
{
|
||||
self.validate_world_and_update_archetypes(world);
|
||||
// SAFETY: Param is read-only and doesn't allow mutable access to World. It also matches the World this SystemState was created with.
|
||||
|
@ -174,10 +171,7 @@ impl<Param: SystemParam> SystemState<Param> {
|
|||
|
||||
/// Retrieve the mutable [`SystemParam`] values.
|
||||
#[inline]
|
||||
pub fn get_mut<'w, 's>(
|
||||
&'s mut self,
|
||||
world: &'w mut World,
|
||||
) -> <Param::Fetch as SystemParamFetch<'w, 's>>::Item {
|
||||
pub fn get_mut<'w, 's>(&'s mut self, world: &'w mut World) -> SystemParamItem<'w, 's, Param> {
|
||||
self.validate_world_and_update_archetypes(world);
|
||||
// SAFETY: World is uniquely borrowed and matches the World this SystemState was created with.
|
||||
unsafe { self.get_unchecked_manual(world) }
|
||||
|
@ -221,9 +215,9 @@ impl<Param: SystemParam> SystemState<Param> {
|
|||
pub unsafe fn get_unchecked_manual<'w, 's>(
|
||||
&'s mut self,
|
||||
world: &'w World,
|
||||
) -> <Param::Fetch as SystemParamFetch<'w, 's>>::Item {
|
||||
) -> SystemParamItem<'w, 's, Param> {
|
||||
let change_tick = world.increment_change_tick();
|
||||
let param = <Param::Fetch as SystemParamFetch>::get_param(
|
||||
let param = <Param::State as SystemParamState>::get_param(
|
||||
&mut self.param_state,
|
||||
&self.meta,
|
||||
world,
|
||||
|
@ -315,7 +309,7 @@ where
|
|||
Param: SystemParam,
|
||||
{
|
||||
func: F,
|
||||
param_state: Option<Param::Fetch>,
|
||||
param_state: Option<Param::State>,
|
||||
system_meta: SystemMeta,
|
||||
world_id: Option<WorldId>,
|
||||
archetype_generation: ArchetypeGeneration,
|
||||
|
@ -400,7 +394,7 @@ where
|
|||
// We update the archetype component access correctly based on `Param`'s requirements
|
||||
// in `update_archetype_component_access`.
|
||||
// Our caller upholds the requirements.
|
||||
let params = <Param as SystemParam>::Fetch::get_param(
|
||||
let params = <Param as SystemParam>::State::get_param(
|
||||
self.param_state.as_mut().expect(Self::PARAM_MESSAGE),
|
||||
&self.system_meta,
|
||||
world,
|
||||
|
@ -429,7 +423,7 @@ where
|
|||
fn initialize(&mut self, world: &mut World) {
|
||||
self.world_id = Some(world.id());
|
||||
self.system_meta.last_change_tick = world.change_tick().wrapping_sub(MAX_CHANGE_AGE);
|
||||
self.param_state = Some(<Param::Fetch as SystemParamState>::init(
|
||||
self.param_state = Some(<Param::State as SystemParamState>::init(
|
||||
world,
|
||||
&mut self.system_meta,
|
||||
));
|
||||
|
@ -588,7 +582,7 @@ macro_rules! impl_system_function {
|
|||
where
|
||||
for <'a> &'a mut Func:
|
||||
FnMut(In<Input>, $($param),*) -> Out +
|
||||
FnMut(In<Input>, $(<<$param as SystemParam>::Fetch as SystemParamFetch>::Item),*) -> Out, Out: 'static
|
||||
FnMut(In<Input>, $(SystemParamItem<$param>),*) -> Out, Out: 'static
|
||||
{
|
||||
#[inline]
|
||||
fn run(&mut self, input: Input, param_value: SystemParamItem< ($($param,)*)>) -> Out {
|
||||
|
|
|
@ -72,7 +72,7 @@ use std::{
|
|||
///
|
||||
/// ```text
|
||||
/// expected ... [ParamType]
|
||||
/// found associated type `<<[ParamType] as SystemParam>::Fetch as SystemParamFetch<'_, '_>>::Item`
|
||||
/// found associated type `<<[ParamType] as SystemParam>::State as SystemParamState>::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`]
|
||||
|
@ -81,7 +81,7 @@ use std::{
|
|||
/// ## Details
|
||||
///
|
||||
/// The derive macro requires that the [`SystemParam`] implementation of
|
||||
/// each field `F`'s [`Fetch`](`SystemParam::Fetch`)'s [`Item`](`SystemParamFetch::Item`) is itself `F`
|
||||
/// each field `F`'s [`State`](`SystemParam::State`)'s [`Item`](`SystemParamState::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.
|
||||
|
@ -122,17 +122,17 @@ use std::{
|
|||
/// [`SyncCell`]: bevy_utils::synccell::SyncCell
|
||||
/// [`Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html
|
||||
pub trait SystemParam: Sized {
|
||||
type Fetch: for<'w, 's> SystemParamFetch<'w, 's>;
|
||||
type State: SystemParamState;
|
||||
}
|
||||
|
||||
pub type SystemParamItem<'w, 's, P> = <<P as SystemParam>::Fetch as SystemParamFetch<'w, 's>>::Item;
|
||||
pub type SystemParamItem<'w, 's, P> = <<P as SystemParam>::State as SystemParamState>::Item<'w, 's>;
|
||||
|
||||
/// 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`]).
|
||||
/// [`World`] access used by the [`SystemParamState`].
|
||||
/// 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 {
|
||||
|
@ -141,37 +141,35 @@ pub unsafe trait SystemParamState: Send + Sync + 'static {
|
|||
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<Fetch = Self>;
|
||||
type Item<'world, 'state>: SystemParam<State = Self>;
|
||||
/// # 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(
|
||||
unsafe fn get_param<'world, 'state>(
|
||||
state: &'state mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'world World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item;
|
||||
) -> Self::Item<'world, 'state>;
|
||||
}
|
||||
|
||||
/// A [`SystemParam`] that only reads a given [`World`].
|
||||
///
|
||||
/// # Safety
|
||||
/// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParamState::get_param`]
|
||||
pub unsafe trait ReadOnlySystemParam: SystemParam {}
|
||||
|
||||
impl<'w, 's, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemParam
|
||||
for Query<'w, 's, Q, F>
|
||||
{
|
||||
type Fetch = QueryState<Q, F>;
|
||||
type State = QueryState<Q, F>;
|
||||
}
|
||||
|
||||
// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
|
||||
unsafe impl<Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery> ReadOnlySystemParamFetch
|
||||
for QueryState<Q, F>
|
||||
unsafe impl<'w, 's, Q: ReadOnlyWorldQuery + 'static, F: ReadOnlyWorldQuery + 'static>
|
||||
ReadOnlySystemParam for Query<'w, 's, Q, F>
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -180,6 +178,8 @@ unsafe impl<Q: ReadOnlyWorldQuery, F: ReadOnlyWorldQuery> ReadOnlySystemParamFet
|
|||
unsafe impl<Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemParamState
|
||||
for QueryState<Q, F>
|
||||
{
|
||||
type Item<'w, 's> = Query<'w, 's, Q, F>;
|
||||
|
||||
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
|
||||
let state = QueryState::new(world);
|
||||
assert_component_access_compatibility(
|
||||
|
@ -205,20 +205,14 @@ unsafe impl<Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemPara
|
|||
.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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
Query::new(world, state, system_meta.last_change_tick, change_tick)
|
||||
}
|
||||
}
|
||||
|
@ -245,13 +239,13 @@ fn assert_component_access_compatibility(
|
|||
}
|
||||
|
||||
pub struct ParamSet<'w, 's, T: SystemParam> {
|
||||
param_states: &'s mut T::Fetch,
|
||||
param_states: &'s mut T::State,
|
||||
world: &'w World,
|
||||
system_meta: SystemMeta,
|
||||
change_tick: u32,
|
||||
}
|
||||
/// The [`SystemParamState`] of [`ParamSet<T::Item>`].
|
||||
pub struct ParamSetState<T: for<'w, 's> SystemParamFetch<'w, 's>>(T);
|
||||
pub struct ParamSetState<T: SystemParamState>(T);
|
||||
|
||||
impl_param_set!();
|
||||
|
||||
|
@ -308,7 +302,7 @@ pub struct Res<'w, T: Resource> {
|
|||
}
|
||||
|
||||
// SAFETY: Res only reads a single World resource
|
||||
unsafe impl<T: Resource> ReadOnlySystemParamFetch for ResState<T> {}
|
||||
unsafe impl<'w, T: Resource> ReadOnlySystemParam for Res<'w, T> {}
|
||||
|
||||
impl<'w, T: Resource> Debug for Res<'w, T>
|
||||
where
|
||||
|
@ -396,12 +390,14 @@ pub struct ResState<T> {
|
|||
}
|
||||
|
||||
impl<'a, T: Resource> SystemParam for Res<'a, T> {
|
||||
type Fetch = ResState<T>;
|
||||
type State = ResState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res
|
||||
// conflicts with any prior access, a panic will occur.
|
||||
unsafe impl<T: Resource> SystemParamState for ResState<T> {
|
||||
type Item<'w, 's> = Res<'w, 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();
|
||||
|
@ -426,18 +422,14 @@ unsafe impl<T: Resource> SystemParamState for ResState<T> {
|
|||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState<T> {
|
||||
type Item = Res<'w, T>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_param(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
let (ptr, ticks) = world
|
||||
.get_resource_with_ticks(state.component_id)
|
||||
.unwrap_or_else(|| {
|
||||
|
@ -463,30 +455,28 @@ impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState<T> {
|
|||
pub struct OptionResState<T>(ResState<T>);
|
||||
|
||||
impl<'a, T: Resource> SystemParam for Option<Res<'a, T>> {
|
||||
type Fetch = OptionResState<T>;
|
||||
type State = OptionResState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: Only reads a single World resource
|
||||
unsafe impl<T: Resource> ReadOnlySystemParamFetch for OptionResState<T> {}
|
||||
unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option<Res<'a, T>> {}
|
||||
|
||||
// SAFETY: this impl defers to `ResState`, which initializes
|
||||
// and validates the correct world access
|
||||
unsafe impl<T: Resource> SystemParamState for OptionResState<T> {
|
||||
type Item<'w, 's> = Option<Res<'w, 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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world
|
||||
.get_resource_with_ticks(state.0.component_id)
|
||||
.map(|(ptr, ticks)| Res {
|
||||
|
@ -507,12 +497,14 @@ pub struct ResMutState<T> {
|
|||
}
|
||||
|
||||
impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
|
||||
type Fetch = ResMutState<T>;
|
||||
type State = ResMutState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res
|
||||
// conflicts with any prior access, a panic will occur.
|
||||
unsafe impl<T: Resource> SystemParamState for ResMutState<T> {
|
||||
type Item<'w, 's> = ResMut<'w, 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();
|
||||
|
@ -540,18 +532,14 @@ unsafe impl<T: Resource> SystemParamState for ResMutState<T> {
|
|||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResMutState<T> {
|
||||
type Item = ResMut<'w, T>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_param(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
let value = world
|
||||
.get_resource_unchecked_mut_with_id(state.component_id)
|
||||
.unwrap_or_else(|| {
|
||||
|
@ -579,27 +567,25 @@ impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResMutState<T> {
|
|||
pub struct OptionResMutState<T>(ResMutState<T>);
|
||||
|
||||
impl<'a, T: Resource> SystemParam for Option<ResMut<'a, T>> {
|
||||
type Fetch = OptionResMutState<T>;
|
||||
type State = OptionResMutState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: this impl defers to `ResMutState`, which initializes
|
||||
// and validates the correct world access
|
||||
unsafe impl<T: Resource> SystemParamState for OptionResMutState<T> {
|
||||
type Item<'w, 's> = Option<ResMut<'w, 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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world
|
||||
.get_resource_unchecked_mut_with_id(state.0.component_id)
|
||||
.map(|value| ResMut {
|
||||
|
@ -615,14 +601,16 @@ impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResMutState<T> {
|
|||
}
|
||||
|
||||
impl<'w, 's> SystemParam for Commands<'w, 's> {
|
||||
type Fetch = CommandQueue;
|
||||
type State = CommandQueue;
|
||||
}
|
||||
|
||||
// SAFETY: Commands only accesses internal state
|
||||
unsafe impl ReadOnlySystemParamFetch for CommandQueue {}
|
||||
unsafe impl<'w, 's> ReadOnlySystemParam for Commands<'w, 's> {}
|
||||
|
||||
// SAFETY: only local state is accessed
|
||||
unsafe impl SystemParamState for CommandQueue {
|
||||
type Item<'w, 's> = Commands<'w, 's>;
|
||||
|
||||
fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
@ -630,35 +618,33 @@ unsafe impl SystemParamState for CommandQueue {
|
|||
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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
Commands::new(state, world)
|
||||
}
|
||||
}
|
||||
|
||||
/// SAFETY: only reads world
|
||||
unsafe impl ReadOnlySystemParamFetch for WorldState {}
|
||||
unsafe impl<'w> ReadOnlySystemParam for &'w World {}
|
||||
|
||||
/// The [`SystemParamState`] of [`&World`](crate::world::World).
|
||||
#[doc(hidden)]
|
||||
pub struct WorldState;
|
||||
|
||||
impl<'w> SystemParam for &'w World {
|
||||
type Fetch = WorldState;
|
||||
type State = WorldState;
|
||||
}
|
||||
|
||||
// SAFETY: `read_all` access is set and conflicts result in a panic
|
||||
unsafe impl SystemParamState for WorldState {
|
||||
type Item<'w, 's> = &'w World;
|
||||
|
||||
fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self {
|
||||
let mut access = Access::default();
|
||||
access.read_all();
|
||||
|
@ -684,16 +670,13 @@ unsafe impl SystemParamState for WorldState {
|
|||
|
||||
WorldState
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's> SystemParamFetch<'w, 's> for WorldState {
|
||||
type Item = &'w World;
|
||||
unsafe fn get_param(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
_state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world
|
||||
}
|
||||
}
|
||||
|
@ -744,7 +727,7 @@ impl<'w, 's> SystemParamFetch<'w, 's> for WorldState {
|
|||
pub struct Local<'a, T: FromWorld + Send + 'static>(pub(crate) &'a mut T);
|
||||
|
||||
// SAFETY: Local only accesses internal state
|
||||
unsafe impl<T: Send + 'static> ReadOnlySystemParamFetch for LocalState<T> {}
|
||||
unsafe impl<'a, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'a, T> {}
|
||||
|
||||
impl<'a, T: FromWorld + Send + Sync + 'static> Debug for Local<'a, T>
|
||||
where
|
||||
|
@ -800,26 +783,24 @@ where
|
|||
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>;
|
||||
type State = LocalState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: only local state is accessed
|
||||
unsafe impl<T: FromWorld + Send + 'static> SystemParamState for LocalState<T> {
|
||||
type Item<'w, 's> = Local<'s, 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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
_world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
Local(state.0.get())
|
||||
}
|
||||
}
|
||||
|
@ -881,7 +862,7 @@ impl<'a, T: Component> IntoIterator for &'a RemovedComponents<'a, T> {
|
|||
}
|
||||
|
||||
// SAFETY: Only reads World components
|
||||
unsafe impl<T: Component> ReadOnlySystemParamFetch for RemovedComponentsState<T> {}
|
||||
unsafe impl<'a, T: Component> ReadOnlySystemParam for RemovedComponents<'a, T> {}
|
||||
|
||||
/// The [`SystemParamState`] of [`RemovedComponents<T>`].
|
||||
#[doc(hidden)]
|
||||
|
@ -891,30 +872,28 @@ pub struct RemovedComponentsState<T> {
|
|||
}
|
||||
|
||||
impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> {
|
||||
type Fetch = RemovedComponentsState<T>;
|
||||
type State = RemovedComponentsState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: no component access. removed component entity collections can be read in parallel and are
|
||||
// never mutably borrowed during system execution
|
||||
unsafe impl<T: Component> SystemParamState for RemovedComponentsState<T> {
|
||||
type Item<'w, 's> = RemovedComponents<'w, 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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
RemovedComponents {
|
||||
world,
|
||||
component_id: state.component_id,
|
||||
|
@ -943,7 +922,7 @@ pub struct NonSend<'w, T: 'static> {
|
|||
}
|
||||
|
||||
// SAFETY: Only reads a single World non-send resource
|
||||
unsafe impl<T> ReadOnlySystemParamFetch for NonSendState<T> {}
|
||||
unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {}
|
||||
|
||||
impl<'w, T> Debug for NonSend<'w, T>
|
||||
where
|
||||
|
@ -996,12 +975,14 @@ pub struct NonSendState<T> {
|
|||
}
|
||||
|
||||
impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
|
||||
type Fetch = NonSendState<T>;
|
||||
type State = NonSendState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: NonSendComponentId and ArchetypeComponentId access is applied to SystemMeta. If this
|
||||
// NonSend conflicts with any prior access, a panic will occur.
|
||||
unsafe impl<T: 'static> SystemParamState for NonSendState<T> {
|
||||
type Item<'w, 's> = NonSend<'w, T>;
|
||||
|
||||
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
|
||||
system_meta.set_non_send();
|
||||
|
||||
|
@ -1028,18 +1009,14 @@ unsafe impl<T: 'static> SystemParamState for NonSendState<T> {
|
|||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState<T> {
|
||||
type Item = NonSend<'w, T>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_param(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.validate_non_send_access::<T>();
|
||||
let (ptr, ticks) = world
|
||||
.get_resource_with_ticks(state.component_id)
|
||||
|
@ -1066,30 +1043,28 @@ impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState<T> {
|
|||
pub struct OptionNonSendState<T>(NonSendState<T>);
|
||||
|
||||
impl<'w, T: 'static> SystemParam for Option<NonSend<'w, T>> {
|
||||
type Fetch = OptionNonSendState<T>;
|
||||
type State = OptionNonSendState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: Only reads a single non-send resource
|
||||
unsafe impl<T: 'static> ReadOnlySystemParamFetch for OptionNonSendState<T> {}
|
||||
unsafe impl<'w, T: 'static> ReadOnlySystemParam for Option<NonSend<'w, T>> {}
|
||||
|
||||
// SAFETY: this impl defers to `NonSendState`, which initializes
|
||||
// and validates the correct world access
|
||||
unsafe impl<T: 'static> SystemParamState for OptionNonSendState<T> {
|
||||
type Item<'w, 's> = Option<NonSend<'w, 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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.validate_non_send_access::<T>();
|
||||
world
|
||||
.get_resource_with_ticks(state.0.component_id)
|
||||
|
@ -1110,12 +1085,14 @@ pub struct NonSendMutState<T> {
|
|||
}
|
||||
|
||||
impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
|
||||
type Fetch = NonSendMutState<T>;
|
||||
type State = NonSendMutState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this
|
||||
// NonSendMut conflicts with any prior access, a panic will occur.
|
||||
unsafe impl<T: 'static> SystemParamState for NonSendMutState<T> {
|
||||
type Item<'w, 's> = NonSendMut<'w, T>;
|
||||
|
||||
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
|
||||
system_meta.set_non_send();
|
||||
|
||||
|
@ -1145,18 +1122,14 @@ unsafe impl<T: 'static> SystemParamState for NonSendMutState<T> {
|
|||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendMutState<T> {
|
||||
type Item = NonSendMut<'w, T>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_param(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.validate_non_send_access::<T>();
|
||||
let (ptr, ticks) = world
|
||||
.get_resource_with_ticks(state.component_id)
|
||||
|
@ -1180,27 +1153,25 @@ impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendMutState<T> {
|
|||
pub struct OptionNonSendMutState<T>(NonSendMutState<T>);
|
||||
|
||||
impl<'a, T: 'static> SystemParam for Option<NonSendMut<'a, T>> {
|
||||
type Fetch = OptionNonSendMutState<T>;
|
||||
type State = OptionNonSendMutState<T>;
|
||||
}
|
||||
|
||||
// SAFETY: this impl defers to `NonSendMutState`, which initializes
|
||||
// and validates the correct world access
|
||||
unsafe impl<T: 'static> SystemParamState for OptionNonSendMutState<T> {
|
||||
type Item<'w, 's> = Option<NonSendMut<'w, 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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.validate_non_send_access::<T>();
|
||||
world
|
||||
.get_resource_with_ticks(state.0.component_id)
|
||||
|
@ -1212,11 +1183,11 @@ impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendMutState<T> {
|
|||
}
|
||||
|
||||
impl<'a> SystemParam for &'a Archetypes {
|
||||
type Fetch = ArchetypesState;
|
||||
type State = ArchetypesState;
|
||||
}
|
||||
|
||||
// SAFETY: Only reads World archetypes
|
||||
unsafe impl ReadOnlySystemParamFetch for ArchetypesState {}
|
||||
unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}
|
||||
|
||||
/// The [`SystemParamState`] of [`Archetypes`].
|
||||
#[doc(hidden)]
|
||||
|
@ -1224,31 +1195,29 @@ pub struct ArchetypesState;
|
|||
|
||||
// SAFETY: no component value access
|
||||
unsafe impl SystemParamState for ArchetypesState {
|
||||
type Item<'w, 's> = &'w Archetypes;
|
||||
|
||||
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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
_state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.archetypes()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SystemParam for &'a Components {
|
||||
type Fetch = ComponentsState;
|
||||
type State = ComponentsState;
|
||||
}
|
||||
|
||||
// SAFETY: Only reads World components
|
||||
unsafe impl ReadOnlySystemParamFetch for ComponentsState {}
|
||||
unsafe impl<'a> ReadOnlySystemParam for &'a Components {}
|
||||
|
||||
/// The [`SystemParamState`] of [`Components`].
|
||||
#[doc(hidden)]
|
||||
|
@ -1256,31 +1225,29 @@ pub struct ComponentsState;
|
|||
|
||||
// SAFETY: no component value access
|
||||
unsafe impl SystemParamState for ComponentsState {
|
||||
type Item<'w, 's> = &'w Components;
|
||||
|
||||
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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
_state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.components()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SystemParam for &'a Entities {
|
||||
type Fetch = EntitiesState;
|
||||
type State = EntitiesState;
|
||||
}
|
||||
|
||||
// SAFETY: Only reads World entities
|
||||
unsafe impl ReadOnlySystemParamFetch for EntitiesState {}
|
||||
unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}
|
||||
|
||||
/// The [`SystemParamState`] of [`Entities`].
|
||||
#[doc(hidden)]
|
||||
|
@ -1288,31 +1255,29 @@ pub struct EntitiesState;
|
|||
|
||||
// SAFETY: no component value access
|
||||
unsafe impl SystemParamState for EntitiesState {
|
||||
type Item<'w, 's> = &'w Entities;
|
||||
|
||||
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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
_state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.entities()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SystemParam for &'a Bundles {
|
||||
type Fetch = BundlesState;
|
||||
type State = BundlesState;
|
||||
}
|
||||
|
||||
// SAFETY: Only reads World bundles
|
||||
unsafe impl ReadOnlySystemParamFetch for BundlesState {}
|
||||
unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}
|
||||
|
||||
/// The [`SystemParamState`] of [`Bundles`].
|
||||
#[doc(hidden)]
|
||||
|
@ -1320,21 +1285,19 @@ pub struct BundlesState;
|
|||
|
||||
// SAFETY: no component value access
|
||||
unsafe impl SystemParamState for BundlesState {
|
||||
type Item<'w, 's> = &'w Bundles;
|
||||
|
||||
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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
_state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
world.bundles()
|
||||
}
|
||||
}
|
||||
|
@ -1369,10 +1332,10 @@ impl SystemChangeTick {
|
|||
}
|
||||
|
||||
// SAFETY: Only reads internal system state
|
||||
unsafe impl ReadOnlySystemParamFetch for SystemChangeTickState {}
|
||||
unsafe impl ReadOnlySystemParam for SystemChangeTick {}
|
||||
|
||||
impl SystemParam for SystemChangeTick {
|
||||
type Fetch = SystemChangeTickState;
|
||||
type State = SystemChangeTickState;
|
||||
}
|
||||
|
||||
/// The [`SystemParamState`] of [`SystemChangeTick`].
|
||||
|
@ -1381,20 +1344,18 @@ pub struct SystemChangeTickState {}
|
|||
|
||||
// SAFETY: `SystemParamTickState` doesn't require any world access
|
||||
unsafe impl SystemParamState for SystemChangeTickState {
|
||||
type Item<'w, 's> = SystemChangeTick;
|
||||
|
||||
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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
_state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
_world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
SystemChangeTick {
|
||||
last_change_tick: system_meta.last_change_tick,
|
||||
change_tick,
|
||||
|
@ -1450,11 +1411,11 @@ impl<'s> std::fmt::Display for SystemName<'s> {
|
|||
}
|
||||
|
||||
impl<'s> SystemParam for SystemName<'s> {
|
||||
type Fetch = SystemNameState;
|
||||
type State = SystemNameState;
|
||||
}
|
||||
|
||||
// SAFETY: Only reads internal system state
|
||||
unsafe impl ReadOnlySystemParamFetch for SystemNameState {}
|
||||
unsafe impl<'s> ReadOnlySystemParam for SystemName<'s> {}
|
||||
|
||||
/// The [`SystemParamState`] of [`SystemName`].
|
||||
#[doc(hidden)]
|
||||
|
@ -1464,23 +1425,21 @@ pub struct SystemNameState {
|
|||
|
||||
// SAFETY: no component value access
|
||||
unsafe impl SystemParamState for SystemNameState {
|
||||
type Item<'w, 's> = SystemName<'s>;
|
||||
|
||||
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(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
_world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
SystemName {
|
||||
name: state.name.as_ref(),
|
||||
}
|
||||
|
@ -1490,35 +1449,19 @@ impl<'w, 's> SystemParamFetch<'w, 's> for SystemNameState {
|
|||
macro_rules! impl_system_param_tuple {
|
||||
($($param: ident),*) => {
|
||||
impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
|
||||
type Fetch = ($($param::Fetch,)*);
|
||||
type State = ($($param::State,)*);
|
||||
}
|
||||
|
||||
// SAFETY: tuple consists only of ReadOnlySystemParamFetches
|
||||
unsafe impl<$($param: ReadOnlySystemParamFetch),*> ReadOnlySystemParamFetch for ($($param,)*) {}
|
||||
// SAFETY: tuple consists only of ReadOnlySystemParams
|
||||
unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam 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),)*)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: implementors of each `SystemParamState` in the tuple have validated their impls
|
||||
#[allow(clippy::undocumented_unsafe_blocks)] // false positive by clippy
|
||||
#[allow(non_snake_case)]
|
||||
unsafe impl<$($param: SystemParamState),*> SystemParamState for ($($param,)*) {
|
||||
type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);
|
||||
|
||||
#[inline]
|
||||
fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self {
|
||||
(($($param::init(_world, _system_meta),)*))
|
||||
|
@ -1535,6 +1478,19 @@ macro_rules! impl_system_param_tuple {
|
|||
let ($($param,)*) = self;
|
||||
$($param.apply(_world);)*
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(clippy::unused_unit)]
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
_world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item<'w, 's> {
|
||||
|
||||
let ($($param,)*) = state;
|
||||
($($param::get_param($param, _system_meta, _world, _change_tick),)*)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1553,7 +1509,7 @@ pub mod lifetimeless {
|
|||
/// 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),
|
||||
/// `Self::State::Item == Self` (ignoring lifetimes for brevity),
|
||||
/// no matter the argument [`SystemParam`] (`P`) (other than
|
||||
/// that `P` must be `'static`)
|
||||
///
|
||||
|
@ -1592,7 +1548,7 @@ pub mod lifetimeless {
|
|||
/// fn do_thing_generically<T: SystemParam + 'static>(t: T) {}
|
||||
///
|
||||
/// #[derive(SystemParam)]
|
||||
/// struct GenericParam<'w,'s, T: SystemParam> {
|
||||
/// struct GenericParam<'w, 's, T: SystemParam> {
|
||||
/// field: T,
|
||||
/// #[system_param(ignore)]
|
||||
/// // Use the lifetimes in this type, or they will be unbound.
|
||||
|
@ -1631,39 +1587,23 @@ impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {
|
|||
pub struct StaticSystemParamState<S, P>(S, PhantomData<fn() -> P>);
|
||||
|
||||
// SAFETY: This doesn't add any more reads, and the delegated fetch confirms it
|
||||
unsafe impl<S: ReadOnlySystemParamFetch, P> ReadOnlySystemParamFetch
|
||||
for StaticSystemParamState<S, P>
|
||||
unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam
|
||||
for StaticSystemParam<'w, '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 {
|
||||
// SAFETY: We properly delegate SystemParamState
|
||||
StaticSystemParam(S::get_param(&mut state.0, system_meta, world, change_tick))
|
||||
}
|
||||
type State = StaticSystemParamState<P::State, P>;
|
||||
}
|
||||
|
||||
// SAFETY: all methods are just delegated to `S`'s `SystemParamState` implementation
|
||||
unsafe impl<S: SystemParamState, P: SystemParam + 'static> SystemParamState
|
||||
unsafe impl<S: SystemParamState, P: SystemParam<State = S> + 'static> SystemParamState
|
||||
for StaticSystemParamState<S, P>
|
||||
{
|
||||
type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;
|
||||
|
||||
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
|
||||
Self(S::init(world, system_meta), PhantomData)
|
||||
}
|
||||
|
@ -1675,6 +1615,16 @@ unsafe impl<S: SystemParamState, P: SystemParam + 'static> SystemParamState
|
|||
fn apply(&mut self, world: &mut World) {
|
||||
self.0.apply(world);
|
||||
}
|
||||
|
||||
unsafe fn get_param<'world, 'state>(
|
||||
state: &'state mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'world World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item<'world, 'state> {
|
||||
// SAFETY: We properly delegate SystemParamState
|
||||
StaticSystemParam(S::get_param(&mut state.0, system_meta, world, change_tick))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_ecs::system::{ReadOnlySystemParamFetch, SystemParam, SystemState};
|
||||
use bevy_ecs::system::{ReadOnlySystemParam, SystemParam, SystemState};
|
||||
|
||||
#[derive(Component)]
|
||||
struct Foo;
|
||||
|
@ -18,8 +18,8 @@ fn main() {
|
|||
assert_readonly::<Mutable>();
|
||||
}
|
||||
|
||||
fn assert_readonly<P: SystemParam>()
|
||||
fn assert_readonly<P>()
|
||||
where
|
||||
<P as SystemParam>::Fetch: ReadOnlySystemParamFetch,
|
||||
P: ReadOnlySystemParam,
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
warning: unused import: `SystemState`
|
||||
--> tests/ui/system_param_derive_readonly.rs:2:63
|
||||
--> tests/ui/system_param_derive_readonly.rs:2:58
|
||||
|
|
||||
2 | use bevy_ecs::system::{ReadOnlySystemParamFetch, SystemParam, SystemState};
|
||||
| ^^^^^^^^^^^
|
||||
2 | use bevy_ecs::system::{ReadOnlySystemParam, SystemParam, SystemState};
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(unused_imports)]` on by default
|
||||
|
||||
|
@ -23,14 +23,14 @@ error[E0277]: the trait bound `&'static mut Foo: ReadOnlyWorldQuery` is not sati
|
|||
(F0, F1, F2, F3, F4, F5, F6)
|
||||
and $N others
|
||||
= note: `ReadOnlyWorldQuery` is implemented for `&'static Foo`, but not for `&'static mut Foo`
|
||||
= note: required for `QueryState<&'static mut Foo>` to implement `ReadOnlySystemParamFetch`
|
||||
= note: 2 redundant requirements hidden
|
||||
= note: required for `FetchState<(QueryState<&'static mut Foo>,)>` to implement `ReadOnlySystemParamFetch`
|
||||
= note: required for `bevy_ecs::system::Query<'_, '_, &'static mut Foo>` to implement `ReadOnlySystemParam`
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `Mutable<'_, '_>` to implement `ReadOnlySystemParam`
|
||||
note: required by a bound in `assert_readonly`
|
||||
--> tests/ui/system_param_derive_readonly.rs:23:32
|
||||
--> tests/ui/system_param_derive_readonly.rs:23:8
|
||||
|
|
||||
21 | fn assert_readonly<P: SystemParam>()
|
||||
21 | fn assert_readonly<P>()
|
||||
| --------------- required by a bound in this
|
||||
22 | where
|
||||
23 | <P as SystemParam>::Fetch: ReadOnlySystemParamFetch,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_readonly`
|
||||
23 | P: ReadOnlySystemParam,
|
||||
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_readonly`
|
||||
|
|
|
@ -2,8 +2,8 @@ use crate::MainWorld;
|
|||
use bevy_ecs::{
|
||||
prelude::*,
|
||||
system::{
|
||||
ReadOnlySystemParamFetch, ResState, SystemMeta, SystemParam, SystemParamFetch,
|
||||
SystemParamItem, SystemParamState, SystemState,
|
||||
ReadOnlySystemParam, ResState, SystemMeta, SystemParam, SystemParamItem, SystemParamState,
|
||||
SystemState,
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
@ -42,18 +42,18 @@ use std::ops::{Deref, DerefMut};
|
|||
///
|
||||
/// [`RenderStage::Extract`]: crate::RenderStage::Extract
|
||||
/// [Window]: bevy_window::Window
|
||||
pub struct Extract<'w, 's, P: SystemParam + 'static>
|
||||
pub struct Extract<'w, 's, P>
|
||||
where
|
||||
P::Fetch: ReadOnlySystemParamFetch,
|
||||
P: ReadOnlySystemParam + 'static,
|
||||
{
|
||||
item: <P::Fetch as SystemParamFetch<'w, 's>>::Item,
|
||||
item: SystemParamItem<'w, 's, P>,
|
||||
}
|
||||
|
||||
impl<'w, 's, P: SystemParam> SystemParam for Extract<'w, 's, P>
|
||||
impl<'w, 's, P> SystemParam for Extract<'w, 's, P>
|
||||
where
|
||||
P::Fetch: ReadOnlySystemParamFetch,
|
||||
P: ReadOnlySystemParam,
|
||||
{
|
||||
type Fetch = ExtractState<P>;
|
||||
type State = ExtractState<P>;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -64,7 +64,12 @@ pub struct ExtractState<P: SystemParam + 'static> {
|
|||
|
||||
// SAFETY: only accesses MainWorld resource with read only system params using ResState,
|
||||
// which is initialized in init()
|
||||
unsafe impl<P: SystemParam + 'static> SystemParamState for ExtractState<P> {
|
||||
unsafe impl<P: SystemParam + 'static> SystemParamState for ExtractState<P>
|
||||
where
|
||||
P: ReadOnlySystemParam + 'static,
|
||||
{
|
||||
type Item<'w, 's> = Extract<'w, 's, P>;
|
||||
|
||||
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
|
||||
let mut main_world = world.resource_mut::<MainWorld>();
|
||||
Self {
|
||||
|
@ -72,20 +77,13 @@ unsafe impl<P: SystemParam + 'static> SystemParamState for ExtractState<P> {
|
|||
main_world_state: ResState::init(world, system_meta),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w, 's, P: SystemParam + 'static> SystemParamFetch<'w, 's> for ExtractState<P>
|
||||
where
|
||||
P::Fetch: ReadOnlySystemParamFetch,
|
||||
{
|
||||
type Item = Extract<'w, 's, P>;
|
||||
|
||||
unsafe fn get_param(
|
||||
unsafe fn get_param<'w, 's>(
|
||||
state: &'s mut Self,
|
||||
system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
change_tick: u32,
|
||||
) -> Self::Item {
|
||||
) -> Self::Item<'w, 's> {
|
||||
let main_world = ResState::<MainWorld>::get_param(
|
||||
&mut state.main_world_state,
|
||||
system_meta,
|
||||
|
@ -99,9 +97,9 @@ where
|
|||
|
||||
impl<'w, 's, P: SystemParam> Deref for Extract<'w, 's, P>
|
||||
where
|
||||
P::Fetch: ReadOnlySystemParamFetch,
|
||||
P: ReadOnlySystemParam,
|
||||
{
|
||||
type Target = <P::Fetch as SystemParamFetch<'w, 's>>::Item;
|
||||
type Target = SystemParamItem<'w, 's, P>;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
@ -111,7 +109,7 @@ where
|
|||
|
||||
impl<'w, 's, P: SystemParam> DerefMut for Extract<'w, 's, P>
|
||||
where
|
||||
P::Fetch: ReadOnlySystemParamFetch,
|
||||
P: ReadOnlySystemParam,
|
||||
{
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
|
@ -121,7 +119,7 @@ where
|
|||
|
||||
impl<'a, 'w, 's, P: SystemParam> IntoIterator for &'a Extract<'w, 's, P>
|
||||
where
|
||||
P::Fetch: ReadOnlySystemParamFetch,
|
||||
P: ReadOnlySystemParam,
|
||||
&'a SystemParamItem<'w, 's, P>: IntoIterator,
|
||||
{
|
||||
type Item = <&'a SystemParamItem<'w, 's, P> as IntoIterator>::Item;
|
||||
|
|
|
@ -7,7 +7,7 @@ use bevy_ecs::{
|
|||
all_tuples,
|
||||
entity::Entity,
|
||||
system::{
|
||||
lifetimeless::SRes, ReadOnlySystemParamFetch, Resource, SystemParam, SystemParamItem,
|
||||
lifetimeless::SRes, ReadOnlySystemParam, Resource, SystemParam, SystemParamItem,
|
||||
SystemState,
|
||||
},
|
||||
world::World,
|
||||
|
@ -325,7 +325,7 @@ impl<P: PhaseItem, C: RenderCommand<P>> RenderCommandState<P, C> {
|
|||
|
||||
impl<P: PhaseItem, C: RenderCommand<P> + Send + Sync + 'static> Draw<P> for RenderCommandState<P, C>
|
||||
where
|
||||
<C::Param as SystemParam>::Fetch: ReadOnlySystemParamFetch,
|
||||
C::Param: ReadOnlySystemParam,
|
||||
{
|
||||
/// Prepares the ECS parameters for the wrapped [`RenderCommand`] and then renders it.
|
||||
fn draw<'w>(
|
||||
|
@ -348,7 +348,7 @@ pub trait AddRenderCommand {
|
|||
&mut self,
|
||||
) -> &mut Self
|
||||
where
|
||||
<C::Param as SystemParam>::Fetch: ReadOnlySystemParamFetch;
|
||||
C::Param: ReadOnlySystemParam;
|
||||
}
|
||||
|
||||
impl AddRenderCommand for App {
|
||||
|
@ -356,7 +356,7 @@ impl AddRenderCommand for App {
|
|||
&mut self,
|
||||
) -> &mut Self
|
||||
where
|
||||
<C::Param as SystemParam>::Fetch: ReadOnlySystemParamFetch,
|
||||
C::Param: ReadOnlySystemParam,
|
||||
{
|
||||
let draw_function = RenderCommandState::<P, C>::new(&mut self.world);
|
||||
let draw_functions = self
|
||||
|
|
Loading…
Reference in a new issue