From f45bd02223c36e551847e5b3179874c21c77d0e3 Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Wed, 2 Dec 2020 01:40:55 -0800 Subject: [PATCH 1/6] First pass at docs --- crates/bevy_ecs/src/system/commands.rs | 89 +++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/commands.rs b/crates/bevy_ecs/src/system/commands.rs index 397fecdef7b77..a4c2c9d728516 100644 --- a/crates/bevy_ecs/src/system/commands.rs +++ b/crates/bevy_ecs/src/system/commands.rs @@ -181,6 +181,7 @@ impl Command for InsertLocalResource { } } +/// A list of commands that will be run to populate a `World` and `Resources`. #[derive(Default)] pub struct Commands { commands: Vec>, @@ -189,17 +190,50 @@ pub struct Commands { } impl Commands { + /// Creates a new entity and calls `insert` with the it and `components`. + /// + /// Note that `components` is a bundle. If you would like to spawn an entity with a single component, consider wrapping the component in a tuple (which `DynamicBundle` is implemented for). + /// + /// See `set_current_entity`, `insert`. + /// + /// # Example + /// + /// ``` + /// use bevy_ecs::prelude::*; + /// + /// struct Component1; + /// struct Component2; + /// + /// #[derive(Bundle)] + /// struct ExampleBundle { + /// a: Component1, + /// b: Component2, + /// } + /// + /// fn example_system(mut commands: Commands) { + /// // Create a new entity with a component bundle. + /// commands.spawn(ExampleBundle { + /// a: Component1, + /// b: Component2, + /// }); + /// + /// // Create new entities with a single component each. + /// commands.spawn((Component1,)); + /// commands.spawn((Component2,)); + /// } + /// ``` pub fn spawn(&mut self, components: impl DynamicBundle + Send + Sync + 'static) -> &mut Self { let entity = self .entity_reserver .as_ref() .expect("entity reserver has not been set") .reserve_entity(); - self.current_entity = Some(entity); - self.commands.push(Box::new(Insert { entity, components })); + self.set_current_entity(entity); + self.insert(entity, components); self } + /// Equivalent to iterating of `components_iter` and calling `spawn` on each bundle, but slightly more performant. pub fn spawn_batch(&mut self, components_iter: I) -> &mut Self where I: IntoIterator + Send + Sync + 'static, @@ -213,6 +247,9 @@ impl Commands { self.add_command(Despawn { entity }) } + /// Inserts a bundle of components into `entity`. + /// + /// See `World::insert`. pub fn insert( &mut self, entity: Entity, @@ -221,6 +258,9 @@ impl Commands { self.add_command(Insert { entity, components }) } + /// Inserts a single component into `entity`. + /// + /// See `World::insert_one`. pub fn insert_one(&mut self, entity: Entity, component: impl Component) -> &mut Self { self.add_command(InsertOne { entity, component }) } @@ -240,6 +280,7 @@ impl Commands { }) } + /// See `World::remove_one`. pub fn remove_one(&mut self, entity: Entity) -> &mut Self where T: Component, @@ -250,6 +291,7 @@ impl Commands { }) } + /// See `World::remove`. pub fn remove(&mut self, entity: Entity) -> &mut Self where T: Bundle + Send + Sync + 'static, @@ -260,6 +302,9 @@ impl Commands { }) } + /// Adds a bundle of components to the current entity. + /// + /// See `with`, `current_entity`. pub fn with_bundle( &mut self, components: impl DynamicBundle + Send + Sync + 'static, @@ -272,6 +317,42 @@ impl Commands { self } + /// Adds a single component to the current entity. + /// + /// See `with_bundle`, `current_entity`. + /// + /// # Warning + /// + /// It's possible to call this with a bundle, but this is likely not intended and `with_bundle` should be used instead. If `with` is called with a bundle, the bundle itself will be added as a component instead of the bundles' inner components each being added. + /// + /// # Example + /// + /// `with` can be chained with `spawn`. + /// + /// ``` + /// use bevy_ecs::prelude::*; + /// + /// struct Component1; + /// struct Component2; + /// + /// fn example_system(mut commands: Commands) { + /// // Create a new entity with a `Component1` and `Component2`. + /// commands.spawn((Component1,)).with(Component2); + /// + /// // Psst! These are also equivalent to the line above! + /// commands.spawn((Component1, Component2)); + /// commands.spawn(()).with(Component1).with(Component2); + /// #[derive(Bundle)] + /// struct ExampleBundle { + /// a: Component1, + /// b: Component2, + /// } + /// commands.spawn(()).with_bundle(ExampleBundle { + /// a: Component1, + /// b: Component2, + /// }); + /// } + /// ``` pub fn with(&mut self, component: impl Component) -> &mut Self { let current_entity = self.current_entity.expect("Cannot add component because the 'current entity' is not set. You should spawn an entity first."); self.commands.push(Box::new(InsertOne { @@ -281,22 +362,26 @@ impl Commands { self } + /// Adds a command directly to the command list. If `command` is boxed, call `add_command_boxed`. pub fn add_command(&mut self, command: C) -> &mut Self { self.commands.push(Box::new(command)); self } + /// See `add_command`. pub fn add_command_boxed(&mut self, command: Box) -> &mut Self { self.commands.push(command); self } + /// Runs all the stored commands on `world` and `resources`. The command buffer is emptied as a part of this call. pub fn apply(&mut self, world: &mut World, resources: &mut Resources) { for command in self.commands.drain(..) { command.write(world, resources); } } + /// Returns the current entity, set by `spawn` or with `set_current_entity`. pub fn current_entity(&self) -> Option { self.current_entity } From 76959027c5fe569d4b968fa9c20fb98cceacb2bd Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Wed, 2 Dec 2020 02:33:43 -0800 Subject: [PATCH 2/6] Use intra-doc links for `See: ...` comments. --- crates/bevy_ecs/src/system/commands.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/bevy_ecs/src/system/commands.rs b/crates/bevy_ecs/src/system/commands.rs index a4c2c9d728516..e8e9947394d42 100644 --- a/crates/bevy_ecs/src/system/commands.rs +++ b/crates/bevy_ecs/src/system/commands.rs @@ -194,7 +194,7 @@ impl Commands { /// /// Note that `components` is a bundle. If you would like to spawn an entity with a single component, consider wrapping the component in a tuple (which `DynamicBundle` is implemented for). /// - /// See `set_current_entity`, `insert`. + /// See [`Commands::set_current_entity`], [`Commands::insert`]. /// /// # Example /// @@ -249,7 +249,7 @@ impl Commands { /// Inserts a bundle of components into `entity`. /// - /// See `World::insert`. + /// See [`World::insert`]. pub fn insert( &mut self, entity: Entity, @@ -260,7 +260,7 @@ impl Commands { /// Inserts a single component into `entity`. /// - /// See `World::insert_one`. + /// See [`World::insert_one`]. pub fn insert_one(&mut self, entity: Entity, component: impl Component) -> &mut Self { self.add_command(InsertOne { entity, component }) } @@ -280,7 +280,7 @@ impl Commands { }) } - /// See `World::remove_one`. + /// See [`World::remove_one`]. pub fn remove_one(&mut self, entity: Entity) -> &mut Self where T: Component, @@ -291,7 +291,7 @@ impl Commands { }) } - /// See `World::remove`. + /// See [`World::remove`]. pub fn remove(&mut self, entity: Entity) -> &mut Self where T: Bundle + Send + Sync + 'static, @@ -304,7 +304,7 @@ impl Commands { /// Adds a bundle of components to the current entity. /// - /// See `with`, `current_entity`. + /// See [`Commands::with`], [`Commands::current_entity`]. pub fn with_bundle( &mut self, components: impl DynamicBundle + Send + Sync + 'static, @@ -319,7 +319,7 @@ impl Commands { /// Adds a single component to the current entity. /// - /// See `with_bundle`, `current_entity`. + /// See [`Commands::with_bundle`], [`Commands::current_entity`]. /// /// # Warning /// @@ -362,13 +362,13 @@ impl Commands { self } - /// Adds a command directly to the command list. If `command` is boxed, call `add_command_boxed`. + /// Adds a command directly to the command list. Prefer this to `add_command_boxed` if the type of |command| is statically known. pub fn add_command(&mut self, command: C) -> &mut Self { self.commands.push(Box::new(command)); self } - /// See `add_command`. + /// See [`Commands::add_command`]. pub fn add_command_boxed(&mut self, command: Box) -> &mut Self { self.commands.push(command); self From 520e5efe8561ed51312a6d258bce3ecfa9e29b88 Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Wed, 2 Dec 2020 02:34:15 -0800 Subject: [PATCH 3/6] Rename `components` -> `bundle` in `Commands`/`World`. --- crates/bevy_ecs/src/core/world.rs | 16 +++++------ crates/bevy_ecs/src/system/commands.rs | 39 ++++++++++++-------------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/crates/bevy_ecs/src/core/world.rs b/crates/bevy_ecs/src/core/world.rs index 2a80f9ff0350f..ca0c2938f0976 100644 --- a/crates/bevy_ecs/src/core/world.rs +++ b/crates/bevy_ecs/src/core/world.rs @@ -76,16 +76,16 @@ impl World { /// let a = world.spawn((123, "abc")); /// let b = world.spawn((456, true)); /// ``` - pub fn spawn(&mut self, components: impl DynamicBundle) -> Entity { + pub fn spawn(&mut self, bundle: impl DynamicBundle) -> Entity { // Ensure all entity allocations are accounted for so `self.entities` can realloc if // necessary self.flush(); let entity = self.entities.alloc(); - let archetype_id = components.with_ids(|ids| { + let archetype_id = bundle.with_ids(|ids| { self.index.get(ids).copied().unwrap_or_else(|| { let x = self.archetypes.len() as u32; - self.archetypes.push(Archetype::new(components.type_info())); + self.archetypes.push(Archetype::new(bundle.type_info())); self.index.insert(ids.to_vec(), x); self.archetype_generation += 1; x @@ -95,7 +95,7 @@ impl World { let archetype = &mut self.archetypes[archetype_id as usize]; unsafe { let index = archetype.allocate(entity); - components.put(|ptr, ty, size| { + bundle.put(|ptr, ty, size| { archetype.put_dynamic(ptr, ty, size, index, ComponentFlags::ADDED); true }); @@ -566,7 +566,7 @@ impl World { pub fn insert( &mut self, entity: Entity, - components: impl DynamicBundle, + bundle: impl DynamicBundle, ) -> Result<(), NoSuchEntity> { use std::collections::hash_map::Entry; @@ -576,7 +576,7 @@ impl World { // Assemble Vec for the final entity let arch = &mut self.archetypes[loc.archetype as usize]; let mut info = arch.types().to_vec(); - for ty in components.type_info() { + for ty in bundle.type_info() { if let Some(ptr) = arch.get_dynamic(ty.id(), ty.layout().size(), loc.index) { ty.drop(ptr.as_ptr()); } else { @@ -601,7 +601,7 @@ impl World { if target == loc.archetype { // Update components in the current archetype let arch = &mut self.archetypes[loc.archetype as usize]; - components.put(|ptr, ty, size| { + bundle.put(|ptr, ty, size| { arch.put_dynamic(ptr, ty, size, loc.index, ComponentFlags::MUTATED); true }); @@ -625,7 +625,7 @@ impl World { self.entities.get_mut(moved).unwrap().index = old_index; } - components.put(|ptr, ty, size| { + bundle.put(|ptr, ty, size| { let had_component = source_arch.has_dynamic(ty); let flags = if had_component { ComponentFlags::MUTATED diff --git a/crates/bevy_ecs/src/system/commands.rs b/crates/bevy_ecs/src/system/commands.rs index e8e9947394d42..44ca41d3a378d 100644 --- a/crates/bevy_ecs/src/system/commands.rs +++ b/crates/bevy_ecs/src/system/commands.rs @@ -16,7 +16,7 @@ pub(crate) struct Spawn where T: DynamicBundle + Send + Sync + 'static, { - components: T, + bundle: T, } impl Command for Spawn @@ -24,7 +24,7 @@ where T: DynamicBundle + Send + Sync + 'static, { fn write(self: Box, world: &mut World, _resources: &mut Resources) { - world.spawn(self.components); + world.spawn(self.bundle); } } @@ -33,7 +33,7 @@ where I: IntoIterator, I::Item: Bundle, { - components_iter: I, + bundles_iter: I, } impl Command for SpawnBatch @@ -42,7 +42,7 @@ where I::Item: Bundle, { fn write(self: Box, world: &mut World, _resources: &mut Resources) { - world.spawn_batch(self.components_iter); + world.spawn_batch(self.bundles_iter); } } @@ -64,7 +64,7 @@ where T: DynamicBundle + Send + Sync + 'static, { entity: Entity, - components: T, + bundle: T, } impl Command for Insert @@ -72,7 +72,7 @@ where T: DynamicBundle + Send + Sync + 'static, { fn write(self: Box, world: &mut World, _resources: &mut Resources) { - world.insert(self.entity, self.components).unwrap(); + world.insert(self.entity, self.bundle).unwrap(); } } @@ -190,9 +190,9 @@ pub struct Commands { } impl Commands { - /// Creates a new entity and calls `insert` with the it and `components`. + /// Creates a new entity and calls `insert` with the it and `bundle`. /// - /// Note that `components` is a bundle. If you would like to spawn an entity with a single component, consider wrapping the component in a tuple (which `DynamicBundle` is implemented for). + /// Note that `bundle` is a bundle. If you would like to spawn an entity with a single component, consider wrapping the component in a tuple (which `Bundle` is implemented for). /// /// See [`Commands::set_current_entity`], [`Commands::insert`]. /// @@ -222,24 +222,24 @@ impl Commands { /// commands.spawn((Component2,)); /// } /// ``` - pub fn spawn(&mut self, components: impl DynamicBundle + Send + Sync + 'static) -> &mut Self { + pub fn spawn(&mut self, bundle: impl DynamicBundle + Send + Sync + 'static) -> &mut Self { let entity = self .entity_reserver .as_ref() .expect("entity reserver has not been set") .reserve_entity(); self.set_current_entity(entity); - self.insert(entity, components); + self.insert(entity, bundle); self } - /// Equivalent to iterating of `components_iter` and calling `spawn` on each bundle, but slightly more performant. - pub fn spawn_batch(&mut self, components_iter: I) -> &mut Self + /// Equivalent to iterating of `bundles_iter` and calling `spawn` on each bundle, but slightly more performant. + pub fn spawn_batch(&mut self, bundles_iter: I) -> &mut Self where I: IntoIterator + Send + Sync + 'static, I::Item: Bundle, { - self.add_command(SpawnBatch { components_iter }) + self.add_command(SpawnBatch { bundles_iter }) } /// Despawns only the specified entity, ignoring any other consideration. @@ -253,9 +253,9 @@ impl Commands { pub fn insert( &mut self, entity: Entity, - components: impl DynamicBundle + Send + Sync + 'static, + bundle: impl DynamicBundle + Send + Sync + 'static, ) -> &mut Self { - self.add_command(Insert { entity, components }) + self.add_command(Insert { entity, bundle }) } /// Inserts a single component into `entity`. @@ -305,14 +305,11 @@ impl Commands { /// Adds a bundle of components to the current entity. /// /// See [`Commands::with`], [`Commands::current_entity`]. - pub fn with_bundle( - &mut self, - components: impl DynamicBundle + Send + Sync + 'static, - ) -> &mut Self { - let current_entity = self.current_entity.expect("Cannot add components because the 'current entity' is not set. You should spawn an entity first."); + pub fn with_bundle(&mut self, bundle: impl DynamicBundle + Send + Sync + 'static) -> &mut Self { + let current_entity = self.current_entity.expect("Cannot add bundle because the 'current entity' is not set. You should spawn an entity first."); self.commands.push(Box::new(Insert { entity: current_entity, - components, + bundle, })); self } From fafe641dfc85529beba379427f208a1fdfc65ae6 Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Wed, 2 Dec 2020 02:41:12 -0800 Subject: [PATCH 4/6] Add note about Commands::despawn --- crates/bevy_ecs/src/system/commands.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_ecs/src/system/commands.rs b/crates/bevy_ecs/src/system/commands.rs index 44ca41d3a378d..c595d118efb49 100644 --- a/crates/bevy_ecs/src/system/commands.rs +++ b/crates/bevy_ecs/src/system/commands.rs @@ -243,6 +243,8 @@ impl Commands { } /// Despawns only the specified entity, ignoring any other consideration. + /// + /// Note that this does not recursively despawn and entity's children. pub fn despawn(&mut self, entity: Entity) -> &mut Self { self.add_command(Despawn { entity }) } From a63173dc16ea5943adc8bcbfb20766feebab6ba6 Mon Sep 17 00:00:00 2001 From: Michael Tang Date: Wed, 2 Dec 2020 13:18:22 -0800 Subject: [PATCH 5/6] PR comment feedback --- crates/bevy_ecs/src/core/bundle.rs | 4 +++ crates/bevy_ecs/src/system/commands.rs | 34 ++++++++++++++------------ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/crates/bevy_ecs/src/core/bundle.rs b/crates/bevy_ecs/src/core/bundle.rs index e69eecb14a4ff..7ca93433d2e74 100644 --- a/crates/bevy_ecs/src/core/bundle.rs +++ b/crates/bevy_ecs/src/core/bundle.rs @@ -22,6 +22,8 @@ use std::{ }; /// A dynamically typed collection of components +/// +/// See [Bundle] pub trait DynamicBundle { /// Invoke a callback on the fields' type IDs, sorted by descending alignment then id #[doc(hidden)] @@ -38,6 +40,8 @@ pub trait DynamicBundle { } /// A statically typed collection of components +/// +/// See [DynamicBundle] pub trait Bundle: DynamicBundle { #[doc(hidden)] fn with_static_ids(f: impl FnOnce(&[TypeId]) -> T) -> T; diff --git a/crates/bevy_ecs/src/system/commands.rs b/crates/bevy_ecs/src/system/commands.rs index c595d118efb49..46ad938e52349 100644 --- a/crates/bevy_ecs/src/system/commands.rs +++ b/crates/bevy_ecs/src/system/commands.rs @@ -190,11 +190,11 @@ pub struct Commands { } impl Commands { - /// Creates a new entity and calls `insert` with the it and `bundle`. + /// Creates a new entity with the components contained in `bundle`. /// - /// Note that `bundle` is a bundle. If you would like to spawn an entity with a single component, consider wrapping the component in a tuple (which `Bundle` is implemented for). + /// Note that `bundle` is a [DynamicBundle], which is a collection of components. [DynamicBundle] is automatically implemented for tuples of components. You can also create your own bundle types by deriving [`derive@Bundle`]. If you would like to spawn an entity with a single component, consider wrapping the component in a tuple (which [DynamicBundle] is implemented for). /// - /// See [`Commands::set_current_entity`], [`Commands::insert`]. + /// See [`Self::set_current_entity`], [`Self::insert`]. /// /// # Example /// @@ -217,9 +217,10 @@ impl Commands { /// b: Component2, /// }); /// - /// // Create new entities with a single component each. + /// // Create a new entity with a single component. /// commands.spawn((Component1,)); - /// commands.spawn((Component2,)); + /// // Create a new entity with two components. + /// commands.spawn((Component1, Component2)); /// } /// ``` pub fn spawn(&mut self, bundle: impl DynamicBundle + Send + Sync + 'static) -> &mut Self { @@ -233,7 +234,7 @@ impl Commands { self } - /// Equivalent to iterating of `bundles_iter` and calling `spawn` on each bundle, but slightly more performant. + /// Equivalent to iterating of `bundles_iter` and calling [`Self::spawn`] on each bundle, but slightly more performant. pub fn spawn_batch(&mut self, bundles_iter: I) -> &mut Self where I: IntoIterator + Send + Sync + 'static, @@ -242,9 +243,7 @@ impl Commands { self.add_command(SpawnBatch { bundles_iter }) } - /// Despawns only the specified entity, ignoring any other consideration. - /// - /// Note that this does not recursively despawn and entity's children. + /// Despawns only the specified entity, not including its children. pub fn despawn(&mut self, entity: Entity) -> &mut Self { self.add_command(Despawn { entity }) } @@ -271,6 +270,9 @@ impl Commands { self.add_command(InsertResource { resource }) } + /// Insert a resource that is local to a specific system. + /// + /// See [`crate::System::id`]. pub fn insert_local_resource( &mut self, system_id: SystemId, @@ -306,7 +308,7 @@ impl Commands { /// Adds a bundle of components to the current entity. /// - /// See [`Commands::with`], [`Commands::current_entity`]. + /// See [`Self::with`], [`Self::current_entity`]. pub fn with_bundle(&mut self, bundle: impl DynamicBundle + Send + Sync + 'static) -> &mut Self { let current_entity = self.current_entity.expect("Cannot add bundle because the 'current entity' is not set. You should spawn an entity first."); self.commands.push(Box::new(Insert { @@ -318,15 +320,15 @@ impl Commands { /// Adds a single component to the current entity. /// - /// See [`Commands::with_bundle`], [`Commands::current_entity`]. + /// See [`Self::with_bundle`], [`Self::current_entity`]. /// /// # Warning /// - /// It's possible to call this with a bundle, but this is likely not intended and `with_bundle` should be used instead. If `with` is called with a bundle, the bundle itself will be added as a component instead of the bundles' inner components each being added. + /// It's possible to call this with a bundle, but this is likely not intended and [`Self::with_bundle`] should be used instead. If `with` is called with a bundle, the bundle itself will be added as a component instead of the bundles' inner components each being added. /// /// # Example /// - /// `with` can be chained with `spawn`. + /// `with` can be chained with [`Self::spawn`]. /// /// ``` /// use bevy_ecs::prelude::*; @@ -361,13 +363,13 @@ impl Commands { self } - /// Adds a command directly to the command list. Prefer this to `add_command_boxed` if the type of |command| is statically known. + /// Adds a command directly to the command list. Prefer this to [`Self::add_command_boxed`] if the type of `command` is statically known. pub fn add_command(&mut self, command: C) -> &mut Self { self.commands.push(Box::new(command)); self } - /// See [`Commands::add_command`]. + /// See [`Self::add_command`]. pub fn add_command_boxed(&mut self, command: Box) -> &mut Self { self.commands.push(command); self @@ -380,7 +382,7 @@ impl Commands { } } - /// Returns the current entity, set by `spawn` or with `set_current_entity`. + /// Returns the current entity, set by [`Self::spawn`] or with [`Self::set_current_entity`]. pub fn current_entity(&self) -> Option { self.current_entity } From 6a259d5c1054dfa2884afa396520f2aa5a5b91dc Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Wed, 2 Dec 2020 16:18:37 -0800 Subject: [PATCH 6/6] Update commands.rs --- crates/bevy_ecs/src/system/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/commands.rs b/crates/bevy_ecs/src/system/commands.rs index 46ad938e52349..7edfdd8e46b17 100644 --- a/crates/bevy_ecs/src/system/commands.rs +++ b/crates/bevy_ecs/src/system/commands.rs @@ -234,7 +234,7 @@ impl Commands { self } - /// Equivalent to iterating of `bundles_iter` and calling [`Self::spawn`] on each bundle, but slightly more performant. + /// Equivalent to iterating `bundles_iter` and calling [`Self::spawn`] on each bundle, but slightly more performant. pub fn spawn_batch(&mut self, bundles_iter: I) -> &mut Self where I: IntoIterator + Send + Sync + 'static,