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.with.union_with(&access.with);
|
||||||
self.without.union_with(&access.without);
|
self.without.union_with(&access.without);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_all(&mut self) {
|
||||||
|
self.access.read_all();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilteredAccessSet<T: SparseSetIndex> {
|
pub struct FilteredAccessSet<T: SparseSetIndex> {
|
||||||
|
|||||||
@ -443,6 +443,35 @@ mod tests {
|
|||||||
assert_eq!(receive_events(&world), vec![StartedSystems(2),]);
|
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]
|
#[test]
|
||||||
fn non_send_resource() {
|
fn non_send_resource() {
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|||||||
@ -56,6 +56,7 @@
|
|||||||
//! - [`EventWriter`](crate::event::EventWriter)
|
//! - [`EventWriter`](crate::event::EventWriter)
|
||||||
//! - [`NonSend`] and `Option<NonSend>`
|
//! - [`NonSend`] and `Option<NonSend>`
|
||||||
//! - [`NonSendMut`] and `Option<NonSendMut>`
|
//! - [`NonSendMut`] and `Option<NonSendMut>`
|
||||||
|
//! - [`&World`](crate::world::World)
|
||||||
//! - [`RemovedComponents`]
|
//! - [`RemovedComponents`]
|
||||||
//! - [`SystemChangeTick`]
|
//! - [`SystemChangeTick`]
|
||||||
//! - [`Archetypes`](crate::archetype::Archetypes) (Provides Archetype metadata)
|
//! - [`Archetypes`](crate::archetype::Archetypes) (Provides Archetype metadata)
|
||||||
|
|||||||
@ -6,7 +6,8 @@ use crate::{
|
|||||||
component::{Component, ComponentId, ComponentTicks, Components},
|
component::{Component, ComponentId, ComponentTicks, Components},
|
||||||
entity::{Entities, Entity},
|
entity::{Entities, Entity},
|
||||||
query::{
|
query::{
|
||||||
FilterFetch, FilteredAccess, FilteredAccessSet, QueryState, ReadOnlyFetch, WorldQuery,
|
Access, FilterFetch, FilteredAccess, FilteredAccessSet, QueryState, ReadOnlyFetch,
|
||||||
|
WorldQuery,
|
||||||
},
|
},
|
||||||
system::{CommandQueue, Commands, Query, SystemMeta},
|
system::{CommandQueue, Commands, Query, SystemMeta},
|
||||||
world::{FromWorld, World},
|
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 system local [`SystemParam`].
|
||||||
///
|
///
|
||||||
/// A local may only be accessed by the system itself and is therefore not visible to other systems.
|
/// 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