From 7b044c09088ef1bdf878ce14d42bec2ebc42e4ab Mon Sep 17 00:00:00 2001 From: Elliott Pierce Date: Fri, 30 May 2025 22:53:23 -0400 Subject: [PATCH] docs --- crates/bevy_ecs/src/entity/map_entities.rs | 2 +- crates/bevy_ecs/src/entity/mod.rs | 8 +++-- crates/bevy_ecs/src/world/entity_ref.rs | 20 +++++++++++- crates/bevy_ecs/src/world/mod.rs | 38 +++++++++++++++++++++- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ecs/src/entity/map_entities.rs b/crates/bevy_ecs/src/entity/map_entities.rs index 5113d8b7fd..883095933b 100644 --- a/crates/bevy_ecs/src/entity/map_entities.rs +++ b/crates/bevy_ecs/src/entity/map_entities.rs @@ -334,7 +334,7 @@ mod tests { fn entity_mapper() { let mut map = EntityHashMap::default(); let mut world = World::new(); - let mut mapper = SceneEntityMapper::new(&mut map, &mut world); + let mut mapper = SceneEntityMapper::new(&mut map, &world); let mapped_ent = Entity::from_raw_u32(1).unwrap(); let dead_ref = mapper.get_mapped(mapped_ent); diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index 36daffd44f..0c0b92546f 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -658,8 +658,9 @@ impl SparseSetIndex for Entity { } } +/// Allocates [`Entity`] ids uniquely. #[derive(Default, Debug)] -pub(crate) struct EntitiesAllocator { +pub struct EntitiesAllocator { free: Vec, free_len: AtomicU32, next_row: AtomicU32, @@ -761,7 +762,7 @@ impl Entities { /// Clears all entity information pub fn clear(&mut self) { - self.meta.clear() + self.meta.clear(); } /// Returns the [`EntityLocation`] of an [`Entity`]. @@ -981,10 +982,13 @@ impl Entities { /// An error that occurs when a specified [`Entity`] can not be constructed. #[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)] pub enum ConstructionError { + /// The [`Entity`] to construct was invalid. + /// It probably had the wrong generation or was created erroneously. #[error( "The entity's id was invalid: either erroneously created or with the wrong generation." )] InvalidId, + /// The [`Entity`] to construct was already constructed. #[error("The entity can not be constructed as it already has a location.")] AlreadyConstructed, } diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index dd324eac9d..5a61535d52 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -2333,6 +2333,9 @@ impl<'w> EntityWorldMut<'w> { self } + /// Constructs the entity. + /// If the entity has not been constructed or has been destructed, the can construct it. + /// See [`World::construct`] for details. #[track_caller] pub fn construct(&mut self, bundle: B) -> Result<&mut Self, ConstructionError> { let Self { @@ -2340,11 +2343,26 @@ impl<'w> EntityWorldMut<'w> { entity, location, } = self; - let found = world.construct(*entity, bundle)?; + let found = world.construct_with_caller(*entity, bundle, MaybeLocation::caller())?; *location = found.location; Ok(self) } + /// A faster version of [`construct`](Self::construct) for the empty bundle. + #[track_caller] + pub fn construct_empty(&mut self) -> Result<&mut Self, ConstructionError> { + let Self { + world, + entity, + location, + } = self; + let found = world.construct_empty_with_caller(*entity, MaybeLocation::caller())?; + *location = found.location; + Ok(self) + } + + /// Destructs the entity, without releasing it. + /// This may be later [`constructed`](Self::construct). #[track_caller] pub fn destruct(&mut self) -> &mut Self { self.destruct_with_caller(MaybeLocation::caller()) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 5acbad2b78..70afda9efe 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -1053,16 +1053,46 @@ impl World { } /// Spawns an [`Entity`] that is void/null. - /// The returned entity id is valid and unique, but it does not correspond to any conceptual entity. + /// The returned entity id is valid and unique, but it does not correspond to any conceptual entity yet. /// The conceptual entity does not exist, and using the id as if it did may produce errors. /// It can not be queried, and it has no [`EntityLocation`](crate::entity::EntityLocation). /// /// This is different from empty entities, which do exist in the world; /// they just happen to have no components. + /// + /// This is particularly useful when spawning entities in special ways. + /// For example, commands uses this to allocate an entity and [`construct`](Self::construct) it later. + /// Note that since this entity is not queryable and its id is not discoverable, loosing the returned [`Entity`] effectively leaks it, never to be used again! + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::{prelude::*}; + /// let mut world = World::new(); + /// let entity = world.spawn_null(); + /// // wait as long as you like + /// let entity_access = world.construct_empty(entity).unwrap(); + /// // treat it as a normal entity + /// entity_access.despawn(); + /// ``` pub fn spawn_null(&self) -> Entity { self.allocator.alloc() } + /// This releases the entity to be reused by the allocator. + /// It despawns the entity as needed. + /// + /// This is useful when the entity may not be constructed. + /// + /// # Example + /// + /// ``` + /// # use bevy_ecs::{prelude::*}; + /// let mut world = World::new(); + /// let entity = world.spawn_null(); + /// // The entity was never constructed. + /// world.release(entity); + /// ``` pub fn release(&mut self, entity: Entity) { let Ok(entity) = self.get_entity_mut(entity) else { return; // Already released then. @@ -1085,6 +1115,11 @@ impl World { .free(self.entities.mark_free(entity, generations)); } + /// Constructs the bundle on the entity. + /// If the entity can not be constructed for any reason, returns an error. + /// + /// If it succeeds, this declares the entity to have this bundle. + /// It is possible to construct an `entity` that has not been allocated yet. #[track_caller] pub fn construct( &mut self, @@ -1137,6 +1172,7 @@ impl World { entity } + /// A faster version of [`construct`](Self::construct) for the empty bundle. #[track_caller] pub fn construct_empty( &mut self,