diff options
author | HampusM <hampus@hampusmat.com> | 2025-08-26 16:43:40 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-09-11 18:24:48 +0200 |
commit | 09981e0173a2427264e432226804292c91e1f920 (patch) | |
tree | 70112b6cda98a55da625ec9f6762927f00affe91 /ecs/src/lib.rs | |
parent | ce1bade2c21cc3129fa8bc2b4bc67bc4dc2c25c3 (diff) |
feat(ecs): add component changed event
Diffstat (limited to 'ecs/src/lib.rs')
-rw-r--r-- | ecs/src/lib.rs | 158 |
1 files changed, 115 insertions, 43 deletions
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index ab30980..6f49a91 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -14,10 +14,12 @@ use crate::component::storage::archetype::EntityComponent as ArchetypeEntityComp use crate::component::storage::Storage as ComponentStorage; use crate::component::{ Component, + IntoParts as IntoComponentParts, Parts as ComponentParts, Sequence as ComponentSequence, }; use crate::entity::{Declaration as EntityDeclaration, Handle as EntityHandle}; +use crate::event::{Emitted as EmittedEvent, NewEvents, Submitter as EventSubmitter}; use crate::extension::{Collector as ExtensionCollector, Extension}; use crate::lock::Lock; use crate::pair::{ChildOf, DependsOn, Pair, Wildcard}; @@ -33,6 +35,7 @@ use crate::query::{ }; use crate::sole::Sole; use crate::stats::Stats; +use crate::system::observer::{Observer, WrapperComponent as ObserverWrapperComponent}; use crate::system::{Callbacks, Metadata as SystemMetadata, System, SystemComponent}; use crate::uid::{Kind as UidKind, Uid}; @@ -103,18 +106,7 @@ impl World where Comps: ComponentSequence, { - debug_assert_eq!(entity_uid.kind(), UidKind::Entity); - - if let Err(err) = self.data.component_storage.create_entity(entity_uid) { - tracing::warn!("Failed to create entity: {err}"); - return; - } - - Self::add_entity_components( - entity_uid, - components.into_parts_array(), - &mut self.data.component_storage, - ); + self.create_ent(entity_uid, components.into_parts_array()); } pub fn add_component(&mut self, entity_id: Uid, component_parts: ComponentParts) @@ -142,32 +134,40 @@ impl World self.data.sole_storage.insert(sole) } - pub fn register_system<'this, SystemImpl>( + pub fn register_observer<'this, SystemImpl, ObserverT>( &'this mut self, - phase_euid: Uid, - system: impl System<'this, SystemImpl>, - ) + observer: ObserverT, + ) where + ObserverT: Observer<'this, SystemImpl>, { - let (type_erased_system, mut system_callbacks) = system.finish(); + let (wrapper_comp, mut system_callbacks) = observer.finish_observer(); - let system_ent_id = self.create_entity(( - SystemComponent { system: type_erased_system }, - Pair::new::<DependsOn>(phase_euid), - )); + let ent_id = Uid::new_unique(UidKind::Entity); - system_callbacks.on_created(self, SystemMetadata { ent_id: system_ent_id }); + self.create_ent( + ent_id, + [wrapper_comp.into_parts()].into_iter().chain( + ObserverT::observed_events() + .into_iter() + .map(IntoComponentParts::into_parts), + ), + ); + + system_callbacks.on_created(self, SystemMetadata { ent_id }); } - pub fn register_observer_system<'this, SystemImpl>( + pub fn register_system<'this, SystemImpl>( &'this mut self, + phase_euid: Uid, system: impl System<'this, SystemImpl>, - event: Pair<Uid, Uid>, ) { let (type_erased_system, mut system_callbacks) = system.finish(); - let system_ent_id = - self.create_entity((SystemComponent { system: type_erased_system }, event)); + let system_ent_id = self.create_entity(( + SystemComponent { system: type_erased_system }, + Pair::new::<DependsOn>(phase_euid), + )); system_callbacks.on_created(self, SystemMetadata { ent_id: system_ent_id }); } @@ -209,7 +209,12 @@ impl World unreachable!("Should exist since archetype was found by entity id"); }; - Some(EntityHandle::new(archetype, entity)) + Some(EntityHandle::new(archetype, entity, self)) + } + + pub fn event_submitter(&self) -> EventSubmitter<'_> + { + EventSubmitter::new(self) } /// Performs a single tick. @@ -231,6 +236,8 @@ impl World self.perform_phases(); + self.emit_new_events(); + self.data.component_storage.create_imaginary_archetypes(); self.perform_queued_actions(); @@ -309,6 +316,27 @@ impl World ) } + #[tracing::instrument(skip_all)] + fn create_ent( + &mut self, + entity_uid: Uid, + components: impl IntoIterator<Item = ComponentParts>, + ) + { + debug_assert_eq!(entity_uid.kind(), UidKind::Entity); + + if let Err(err) = self.data.component_storage.create_entity(entity_uid) { + tracing::warn!("Failed to create entity: {err}"); + return; + } + + Self::add_entity_components( + entity_uid, + components, + &mut self.data.component_storage, + ); + } + fn query_and_run_systems(&self, phase_euid: Uid) { let system_query = Query::<(&SystemComponent,)>::from_flexible_query( @@ -363,6 +391,26 @@ impl World } } + fn emit_new_events(&self) + { + let new_events = self + .data + .new_events + .write_nonblock() + .expect("Failed to acquire read-write lock to new events") + .take(); + + for (event_id, event_matches) in new_events { + self.emit_event_observers( + event_id, + &EmittedEvent { + event: event_id, + match_ids: &event_matches.match_ids, + }, + ); + } + } + #[tracing::instrument(skip_all)] fn perform_queued_actions(&mut self) { @@ -473,6 +521,29 @@ impl World removed_component_ids } + + fn emit_event_observers(&self, event_id: Uid, emitted_event: &EmittedEvent<'_>) + { + assert_eq!(event_id.kind(), UidKind::Pair); + + let query = Query::<(&ObserverWrapperComponent,)>::from_flexible_query( + self.flexible_query( + QueryTerms::<QUERY_MAX_TERM_CNT>::builder() + .with_required([ObserverWrapperComponent::id(), event_id]) + .build(), + ), + ); + + for (observer_ent_id, (observer,)) in query.iter_with_euids() { + unsafe { + observer.run( + self, + SystemMetadata { ent_id: observer_ent_id }, + emitted_event.clone(), + ); + } + } + } } impl Default for World @@ -493,31 +564,21 @@ pub enum StepResult Stop, } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct WorldData { component_storage: ComponentStorage, sole_storage: SoleStorage, action_queue: Rc<ActionQueue>, + new_events: Lock<NewEvents>, } -impl Default for WorldData -{ - fn default() -> Self - { - Self { - component_storage: ComponentStorage::default(), - sole_storage: SoleStorage::default(), - action_queue: Rc::new(ActionQueue::default()), - } - } -} - -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct EntityComponentRef<'a> { component_id: Uid, component: &'a ArchetypeEntityComponent, + entity_id: Uid, } impl<'a> EntityComponentRef<'a> @@ -533,9 +594,20 @@ impl<'a> EntityComponentRef<'a> self.component_id } - fn new(component_id: Uid, comp: &'a ArchetypeEntityComponent) -> Self + #[must_use] + pub fn entity_id(&self) -> Uid { - Self { component_id, component: comp } + self.entity_id + } + + fn new(component_id: Uid, comp: &'a ArchetypeEntityComponent, entity_id: Uid) + -> Self + { + Self { + component_id, + component: comp, + entity_id, + } } } |