ecs: fix BatchedSystem, implement ways for `Criteria`s to modify the world before and after execution
This commit is contained in:
parent
e2c6b557bb
commit
53837d469b
|
@ -1,9 +1,9 @@
|
||||||
use lyra_ecs::World;
|
use lyra_ecs::World;
|
||||||
use tracing::debug_span;
|
use tracing::{debug_span, instrument};
|
||||||
|
|
||||||
use crate::Access;
|
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.
|
/// 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
|
/// You can optionally add criteria that must pass before the systems are
|
||||||
|
@ -13,6 +13,7 @@ pub struct BatchedSystem {
|
||||||
systems: Vec<Box<dyn System>>,
|
systems: Vec<Box<dyn System>>,
|
||||||
criteria: Vec<Box<dyn Criteria>>,
|
criteria: Vec<Box<dyn Criteria>>,
|
||||||
criteria_checks: u32,
|
criteria_checks: u32,
|
||||||
|
did_run: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BatchedSystem {
|
impl BatchedSystem {
|
||||||
|
@ -47,6 +48,7 @@ impl System for BatchedSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self, world))]
|
||||||
fn execute(&mut self, world: std::ptr::NonNull<World>) -> anyhow::Result<()> {
|
fn execute(&mut self, world: std::ptr::NonNull<World>) -> anyhow::Result<()> {
|
||||||
let mut can_run = true;
|
let mut can_run = true;
|
||||||
let mut check_again = false;
|
let mut check_again = false;
|
||||||
|
@ -69,13 +71,26 @@ impl System for BatchedSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
if can_run {
|
if can_run {
|
||||||
|
for criteria in self.criteria.iter_mut() {
|
||||||
|
criteria.modify_world(world);
|
||||||
|
}
|
||||||
|
|
||||||
for (idx, system) in self.systems.iter_mut().enumerate() {
|
for (idx, system) in self.systems.iter_mut().enumerate() {
|
||||||
let sys_span = debug_span!("batch", system=tracing::field::Empty);
|
let span = debug_span!("batch", system=idx);
|
||||||
sys_span.record("system", idx);
|
let _e = span.enter();
|
||||||
let _e = sys_span.enter();
|
|
||||||
|
|
||||||
system.execute(world)?;
|
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 {
|
if check_again {
|
||||||
|
@ -87,9 +102,26 @@ impl System for BatchedSystem {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_deferred(&mut self, _: std::ptr::NonNull<World>) -> anyhow::Result<()> {
|
#[instrument(skip(self, world))]
|
||||||
todo!()
|
fn execute_deferred(&mut self, world: std::ptr::NonNull<World>) -> 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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,17 @@ pub trait Criteria {
|
||||||
/// * `world` - The ecs world.
|
/// * `world` - The ecs world.
|
||||||
/// * `check_count` - The amount of times the Criteria has been checked this tick.
|
/// * `check_count` - The amount of times the Criteria has been checked this tick.
|
||||||
fn can_run(&mut self, world: NonNull<World>, check_count: u32) -> CriteriaSchedule;
|
fn can_run(&mut self, world: NonNull<World>, check_count: u32) -> CriteriaSchedule;
|
||||||
}
|
|
||||||
|
|
||||||
impl<F> Criteria for F
|
/// Modify the world after the [`Criteria`] in the system batch allows the systems to run.
|
||||||
where F: FnMut(&mut World, u32) -> CriteriaSchedule
|
///
|
||||||
{
|
/// This can be great if this Criteria limits the execution of systems based off of resources.
|
||||||
fn can_run(&mut self, mut world: NonNull<World>, check_count: u32) -> CriteriaSchedule {
|
/// A `FixedTimestep` criteria would use this to replace the [`DeltaTime`] resource in the
|
||||||
let world_mut = unsafe { world.as_mut() };
|
/// world to match the timestep time.
|
||||||
self(world_mut, check_count)
|
fn modify_world(&mut self, world: NonNull<World>);
|
||||||
}
|
|
||||||
|
/// 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<World>);
|
||||||
}
|
}
|
Loading…
Reference in New Issue