summaryrefslogtreecommitdiff
path: root/ecs/src/system/stateful.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-08-26 16:43:40 +0200
committerHampusM <hampus@hampusmat.com>2025-09-11 18:24:48 +0200
commit09981e0173a2427264e432226804292c91e1f920 (patch)
tree70112b6cda98a55da625ec9f6762927f00affe91 /ecs/src/system/stateful.rs
parentce1bade2c21cc3129fa8bc2b4bc67bc4dc2c25c3 (diff)
feat(ecs): add component changed event
Diffstat (limited to 'ecs/src/system/stateful.rs')
-rw-r--r--ecs/src/system/stateful.rs127
1 files changed, 126 insertions, 1 deletions
diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs
index 7b2b608..e74ef31 100644
--- a/ecs/src/system/stateful.rs
+++ b/ecs/src/system/stateful.rs
@@ -1,10 +1,18 @@
+use std::mem::transmute;
use std::panic::{RefUnwindSafe, UnwindSafe};
use seq_macro::seq;
use crate::component::local::SystemWithLocalComponents;
use crate::component::Parts as ComponentParts;
+use crate::event::Emitted as EmittedEvent;
use crate::system::initializable::{Initializable, MaybeInitializableParamTuple};
+use crate::system::observer::{
+ Observe,
+ Observed,
+ Observer,
+ WrapperComponent as ObserverWrapperComponent,
+};
use crate::system::{Into as IntoSystem, Metadata, Param, System, TypeErased};
use crate::World;
@@ -68,9 +76,10 @@ macro_rules! impl_system {
}
}
- impl<Func, #(TParam~I,)*> IntoSystem<fn(#(TParam~I,)*)>
+ impl<'world, Func, #(TParam~I,)*> IntoSystem<'world, fn(#(TParam~I,)*)>
for Func
where
+ #(TParam~I: Param<'world>,)*
Func: Fn(#(TParam~I,)*) + Copy + 'static,
{
type System = Stateful<Func>;
@@ -123,3 +132,119 @@ fn init_initializable_params<'world, SystemT, Params>(
{
Params::init_initializable(system, inputs);
}
+
+macro_rules! impl_observer {
+ ($c: tt) => {
+ seq!(I in 0..$c {
+ impl<'world, ObservedT, Func, #(TParam~I,)*> System<
+ 'world,
+ fn(Observe<'world, ObservedT>, #(TParam~I,)*)
+ > for Stateful<Func>
+ where
+ ObservedT: Observed,
+ Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static,
+ #(TParam~I: Param<'world>,)*
+ {
+ type Callbacks = Callbacks;
+
+ fn finish(self) -> (TypeErased, Callbacks)
+ {
+ unimplemented!();
+ }
+ }
+
+ impl<'world, ObservedT, Func, #(TParam~I,)*> Initializable<
+ 'world,
+ fn(Observe<'world, ObservedT>, #(TParam~I,)*)
+ > for Stateful<Func>
+ where
+ ObservedT: Observed,
+ Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static,
+ #(TParam~I: Param<'world>,)*
+ (#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self>
+ {
+ type Inputs = <
+ (#(TParam~I,)*) as MaybeInitializableParamTuple<'world, Self>
+ >::Inputs;
+
+ fn initialize(mut self, inputs: Self::Inputs) -> Self
+ {
+ init_initializable_params::<_, (#(TParam~I,)*)>(&mut self, inputs);
+
+ self
+ }
+ }
+
+ impl<'world, ObservedT, Func, #(TParam~I,)*> Observer<
+ 'world,
+ fn(Observe<'world, ObservedT>, #(TParam~I,)*)
+ > for Stateful<Func>
+ where
+ ObservedT: Observed,
+ Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static,
+ #(TParam~I: Param<'world>,)*
+ {
+ type ObservedEvents = ObservedT::Events;
+
+ fn observed_events() -> Self::ObservedEvents
+ {
+ ObservedT::events()
+ }
+
+ fn finish_observer(self) -> (ObserverWrapperComponent, Callbacks)
+ {
+ let Self { func, local_components } = self;
+
+ let callbacks = Callbacks { local_components };
+
+ let wrapper_comp = ObserverWrapperComponent::new(
+ move |world, metadata, emitted_event| {
+ // SAFETY: The caller of TypeErased::run ensures the lifetime
+ // is correct
+ let world = unsafe { &*std::ptr::from_ref(world) };
+
+ // SAFETY: The caller of TypeErased::run ensures the lifetime
+ // is correct
+ let emitted_event = unsafe {
+ transmute::<EmittedEvent<'_>, EmittedEvent<'_>>(
+ emitted_event
+ )
+ };
+
+ func(Observe::new(world, emitted_event), #({
+ TParam~I::new(world, &metadata)
+ },)*);
+ },
+ );
+
+ (wrapper_comp, callbacks)
+ }
+ }
+
+ impl<'world, Func, ObservedT, #(TParam~I,)*> IntoSystem<
+ 'world,
+ fn(Observe<'world, ObservedT>,
+ #(TParam~I,)*)
+ > for Func
+ where
+ ObservedT: Observed,
+ #(TParam~I: Param<'world>,)*
+ Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) + Copy + 'static,
+ {
+ type System = Stateful<Func>;
+
+ fn into_system(self) -> Stateful<Func>
+ {
+ Stateful {
+ func: self,
+ local_components: Vec::new(), // TODO: Use Vec::with_capacity
+ }
+ }
+ }
+ });
+ };
+}
+
+seq!(C in 1..16 {
+ impl_observer!(C);
+});