Add &World as SystemParam (#2923)
# Objective Make it possible to use `&World` as a system parameter ## Solution It seems like all the pieces were already in place, very simple impl Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
parent
c216738b33
commit
1f99363de9
@ -186,6 +186,10 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
|
||||
self.with.union_with(&access.with);
|
||||
self.without.union_with(&access.without);
|
||||
}
|
||||
|
||||
pub fn read_all(&mut self) {
|
||||
self.access.read_all();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FilteredAccessSet<T: SparseSetIndex> {
|
||||
|
||||
@ -443,6 +443,35 @@ mod tests {
|
||||
assert_eq!(receive_events(&world), vec![StartedSystems(2),]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn world() {
|
||||
let mut world = World::new();
|
||||
world.spawn().insert(W(0usize));
|
||||
fn wants_world(_: &World) {}
|
||||
fn wants_mut(_: Query<&mut W<usize>>) {}
|
||||
let mut stage = SystemStage::parallel()
|
||||
.with_system(wants_mut)
|
||||
.with_system(wants_mut);
|
||||
stage.run(&mut world);
|
||||
assert_eq!(
|
||||
receive_events(&world),
|
||||
vec![StartedSystems(1), StartedSystems(1),]
|
||||
);
|
||||
let mut stage = SystemStage::parallel()
|
||||
.with_system(wants_mut)
|
||||
.with_system(wants_world);
|
||||
stage.run(&mut world);
|
||||
assert_eq!(
|
||||
receive_events(&world),
|
||||
vec![StartedSystems(1), StartedSystems(1),]
|
||||
);
|
||||
let mut stage = SystemStage::parallel()
|
||||
.with_system(wants_world)
|
||||
.with_system(wants_world);
|
||||
stage.run(&mut world);
|
||||
assert_eq!(receive_events(&world), vec![StartedSystems(2),]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_send_resource() {
|
||||
use std::thread;
|
||||
|
||||
@ -56,6 +56,7 @@
|
||||
//! - [`EventWriter`](crate::event::EventWriter)
|
||||
//! - [`NonSend`] and `Option<NonSend>`
|
||||
//! - [`NonSendMut`] and `Option<NonSendMut>`
|
||||
//! - [`&World`](crate::world::World)
|
||||
//! - [`RemovedComponents`]
|
||||
//! - [`SystemChangeTick`]
|
||||
//! - [`Archetypes`](crate::archetype::Archetypes) (Provides Archetype metadata)
|
||||
|
||||
@ -6,7 +6,8 @@ use crate::{
|
||||
component::{Component, ComponentId, ComponentTicks, Components},
|
||||
entity::{Entities, Entity},
|
||||
query::{
|
||||
FilterFetch, FilteredAccess, FilteredAccessSet, QueryState, ReadOnlyFetch, WorldQuery,
|
||||
Access, FilterFetch, FilteredAccess, FilteredAccessSet, QueryState, ReadOnlyFetch,
|
||||
WorldQuery,
|
||||
},
|
||||
system::{CommandQueue, Commands, Query, SystemMeta},
|
||||
world::{FromWorld, World},
|
||||
@ -532,6 +533,60 @@ impl<'w, 's> SystemParamFetch<'w, 's> for CommandQueue {
|
||||
}
|
||||
}
|
||||
|
||||
/// SAFE: only reads world
|
||||
unsafe impl ReadOnlySystemParamFetch for WorldState {}
|
||||
|
||||
/// The [`SystemParamState`] of [`&World`](crate::world::World).
|
||||
pub struct WorldState;
|
||||
|
||||
impl<'w, 's> SystemParam for &'w World {
|
||||
type Fetch = WorldState;
|
||||
}
|
||||
|
||||
unsafe impl<'w, 's> SystemParamState for WorldState {
|
||||
type Config = ();
|
||||
|
||||
fn init(_world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> 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(&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
|
||||
}
|
||||
|
||||
fn default_config() -> Self::Config {}
|
||||
}
|
||||
|
||||
impl<'w, 's> SystemParamFetch<'w, 's> for WorldState {
|
||||
type Item = &'w World;
|
||||
unsafe fn get_param(
|
||||
_state: &'s mut Self,
|
||||
_system_meta: &SystemMeta,
|
||||
world: &'w World,
|
||||
_change_tick: u32,
|
||||
) -> Self::Item {
|
||||
world
|
||||
}
|
||||
}
|
||||
|
||||
/// A system local [`SystemParam`].
|
||||
///
|
||||
/// A local may only be accessed by the system itself and is therefore not visible to other systems.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user