From d8a6872b55bb383ed173a7aae7752ce8e9b57024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tudor=20Lechin=C8=9Ban?= Date: Fri, 30 Aug 2024 13:06:54 +0300 Subject: [PATCH] docs: document world module --- src/component/component_storage.rs | 8 +- src/world/builder.rs | 9 ++ src/world/mod.rs | 226 ++++++++++++++++------------- 3 files changed, 143 insertions(+), 100 deletions(-) diff --git a/src/component/component_storage.rs b/src/component/component_storage.rs index e84be05..11d28fb 100644 --- a/src/component/component_storage.rs +++ b/src/component/component_storage.rs @@ -141,7 +141,13 @@ impl ComponentStorage { where T: Component, { - self.metadata.contains_key(&TypeId::of::()) + self.is_registered_dyn(TypeId::of::()) + } + + #[inline] + #[must_use] + pub fn is_registered_dyn(&self, type_id: TypeId) -> bool { + self.metadata.contains_key(&type_id) } pub fn strip(&mut self, entity: Entity) { diff --git a/src/world/builder.rs b/src/world/builder.rs index 4d407ee..1f54bdc 100644 --- a/src/world/builder.rs +++ b/src/world/builder.rs @@ -2,6 +2,7 @@ use crate::component::{Component, ComponentData, GroupDescriptor, GroupLayout}; use crate::world::World; use alloc::vec::Vec; +/// Builder struct for creating a [`World`]. #[must_use] #[derive(Clone, Default, Debug)] pub struct WorldBuilder { @@ -10,12 +11,14 @@ pub struct WorldBuilder { } impl WorldBuilder { + /// Sets a group `layout` for the world. #[inline] pub fn set_layout(&mut self, layout: GroupLayout) -> &mut Self { self.layout = layout; self } + /// Adds a new component group to the world. pub fn add_group(&mut self) -> &mut Self where G: GroupDescriptor, @@ -23,12 +26,14 @@ impl WorldBuilder { self.add_group_dyn(G::COMPONENTS) } + /// Adds a new component group to the world. #[inline] pub fn add_group_dyn(&mut self, components: &[ComponentData]) -> &mut Self { self.layout.add_group_dyn(components); self } + /// Registers a new component type on the world. pub fn register(&mut self) -> &mut Self where T: Component, @@ -36,12 +41,16 @@ impl WorldBuilder { self.register_dyn(ComponentData::new::()) } + /// Registers a new component type on the world. #[inline] pub fn register_dyn(&mut self, component: ComponentData) -> &mut Self { self.components.push(component); self } + /// Buidls the world with the previously specified options. + /// + /// Returns the newly created world. #[must_use] pub fn build(&self) -> World { let mut world = World::new(&self.layout); diff --git a/src/world/mod.rs b/src/world/mod.rs index fa8ca5f..0b70b08 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -1,5 +1,9 @@ +//! Manage and query entities and their associated components. + mod builder; +use core::any::TypeId; + pub use self::builder::*; use crate::component::{ @@ -8,7 +12,7 @@ use crate::component::{ use crate::entity::{Entity, EntityStorage}; use crate::query::{Query, QueryAll, QueryOne}; -/// Storage for entities and components. +/// Collection for entities and their associated components. #[derive(Default, Debug)] pub struct World { pub(crate) entities: EntityStorage, @@ -16,7 +20,13 @@ pub struct World { } impl World { - /// Creates a new `EntityStorage` with the given `GroupLayout`. + /// Create and configure a new world using the builder pattern. + #[inline] + pub fn builder() -> WorldBuilder { + WorldBuilder::default() + } + + /// Creates a new world with the given group `layout`. #[inline] #[must_use] pub fn new(layout: &GroupLayout) -> Self { @@ -26,53 +36,10 @@ impl World { } } - #[inline] - pub fn builder() -> WorldBuilder { - WorldBuilder::default() - } - - pub fn query_one(&self) -> QueryOne - where - G: Query, - { - QueryOne::new(self) - } - - pub fn query_all(&self) -> QueryAll - where - G: Query, - { - QueryAll::new(self) - } - - #[must_use] - pub fn contains(&self, entity: Entity) -> bool - where - G: Query, - { - QueryOne::::new(self).contains(entity) - } - - pub fn for_each(&self, f: impl FnMut(G::Item<'_>)) - where - G: Query, - { - self.query_all().for_each(f); - } - - #[cfg(feature = "parallel")] - pub fn par_for_each(&self, f: impl Fn(G::Item<'_>) + Send + Sync) - where - G: Query, - for<'a> G::Item<'a>: Send, - { - self.query_all().par_for_each(f); - } - - /// Sets a new `GroupLayout`. + /// Sets a new group `layout` on this world. /// - /// This function iterates over all entities in the storage, so it is best called when the - /// storage is empty. + /// This operation requires iteration over all entities in the world, so it + /// is best called when the world is empty. #[inline] pub fn set_layout(&mut self, layout: &GroupLayout) { unsafe { @@ -80,28 +47,38 @@ impl World { } } - /// Registers a new component type. + /// Registers a new component type on this world. /// /// Returns whether the component was newly registered. pub fn register(&mut self) -> bool where T: Component, { - self.components.register::() + self.register_dyn(ComponentData::new::()) } + /// Registers a new component type on this world. + /// + /// Returns whether the component was newly registered. #[inline] pub fn register_dyn(&mut self, component: ComponentData) -> bool { self.components.register_dyn(component) } - /// Returns whether component type `T` is registered. + /// Returns whether the component type is registered. #[must_use] pub fn is_registered(&self) -> bool where T: Component, { - self.components.is_registered::() + self.is_registered_dyn(TypeId::of::()) + } + + /// Returns whether the component type is registered. + #[inline] + #[must_use] + pub fn is_registered_dyn(&self, component: TypeId) -> bool { + self.components.is_registered_dyn(component) } /// Creates a new entity with the given `components`. @@ -116,7 +93,7 @@ impl World { entity } - /// Creates new entities with the components produced by the iterator. + /// Creates new entities with the `components` produced by the iterator. /// /// Returns the newly created entities as a slice. pub fn extend(&mut self, components: I) -> &[Entity] @@ -127,18 +104,42 @@ impl World { C::extend(self, components) } - /// Creates a new entity without requiring exclusive access to the storage. The entity is not - /// added to the storage until [`maintain`](Self::maintain) is called. + /// Removes the `entity` and its associated components from the world. /// - /// Returns the newly created entity. + /// Returns whether the operation was successfull, i.e. whether the entity + /// existed in the world before this call. + #[inline] + pub fn destroy(&mut self, entity: Entity) -> bool { + if !self.entities.remove(entity) { + return false; + } + + self.components.strip(entity); + true + } + + /// Queues the creation of an entity without requiring exclusive access to + /// the world. Entities created with this method can be added to the world + /// by calling [`maintain`](Self::maintain). + /// + /// Returns the entity to be created. #[inline] pub fn create_atomic(&self) -> Entity { self.entities.create_atomic() } - /// Adds the given `components` to `entity` if `entity` is present in the storage. + /// Adds the entities created with [`create_atomic`](Self::create_atomic) + /// to the world. + #[inline] + pub fn maintain(&mut self) { + self.entities.maintain(); + } + + /// Inserts `components` to an existing `entity`, overwriting previous data + /// if necessary. /// - /// Returns whether the components were successfully added. + /// Returns whether the `components` were added successfully, i.e. whether + /// the `entity` existed in the world before this call. pub fn insert(&mut self, entity: Entity, components: C) -> bool where C: ComponentSet, @@ -151,9 +152,8 @@ impl World { true } - /// Removes components from the given `entity`. - /// - /// Returns the components that were successfully removed. + /// Removes components from the `entity`, returning the removed components + /// as options. #[must_use = "Use `delete` to discard the components."] pub fn remove(&mut self, entity: Entity) -> C::Remove where @@ -162,7 +162,9 @@ impl World { C::remove(self, entity) } - /// Removes components from the given `entity`. + /// Removes components from the `entity`, without returning them. + /// + /// This is faster than calling [`remove`](Self::remove). pub fn delete(&mut self, entity: Entity) where C: ComponentSet, @@ -170,64 +172,86 @@ impl World { C::delete(self, entity); } - /// Removes the given `entity` and its components from the storage. - /// - /// Returns whether the `entity` was present in the storage. - #[inline] - pub fn destroy(&mut self, entity: Entity) -> bool { - if !self.entities.remove(entity) { - return false; - } - - self.components.strip(entity); - true + /// Queries an entity with the given components. + pub fn query_one(&self) -> QueryOne + where + G: Query, + { + QueryOne::new(self) } - /// Returns whether the storage contains no entities. - #[inline] - #[must_use] - pub fn is_empty(&self) -> bool { - self.entities.is_empty() + /// Queries all entities with the given components. + pub fn query_all(&self) -> QueryAll + where + G: Query, + { + QueryAll::new(self) } - /// Removes all entities and components from the storage. - #[inline] - pub fn clear(&mut self) { - self.maintain(); - self.entities.clear(); - self.components.clear(); + /// Returns whether the `entity` contains the given components. + #[must_use] + pub fn contains(&self, entity: Entity) -> bool + where + G: Query, + { + QueryOne::::new(self).contains(entity) } - /// Removes all entities and components from the storage and resets the entity allocator. - /// - /// After this call, the storage is allowed to return previously allocated entities. - #[inline] - pub fn reset(&mut self) { - self.entities.reset(); - self.components.clear(); + /// Iterates over all entities with the given components. + pub fn for_each(&self, f: impl FnMut(G::Item<'_>)) + where + G: Query, + { + self.query_all().for_each(f); } - /// Adds the entities allocated with [`create_atomic`](Self::create_atomic) to the storage. - #[inline] - pub fn maintain(&mut self) { - self.entities.maintain(); + /// Iterates in parallel over all entities with the given components. + #[cfg(feature = "parallel")] + pub fn par_for_each(&self, f: impl Fn(G::Item<'_>) + Send + Sync) + where + G: Query, + for<'a> G::Item<'a>: Send, + { + self.query_all().par_for_each(f); } - /// Returns wether `entity` is present in the storage. + /// Returns whether the world contains the given `entity`. #[inline] #[must_use] pub fn contains_entity(&self, entity: Entity) -> bool { self.entities.contains(entity) } - /// Returns all entities in the storage as a slice. + /// Returns all entities in the world as a slice. #[inline] #[must_use] pub fn entities(&self) -> &[Entity] { self.entities.as_slice() } - /// Borrows a shared view over all components of type `T` in the storage. + /// Returns whether the world contains no entities. + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.entities.is_empty() + } + + /// Removes all entities and components from the world. + #[inline] + pub fn clear(&mut self) { + self.entities.clear(); + self.components.clear(); + } + + /// Removes all entities and components from the world and resets the entity + /// allocator, allowing the world to reuse previously allocated entities. + #[inline] + pub fn reset(&mut self) { + self.entities.reset(); + self.components.clear(); + } + + /// Returns a shared view over all components of type `T`. #[must_use] pub fn borrow(&self) -> View where @@ -236,7 +260,7 @@ impl World { self.components.borrow::() } - /// Borrows an exclusive view over all components of type `T` in the storage. + /// Returns an exclusive view over all components of type `T`. #[must_use] pub fn borrow_mut(&self) -> ViewMut where @@ -245,6 +269,8 @@ impl World { self.components.borrow_mut::() } + /// Returns a shared view over all components of type `T`, along with + /// grouping information. #[must_use] pub fn borrow_with_group_info(&self) -> (View, Option) where @@ -253,6 +279,8 @@ impl World { self.components.borrow_with_group_info::() } + /// Returns an exclusive view over all components of type `T`, along with + /// grouping information. #[must_use] pub fn borrow_with_group_info_mut(&self) -> (ViewMut, Option) where