From 7f639e212ace1299372e5250317fa9df43545861 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 18:39:09 -0500
Subject: [PATCH 01/16] implement `Command` for `FunctionSystem`
---
crates/bevy_ecs/src/system/commands/mod.rs | 4 +++-
crates/bevy_ecs/src/system/function_system.rs | 18 +++++++++++++++++-
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs
index ed2d469b9b2f5..fd8031d53f695 100644
--- a/crates/bevy_ecs/src/system/commands/mod.rs
+++ b/crates/bevy_ecs/src/system/commands/mod.rs
@@ -11,7 +11,7 @@ pub use command_queue::CommandQueue;
pub use parallel_scope::*;
use std::marker::PhantomData;
-use super::Resource;
+use super::{Resource, SystemParam};
/// A [`World`] mutation.
///
@@ -44,6 +44,8 @@ pub trait Command: Send + 'static {
fn write(self, world: &mut World);
}
+pub trait CommandParam: SystemParam {}
+
/// A [`Command`] queue to perform impactful changes to the [`World`].
///
/// Since each command requires exclusive access to the `World`,
diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs
index 7ec7c24489380..b78ab2dfc2cf3 100644
--- a/crates/bevy_ecs/src/system/function_system.rs
+++ b/crates/bevy_ecs/src/system/function_system.rs
@@ -5,7 +5,10 @@ use crate::{
prelude::FromWorld,
query::{Access, FilteredAccessSet},
schedule::{SystemLabel, SystemLabelId},
- system::{check_system_change_tick, ReadOnlySystemParam, System, SystemParam, SystemParamItem},
+ system::{
+ check_system_change_tick, Command, CommandParam, ReadOnlySystemParam, System, SystemParam,
+ SystemParamItem,
+ },
world::{World, WorldId},
};
use bevy_ecs_macros::all_tuples;
@@ -458,6 +461,19 @@ where
}
}
+impl Command for FunctionSystem<(), (), Param, Marker, F>
+where
+ Param: CommandParam + 'static,
+ Marker: 'static,
+ F: SystemParamFunction<(), (), Param, Marker> + Send + Sync + 'static,
+{
+ fn write(mut self, world: &mut World) {
+ self.initialize(world);
+ self.run((), world);
+ self.apply_buffers(world);
+ }
+}
+
/// A [`SystemLabel`] that was automatically generated for a system on the basis of its `TypeId`.
pub struct SystemTypeIdLabel(pub(crate) PhantomData T>);
From 1205dfa1631d01cb296466ce197fc236515f7d00 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 18:57:40 -0500
Subject: [PATCH 02/16] add the `IntoCommand` trait
---
crates/bevy_ecs/src/system/commands/mod.rs | 30 +++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs
index fd8031d53f695..55fdc21ae21c6 100644
--- a/crates/bevy_ecs/src/system/commands/mod.rs
+++ b/crates/bevy_ecs/src/system/commands/mod.rs
@@ -11,7 +11,7 @@ pub use command_queue::CommandQueue;
pub use parallel_scope::*;
use std::marker::PhantomData;
-use super::{Resource, SystemParam};
+use super::{IntoSystem, Resource, SystemParam};
/// A [`World`] mutation.
///
@@ -46,6 +46,30 @@ pub trait Command: Send + 'static {
pub trait CommandParam: SystemParam {}
+pub trait IntoCommand {
+ type Command: Command;
+ fn into_command(self) -> Self::Command;
+}
+
+impl IntoCommand<()> for T {
+ type Command = Self;
+ fn into_command(self) -> Self::Command {
+ self
+ }
+}
+
+pub struct IsSystemCommand;
+
+impl> IntoCommand<(IsSystemCommand, Marker)> for T
+where
+ T::System: Command,
+{
+ type Command = T::System;
+ fn into_command(self) -> Self::Command {
+ IntoSystem::into_system(self)
+ }
+}
+
/// A [`Command`] queue to perform impactful changes to the [`World`].
///
/// Since each command requires exclusive access to the `World`,
@@ -524,8 +548,8 @@ impl<'w, 's> Commands<'w, 's> {
/// # bevy_ecs::system::assert_is_system(add_three_to_counter_system);
/// # bevy_ecs::system::assert_is_system(add_twenty_five_to_counter_system);
/// ```
- pub fn add(&mut self, command: C) {
- self.queue.push(command);
+ pub fn add>(&mut self, command: C) {
+ self.queue.push(command.into_command());
}
}
From 922bfb77be94acc0af617722eec57c21c9512273 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 19:31:46 -0500
Subject: [PATCH 03/16] implement `CommandParam` for types
---
crates/bevy_ecs/macros/src/lib.rs | 3 ++
crates/bevy_ecs/src/system/system_param.rs | 35 +++++++++++++++++++++-
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs
index 3d8a10b3af68e..3959474ccb65c 100644
--- a/crates/bevy_ecs/macros/src/lib.rs
+++ b/crates/bevy_ecs/macros/src/lib.rs
@@ -304,6 +304,9 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
}
}
+ impl<'_w, '_s, #(#param: CommandParam,)*> CommandParam for ParamSet<'_w, '_s, (#(#param,)*)>
+ {}
+
impl<'w, 's, #(#param: SystemParam,)*> ParamSet<'w, 's, (#(#param,)*)>
{
#(#param_fn_mut)*
diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs
index e08326f8868a7..ffe8ffdc7e718 100644
--- a/crates/bevy_ecs/src/system/system_param.rs
+++ b/crates/bevy_ecs/src/system/system_param.rs
@@ -8,7 +8,7 @@ use crate::{
query::{
Access, FilteredAccess, FilteredAccessSet, QueryState, ReadOnlyWorldQuery, WorldQuery,
},
- system::{CommandQueue, Commands, Query, SystemMeta},
+ system::{CommandParam, CommandQueue, Commands, Query, SystemMeta},
world::{FromWorld, World},
};
pub use bevy_ecs_macros::Resource;
@@ -233,6 +233,11 @@ unsafe impl SystemPara
}
}
+impl CommandParam
+ for Query<'_, '_, Q, F>
+{
+}
+
fn assert_component_access_compatibility(
system_name: &str,
query_type: &'static str,
@@ -463,6 +468,8 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
}
}
+impl CommandParam for Res<'_, T> {}
+
// SAFETY: Only reads a single World resource
unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {}
@@ -496,6 +503,8 @@ unsafe impl<'a, T: Resource> SystemParam for Option> {
}
}
+impl CommandParam for Option> {}
+
// SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res
// conflicts with any prior access, a panic will occur.
unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
@@ -556,6 +565,8 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
}
}
+impl CommandParam for ResMut<'_, T> {}
+
// SAFETY: this impl defers to `ResMut`, which initializes and validates the correct world access.
unsafe impl<'a, T: Resource> SystemParam for Option> {
type State = ComponentId;
@@ -586,6 +597,8 @@ unsafe impl<'a, T: Resource> SystemParam for Option> {
}
}
+impl CommandParam for Option> {}
+
// SAFETY: Commands only accesses internal state
unsafe impl<'w, 's> ReadOnlySystemParam for Commands<'w, 's> {}
@@ -659,6 +672,8 @@ unsafe impl SystemParam for &'_ World {
}
}
+impl CommandParam for &World {}
+
/// A system local [`SystemParam`].
///
/// A local may only be accessed by the system itself and is therefore not visible to other systems.
@@ -985,6 +1000,8 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
}
}
+impl CommandParam for NonSend<'_, T> {}
+
// SAFETY: this impl defers to `NonSend`, which initializes and validates the correct world access.
unsafe impl SystemParam for Option> {
type State = ComponentId;
@@ -1012,6 +1029,8 @@ unsafe impl SystemParam for Option> {
}
}
+impl CommandParam for Option> {}
+
// SAFETY: Only reads a single non-send resource
unsafe impl<'a, T: 'static> ReadOnlySystemParam for NonSendMut<'a, T> {}
@@ -1072,6 +1091,8 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
}
}
+impl CommandParam for NonSendMut<'_, T> {}
+
// SAFETY: this impl defers to `NonSendMut`, which initializes and validates the correct world access.
unsafe impl<'a, T: 'static> SystemParam for Option> {
type State = ComponentId;
@@ -1097,6 +1118,8 @@ unsafe impl<'a, T: 'static> SystemParam for Option> {
}
}
+impl CommandParam for Option> {}
+
// SAFETY: Only reads World archetypes
unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}
@@ -1118,6 +1141,8 @@ unsafe impl<'a> SystemParam for &'a Archetypes {
}
}
+impl CommandParam for &Archetypes {}
+
// SAFETY: Only reads World components
unsafe impl<'a> ReadOnlySystemParam for &'a Components {}
@@ -1139,6 +1164,8 @@ unsafe impl<'a> SystemParam for &'a Components {
}
}
+impl CommandParam for &Components {}
+
// SAFETY: Only reads World entities
unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}
@@ -1159,6 +1186,7 @@ unsafe impl<'a> SystemParam for &'a Entities {
world.entities()
}
}
+impl CommandParam for &Entities {}
// SAFETY: Only reads World bundles
unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}
@@ -1181,6 +1209,8 @@ unsafe impl<'a> SystemParam for &'a Bundles {
}
}
+impl CommandParam for &Bundles {}
+
/// A [`SystemParam`] that reads the previous and current change ticks of the system.
///
/// A system's change ticks are updated each time it runs:
@@ -1344,6 +1374,9 @@ macro_rules! impl_system_param_tuple {
($($param::get_param($param, _system_meta, _world, _change_tick),)*)
}
}
+
+ #[allow(non_snake_case)]
+ impl<$($param: CommandParam),*> CommandParam for ($($param,)*) {}
};
}
From 535267229fd71259223b2053f8a6d094d73628ae Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 19:37:31 -0500
Subject: [PATCH 04/16] implement `CommandParam` for derived types
---
crates/bevy_ecs/macros/src/lib.rs | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs
index 3959474ccb65c..7cd09804370b6 100644
--- a/crates/bevy_ecs/macros/src/lib.rs
+++ b/crates/bevy_ecs/macros/src/lib.rs
@@ -459,6 +459,16 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
.push(syn::parse_quote!(#field_type: #path::system::ReadOnlySystemParam));
}
+ // Create a where clause for the `CommandParam` impl.
+ // Ensure that each field implements `CommandParam`.
+ let mut command_param_generics = generics.clone();
+ let command_param_where_clause = command_param_generics.make_where_clause();
+ for field_type in &field_types {
+ command_param_where_clause
+ .predicates
+ .push(syn::parse_quote!(#field_type: #path::system::CommandParam));
+ }
+
let struct_name = &ast.ident;
let state_struct_visibility = &ast.vis;
@@ -514,6 +524,8 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
// 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 {}
+
+ impl<'w, 's, #punctuated_generics> #path::system::CommandParam for #struct_name #ty_generics #command_param_where_clause {}
};
})
}
From 04ea33f186ceabb1f09646a6d84e6a03e2d160d2 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 19:38:54 -0500
Subject: [PATCH 05/16] add a test case for system commands
---
crates/bevy_ecs/src/system/commands/mod.rs | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs
index 55fdc21ae21c6..2c04ae9214a8d 100644
--- a/crates/bevy_ecs/src/system/commands/mod.rs
+++ b/crates/bevy_ecs/src/system/commands/mod.rs
@@ -1018,6 +1018,7 @@ mod tests {
use crate::{
self as bevy_ecs,
component::Component,
+ event::{EventWriter, Events},
system::{CommandQueue, Commands, Resource},
world::World,
};
@@ -1172,4 +1173,23 @@ mod tests {
assert!(!world.contains_resource::>());
assert!(world.contains_resource::>());
}
+
+ #[test]
+ fn system_commands() {
+ struct E;
+
+ let mut world = World::new();
+ world.init_resource::>();
+
+ let mut command_queue = CommandQueue::default();
+
+ let mut commands = Commands::new(&mut command_queue, &world);
+ commands.add(|mut events: EventWriter| {
+ events.send(E);
+ });
+
+ command_queue.apply(&mut world);
+
+ assert!(!world.resource::>().is_empty());
+ }
}
From 1f70a83e1332c249ecb1cfadc5c9d8af99f863f0 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 20:15:18 -0500
Subject: [PATCH 06/16] add a module for system commands
---
crates/bevy_ecs/src/system/commands/mod.rs | 15 ++-------------
.../src/system/commands/system_command.rs | 15 +++++++++++++++
2 files changed, 17 insertions(+), 13 deletions(-)
create mode 100644 crates/bevy_ecs/src/system/commands/system_command.rs
diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs
index 2c04ae9214a8d..b56d61d27257d 100644
--- a/crates/bevy_ecs/src/system/commands/mod.rs
+++ b/crates/bevy_ecs/src/system/commands/mod.rs
@@ -1,5 +1,6 @@
mod command_queue;
mod parallel_scope;
+mod system_command;
use crate::{
bundle::Bundle,
@@ -11,7 +12,7 @@ pub use command_queue::CommandQueue;
pub use parallel_scope::*;
use std::marker::PhantomData;
-use super::{IntoSystem, Resource, SystemParam};
+use super::{Resource, SystemParam};
/// A [`World`] mutation.
///
@@ -58,18 +59,6 @@ impl IntoCommand<()> for T {
}
}
-pub struct IsSystemCommand;
-
-impl> IntoCommand<(IsSystemCommand, Marker)> for T
-where
- T::System: Command,
-{
- type Command = T::System;
- fn into_command(self) -> Self::Command {
- IntoSystem::into_system(self)
- }
-}
-
/// A [`Command`] queue to perform impactful changes to the [`World`].
///
/// Since each command requires exclusive access to the `World`,
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
new file mode 100644
index 0000000000000..b302f8e304068
--- /dev/null
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -0,0 +1,15 @@
+use crate::system::IntoSystem;
+
+use super::{Command, IntoCommand};
+
+pub struct IsSystemCommand;
+
+impl> IntoCommand<(IsSystemCommand, Marker)> for T
+where
+ T::System: Command,
+{
+ type Command = T::System;
+ fn into_command(self) -> Self::Command {
+ IntoSystem::into_system(self)
+ }
+}
From 290080eec56669c75d817a68a2ea971e50a2753f Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 20:15:29 -0500
Subject: [PATCH 07/16] hide a marker struct
---
crates/bevy_ecs/src/system/commands/system_command.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
index b302f8e304068..ac585f23fcebf 100644
--- a/crates/bevy_ecs/src/system/commands/system_command.rs
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -2,6 +2,7 @@ use crate::system::IntoSystem;
use super::{Command, IntoCommand};
+#[doc(hidden)]
pub struct IsSystemCommand;
impl> IntoCommand<(IsSystemCommand, Marker)> for T
From ee58a907a33d4201bebad3e2ccc870ab5d2721d3 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 20:17:02 -0500
Subject: [PATCH 08/16] move `CommandParam` into the new module
---
crates/bevy_ecs/src/system/commands/mod.rs | 5 ++---
crates/bevy_ecs/src/system/commands/system_command.rs | 4 +++-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs
index b56d61d27257d..637a340121cb0 100644
--- a/crates/bevy_ecs/src/system/commands/mod.rs
+++ b/crates/bevy_ecs/src/system/commands/mod.rs
@@ -11,8 +11,9 @@ use bevy_utils::tracing::{error, info};
pub use command_queue::CommandQueue;
pub use parallel_scope::*;
use std::marker::PhantomData;
+pub use system_command::CommandParam;
-use super::{Resource, SystemParam};
+use super::Resource;
/// A [`World`] mutation.
///
@@ -45,8 +46,6 @@ pub trait Command: Send + 'static {
fn write(self, world: &mut World);
}
-pub trait CommandParam: SystemParam {}
-
pub trait IntoCommand {
type Command: Command;
fn into_command(self) -> Self::Command;
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
index ac585f23fcebf..82048fb815701 100644
--- a/crates/bevy_ecs/src/system/commands/system_command.rs
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -1,10 +1,12 @@
-use crate::system::IntoSystem;
+use crate::system::{IntoSystem, SystemParam};
use super::{Command, IntoCommand};
#[doc(hidden)]
pub struct IsSystemCommand;
+pub trait CommandParam: SystemParam {}
+
impl> IntoCommand<(IsSystemCommand, Marker)> for T
where
T::System: Command,
From 69c148c3d08310a6609235ffe375fee5d116481f Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 20:39:36 -0500
Subject: [PATCH 09/16] turn a method into an associated fn
---
crates/bevy_ecs/src/system/commands/mod.rs | 8 ++++----
crates/bevy_ecs/src/system/commands/system_command.rs | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs
index 637a340121cb0..e17de22bcc902 100644
--- a/crates/bevy_ecs/src/system/commands/mod.rs
+++ b/crates/bevy_ecs/src/system/commands/mod.rs
@@ -48,13 +48,13 @@ pub trait Command: Send + 'static {
pub trait IntoCommand {
type Command: Command;
- fn into_command(self) -> Self::Command;
+ fn into_command(this: Self) -> Self::Command;
}
impl IntoCommand<()> for T {
type Command = Self;
- fn into_command(self) -> Self::Command {
- self
+ fn into_command(this: Self) -> Self::Command {
+ this
}
}
@@ -537,7 +537,7 @@ impl<'w, 's> Commands<'w, 's> {
/// # bevy_ecs::system::assert_is_system(add_twenty_five_to_counter_system);
/// ```
pub fn add>(&mut self, command: C) {
- self.queue.push(command.into_command());
+ self.queue.push(IntoCommand::into_command(command));
}
}
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
index 82048fb815701..5d33b1ed6c6f1 100644
--- a/crates/bevy_ecs/src/system/commands/system_command.rs
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -12,7 +12,7 @@ where
T::System: Command,
{
type Command = T::System;
- fn into_command(self) -> Self::Command {
- IntoSystem::into_system(self)
+ fn into_command(this: Self) -> Self::Command {
+ IntoSystem::into_system(this)
}
}
From 5b72c8601fdde32d0cf6215949c13c9611960ed1 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 20:40:09 -0500
Subject: [PATCH 10/16] replace `FunctionSystem` with a type specialized for
commands
---
.../src/system/commands/system_command.rs | 57 +++++++++++++++++--
crates/bevy_ecs/src/system/function_system.rs | 18 +-----
2 files changed, 54 insertions(+), 21 deletions(-)
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
index 5d33b1ed6c6f1..cac4ffb7e4bdd 100644
--- a/crates/bevy_ecs/src/system/commands/system_command.rs
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -1,9 +1,11 @@
-use crate::system::{IntoSystem, SystemParam};
+use std::marker::PhantomData;
-use super::{Command, IntoCommand};
+use crate::{
+ prelude::World,
+ system::{IntoSystem, SystemMeta, SystemParam, SystemParamFunction},
+};
-#[doc(hidden)]
-pub struct IsSystemCommand;
+use super::{Command, IntoCommand};
pub trait CommandParam: SystemParam {}
@@ -16,3 +18,50 @@ where
IntoSystem::into_system(this)
}
}
+
+#[doc(hidden)]
+pub struct IsSystemCommand;
+
+pub struct SystemCommand
+where
+ Param: CommandParam,
+{
+ func: F,
+ system_meta: SystemMeta,
+ // NOTE: PhantomData T> gives this safe Send/Sync impls
+ marker: PhantomData (Param, Marker)>,
+}
+
+impl IntoCommand<(IsSystemCommand, Param, Marker)> for F
+where
+ Param: CommandParam + 'static,
+ Marker: 'static,
+ F: SystemParamFunction<(), (), Param, Marker> + Send + Sync + 'static,
+{
+ type Command = SystemCommand;
+ fn into_command(func: Self) -> Self::Command {
+ SystemCommand {
+ func,
+ system_meta: SystemMeta::new::(),
+ marker: PhantomData,
+ }
+ }
+}
+
+impl Command for SystemCommand
+where
+ Param: CommandParam + 'static,
+ Marker: 'static,
+ F: SystemParamFunction<(), (), Param, Marker> + Send + Sync + 'static,
+{
+ fn write(mut self, world: &mut World) {
+ let change_tick = world.change_tick();
+
+ let mut param_state = Param::init_state(world, &mut self.system_meta);
+ let params =
+ // SAFETY: We have exclusive world access.
+ unsafe { Param::get_param(&mut param_state, &self.system_meta, world, change_tick) };
+ self.func.run((), params);
+ Param::apply(&mut param_state, &self.system_meta, world);
+ }
+}
diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs
index b78ab2dfc2cf3..7ec7c24489380 100644
--- a/crates/bevy_ecs/src/system/function_system.rs
+++ b/crates/bevy_ecs/src/system/function_system.rs
@@ -5,10 +5,7 @@ use crate::{
prelude::FromWorld,
query::{Access, FilteredAccessSet},
schedule::{SystemLabel, SystemLabelId},
- system::{
- check_system_change_tick, Command, CommandParam, ReadOnlySystemParam, System, SystemParam,
- SystemParamItem,
- },
+ system::{check_system_change_tick, ReadOnlySystemParam, System, SystemParam, SystemParamItem},
world::{World, WorldId},
};
use bevy_ecs_macros::all_tuples;
@@ -461,19 +458,6 @@ where
}
}
-impl Command for FunctionSystem<(), (), Param, Marker, F>
-where
- Param: CommandParam + 'static,
- Marker: 'static,
- F: SystemParamFunction<(), (), Param, Marker> + Send + Sync + 'static,
-{
- fn write(mut self, world: &mut World) {
- self.initialize(world);
- self.run((), world);
- self.apply_buffers(world);
- }
-}
-
/// A [`SystemLabel`] that was automatically generated for a system on the basis of its `TypeId`.
pub struct SystemTypeIdLabel(pub(crate) PhantomData T>);
From 2f524769180e521bdd7cd172842a5b92c32a54ef Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 20:44:40 -0500
Subject: [PATCH 11/16] fix variance for a marker
---
crates/bevy_ecs/src/system/commands/system_command.rs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
index cac4ffb7e4bdd..1451ea7919832 100644
--- a/crates/bevy_ecs/src/system/commands/system_command.rs
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -28,8 +28,7 @@ where
{
func: F,
system_meta: SystemMeta,
- // NOTE: PhantomData T> gives this safe Send/Sync impls
- marker: PhantomData (Param, Marker)>,
+ marker: PhantomData Marker>,
}
impl IntoCommand<(IsSystemCommand, Param, Marker)> for F
From 927595a55e5548c5cd9a707706005304eedf5b89 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 21:29:22 -0500
Subject: [PATCH 12/16] don't implement `CommandParam` for `NonSend*`
---
crates/bevy_ecs/src/system/system_param.rs | 8 --------
1 file changed, 8 deletions(-)
diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs
index ef52fb7a6a559..b29a822400f7e 100644
--- a/crates/bevy_ecs/src/system/system_param.rs
+++ b/crates/bevy_ecs/src/system/system_param.rs
@@ -1000,8 +1000,6 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
}
}
-impl CommandParam for NonSend<'_, T> {}
-
// SAFETY: this impl defers to `NonSend`, which initializes and validates the correct world access.
unsafe impl SystemParam for Option> {
type State = ComponentId;
@@ -1029,8 +1027,6 @@ unsafe impl SystemParam for Option> {
}
}
-impl CommandParam for Option> {}
-
// SAFETY: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this
// NonSendMut conflicts with any prior access, a panic will occur.
unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
@@ -1088,8 +1084,6 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
}
}
-impl CommandParam for NonSendMut<'_, T> {}
-
// SAFETY: this impl defers to `NonSendMut`, which initializes and validates the correct world access.
unsafe impl<'a, T: 'static> SystemParam for Option> {
type State = ComponentId;
@@ -1115,8 +1109,6 @@ unsafe impl<'a, T: 'static> SystemParam for Option> {
}
}
-impl CommandParam for Option> {}
-
// SAFETY: Only reads World archetypes
unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}
From e2fada4829966f08ca9ae8c942dd8dbc12071d40 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 21:37:31 -0500
Subject: [PATCH 13/16] add a line break
---
crates/bevy_ecs/src/system/system_param.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs
index b29a822400f7e..fbc29db9ede6b 100644
--- a/crates/bevy_ecs/src/system/system_param.rs
+++ b/crates/bevy_ecs/src/system/system_param.rs
@@ -1175,6 +1175,7 @@ unsafe impl<'a> SystemParam for &'a Entities {
world.entities()
}
}
+
impl CommandParam for &Entities {}
// SAFETY: Only reads World bundles
From 2aa8501224b150477d8b74b8f8cad341db48a819 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 21:47:26 -0500
Subject: [PATCH 14/16] `CommandParam` -> `CommandSystemParam`
---
crates/bevy_ecs/macros/src/lib.rs | 10 ++++----
crates/bevy_ecs/src/system/commands/mod.rs | 2 +-
.../src/system/commands/system_command.rs | 8 +++----
crates/bevy_ecs/src/system/system_param.rs | 24 +++++++++----------
4 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs
index f6011a119be98..c97d440e1de1c 100644
--- a/crates/bevy_ecs/macros/src/lib.rs
+++ b/crates/bevy_ecs/macros/src/lib.rs
@@ -306,7 +306,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
}
}
- impl<'_w, '_s, #(#param: CommandParam,)*> CommandParam for ParamSet<'_w, '_s, (#(#param,)*)>
+ impl<'_w, '_s, #(#param: CommandSystemParam,)*> CommandSystemParam for ParamSet<'_w, '_s, (#(#param,)*)>
{}
impl<'w, 's, #(#param: SystemParam,)*> ParamSet<'w, 's, (#(#param,)*)>
@@ -461,14 +461,14 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
.push(syn::parse_quote!(#field_type: #path::system::ReadOnlySystemParam));
}
- // Create a where clause for the `CommandParam` impl.
- // Ensure that each field implements `CommandParam`.
+ // Create a where clause for the `CommandSystemParam` impl.
+ // Ensure that each field implements `CommandSystemParam`.
let mut command_param_generics = generics.clone();
let command_param_where_clause = command_param_generics.make_where_clause();
for field_type in &field_types {
command_param_where_clause
.predicates
- .push(syn::parse_quote!(#field_type: #path::system::CommandParam));
+ .push(syn::parse_quote!(#field_type: #path::system::CommandSystemParam));
}
let struct_name = &ast.ident;
@@ -527,7 +527,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
// 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 {}
- impl<'w, 's, #punctuated_generics> #path::system::CommandParam for #struct_name #ty_generics #command_param_where_clause {}
+ impl<'w, 's, #punctuated_generics> #path::system::CommandSystemParam for #struct_name #ty_generics #command_param_where_clause {}
};
})
}
diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs
index e17de22bcc902..2e8b1d6033601 100644
--- a/crates/bevy_ecs/src/system/commands/mod.rs
+++ b/crates/bevy_ecs/src/system/commands/mod.rs
@@ -11,7 +11,7 @@ use bevy_utils::tracing::{error, info};
pub use command_queue::CommandQueue;
pub use parallel_scope::*;
use std::marker::PhantomData;
-pub use system_command::CommandParam;
+pub use system_command::CommandSystemParam;
use super::Resource;
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
index 1451ea7919832..2b2b2c0a25a7a 100644
--- a/crates/bevy_ecs/src/system/commands/system_command.rs
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -7,7 +7,7 @@ use crate::{
use super::{Command, IntoCommand};
-pub trait CommandParam: SystemParam {}
+pub trait CommandSystemParam: SystemParam {}
impl> IntoCommand<(IsSystemCommand, Marker)> for T
where
@@ -24,7 +24,7 @@ pub struct IsSystemCommand;
pub struct SystemCommand
where
- Param: CommandParam,
+ Param: CommandSystemParam,
{
func: F,
system_meta: SystemMeta,
@@ -33,7 +33,7 @@ where
impl IntoCommand<(IsSystemCommand, Param, Marker)> for F
where
- Param: CommandParam + 'static,
+ Param: CommandSystemParam + 'static,
Marker: 'static,
F: SystemParamFunction<(), (), Param, Marker> + Send + Sync + 'static,
{
@@ -49,7 +49,7 @@ where
impl Command for SystemCommand
where
- Param: CommandParam + 'static,
+ Param: CommandSystemParam + 'static,
Marker: 'static,
F: SystemParamFunction<(), (), Param, Marker> + Send + Sync + 'static,
{
diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs
index fbc29db9ede6b..2c4caecd5d552 100644
--- a/crates/bevy_ecs/src/system/system_param.rs
+++ b/crates/bevy_ecs/src/system/system_param.rs
@@ -8,7 +8,7 @@ use crate::{
query::{
Access, FilteredAccess, FilteredAccessSet, QueryState, ReadOnlyWorldQuery, WorldQuery,
},
- system::{CommandParam, CommandQueue, Commands, Query, SystemMeta},
+ system::{CommandQueue, CommandSystemParam, Commands, Query, SystemMeta},
world::{FromWorld, World},
};
pub use bevy_ecs_macros::Resource;
@@ -233,7 +233,7 @@ unsafe impl SystemPara
}
}
-impl CommandParam
+impl CommandSystemParam
for Query<'_, '_, Q, F>
{
}
@@ -468,7 +468,7 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
}
}
-impl CommandParam for Res<'_, T> {}
+impl CommandSystemParam for Res<'_, T> {}
// SAFETY: Only reads a single World resource
unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {}
@@ -503,7 +503,7 @@ unsafe impl<'a, T: Resource> SystemParam for Option> {
}
}
-impl CommandParam for Option> {}
+impl CommandSystemParam for Option> {}
// SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res
// conflicts with any prior access, a panic will occur.
@@ -565,7 +565,7 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
}
}
-impl CommandParam for ResMut<'_, T> {}
+impl CommandSystemParam for ResMut<'_, T> {}
// SAFETY: this impl defers to `ResMut`, which initializes and validates the correct world access.
unsafe impl<'a, T: Resource> SystemParam for Option> {
@@ -597,7 +597,7 @@ unsafe impl<'a, T: Resource> SystemParam for Option> {
}
}
-impl CommandParam for Option> {}
+impl CommandSystemParam for Option> {}
// SAFETY: Commands only accesses internal state
unsafe impl<'w, 's> ReadOnlySystemParam for Commands<'w, 's> {}
@@ -672,7 +672,7 @@ unsafe impl SystemParam for &'_ World {
}
}
-impl CommandParam for &World {}
+impl CommandSystemParam for &World {}
/// A system local [`SystemParam`].
///
@@ -1130,7 +1130,7 @@ unsafe impl<'a> SystemParam for &'a Archetypes {
}
}
-impl CommandParam for &Archetypes {}
+impl CommandSystemParam for &Archetypes {}
// SAFETY: Only reads World components
unsafe impl<'a> ReadOnlySystemParam for &'a Components {}
@@ -1153,7 +1153,7 @@ unsafe impl<'a> SystemParam for &'a Components {
}
}
-impl CommandParam for &Components {}
+impl CommandSystemParam for &Components {}
// SAFETY: Only reads World entities
unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}
@@ -1176,7 +1176,7 @@ unsafe impl<'a> SystemParam for &'a Entities {
}
}
-impl CommandParam for &Entities {}
+impl CommandSystemParam for &Entities {}
// SAFETY: Only reads World bundles
unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}
@@ -1199,7 +1199,7 @@ unsafe impl<'a> SystemParam for &'a Bundles {
}
}
-impl CommandParam for &Bundles {}
+impl CommandSystemParam for &Bundles {}
/// A [`SystemParam`] that reads the previous and current change ticks of the system.
///
@@ -1366,7 +1366,7 @@ macro_rules! impl_system_param_tuple {
}
#[allow(non_snake_case)]
- impl<$($param: CommandParam),*> CommandParam for ($($param,)*) {}
+ impl<$($param: CommandSystemParam),*> CommandSystemParam for ($($param,)*) {}
};
}
From 98d51ac4dac7152b90b789acf6ceadc1aae1a698 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 21:51:21 -0500
Subject: [PATCH 15/16] remove redundant bounds
---
crates/bevy_ecs/src/system/commands/system_command.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
index 2b2b2c0a25a7a..a974ad9e2d427 100644
--- a/crates/bevy_ecs/src/system/commands/system_command.rs
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -35,7 +35,7 @@ impl IntoCommand<(IsSystemCommand, Param, Marker)> for F
where
Param: CommandSystemParam + 'static,
Marker: 'static,
- F: SystemParamFunction<(), (), Param, Marker> + Send + Sync + 'static,
+ F: SystemParamFunction<(), (), Param, Marker>,
{
type Command = SystemCommand;
fn into_command(func: Self) -> Self::Command {
@@ -51,7 +51,7 @@ impl Command for SystemCommand
where
Param: CommandSystemParam + 'static,
Marker: 'static,
- F: SystemParamFunction<(), (), Param, Marker> + Send + Sync + 'static,
+ F: SystemParamFunction<(), (), Param, Marker>,
{
fn write(mut self, world: &mut World) {
let change_tick = world.change_tick();
From 75e524d37a1c5c7ccc6300276acdca915dc40c57 Mon Sep 17 00:00:00 2001
From: JoJoJet <21144246+JoJoJet@users.noreply.github.com>
Date: Mon, 16 Jan 2023 21:56:10 -0500
Subject: [PATCH 16/16] don't store `SystemMeta`
---
crates/bevy_ecs/src/system/commands/system_command.rs | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/crates/bevy_ecs/src/system/commands/system_command.rs b/crates/bevy_ecs/src/system/commands/system_command.rs
index a974ad9e2d427..83ed88cff5bea 100644
--- a/crates/bevy_ecs/src/system/commands/system_command.rs
+++ b/crates/bevy_ecs/src/system/commands/system_command.rs
@@ -27,7 +27,6 @@ where
Param: CommandSystemParam,
{
func: F,
- system_meta: SystemMeta,
marker: PhantomData Marker>,
}
@@ -41,7 +40,6 @@ where
fn into_command(func: Self) -> Self::Command {
SystemCommand {
func,
- system_meta: SystemMeta::new::(),
marker: PhantomData,
}
}
@@ -56,11 +54,12 @@ where
fn write(mut self, world: &mut World) {
let change_tick = world.change_tick();
- let mut param_state = Param::init_state(world, &mut self.system_meta);
+ let mut system_meta = SystemMeta::new::();
+ let mut param_state = Param::init_state(world, &mut system_meta);
let params =
// SAFETY: We have exclusive world access.
- unsafe { Param::get_param(&mut param_state, &self.system_meta, world, change_tick) };
+ unsafe { Param::get_param(&mut param_state, &system_meta, world, change_tick) };
self.func.run((), params);
- Param::apply(&mut param_state, &self.system_meta, world);
+ Param::apply(&mut param_state, &system_meta, world);
}
}