From b9668a6ba06af650eab5c77c78a487556af20a6b Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 6 Mar 2024 00:45:51 +0100 Subject: feat(ecs): add queueing up spawning entities from systems --- ecs/src/actions.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ecs/src/lib.rs | 18 ++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 ecs/src/actions.rs diff --git a/ecs/src/actions.rs b/ecs/src/actions.rs new file mode 100644 index 0000000..d67f895 --- /dev/null +++ b/ecs/src/actions.rs @@ -0,0 +1,63 @@ +use std::any::Any; + +use crate::component::{Component, Sequence as ComponentSequence}; +use crate::system::{NoInitParamFlag, Param as SystemParam, System}; +use crate::tuple::FilterExclude as TupleFilterExclude; +use crate::WorldData; + +/// Used to to queue up actions for a [`World`] to perform. +#[derive(Debug)] +pub struct Actions<'world> +{ + world_data: &'world mut WorldData, +} + +impl<'world> Actions<'world> +{ + /// Adds a spawning a new entity to the action queue. + pub fn spawn(&mut self, components: Comps) + { + self.world_data + .action_queue + .push(Action::Spawn(components.into_vec())); + } +} + +unsafe impl<'world> SystemParam<'world> for Actions<'world> +{ + type Flags = NoInitParamFlag; + type Input = TupleFilterExclude; + + fn initialize(_system: &mut impl System, _input: Self::Input) + { + } + + fn new( + _system: &'world mut impl System, + world_data: &'world mut WorldData, + ) -> Self + { + Self { world_data } + } + + fn is_compatible>() -> bool + { + let other_comparable = Other::get_comparable(); + + other_comparable.downcast_ref::().is_none() + } + + fn get_comparable() -> Box + { + Box::new(()) + } +} + +/// A action for a [`System`] to perform. +#[derive(Debug)] +pub enum Action +{ + Spawn(Vec>), +} + +struct Comparable; diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 0c06472..6b9373c 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -6,6 +6,7 @@ use std::fmt::Debug; use std::marker::PhantomData; use std::slice::{Iter as SliceIter, IterMut as SliceIterMut}; +use crate::actions::Action; use crate::component::{Component, Sequence as ComponentSequence}; use crate::event::{Event, Id as EventId}; use crate::system::{ @@ -16,6 +17,7 @@ use crate::system::{ }; use crate::tuple::FilterExclude as TupleFilterExclude; +pub mod actions; pub mod component; pub mod event; pub mod system; @@ -94,6 +96,21 @@ impl World { Query::new(&mut self.data) } + + /// Peforms the actions that have been queued up using [`Actions`]. + pub fn perform_queued_actions(&mut self) + { + for action in self.data.action_queue.drain(..) { + match action { + Action::Spawn(components) => { + self.data + .component_storage + .entities + .push(Entity { components }); + } + } + } + } } #[derive(Debug, Default)] @@ -101,6 +118,7 @@ pub struct WorldData { events: HashMap>, component_storage: ComponentStorage, + action_queue: Vec, } #[derive(Debug)] -- cgit v1.2.3-18-g5258