add doc comments for entity and event functionality
This commit is contained in:
parent
e8cbe1debe
commit
100c02fc58
|
@ -17,8 +17,14 @@ pub type RefComponents<'a, T> = Ref<'a, HashMap<EntityId, T>>;
|
|||
pub type RefMutComponents<'a, T> = RefMut<'a, HashMap<EntityId, T>>;
|
||||
|
||||
pub trait GenericComponentStore: AsAny {
|
||||
/// Returns true if this component store currently has a component for the specified entity.
|
||||
fn has(&self, entity: EntityId) -> bool;
|
||||
|
||||
/// If this component store has a component for the specified entity, removes it and returns
|
||||
/// true. Otherwise, returns false.
|
||||
fn remove(&mut self, entity: EntityId) -> bool;
|
||||
|
||||
/// Removes all components from this store.
|
||||
fn clear(&mut self);
|
||||
}
|
||||
|
||||
|
@ -55,6 +61,7 @@ pub fn as_component_store_mut<T: Component>(
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Entity manager. Stores entity components and manages entity IDs.
|
||||
pub struct Entities {
|
||||
entities: HashSet<EntityId>,
|
||||
component_stores: HashMap<TypeId, Box<dyn GenericComponentStore>>,
|
||||
|
@ -62,6 +69,7 @@ pub struct Entities {
|
|||
}
|
||||
|
||||
impl Entities {
|
||||
/// Creates and returns a new instance of an entity manager.
|
||||
pub fn new() -> Self {
|
||||
Entities {
|
||||
entities: HashSet::new(),
|
||||
|
@ -99,11 +107,13 @@ impl Entities {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the entity manager currently is aware of an entity with the given ID.
|
||||
#[inline]
|
||||
pub fn has_entity(&self, entity: EntityId) -> bool {
|
||||
self.entities.contains(&entity)
|
||||
}
|
||||
|
||||
/// Returns a previously unused entity ID. Use this to "create" a new entity.
|
||||
pub fn new_entity(&mut self) -> EntityId {
|
||||
let new_entity_id = self.next_id;
|
||||
self.next_id = self.next_id.wrapping_add(1);
|
||||
|
@ -111,6 +121,9 @@ impl Entities {
|
|||
new_entity_id
|
||||
}
|
||||
|
||||
/// Removes an entity, making the entity ID unusable with this entity manager as well as
|
||||
/// removing all of the entity's components. Returns true if the entity was removed, false if
|
||||
/// the entity ID given did not exist.
|
||||
pub fn remove_entity(&mut self, entity: EntityId) -> bool {
|
||||
if !self.has_entity(entity) {
|
||||
return false;
|
||||
|
@ -123,6 +136,7 @@ impl Entities {
|
|||
true
|
||||
}
|
||||
|
||||
/// Removes all entities from the entity manager, as well as all of their components.
|
||||
pub fn remove_all_entities(&mut self) {
|
||||
self.entities.clear();
|
||||
for (_, component_store) in self.component_stores.iter_mut() {
|
||||
|
@ -130,6 +144,7 @@ impl Entities {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if the given entity currently has a component of the specified type.
|
||||
pub fn has_component<T: Component>(&self, entity: EntityId) -> bool {
|
||||
if !self.has_entity(entity) {
|
||||
false
|
||||
|
@ -143,6 +158,9 @@ impl Entities {
|
|||
}
|
||||
}
|
||||
|
||||
/// Adds the given component to the entity manager, associating it with the given entity ID.
|
||||
/// If this entity already had a component of the same type, that existing component is replaced
|
||||
/// with this one. Returns true if the component was set to the entity.
|
||||
pub fn add_component<T: Component>(&mut self, entity: EntityId, component: T) -> bool {
|
||||
if !self.has_entity(entity) {
|
||||
false
|
||||
|
@ -158,6 +176,8 @@ impl Entities {
|
|||
}
|
||||
}
|
||||
|
||||
/// Removes any component of the given type from the specified entity. If the entity had a
|
||||
/// component of that type and it was removed, returns true.
|
||||
pub fn remove_component<T: Component>(&mut self, entity: EntityId) -> bool {
|
||||
if !self.has_entity(entity) {
|
||||
false
|
||||
|
@ -171,6 +191,9 @@ impl Entities {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the component store for the given component type. This allows you
|
||||
/// to get components of the specified type for any number of entities. If there is currently
|
||||
/// no component store for this type of component, `None` is returned.
|
||||
#[inline]
|
||||
pub fn components<T: Component>(&self) -> Option<RefComponents<T>> {
|
||||
if let Some(component_store) = self.get_component_store() {
|
||||
|
@ -180,6 +203,13 @@ impl Entities {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the mutable component store for the given component type. This allows
|
||||
/// you to get and modify components of the specified type for any number of entities. IF there
|
||||
/// is currently no component store for this type of component, `None` is returned.
|
||||
///
|
||||
/// Note that while technically you can add/remove components using the returned store, you
|
||||
/// should instead prefer to use [`Entities::add_component`] and [`Entities::remove_component`]
|
||||
/// instead.
|
||||
#[inline]
|
||||
pub fn components_mut<T: Component>(&self) -> Option<RefMutComponents<T>> {
|
||||
if let Some(component_store) = self.get_component_store() {
|
||||
|
@ -189,6 +219,14 @@ impl Entities {
|
|||
}
|
||||
}
|
||||
|
||||
/// Initializes a component store for the given component type if one does not exist already.
|
||||
///
|
||||
/// This is technically never needed to be called explicitly (because
|
||||
/// [`Entities::add_component`] will initialize a missing component store automatically if
|
||||
/// needed), but is provided as a convenience so that you could, for example, always
|
||||
/// pre-initialize all of your component stores so that subsequent calls to
|
||||
/// [`Entities::components`] and [`Entities::components_mut`] are guaranteed to never return
|
||||
/// `None`.
|
||||
pub fn init_components<T: Component>(&mut self) {
|
||||
if self.get_component_store::<T>().is_none() {
|
||||
self.add_component_store::<T>();
|
||||
|
@ -200,15 +238,36 @@ impl Entities {
|
|||
|
||||
// TODO: is there some fancy way to get rid of the impl duplication here ... ?
|
||||
|
||||
/// Convenience methods that slightly help the ergonomics of using component stores returned from
|
||||
/// [`Entities::components`].
|
||||
pub trait ComponentStoreConvenience<T: Component> {
|
||||
/// Returns the "first" component from the component store along with the entity ID the
|
||||
/// component is for. This method should only ever be used with components that you know will
|
||||
/// only ever be attached to one entity (and therefore, the component store for this type of
|
||||
/// component only has a single entry in it). Otherwise, which component it returns is
|
||||
/// undefined.
|
||||
fn single(&self) -> Option<(&EntityId, &T)>;
|
||||
|
||||
/// Returns the component for the given entity, if one exists, otherwise returns `None`.
|
||||
fn get(&self, k: &EntityId) -> Option<&T>;
|
||||
|
||||
/// Returns true if there is a component for the given entity in this store.
|
||||
fn contains_key(&self, k: &EntityId) -> bool;
|
||||
}
|
||||
|
||||
pub trait ComponentStoreConvenienceMut<T: Component> {
|
||||
/// Returns the "first" component from the component store along with the entity ID the
|
||||
/// component is for as a mutable reference. This method should only ever be used with
|
||||
/// components that you know will only ever be attached to one entity (and therefore, the
|
||||
/// component store for this type of component only has a single entry in it). Otherwise, which
|
||||
/// component it returns is undefined.
|
||||
fn single_mut(&mut self) -> Option<(&EntityId, &mut T)>;
|
||||
|
||||
/// Returns the component for the given entity as a mutable reference if one exists, otherwise
|
||||
/// returns `None`.
|
||||
fn get_mut(&mut self, k: &EntityId) -> Option<&mut T>;
|
||||
|
||||
/// Returns true if there is a component for the given entity in this store.
|
||||
fn contains_key(&mut self, k: &EntityId) -> bool;
|
||||
}
|
||||
|
||||
|
@ -293,8 +352,14 @@ impl<'a, T: Component> ComponentStoreConvenienceMut<T> for Option<RefMutComponen
|
|||
}
|
||||
}
|
||||
|
||||
/// Convenience methods that slightly help the ergonomics of using component stores returned from
|
||||
/// [`Entities::components`].
|
||||
pub trait OptionComponentStore<T: Component> {
|
||||
/// Returns the total number of components in this component store. This is the same as the
|
||||
/// number of entities that have a component of this type.
|
||||
fn len(&self) -> usize;
|
||||
|
||||
/// Returns true if this store is empty.
|
||||
fn is_empty(&self) -> bool;
|
||||
}
|
||||
|
||||
|
@ -336,9 +401,22 @@ impl<'a, T: Component> OptionComponentStore<T> for Option<RefMutComponents<'a, T
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// An "update component system" function that is used to update entity component state for a
|
||||
/// certain type/set of components. The generic type used is some application-specific context
|
||||
/// type that should be passed to all of your "update component system" functions.
|
||||
pub type UpdateFn<T> = fn(&mut T);
|
||||
|
||||
/// A "render component system" function that is used to execute render logic for entities based
|
||||
/// on a certain type/set of components. The generic type used is some application-specific context
|
||||
/// type that should be passed to all of your "render component system" functions.
|
||||
pub type RenderFn<T> = fn(&mut T);
|
||||
|
||||
/// This is a totally optional minor convenience to help you to manage your "component systems"
|
||||
/// and ensure they are always called in the same order.
|
||||
///
|
||||
/// The generic types `U` and `R` refer to application-specific context types that are needed by
|
||||
/// all of your "update" and "render" component system functions. Both of these types may be the
|
||||
/// same type or different depending on your needs.
|
||||
pub struct ComponentSystems<U, R> {
|
||||
update_systems: Vec<UpdateFn<U>>,
|
||||
render_systems: Vec<RenderFn<R>>,
|
||||
|
@ -352,25 +430,34 @@ impl<U, R> ComponentSystems<U, R> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Adds an update component system function to the list of functions that will be called in
|
||||
/// order whenever [`ComponentSystems::update`] is called.
|
||||
pub fn add_update_system(&mut self, f: UpdateFn<U>) {
|
||||
self.update_systems.push(f);
|
||||
}
|
||||
|
||||
/// Adds a render component system function to the list of functions that will be called in
|
||||
/// order whenever [`ComponentSystems::render`] is called.
|
||||
pub fn add_render_system(&mut self, f: RenderFn<R>) {
|
||||
self.render_systems.push(f);
|
||||
}
|
||||
|
||||
/// Removes all existing update and render component system functions.
|
||||
pub fn reset(&mut self) {
|
||||
self.update_systems.clear();
|
||||
self.render_systems.clear();
|
||||
}
|
||||
|
||||
/// Calls each of the update component system functions in the same order that they were added,
|
||||
/// passing each of them the context argument provided.
|
||||
pub fn update(&mut self, context: &mut U) {
|
||||
for f in self.update_systems.iter_mut() {
|
||||
f(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls each of the render component system functions in the same order that they were added,
|
||||
/// passing each of them the context argument provided.
|
||||
pub fn render(&mut self, context: &mut R) {
|
||||
for f in self.render_systems.iter_mut() {
|
||||
f(context);
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
/// An event listener/handler function that returns true if it handled the event and no other
|
||||
/// listeners/handlers should be called next with the same event, or false if the event was not
|
||||
/// handled and any subsequent listeners/handlers should be called.
|
||||
pub type ListenerFn<EventType, ContextType> = fn(event: &EventType, &mut ContextType) -> bool;
|
||||
|
||||
/// An event publisher that code can use to queue up events to be handled by an [`EventListeners`]
|
||||
/// instance. The `EventType` here should usually be an application-specific "events" enum.
|
||||
pub struct EventPublisher<EventType> {
|
||||
queue: VecDeque<EventType>,
|
||||
}
|
||||
|
@ -13,16 +18,19 @@ impl<EventType> EventPublisher<EventType> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the number of events that have been queued.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.queue.len()
|
||||
}
|
||||
|
||||
/// Clears the current event queue. The events will not be processed/handled.
|
||||
#[inline]
|
||||
pub fn clear(&mut self) {
|
||||
self.queue.clear();
|
||||
}
|
||||
|
||||
/// Pushes the given event to the back of the queue.
|
||||
#[inline]
|
||||
pub fn queue(&mut self, event: EventType) {
|
||||
self.queue.push_back(event);
|
||||
|
@ -35,6 +43,14 @@ impl<EventType> EventPublisher<EventType> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A manager for application event listeners/handlers that can dispatch events queued up by a
|
||||
/// [`EventPublisher`] to each of the event listeners/handlers registered with this manager.
|
||||
///
|
||||
/// The `EventType` specified here should usually be an application-specific "events" enum and
|
||||
/// should be the same as the type used in your application's [`EventPublisher`].
|
||||
///
|
||||
/// The `ContextType` specified here should be some application-specific context type that you
|
||||
/// want available in all of your event listener/handler functions.
|
||||
pub struct EventListeners<EventType, ContextType> {
|
||||
listeners: Vec<ListenerFn<EventType, ContextType>>,
|
||||
dispatch_queue: VecDeque<EventType>,
|
||||
|
@ -48,16 +64,20 @@ impl<EventType, ContextType> EventListeners<EventType, ContextType> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the number of event listeners/handlers registered with this manager.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.listeners.len()
|
||||
}
|
||||
|
||||
/// Unregisters all event listeners/managers previously registered with this manager.
|
||||
#[inline]
|
||||
pub fn clear(&mut self) {
|
||||
self.listeners.clear();
|
||||
}
|
||||
|
||||
/// Adds/Registers the given event listener/handler function with this manager so that
|
||||
/// it will be called during dispatching of events. Returns true if the function was added.
|
||||
pub fn add(&mut self, listener: ListenerFn<EventType, ContextType>) -> bool {
|
||||
// HACK?: most advice i've seen right now for comparing function pointers suggests doing
|
||||
// this, but i've also come across comments suggesting there are times where this
|
||||
|
@ -70,6 +90,7 @@ impl<EventType, ContextType> EventListeners<EventType, ContextType> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Removes/Unregisters the specified event listener/handler function from this manager.
|
||||
pub fn remove(&mut self, listener: ListenerFn<EventType, ContextType>) -> bool {
|
||||
let before_size = self.listeners.len();
|
||||
// HACK?: comparing function pointers -- see above "HACK?" comment. same concern here.
|
||||
|
@ -78,11 +99,19 @@ impl<EventType, ContextType> EventListeners<EventType, ContextType> {
|
|||
return before_size != self.listeners.len()
|
||||
}
|
||||
|
||||
/// Moves the queue from the given [`EventPublisher`] to this manager in preparation for
|
||||
/// dispatching the queued events via [`EventListeners::dispatch_queue`]. After calling this,
|
||||
/// the [`EventPublisher`]'s queue will be empty.
|
||||
pub fn take_queue_from(&mut self, publisher: &mut EventPublisher<EventType>) -> usize {
|
||||
publisher.take_queue(&mut self.dispatch_queue);
|
||||
self.dispatch_queue.len()
|
||||
}
|
||||
|
||||
/// Dispatches the previous obtained event queue (via a call to
|
||||
/// [`EventListeners::take_queue_from`]) to all of the registered event listeners/handlers,
|
||||
/// passing each of them the given context argument. Not all of the event listeners/handlers
|
||||
/// will necessarily be called for each event being dispatched depending on which ones handled
|
||||
/// which events.
|
||||
pub fn dispatch_queue(&mut self, context: &mut ContextType) {
|
||||
while let Some(event) = self.dispatch_queue.pop_front() {
|
||||
for listener in &self.listeners {
|
||||
|
|
Loading…
Reference in a new issue