diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index f7ce1fa9f0..4146268905 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -16,9 +16,10 @@ use bevy_utils::tracing::info_span; #[allow(clippy::needless_doctest_main)] /// Containers of app logic and data /// -/// App store the ECS World, Resources, Schedule, and Executor. They also store the "run" function -/// of the App, which by default executes the App schedule once. Apps are constructed using the -/// builder pattern. +/// Bundles together the necessary elements, like [`World`] and [`Schedule`], to create +/// an ECS-based application. It also stores a pointer to a +/// [runner function](App::set_runner), which by default executes the App schedule +/// once. Apps are constructed with the builder pattern. /// /// ## Example /// Here is a simple "Hello World" Bevy app: @@ -74,6 +75,9 @@ impl App { } } + /// Advances the execution of the [`Schedule`] by one cycle. + /// + /// See [`Schedule::run_once`] for more details. pub fn update(&mut self) { #[cfg(feature = "trace")] let bevy_frame_update_span = info_span!("frame"); @@ -82,22 +86,10 @@ impl App { self.schedule.run(&mut self.world); } - /// Start the application (through main runner) + /// Starts the application by calling the app's [runner function](Self::set_runner). /// - /// Runs the application main loop. - /// - /// Usually the main loop is handled by Bevy integrated plugins (`winit`), but - /// one can also set the runner function through [`App::set_runner`]. - /// - /// ## Example - /// ``` - /// # use bevy_app::prelude::*; - /// # - /// App::new() - /// // all required plugin insertions, systems, etc inserted here - /// // finally, call: - /// .run(); - /// ``` + /// Finalizes the [`App`] configuration. For general usage, see the example on the item + /// level documentation. pub fn run(&mut self) { #[cfg(feature = "trace")] let bevy_app_run_span = info_span!("bevy_app"); @@ -109,11 +101,35 @@ impl App { (runner)(app); } + /// Adds a [`Stage`] with the given `label` to the last position of the app's + /// [`Schedule`]. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # let mut app = App::new(); + /// # + /// app.add_stage("my_stage", SystemStage::parallel()); + /// ``` pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { self.schedule.add_stage(label, stage); self } + /// Adds a [`Stage`] with the given `label` to the app's [`Schedule`], located + /// immediately after the stage labeled by `target`. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # let mut app = App::new(); + /// # + /// app.add_stage_after(CoreStage::Update, "my_stage", SystemStage::parallel()); + /// ``` pub fn add_stage_after( &mut self, target: impl StageLabel, @@ -124,6 +140,18 @@ impl App { self } + /// Adds a [`Stage`] with the given `label` to the app's [`Schedule`], located + /// immediately before the stage labeled by `target`. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # let mut app = App::new(); + /// # + /// app.add_stage_before(CoreStage::Update, "my_stage", SystemStage::parallel()); + /// ``` pub fn add_stage_before( &mut self, target: impl StageLabel, @@ -134,6 +162,18 @@ impl App { self } + /// Adds a [`Stage`] with the given `label` to the last position of the + /// [startup schedule](Self::add_default_stages). + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # let mut app = App::new(); + /// # + /// app.add_startup_stage("my_startup_stage", SystemStage::parallel()); + /// ``` pub fn add_startup_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { self.schedule .stage(CoreStage::Startup, |schedule: &mut Schedule| { @@ -142,6 +182,24 @@ impl App { self } + /// Adds a [startup stage](Self::add_default_stages) with the given `label`, immediately + /// after the stage labeled by `target`. + /// + /// The `target` label must refer to a stage inside the startup schedule. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # let mut app = App::new(); + /// # + /// app.add_startup_stage_after( + /// StartupStage::Startup, + /// "my_startup_stage", + /// SystemStage::parallel() + /// ); + /// ``` pub fn add_startup_stage_after( &mut self, target: impl StageLabel, @@ -155,6 +213,24 @@ impl App { self } + /// Adds a [startup stage](Self::add_default_stages) with the given `label`, immediately + /// before the stage labeled by `target`. + /// + /// The `target` label must refer to a stage inside the startup schedule. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # let mut app = App::new(); + /// # + /// app.add_startup_stage_before( + /// StartupStage::Startup, + /// "my_startup_stage", + /// SystemStage::parallel() + /// ); + /// ``` pub fn add_startup_stage_before( &mut self, target: impl StageLabel, @@ -168,6 +244,30 @@ impl App { self } + /// Fetches the [`Stage`] of type `T` marked with `label` from the [`Schedule`], then + /// executes the provided `func` passing the fetched stage to it as an argument. + /// + /// The `func` argument should be a function or a closure that accepts a mutable reference + /// to a struct implementing `Stage` and returns the same type. That means that it should + /// also assume that the stage has already been fetched successfully. + /// + /// See [`Schedule::stage`] for more details. + /// + /// # Example + /// + /// Here the closure is used to add a system to the update stage: + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut app = App::new(); + /// # fn my_system() {} + /// # + /// app.stage(CoreStage::Update, |stage: &mut SystemStage| { + /// stage.add_system(my_system) + /// }); + /// ``` pub fn stage &mut T>( &mut self, label: impl StageLabel, @@ -177,40 +277,63 @@ impl App { self } - /// Adds a system that runs every time `app.update()` is called by the runner + /// Adds a system to the [update stage](Self::add_default_stages) of the app's [`Schedule`]. /// - /// Systems are the main building block in the Bevy ECS app model. You can define - /// normal rust functions, and use them as a Bevy system. + /// Refer to the [system module documentation](bevy_ecs::system) to see how a system + /// can be defined. /// - /// System functions can have parameters, through which one can query and - /// mutate Bevy ECS states. - /// See [The Bevy Book](https://bevyengine.org/learn/book/introduction/) for more information. + /// # Example /// - /// Systems are run in parallel, and the execution order is not deterministic. - /// If you want more fine-grained control for order, see [`App::add_system_to_stage`]. - /// - /// For adding a system that runs only at app startup, see [`App::add_startup_system`]. - /// - /// ## Example /// ``` /// # use bevy_app::prelude::*; /// # use bevy_ecs::prelude::*; /// # - /// fn my_system(_commands: Commands) { - /// println!("My system, triggered once per frame"); - /// } - /// - /// App::new() - /// .add_system(my_system); + /// # fn my_system() {} + /// # let mut app = App::new(); + /// # + /// app.add_system(my_system); /// ``` pub fn add_system(&mut self, system: impl IntoSystemDescriptor) -> &mut Self { self.add_system_to_stage(CoreStage::Update, system) } + /// Adds a [`SystemSet`] to the [update stage](Self::add_default_stages). + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut app = App::new(); + /// # fn system_a() {} + /// # fn system_b() {} + /// # fn system_c() {} + /// # + /// app.add_system_set( + /// SystemSet::new() + /// .with_system(system_a) + /// .with_system(system_b) + /// .with_system(system_c), + /// ); + /// ``` pub fn add_system_set(&mut self, system_set: SystemSet) -> &mut Self { self.add_system_set_to_stage(CoreStage::Update, system_set) } + /// Adds a system to the [`Stage`] identified by `stage_label`. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut app = App::new(); + /// # fn my_system() {} + /// # + /// app.add_system_to_stage(CoreStage::PostUpdate, my_system); + /// ``` pub fn add_system_to_stage( &mut self, stage_label: impl StageLabel, @@ -220,6 +343,27 @@ impl App { self } + /// Adds a [`SystemSet`] to the [`Stage`] identified by `stage_label`. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut app = App::new(); + /// # fn system_a() {} + /// # fn system_b() {} + /// # fn system_c() {} + /// # + /// app.add_system_set_to_stage( + /// CoreStage::PostUpdate, + /// SystemSet::new() + /// .with_system(system_a) + /// .with_system(system_b) + /// .with_system(system_c), + /// ); + /// ``` pub fn add_system_set_to_stage( &mut self, stage_label: impl StageLabel, @@ -230,13 +374,10 @@ impl App { self } - /// Adds a system that is run once at application startup + /// Adds a system to the [startup stage](Self::add_default_stages) of the app's [`Schedule`]. /// - /// Startup systems run exactly once BEFORE all other systems. These are generally used for - /// app initialization code (ex: adding entities and resources). - /// - /// * For adding a system that runs for every frame, see [`App::add_system`]. - /// * For adding a system to specific stage, see [`App::add_system_to_stage`]. + /// * For adding a system that runs for every frame, see [`add_system`](Self::add_system). + /// * For adding a system to specific stage, see [`add_system_to_stage`](Self::add_system_to_stage). /// /// ## Example /// ``` @@ -248,7 +389,7 @@ impl App { /// } /// /// App::new() - /// .add_startup_system(my_startup_system); + /// .add_startup_system(my_startup_system.system()); /// ``` pub fn add_startup_system( &mut self, @@ -257,10 +398,46 @@ impl App { self.add_startup_system_to_stage(StartupStage::Startup, system) } + /// Adds a [`SystemSet`] to the [startup stage](Self::add_default_stages) + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut app = App::new(); + /// # fn startup_system_a() {} + /// # fn startup_system_b() {} + /// # fn startup_system_c() {} + /// # + /// app.add_startup_system_set( + /// SystemSet::new() + /// .with_system(startup_system_a) + /// .with_system(startup_system_b) + /// .with_system(startup_system_c), + /// ); + /// ``` pub fn add_startup_system_set(&mut self, system_set: SystemSet) -> &mut Self { self.add_startup_system_set_to_stage(StartupStage::Startup, system_set) } + /// Adds a system to the [startup schedule](Self::add_default_stages), in the stage + /// identified by `stage_label`. + /// + /// `stage_label` must refer to a stage inside the startup schedule. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut app = App::new(); + /// # fn my_startup_system() {} + /// # + /// app.add_startup_system_to_stage(StartupStage::PreStartup, my_startup_system); + /// ``` pub fn add_startup_system_to_stage( &mut self, stage_label: impl StageLabel, @@ -273,6 +450,30 @@ impl App { self } + /// Adds a [`SystemSet`] to the [startup schedule](Self::add_default_stages), in the stage + /// identified by `stage_label`. + /// + /// `stage_label` must refer to a stage inside the startup schedule. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut app = App::new(); + /// # fn startup_system_a() {} + /// # fn startup_system_b() {} + /// # fn startup_system_c() {} + /// # + /// app.add_startup_system_set_to_stage( + /// StartupStage::PreStartup, + /// SystemSet::new() + /// .with_system(startup_system_a) + /// .with_system(startup_system_b) + /// .with_system(startup_system_c), + /// ); + /// ``` pub fn add_startup_system_set_to_stage( &mut self, stage_label: impl StageLabel, @@ -310,6 +511,41 @@ impl App { .add_system_set_to_stage(stage, State::::get_driver()) } + /// Adds utility stages to the [`Schedule`], giving it a standardized structure. + /// + /// Adding those stages is necessary to make some core engine features work, like + /// adding systems without specifying a stage, or registering events. This is however + /// done by default by calling `App::default`, which is in turn called by + /// [`App::new`]. + /// + /// # The stages + /// + /// All the added stages, with the exception of the startup stage, run every time the + /// schedule is invoked. The stages are the following, in order of execution: + /// - **First:** Runs at the very start of the schedule execution cycle, even before the + /// startup stage. + /// - **Startup:** This is actually a schedule containing sub-stages. Runs only once + /// when the app starts. + /// - **Pre-startup:** Intended for systems that need to run before other startup systems. + /// - **Startup:** The main startup stage. Startup systems are added here by default. + /// - **Post-startup:** Intended for systems that need to run after other startup systems. + /// - **Pre-update:** Often used by plugins to prepare their internal state before the + /// update stage begins. + /// - **Update:** Intended for user defined logic. Systems are added here by default. + /// - **Post-update:** Often used by plugins to finalize their internal state after the + /// world changes that happened during the update stage. + /// - **Last:** Runs right before the end of the schedule execution cycle. + /// + /// The labels for those stages are defined in the [`CoreStage`] and [`StartupStage`] + /// `enum`s. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # + /// let app = App::empty().add_default_stages(); + /// ``` pub fn add_default_stages(&mut self) -> &mut Self { self.add_stage(CoreStage::First, SystemStage::parallel()) .add_stage( @@ -330,6 +566,20 @@ impl App { /// /// This is done by adding a `Resource` of type `Events::`, /// and inserting a `Events::::update_system` system into `CoreStage::First`. + /// + /// See [`Events`](bevy_ecs::event::Events) for defining events. + /// + /// # Example + /// + /// ``` + /// # use bevy_app::prelude::*; + /// # use bevy_ecs::prelude::*; + /// # + /// # struct MyEvent; + /// # let mut app = App::new(); + /// # + /// app.add_event::(); + /// ``` pub fn add_event(&mut self) -> &mut Self where T: Component, @@ -341,7 +591,7 @@ impl App { /// Inserts a resource to the current [App] and overwrites any resource previously added of the same type. /// /// A resource in Bevy represents globally unique data. Resources must be added to Bevy Apps - /// before using them. This happens with [`App::insert_resource`]. + /// before using them. This happens with [`insert_resource`](Self::insert_resource). /// /// See also `init_resource` for resources that implement `Default` or [`FromWorld`]. /// @@ -388,10 +638,11 @@ impl App { self } - /// Initialize a resource in the current [App], if it does not exist yet + /// Initialize a resource in the current [`App`], if it does not exist yet + /// + /// If the resource already exists, nothing happens. /// /// Adds a resource that implements `Default` or [`FromWorld`] trait. - /// If the resource already exists, `init_resource` does nothing. /// /// ## Example /// ``` @@ -426,6 +677,9 @@ impl App { self } + /// Initialize a non-send resource in the current [`App`], if it does not exist yet. + /// + /// Adds a resource that implements `Default` or [`FromWorld`] trait. pub fn init_non_send_resource(&mut self) -> &mut Self where R: FromWorld + 'static, @@ -438,13 +692,14 @@ impl App { self } - /// Sets the main runner loop function for this Bevy App + /// Sets the function that will be called when the app is run. /// - /// Usually the main loop is handled by Bevy integrated plugins - /// ([`WinitPlugin`](https://docs.rs/bevy/*/bevy/winit/struct.WinitPlugin.html)), - /// but in some cases one might wish to implement their own main loop. + /// The runner function (`run_fn`) is called only once by [`App::run`]. If the + /// presence of a main loop in the app is desired, it is responsibility of the runner + /// function to provide it. /// - /// This method sets the main loop function, overwriting a previous runner if any. + /// The runner function is usually not set manually, but by Bevy integrated plugins + /// (e.g. winit plugin). /// /// ## Example /// ``` @@ -470,7 +725,7 @@ impl App { /// One of Bevy's core principles is modularity. All Bevy engine features are implemented /// as plugins. This includes internal features like the renderer. /// - /// Bevy also provides a few sets of default plugins. See [`App::add_plugins`]. + /// Bevy also provides a few sets of default plugins. See [`add_plugins`](Self::add_plugins). /// /// ## Example /// ``` @@ -492,9 +747,7 @@ impl App { /// Bevy plugins can be grouped into a set of plugins. Bevy provides /// built-in PluginGroups that provide core engine functionality. /// - /// The plugin groups available by default are - /// [`DefaultPlugins`](https://docs.rs/bevy/*/bevy/struct.DefaultPlugins.html) - /// and [`MinimalPlugins`](https://docs.rs/bevy/*/bevy/struct.MinimalPlugins.html). + /// The plugin groups available by default are `DefaultPlugins` and `MinimalPlugins`. /// /// ## Example /// ``` @@ -557,10 +810,11 @@ impl App { self } - /// Registers a new component using the given [ComponentDescriptor]. Components do not need to - /// be manually registered. This just provides a way to override default configuration. - /// Attempting to register a component with a type that has already been used by [World] - /// will result in an error. + /// Registers a new component using the given [ComponentDescriptor]. + /// + /// Components do not need to be manually registered. This just provides a way to + /// override default configuration. Attempting to register a component with a type + /// that has already been used by [World] will result in an error. /// /// See [World::register_component] pub fn register_component(&mut self, descriptor: ComponentDescriptor) -> &mut Self { @@ -568,6 +822,7 @@ impl App { self } + /// Adds the type `T` to the type registry resource. #[cfg(feature = "bevy_reflect")] pub fn register_type(&mut self) -> &mut Self { { diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index 7349ce86b1..c54d79d90f 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -1,3 +1,6 @@ +//! This crate is about everything concerning the highest-level, application layer of a Bevy +//! app. + mod app; mod plugin; mod plugin_group; @@ -21,9 +24,14 @@ pub mod prelude { use bevy_ecs::schedule::StageLabel; /// The names of the default App stages +/// +/// The relative stages are added by [`App::add_default_stages`]. #[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)] pub enum CoreStage { - /// Runs once at the beginning of the app. + /// Runs only once at the beginning of the app. + /// + /// Consists of the sub-stages defined in [`StartupStage`]. Systems added here are + /// referred to as "startup systems". Startup, /// Name of app stage that runs before all other app stages First, diff --git a/crates/bevy_ecs/src/archetype.rs b/crates/bevy_ecs/src/archetype.rs index d2ed1da1ac..9d6ba80bd9 100644 --- a/crates/bevy_ecs/src/archetype.rs +++ b/crates/bevy_ecs/src/archetype.rs @@ -1,3 +1,6 @@ +//! Types for defining [`Archetype`]s, collections of entities that have the same set of +//! components. + use crate::{ bundle::BundleId, component::{ComponentId, StorageType}, diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 76f94dfa53..cfb9f96c10 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -1,3 +1,7 @@ +//! Types for handling [`Bundle`]s. +//! +//! This module contains the `Bundle` trait and some other helper types. + pub use bevy_ecs_macros::Bundle; use crate::{ @@ -9,15 +13,35 @@ use crate::{ use bevy_ecs_macros::all_tuples; use std::{any::TypeId, collections::HashMap}; -/// An ordered collection of components, commonly used for spawning entities, and adding and -/// removing components in bulk. +/// An ordered collection of components. /// -/// Typically, you will simply use `#[derive(Bundle)]` when creating your own `Bundle`. -/// The `Bundle` trait is automatically implemented for tuples of components: -/// `(ComponentA, ComponentB)` is a very convenient shorthand when working with one-off collections -/// of components. Note that both `()` and `(ComponentA, )` are valid tuples. +/// Commonly used for spawning entities and adding and removing components in bulk. This +/// trait is automatically implemented for tuples of components: `(ComponentA, ComponentB)` +/// is a very convenient shorthand when working with one-off collections of components. Note +/// that both the unit type `()` and `(ComponentA, )` are valid bundles. The unit bundle is +/// particularly useful for spawning multiple empty entities by using +/// [`Commands::spawn_batch`](crate::system::Commands::spawn_batch). /// -/// You can nest bundles like so: +/// # Examples +/// +/// Typically, you will simply use `#[derive(Bundle)]` when creating your own `Bundle`. Each +/// struct field is a component: +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// # struct ComponentA; +/// # struct ComponentB; +/// # struct ComponentC; +/// # +/// #[derive(Bundle)] +/// struct MyBundle { +/// a: ComponentA, +/// b: ComponentB, +/// c: ComponentC, +/// } +/// ``` +/// +/// You can nest bundles using the `#[bundle]` attribute: /// ``` /// # use bevy_ecs::bundle::Bundle; /// @@ -36,10 +60,11 @@ use std::{any::TypeId, collections::HashMap}; /// ``` /// /// # Safety -/// [Bundle::component_ids] must return the ComponentId for each component type in the bundle, in the -/// _exact_ order that [Bundle::get_components] is called. -/// [Bundle::from_components] must call `func` exactly once for each [ComponentId] returned by -/// [Bundle::component_ids] +/// +/// - [Bundle::component_ids] must return the ComponentId for each component type in the bundle, in the +/// _exact_ order that [Bundle::get_components] is called. +/// - [Bundle::from_components] must call `func` exactly once for each [ComponentId] returned by +/// [Bundle::component_ids]. pub unsafe trait Bundle: Send + Sync + 'static { /// Gets this [Bundle]'s component ids, in the order of this bundle's Components fn component_ids(components: &mut Components) -> Vec; diff --git a/crates/bevy_ecs/src/change_detection.rs b/crates/bevy_ecs/src/change_detection.rs index 2ebd0a3ed5..3cf2fecc49 100644 --- a/crates/bevy_ecs/src/change_detection.rs +++ b/crates/bevy_ecs/src/change_detection.rs @@ -1,3 +1,5 @@ +//! Types that detect when their internal data mutate. + use crate::component::{Component, ComponentTicks}; use bevy_reflect::Reflect; use std::ops::{Deref, DerefMut}; @@ -136,9 +138,13 @@ pub(crate) struct Ticks<'a> { /// Unique mutable borrow of a resource. /// +/// See the [`World`](crate::world::World) documentation to see the usage of a resource. +/// +/// If you need a shared borrow, use [`Res`](crate::system::Res) instead. +/// /// # Panics /// -/// Panics when used as a [`SystemParameter`](crate::system::SystemParam) if the resource does not exist. +/// Panics when used as a [`SystemParam`](crate::system::SystemParam) if the resource does not exist. /// /// Use `Option>` instead if the resource might not always exist. pub struct ResMut<'a, T: Component> { @@ -152,7 +158,7 @@ impl_debug!(ResMut<'a, T>, Component); /// Unique borrow of a non-[`Send`] resource. /// -/// Only [`Send`] resources may be accessed with the [`ResMut`] [`crate::system::SystemParam`]. In case that the +/// Only [`Send`] resources may be accessed with the [`ResMut`] [`SystemParam`](crate::system::SystemParam). In case that the /// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct /// the scheduler to instead run the system on the main thread so that it doesn't send the resource /// over to another thread. diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index 6e71a1a7d9..a633ff620e 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -1,3 +1,5 @@ +//! Types for declaring and storing [`Component`]s. + use crate::storage::SparseSetIndex; use std::{ alloc::Layout, diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 4f4681757d..c74974d7a4 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -1,3 +1,27 @@ +//! Entity handling types. +//! +//! In Bevy ECS, there is no monolithic data structure for an entity. Instead, the [`Entity`] +//! `struct` is just a *generational index* (a combination of an ID and a generation). Then, +//! the `Entity` maps to the specific [`Component`s](crate::component::Component). This way, +//! entities can have meaningful data attached to it. This is a fundamental design choice +//! that has been taken to enhance performance and usability. +//! +//! # Usage +//! +//! Here are links to the methods used to perform common operations +//! involving entities: +//! +//! - **Spawning an empty entity:** use [`Commands::spawn`](crate::system::Commands::spawn). +//! - **Spawning an entity with components:** use +//! [`Commands::spawn_bundle`](crate::system::Commands::spawn_bundle). +//! - **Despawning an entity:** use +//! [`EntityCommands::despawn`](crate::system::EntityCommands::despawn). +//! - **Inserting a component to an entity:** use +//! [`EntityCommands::insert`](crate::system::EntityCommands::insert). +//! - **Adding multiple components to an entity:** use +//! [`EntityCommands::insert_bundle`](crate::system::EntityCommands::insert_bundle). +//! - **Removing a component to an entity:** use +//! [`EntityCommands::remove`](crate::system::EntityCommands::remove). mod map_entities; mod serde; @@ -36,9 +60,11 @@ impl Entity { /// Creates a new entity reference with a generation of 0. /// /// # Note - /// Spawning a specific `entity` value is rarely the right choice. Most apps should favor [`Commands::spawn`]. - /// This method should generally only be used for sharing entities across apps, and only when they have a - /// scheme worked out to share an ID space (which doesn't happen by default). + /// + /// Spawning a specific `entity` value is rarely the right choice. Most apps should favor + /// [`Commands::spawn`](crate::system::Commands::spawn). This method should generally + /// only be used for sharing entities across apps, and only when they have a scheme + /// worked out to share an ID space (which doesn't happen by default). pub fn new(id: u32) -> Entity { Entity { id, generation: 0 } } diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 6d0ffd4a23..6b5cc1af48 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -1,3 +1,5 @@ +//! Event handling types. + use crate as bevy_ecs; use crate::{ component::Component, diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index c51925b710..de7c17baf6 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -12,6 +12,7 @@ pub mod storage; pub mod system; pub mod world; +/// Most commonly used re-exported types. pub mod prelude { #[doc(hidden)] #[cfg(feature = "bevy_reflect")] diff --git a/crates/bevy_ecs/src/reflect.rs b/crates/bevy_ecs/src/reflect.rs index f798b753f9..a967c60449 100644 --- a/crates/bevy_ecs/src/reflect.rs +++ b/crates/bevy_ecs/src/reflect.rs @@ -1,3 +1,5 @@ +//! Types that enable reflection support. + pub use crate::change_detection::ReflectMut; use crate::{ component::Component, diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index a1c386446c..f8d04a8cab 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -1,3 +1,8 @@ +//! Tools for controlling system execution. +//! +//! When using Bevy ECS, systems are usually not run directly, but are inserted into a +//! [`Stage`], which then lives within a [`Schedule`]. + mod executor; mod executor_parallel; pub mod graph_utils; @@ -25,6 +30,12 @@ use std::fmt::Debug; use crate::{system::System, world::World}; use bevy_utils::HashMap; +/// A container of [`Stage`]s set to be run in a linear order. +/// +/// Since `Schedule` implements the [`Stage`] trait, it can be inserted into another schedule. +/// In this way, the properties of the child schedule can be set differently from the parent. +/// For example, it can be set to run only once during app execution, while the parent schedule +/// runs indefinitely. #[derive(Default)] pub struct Schedule { stages: HashMap>, @@ -33,11 +44,13 @@ pub struct Schedule { } impl Schedule { + /// Similar to [`add_stage`](Self::add_stage), but it also returns itself. pub fn with_stage(mut self, label: impl StageLabel, stage: S) -> Self { self.add_stage(label, stage); self } + /// Similar to [`add_stage_after`](Self::add_stage_after), but it also returns itself. pub fn with_stage_after( mut self, target: impl StageLabel, @@ -48,6 +61,7 @@ impl Schedule { self } + /// Similar to [`add_stage_before`](Self::add_stage_before), but it also returns itself. pub fn with_stage_before( mut self, target: impl StageLabel, @@ -63,6 +77,7 @@ impl Schedule { self } + /// Similar to [`add_system_to_stage`](Self::add_system_to_stage), but it also returns itself. pub fn with_system_in_stage( mut self, stage_label: impl StageLabel, @@ -80,6 +95,16 @@ impl Schedule { self } + /// Adds the given `stage` at the last position of the schedule. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut schedule = Schedule::default(); + /// schedule.add_stage("my_stage", SystemStage::parallel()); + /// ``` pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { let label: Box = Box::new(label); self.stage_order.push(label.clone()); @@ -90,6 +115,17 @@ impl Schedule { self } + /// Adds the given `stage` immediately after the `target` stage. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut schedule = Schedule::default(); + /// # schedule.add_stage("target_stage", SystemStage::parallel()); + /// schedule.add_stage_after("target_stage", "my_stage", SystemStage::parallel()); + /// ``` pub fn add_stage_after( &mut self, target: impl StageLabel, @@ -114,6 +150,17 @@ impl Schedule { self } + /// Adds the given `stage` immediately before the `target` stage. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut schedule = Schedule::default(); + /// # schedule.add_stage("target_stage", SystemStage::parallel()); + /// # + /// schedule.add_stage_before("target_stage", "my_stage", SystemStage::parallel()); pub fn add_stage_before( &mut self, target: impl StageLabel, @@ -138,6 +185,18 @@ impl Schedule { self } + /// Adds the given `system` to the stage identified by `stage_label`. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # fn my_system() {} + /// # let mut schedule = Schedule::default(); + /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # + /// schedule.add_system_to_stage("my_stage", my_system); pub fn add_system_to_stage( &mut self, stage_label: impl StageLabel, @@ -160,6 +219,29 @@ impl Schedule { self } + /// Adds the given `system_set` to the stage identified by `stage_label`. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # fn my_system() {} + /// # let mut schedule = Schedule::default(); + /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # + /// schedule.add_system_set_to_stage( + /// "my_stage", + /// SystemSet::new() + /// .with_system(system_a) + /// .with_system(system_b) + /// .with_system(system_c) + /// ); + /// # + /// # fn system_a() {} + /// # fn system_b() {} + /// # fn system_c() {} + /// ``` pub fn add_system_set_to_stage( &mut self, stage_label: impl StageLabel, @@ -170,6 +252,31 @@ impl Schedule { }) } + /// Fetches the [`Stage`] of type `T` marked with `label`, then executes the provided + /// `func` passing the fetched stage to it as an argument. + /// + /// The `func` argument should be a function or a closure that accepts a mutable reference + /// to a struct implementing `Stage` and returns the same type. That means that it should + /// also assume that the stage has already been fetched successfully. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # let mut schedule = Schedule::default(); + /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # + /// schedule.stage("my_stage", |stage: &mut SystemStage| { + /// stage.add_system(my_system) + /// }); + /// # + /// # fn my_system() {} + /// ``` + /// + /// # Panics + /// + /// Panics if `label` refers to a non-existing stage, or if it's not of type `T`. pub fn stage &mut T>( &mut self, label: impl StageLabel, @@ -182,18 +289,48 @@ impl Schedule { self } + /// Returns a shared reference to the stage identified by `label`, if it exists. + /// + /// If the requested stage does not exist, `None` is returned instead. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # fn my_system() {} + /// # let mut schedule = Schedule::default(); + /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # + /// let stage = schedule.get_stage::(&"my_stage").unwrap(); + /// ``` pub fn get_stage(&self, label: &dyn StageLabel) -> Option<&T> { self.stages .get(label) .and_then(|stage| stage.downcast_ref::()) } + /// Returns a unique, mutable reference to the stage identified by `label`, if it exists. + /// + /// If the requested stage does not exist, `None` is returned instead. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # fn my_system() {} + /// # let mut schedule = Schedule::default(); + /// # schedule.add_stage("my_stage", SystemStage::parallel()); + /// # + /// let stage = schedule.get_stage_mut::(&"my_stage").unwrap(); pub fn get_stage_mut(&mut self, label: &dyn StageLabel) -> Option<&mut T> { self.stages .get_mut(label) .and_then(|stage| stage.downcast_mut::()) } + /// Executes each [`Stage`] contained in the schedule, one at a time. pub fn run_once(&mut self, world: &mut World) { for label in self.stage_order.iter() { #[cfg(feature = "trace")] diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index 9d5dda4bdf..edef90da49 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -18,6 +18,7 @@ use std::fmt::Debug; use super::IntoSystemDescriptor; +/// A type that can run as a step of a [`Schedule`](super::Schedule). pub trait Stage: Downcast + Send + Sync { /// Runs the stage; this happens once per update. /// Implementors must initialize all of their state and systems before running the first time. diff --git a/crates/bevy_ecs/src/storage/mod.rs b/crates/bevy_ecs/src/storage/mod.rs index 5c93815f4d..26f92fdf88 100644 --- a/crates/bevy_ecs/src/storage/mod.rs +++ b/crates/bevy_ecs/src/storage/mod.rs @@ -1,3 +1,5 @@ +//! Storage layouts for ECS data. + mod blob_vec; mod sparse_set; mod table; diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index fc875f383c..a172692074 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -15,7 +15,23 @@ pub trait Command: Send + Sync + 'static { fn write(self, world: &mut World); } -/// A list of commands that will be run to modify a [`World`]. +/// A list of commands that modify a [`World`], running at the end of the stage where they +/// have been invoked. +/// +/// # Usage +/// +/// `Commands` is a [`SystemParam`](crate::system::SystemParam), therefore it is declared +/// as a function parameter: +/// +/// ``` +/// # use bevy_ecs::prelude::*; +/// # +/// fn my_system(mut commands: Commands) { +/// // ... +/// } +/// ``` +/// +/// Then, commands can be invoked by calling the methods of `commands`. pub struct Commands<'w, 's> { queue: &'s mut CommandQueue, entities: &'w Entities, @@ -32,6 +48,11 @@ impl<'w, 's> Commands<'w, 's> { /// Creates a new empty [`Entity`] and returns an [`EntityCommands`] builder for it. /// + /// To directly spawn an entity with a [`Bundle`] included, you can use + /// [`spawn_bundle`](Self::spawn_bundle) instead of `.spawn().insert_bundle()`. + /// + /// See [`World::spawn`] for more details. + /// /// # Example /// /// ``` @@ -157,8 +178,35 @@ impl<'w, 's> Commands<'w, 's> { } } - /// Equivalent to iterating `bundles_iter` and calling [`Self::spawn`] on each bundle, but - /// slightly more performant. + /// Spawns entities to the [`World`] according to the given iterator (or a type that can + /// be converted to it). + /// + /// The end result of this command is equivalent to iterating `bundles_iter` and calling + /// [`spawn`](Self::spawn) on each bundle, but it is more performant due to memory + /// pre-allocation. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Name(String); + /// # struct Score(u32); + /// # + /// # fn system(mut commands: Commands) { + /// commands.spawn_batch(vec![ + /// ( + /// Name("Alice".to_string()), + /// Score(0), + /// ), + /// ( + /// Name("Bob".to_string()), + /// Score(0), + /// ), + /// ]); + /// # } + /// # system.system(); + /// ``` pub fn spawn_batch(&mut self, bundles_iter: I) where I: IntoIterator + Send + Sync + 'static, @@ -169,9 +217,11 @@ impl<'w, 's> Commands<'w, 's> { /// For a given batch of ([Entity], [Bundle]) pairs, either spawns each [Entity] with the given /// bundle (if the entity does not exist), or inserts the [Bundle] (if the entity already exists). + /// /// This is faster than doing equivalent operations one-by-one. /// /// # Note + /// /// Spawning a specific `entity` value is rarely the right choice. Most apps should use [`Commands::spawn_batch`]. /// This method should generally only be used for sharing entities across apps, and only when they have a scheme /// worked out to share an ID space (which doesn't happen by default). @@ -184,12 +234,51 @@ impl<'w, 's> Commands<'w, 's> { self.queue.push(InsertOrSpawnBatch { bundles_iter }); } - /// See [`World::insert_resource`]. + /// Inserts a resource to the [`World`], overwriting any previous value of the same type. + /// + /// See [`World::insert_resource`] for more details. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Scoreboard { + /// # current_score: u32, + /// # high_score: u32, + /// # } + /// # + /// # fn system(mut commands: Commands) { + /// commands.insert_resource(Scoreboard { + /// current_score: 0, + /// high_score: 0, + /// }); + /// # } + /// # system.system(); + /// ``` pub fn insert_resource(&mut self, resource: T) { self.queue.push(InsertResource { resource }) } - /// Queue a resource removal. + /// Removes a resource from the [`World`]. + /// + /// See [`World::remove_resource`] for more details. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Scoreboard { + /// # current_score: u32, + /// # high_score: u32, + /// # } + /// # + /// # fn system(mut commands: Commands) { + /// commands.remove_resource::(); + /// # } + /// # system.system(); + /// ``` pub fn remove_resource(&mut self) { self.queue.push(RemoveResource:: { phantom: PhantomData, @@ -197,25 +286,94 @@ impl<'w, 's> Commands<'w, 's> { } /// Adds a command directly to the command list. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// use bevy_ecs::system::InsertBundle; + /// # + /// # struct PlayerEntity { entity: Entity } + /// # struct Health(u32); + /// # struct Strength(u32); + /// # struct Defense(u32); + /// # + /// # #[derive(Bundle)] + /// # struct CombatBundle { + /// # health: Health, + /// # strength: Strength, + /// # defense: Defense, + /// # } + /// + /// fn add_combat_stats_system(mut commands: Commands, player: Res) { + /// commands.add(InsertBundle { + /// entity: player.entity, + /// bundle: CombatBundle { + /// health: Health(100), + /// strength: Strength(40), + /// defense: Defense(20), + /// }, + /// }); + /// } + /// # add_combat_stats_system.system(); + /// ``` pub fn add(&mut self, command: C) { self.queue.push(command); } } -/// A list of commands that will be run to modify an [`Entity`]. +/// A list of commands that will be run to modify an [entity](crate::entity). pub struct EntityCommands<'w, 's, 'a> { entity: Entity, commands: &'a mut Commands<'w, 's>, } impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { - /// Retrieves the current entity's unique [`Entity`] id. + /// Returns the [`Entity`] id of the entity. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// fn my_system(mut commands: Commands) { + /// let entity_id = commands.spawn().id(); + /// } + /// # my_system.system(); + /// ``` #[inline] pub fn id(&self) -> Entity { self.entity } - /// Adds a [`Bundle`] of components to the current entity. + /// Adds a [`Bundle`] of components to the entity. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct PlayerEntity { entity: Entity } + /// # struct Health(u32); + /// # struct Strength(u32); + /// # struct Defense(u32); + /// # + /// # #[derive(Bundle)] + /// # struct CombatBundle { + /// # health: Health, + /// # strength: Strength, + /// # defense: Defense, + /// # } + /// # + /// fn add_combat_stats_system(mut commands: Commands, player: Res) { + /// commands.entity(player.entity).insert_bundle(CombatBundle { + /// health: Health(100), + /// strength: Strength(40), + /// defense: Defense(20), + /// }); + /// } + /// # add_combat_stats_system.system(); + /// ``` pub fn insert_bundle(&mut self, bundle: impl Bundle) -> &mut Self { self.commands.add(InsertBundle { entity: self.entity, @@ -224,8 +382,10 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { self } - /// Adds a single [`Component`] to the current entity. + /// Adds a single [`Component`] to the entity. /// + /// See [`EntityMut::insert`](crate::world::EntityMut::insert) for more + /// details. /// /// # Warning /// @@ -239,18 +399,18 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { /// `Self::insert` can be chained with [`Commands::spawn`]. /// /// ``` - /// use bevy_ecs::prelude::*; - /// - /// struct Component1; - /// struct Component2; - /// + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Component1; + /// # struct Component2; + /// # /// fn example_system(mut commands: Commands) { /// // Create a new entity with `Component1` and `Component2` /// commands.spawn() /// .insert(Component1) /// .insert(Component2); /// - /// // Psst! These are also equivalent to the expression above! + /// // The following statements are equivalent to above one. /// commands.spawn().insert_bundle((Component1, Component2)); /// commands.spawn_bundle((Component1, Component2)); /// } @@ -264,7 +424,26 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { self } - /// See [`EntityMut::remove_bundle`](crate::world::EntityMut::remove_bundle). + /// Removes a [`Bundle`] of components from the entity. + /// + /// See [`EntityMut::remove_bundle`](crate::world::EntityMut::remove_bundle) for more + /// details. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct PlayerEntity { entity: Entity } + /// # + /// # #[derive(Bundle)] + /// # struct CombatBundle { a: u32 }; // dummy field, unit bundles are not permitted. + /// # + /// fn remove_combat_stats_system(mut commands: Commands, player: Res) { + /// commands.entity(player.entity).remove_bundle::(); + /// } + /// # remove_combat_stats_system.system(); + /// ``` pub fn remove_bundle(&mut self) -> &mut Self where T: Bundle, @@ -276,7 +455,23 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { self } - /// See [`EntityMut::remove`](crate::world::EntityMut::remove). + /// Removes a single component from the entity. + /// + /// See [`EntityMut::remove`](crate::world::EntityMut::remove) for more details. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct TargetEnemy { entity: Entity } + /// # struct Enemy; + /// # + /// fn convert_enemy_system(mut commands: Commands, enemy: Res) { + /// commands.entity(enemy.entity).remove::(); + /// } + /// # convert_enemy_system.system(); + /// ``` pub fn remove(&mut self) -> &mut Self where T: Component, @@ -288,14 +483,33 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> { self } - /// Despawns only the specified entity, not including its children. + /// Despawns the entity. + /// + /// See [`World::despawn`] for more details. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct CharacterToRemove { entity: Entity } + /// # + /// fn remove_character_system( + /// mut commands: Commands, + /// character_to_remove: Res + /// ) + /// { + /// commands.entity(character_to_remove.entity).despawn(); + /// } + /// # remove_character_system.system(); + /// ``` pub fn despawn(&mut self) { self.commands.add(Despawn { entity: self.entity, }) } - /// Returns the underlying `[Commands]`. + /// Returns the underlying [`Commands`]. pub fn commands(&mut self) -> &mut Commands<'w, 's> { self.commands } diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index 7bed6a4712..5525cce662 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -1,3 +1,68 @@ +//! Tools for controlling behavior in an ECS application. +//! +//! Systems define how an ECS based application behaves. They have to be registered to a +//! [`SystemStage`](crate::schedule::SystemStage) to be able to run. A system is usually +//! written as a normal function that will be automatically converted into a system. +//! +//! System functions can have parameters, through which one can query and mutate Bevy ECS state. +//! Only types that implement [`SystemParam`] can be used, automatically fetching data from +//! the [`World`](crate::world::World). +//! +//! System functions often look like this: +//! +//! ``` +//! # use bevy_ecs::prelude::*; +//! # +//! # struct Player { alive: bool } +//! # struct Score(u32); +//! # struct Round(u32); +//! # +//! fn update_score_system( +//! mut query: Query<(&Player, &mut Score)>, +//! mut round: ResMut, +//! ) { +//! for (player, mut score) in query.iter_mut() { +//! if player.alive { +//! score.0 += round.0; +//! } +//! } +//! round.0 += 1; +//! } +//! # update_score_system.system(); +//! ``` +//! +//! # System ordering +//! +//! While the execution of systems is usually parallel and not deterministic, there are two +//! ways to determine a certain degree of execution order: +//! +//! - **System Stages:** They determine hard execution synchronization boundaries inside of +//! which systems run in parallel by default. +//! - **Labeling:** First, systems are labeled upon creation by calling `.label()`. Then, +//! methods such as `.before()` and `.after()` are appended to systems to determine +//! execution order in respect to other systems. +//! +//! # System parameter list +//! Following is the complete list of accepted types as system parameters: +//! +//! - [`Query`] +//! - [`Res`] and `Option` +//! - [`ResMut`] and `Option` +//! - [`Commands`] +//! - [`Local`] +//! - [`EventReader`](crate::event::EventReader) +//! - [`EventWriter`](crate::event::EventWriter) +//! - [`NonSend`] and `Option` +//! - [`NonSendMut`] and `Option` +//! - [`RemovedComponents`] +//! - [`SystemChangeTick`] +//! - [`Archetypes`](crate::archetype::Archetypes) (Provides Archetype metadata) +//! - [`Bundles`](crate::bundle::Bundles) (Provides Bundles metadata) +//! - [`Components`](crate::component::Components) (Provides Components metadata) +//! - [`Entities`](crate::entity::Entities) (Provides Entities metadata) +//! - All tuples between 1 to 16 elements where each element implements [`SystemParam`] +//! - [`()` (unit primitive type)](https://doc.rust-lang.org/stable/std/primitive.unit.html) + mod commands; mod exclusive_system; mod function_system; diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 921454ec2c..d9afa6a7eb 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -11,102 +11,225 @@ use bevy_tasks::TaskPool; use std::{any::TypeId, fmt::Debug}; use thiserror::Error; -/// Provides scoped access to a [`World`] according to a given [`WorldQuery`] and query filter. +/// Provides scoped access to components in a [`World`]. /// -/// Queries are a powerful tool enabling the programmer to iterate over entities and their components -/// as well as filtering them on certain conditions. +/// Queries enable iteration over entities and their components as well as filtering them +/// on certain conditions. A query matches its parameters against the world to produce a series +/// of results. Each *query result* is a tuple of components (the same components defined +/// in the query) that belong to the same entity. /// -/// # Query Building Primer +/// Computational cost of queries is reduced by the fact that they have an internal archetype +/// cache to avoid re-computing archetype matches on each query access. /// -/// ### Basic Component Access +/// Query functionality is based on the [`WorldQuery`] trait. Both tuples of components +/// (up to 16 elements) and query filters implement this trait. /// -/// A basic query looks like `Query<&UnitHealth>` and all it does is grant immutable access to all -/// `UnitHealth` components. Similarly using `&mut UnitHealth` instead grants mutable access instead. +/// `Query` accepts two type parameters: /// -/// The main way to access the components of a query is through the [`Query::iter`] and [`Query::iter_mut`] -/// functions which return a [`QueryIter`] to iterate over: +/// 1. **Component access:** the components that an entity must have at the same time to yield +/// a query result. +/// 2. **Query filters (optional):** a predicate that ignores query results that don't match +/// its conditions. +/// +/// # Usage as system parameter +/// +/// A query is defined by declaring it as a system parameter. This section shows the various +/// use cases of `Query` as a system parameter. +/// +/// ## Immutable component access +/// +/// The following example defines a query that gives an iterator over `(&ComponentA, &ComponentB)` +/// tuples, where `ComponentA` and `ComponentB` belong to the same entity. Accessing components +/// immutably helps system parallelization. /// /// ``` /// # use bevy_ecs::system::IntoSystem; /// # use bevy_ecs::system::Query; -/// struct UnitHealth(pub u32); -/// fn system(query: Query<&UnitHealth>) { -/// for UnitHealth(health) in query.iter() { -/// println!("We got {} health points left!", health); -/// } -/// } +/// # struct ComponentA; +/// # struct ComponentB; +/// # fn system( +/// query: Query<(&ComponentA, &ComponentB)> +/// # ) {} /// # system.system(); /// ``` /// -/// ### Multiple Component Access +/// ## Mutable component access /// -/// Instead of asking for just one component like before we can build a query that queries for multiple -/// components with the help of tuples,`Query<(&Shape, &Color, &mut Size)>`. This query retrieves -/// immutable references to the `Shape` and `Color` component and a mutable reference to the `Size` -/// component. +/// The following example is similar to the previous one, with the exception of `ComponentA` +/// being accessed mutably here. Note that both mutable and immutable accesses are allowed +/// in the same query. /// /// ``` /// # use bevy_ecs::system::IntoSystem; /// # use bevy_ecs::system::Query; -/// #[derive(Debug)] -/// enum Shape { -/// Circle, -/// Box, -/// }; -/// struct Color(pub String); -/// struct Size(pub u32); -/// fn system(mut query: Query<(&Shape, &Color, &mut Size)>) { -/// for (shape, color, mut size) in query.iter_mut() { -/// *size = Size(1); -/// println!("We got a {} colored {:?} and made it one unit big!", color.0, shape); -/// } -/// } +/// # struct ComponentA; +/// # struct ComponentB; +/// # fn system( +/// // `ComponentA` is accessed mutably, while `ComponentB` is accessed immutably. +/// mut query: Query<(&mut ComponentA, &ComponentB)> +/// # ) {} /// # system.system(); /// ``` /// -/// Note the use of [`Query::iter_mut`] here, as our query is not read-only anymore due to the use -/// of the `&mut` [`WorldQuery`] we aren't able to use the `iter` method any longer. +/// Two systems cannot be executed in parallel if both access a certain component and +/// at least one of the accesses is mutable, unless the schedule can verify that no entity +/// could be found in both queries, as otherwise Rusts mutability Rules would be broken. /// -/// ### Filtering Query Results +/// Similarly, a system cannot contain two queries that would break Rust's mutability Rules. +/// If you need such Queries, you can use Filters to make the Queries disjoint or use a +/// [`QuerySet`](super::QuerySet). /// -/// Queries also support filters. A filter is a [`WorldQuery`] that can be used as a predicate to -/// filter out entities that do not meet the requirement set by the predicate. [`With`](crate::query::With) -/// is one such filter and all it does is filter out all entities that do not contain the component -/// it requests. Let's look at an example on how to use this filter. +/// ## Entity ID access +/// +/// Inserting [`Entity`](crate::entity::Entity) at any position in the type parameter tuple +/// will give access to the entity ID. /// /// ``` +/// # use bevy_ecs::entity::Entity; /// # use bevy_ecs::system::IntoSystem; /// # use bevy_ecs::system::Query; +/// # struct ComponentA; +/// # struct ComponentB; +/// # fn system( +/// query: Query<(Entity, &ComponentA, &ComponentB)> +/// # ) {} +/// # system.system(); +/// ``` +/// +/// ## Query filtering +/// +/// The second, optional type parameter of query, is used for filters can be added to filter +/// out the query results that don't satisfy the given condition. +/// +/// ``` /// # use bevy_ecs::query::With; -/// struct Person(String); -/// struct IsTallEnough; -/// fn system(query: Query<&Person, With>) { -/// for person in query.iter() { -/// println!("{} is tall enough!", person.0); -/// } -/// } +/// # use bevy_ecs::system::IntoSystem; +/// # use bevy_ecs::system::Query; +/// # struct ComponentA; +/// # struct ComponentB; +/// # struct ComponentC; +/// # fn system( +/// // `ComponentC` data won't be accessed, but only entities that contain it will be queried. +/// query: Query<(&ComponentA, &ComponentB), With> +/// # ) {} /// # system.system(); /// ``` /// -/// As shown above, the filter is a second type parameter of the query. It is optional (defaults to -/// ()). Filters do not give access to the component data, only limit the entities that the query will match. +/// If you need to apply more filters in a single query, group them into a tuple: /// -/// ### Optional Components +/// ``` +/// # use bevy_ecs::query::{Changed, With}; +/// # use bevy_ecs::system::IntoSystem; +/// # use bevy_ecs::system::Query; +/// # struct ComponentA; +/// # struct ComponentB; +/// # struct ComponentC; +/// # fn system( +/// // Similar to the previous query, but with the addition of a `Changed` filter. +/// query: Query<(&ComponentA, &ComponentB), (With, Changed)> +/// # ) {} +/// # system.system(); +/// ``` /// -/// Now we've seen how to narrow down results of a query, but what if we want to act on entities that -/// may have a component but not always. This is where [`Option`] comes into play, with `Option` we -/// can specify just that. The result of the following query, `Query<&Color, Option<&mut Size>>`, is -/// the tuple `(&Color, Option<&mut Size>)` containing all entities that have the `Color` component, -/// some of which also have a `Size` component. Note that we didn't put a [`Component`] inside the -/// `Option` but a [`WorldQuery`], `&mut T` in this case. This means we can also do the following -/// just fine, `Query>`. +/// The following list contains all the available query filters: /// -/// Do take care when handling optional components though, as iterating a query that solely consists -/// of optional components will go over all the entities of the [`World`]. Therefore it's best to -/// design your queries in such a way that they at least contain one non-optional [`WorldQuery`]. +/// - [`Added`](crate::query::Added) +/// - [`Changed`](crate::query::Changed) +/// - [`With`](crate::query::With) +/// - [`Without`](crate::query::Without) +/// - [`Or`](crate::query::Or) /// -/// This touches all the basics of queries, make sure to check out all the [`WorldQueries`](WorldQuery) -/// bevy has to offer. +/// ## Optional component access +/// +/// A component can be made optional in a query by wrapping it into an [`Option`]. In the +/// following example, the query will iterate over components of both entities that contain +/// `ComponentA` and `ComponentB`, and entities that contain `ComponentA` but not `ComponentB`. +/// +/// ``` +/// # use bevy_ecs::system::IntoSystem; +/// # use bevy_ecs::system::Query; +/// # struct ComponentA; +/// # struct ComponentB; +/// # fn system( +/// query: Query<(&ComponentA, Option<&ComponentB>)> +/// # ) {} +/// # system.system(); +/// ``` +/// +/// If an entity does not contain a component, its corresponding query result value will be +/// `None`. Optional components increase the number of entities a query has to match against, +/// therefore they can hurt iteration performance, especially in the worst case scenario where +/// the query solely consists of only optional components, since all entities will be iterated +/// over. +/// +/// ## Single component access +/// +/// If just a single component needs to be accessed, using a tuple as the first type parameter +/// of `Query` can be omitted. +/// +/// ``` +/// # use bevy_ecs::system::IntoSystem; +/// # use bevy_ecs::system::Query; +/// # struct MyComponent; +/// # fn tuple_system( +/// // This is correct, but can be avoided. +/// query: Query<(&MyComponent,)> +/// # ) {} +/// # tuple_system.system(); +/// +/// # fn non_tuple_system( +/// // This is the preferred method. +/// query: Query<&MyComponent> +/// # ) {} +/// # non_tuple_system.system(); +/// ``` +/// +/// # Usage of query results +/// +/// Inside the body of the system function, the `Query` is available as a function parameter. +/// This section shows various methods to access query results. +/// +/// ## Iteration over every query result +/// +/// The [`iter`](Self::iter) and [`iter_mut`](Self::iter_mut) methods are used to iterate +/// over every query result. Refer to the +/// [`Iterator` API docs](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) +/// for advanced iterator usage. +/// +/// ``` +/// # use bevy_ecs::system::IntoSystem; +/// # use bevy_ecs::system::Query; +/// # struct ComponentA; +/// # struct ComponentB; +/// fn immutable_query_system(mut query: Query<(&ComponentA, &ComponentB)>) { +/// for (a, b) in query.iter() { +/// // Here, `a` and `b` are normal references to components, relatively of +/// // `&ComponentA` and `&ComponentB` types. +/// } +/// } +/// # immutable_query_system.system(); +/// +/// fn mutable_query_system(mut query: Query<(&mut ComponentA, &ComponentB)>) { +/// for (mut a, b) in query.iter_mut() { +/// // Similar to the above system, but this time `ComponentA` can be accessed mutably. +/// // Note the usage of `mut` in the tuple and the call to `iter_mut` instead of `iter`. +/// } +/// } +/// # mutable_query_system.system(); +/// ``` +/// +/// ## Getting the query result for a particular entity +/// +/// If you have an [`Entity`] ID, you can use the [`get`](Self::get) or +/// [`get_mut`](Self::get_mut) methods to access the query result for that particular entity. +/// +/// ## Getting a single query result +/// +/// While it's possible to get a single result from a query by using `iter.next()`, a more +/// idiomatic approach would use the [`single`](Self::single) or [`single_mut`](Self::single_mut) +/// methods instead. Keep in mind though that they will return a [`QuerySingleError`] if the +/// number of query results differ from being exactly one. If that's the case, use `iter.next()` +/// (or `iter_mut.next()`) to only get the first query result. pub struct Query<'world, 'state, Q: WorldQuery, F: WorldQuery = ()> where F::Fetch: FilterFetch, @@ -144,7 +267,26 @@ where /// Returns an [`Iterator`] over the query results. /// - /// This can only be called for read-only queries, see [`Self::iter_mut`] for write-queries. + /// This can only be called for read-only queries (due to the [`ReadOnlyFetch`] trait + /// bound). See [`Self::iter_mut`] for queries that contain at least one mutable component. + /// + /// # Example + /// + /// Here, the `report_names_system` iterates over the `Player` component of every entity + /// that contains it: + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Player { name: String } + /// # + /// fn report_names_system(query: Query<&Player>) { + /// for player in query.iter() { + /// println!("Say hello to {}!", player.name); + /// } + /// } + /// # report_names_system.system(); + /// ``` #[inline] pub fn iter(&'s self) -> QueryIter<'w, 's, Q, F> where @@ -159,6 +301,24 @@ where } /// Returns an [`Iterator`] over the query results. + /// + /// # Example + /// + /// Here, the `gravity_system` iterates over the `Velocity` component of every entity in + /// the world that contains it in order to update it: + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Velocity { x: f32, y: f32, z: f32 } + /// fn gravity_system(mut query: Query<&mut Velocity>) { + /// const DELTA: f32 = 1.0 / 60.0; + /// for mut velocity in query.iter_mut() { + /// velocity.y -= 9.8 * DELTA; + /// } + /// } + /// # gravity_system.system(); + /// ``` #[inline] pub fn iter_mut(&mut self) -> QueryIter<'_, '_, Q, F> { // SAFE: system runs without conflicts with other systems. @@ -265,6 +425,24 @@ where /// be chained like a normal [`Iterator`]. /// /// This can only be called for read-only queries, see [`Self::for_each_mut`] for write-queries. + /// + /// # Example + /// + /// Here, the `report_names_system` iterates over the `Player` component of every entity + /// that contains it: + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Player { name: String } + /// # + /// fn report_names_system(query: Query<&Player>) { + /// query.for_each(|player| { + /// println!("Say hello to {}!", player.name); + /// }); + /// } + /// # report_names_system.system(); + /// ``` #[inline] pub fn for_each(&'s self, f: impl FnMut(>::Item)) where @@ -284,6 +462,24 @@ where /// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot /// be chained like a normal [`Iterator`]. + /// + /// # Example + /// + /// Here, the `gravity_system` iterates over the `Velocity` component of every entity in + /// the world that contains it in order to update it: + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Velocity { x: f32, y: f32, z: f32 } + /// fn gravity_system(mut query: Query<&mut Velocity>) { + /// const DELTA: f32 = 1.0 / 60.0; + /// query.for_each_mut(|mut velocity| { + /// velocity.y -= 9.8 * DELTA; + /// }); + /// } + /// # gravity_system.system(); + /// ``` #[inline] pub fn for_each_mut<'a>(&'a mut self, f: impl FnMut(>::Item)) { // SAFE: system runs without conflicts with other systems. same-system queries have runtime @@ -347,9 +543,36 @@ where }; } - /// Gets the query result for the given [`Entity`]. + /// Returns the query result for the given [`Entity`]. /// - /// This can only be called for read-only queries, see [`Self::get_mut`] for write-queries. + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. + /// + /// This can only be called for read-only queries (due to the [`ReadOnlyFetch`] trait bound). + /// see [`get_mut`](Self::get_mut) for queries that contain at least one mutable component. + /// + /// # Example + /// + /// Here, `get` is used to retrieve the exact query result of the entity specified by the + /// `SelectedCharacter` resource. + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct SelectedCharacter { entity: Entity } + /// # struct Character { name: String } + /// # + /// fn print_selected_character_name_system( + /// query: Query<&Character>, + /// selection: Res + /// ) + /// { + /// if let Ok(selected_character) = query.get(selection.entity) { + /// println!("{}", selected_character.name); + /// } + /// } + /// # print_selected_character_name_system.system(); + /// ``` #[inline] pub fn get( &'s self, @@ -370,7 +593,29 @@ where } } - /// Gets the query result for the given [`Entity`]. + /// Returns the query result for the given [`Entity`]. + /// + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. + /// + /// # Example + /// + /// Here, `get_mut` is used to retrieve the exact query result of the entity specified by the + /// `PoisonedCharacter` resource. + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct PoisonedCharacter { character_id: Entity } + /// # struct Health(u32); + /// # + /// fn poison_system(mut query: Query<&mut Health>, poisoned: Res) { + /// if let Ok(mut health) = query.get_mut(poisoned.character_id) { + /// health.0 -= 1; + /// } + /// } + /// # poison_system.system(); + /// ``` #[inline] pub fn get_mut( &mut self, @@ -388,7 +633,10 @@ where } } - /// Gets the query result for the given [`Entity`]. + /// Returns the query result for the given [`Entity`]. + /// + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// /// # Safety /// @@ -405,9 +653,33 @@ where .get_unchecked_manual(self.world, entity, self.last_change_tick, self.change_tick) } - /// Gets a reference to the [`Entity`]'s [`Component`] of the given type. This will fail if the - /// entity does not have the given component type or if the given component type does not match - /// this query. + /// Returns a reference to the [`Entity`]'s [`Component`] of the given type. + /// + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. + /// + /// # Example + /// + /// Here, `get_component` is used to retrieve the `Character` component of the entity + /// specified by the `SelectedCharacter` resource. + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct SelectedCharacter { entity: Entity } + /// # struct Character { name: String } + /// # + /// fn print_selected_character_name_system( + /// query: Query<&Character>, + /// selection: Res + /// ) + /// { + /// if let Ok(selected_character) = query.get_component::(selection.entity) { + /// println!("{}", selected_character.name); + /// } + /// } + /// # print_selected_character_name_system.system(); + /// ``` #[inline] pub fn get_component( &self, @@ -438,9 +710,29 @@ where } } - /// Gets a mutable reference to the [`Entity`]'s [`Component`] of the given type. This will fail - /// if the entity does not have the given component type or if the given component type does not - /// match this query. + /// Returns a mutable reference to the [`Entity`]'s [`Component`] of the given type. + /// + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. + /// + /// # Example + /// + /// Here, `get_component_mut` is used to retrieve the `Health` component of the entity + /// specified by the `PoisonedCharacter` resource. + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct PoisonedCharacter { character_id: Entity } + /// # struct Health(u32); + /// # + /// fn poison_system(mut query: Query<&mut Health>, poisoned: Res) { + /// if let Ok(mut health) = query.get_component_mut::(poisoned.character_id) { + /// health.0 -= 1; + /// } + /// } + /// # poison_system.system(); + /// ``` #[inline] pub fn get_component_mut( &mut self, @@ -450,9 +742,10 @@ where unsafe { self.get_component_unchecked_mut(entity) } } - /// Gets a mutable reference to the [`Entity`]'s [`Component`] of the given type. This will fail - /// if the entity does not have the given component type or the component does not match the - /// query. + /// Returns a mutable reference to the [`Entity`]'s [`Component`] of the given type. + /// + /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is + /// returned instead. /// /// # Safety /// @@ -488,25 +781,30 @@ where } } - /// Gets the result of a single-result query. + /// Returns a single immutable query result when there is exactly one entity matching + /// the query. /// - /// Assumes this query has only one result and panics if there are no or multiple results. - /// Use [`Self::get_single`] to handle the error cases explicitly + /// This can only be called for read-only queries (due to the [`ReadOnlyFetch`] trait + /// bound). Use [`single_mut`](Self::single_mut) for queries that contain at least one + /// mutable component. /// /// # Example /// /// ``` - /// # use bevy_ecs::prelude::{IntoSystem, Query, With}; - /// struct Player; - /// struct Position(f32, f32); + /// # use bevy_ecs::prelude::{IntoSystem, Query, With}; + /// # struct Player; + /// # struct Position(f32, f32); /// fn player_system(query: Query<&Position, With>) { /// let player_position = query.single(); /// // do something with player_position /// } - /// # let _check_that_its_a_system = player_system.system(); + /// # player_system.system(); /// ``` /// - /// This can only be called for read-only queries, see [`Self::single_mut`] for write-queries. + /// # Panics + /// + /// Panics if the number of query results is not exactly one. Use + /// [`get_single`](Self::get_single) to return a `Result` instead of panicking. #[track_caller] pub fn single(&'s self) -> >::Item where @@ -515,36 +813,37 @@ where self.get_single().unwrap() } - /// Gets the result of a single-result query. + /// Returns a single immutable query result when there is exactly one entity matching + /// the query. /// - /// If the query has exactly one result, returns the result inside `Ok` - /// otherwise returns either [`QuerySingleError::NoEntities`] - /// or [`QuerySingleError::MultipleEntities`], as appropriate. + /// This can only be called for read-only queries (due to the [`ReadOnlyFetch`] trait + /// bound). Use [`get_single_mut`](Self::get_single_mut) for queries that contain at least one + /// mutable component. /// - /// # Examples + /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned + /// instead. + /// + /// # Example /// /// ``` - /// # use bevy_ecs::prelude::{IntoSystem, With}; /// # use bevy_ecs::system::{Query, QuerySingleError}; - /// struct Player; - /// struct Position(f32, f32); - /// fn player_system(query: Query<&Position, With>) { + /// # use bevy_ecs::prelude::IntoSystem; + /// # struct PlayerScore(i32); + /// fn player_scoring_system(query: Query<&PlayerScore>) { /// match query.get_single() { - /// Ok(position) => { - /// // do something with position + /// Ok(PlayerScore(score)) => { + /// println!("Score: {}", score); /// } /// Err(QuerySingleError::NoEntities(_)) => { - /// // no position with Player + /// println!("Error: There is no player!"); /// } /// Err(QuerySingleError::MultipleEntities(_)) => { - /// // multiple position with Player + /// println!("Error: There is more than one player!"); /// } /// } /// } - /// # let _check_that_its_a_system = player_system.system(); + /// # player_scoring_system.system(); /// ``` - /// - /// This can only be called for read-only queries, see [`Self::get_single_mut`] for write-queries. pub fn get_single(&'s self) -> Result<>::Item, QuerySingleError> where Q::Fetch: ReadOnlyFetch, @@ -562,15 +861,53 @@ where } } - /// Gets the query result if it is only a single result, otherwise panics - /// If you want to handle the error case yourself you can use the [`Self::get_single_mut`] variant. + /// Returns a single mutable query result when there is exactly one entity matching + /// the query. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Player; + /// # struct Health(u32); + /// # + /// fn regenerate_player_health_system(mut query: Query<&mut Health, With>) { + /// let mut health = query.single_mut(); + /// health.0 += 1; + /// } + /// # regenerate_player_health_system.system(); + /// ``` + /// + /// # Panics + /// + /// Panics if the number of query results is not exactly one. Use + /// [`get_single_mut`](Self::get_single_mut) to return a `Result` instead of panicking. #[track_caller] pub fn single_mut(&mut self) -> >::Item { self.get_single_mut().unwrap() } - /// Gets the query result if it is only a single result, otherwise returns a - /// [`QuerySingleError`]. + /// Returns a single mutable query result when there is exactly one entity matching + /// the query. + /// + /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned + /// instead. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Player; + /// # struct Health(u32); + /// # + /// fn regenerate_player_health_system(mut query: Query<&mut Health, With>) { + /// let mut health = query.get_single_mut().expect("Error: Could not find a single player."); + /// health.0 += 1; + /// } + /// # regenerate_player_health_system.system(); + /// ``` pub fn get_single_mut( &mut self, ) -> Result<>::Item, QuerySingleError> { @@ -587,7 +924,25 @@ where } } - /// Returns true if this query contains no elements. + /// Returns `true` if there are no query results. + /// + /// # Example + /// + /// Here, the score is increased only if an entity with a `Player` component is present + /// in the world: + /// + /// ``` + /// # use bevy_ecs::prelude::*; + /// # + /// # struct Player; + /// # struct Score(u32); + /// fn update_score_system(query: Query<(), With>, mut score: ResMut) { + /// if !query.is_empty() { + /// score.0 += 1; + /// } + /// } + /// # update_score_system.system(); + /// ``` #[inline] pub fn is_empty(&self) -> bool { // TODO: This code can be replaced with `self.iter().next().is_none()` if/when diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 6f3e731ad3..6868c7fb97 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -23,7 +23,8 @@ use std::{ /// /// # Derive /// -/// This trait can be derived with the [`derive@super::SystemParam`] macro. +/// This trait can be derived with the [`derive@super::SystemParam`] macro. The only requirement +/// is that every struct field must also implement `SystemParam`. /// /// ``` /// # use bevy_ecs::prelude::*; @@ -201,6 +202,10 @@ impl_query_set!(); /// Shared borrow of a resource. /// +/// See the [`World`] documentation to see the usage of a resource. +/// +/// If you need a unique mutable borrow, use [`ResMut`] instead. +/// /// # Panics /// /// Panics when used as a [`SystemParameter`](SystemParam) if the resource does not exist. diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index f4a542b7f1..4fe571bdf7 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -34,11 +34,48 @@ impl Default for WorldId { } } -/// [World] stores and exposes operations on [entities](Entity), [components](Component), +/// Stores and exposes operations on [entities](Entity), [components](Component), resources, /// and their associated metadata. +/// /// Each [Entity] has a set of components. Each component can have up to one instance of each /// component type. Entity components can be created, updated, removed, and queried using a given /// [World]. +/// +/// # Resources +/// +/// Worlds can also store *resources*, which are unique instances of a given type that don't +/// belong to a specific Entity. There are also *non send resources*, which can only be +/// accessed on the main thread. +/// +/// ## Usage of global resources +/// +/// 1. Insert the resource into the `World`, using [`World::insert_resource`]. +/// 2. Fetch the resource from a system, using [`Res`](crate::system::Res) or [`ResMut`](crate::system::ResMut). +/// +/// ``` +/// # let mut world = World::default(); +/// # let mut schedule = Schedule::default(); +/// # schedule.add_stage("update", SystemStage::parallel()); +/// # use bevy_ecs::prelude::*; +/// # +/// struct MyResource { value: u32 } +/// +/// world.insert_resource(MyResource { value: 42 }); +/// +/// fn read_resource_system(resource: Res) { +/// assert_eq!(resource.value, 42); +/// } +/// +/// fn write_resource_system(mut resource: ResMut) { +/// assert_eq!(resource.value, 42); +/// resource.value = 0; +/// assert_eq!(resource.value, 0); +/// } +/// # +/// # schedule.add_system_to_stage("update", read_resource_system.label("first")); +/// # schedule.add_system_to_stage("update", write_resource_system.after("first")); +/// # schedule.run_once(&mut world); +/// ``` pub struct World { id: WorldId, pub(crate) entities: Entities,