From 0c194b734adf3e86db317542aa6fd0cc05f3f2e0 Mon Sep 17 00:00:00 2001 From: Elliott Pierce Date: Sat, 31 May 2025 17:40:09 -0400 Subject: [PATCH] doc improvements --- crates/bevy_app/src/app.rs | 2 +- .../src/entity_count_diagnostics_plugin.rs | 2 +- crates/bevy_ecs/src/entity/mod.rs | 67 +++++++++---------- crates/bevy_ecs/src/lib.rs | 16 ++--- crates/bevy_ecs/src/observer/mod.rs | 2 +- crates/bevy_ecs/src/system/commands/mod.rs | 2 +- crates/bevy_ecs/src/system/system.rs | 4 +- crates/bevy_ecs/src/system/system_registry.rs | 4 +- crates/bevy_ecs/src/world/command_queue.rs | 6 +- crates/bevy_ecs/src/world/mod.rs | 2 +- 10 files changed, 53 insertions(+), 54 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index dcd58e7b77..4878ed9b56 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1579,7 +1579,7 @@ mod tests { app.add_systems(EnterMainMenu, (foo, bar)); app.world_mut().run_schedule(EnterMainMenu); - assert_eq!(app.world().entities().count_active(), 2); + assert_eq!(app.world().entities().count_constructed(), 2); } #[test] diff --git a/crates/bevy_diagnostic/src/entity_count_diagnostics_plugin.rs b/crates/bevy_diagnostic/src/entity_count_diagnostics_plugin.rs index 864dc1b489..8c71188bf7 100644 --- a/crates/bevy_diagnostic/src/entity_count_diagnostics_plugin.rs +++ b/crates/bevy_diagnostic/src/entity_count_diagnostics_plugin.rs @@ -22,6 +22,6 @@ impl EntityCountDiagnosticsPlugin { pub const ENTITY_COUNT: DiagnosticPath = DiagnosticPath::const_new("entity_count"); pub fn diagnostic_system(mut diagnostics: Diagnostics, entities: &Entities) { - diagnostics.add_measurement(&Self::ENTITY_COUNT, || entities.count_active() as f64); + diagnostics.add_measurement(&Self::ENTITY_COUNT, || entities.count_constructed() as f64); } } diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index f4721eb609..fe1e50ab46 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -761,7 +761,7 @@ impl<'a> Iterator for AllocEntitiesIterator<'a> { impl<'a> ExactSizeIterator for AllocEntitiesIterator<'a> {} impl<'a> core::iter::FusedIterator for AllocEntitiesIterator<'a> {} -// SAFETY: Newly reserved entity values are unique. +// SAFETY: Newly allocated entity values are unique. unsafe impl EntitySetIterator for AllocEntitiesIterator<'_> {} /// [`Entities`] tracks all know [`EntityRow`]s and their metadata. @@ -781,8 +781,7 @@ impl Entities { self.meta.clear(); } - /// Returns the [`EntityLocation`] of an [`Entity`]. - /// Note: for non-constructed entities, returns `None`. + /// Returns the [`EntityLocation`] of an [`Entity`] if it exists and is constructed. #[inline] pub fn get_constructed( &self, @@ -829,7 +828,7 @@ impl Entities { } } - /// Returns the [`EntityIdLocation`] of an [`Entity`]. + /// Returns the [`EntityIdLocation`] of an [`Entity`] if it exists. #[inline] pub fn get(&self, entity: Entity) -> Result { match self.meta.get(entity.index() as usize) { @@ -866,14 +865,22 @@ impl Entities { .unwrap_or(Entity::from_raw(row)) } + /// Returns whether the entity at this `row` is constructed or not. + #[inline] + pub fn is_row_constructed(&self, row: EntityRow) -> bool { + self.meta + .get(row.index() as usize) + .map(|meta| meta.location.is_some()) + .unwrap_or_default() + } + /// Returns true if the entity exists. /// This will return true for entities that exist but have not been constructed. pub fn contains(&self, entity: Entity) -> bool { self.resolve_from_row(entity.row()).generation() == entity.generation() } - /// Returns true if the entity exists in the world *now*. - /// This will return false if the `entity` is not constructed. + /// Returns true if the entity exists and are constructed. pub fn contains_constructed(&self, entity: Entity) -> bool { self.get_constructed(entity).is_ok() } @@ -922,8 +929,7 @@ impl Entities { ) -> EntityIdLocation { self.ensure_row(row); // SAFETY: We just did `ensure_row` - let meta = unsafe { self.meta.get_unchecked_mut(row.index() as usize) }; - mem::replace(&mut meta.location, location) + self.update(row, location) } /// Ensures row is valid. @@ -931,9 +937,9 @@ impl Entities { fn ensure_row(&mut self, row: EntityRow) { #[cold] // to help with branch prediction fn expand(meta: &mut Vec, len: usize) { - meta.resize(len, EntityMeta::EMPTY); + meta.resize(len, EntityMeta::FRESH); // Set these up too while we're here. - meta.resize(meta.capacity(), EntityMeta::EMPTY); + meta.resize(meta.capacity(), EntityMeta::FRESH); } let index = row.index() as usize; @@ -947,7 +953,7 @@ impl Entities { /// /// # Safety /// - /// - `row` must its [`EntityIdLocation`] set to `None`. + /// - `row` must be destructed (have no location) already. pub(crate) unsafe fn mark_free(&mut self, row: EntityRow, generations: u32) -> Entity { // We need to do this in case an entity is being freed that was never constructed. self.ensure_row(row); @@ -966,7 +972,7 @@ impl Entities { /// Mark an [`EntityRow`] as constructed or destructed in the given tick. /// /// # Safety - /// - `row` must have either been constructed or destructed, ensuring its row is valid. + /// - `row` must have been constructed at least once, ensuring its row is valid. #[inline] pub(crate) unsafe fn mark_construct_or_destruct( &mut self, @@ -979,11 +985,9 @@ impl Entities { meta.spawned_or_despawned = SpawnedOrDespawned { by, at }; } - /// Try to get the source code location from which this entity has last been - /// spawned, despawned or flushed. + /// Try to get the source code location from which this entity has last been constructed or destructed. /// - /// Returns `None` if its index has been reused by another entity - /// or if this entity has never existed. + /// Returns `None` if the entity does not exist or has never been construced/destructed. pub fn entity_get_spawned_or_despawned_by( &self, entity: Entity, @@ -994,21 +998,17 @@ impl Entities { }) } - /// Try to get the [`Tick`] at which this entity has last been - /// spawned, despawned or flushed. + /// Try to get the [`Tick`] at which this entity has last been constructed or destructed. /// - /// Returns `None` if its index has been reused by another entity or if this entity - /// has never been spawned. + /// Returns `None` if the entity does not exist or has never been construced/destructed. pub fn entity_get_spawned_or_despawned_at(&self, entity: Entity) -> Option { self.entity_get_spawned_or_despawned(entity) .map(|spawned_or_despawned| spawned_or_despawned.at) } - /// Try to get the [`SpawnedOrDespawned`] related to the entity's last spawn, - /// despawn or flush. + /// Try to get the [`SpawnedOrDespawned`] related to the entity's last construction or destruction. /// - /// Returns `None` if its index has been reused by another entity or if - /// this entity has never been spawned. + /// Returns `None` if the entity does not exist or has never been construced/destructed. #[inline] fn entity_get_spawned_or_despawned(&self, entity: Entity) -> Option { self.meta @@ -1016,8 +1016,7 @@ impl Entities { .filter(|meta| // Generation is incremented immediately upon despawn (meta.generation == entity.generation) - || meta.location.is_none() - && (meta.generation == entity.generation.after_versions(1))) + || (meta.location.is_none() && meta.generation == entity.generation.after_versions(1))) .map(|meta| meta.spawned_or_despawned) } @@ -1051,22 +1050,22 @@ impl Entities { self.meta.len() as u32 } - /// Checks if any entity has been allocated + /// Checks if any entity has been declared #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } - /// Counts the number of entities currently participating in the world, those that have locations. - pub fn count_active(&self) -> u32 { + /// Counts the number of entities currently constructed, those that have locations. + pub fn count_constructed(&self) -> u32 { self.meta .iter() .filter(|meta| meta.location.is_some()) .count() as u32 } - /// Returns true if there are any entities active in the world, entities that have locations. - pub fn any_active(&self) -> bool { + /// Returns true if there are any entities currently constructed, entities that have locations. + pub fn any_constructed(&self) -> bool { self.meta.iter().any(|meta| meta.location.is_some()) } } @@ -1152,7 +1151,7 @@ struct EntityMeta { generation: EntityGeneration, /// The current location of the [`EntityRow`]. location: EntityIdLocation, - /// Location and tick of the last spawn, despawn or flush of this entity. + /// Location and tick of the last construct/destruct spawned_or_despawned: SpawnedOrDespawned, } @@ -1163,8 +1162,8 @@ struct SpawnedOrDespawned { } impl EntityMeta { - /// meta for **pending entity** - const EMPTY: EntityMeta = EntityMeta { + /// The metadata for a fresh entity: Never constructed/destructed, no location, etc. + const FRESH: EntityMeta = EntityMeta { generation: EntityGeneration::FIRST, location: None, spawned_or_despawned: SpawnedOrDespawned { diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index ddef365f3b..329d8b4873 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -374,9 +374,9 @@ mod tests { .construct((TableStored("def"), A(456))) .unwrap(); - assert_eq!(world.entities.count_active(), 2); + assert_eq!(world.entities.count_constructed(), 2); assert!(world.despawn(e1)); - assert_eq!(world.entities.count_active(), 1); + assert_eq!(world.entities.count_constructed(), 1); assert!(world.get::(e1).is_none()); assert!(world.get::(e1).is_none()); assert_eq!(world.get::(e4).unwrap().0, "def"); @@ -388,9 +388,9 @@ mod tests { let mut world = World::new(); let e = world.spawn((TableStored("abc"), A(123))).id(); let f = world.spawn((TableStored("def"), A(456))).id(); - assert_eq!(world.entities.count_active(), 2); + assert_eq!(world.entities.count_constructed(), 2); assert!(world.despawn(e)); - assert_eq!(world.entities.count_active(), 1); + assert_eq!(world.entities.count_constructed(), 1); assert!(world.get::(e).is_none()); assert!(world.get::(e).is_none()); assert_eq!(world.get::(f).unwrap().0, "def"); @@ -403,9 +403,9 @@ mod tests { let e = world.spawn((TableStored("abc"), SparseStored(123))).id(); let f = world.spawn((TableStored("def"), SparseStored(456))).id(); - assert_eq!(world.entities.count_active(), 2); + assert_eq!(world.entities.count_constructed(), 2); assert!(world.despawn(e)); - assert_eq!(world.entities.count_active(), 1); + assert_eq!(world.entities.count_constructed(), 1); assert!(world.get::(e).is_none()); assert!(world.get::(e).is_none()); assert_eq!(world.get::(f).unwrap().0, "def"); @@ -1640,7 +1640,7 @@ mod tests { assert_eq!(q1.iter(&world).len(), 1); assert_eq!(q2.iter(&world).len(), 1); - assert_eq!(world.entities().count_active(), 2); + assert_eq!(world.entities().count_constructed(), 2); world.clear_entities(); @@ -1655,7 +1655,7 @@ mod tests { "world should not contain sparse set components" ); assert_eq!( - world.entities().count_active(), + world.entities().count_constructed(), 0, "world should not have any entities" ); diff --git a/crates/bevy_ecs/src/observer/mod.rs b/crates/bevy_ecs/src/observer/mod.rs index 26bddad656..61b4b4eaf7 100644 --- a/crates/bevy_ecs/src/observer/mod.rs +++ b/crates/bevy_ecs/src/observer/mod.rs @@ -1079,7 +1079,7 @@ mod tests { world.spawn(A).flush(); assert_eq!(vec!["add_2", "add_1"], world.resource::().0); // Our A entity plus our two observers - assert_eq!(world.entities().count_active(), 3); + assert_eq!(world.entities().count_constructed(), 3); } #[test] diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index 56b720b0fb..8075c72e5a 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -2375,7 +2375,7 @@ mod tests { .spawn((W(1u32), W(2u64))) .id(); command_queue.apply(&mut world); - assert_eq!(world.entities().count_active(), 1); + assert_eq!(world.entities().count_constructed(), 1); let results = world .query::<(&W, &W)>() .iter(&world) diff --git a/crates/bevy_ecs/src/system/system.rs b/crates/bevy_ecs/src/system/system.rs index 8b57e272f1..00731a47eb 100644 --- a/crates/bevy_ecs/src/system/system.rs +++ b/crates/bevy_ecs/src/system/system.rs @@ -423,9 +423,9 @@ mod tests { #[test] fn command_processing() { let mut world = World::new(); - assert_eq!(world.entities.count_active(), 0); + assert_eq!(world.entities.count_constructed(), 0); world.run_system_once(spawn_entity).unwrap(); - assert_eq!(world.entities.count_active(), 1); + assert_eq!(world.entities.count_constructed(), 1); } #[test] diff --git a/crates/bevy_ecs/src/system/system_registry.rs b/crates/bevy_ecs/src/system/system_registry.rs index 80ee952282..ffce1214e6 100644 --- a/crates/bevy_ecs/src/system/system_registry.rs +++ b/crates/bevy_ecs/src/system/system_registry.rs @@ -657,9 +657,9 @@ mod tests { let exclusive_system_id = world.register_system(|world: &mut World| { world.spawn_empty(); }); - let entity_count = world.entities.count_active(); + let entity_count = world.entities.count_constructed(); let _ = world.run_system(exclusive_system_id); - assert_eq!(world.entities.count_active(), entity_count + 1); + assert_eq!(world.entities.count_constructed(), entity_count + 1); } #[test] diff --git a/crates/bevy_ecs/src/world/command_queue.rs b/crates/bevy_ecs/src/world/command_queue.rs index 3d922036b2..18c9eb4d45 100644 --- a/crates/bevy_ecs/src/world/command_queue.rs +++ b/crates/bevy_ecs/src/world/command_queue.rs @@ -420,12 +420,12 @@ mod test { let mut world = World::new(); queue.apply(&mut world); - assert_eq!(world.entities().count_active(), 2); + assert_eq!(world.entities().count_constructed(), 2); // The previous call to `apply` cleared the queue. // This call should do nothing. queue.apply(&mut world); - assert_eq!(world.entities().count_active(), 2); + assert_eq!(world.entities().count_constructed(), 2); } #[expect( @@ -459,7 +459,7 @@ mod test { queue.push(SpawnCommand); queue.push(SpawnCommand); queue.apply(&mut world); - assert_eq!(world.entities().count_active(), 3); + assert_eq!(world.entities().count_constructed(), 3); } #[test] diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index c08e69430f..f745e1fb43 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -3672,7 +3672,7 @@ impl fmt::Debug for World { // Accessing any data stored in the world would be unsound. f.debug_struct("World") .field("id", &self.id) - .field("entity_count", &self.entities.count_active()) + .field("entity_count", &self.entities.count_constructed()) .field("archetype_count", &self.archetypes.len()) .field("component_count", &self.components.len()) .field("resource_count", &self.storages.resources.len())