summaryrefslogtreecommitdiff
path: root/ecs/src/system.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/system.rs')
-rw-r--r--ecs/src/system.rs344
1 files changed, 32 insertions, 312 deletions
diff --git a/ecs/src/system.rs b/ecs/src/system.rs
index 40eba8d..95ab7a8 100644
--- a/ecs/src/system.rs
+++ b/ecs/src/system.rs
@@ -1,52 +1,28 @@
-use std::any::{type_name, Any};
-use std::convert::Infallible;
use std::fmt::Debug;
-use std::marker::PhantomData;
-use std::ops::{Deref, DerefMut};
use ecs_macros::Component;
use seq_macro::seq;
-use crate::component::{
- Component,
- FromLockedOptional as FromLockedOptionalComponent,
- FromOptional as FromOptionalComponent,
- FromOptionalMut as FromOptionalMutComponent,
-};
-use crate::lock::{
- Error as LockError,
- Lock,
- MappedReadGuard,
- MappedWriteGuard,
- ReadGuard,
- WriteGuard,
-};
-use crate::tuple::{ReduceElement as TupleReduceElement, Tuple};
+use crate::uid::Uid;
use crate::World;
+pub mod initializable;
+pub mod observer;
pub mod stateful;
-pub trait System<'world, Impl>: 'static
+/// Metadata of a system.
+#[derive(Debug)]
+#[non_exhaustive]
+pub struct Metadata
{
- type Input;
-
- #[must_use]
- fn initialize(self, input: Self::Input) -> Self;
-
- fn run<'this>(&'this self, world: &'world World)
- where
- 'this: 'world;
-
- fn into_type_erased(self) -> TypeErased;
+ pub ent_id: Uid,
+}
- fn get_local_component_mut<LocalComponent: Component>(
- &self,
- ) -> Option<ComponentRefMut<LocalComponent>>;
+pub trait System<'world, Impl>: 'static
+{
+ type Callbacks: Callbacks;
- fn set_local_component<LocalComponent: Component>(
- &mut self,
- local_component: LocalComponent,
- );
+ fn finish(self) -> (TypeErased, Self::Callbacks);
}
macro_rules! impl_system {
@@ -58,58 +34,23 @@ macro_rules! impl_system {
Func: Fn(#(TParam~I,)*) + Copy + 'static,
#(TParam~I: Param<'world, Input = ()>,)*
{
- type Input = Infallible;
-
- fn initialize(self, _input: Self::Input) -> Self
- {
- self
- }
-
- fn run<'this>(&'this self, world: &'world World)
- where
- 'this: 'world
- {
- let func = *self;
-
- func(#({
- TParam~I::new(self, world)
- },)*);
- }
+ type Callbacks = NoCallbacks;
- 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 me = data
- .downcast_ref::<Func>()
- .expect("Function downcast failed");
-
+ 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);
+ self(#({
+ TParam~I::new(world, &metadata)
+ },)*);
}),
- }
- }
-
- fn get_local_component_mut<LocalComponent: Component>(
- &self,
- ) -> Option<ComponentRefMut<LocalComponent>>
- {
- panic!("System does not have any local components");
- }
+ };
- fn set_local_component<LocalComponent: Component>(
- &mut self,
- _local_component: LocalComponent,
- ) {
- panic!("System does not have any local components");
+ (type_erased, NoCallbacks)
}
}
});
@@ -120,7 +61,7 @@ seq!(C in 1..16 {
impl_system!(C);
});
-pub trait Into<Impl>
+pub trait Into<'world, Impl>
{
type System;
@@ -129,7 +70,6 @@ pub trait Into<Impl>
pub struct TypeErased
{
- data: Box<dyn Any>,
run: Box<TypeErasedRunFn>,
}
@@ -139,12 +79,9 @@ impl TypeErased
///
/// # Safety
/// `world_data` must live at least as long as the [`World`] the system belongs to.
- pub unsafe fn run(&self, world: &World)
+ pub unsafe fn run(&self, world: &World, metadata: Metadata)
{
- // You have to dereference for downcasting to work for some reason
- let data = &*self.data;
-
- (self.run)(data, world);
+ (self.run)(world, metadata);
}
}
@@ -157,246 +94,29 @@ impl Debug for TypeErased
}
/// Function in [`TypeErased`] used to run the system.
-type TypeErasedRunFn = dyn Fn(&dyn Any, &World);
+type TypeErasedRunFn = dyn Fn(&World, Metadata);
/// A parameter to a [`System`].
pub trait Param<'world>
{
type Input;
- fn initialize<SystemImpl>(
- system: &mut impl System<'world, SystemImpl>,
- input: Self::Input,
- );
-
- fn new<SystemImpl>(
- system: &'world impl System<'world, SystemImpl>,
- world: &'world World,
- ) -> Self;
+ fn new(world: &'world World, system_metadata: &Metadata) -> Self;
}
/// A type which can be used as input to a [`System`].
pub trait Input: 'static {}
-/// Component tuple reducing operation to get the parameters that takes input.
-pub struct ParamWithInputFilter;
-
-impl<InputT: Input, Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter>
- for InputT
-where
- Accumulator: Tuple,
-{
- type Return = Accumulator::WithElementAtEnd<Self>;
-}
-
-impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for ()
-{
- type Return = Accumulator;
-}
-
-#[derive(Debug)]
-pub struct ComponentRefMut<'a, ComponentT: Component>
-{
- inner: MappedWriteGuard<'a, ComponentT>,
- _ph: PhantomData<ComponentT>,
-}
-
-impl<'a, ComponentT: Component> ComponentRefMut<'a, ComponentT>
-{
- pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self
- {
- Self {
- inner: inner.map(|component| {
- let component_type_name = component.type_name();
-
- component.downcast_mut::<ComponentT>().unwrap_or_else(|| {
- panic!(
- "Cannot downcast component {component_type_name} to type {}",
- type_name::<ComponentT>()
- );
- })
- }),
- _ph: PhantomData,
- }
- }
-}
-
-impl<'component, ComponentT: Component> FromOptionalMutComponent<'component>
- for ComponentRefMut<'component, ComponentT>
-{
- fn from_optional_mut_component(
- inner: Option<WriteGuard<'component, Box<dyn Component>>>,
- _world: &'component World,
- ) -> Self
- {
- Self::new(inner.unwrap_or_else(|| {
- panic!(
- "Component {} was not found in entity",
- type_name::<ComponentT>()
- );
- }))
- }
-}
-
-impl<'component, ComponentT: Component> FromLockedOptionalComponent<'component>
- for ComponentRefMut<'component, ComponentT>
-{
- fn from_locked_optional_component(
- optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>,
- world: &'component World,
- ) -> Result<Self, LockError>
- {
- Ok(Self::from_optional_mut_component(
- optional_component.map(Lock::write_nonblock).transpose()?,
- world,
- ))
- }
-}
-
-impl<'comp, ComponentT> FromOptionalMutComponent<'comp>
- for Option<ComponentRefMut<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_optional_mut_component(
- optional_component: Option<WriteGuard<'comp, Box<dyn Component>>>,
- _world: &'comp World,
- ) -> Self
- {
- optional_component.map(|component| ComponentRefMut::new(component))
- }
-}
-
-impl<'comp, ComponentT> FromLockedOptionalComponent<'comp>
- for Option<ComponentRefMut<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
- _world: &'comp World,
- ) -> Result<Self, LockError>
- {
- optional_component
- .map(|lock| Ok(ComponentRefMut::new(lock.write_nonblock()?)))
- .transpose()
- }
-}
-
-impl<ComponentT: Component> Deref for ComponentRefMut<'_, ComponentT>
-{
- type Target = ComponentT;
-
- fn deref(&self) -> &Self::Target
- {
- &self.inner
- }
-}
-
-impl<ComponentT: Component> DerefMut for ComponentRefMut<'_, ComponentT>
+pub trait Callbacks
{
- fn deref_mut(&mut self) -> &mut Self::Target
- {
- &mut self.inner
- }
+ fn on_created(&mut self, world: &mut World, metadata: Metadata);
}
-#[derive(Debug)]
-pub struct ComponentRef<'a, ComponentT: Component>
-{
- inner: MappedReadGuard<'a, ComponentT>,
- _ph: PhantomData<ComponentT>,
-}
+pub struct NoCallbacks;
-impl<'a, ComponentT: Component> ComponentRef<'a, ComponentT>
+impl Callbacks for NoCallbacks
{
- pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self
- {
- Self {
- inner: inner.map(|component| {
- component.downcast_ref::<ComponentT>().unwrap_or_else(|| {
- panic!(
- "Cannot downcast component {} to type {}",
- component.type_name(),
- type_name::<ComponentT>()
- );
- })
- }),
- _ph: PhantomData,
- }
- }
-}
-
-impl<'component, ComponentT: Component> FromOptionalComponent<'component>
- for ComponentRef<'component, ComponentT>
-{
- fn from_optional_component(
- inner: Option<ReadGuard<'component, Box<dyn Component>>>,
- _world: &'component World,
- ) -> Self
- {
- Self::new(inner.unwrap_or_else(|| {
- panic!(
- "Component {} was not found in entity",
- type_name::<ComponentT>()
- );
- }))
- }
-}
-
-impl<'component, ComponentT: Component> FromLockedOptionalComponent<'component>
- for ComponentRef<'component, ComponentT>
-{
- fn from_locked_optional_component(
- optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>,
- world: &'component World,
- ) -> Result<Self, LockError>
- {
- Ok(Self::from_optional_component(
- optional_component.map(Lock::read_nonblock).transpose()?,
- world,
- ))
- }
-}
-
-impl<'comp, ComponentT> FromOptionalComponent<'comp>
- for Option<ComponentRef<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_optional_component(
- optional_component: Option<ReadGuard<'comp, Box<dyn Component>>>,
- _world: &'comp World,
- ) -> Self
- {
- optional_component.map(|component| ComponentRef::new(component))
- }
-}
-
-impl<'comp, ComponentT> FromLockedOptionalComponent<'comp>
- for Option<ComponentRef<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
- _world: &'comp World,
- ) -> Result<Self, LockError>
- {
- optional_component
- .map(|lock| Ok(ComponentRef::new(lock.read_nonblock()?)))
- .transpose()
- }
-}
-
-impl<ComponentT: Component> Deref for ComponentRef<'_, ComponentT>
-{
- type Target = ComponentT;
-
- fn deref(&self) -> &Self::Target
- {
- &self.inner
- }
+ fn on_created(&mut self, _world: &mut World, _metadata: Metadata) {}
}
#[derive(Debug, Component)]