use crate::{ ArchetypeComponent, Resources, System, SystemId, ThreadLocalExecution, TypeAccess, World, }; use std::{any::TypeId, borrow::Cow}; pub struct ChainSystem { system_a: SystemA, system_b: SystemB, name: Cow<'static, str>, id: SystemId, pub(crate) archetype_component_access: TypeAccess, pub(crate) resource_access: TypeAccess, } impl> System for ChainSystem { type In = SystemA::In; type Out = SystemB::Out; fn name(&self) -> Cow<'static, str> { self.name.clone() } fn id(&self) -> SystemId { self.id } fn update(&mut self, world: &World) { self.archetype_component_access.clear(); self.resource_access.clear(); self.system_a.update(world); self.system_b.update(world); self.archetype_component_access .union(self.system_a.archetype_component_access()); self.resource_access.union(self.system_b.resource_access()); } fn archetype_component_access(&self) -> &TypeAccess { &self.archetype_component_access } fn resource_access(&self) -> &TypeAccess { &self.resource_access } fn thread_local_execution(&self) -> ThreadLocalExecution { ThreadLocalExecution::NextFlush } unsafe fn run_unsafe( &mut self, input: Self::In, world: &World, resources: &Resources, ) -> Option { let out = self.system_a.run_unsafe(input, world, resources).unwrap(); self.system_b.run_unsafe(out, world, resources) } fn run_thread_local(&mut self, world: &mut World, resources: &mut Resources) { self.system_a.run_thread_local(world, resources); self.system_b.run_thread_local(world, resources); } fn initialize(&mut self, world: &mut World, resources: &mut Resources) { self.system_a.initialize(world, resources); self.system_b.initialize(world, resources); } } pub trait IntoChainSystem: System + Sized where SystemB: System, { fn chain(self, system: SystemB) -> ChainSystem; } impl IntoChainSystem for SystemA where SystemA: System, SystemB: System, { fn chain(self, system: SystemB) -> ChainSystem { ChainSystem { name: Cow::Owned(format!("Chain({}, {})", self.name(), system.name())), system_a: self, system_b: system, archetype_component_access: Default::default(), resource_access: Default::default(), id: SystemId::new(), } } }