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.rs170
1 files changed, 132 insertions, 38 deletions
diff --git a/ecs/src/system.rs b/ecs/src/system.rs
index 046d25b..b410d8f 100644
--- a/ecs/src/system.rs
+++ b/ecs/src/system.rs
@@ -3,17 +3,25 @@ use std::convert::Infallible;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
-use std::panic::{RefUnwindSafe, UnwindSafe};
+use ecs_macros::Component;
use seq_macro::seq;
use crate::component::{
Component,
+ FromLockedOptional as FromLockedOptionalComponent,
FromOptional as FromOptionalComponent,
FromOptionalMut as FromOptionalMutComponent,
};
-use crate::lock::{ReadGuard, WriteGuard};
-use crate::tuple::{ReduceElement as TupleReduceElement, With as TupleWith};
+use crate::lock::{
+ Error as LockError,
+ Lock,
+ MappedReadGuard,
+ MappedWriteGuard,
+ ReadGuard,
+ WriteGuard,
+};
+use crate::tuple::{ReduceElement as TupleReduceElement, Tuple};
use crate::World;
pub mod stateful;
@@ -47,8 +55,8 @@ macro_rules! impl_system {
impl<'world, Func, #(TParam~I,)*> System<'world, fn(#(TParam~I,)*)>
for Func
where
- Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static,
- #(TParam~I: Param<'world, Flags = NoInitParamFlag>,)*
+ Func: Fn(#(TParam~I,)*) + Copy + 'static,
+ #(TParam~I: Param<'world, Input = ()>,)*
{
type Input = Infallible;
@@ -121,7 +129,7 @@ pub trait Into<Impl>
pub struct TypeErased
{
- data: Box<dyn Any + RefUnwindSafe + UnwindSafe>,
+ data: Box<dyn Any>,
run: Box<TypeErasedRunFn>,
}
@@ -149,13 +157,12 @@ impl Debug for TypeErased
}
/// Function in [`TypeErased`] used to run the system.
-type TypeErasedRunFn = dyn Fn(&dyn Any, &World) + RefUnwindSafe + UnwindSafe;
+type TypeErasedRunFn = dyn Fn(&dyn Any, &World);
/// A parameter to a [`System`].
-pub unsafe trait Param<'world>
+pub trait Param<'world>
{
type Input;
- type Flags;
fn initialize<SystemImpl>(
system: &mut impl System<'world, SystemImpl>,
@@ -168,8 +175,6 @@ pub unsafe trait Param<'world>
) -> Self;
}
-pub struct NoInitParamFlag {}
-
/// A type which can be used as input to a [`System`].
pub trait Input: 'static {}
@@ -179,9 +184,9 @@ pub struct ParamWithInputFilter;
impl<InputT: Input, Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter>
for InputT
where
- Accumulator: TupleWith<Self>,
+ Accumulator: Tuple,
{
- type Return = Accumulator::With;
+ type Return = Accumulator::WithElementAtEnd<Self>;
}
impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for ()
@@ -192,7 +197,7 @@ impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for ()
#[derive(Debug)]
pub struct ComponentRefMut<'a, ComponentT: Component>
{
- inner: WriteGuard<'a, Box<dyn Component>>,
+ inner: MappedWriteGuard<'a, ComponentT>,
_ph: PhantomData<ComponentT>,
}
@@ -200,7 +205,19 @@ impl<'a, ComponentT: Component> ComponentRefMut<'a, ComponentT>
{
pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self
{
- Self { inner, _ph: PhantomData }
+ 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,
+ }
}
}
@@ -212,15 +229,29 @@ impl<'component, ComponentT: Component> FromOptionalMutComponent<'component>
_world: &'component World,
) -> Self
{
- Self {
- inner: inner.unwrap_or_else(|| {
- panic!(
- "Component {} was not found in entity",
- type_name::<ComponentT>()
- );
- }),
- _ph: PhantomData,
- }
+ 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| lock.write_nonblock())
+ .transpose()?,
+ world,
+ ))
}
}
@@ -238,13 +269,29 @@ where
}
}
+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<'a, ComponentT: Component> Deref for ComponentRefMut<'a, ComponentT>
{
type Target = ComponentT;
fn deref(&self) -> &Self::Target
{
- self.inner.downcast_ref().unwrap()
+ &self.inner
}
}
@@ -252,14 +299,14 @@ impl<'a, ComponentT: Component> DerefMut for ComponentRefMut<'a, ComponentT>
{
fn deref_mut(&mut self) -> &mut Self::Target
{
- self.inner.downcast_mut().unwrap()
+ &mut self.inner
}
}
#[derive(Debug)]
pub struct ComponentRef<'a, ComponentT: Component>
{
- inner: ReadGuard<'a, Box<dyn Component>>,
+ inner: MappedReadGuard<'a, ComponentT>,
_ph: PhantomData<ComponentT>,
}
@@ -267,7 +314,18 @@ impl<'a, ComponentT: Component> ComponentRef<'a, ComponentT>
{
pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self
{
- Self { inner, _ph: PhantomData }
+ 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,
+ }
}
}
@@ -279,15 +337,29 @@ impl<'component, ComponentT: Component> FromOptionalComponent<'component>
_world: &'component World,
) -> Self
{
- Self {
- inner: inner.unwrap_or_else(|| {
- panic!(
- "Component {} was not found in entity",
- type_name::<ComponentT>()
- );
- }),
- _ph: PhantomData,
- }
+ 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| lock.read_nonblock())
+ .transpose()?,
+ world,
+ ))
}
}
@@ -305,12 +377,34 @@ where
}
}
+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<'a, ComponentT: Component> Deref for ComponentRef<'a, ComponentT>
{
type Target = ComponentT;
fn deref(&self) -> &Self::Target
{
- self.inner.downcast_ref().unwrap()
+ &self.inner
}
}
+
+#[derive(Debug, Component)]
+pub(crate) struct SystemComponent
+{
+ pub(crate) system: TypeErased,
+}