summaryrefslogtreecommitdiff
path: root/engine-ecs/src/system
diff options
context:
space:
mode:
Diffstat (limited to 'engine-ecs/src/system')
-rw-r--r--engine-ecs/src/system/initializable.rs4
-rw-r--r--engine-ecs/src/system/observer.rs107
-rw-r--r--engine-ecs/src/system/stateful.rs86
3 files changed, 67 insertions, 130 deletions
diff --git a/engine-ecs/src/system/initializable.rs b/engine-ecs/src/system/initializable.rs
index b6ec8e8..fa925e0 100644
--- a/engine-ecs/src/system/initializable.rs
+++ b/engine-ecs/src/system/initializable.rs
@@ -2,11 +2,11 @@ use std::marker::PhantomData;
use seq_macro::seq;
-use crate::system::{Input, Param as SystemParam, System};
+use crate::system::{Input, Param as SystemParam};
use crate::tuple::{Reduce as TupleReduce, ReduceElement as TupleReduceElement, Tuple};
/// A initializable system.
-pub trait Initializable<'world, Impl>: System<'world, Impl>
+pub trait Initializable<'world, Impl>
{
type Inputs;
diff --git a/engine-ecs/src/system/observer.rs b/engine-ecs/src/system/observer.rs
index 1ad7496..e5345cd 100644
--- a/engine-ecs/src/system/observer.rs
+++ b/engine-ecs/src/system/observer.rs
@@ -7,15 +7,13 @@ use std::slice::Iter as SliceIter;
use seq_macro::seq;
use crate::entity::Handle as EntityHandle;
-use crate::error::Error;
use crate::event::Emitted as EmittedEvent;
use crate::pair::Pair;
use crate::system::{
- Metadata,
+ Callbacks,
NoCallbacks,
Param,
ReturnValue as SystemReturnValue,
- System,
TypeErased as TypeErasedSystem,
};
use crate::uid::Uid;
@@ -46,13 +44,14 @@ where
}
/// Observer system.
-pub trait Observer<'world, Impl>: System<'world, Impl>
+pub trait Observer<'world, Impl>
{
+ type Callbacks: Callbacks;
type ObservedEvents: Array<Pair<Uid, Uid>>;
fn observed_events() -> Self::ObservedEvents;
- fn finish_observer(self) -> (WrapperComponent, Self::Callbacks);
+ fn finish_observer(self) -> (TypeErasedSystem, Self::Callbacks);
}
pub struct Observe<'world, ObservedT: Observed>
@@ -155,36 +154,17 @@ impl<'world, ObservedT: Observed> EventMatch<'world, ObservedT>
macro_rules! impl_observer {
($c: tt) => {
seq!(I in 0..$c {
- impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> System<
- 'world,
- fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret
- > for Func
- where
- ObservedT: Observed,
- Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static,
- Ret: SystemReturnValue,
- #(TParam~I: Param<'world, Input = ()>,)*
- {
- type Callbacks = NoCallbacks;
-
- fn finish(self) -> (TypeErasedSystem, NoCallbacks)
- {
- const {
- panic!("Observers cannot be used as regular systems");
- }
- }
- }
-
impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> Observer<
'world,
fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret
> for Func
where
ObservedT: Observed,
- Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static,
+ Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + Copy + 'static,
Ret: SystemReturnValue,
#(TParam~I: Param<'world, Input = ()>,)*
{
+ type Callbacks = NoCallbacks;
type ObservedEvents = ObservedT::Events;
fn observed_events() -> Self::ObservedEvents
@@ -192,16 +172,24 @@ macro_rules! impl_observer {
ObservedT::events()
}
- fn finish_observer(self) -> (WrapperComponent, NoCallbacks)
+ fn finish_observer(self) -> (TypeErasedSystem, NoCallbacks)
{
- #[allow(unused)]
+ #![allow(unused)]
- let wrapper_comp = WrapperComponent::new(
- move |world, metadata, emitted_event| {
+ crate::util::const_assert!(
+ size_of::<Func>() == 0,
+ "System function is not zero-sized (not function pointer)"
+ );
+
+ let system = TypeErasedSystem {
+ run: |world, metadata, emitted_event| {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
let world = unsafe { &*std::ptr::from_ref(world) };
+ let emitted_event =
+ emitted_event.expect("No event info passed to observer");
+
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
let emitted_event = unsafe {
@@ -210,14 +198,16 @@ macro_rules! impl_observer {
)
};
- self(Observe::new(world, emitted_event), #({
+ let func = unsafe { std::mem::zeroed::<Func>() };
+
+ func(Observe::new(world, emitted_event), #({
TParam~I::new(world, &metadata)
},)*).into_result()
},
- type_name::<Func>()
- );
+ name: type_name::<Func>()
+ };
- (wrapper_comp, NoCallbacks)
+ (system, NoCallbacks)
}
}
});
@@ -227,52 +217,3 @@ macro_rules! impl_observer {
seq!(C in 0..16 {
impl_observer!(C);
});
-
-#[derive(Component)]
-pub struct WrapperComponent
-{
- run: Box<RunFn>,
- name: &'static str,
-}
-
-impl WrapperComponent
-{
- pub fn new(
- run: impl Fn(&World, Metadata, EmittedEvent<'_>) -> Result<(), Error> + 'static,
- name: &'static str,
- ) -> Self
- {
- Self { run: Box::new(run), name }
- }
-
- /// Runs the observer system.
- ///
- /// # Safety
- /// `world` must live at least as long as the [`World`] the system belongs to.
- pub unsafe fn run(
- &self,
- world: &World,
- metadata: Metadata,
- emitted_event: EmittedEvent<'_>,
- ) -> Result<(), Error>
- {
- (self.run)(world, metadata, emitted_event)
- }
-
- pub fn name(&self) -> &'static str
- {
- self.name
- }
-}
-
-impl Debug for WrapperComponent
-{
- fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
- {
- formatter
- .debug_struct("WrapperComponent")
- .finish_non_exhaustive()
- }
-}
-
-type RunFn = dyn Fn(&World, Metadata, EmittedEvent<'_>) -> Result<(), Error>;
diff --git a/engine-ecs/src/system/stateful.rs b/engine-ecs/src/system/stateful.rs
index b73baeb..c9354c3 100644
--- a/engine-ecs/src/system/stateful.rs
+++ b/engine-ecs/src/system/stateful.rs
@@ -1,4 +1,5 @@
use std::any::type_name;
+use std::marker::PhantomData;
use std::mem::transmute;
use seq_macro::seq;
@@ -7,12 +8,7 @@ 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::observer::{Observe, Observed, Observer};
use crate::system::{
Into as IntoSystem,
Metadata,
@@ -24,10 +20,10 @@ use crate::system::{
use crate::World;
/// A stateful system.
-pub struct Stateful<Func>
+pub struct Stateful<Func: Copy + 'static>
{
- func: Func,
local_components: Vec<ComponentParts>,
+ _pd: PhantomData<Func>,
}
macro_rules! impl_system {
@@ -36,7 +32,7 @@ macro_rules! impl_system {
impl<'world, Func, Ret, #(TParam~I,)*>
System<'world, fn(#(TParam~I,)*) -> Ret> for Stateful<Func>
where
- Func: Fn(#(TParam~I,)*) -> Ret + 'static,
+ Func: Fn(#(TParam~I,)*) -> Ret + Copy + 'static,
Ret: ReturnValue,
#(TParam~I: Param<'world, Input: 'static>,)*
{
@@ -44,22 +40,29 @@ macro_rules! impl_system {
fn finish(self) -> (TypeErased, Self::Callbacks)
{
- let Self { func, local_components } = self;
+ crate::util::const_assert!(
+ size_of::<Func>() == 0,
+ "System function is not zero-sized (not function pointer)"
+ );
+
+ let Self { local_components, .. } = self;
let callbacks = Callbacks { local_components };
let type_erased = TypeErased {
- run: Box::new(move |world, metadata| {
+ run: |world, metadata, _| {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
let world = unsafe { &*std::ptr::from_ref(world) };
+ let func = unsafe { std::mem::zeroed::<Func>() };
+
func(#({
TParam~I::new(&world, &metadata)
},)*);
Ok(())
- }),
+ },
name: type_name::<Func>()
};
@@ -71,7 +74,7 @@ macro_rules! impl_system {
impl<'world, Func, Ret, #(TParam~I,)*>
Initializable<'world, fn(#(TParam~I,)*) -> Ret> for Stateful<Func>
where
- Func: Fn(#(TParam~I,)*) -> Ret + 'static,
+ Func: Fn(#(TParam~I,)*) -> Ret + Copy + 'static,
Ret: ReturnValue,
#(TParam~I: Param<'world, Input: 'static>,)*
(#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self>
@@ -91,7 +94,7 @@ macro_rules! impl_system {
impl<'world, Func, Ret, #(TParam~I,)*>
IntoSystem<'world, fn(#(TParam~I,)*) -> Ret> for Func
where
- Func: Fn(#(TParam~I,)*) -> Ret + 'static,
+ Func: Fn(#(TParam~I,)*) -> Ret + Copy + 'static,
Ret: ReturnValue,
#(TParam~I: Param<'world>,)*
{
@@ -100,8 +103,8 @@ macro_rules! impl_system {
fn into_system(self) -> Self::System
{
Self::System {
- func: self,
local_components: Vec::new(), // TODO: Use Vec::with_capacity
+ _pd: PhantomData
}
}
}
@@ -113,7 +116,7 @@ seq!(C in 1..16 {
impl_system!(C);
});
-impl<Func> SystemWithLocalComponents for Stateful<Func>
+impl<Func: Copy + 'static> SystemWithLocalComponents for Stateful<Func>
{
fn add_local_component(&mut self, component_parts: ComponentParts)
{
@@ -149,31 +152,13 @@ fn init_initializable_params<'world, SystemT, Params>(
macro_rules! impl_observer {
($c: tt) => {
seq!(I in 0..$c {
- impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> System<
- 'world,
- fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret
- > for Stateful<Func>
- where
- ObservedT: Observed,
- Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static,
- Ret: ReturnValue,
- #(TParam~I: Param<'world>,)*
- {
- type Callbacks = Callbacks;
-
- fn finish(self) -> (TypeErased, Callbacks)
- {
- unimplemented!();
- }
- }
-
impl<'world, ObservedT, Func, Ret, #(TParam~I,)*> Initializable<
'world,
fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret
> for Stateful<Func>
where
ObservedT: Observed,
- Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static,
+ Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + Copy + 'static,
Ret: ReturnValue,
#(TParam~I: Param<'world>,)*
(#(TParam~I,)*): MaybeInitializableParamTuple<'world, Self>
@@ -196,10 +181,11 @@ macro_rules! impl_observer {
> for Stateful<Func>
where
ObservedT: Observed,
- Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static,
+ Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + Copy + 'static,
Ret: ReturnValue,
#(TParam~I: Param<'world>,)*
{
+ type Callbacks = Callbacks;
type ObservedEvents = ObservedT::Events;
fn observed_events() -> Self::ObservedEvents
@@ -207,20 +193,28 @@ macro_rules! impl_observer {
ObservedT::events()
}
- fn finish_observer(self) -> (ObserverWrapperComponent, Callbacks)
+ fn finish_observer(self) -> (TypeErased, Callbacks)
{
#![allow(unused)]
- let Self { func, local_components } = self;
+ crate::util::const_assert!(
+ size_of::<Func>() == 0,
+ "System function is not zero-sized (not function pointer)"
+ );
+
+ let Self { local_components, .. } = self;
let callbacks = Callbacks { local_components };
- let wrapper_comp = ObserverWrapperComponent::new(
- move |world, metadata, emitted_event| {
+ let system = TypeErased {
+ run: |world, metadata, emitted_event| {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
let world = unsafe { &*std::ptr::from_ref(world) };
+ let emitted_event =
+ emitted_event.expect("No event info passed to observer");
+
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
let emitted_event = unsafe {
@@ -229,14 +223,16 @@ macro_rules! impl_observer {
)
};
+ let func = unsafe { std::mem::zeroed::<Func>() };
+
func(Observe::new(world, emitted_event), #({
TParam~I::new(world, &metadata)
},)*).into_result()
},
- type_name::<Func>()
- );
+ name: type_name::<Func>()
+ };
- (wrapper_comp, callbacks)
+ (system, callbacks)
}
}
@@ -246,7 +242,7 @@ macro_rules! impl_observer {
> for Func
where
ObservedT: Observed,
- Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + 'static,
+ Func: Fn(Observe<'world, ObservedT>, #(TParam~I,)*) -> Ret + Copy + 'static,
Ret: ReturnValue,
#(TParam~I: Param<'world>,)*
{
@@ -255,8 +251,8 @@ macro_rules! impl_observer {
fn into_system(self) -> Stateful<Func>
{
Stateful {
- func: self,
local_components: Vec::new(), // TODO: Use Vec::with_capacity
+ _pd: PhantomData
}
}
}