Document every public item in bevy_ecs (#8731)

# Objective

Title.

---------

Co-authored-by: François <mockersf@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: James Liu <contact@jamessliu.com>
This commit is contained in:
JoJoJet 2023-06-10 19:23:48 -04:00 committed by GitHub
parent 50bc785c8a
commit 32faf4cb5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 374 additions and 14 deletions

View file

@ -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

View file

@ -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<BundleInfo>,
@ -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<BundleId> {
self.bundle_ids.get(&type_id).cloned()

View file

@ -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<T>`, 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
}

View file

@ -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<TypeId> {
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<TypeId> {
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<ComponentInfo>,
@ -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<T: Component>(&mut self, storages: &mut Storages) -> ComponentId {
let type_id = TypeId::of::<T>();
@ -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::<T>())
}
/// 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<T: 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<T: Any>(&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<Item = &ComponentInfo> + '_ {
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<Tick>,
/// The tick indicating the last time the value was modified.
pub changed: &'a UnsafeCell<Tick>,
}

View file

@ -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

View file

@ -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<E: Event> {
/// 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<E>,
}
@ -178,6 +182,7 @@ impl<E: Event> Default for Events<E> {
}
impl<E: Event> Events<E> {
/// 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<Item = E>) {
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<E>`] resource is required to read any incoming events.
#[derive(Debug)]
pub struct ManualEventReader<E: Event> {
last_event_count: usize,
@ -412,6 +424,7 @@ impl<E: Event> ManualEventReader<E> {
}
}
/// 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<E>,
@ -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<E>, events: &'a Events<E>) -> 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<E: Event> Events<E> {
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

View file

@ -1,4 +1,5 @@
#![warn(clippy::undocumented_unsafe_blocks)]
#![warn(missing_docs)]
#![allow(clippy::type_complexity)]
#![doc = include_str!("../README.md")]

View file

@ -302,6 +302,7 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
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<T>) {
self.access.extend(&other.access);
}
@ -502,6 +503,7 @@ impl<T: SparseSetIndex> FilteredAccessSet<T> {
self.add(filter);
}
/// Adds all of the accesses from the passed set to `self`.
pub fn extend(&mut self, filtered_access_set: FilteredAccessSet<T>) {
self.combined_access
.extend(&filtered_access_set.combined_access);
@ -509,6 +511,7 @@ impl<T: SparseSetIndex> FilteredAccessSet<T> {
.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();

View file

@ -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<ComponentId>);
/// 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<ArchetypeComponentId>,
);
/// 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,

View file

@ -1,3 +1,5 @@
//! Contains APIs for retrieving component data from the world.
mod access;
mod fetch;
mod filter;

View file

@ -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,

View file

@ -145,7 +145,7 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
///
/// # 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<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
}
}
/// # 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<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
}
}
/// 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,

View file

@ -410,6 +410,11 @@ impl<C: Resource + Reflect + FromWorld> FromType<C> 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),

View file

@ -65,24 +65,27 @@ impl<T: Component> DerefMut for RemovedComponentReader<T> {
}
}
/// Wrapper around a map of components to [`Events<RemovedComponentEntity>`].
/// 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<ComponentId, Events<RemovedComponentEntity>>,
}
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<ComponentId>,
@ -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<ComponentId>, entity: Entity) {
self.event_sets
.get_or_insert_with(component_id.into(), Default::default)

View file

@ -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<In = ()> = Box<dyn ReadOnlySystem<In = In, Out = bool>>;
/// 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;

View file

@ -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<SystemConfigs>,
/// Run conditions applied to everything in the tuple.
collective_conditions: Vec<BoxedCondition>,
/// 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 {

View file

@ -62,6 +62,7 @@ pub struct SystemSchedule {
}
impl SystemSchedule {
/// Creates an empty [`SystemSchedule`].
pub const fn new() -> Self {
Self {
systems: Vec::new(),

View file

@ -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())
}

View file

@ -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(),

View file

@ -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(),

View file

@ -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),
}

View file

@ -1,3 +1,5 @@
//! Contains APIs for ordering systems and executing them on a [`World`](crate::world::World)
mod condition;
mod config;
mod executor;

View file

@ -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,

View file

@ -14,7 +14,9 @@ use crate::system::{
define_boxed_label!(ScheduleLabel);
/// A shorthand for `Box<dyn SystemSet>`.
pub type BoxedSystemSet = Box<dyn SystemSet>;
/// A shorthand for `Box<dyn ScheduleLabel>`.
pub type BoxedScheduleLabel = Box<dyn ScheduleLabel>;
/// 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<Marker>: 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;
}

View file

@ -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<Item = Self>;
/// Returns an iterator over all the state variants.

View file

