use crate::{ ArchetypeComponent, IntoSystem, 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 Input = SystemA::Input; type Output = SystemB::Output; fn name(&self) -> Cow<'static, str> { self.name.clone() } fn id(&self) -> SystemId { self.id } fn is_initialized(&self) -> bool { self.system_a.is_initialized() && self.system_b.is_initialized() } 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::Input, 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); } } pub trait IntoChainSystem: IntoSystem + Sized where IntoB: IntoSystem, SystemA: System, SystemB: System, { fn chain(self, system: IntoB) -> ChainSystem; } impl IntoChainSystem for IntoA where SystemA: System, SystemB: System, IntoA: IntoSystem, IntoB: IntoSystem, { fn chain(self, system: IntoB) -> ChainSystem { let system_a = self.system(); let system_b = system.system(); ChainSystem { name: Cow::Owned(format!("Chain({}, {})", system_a.name(), system_b.name())), system_a, system_b, archetype_component_access: Default::default(), resource_access: Default::default(), id: SystemId::new(), } } }