use crate::{ArchetypeComponent, Resources, System, SystemId, TypeAccess, World}; use std::{any::TypeId, borrow::Cow}; pub struct ChainSystem { system_a: SystemA, system_b: SystemB, name: Cow<'static, str>, id: SystemId, archetype_component_access: TypeAccess, component_access: TypeAccess, 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_access(&mut self, world: &World) { self.archetype_component_access.clear(); self.component_access.clear(); self.resource_access.clear(); self.system_a.update_access(world); self.system_b.update_access(world); self.archetype_component_access .extend(self.system_a.archetype_component_access()); self.archetype_component_access .extend(self.system_b.archetype_component_access()); self.component_access .extend(self.system_a.component_access()); self.component_access .extend(self.system_b.component_access()); self.resource_access.extend(self.system_a.resource_access()); self.resource_access.extend(self.system_b.resource_access()); } fn archetype_component_access(&self) -> &TypeAccess { &self.archetype_component_access } fn component_access(&self) -> &TypeAccess { &self.component_access } fn resource_access(&self) -> &TypeAccess { &self.resource_access } fn is_non_send(&self) -> bool { self.system_a.is_non_send() || self.system_b.is_non_send() } 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 apply_buffers(&mut self, world: &mut World, resources: &mut Resources) { self.system_a.apply_buffers(world, resources); self.system_b.apply_buffers(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(), component_access: Default::default(), resource_access: Default::default(), id: SystemId::new(), } } }