From 07aa59a122cc5e14d2fb2e2c6e3d8f82e4397bde Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 14 Aug 2024 20:05:30 +0200 Subject: feat(ecs): add component added event --- ecs/src/lib.rs | 124 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 104 insertions(+), 20 deletions(-) (limited to 'ecs/src/lib.rs') diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 04c9b9f..ed2ccef 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -1,18 +1,21 @@ #![deny(clippy::all, clippy::pedantic)] use std::any::{type_name, TypeId}; +use std::cell::RefCell; use std::collections::HashMap; use std::fmt::Debug; use std::mem::ManuallyDrop; -use std::ops::RangeBounds; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use std::vec::Drain; use crate::actions::Action; use crate::component::storage::Storage as ComponentStorage; use crate::component::{Component, Id as ComponentId, Sequence as ComponentSequence}; use crate::entity::Uid as EntityUid; +use crate::event::component::{ + create_added_id as create_component_added_event_id, + ComponentToAddedEvent, +}; use crate::event::start::Start as StartEvent; use crate::event::{Event, Id as EventId, Ids, Sequence as EventSequence}; use crate::extension::{Collector as ExtensionCollector, Extension}; @@ -20,6 +23,7 @@ use crate::lock::Lock; use crate::query::options::Options as QueryOptions; use crate::sole::Sole; use crate::system::{System, TypeErased as TypeErasedSystem}; +use crate::tuple::Reduce as TupleReduce; use crate::type_name::TypeName; pub mod actions; @@ -64,7 +68,8 @@ impl World /// Will panic if mutable internal lock cannot be acquired. pub fn create_entity(&mut self, components: Comps) -> EntityUid where - Comps: ComponentSequence, + Comps: ComponentSequence + TupleReduce, + Comps::Out: EventSequence, { let (_, entity_uid) = self .data @@ -73,6 +78,10 @@ impl World .expect("Failed to acquire read-write component storage lock") .push_entity(EntityUid::new_unique(), components.into_vec()); + for component_added_event_id in ::ids().iter() { + self.emit_event_by_id(*component_added_event_id); + } + entity_uid } @@ -98,7 +107,7 @@ impl World self.data .events - .entry(EventId::of::()) + .entry(EventT::id()) .or_default() .push(self.systems.len() - 1); @@ -125,7 +134,7 @@ impl World where EventT: Event, { - self.emit_event_by_id(EventId::of::()); + self.emit_event_by_id(EventT::id()); drop(event); } @@ -144,13 +153,22 @@ impl World /// Will panic if a mutable internal lock cannot be acquired. pub fn perform_queued_actions(&self) { - for action in self - .data - .action_queue - .write_nonblock() - .expect("Failed to aquire read-write action queue lock") - .drain(..) + let mut active_action_queue = match *self.data.action_queue.active_queue.borrow() { + ActiveActionQueue::A => &self.data.action_queue.queue_a, + ActiveActionQueue::B => &self.data.action_queue.queue_b, + } + .write_nonblock() + .unwrap_or_else(|err| { + panic!( + "Failed to take read-write action queue lock {:?}: {err}", + self.data.action_queue.active_queue + ); + }); + + let mut has_swapped_active_queue = false; + + for action in active_action_queue.drain(..) { match action { Action::Spawn(components) => { let mut component_storage_lock = @@ -158,8 +176,33 @@ impl World "Failed to acquire read-write component storage lock", ); + let component_ids = components + .iter() + .map(|component| component.id()) + .collect::>(); + component_storage_lock .push_entity(EntityUid::new_unique(), components); + + drop(component_storage_lock); + + if !has_swapped_active_queue { + let mut active_queue = + self.data.action_queue.active_queue.borrow_mut(); + + *active_queue = match *active_queue { + ActiveActionQueue::A => ActiveActionQueue::B, + ActiveActionQueue::B => ActiveActionQueue::A, + }; + + has_swapped_active_queue = true; + } + + for component_id in component_ids { + self.emit_event_by_id(create_component_added_event_id( + component_id, + )); + } } Action::AddComponents(entity_uid, components) => { let mut component_storage_lock = @@ -167,8 +210,33 @@ impl World "Failed to acquire read-write component storage lock", ); + let component_ids = components + .iter() + .map(|component| component.id()) + .collect::>(); + component_storage_lock .add_components_to_entity(entity_uid, components); + + drop(component_storage_lock); + + if !has_swapped_active_queue { + let mut active_queue = + self.data.action_queue.active_queue.borrow_mut(); + + *active_queue = match *active_queue { + ActiveActionQueue::A => ActiveActionQueue::B, + ActiveActionQueue::B => ActiveActionQueue::A, + }; + + has_swapped_active_queue = true; + } + + for component_id in component_ids { + self.emit_event_by_id(create_component_added_event_id( + component_id, + )); + } } Action::RemoveComponents(entity_uid, component_ids) => { let mut component_storage_lock = @@ -237,7 +305,7 @@ pub struct WorldData events: HashMap>, component_storage: Arc>, sole_storage: SoleStorage, - action_queue: Arc>, + action_queue: Arc, } #[derive(Debug)] @@ -261,22 +329,38 @@ impl From> for EntityComponent } } +#[derive(Debug, Default, Clone, Copy)] +enum ActiveActionQueue +{ + #[default] + A, + B, +} + #[derive(Debug, Default)] struct ActionQueue { - queue: Vec, + queue_a: Lock>, + queue_b: Lock>, + active_queue: RefCell, } impl ActionQueue { - fn push(&mut self, action: Action) + fn push(&self, action: Action) { - self.queue.push(action); - } - - fn drain(&mut self, range: impl RangeBounds) -> Drain - { - self.queue.drain(range) + match *self.active_queue.borrow() { + ActiveActionQueue::A => self + .queue_a + .write_nonblock() + .expect("Failed to aquire read-write action queue A lock") + .push(action), + ActiveActionQueue::B => self + .queue_b + .write_nonblock() + .expect("Failed to aquire read-write action queue A lock") + .push(action), + } } } -- cgit v1.2.3-18-g5258