From 6218abad17af4335e250477298249e51e4a0ed38 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 29 Jun 2021 21:59:59 -0400 Subject: [PATCH 1/8] Basic implementation of World::run_system --- crates/bevy_ecs/src/world/mod.rs | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 5068fdc4e5074..f04b39bf03b1a 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -18,6 +18,7 @@ use crate::{ }, entity::{Entities, Entity}, query::{FilterFetch, QueryState, WorldQuery}, + schedule::SystemDescriptor, storage::{Column, SparseSet, Storages}, }; use std::{ @@ -917,6 +918,49 @@ impl World { column.check_change_ticks(change_tick); } } + + /// Runs a system in a sequential, blocking fashion on the `World` + /// + /// Use [System::run_unsafe] directly for manual unsafe execution + /// of simultaneous systems in parallel. + /// + /// The `system` parameter here can be any function + /// that could be added as a system to a standard `App`. + /// + /// This system cannot have an input or output; + /// use [World::run_system_chainable] instead + /// if this behavior is desired. + /// + /// #Examples + /// + /// ```rust + /// #[derive(Default)] + /// struct Counter(u8); + /// let mut world = World::new(); + /// + /// fn count_up(mut counter: ResMut){ + /// counter += 1; + /// } + /// + /// world.insert_resource::(Counter(0)); + /// world.run_system(count_up); + /// let counter = world.get_resource::().unwrap(); + /// assert_eq!(counter.0, 1); + /// ``` + pub fn run_system(&mut self, system: impl Into) { + let system_descriptor: SystemDescriptor = system.into(); + + match system_descriptor { + SystemDescriptor::Parallel(par_system_descriptor) => { + let mut boxed_system = par_system_descriptor.system; + boxed_system.run((), self); + } + SystemDescriptor::Exclusive(exc_system_descriptor) => { + let mut boxed_system = exc_system_descriptor.system; + boxed_system.run(self); + } + } + } } impl fmt::Debug for World { From d237781178b66448d5da1f31317384592370187f Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 29 Jun 2021 22:49:35 -0400 Subject: [PATCH 2/8] Basic tests --- crates/bevy_ecs/src/world/mod.rs | 38 ++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index f04b39bf03b1a..2188fc043eb1f 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -934,12 +934,11 @@ impl World { /// #Examples /// /// ```rust - /// #[derive(Default)] /// struct Counter(u8); /// let mut world = World::new(); /// /// fn count_up(mut counter: ResMut){ - /// counter += 1; + /// counter.0 += 1; /// } /// /// world.insert_resource::(Counter(0)); @@ -1010,3 +1009,38 @@ impl Default for MainThreadValidator { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::prelude::*; + + struct Counter(u8); + + fn count_up(mut counter: ResMut) { + counter.0 += 1; + } + + fn count_up_exclusive(world: &mut World) { + let mut counter = world.get_resource_mut::().unwrap(); + counter.0 += 1; + } + + #[test] + fn run_parallel_system_from_world() { + let mut world = World::new(); + world.insert_resource::(Counter(0)); + world.run_system(count_up.system()); + let counter = world.get_resource::().unwrap(); + assert_eq!(counter.0, 1); + } + + #[test] + fn run_exclusive_system_from_world() { + let mut world = World::new(); + world.insert_resource::(Counter(0)); + world.run_system(count_up_exclusive.exclusive_system()); + let counter = world.get_resource::().unwrap(); + assert_eq!(counter.0, 1); + } +} From 51fa4b6d28a29fd51445be9c6543c4c60febec8e Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 29 Jun 2021 23:03:15 -0400 Subject: [PATCH 3/8] Semantically significant typo in docs --- crates/bevy_ecs/src/system/function_system.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 566ef78dbf9c7..f75f7bd6a30b4 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -221,10 +221,10 @@ impl> IntoSystem(pub In); pub struct InputMarker; -/// The [`System`] counter part of an ordinary function. +/// The [`System`] counterpart of an ordinary function. /// /// You get this by calling [`IntoSystem::system`] on a function that only accepts -/// [`SystemParam`]s. The output of the system becomes the functions return type, while the input +/// [`SystemParam`]s. The output of the system becomes the function's return type, while the input /// becomes the functions [`In`] tagged parameter or `()` if no such paramater exists. pub struct FunctionSystem where From b51cc35ceaf442ae3a23df9e566f0fc6d1303f32 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 29 Jun 2021 23:24:55 -0400 Subject: [PATCH 4/8] Correctly use IntoSystemDescriptor, not Into --- crates/bevy_ecs/src/world/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 2188fc043eb1f..2b65b1248227a 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -18,7 +18,7 @@ use crate::{ }, entity::{Entities, Entity}, query::{FilterFetch, QueryState, WorldQuery}, - schedule::SystemDescriptor, + schedule::{IntoSystemDescriptor, SystemDescriptor}, storage::{Column, SparseSet, Storages}, }; use std::{ @@ -946,8 +946,8 @@ impl World { /// let counter = world.get_resource::().unwrap(); /// assert_eq!(counter.0, 1); /// ``` - pub fn run_system(&mut self, system: impl Into) { - let system_descriptor: SystemDescriptor = system.into(); + pub fn run_system(&mut self, system: impl IntoSystemDescriptor) { + let system_descriptor: SystemDescriptor = system.into_descriptor(); match system_descriptor { SystemDescriptor::Parallel(par_system_descriptor) => { From 2e0d8861de7f32e1a4cd96dc3da2422867dd6ecd Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 30 Jun 2021 03:45:04 -0400 Subject: [PATCH 5/8] Run parallel systems on world correctly Credit to @mockersf for teaching me how to do this --- crates/bevy_ecs/src/world/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 2b65b1248227a..6edf28a23de1f 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -952,7 +952,10 @@ impl World { match system_descriptor { SystemDescriptor::Parallel(par_system_descriptor) => { let mut boxed_system = par_system_descriptor.system; + boxed_system.initialize(self); boxed_system.run((), self); + // Immediately flushes any Commands or similar buffers created + boxed_system.apply_buffers(self); } SystemDescriptor::Exclusive(exc_system_descriptor) => { let mut boxed_system = exc_system_descriptor.system; From d315994381cf0e0790d79cd88311e8012c20f0a6 Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 30 Jun 2021 03:55:42 -0400 Subject: [PATCH 6/8] Exclusive systems should also be initialized --- crates/bevy_ecs/src/world/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 6edf28a23de1f..d4b08925c7001 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -959,6 +959,7 @@ impl World { } SystemDescriptor::Exclusive(exc_system_descriptor) => { let mut boxed_system = exc_system_descriptor.system; + boxed_system.initialize(self); boxed_system.run(self); } } From f1f459b42296a433d92131efc776cc8078f1027c Mon Sep 17 00:00:00 2001 From: Alice Date: Wed, 30 Jun 2021 04:14:25 -0400 Subject: [PATCH 7/8] Code cleanup --- crates/bevy_ecs/src/world/mod.rs | 60 +++++++++++--------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index d4b08925c7001..6b0d3412dd280 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -927,18 +927,16 @@ impl World { /// The `system` parameter here can be any function /// that could be added as a system to a standard `App`. /// - /// This system cannot have an input or output; - /// use [World::run_system_chainable] instead - /// if this behavior is desired. - /// /// #Examples /// /// ```rust + /// use bevy_ecs::prelude::*; + /// /// struct Counter(u8); /// let mut world = World::new(); /// /// fn count_up(mut counter: ResMut){ - /// counter.0 += 1; + /// counter.0 += 1; /// } /// /// world.insert_resource::(Counter(0)); @@ -946,6 +944,23 @@ impl World { /// let counter = world.get_resource::().unwrap(); /// assert_eq!(counter.0, 1); /// ``` + /// + /// ```rust + /// use bevy_ecs::prelude::*; + /// + /// struct Counter(u8); + /// let mut world = World::new(); + /// + /// fn count_up_exclusive(world: &mut World){ + /// let mut counter = world.get_resource_mut::().unwrap(); + /// counter.0 += 1; + /// } + /// + /// world.insert_resource::(Counter(0)); + /// world.run_system(count_up_exclusive.exclusive_system()); + /// let counter = world.get_resource::().unwrap(); + /// assert_eq!(counter.0, 1); + /// ``` pub fn run_system(&mut self, system: impl IntoSystemDescriptor) { let system_descriptor: SystemDescriptor = system.into_descriptor(); @@ -1013,38 +1028,3 @@ impl Default for MainThreadValidator { } } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::prelude::*; - - struct Counter(u8); - - fn count_up(mut counter: ResMut) { - counter.0 += 1; - } - - fn count_up_exclusive(world: &mut World) { - let mut counter = world.get_resource_mut::().unwrap(); - counter.0 += 1; - } - - #[test] - fn run_parallel_system_from_world() { - let mut world = World::new(); - world.insert_resource::(Counter(0)); - world.run_system(count_up.system()); - let counter = world.get_resource::().unwrap(); - assert_eq!(counter.0, 1); - } - - #[test] - fn run_exclusive_system_from_world() { - let mut world = World::new(); - world.insert_resource::(Counter(0)); - world.run_system(count_up_exclusive.exclusive_system()); - let counter = world.get_resource::().unwrap(); - assert_eq!(counter.0, 1); - } -} From d9335acf3a871a04ea4fd6faa64a3e102e89a62c Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Wed, 30 Jun 2021 18:28:14 -0400 Subject: [PATCH 8/8] Improved doc strings --- crates/bevy_ecs/src/world/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 6b0d3412dd280..a70766ecf8d41 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -919,7 +919,7 @@ impl World { } } - /// Runs a system in a sequential, blocking fashion on the `World` + /// Runs a system in a blocking fashion on the `World` /// /// Use [System::run_unsafe] directly for manual unsafe execution /// of simultaneous systems in parallel. @@ -927,8 +927,9 @@ impl World { /// The `system` parameter here can be any function /// that could be added as a system to a standard `App`. /// - /// #Examples - /// + /// # Examples + /// + /// Here's an example of how to directly run an ordinary parallel system. /// ```rust /// use bevy_ecs::prelude::*; /// @@ -944,7 +945,7 @@ impl World { /// let counter = world.get_resource::().unwrap(); /// assert_eq!(counter.0, 1); /// ``` - /// + /// And here's how you directly run an exclusive system. /// ```rust /// use bevy_ecs::prelude::*; ///