diff --git a/lyra-ecs/src/system/batched.rs b/lyra-ecs/src/system/batched.rs index 00de666..d8f4d64 100644 --- a/lyra-ecs/src/system/batched.rs +++ b/lyra-ecs/src/system/batched.rs @@ -1,9 +1,9 @@ use lyra_ecs::World; -use tracing::debug_span; +use tracing::{debug_span, instrument}; use crate::Access; -use super::{System, Criteria, IntoSystem}; +use super::{Criteria, GraphExecutorError, IntoSystem, System}; /// A system that executes a batch of systems in order that they were given. /// You can optionally add criteria that must pass before the systems are @@ -13,6 +13,7 @@ pub struct BatchedSystem { systems: Vec>, criteria: Vec>, criteria_checks: u32, + did_run: bool, } impl BatchedSystem { @@ -47,6 +48,7 @@ impl System for BatchedSystem { } } + #[instrument(skip(self, world))] fn execute(&mut self, world: std::ptr::NonNull) -> anyhow::Result<()> { let mut can_run = true; let mut check_again = false; @@ -69,13 +71,26 @@ impl System for BatchedSystem { } if can_run { + for criteria in self.criteria.iter_mut() { + criteria.modify_world(world); + } + for (idx, system) in self.systems.iter_mut().enumerate() { - let sys_span = debug_span!("batch", system=tracing::field::Empty); - sys_span.record("system", idx); - let _e = sys_span.enter(); + let span = debug_span!("batch", system=idx); + let _e = span.enter(); system.execute(world)?; + + /* let deferred_span = debug_span!("deferred_exec"); + let _e = deferred_span.enter(); + + if let Err(e) = system.execute_deferred(world) + .map_err(|e| GraphExecutorError::Command(e)) { + return Err(e.into()); + } */ } + + self.did_run = true; } if check_again { @@ -87,9 +102,26 @@ impl System for BatchedSystem { Ok(()) } - - fn execute_deferred(&mut self, _: std::ptr::NonNull) -> anyhow::Result<()> { - todo!() + + #[instrument(skip(self, world))] + fn execute_deferred(&mut self, world: std::ptr::NonNull) -> anyhow::Result<()> { + if self.did_run { + for (idx, system) in self.systems.iter_mut().enumerate() { + let span = debug_span!("batch", system=idx); + let _e = span.enter(); + + system.execute_deferred(world) + .map_err(|e| GraphExecutorError::Command(e))?; + } + + for criteria in self.criteria.iter_mut() { + criteria.undo_world_modifications(world); + } + } + + self.did_run = false; + + Ok(()) } } diff --git a/lyra-ecs/src/system/criteria.rs b/lyra-ecs/src/system/criteria.rs index d0a2868..95e4699 100644 --- a/lyra-ecs/src/system/criteria.rs +++ b/lyra-ecs/src/system/criteria.rs @@ -26,13 +26,17 @@ pub trait Criteria { /// * `world` - The ecs world. /// * `check_count` - The amount of times the Criteria has been checked this tick. fn can_run(&mut self, world: NonNull, check_count: u32) -> CriteriaSchedule; -} -impl Criteria for F - where F: FnMut(&mut World, u32) -> CriteriaSchedule -{ - fn can_run(&mut self, mut world: NonNull, check_count: u32) -> CriteriaSchedule { - let world_mut = unsafe { world.as_mut() }; - self(world_mut, check_count) - } + /// Modify the world after the [`Criteria`] in the system batch allows the systems to run. + /// + /// This can be great if this Criteria limits the execution of systems based off of resources. + /// A `FixedTimestep` criteria would use this to replace the [`DeltaTime`] resource in the + /// world to match the timestep time. + fn modify_world(&mut self, world: NonNull); + + /// Undo modifications to the world after the systems in the batch have been executed. + /// + /// The `FixedTimestep` criteria (see docs for [`Criteria::modify_world`]) uses this + /// to replace the [`DeltaTime`] resource with its original value before it was replaced. + fn undo_world_modifications(&mut self, world: NonNull); } \ No newline at end of file