summaryrefslogtreecommitdiff
path: root/ecs/src
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-02-20 23:02:57 +0100
committerHampusM <hampus@hampusmat.com>2024-02-21 23:18:56 +0100
commitb0ef7f2cf8787c5732e0eb5554161ad75179a4b3 (patch)
tree726721a222509f532c02e8e4bbc543edc85f5cb5 /ecs/src
parent3e18fb061538265610041d45c45642ee2686efd9 (diff)
refactor(ecs): add system trait
Diffstat (limited to 'ecs/src')
-rw-r--r--ecs/src/lib.rs37
-rw-r--r--ecs/src/system.rs64
2 files changed, 71 insertions, 30 deletions
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index f824ebc..6106862 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -8,8 +8,10 @@ use std::marker::PhantomData;
use std::slice::IterMut as SliceIterMut;
use crate::component::{Component, Sequence as ComponentSequence};
+use crate::system::{System, TypeErased as TypeErasedSystem};
pub mod component;
+pub mod system;
#[derive(Debug)]
struct Entity
@@ -20,7 +22,7 @@ struct Entity
#[derive(Debug)]
pub struct World<Event>
{
- systems: Vec<Box<dyn AnySystem>>,
+ systems: Vec<TypeErasedSystem>,
events: HashMap<Event, Vec<usize>>,
component_storage: ComponentStorage,
}
@@ -46,12 +48,12 @@ impl<Event> World<Event>
.push(Entity { components: components.into_vec() });
}
- pub fn register_system<Comps>(&mut self, event: Event, system: System<Comps>)
+ pub fn register_system<TSystem, SystemImpl>(&mut self, event: Event, system: TSystem)
where
Event: Hash + PartialEq + Eq,
- Comps: ComponentSequence + 'static,
+ TSystem: System<SystemImpl>,
{
- self.systems.push(Box::new(system));
+ self.systems.push(system.into_type_erased());
self.events
.entry(event)
@@ -75,7 +77,7 @@ impl<Event> World<Event>
for system_index in system_indices {
let system = self.systems.get_mut(system_index).unwrap();
- system.call(&mut self.component_storage);
+ system.run(&mut self.component_storage);
}
}
@@ -95,31 +97,6 @@ impl<Event> Default for World<Event>
}
}
-pub type System<Comps> = fn(Query<Comps>);
-
-trait AnySystem
-{
- fn call(&self, component_storage: &mut ComponentStorage);
-}
-
-impl<Comps> AnySystem for System<Comps>
-where
- Comps: ComponentSequence,
-{
- fn call(&self, component_storage: &mut ComponentStorage)
- {
- self(Query::new(component_storage));
- }
-}
-
-impl Debug for dyn AnySystem
-{
- fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
- {
- formatter.debug_struct("AnySystem").finish_non_exhaustive()
- }
-}
-
#[derive(Debug)]
pub struct Query<'world, Comps>
{
diff --git a/ecs/src/system.rs b/ecs/src/system.rs
new file mode 100644
index 0000000..ecf1885
--- /dev/null
+++ b/ecs/src/system.rs
@@ -0,0 +1,64 @@
+use std::any::Any;
+use std::fmt::Debug;
+
+use crate::component::Sequence as ComponentSequence;
+use crate::{ComponentStorage, Query};
+
+pub trait System<Impl>: 'static
+{
+ type Query<'a>;
+
+ fn run(&self, component_storage: &mut ComponentStorage);
+
+ fn into_type_erased(self) -> TypeErased;
+}
+
+impl<Func, Comps> System<fn(Query<Comps>)> for Func
+where
+ Func: Fn(Query<Comps>) + 'static,
+ Comps: ComponentSequence,
+{
+ type Query<'a> = Query<'a, Comps>;
+
+ fn run(&self, component_storage: &mut ComponentStorage)
+ {
+ self(Query::new(component_storage));
+ }
+
+ fn into_type_erased(self) -> TypeErased
+ {
+ TypeErased {
+ data: Box::new(self),
+ func: Box::new(|data, component_storage| {
+ let me = data.downcast_mut::<Func>().unwrap();
+
+ me.run(component_storage);
+ }),
+ }
+ }
+}
+
+pub struct TypeErased
+{
+ data: Box<dyn Any>,
+ func: Box<TypeErasedFunc>,
+}
+
+impl TypeErased
+{
+ pub fn run(&mut self, component_storage: &mut ComponentStorage)
+ {
+ (self.func)(self.data.as_mut(), component_storage);
+ }
+}
+
+impl Debug for TypeErased
+{
+ fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
+ {
+ formatter.debug_struct("TypeErased").finish_non_exhaustive()
+ }
+}
+
+/// Function in [`TypeErased`] used to run the system.
+type TypeErasedFunc = dyn Fn(&mut dyn Any, &mut ComponentStorage);