@ -539,7 +539,9 @@ impl<I: SparseSetIndex, V> SparseSet<I, V> {
/// 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;
}

View file

@ -113,6 +113,9 @@ pub struct CombinatorSystem<Func, A, B> {
}
impl<Func, A, B> CombinatorSystem<Func, A, B> {
/// Creates a new system that combines two inner systems.
///
/// The returned system will only be usable if `Func` implements [`Combine<A, B>`].
pub const fn new(a: A, b: B, name: Cow<'static, str>) -> Self {
Self {
_marker: PhantomData,

View file

@ -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<Self>
@ -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<I>
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<I, B>
where
I: IntoIterator + Send + Sync + 'static,
B: Bundle,
I::IntoIter: Iterator<Item = (Entity, B)>,
{
/// 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<T> {
/// The entity from which the components will be removed.
pub entity: Entity,
_marker: PhantomData<T>,
}
@ -987,6 +1001,7 @@ impl<R: Resource + FromWorld> InitResource<R> {
/// A [`Command`] that inserts a [`Resource`] into the world.
pub struct InsertResource<R: Resource> {
/// The resource that will be added to the world.
pub resource: R,
}

View file

@ -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<R>(&self, f: impl FnOnce(Commands) -> R) -> R {
let store = &self.state.thread_local_storage;
let command_queue_cell = store.get_or_default();

View file

@ -29,6 +29,8 @@ where
marker: PhantomData<fn() -> Marker>,
}
/// A marker type used to distinguish exclusive function systems from regular function systems.
#[doc(hidden)]
pub struct IsExclusiveFunctionSystem;
impl<Marker, F> IntoSystem<F::In, F::Out, (IsExclusiveFunctionSystem, Marker)> for F

View file

@ -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<State = Self::State>;
/// 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> = <P as ExclusiveSystemParam>::Item<'s>;
impl<'a, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParam

View file

@ -152,6 +152,13 @@ pub struct SystemState<Param: SystemParam + 'static> {
}
impl<Param: SystemParam> SystemState<Param> {
/// 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::<Param>();
meta.last_run = world.change_tick().relative_to(Tick::MAX);
@ -164,6 +171,7 @@ impl<Param: SystemParam> SystemState<Param> {
}
}
/// Gets the metadata for this instance.
#[inline]
pub fn meta(&self) -> &SystemMeta {
&self.meta
@ -198,6 +206,8 @@ impl<Param: SystemParam> SystemState<Param> {
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<Marker, F> IntoSystem<F::In, F::Out, (IsFunctionSystem, Marker)> for F

View file

@ -208,7 +208,9 @@ where
// because Rust thinks a type could impl multiple different `FnMut` combinations
// even though none can currently
pub trait IntoSystem<In, Out, Marker>: Sized {
/// The type of [`System`] that this instance converts into.
type System: System<In = In, Out = Out>;
/// Turns this value into its corresponding [`System`].
fn into_system(this: Self) -> Self::System;

View file

@ -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<Box<dyn crate::schedule::SystemSet>> {

View file

@ -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<Q, F = ()> = super::Query<'static, 'static, Q, F>;
/// A shorthand for writing `&'static T`.
pub type Read<T> = &'static T;
/// A shorthand for writing `&'static mut T`.
pub type Write<T> = &'static mut T;
/// A [`Res`](super::Res) with `'static` lifetimes.
pub type SRes<T> = super::Res<'static, T>;
/// A [`ResMut`](super::ResMut) with `'static` lifetimes.
pub type SResMut<T> = super::ResMut<'static, T>;
/// [`Commands`](crate::system::Commands) with `'static` lifetimes.
pub type SCommands = crate::system::Commands<'static, 'static>;
}

View file

@ -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<T: Component>(&self) -> bool {
self.contains_type_id(TypeId::of::<T>())
}
/// 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<T: Component>(&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<T: Component>(&self) -> bool {
self.contains_type_id(TypeId::of::<T>())
}
/// 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<T: Component>(&self) -> Option<&'_ T> {
// SAFETY: &self implies shared access for duration of returned value
unsafe { self.as_unsafe_world_cell_readonly().get::<T>() }
}
/// 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<T: Component>(&mut self) -> Option<Mut<'_, T>> {
// 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

View file

@ -1,3 +1,5 @@
//! Contains error types returned by bevy's schedule.
use thiserror::Error;
use crate::schedule::BoxedScheduleLabel;

View file

@ -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<R: Resource>(&self) -> bool {
self.components
.get_resource_id(TypeId::of::<R>())
@ -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<R: Resource>(&self) -> bool {
self.components
.get_resource_id(TypeId::of::<R>())

View file

@ -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,

View file

@ -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<T: Component>(self) -> bool {
self.contains_type_id(TypeId::of::<T>())
}
/// 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) {

View file

@ -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,