From e229b104593d3afede47cc07e9917a42d6d13e60 Mon Sep 17 00:00:00 2001 From: HampusM Date: Fri, 15 Aug 2025 13:38:27 +0200 Subject: refactor(ecs): store local components as system entity components --- ecs/src/system/stateful.rs | 165 +++++++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 94 deletions(-) (limited to 'ecs/src/system/stateful.rs') diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs index 2ec448c..93bfd5e 100644 --- a/ecs/src/system/stateful.rs +++ b/ecs/src/system/stateful.rs @@ -1,137 +1,81 @@ -use std::any::{type_name, Any, TypeId}; use std::panic::{RefUnwindSafe, UnwindSafe}; -use hashbrown::HashMap; use seq_macro::seq; -use crate::component::{Component, HandleMut as ComponentHandleMut}; -use crate::lock::Lock; -use crate::system::{ - Into as IntoSystem, - Param, - ParamWithInputFilter, - System, - TypeErased, -}; -use crate::tuple::{ - Reduce as TupleReduce, - Tuple, - WithAllElemLtStatic as TupleWithAllElemLtStatic, -}; -use crate::uid::Uid; +use crate::component::local::SystemWithLocalComponents; +use crate::component::Parts as ComponentParts; +use crate::system::initializable::{Initializable, MaybeInitializableParamTuple}; +use crate::system::{Into as IntoSystem, Metadata, Param, System, TypeErased}; use crate::World; /// A stateful system. pub struct Stateful { func: Func, - local_components: HashMap>>, + local_components: Vec, } macro_rules! impl_system { ($c: tt) => { seq!(I in 0..$c { - impl<'world, Func, #(TParam~I,)*> System<'world, fn(&'world (), #(TParam~I,)*)> - for Stateful + impl<'world, Func, #(TParam~I,)*> + System<'world, fn(&'world (), #(TParam~I,)*)> for Stateful where Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, - #(TParam~I: Param<'world>,)* - #(TParam~I::Input: 'static,)* - (#(TParam~I::Input,)*): TupleReduce< - ParamWithInputFilter, - Out: Tuple - >, + #(TParam~I: Param<'world, Input: 'static>,)* { - type Input = - <(#(TParam~I::Input,)*) as TupleReduce>::Out; + type Callbacks = Callbacks; - fn initialize(mut self, input: Self::Input) -> Self - { - let mut option_input = input.into_in_options(); - - let mut index = 0; - - #( - if TypeId::of::() != - TypeId::of::<()>() - { - let input = option_input - .get_mut::>(index) - .expect("Input element index out of range") - .take() - .expect("Input element is already taken"); - - TParam~I::initialize( - &mut self, - input - ); - - #[allow(unused_assignments)] - { - index += 1; - } - } - )* - - self - } - - fn run<'this>(&'this self, world: &'world World) + fn run<'this>(&'this self, world: &'world World, metadata: Metadata) where 'this: 'world { let func = self.func; func(#({ - TParam~I::new(self, &world) + TParam~I::new(&world, &metadata) },)*); } - fn into_type_erased(self) -> TypeErased + fn finish(self) -> (TypeErased, Self::Callbacks) { - TypeErased { - data: Box::new(self), - run: Box::new(|data, world| { - // SAFETY: The caller of TypeErased::run ensures the lifetime - // is correct - let data = unsafe { &*std::ptr::from_ref::(data) }; + let Self { func, local_components } = self; - let me = data.downcast_ref::().unwrap(); + let callbacks = Callbacks { local_components }; + let type_erased = TypeErased { + run: Box::new(move |world, metadata| { // SAFETY: The caller of TypeErased::run ensures the lifetime // is correct let world = unsafe { &*std::ptr::from_ref(world) }; - me.run(world); + func(#({ + TParam~I::new(&world, &metadata) + },)*); }), - } - } + }; - fn get_local_component_mut( - &self, - ) -> Option> - { - let local_component = self.local_components - .get(&LocalComponent::id())? - .write_nonblock() - .expect("Failed to aquire read-write local component lock"); - Some(ComponentHandleMut::new(local_component).unwrap()) + (type_erased, callbacks) } + } + + impl<'world, Func, #(TParam~I,)*> + Initializable<'world, fn(&'world (), #(TParam~I,)*)> for Stateful + where + Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, + #(TParam~I: Param<'world, Input: 'static>,)* + (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self> + { + type Inputs = < + (#(TParam~I,)*) as MaybeInitializableParamTuple<'world, Self> + >::Inputs; - fn set_local_component( - &mut self, - local_component: LocalComponent, - ) + fn initialize(mut self, inputs: Self::Inputs) -> Self { - self.local_components - .insert( - LocalComponent::id(), - Lock::new( - Box::new(local_component), - type_name::() - ) - ); + init_initializable_params::<_, (#(TParam~I,)*)>(&mut self, inputs); + + self } } @@ -146,7 +90,7 @@ macro_rules! impl_system { { Self::System { func: self, - local_components: HashMap::new(), + local_components: Vec::new(), // TODO: Use Vec::with_capacity } } } @@ -157,3 +101,36 @@ macro_rules! impl_system { seq!(C in 1..16 { impl_system!(C); }); + +impl SystemWithLocalComponents for Stateful +{ + fn add_local_component(&mut self, component_parts: ComponentParts) + { + self.local_components.push(component_parts); + } +} + +#[derive(Debug)] +pub struct Callbacks +{ + local_components: Vec, +} + +impl crate::system::Callbacks for Callbacks +{ + fn on_created(&mut self, world: &mut World, metadata: Metadata) + { + for local_comp_parts in self.local_components.drain(..) { + world.add_component(metadata.ent_id, local_comp_parts); + } + } +} + +fn init_initializable_params<'world, SystemT, Params>( + system: &mut SystemT, + inputs: Params::Inputs, +) where + Params: MaybeInitializableParamTuple<'world, SystemT>, +{ + Params::init_initializable(system, inputs); +} -- cgit v1.2.3-18-g5258