From 32faf4cb5c891e9ce99c897962ef4551fe973f3f Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Sat, 10 Jun 2023 19:23:48 -0400 Subject: [PATCH] Document every public item in `bevy_ecs` (#8731) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective Title. --------- Co-authored-by: François Co-authored-by: Alice Cecile Co-authored-by: James Liu --- crates/bevy_ecs/src/archetype.rs | 7 ++ crates/bevy_ecs/src/bundle.rs | 17 +++++ crates/bevy_ecs/src/change_detection.rs | 6 +- crates/bevy_ecs/src/component.rs | 64 ++++++++++++++++++- crates/bevy_ecs/src/entity/mod.rs | 4 +- crates/bevy_ecs/src/event.rs | 22 ++++++- crates/bevy_ecs/src/lib.rs | 1 + crates/bevy_ecs/src/query/access.rs | 3 + crates/bevy_ecs/src/query/fetch.rs | 6 ++ crates/bevy_ecs/src/query/mod.rs | 2 + crates/bevy_ecs/src/query/par_iter.rs | 3 + crates/bevy_ecs/src/query/state.rs | 19 +++++- crates/bevy_ecs/src/reflect.rs | 5 ++ crates/bevy_ecs/src/removal_detection.rs | 8 ++- crates/bevy_ecs/src/schedule/condition.rs | 2 + crates/bevy_ecs/src/schedule/config.rs | 6 ++ crates/bevy_ecs/src/schedule/executor/mod.rs | 1 + .../src/schedule/executor/multi_threaded.rs | 4 ++ .../bevy_ecs/src/schedule/executor/simple.rs | 2 + .../src/schedule/executor/single_threaded.rs | 3 + crates/bevy_ecs/src/schedule/graph_utils.rs | 6 +- crates/bevy_ecs/src/schedule/mod.rs | 2 + crates/bevy_ecs/src/schedule/schedule.rs | 3 + crates/bevy_ecs/src/schedule/set.rs | 4 ++ crates/bevy_ecs/src/schedule/state.rs | 1 + crates/bevy_ecs/src/storage/sparse_set.rs | 2 + crates/bevy_ecs/src/system/combinator.rs | 3 + crates/bevy_ecs/src/system/commands/mod.rs | 15 +++++ .../src/system/commands/parallel_scope.rs | 3 + .../src/system/exclusive_function_system.rs | 2 + .../src/system/exclusive_system_param.rs | 11 ++++ crates/bevy_ecs/src/system/function_system.rs | 12 ++++ crates/bevy_ecs/src/system/mod.rs | 2 + crates/bevy_ecs/src/system/system.rs | 6 ++ crates/bevy_ecs/src/system/system_param.rs | 16 +++++ crates/bevy_ecs/src/world/entity_ref.rs | 61 +++++++++++++++++- crates/bevy_ecs/src/world/error.rs | 2 + crates/bevy_ecs/src/world/mod.rs | 16 +++++ crates/bevy_ecs/src/world/spawn_batch.rs | 4 ++ .../bevy_ecs/src/world/unsafe_world_cell.rs | 28 ++++++++ crates/bevy_ecs/src/world/world_cell.rs | 4 ++ 41 files changed, 374 insertions(+), 14 deletions(-) diff --git a/crates/bevy_ecs/src/archetype.rs b/crates/bevy_ecs/src/archetype.rs index dfac03dc7e..bab8e60b2e 100644 --- a/crates/bevy_ecs/src/archetype.rs +++ b/crates/bevy_ecs/src/archetype.rs @@ -44,6 +44,8 @@ use std::{ pub struct ArchetypeRow(u32); impl ArchetypeRow { + /// Index indicating an invalid archetype row. + /// This is meant to be used as a placeholder. pub const INVALID: ArchetypeRow = ArchetypeRow(u32::MAX); /// Creates a `ArchetypeRow`. @@ -349,6 +351,7 @@ impl Archetype { self.table_id } + /// Fetches the entities contained in this archetype. #[inline] pub fn entities(&self) -> &[ArchetypeEntity] { &self.entities @@ -614,6 +617,8 @@ impl Archetypes { archetypes } + /// Returns the current archetype generation. This is an ID indicating the current set of archetypes + /// that are registered with the world. #[inline] pub fn generation(&self) -> ArchetypeGeneration { ArchetypeGeneration(self.archetypes.len()) @@ -719,6 +724,8 @@ impl Archetypes { }) } + /// Returns the number of components that are stored in archetypes. + /// Note that if some component `T` is stored in more than one archetype, it will be counted once for each archetype it's present in. #[inline] pub fn archetype_components_len(&self) -> usize { self.archetype_component_count diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 8ddf6e6ab9..f121e3429c 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -247,10 +247,16 @@ macro_rules! tuple_impl { all_tuples!(tuple_impl, 0, 15, B); +/// For a specific [`World`], this stores a unique value identifying a type of a registered [`Bundle`]. +/// +/// [`World`]: crate::world::World #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub struct BundleId(usize); impl BundleId { + /// Returns the index of the associated [`Bundle`] type. + /// + /// Note that this is unique per-world, and should not be reused across them. #[inline] pub fn index(self) -> usize { self.0 @@ -269,6 +275,9 @@ impl SparseSetIndex for BundleId { } } +/// Stores metadata associated with a specific type of [`Bundle`] for a given [`World`]. +/// +/// [`World`]: crate::world::World pub struct BundleInfo { id: BundleId, // SAFETY: Every ID in this list must be valid within the World that owns the BundleInfo, @@ -324,11 +333,13 @@ impl BundleInfo { BundleInfo { id, component_ids } } + /// Returns a value identifying the associated [`Bundle`] type. #[inline] pub const fn id(&self) -> BundleId { self.id } + /// Returns the [ID](ComponentId) of each component stored in this bundle. #[inline] pub fn components(&self) -> &[ComponentId] { &self.component_ids @@ -782,6 +793,7 @@ impl<'a, 'b> BundleSpawner<'a, 'b> { } } +/// Metadata for bundles. Stores a [`BundleInfo`] for each type of [`Bundle`] in a given world. #[derive(Default)] pub struct Bundles { bundle_infos: Vec, @@ -794,11 +806,16 @@ pub struct Bundles { } impl Bundles { + /// Gets the metadata associated with a specific type of bundle. + /// Returns `None` if the bundle is not registered with the world. #[inline] pub fn get(&self, bundle_id: BundleId) -> Option<&BundleInfo> { self.bundle_infos.get(bundle_id.index()) } + /// Gets the value identifying a specific type of bundle. + /// Returns `None` if the bundle does not exist in the world, + /// or if `type_id` does not correspond to a type of bundle. #[inline] pub fn get_id(&self, type_id: TypeId) -> Option { self.bundle_ids.get(&type_id).cloned() diff --git a/crates/bevy_ecs/src/change_detection.rs b/crates/bevy_ecs/src/change_detection.rs index 09efcf5c91..b66a098c30 100644 --- a/crates/bevy_ecs/src/change_detection.rs +++ b/crates/bevy_ecs/src/change_detection.rs @@ -401,7 +401,10 @@ pub struct Res<'w, T: ?Sized + Resource> { } impl<'w, T: Resource> Res<'w, T> { - // no it shouldn't clippy + /// Copies a reference to a resource. + /// + /// Note that unless you actually need an instance of `Res`, you should + /// prefer to just convert it to `&T` which can be freely copied. #[allow(clippy::should_implement_trait)] pub fn clone(this: &Self) -> Self { Self { @@ -539,6 +542,7 @@ pub struct Ref<'a, T: ?Sized> { } impl<'a, T: ?Sized> Ref<'a, T> { + /// Returns the reference wrapped by this type. The reference is allowed to outlive `self`, which makes this method more flexible than simply borrowing `self`. pub fn into_inner(self) -> &'a T { self.value } diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index f603bf9fe0..0183f34907 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -146,14 +146,23 @@ use std::{ /// [`SyncCell`]: bevy_utils::synccell::SyncCell /// [`Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html pub trait Component: Send + Sync + 'static { + /// A marker type indicating the storage type used for this component. + /// This must be either [`TableStorage`] or [`SparseStorage`]. type Storage: ComponentStorage; } +/// Marker type for components stored in a [`Table`](crate::storage::Table). pub struct TableStorage; + +/// Marker type for components stored in a [`ComponentSparseSet`](crate::storage::ComponentSparseSet). pub struct SparseStorage; +/// Types used to specify the storage strategy for a component. +/// +/// This trait is implemented for [`TableStorage`] and [`SparseStorage`]. +/// Custom implementations are forbidden. pub trait ComponentStorage: sealed::Sealed { - // because the trait is sealed, those items are private API. + /// A value indicating the storage strategy specified by this type. const STORAGE_TYPE: StorageType; } @@ -191,6 +200,7 @@ pub enum StorageType { SparseSet, } +/// Stores metadata for a type of component or resource stored in a specific [`World`]. #[derive(Debug)] pub struct ComponentInfo { id: ComponentId, @@ -198,21 +208,26 @@ pub struct ComponentInfo { } impl ComponentInfo { + /// Returns a value uniquely identifying the current component. #[inline] pub fn id(&self) -> ComponentId { self.id } + /// Returns the name of the current component. #[inline] pub fn name(&self) -> &str { &self.descriptor.name } + /// Returns the [`TypeId`] of the underlying component type. + /// Returns `None` if the component does not correspond to a Rust type. #[inline] pub fn type_id(&self) -> Option { self.descriptor.type_id } + /// Returns the layout used to store values of this component in memory. #[inline] pub fn layout(&self) -> Layout { self.descriptor.layout @@ -229,11 +244,15 @@ impl ComponentInfo { self.descriptor.drop } + /// Returns a value indicating the storage strategy for the current component. #[inline] pub fn storage_type(&self) -> StorageType { self.descriptor.storage_type } + /// Returns `true` if the underlying component type can be freely shared between threads. + /// If this returns `false`, then extra care must be taken to ensure that components + /// are not accessed from the wrong thread. #[inline] pub fn is_send_and_sync(&self) -> bool { self.descriptor.is_send_and_sync @@ -245,7 +264,7 @@ impl ComponentInfo { } } -/// A semi-opaque value which uniquely identifies the type of a [`Component`] within a +/// A value which uniquely identifies the type of a [`Component`] within a /// [`World`](crate::world::World). /// /// Each time a new `Component` type is registered within a `World` using @@ -266,11 +285,16 @@ impl ComponentInfo { pub struct ComponentId(usize); impl ComponentId { + /// Creates a new [`ComponentId`]. + /// + /// The `index` is a unique value associated with each type of component in a given world. + /// Usually, this value is taken from a counter incremented for each type of component registered with the world. #[inline] pub const fn new(index: usize) -> ComponentId { ComponentId(index) } + /// Returns the index of the current component. #[inline] pub fn index(self) -> usize { self.0 @@ -289,6 +313,7 @@ impl SparseSetIndex for ComponentId { } } +/// A value describing a component or resource, which may or may not correspond to a Rust type. pub struct ComponentDescriptor { name: Cow<'static, str>, // SAFETY: This must remain private. It must match the statically known StorageType of the @@ -384,22 +409,27 @@ impl ComponentDescriptor { } } + /// Returns a value indicating the storage strategy for the current component. #[inline] pub fn storage_type(&self) -> StorageType { self.storage_type } + /// Returns the [`TypeId`] of the underlying component type. + /// Returns `None` if the component does not correspond to a Rust type. #[inline] pub fn type_id(&self) -> Option { self.type_id } + /// Returns the name of the current component. #[inline] pub fn name(&self) -> &str { self.name.as_ref() } } +/// Stores metadata associated with each kind of [`Component`] in a given [`World`]. #[derive(Debug, Default)] pub struct Components { components: Vec, @@ -408,6 +438,9 @@ pub struct Components { } impl Components { + /// Initializes a component of type `T` with this instance. + /// If a component of this type has already been initialized, this will return + /// the ID of the pre-existing component. #[inline] pub fn init_component(&mut self, storages: &mut Storages) -> ComponentId { let type_id = TypeId::of::(); @@ -423,6 +456,12 @@ impl Components { ComponentId(*index) } + /// Initializes a component described by `descriptor`. + /// + /// ## Note + /// + /// If this method is called multiple times with identical descriptors, a distinct `ComponentId` + /// will be created for each one. pub fn init_component_with_descriptor( &mut self, storages: &mut Storages, @@ -447,26 +486,35 @@ impl Components { index } + /// Returns the number of components registered with this instance. #[inline] pub fn len(&self) -> usize { self.components.len() } + /// Returns `true` if there are no components registered with this instance. Otherwise, this returns `false`. #[inline] pub fn is_empty(&self) -> bool { self.components.len() == 0 } + /// Gets the metadata associated with the given component. + /// + /// This will return an incorrect result if `id` did not come from the same world as `self`. It may return `None` or a garbage value. #[inline] pub fn get_info(&self, id: ComponentId) -> Option<&ComponentInfo> { self.components.get(id.0) } + /// Returns the name associated with the given component. + /// + /// This will return an incorrect result if `id` did not come from the same world as `self`. It may return `None` or a garbage value. #[inline] pub fn get_name(&self, id: ComponentId) -> Option<&str> { self.get_info(id).map(|descriptor| descriptor.name()) } + /// Gets the metadata associated with the given component. /// # Safety /// /// `id` must be a valid [`ComponentId`] @@ -542,6 +590,9 @@ impl Components { self.get_resource_id(TypeId::of::()) } + /// Initializes a [`Resource`] of type `T` with this instance. + /// If a resource of this type has already been initialized, this will return + /// the ID of the pre-existing resource. #[inline] pub fn init_resource(&mut self) -> ComponentId { // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`] @@ -552,6 +603,9 @@ impl Components { } } + /// Initializes a [non-send resource](crate::system::NonSend) of type `T` with this instance. + /// If a resource of this type has already been initialized, this will return + /// the ID of the pre-existing resource. #[inline] pub fn init_non_send(&mut self) -> ComponentId { // SAFETY: The [`ComponentDescriptor`] matches the [`TypeId`] @@ -582,6 +636,7 @@ impl Components { ComponentId(*index) } + /// Gets an iterator over all components registered with this instance. pub fn iter(&self) -> impl Iterator + '_ { self.components.iter() } @@ -602,6 +657,7 @@ impl Tick { /// ticks are periodically scanned to ensure their relative values are below this. pub const MAX: Self = Self::new(MAX_CHANGE_AGE); + /// Creates a new [`Tick`] wrapping the given value. #[inline] pub const fn new(tick: u32) -> Self { Self { tick } @@ -659,10 +715,12 @@ impl Tick { } } -/// Wrapper around [`Tick`]s for a single component +/// Interior-mutable access to the [`Tick`]s for a single component or resource. #[derive(Copy, Clone, Debug)] pub struct TickCells<'a> { + /// The tick indicating when the value was added to the world. pub added: &'a UnsafeCell, + /// The tick indicating the last time the value was modified. pub changed: &'a UnsafeCell, } diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 38fecdbd51..a9a4f14759 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -717,8 +717,8 @@ impl Entities { } } - // Flushes all reserved entities to an "invalid" state. Attempting to retrieve them will return None - // unless they are later populated with a valid archetype. + /// Flushes all reserved entities to an "invalid" state. Attempting to retrieve them will return `None` + /// unless they are later populated with a valid archetype. pub fn flush_as_invalid(&mut self) { // SAFETY: as per `flush` safety docs, the archetype id can be set to [`ArchetypeId::INVALID`] if // the [`Entity`] has not been assigned to an [`Archetype`][crate::archetype::Archetype], which is the case here diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index 51365c8cb7..9c762edc6b 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -19,11 +19,15 @@ use std::{ /// Events must be thread-safe. pub trait Event: Send + Sync + 'static {} -/// An `EventId` uniquely identifies an event. +/// An `EventId` uniquely identifies an event stored in a specific [`World`]. /// /// An `EventId` can among other things be used to trace the flow of an event from the point it was /// sent to the point it was processed. +/// +/// [`World`]: crate::world::World pub struct EventId { + /// Uniquely identifies the event associated with this ID. + // This value corresponds to the order in which each event was added to the world. pub id: usize, _marker: PhantomData, } @@ -178,6 +182,7 @@ impl Default for Events { } impl Events { + /// Returns the index of the oldest event stored in the event buffer. pub fn oldest_event_count(&self) -> usize { self.events_a .start_event_count @@ -333,12 +338,17 @@ pub struct EventWriter<'w, E: Event> { } impl<'w, E: Event> EventWriter<'w, E> { - /// Sends an `event`. [`EventReader`]s can then read the event. + /// Sends an `event`, which can later be read by [`EventReader`]s. + /// /// See [`Events`] for details. pub fn send(&mut self, event: E) { self.events.send(event); } + /// Sends a list of `events` all at once, which can later be read by [`EventReader`]s. + /// This is more efficient than sending each event individually. + /// + /// See [`Events`] for details. pub fn send_batch(&mut self, events: impl IntoIterator) { self.events.extend(events); } @@ -352,6 +362,8 @@ impl<'w, E: Event> EventWriter<'w, E> { } } +/// Stores the state for an [`EventReader`]. +/// Access to the [`Events`] resource is required to read any incoming events. #[derive(Debug)] pub struct ManualEventReader { last_event_count: usize, @@ -412,6 +424,7 @@ impl ManualEventReader { } } +/// An iterator that yields any unread events from an [`EventReader`] or [`ManualEventReader`]. pub struct ManualEventIterator<'a, E: Event> { iter: ManualEventIteratorWithId<'a, E>, } @@ -448,6 +461,7 @@ impl<'a, E: Event> ExactSizeIterator for ManualEventIterator<'a, E> { } } +/// An iterator that yields any unread events (and their IDs) from an [`EventReader`] or [`ManualEventReader`]. #[derive(Debug)] pub struct ManualEventIteratorWithId<'a, E: Event> { reader: &'a mut ManualEventReader, @@ -456,6 +470,7 @@ pub struct ManualEventIteratorWithId<'a, E: Event> { } impl<'a, E: Event> ManualEventIteratorWithId<'a, E> { + /// Creates a new iterator that yields any `events` that have not yet been seen by `reader`. pub fn new(reader: &'a mut ManualEventReader, events: &'a Events) -> Self { let a_index = (reader.last_event_count).saturating_sub(events.events_a.start_event_count); let b_index = (reader.last_event_count).saturating_sub(events.events_b.start_event_count); @@ -606,12 +621,13 @@ impl Events { self.events_b.clear(); } + /// Returns the number of events currently stored in the event buffer. #[inline] pub fn len(&self) -> usize { self.events_a.len() + self.events_b.len() } - /// Returns true if there are no events in this collection. + /// Returns true if there are no events currently stored in the event buffer. #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 1ad0156801..62107a9f25 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -1,4 +1,5 @@ #![warn(clippy::undocumented_unsafe_blocks)] +#![warn(missing_docs)] #![allow(clippy::type_complexity)] #![doc = include_str!("../README.md")] diff --git a/crates/bevy_ecs/src/query/access.rs b/crates/bevy_ecs/src/query/access.rs index 706df3b8fd..18705af21e 100644 --- a/crates/bevy_ecs/src/query/access.rs +++ b/crates/bevy_ecs/src/query/access.rs @@ -302,6 +302,7 @@ impl FilteredAccess { self.filter_sets.append(&mut other.filter_sets.clone()); } + /// Adds all of the accesses from `other` to `self`. pub fn extend_access(&mut self, other: &FilteredAccess) { self.access.extend(&other.access); } @@ -502,6 +503,7 @@ impl FilteredAccessSet { self.add(filter); } + /// Adds all of the accesses from the passed set to `self`. pub fn extend(&mut self, filtered_access_set: FilteredAccessSet) { self.combined_access .extend(&filtered_access_set.combined_access); @@ -509,6 +511,7 @@ impl FilteredAccessSet { .extend(filtered_access_set.filtered_accesses); } + /// Removes all accesses stored in this set. pub fn clear(&mut self) { self.combined_access.clear(); self.filtered_accesses.clear(); diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index b1aa64ec16..4540909f61 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -419,9 +419,12 @@ pub unsafe trait WorldQuery { true } + /// Adds any component accesses used by this [`WorldQuery`] to `access`. // This does not have a default body of `{}` because 99% of cases need to add accesses // and forgetting to do so would be unsound. fn update_component_access(state: &Self::State, access: &mut FilteredAccess); + + /// For the given `archetype`, adds any component accessed used by this [`WorldQuery`] to `access`. // This does not have a default body of `{}` because 99% of cases need to add accesses // and forgetting to do so would be unsound. fn update_archetype_component_access( @@ -430,7 +433,10 @@ pub unsafe trait WorldQuery { access: &mut Access, ); + /// Creates and initializes a [`State`](WorldQuery::State) for this [`WorldQuery`] type. fn init_state(world: &mut World) -> Self::State; + + /// Returns `true` if this query matches a set of components. Otherwise, returns `false`. fn matches_component_set( state: &Self::State, set_contains_id: &impl Fn(ComponentId) -> bool, diff --git a/crates/bevy_ecs/src/query/mod.rs b/crates/bevy_ecs/src/query/mod.rs index 8b665219b4..1c6185e4e8 100644 --- a/crates/bevy_ecs/src/query/mod.rs +++ b/crates/bevy_ecs/src/query/mod.rs @@ -1,3 +1,5 @@ +//! Contains APIs for retrieving component data from the world. + mod access; mod fetch; mod filter; diff --git a/crates/bevy_ecs/src/query/par_iter.rs b/crates/bevy_ecs/src/query/par_iter.rs index 4d3393c8f0..77353bfb11 100644 --- a/crates/bevy_ecs/src/query/par_iter.rs +++ b/crates/bevy_ecs/src/query/par_iter.rs @@ -54,16 +54,19 @@ impl BatchingStrategy { } } + /// Configures the minimum allowed batch size of this instance. pub const fn min_batch_size(mut self, batch_size: usize) -> Self { self.batch_size_limits.start = batch_size; self } + /// Configures the maximum allowed batch size of this instance. pub const fn max_batch_size(mut self, batch_size: usize) -> Self { self.batch_size_limits.end = batch_size; self } + /// Configures the number of batches to assign to each thread for this instance. pub fn batches_per_thread(mut self, batches_per_thread: usize) -> Self { assert!( batches_per_thread > 0, diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index b5ccf8263e..87ea0854df 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -145,7 +145,7 @@ impl QueryState { /// /// # Panics /// - /// Panics if the `world.id()` does not equal the current [`QueryState`] internal id. + /// If `world` does not match the one used to call `QueryState::new` for this instance. pub fn update_archetypes(&mut self, world: &World) { self.validate_world(world); let archetypes = world.archetypes(); @@ -158,6 +158,12 @@ impl QueryState { } } + /// # Panics + /// + /// If `world` does not match the one used to call `QueryState::new` for this instance. + /// + /// Many unsafe query methods require the world to match for soundness. This function is the easiest + /// way of ensuring that it matches. #[inline] pub fn validate_world(&self, world: &World) { assert!( @@ -337,6 +343,17 @@ impl QueryState { } } + /// Gets the query result for the given [`World`] and [`Entity`]. + /// + /// This method is slightly more efficient than [`QueryState::get`] in some situations, since + /// it does not update this instance's internal cache. This method will return an error if `entity` + /// belongs to an archetype that has not been cached. + /// + /// To ensure that the cache is up to date, call [`QueryState::update_archetypes`] before this method. + /// The cache is also updated in [`QueryState::new`], `QueryState::get`, or any method with mutable + /// access to `self`. + /// + /// This can only be called for read-only queries, see [`Self::get_mut`] for mutable queries. #[inline] pub fn get_manual<'w>( &self, diff --git a/crates/bevy_ecs/src/reflect.rs b/crates/bevy_ecs/src/reflect.rs index 3f556c0700..cebe950b2b 100644 --- a/crates/bevy_ecs/src/reflect.rs +++ b/crates/bevy_ecs/src/reflect.rs @@ -410,6 +410,11 @@ impl FromType for ReflectResource { impl_reflect_value!((in bevy_ecs) Entity(Hash, PartialEq, Serialize, Deserialize)); impl_from_reflect_value!(Entity); +/// For a specific type of component, this maps any fields with values of type [`Entity`] to a new world. +/// Since a given `Entity` ID is only valid for the world it came frome, when performing deserialization +/// any stored IDs need to be re-allocated in the destination world. +/// +/// See [`MapEntities`] for more information. #[derive(Clone)] pub struct ReflectMapEntities { map_all_entities: fn(&mut World, &mut EntityMapper), diff --git a/crates/bevy_ecs/src/removal_detection.rs b/crates/bevy_ecs/src/removal_detection.rs index 0619752b89..81146371ad 100644 --- a/crates/bevy_ecs/src/removal_detection.rs +++ b/crates/bevy_ecs/src/removal_detection.rs @@ -65,24 +65,27 @@ impl DerefMut for RemovedComponentReader { } } -/// Wrapper around a map of components to [`Events`]. -/// So that we can find the events without naming the type directly. +/// Stores the [`RemovedComponents`] event buffers for all types of component in a given [`World`]. #[derive(Default, Debug)] pub struct RemovedComponentEvents { event_sets: SparseSet>, } impl RemovedComponentEvents { + /// Creates an empty storage buffer for component removal events. pub fn new() -> Self { Self::default() } + /// For each type of component, swaps the event buffers and clears the oldest event buffer. + /// In general, this should be called once per frame/update. pub fn update(&mut self) { for (_component_id, events) in self.event_sets.iter_mut() { events.update(); } } + /// Gets the event storage for a given component. pub fn get( &self, component_id: impl Into, @@ -90,6 +93,7 @@ impl RemovedComponentEvents { self.event_sets.get(component_id.into()) } + /// Sends a removal event for the specified component. pub fn send(&mut self, component_id: impl Into, entity: Entity) { self.event_sets .get_or_insert_with(component_id.into(), Default::default) diff --git a/crates/bevy_ecs/src/schedule/condition.rs b/crates/bevy_ecs/src/schedule/condition.rs index 8ff15f116b..539006c3d2 100644 --- a/crates/bevy_ecs/src/schedule/condition.rs +++ b/crates/bevy_ecs/src/schedule/condition.rs @@ -8,6 +8,7 @@ use crate::system::{CombinatorSystem, Combine, IntoSystem, ReadOnlySystem, Syste use crate::world::unsafe_world_cell::UnsafeWorldCell; use crate::world::World; +/// A type-erased run condition stored in a [`Box`]. pub type BoxedCondition = Box>; /// A system that determines if one or more scheduled systems should run. @@ -178,6 +179,7 @@ mod sealed { } } +/// A collection of [run conditions](Condition) that may be useful in any bevy app. pub mod common_conditions { use std::borrow::Cow; diff --git a/crates/bevy_ecs/src/schedule/config.rs b/crates/bevy_ecs/src/schedule/config.rs index 74cf880c58..bc9a687811 100644 --- a/crates/bevy_ecs/src/schedule/config.rs +++ b/crates/bevy_ecs/src/schedule/config.rs @@ -48,6 +48,7 @@ impl IntoSystemConfigs<()> for BoxedSystem<(), ()> { } } +/// Stores configuration for a single system. pub struct SystemConfig { pub(crate) system: BoxedSystem, pub(crate) graph_info: GraphInfo, @@ -56,9 +57,13 @@ pub struct SystemConfig { /// A collection of [`SystemConfig`]. pub enum SystemConfigs { + /// Configuration for a single system. SystemConfig(SystemConfig), + /// Configuration for a tuple of nested `SystemConfigs` instances. Configs { + /// Configuration for each element of the tuple. configs: Vec, + /// Run conditions applied to everything in the tuple. collective_conditions: Vec, /// If `true`, adds `before -> after` ordering constraints between the successive elements. chained: bool, @@ -381,6 +386,7 @@ impl IntoSystemConfigs<()> for SystemConfigs { } } +#[doc(hidden)] pub struct SystemConfigTupleMarker; macro_rules! impl_system_collection { diff --git a/crates/bevy_ecs/src/schedule/executor/mod.rs b/crates/bevy_ecs/src/schedule/executor/mod.rs index 2e14d41500..ffc4ca1bd7 100644 --- a/crates/bevy_ecs/src/schedule/executor/mod.rs +++ b/crates/bevy_ecs/src/schedule/executor/mod.rs @@ -62,6 +62,7 @@ pub struct SystemSchedule { } impl SystemSchedule { + /// Creates an empty [`SystemSchedule`]. pub const fn new() -> Self { Self { systems: Vec::new(), diff --git a/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs b/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs index 9824393c4f..e046e9d1ac 100644 --- a/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs +++ b/crates/bevy_ecs/src/schedule/executor/multi_threaded.rs @@ -256,6 +256,9 @@ impl SystemExecutor for MultiThreadedExecutor { } impl MultiThreadedExecutor { + /// Creates a new multi-threaded executor for use with a [`Schedule`]. + /// + /// [`Schedule`]: crate::schedule::Schedule pub fn new() -> Self { let (sender, receiver) = async_channel::unbounded(); Self { @@ -735,6 +738,7 @@ impl Default for MainThreadExecutor { } impl MainThreadExecutor { + /// Creates a new executor that can be used to run systems on the main thread. pub fn new() -> Self { MainThreadExecutor(TaskPool::get_thread_executor()) } diff --git a/crates/bevy_ecs/src/schedule/executor/simple.rs b/crates/bevy_ecs/src/schedule/executor/simple.rs index 47f4eb7ff5..e256064ff7 100644 --- a/crates/bevy_ecs/src/schedule/executor/simple.rs +++ b/crates/bevy_ecs/src/schedule/executor/simple.rs @@ -98,6 +98,8 @@ impl SystemExecutor for SimpleExecutor { } impl SimpleExecutor { + /// Creates a new simple executor for use in a [`Schedule`](crate::schedule::Schedule). + /// This calls each system in order and immediately calls [`System::apply_deferred`](crate::system::System::apply_deferred). pub const fn new() -> Self { Self { evaluated_sets: FixedBitSet::new(), diff --git a/crates/bevy_ecs/src/schedule/executor/single_threaded.rs b/crates/bevy_ecs/src/schedule/executor/single_threaded.rs index 9f3d7a2bb3..ab950c0e5c 100644 --- a/crates/bevy_ecs/src/schedule/executor/single_threaded.rs +++ b/crates/bevy_ecs/src/schedule/executor/single_threaded.rs @@ -116,6 +116,9 @@ impl SystemExecutor for SingleThreadedExecutor { } impl SingleThreadedExecutor { + /// Creates a new single-threaded executor for use in a [`Schedule`]. + /// + /// [`Schedule`]: crate::schedule::Schedule pub const fn new() -> Self { Self { evaluated_sets: FixedBitSet::new(), diff --git a/crates/bevy_ecs/src/schedule/graph_utils.rs b/crates/bevy_ecs/src/schedule/graph_utils.rs index 4a0311c8be..26b0a076fc 100644 --- a/crates/bevy_ecs/src/schedule/graph_utils.rs +++ b/crates/bevy_ecs/src/schedule/graph_utils.rs @@ -8,10 +8,14 @@ use fixedbitset::FixedBitSet; use crate::schedule::set::*; -/// Unique identifier for a system or system set. +/// Unique identifier for a system or system set stored in a [`ScheduleGraph`]. +/// +/// [`ScheduleGraph`]: super::ScheduleGraph #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum NodeId { + /// Identifier for a system. System(usize), + /// Identifier for a system set. Set(usize), } diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index 05aaba9f8b..7bb8ef7f66 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -1,3 +1,5 @@ +//! Contains APIs for ordering systems and executing them on a [`World`](crate::world::World) + mod condition; mod config; mod executor; diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index e6aa0eca0d..93f0d9232a 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -399,6 +399,7 @@ pub struct ScheduleGraph { } impl ScheduleGraph { + /// Creates an empty [`ScheduleGraph`] with default settings. pub fn new() -> Self { Self { systems: Vec::new(), @@ -1569,6 +1570,8 @@ impl Default for ScheduleBuildSettings { } impl ScheduleBuildSettings { + /// Default build settings. + /// See the field-level documentation for the default value of each field. pub const fn new() -> Self { Self { ambiguity_detection: LogLevel::Ignore, diff --git a/crates/bevy_ecs/src/schedule/set.rs b/crates/bevy_ecs/src/schedule/set.rs index 590dfc6ee6..c34745b9f3 100644 --- a/crates/bevy_ecs/src/schedule/set.rs +++ b/crates/bevy_ecs/src/schedule/set.rs @@ -14,7 +14,9 @@ use crate::system::{ define_boxed_label!(ScheduleLabel); +/// A shorthand for `Box`. pub type BoxedSystemSet = Box; +/// A shorthand for `Box`. pub type BoxedScheduleLabel = Box; /// Types that identify logical groups of systems. @@ -132,8 +134,10 @@ impl SystemSet for AnonymousSet { /// Types that can be converted into a [`SystemSet`]. pub trait IntoSystemSet: Sized { + /// The type of [`SystemSet`] this instance converts into. type Set: SystemSet; + /// Converts this instance to its associated [`SystemSet`] type. fn into_system_set(self) -> Self::Set; } diff --git a/crates/bevy_ecs/src/schedule/state.rs b/crates/bevy_ecs/src/schedule/state.rs index 27141d05fc..1c7c5f53e8 100644 --- a/crates/bevy_ecs/src/schedule/state.rs +++ b/crates/bevy_ecs/src/schedule/state.rs @@ -37,6 +37,7 @@ pub use bevy_ecs_macros::States; /// /// ``` pub trait States: 'static + Send + Sync + Clone + PartialEq + Eq + Hash + Debug + Default { + /// The type returned when iterating over all [`variants`](States::variants) of this type. type Iter: Iterator; /// Returns an iterator over all the state variants. diff --git a/crates/bevy_ecs/src/storage/sparse_set.rs b/crates/bevy_ecs/src/storage/sparse_set.rs index 32941e277d..4d318d1a46 100644 --- a/crates/bevy_ecs/src/storage/sparse_set.rs +++ b/crates/bevy_ecs/src/storage/sparse_set.rs @@ -539,7 +539,9 @@ impl SparseSet { /// zero), as the number of bits needed to represent a `SparseSetIndex` in a `FixedBitSet` /// is proportional to the **value** of those `usize`. pub trait SparseSetIndex: Clone + PartialEq + Eq + Hash { + /// Gets the sparse set index corresponding to this instance. fn sparse_set_index(&self) -> usize; + /// Creates a new instance of this type with the specified index. fn get_sparse_set_index(value: usize) -> Self; } diff --git a/crates/bevy_ecs/src/system/combinator.rs b/crates/bevy_ecs/src/system/combinator.rs index 3461de257d..4a96296c82 100644 --- a/crates/bevy_ecs/src/system/combinator.rs +++ b/crates/bevy_ecs/src/system/combinator.rs @@ -113,6 +113,9 @@ pub struct CombinatorSystem { } impl CombinatorSystem { + /// Creates a new system that combines two inner systems. + /// + /// The returned system will only be usable if `Func` implements [`Combine`]. pub const fn new(a: A, b: B, name: Cow<'static, str>) -> Self { Self { _marker: PhantomData, diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index d429ccd100..c7b9c3c8c7 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -43,6 +43,7 @@ use super::{Deferred, Resource, SystemBuffer, SystemMeta}; /// } /// ``` pub trait Command: Send + 'static { + /// Executes this command. fn write(self, world: &mut World); } @@ -603,6 +604,7 @@ impl<'w, 's> Commands<'w, 's> { /// } /// ``` pub trait EntityCommand: Send + 'static { + /// Executes this command for the given [`Entity`]. fn write(self, id: Entity, world: &mut World); /// Returns a [`Command`] which executes this [`EntityCommand`] for the given [`Entity`]. fn with_entity(self, id: Entity) -> WithEntity @@ -857,11 +859,15 @@ where } } +/// A [`Command`] that consumes an iterator of [`Bundle`]s to spawn a series of entities. +/// +/// This is more efficient than spawning the entities individually. pub struct SpawnBatch where I: IntoIterator, I::Item: Bundle, { + /// The iterator that returns the [`Bundle`]s which will be added to each newly-spawned entity. pub bundles_iter: I, } @@ -875,12 +881,17 @@ where } } +/// A [`Command`] that consumes an iterator to add a series of [`Bundle`]s to a set of entities. +/// If any entities do not already exist in the world, they will be spawned. +/// +/// This is more efficient than inserting the bundles individually. pub struct InsertOrSpawnBatch where I: IntoIterator + Send + Sync + 'static, B: Bundle, I::IntoIter: Iterator, { + /// The iterator that returns each [entity ID](Entity) and corresponding [`Bundle`]. pub bundles_iter: I, } @@ -902,8 +913,10 @@ where } /// A [`Command`] that despawns a specific entity. +/// This will emit a warning if the entity does not exist. #[derive(Debug)] pub struct Despawn { + /// The entity that will be despawned. pub entity: Entity, } @@ -939,6 +952,7 @@ where /// Any components in the bundle that aren't found on the entity will be ignored. #[derive(Debug)] pub struct Remove { + /// The entity from which the components will be removed. pub entity: Entity, _marker: PhantomData, } @@ -987,6 +1001,7 @@ impl InitResource { /// A [`Command`] that inserts a [`Resource`] into the world. pub struct InsertResource { + /// The resource that will be added to the world. pub resource: R, } diff --git a/crates/bevy_ecs/src/system/commands/parallel_scope.rs b/crates/bevy_ecs/src/system/commands/parallel_scope.rs index 79abf776f5..65b01a8f21 100644 --- a/crates/bevy_ecs/src/system/commands/parallel_scope.rs +++ b/crates/bevy_ecs/src/system/commands/parallel_scope.rs @@ -62,6 +62,9 @@ impl SystemBuffer for ParallelCommandQueue { } impl<'w, 's> ParallelCommands<'w, 's> { + /// Temporarily provides access to the [`Commands`] for the current thread. + /// + /// For an example, see the type-level documentation for [`ParallelCommands`]. pub fn command_scope(&self, f: impl FnOnce(Commands) -> R) -> R { let store = &self.state.thread_local_storage; let command_queue_cell = store.get_or_default(); diff --git a/crates/bevy_ecs/src/system/exclusive_function_system.rs b/crates/bevy_ecs/src/system/exclusive_function_system.rs index 66d95084d2..6d2a31f554 100644 --- a/crates/bevy_ecs/src/system/exclusive_function_system.rs +++ b/crates/bevy_ecs/src/system/exclusive_function_system.rs @@ -29,6 +29,8 @@ where marker: PhantomData Marker>, } +/// A marker type used to distinguish exclusive function systems from regular function systems. +#[doc(hidden)] pub struct IsExclusiveFunctionSystem; impl IntoSystem for F diff --git a/crates/bevy_ecs/src/system/exclusive_system_param.rs b/crates/bevy_ecs/src/system/exclusive_system_param.rs index 9f7ccb5ae9..5bc49b68fa 100644 --- a/crates/bevy_ecs/src/system/exclusive_system_param.rs +++ b/crates/bevy_ecs/src/system/exclusive_system_param.rs @@ -7,15 +7,26 @@ use crate::{ use bevy_utils::all_tuples; use bevy_utils::synccell::SyncCell; +/// A parameter that can be used in an exclusive system (a system with an `&mut World` parameter). +/// Any parameters implementing this trait must come after the `&mut World` parameter. pub trait ExclusiveSystemParam: Sized { + /// Used to store data which persists across invocations of a system. type State: Send + Sync + 'static; + /// The item type returned when constructing this system param. + /// See [`SystemParam::Item`]. type Item<'s>: ExclusiveSystemParam; + /// Creates a new instance of this param's [`State`](Self::State). fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; + /// Creates a parameter to be passed into an [`ExclusiveSystemParamFunction`]. + /// + /// [`ExclusiveSystemParamFunction`]: super::ExclusiveSystemParamFunction fn get_param<'s>(state: &'s mut Self::State, system_meta: &SystemMeta) -> Self::Item<'s>; } +/// Shorthand way of accessing the associated type [`ExclusiveSystemParam::Item`] +/// for a given [`ExclusiveSystemParam`]. pub type ExclusiveSystemParamItem<'s, P> =

::Item<'s>; impl<'a, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParam diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 376a407e7f..1e4647389a 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -152,6 +152,13 @@ pub struct SystemState { } impl SystemState { + /// Creates a new [`SystemState`] with default state. + /// + /// ## Note + /// For users of [`SystemState::get_manual`] or [`get_manual_mut`](SystemState::get_manual_mut): + /// + /// `new` does not cache any of the world's archetypes, so you must call [`SystemState::update_archetypes`] + /// manually before calling `get_manual{_mut}`. pub fn new(world: &mut World) -> Self { let mut meta = SystemMeta::new::(); meta.last_run = world.change_tick().relative_to(Tick::MAX); @@ -164,6 +171,7 @@ impl SystemState { } } + /// Gets the metadata for this instance. #[inline] pub fn meta(&self) -> &SystemMeta { &self.meta @@ -198,6 +206,8 @@ impl SystemState { Param::apply(&mut self.param_state, &self.meta, world); } + /// Returns `true` if `world` is the same one that was used to call [`SystemState::new`]. + /// Otherwise, this returns false. #[inline] pub fn matches_world(&self, world: &World) -> bool { self.world_id == world.id() @@ -350,6 +360,8 @@ where } } +/// A marker type used to distinguish regular function systems from exclusive function systems. +#[doc(hidden)] pub struct IsFunctionSystem; impl IntoSystem for F diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index 942157a0ca..1bf773eb99 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -208,7 +208,9 @@ where // because Rust thinks a type could impl multiple different `FnMut` combinations // even though none can currently pub trait IntoSystem: Sized { + /// The type of [`System`] that this instance converts into. type System: System; + /// Turns this value into its corresponding [`System`]. fn into_system(this: Self) -> Self::System; diff --git a/crates/bevy_ecs/src/system/system.rs b/crates/bevy_ecs/src/system/system.rs index b9e246842f..01b2c711d8 100644 --- a/crates/bevy_ecs/src/system/system.rs +++ b/crates/bevy_ecs/src/system/system.rs @@ -62,6 +62,8 @@ pub trait System: Send + Sync + 'static { unsafe { self.run_unsafe(input, world) } } /// Applies any [`Deferred`](crate::system::Deferred) system parameters (or other system buffers) of this system to the world. + /// + /// This is where [`Commands`](crate::system::Commands) get applied. fn apply_deferred(&mut self, world: &mut World); /// Initialize the system. fn initialize(&mut self, _world: &mut World); @@ -71,6 +73,10 @@ pub trait System: Send + Sync + 'static { /// `world` may only be used to access metadata. This can be done in safe code /// via functions such as [`UnsafeWorldCell::archetypes`]. fn update_archetype_component_access(&mut self, world: UnsafeWorldCell); + /// Checks any [`Tick`]s stored on this system and wraps their value if they get too old. + /// + /// This method must be called periodically to ensure that change detection behaves correctly. + /// When using bevy's default configuration, this will be called for you as needed. fn check_change_tick(&mut self, change_tick: Tick); /// Returns the system's default [system sets](crate::schedule::SystemSet). fn default_system_sets(&self) -> Vec> { diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 41e541ee66..023657bcd9 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -125,6 +125,10 @@ pub unsafe trait SystemParam: Sized { #[allow(unused_variables)] fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {} + /// Creates a parameter to be passed into a [`SystemParamFunction`]. + /// + /// [`SystemParamFunction`]: super::SystemParamFunction + /// /// # Safety /// /// - The passed [`UnsafeWorldCell`] must have access to any world data @@ -1307,6 +1311,7 @@ pub struct SystemName<'s> { } impl<'s> SystemName<'s> { + /// Gets the name of the system. pub fn name(&self) -> &str { self.name } @@ -1413,12 +1418,23 @@ macro_rules! impl_system_param_tuple { all_tuples!(impl_system_param_tuple, 0, 16, P); +/// Contains type aliases for built-in [`SystemParam`]s with `'static` lifetimes. +/// This can make it more convenient to refer to these types in contexts where +/// explicit lifetime annotations are required. +/// +/// [`SystemParam`]: super::SystemParam pub mod lifetimeless { + /// A [`Query`](super::Query) with `'static` lifetimes. pub type SQuery = super::Query<'static, 'static, Q, F>; + /// A shorthand for writing `&'static T`. pub type Read = &'static T; + /// A shorthand for writing `&'static mut T`. pub type Write = &'static mut T; + /// A [`Res`](super::Res) with `'static` lifetimes. pub type SRes = super::Res<'static, T>; + /// A [`ResMut`](super::ResMut) with `'static` lifetimes. pub type SResMut = super::ResMut<'static, T>; + /// [`Commands`](crate::system::Commands) with `'static` lifetimes. pub type SCommands = crate::system::Commands<'static, 'static>; } diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 39e5b8e40f..c97d9a2148 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -49,44 +49,72 @@ impl<'w> EntityRef<'w> { ) } + /// Returns the [ID](Entity) of the current entity. #[inline] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] pub fn id(&self) -> Entity { self.entity } + /// Gets metadata indicating the location where the current entity is stored. #[inline] pub fn location(&self) -> EntityLocation { self.location } + /// Returns the archetype that the current entity belongs to. #[inline] pub fn archetype(&self) -> &Archetype { &self.world.archetypes[self.location.archetype_id] } + /// Gets read-only access to the world that the current entity belongs to. #[inline] pub fn world(&self) -> &'w World { self.world } + /// Returns `true` if the current entity has a component of type `T`. + /// Otherwise, this returns `false`. + /// + /// ## Notes + /// + /// If you do not know the concrete type of a component, consider using + /// [`Self::contains_id`] or [`Self::contains_type_id`]. #[inline] pub fn contains(&self) -> bool { self.contains_type_id(TypeId::of::()) } + /// Returns `true` if the current entity has a component identified by `component_id`. + /// Otherwise, this returns false. + /// + /// ## Notes + /// + /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. + /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using + /// [`Self::contains_type_id`]. #[inline] pub fn contains_id(&self, component_id: ComponentId) -> bool { self.as_unsafe_world_cell_readonly() .contains_id(component_id) } + /// Returns `true` if the current entity has a component with the type identified by `type_id`. + /// Otherwise, this returns false. + /// + /// ## Notes + /// + /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. + /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`]. #[inline] pub fn contains_type_id(&self, type_id: TypeId) -> bool { self.as_unsafe_world_cell_readonly() .contains_type_id(type_id) } + /// Gets access to the component of type `T` for the current entity. + /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get(&self) -> Option<&'w T> { // SAFETY: &self implies shared access for duration of returned value @@ -186,45 +214,74 @@ impl<'w> EntityMut<'w> { } } + /// Returns the [ID](Entity) of the current entity. #[inline] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] pub fn id(&self) -> Entity { self.entity } + /// Gets metadata indicating the location where the current entity is stored. #[inline] pub fn location(&self) -> EntityLocation { self.location } + /// Returns the archetype that the current entity belongs to. #[inline] pub fn archetype(&self) -> &Archetype { &self.world.archetypes[self.location.archetype_id] } + /// Returns `true` if the current entity has a component of type `T`. + /// Otherwise, this returns `false`. + /// + /// ## Notes + /// + /// If you do not know the concrete type of a component, consider using + /// [`Self::contains_id`] or [`Self::contains_type_id`]. #[inline] pub fn contains(&self) -> bool { self.contains_type_id(TypeId::of::()) } + /// Returns `true` if the current entity has a component identified by `component_id`. + /// Otherwise, this returns false. + /// + /// ## Notes + /// + /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. + /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using + /// [`Self::contains_type_id`]. #[inline] pub fn contains_id(&self, component_id: ComponentId) -> bool { self.as_unsafe_world_cell_readonly() .contains_id(component_id) } + /// Returns `true` if the current entity has a component with the type identified by `type_id`. + /// Otherwise, this returns false. + /// + /// ## Notes + /// + /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. + /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`]. #[inline] pub fn contains_type_id(&self, type_id: TypeId) -> bool { self.as_unsafe_world_cell_readonly() .contains_type_id(type_id) } + /// Gets access to the component of type `T` for the current entity. + /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get(&self) -> Option<&'_ T> { // SAFETY: &self implies shared access for duration of returned value unsafe { self.as_unsafe_world_cell_readonly().get::() } } + /// Gets mutable access to the component of type `T` for the current entity. + /// Returns `None` if the entity does not have a component of type `T`. #[inline] pub fn get_mut(&mut self) -> Option> { // SAFETY: &mut self implies exclusive access for duration of returned value @@ -580,6 +637,7 @@ impl<'w> EntityMut<'w> { self } + /// Despawns the current entity. pub fn despawn(self) { debug!("Despawning entity {:?}", self.entity); let world = self.world; @@ -645,6 +703,7 @@ impl<'w> EntityMut<'w> { } } + /// Gets read-only access to the world that the current entity belongs to. #[inline] pub fn world(&self) -> &World { self.world @@ -663,7 +722,7 @@ impl<'w> EntityMut<'w> { self.world } - /// Return this `EntityMut`'s [`World`], consuming itself. + /// Returns this `EntityMut`'s [`World`], consuming itself. #[inline] pub fn into_world_mut(self) -> &'w mut World { self.world diff --git a/crates/bevy_ecs/src/world/error.rs b/crates/bevy_ecs/src/world/error.rs index a6197ac44c..f3794bb03d 100644 --- a/crates/bevy_ecs/src/world/error.rs +++ b/crates/bevy_ecs/src/world/error.rs @@ -1,3 +1,5 @@ +//! Contains error types returned by bevy's schedule. + use thiserror::Error; use crate::schedule::BoxedScheduleLabel; diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 84a262e599..1e4598e1d7 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1,3 +1,5 @@ +//! Defines the [`World`] and APIs for accessing it directly. + mod entity_ref; pub mod error; mod spawn_batch; @@ -941,6 +943,13 @@ impl World { .unwrap_or(false) } + /// Return's `true` if a resource of type `R` exists and was added since the world's + /// [`last_change_tick`](World::last_change_tick()). Otherwise, this return's `false`. + /// + /// This means that: + /// - When called from an exclusive system, this will check for additions since the system last ran. + /// - When called elsewhere, this will check for additions since the last time that [`World::clear_trackers`] + /// was called. pub fn is_resource_added(&self) -> bool { self.components .get_resource_id(TypeId::of::()) @@ -949,6 +958,13 @@ impl World { .unwrap_or(false) } + /// Return's `true` if a resource of type `R` exists and was modified since the world's + /// [`last_change_tick`](World::last_change_tick()). Otherwise, this return's `false`. + /// + /// This means that: + /// - When called from an exclusive system, this will check for changes since the system last ran. + /// - When called elsewhere, this will check for changes since the last time that [`World::clear_trackers`] + /// was called. pub fn is_resource_changed(&self) -> bool { self.components .get_resource_id(TypeId::of::()) diff --git a/crates/bevy_ecs/src/world/spawn_batch.rs b/crates/bevy_ecs/src/world/spawn_batch.rs index 965ff97540..57cb10cbf2 100644 --- a/crates/bevy_ecs/src/world/spawn_batch.rs +++ b/crates/bevy_ecs/src/world/spawn_batch.rs @@ -5,6 +5,10 @@ use crate::{ }; use std::iter::FusedIterator; +/// An iterator that spawns a series of entities and returns the [ID](Entity) of +/// each spawned entity. +/// +/// If this iterator is not fully exhausted, any remaining entities will be spawned when this type is dropped. pub struct SpawnBatchIter<'w, I> where I: Iterator, diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index 9cbab05d27..997862981a 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -1,3 +1,5 @@ +//! Contains types that allow disjoint mutable access to a [`World`]. + #![warn(unsafe_op_in_unsafe_fn)] use super::{Mut, World, WorldId}; @@ -577,37 +579,63 @@ impl<'w> UnsafeEntityCell<'w> { } } + /// Returns the [ID](Entity) of the current entity. #[inline] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] pub fn id(self) -> Entity { self.entity } + /// Gets metadata indicating the location where the current entity is stored. #[inline] pub fn location(self) -> EntityLocation { self.location } + /// Returns the archetype that the current entity belongs to. #[inline] pub fn archetype(self) -> &'w Archetype { &self.world.archetypes()[self.location.archetype_id] } + /// Gets the world that the current entity belongs to. #[inline] pub fn world(self) -> UnsafeWorldCell<'w> { self.world } + /// Returns `true` if the current entity has a component of type `T`. + /// Otherwise, this returns `false`. + /// + /// ## Notes + /// + /// If you do not know the concrete type of a component, consider using + /// [`Self::contains_id`] or [`Self::contains_type_id`]. #[inline] pub fn contains(self) -> bool { self.contains_type_id(TypeId::of::()) } + /// Returns `true` if the current entity has a component identified by `component_id`. + /// Otherwise, this returns false. + /// + /// ## Notes + /// + /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. + /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using + /// [`Self::contains_type_id`]. #[inline] pub fn contains_id(self, component_id: ComponentId) -> bool { self.archetype().contains(component_id) } + /// Returns `true` if the current entity has a component with the type identified by `type_id`. + /// Otherwise, this returns false. + /// + /// ## Notes + /// + /// - If you know the concrete type of the component, you should prefer [`Self::contains`]. + /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`]. #[inline] pub fn contains_type_id(self, type_id: TypeId) -> bool { let id = match self.world.components().get_id(type_id) { diff --git a/crates/bevy_ecs/src/world/world_cell.rs b/crates/bevy_ecs/src/world/world_cell.rs index 73dabe387c..d97cdcac9f 100644 --- a/crates/bevy_ecs/src/world/world_cell.rs +++ b/crates/bevy_ecs/src/world/world_cell.rs @@ -91,6 +91,8 @@ impl<'w> Drop for WorldCell<'w> { } } +/// A read-only borrow of some data stored in a [`World`]. This type is returned by [`WorldCell`], +/// which uses run-time checks to ensure that the borrow does not violate Rust's aliasing rules. pub struct WorldBorrow<'w, T> { value: &'w T, archetype_component_id: ArchetypeComponentId, @@ -133,6 +135,8 @@ impl<'w, T> Drop for WorldBorrow<'w, T> { } } +/// A mutable borrow of some data stored in a [`World`]. This type is returned by [`WorldCell`], +/// which uses run-time checks to ensure that the borrow does not violate Rust's aliasing rules. pub struct WorldBorrowMut<'w, T> { value: Mut<'w, T>, archetype_component_id: ArchetypeComponentId,