diff --git a/crates/bevy_ecs/src/system/commands.rs b/crates/bevy_ecs/src/system/commands.rs index f4fb77b342fb7..849c7d20bbf0b 100644 --- a/crates/bevy_ecs/src/system/commands.rs +++ b/crates/bevy_ecs/src/system/commands.rs @@ -1,8 +1,7 @@ use super::SystemId; use crate::resource::{Resource, Resources}; use bevy_hecs::{Bundle, Component, DynamicBundle, Entity, EntityReserver, World}; -use parking_lot::Mutex; -use std::{marker::PhantomData, sync::Arc}; +use std::marker::PhantomData; /// A [World] mutation pub trait Command: Send + Sync { diff --git a/crates/bevy_ecs/src/system/into_system.rs b/crates/bevy_ecs/src/system/into_system.rs index c3d9c42739a47..58fddc3fd86d9 100644 --- a/crates/bevy_ecs/src/system/into_system.rs +++ b/crates/bevy_ecs/src/system/into_system.rs @@ -1,8 +1,7 @@ -use crate::{ - Commands, Resources, System, SystemId, SystemParam, ThreadLocalExecution, -}; +use crate::{Commands, Resources, System, SystemId, SystemParam, ThreadLocalExecution}; use bevy_hecs::{ArchetypeComponent, QueryAccess, TypeAccess, World}; -use std::{any::TypeId, borrow::Cow}; +use parking_lot::Mutex; +use std::{any::TypeId, borrow::Cow, sync::Arc}; pub struct SystemState { pub(crate) id: SystemId, @@ -14,6 +13,7 @@ pub struct SystemState { pub(crate) query_accesses: Vec>, pub(crate) query_type_names: Vec<&'static str>, pub(crate) commands: Commands, + pub(crate) arc_commands: Option>>, pub(crate) current_query_index: usize, } @@ -151,6 +151,7 @@ macro_rules! impl_into_system { is_initialized: false, id: SystemId::new(), commands: Commands::default(), + arc_commands: Default::default(), query_archetype_component_accesses: Vec::new(), query_accesses: Vec::new(), query_type_names: Vec::new(), @@ -166,6 +167,10 @@ macro_rules! impl_into_system { }, thread_local_func: |state, world, resources| { state.commands.apply(world, resources); + if let Some(ref commands) = state.arc_commands { + let mut commands = commands.lock(); + commands.apply(world, resources); + } }, init_func: |state, world, resources| { $($param::init(state, world, resources);)* @@ -274,14 +279,12 @@ mod tests { fn or_query_set_system() { // Regression test for issue #762 use crate::{Added, Changed, Mutated, Or}; - let query_system = move | - mut ran: ResMut, - set: QuerySet<( - Query, Changed)>>, - Query, Added)>>, - Query, Mutated)>>, - )>, - | { + let query_system = move |mut ran: ResMut, + set: QuerySet<( + Query, Changed)>>, + Query, Added)>>, + Query, Mutated)>>, + )>| { let changed = set.q0().iter().count(); let added = set.q1().iter().count(); let mutated = set.q2().iter().count(); @@ -334,7 +337,10 @@ mod tests { #[test] fn changed_resource_or_system() { - fn incr_e_on_flip(_or: Or<(Option>, Option>)>, mut query: Query<&mut i32>) { + fn incr_e_on_flip( + _or: Or<(Option>, Option>)>, + mut query: Query<&mut i32>, + ) { for mut i in query.iter_mut() { *i += 1; } @@ -363,7 +369,7 @@ mod tests { schedule.run(&mut world, &mut resources); assert_eq!(*(world.get::(ent).unwrap()), 2); - + *resources.get_mut::().unwrap() = 20; schedule.run(&mut world, &mut resources); assert_eq!(*(world.get::(ent).unwrap()), 3); diff --git a/crates/bevy_ecs/src/system/query/mod.rs b/crates/bevy_ecs/src/system/query/mod.rs index e029ca7418a2a..745b76292d56c 100644 --- a/crates/bevy_ecs/src/system/query/mod.rs +++ b/crates/bevy_ecs/src/system/query/mod.rs @@ -28,7 +28,10 @@ pub enum QueryError { impl<'a, Q: HecsQuery> Query<'a, Q> { #[inline] - pub unsafe fn new(world: &'a World, component_access: &'a TypeAccess) -> Self { + pub unsafe fn new( + world: &'a World, + component_access: &'a TypeAccess, + ) -> Self { Self { world, component_access, diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index c9561f2b038d2..500508eb8319f 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -5,7 +5,8 @@ use crate::{ ResourceIndex, Resources, SystemState, }; use bevy_hecs::{ArchetypeComponent, Fetch, Or, Query as HecsQuery, TypeAccess, World}; -use std::any::TypeId; +use parking_lot::Mutex; +use std::{any::TypeId, sync::Arc}; pub trait SystemParam: Sized { fn init(system_state: &mut SystemState, world: &World, resources: &mut Resources); @@ -88,6 +89,25 @@ impl<'a> SystemParam for &'a mut Commands { } } +impl SystemParam for Arc> { + fn init(system_state: &mut SystemState, world: &World, _resources: &mut Resources) { + system_state.arc_commands.get_or_insert_with(|| { + let mut commands = Commands::default(); + commands.set_entity_reserver(world.get_entity_reserver()); + Arc::new(Mutex::new(commands)) + }); + } + + #[inline] + unsafe fn get_param( + system_state: &mut SystemState, + _world: &World, + _resources: &Resources, + ) -> Option { + Some(system_state.arc_commands.as_ref().unwrap().clone()) + } +} + impl<'a, T: Resource> SystemParam for Res<'a, T> { fn init(system_state: &mut SystemState, _world: &World, _resources: &mut Resources) { system_state.resource_access.add_read(TypeId::of::()); diff --git a/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs index de566101f9289..f577c3806be6d 100644 --- a/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs @@ -10,9 +10,7 @@ use crate::{ }; use bevy_asset::{Asset, Assets, Handle, HandleId}; -use bevy_ecs::{ - Commands, Entity, IntoSystem, Local, Query, Res, ResMut, Resources, System, World, -}; +use bevy_ecs::{Commands, Entity, IntoSystem, Local, Query, Res, ResMut, Resources, System, World}; use bevy_utils::HashMap; use renderer::{AssetRenderResourceBindings, BufferId, RenderResourceType, RenderResources}; use std::{hash::Hash, marker::PhantomData, ops::DerefMut};