summaryrefslogtreecommitdiff
path: root/ecs/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/lib.rs')
-rw-r--r--ecs/src/lib.rs158
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,
+ }
}
}