2021-02-09 20:14:10 +00:00
|
|
|
mod executor;
|
|
|
|
mod executor_parallel;
|
2021-02-18 21:20:37 +00:00
|
|
|
mod label;
|
2020-12-13 02:04:42 +00:00
|
|
|
mod stage;
|
2021-02-18 21:20:37 +00:00
|
|
|
//mod stageless;
|
2020-12-13 02:04:42 +00:00
|
|
|
mod state;
|
2021-02-09 20:14:10 +00:00
|
|
|
mod system_container;
|
|
|
|
mod system_descriptor;
|
|
|
|
mod system_set;
|
2020-07-17 02:20:51 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
pub use executor::*;
|
|
|
|
pub use executor_parallel::*;
|
2021-02-18 21:20:37 +00:00
|
|
|
pub use label::*;
|
2020-12-13 02:04:42 +00:00
|
|
|
pub use stage::*;
|
|
|
|
pub use state::*;
|
2021-02-09 20:14:10 +00:00
|
|
|
pub use system_container::*;
|
|
|
|
pub use system_descriptor::*;
|
|
|
|
pub use system_set::*;
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
use crate::{
|
|
|
|
ArchetypeComponent, BoxedSystem, IntoSystem, Resources, System, SystemId, TypeAccess, World,
|
|
|
|
};
|
2020-12-13 02:04:42 +00:00
|
|
|
use bevy_utils::HashMap;
|
2021-02-09 20:14:10 +00:00
|
|
|
use std::{any::TypeId, borrow::Cow};
|
2020-12-13 02:04:42 +00:00
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct Schedule {
|
2021-02-18 21:20:37 +00:00
|
|
|
stages: HashMap<BoxedStageLabel, Box<dyn Stage>>,
|
|
|
|
stage_order: Vec<BoxedStageLabel>,
|
2021-02-09 20:14:10 +00:00
|
|
|
run_criteria: RunCriteria,
|
2020-12-13 02:04:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Schedule {
|
2021-02-18 21:20:37 +00:00
|
|
|
pub fn with_stage<S: Stage>(mut self, label: impl StageLabel, stage: S) -> Self {
|
|
|
|
self.add_stage(label, stage);
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
pub fn with_stage_after<S: Stage>(
|
|
|
|
mut self,
|
|
|
|
target: impl StageLabel,
|
|
|
|
label: impl StageLabel,
|
|
|
|
stage: S,
|
|
|
|
) -> Self {
|
|
|
|
self.add_stage_after(target, label, stage);
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
pub fn with_stage_before<S: Stage>(
|
|
|
|
mut self,
|
|
|
|
target: impl StageLabel,
|
|
|
|
label: impl StageLabel,
|
|
|
|
stage: S,
|
|
|
|
) -> Self {
|
|
|
|
self.add_stage_before(target, label, stage);
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2020-12-16 05:57:16 +00:00
|
|
|
pub fn with_run_criteria<S: System<In = (), Out = ShouldRun>>(mut self, system: S) -> Self {
|
2020-12-13 02:04:42 +00:00
|
|
|
self.set_run_criteria(system);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
pub fn with_system_in_stage(
|
2020-12-13 02:04:42 +00:00
|
|
|
mut self,
|
2021-02-18 21:20:37 +00:00
|
|
|
stage_label: impl StageLabel,
|
2021-02-09 20:14:10 +00:00
|
|
|
system: impl Into<SystemDescriptor>,
|
2020-12-16 05:57:16 +00:00
|
|
|
) -> Self {
|
2021-02-18 21:20:37 +00:00
|
|
|
self.add_system_to_stage(stage_label, system);
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2020-12-16 05:57:16 +00:00
|
|
|
pub fn set_run_criteria<S: System<In = (), Out = ShouldRun>>(
|
|
|
|
&mut self,
|
|
|
|
system: S,
|
|
|
|
) -> &mut Self {
|
2021-02-09 20:14:10 +00:00
|
|
|
self.run_criteria.set(Box::new(system.system()));
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
pub fn add_stage<S: Stage>(&mut self, label: impl StageLabel, stage: S) -> &mut Self {
|
|
|
|
let label: Box<dyn StageLabel> = Box::new(label);
|
|
|
|
self.stage_order.push(label.clone());
|
|
|
|
let prev = self.stages.insert(label.clone(), Box::new(stage));
|
2021-01-30 20:10:14 +00:00
|
|
|
if prev.is_some() {
|
2021-02-18 21:20:37 +00:00
|
|
|
panic!("Stage already exists: {:?}.", label);
|
2021-01-30 20:10:14 +00:00
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
pub fn add_stage_after<S: Stage>(
|
|
|
|
&mut self,
|
|
|
|
target: impl StageLabel,
|
|
|
|
label: impl StageLabel,
|
|
|
|
stage: S,
|
|
|
|
) -> &mut Self {
|
|
|
|
let label: Box<dyn StageLabel> = Box::new(label);
|
|
|
|
let target = &target as &dyn StageLabel;
|
2020-12-13 02:04:42 +00:00
|
|
|
let target_index = self
|
|
|
|
.stage_order
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
2021-02-18 21:20:37 +00:00
|
|
|
.find(|(_i, stage_label)| &***stage_label == target)
|
2020-12-13 02:04:42 +00:00
|
|
|
.map(|(i, _)| i)
|
2021-02-18 21:20:37 +00:00
|
|
|
.unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target));
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
self.stage_order.insert(target_index + 1, label.clone());
|
|
|
|
let prev = self.stages.insert(label.clone(), Box::new(stage));
|
2021-01-30 20:10:14 +00:00
|
|
|
if prev.is_some() {
|
2021-02-18 21:20:37 +00:00
|
|
|
panic!("Stage already exists: {:?}.", label);
|
2021-01-30 20:10:14 +00:00
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
pub fn add_stage_before<S: Stage>(
|
|
|
|
&mut self,
|
|
|
|
target: impl StageLabel,
|
|
|
|
label: impl StageLabel,
|
|
|
|
stage: S,
|
|
|
|
) -> &mut Self {
|
|
|
|
let label: Box<dyn StageLabel> = Box::new(label);
|
|
|
|
let target = &target as &dyn StageLabel;
|
2020-12-13 02:04:42 +00:00
|
|
|
let target_index = self
|
|
|
|
.stage_order
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
2021-02-18 21:20:37 +00:00
|
|
|
.find(|(_i, stage_label)| &***stage_label == target)
|
2020-12-13 02:04:42 +00:00
|
|
|
.map(|(i, _)| i)
|
2021-02-18 21:20:37 +00:00
|
|
|
.unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target));
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
self.stage_order.insert(target_index, label.clone());
|
|
|
|
let prev = self.stages.insert(label.clone(), Box::new(stage));
|
2021-01-30 20:10:14 +00:00
|
|
|
if prev.is_some() {
|
2021-02-18 21:20:37 +00:00
|
|
|
panic!("Stage already exists: {:?}.", label);
|
2021-01-30 20:10:14 +00:00
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
pub fn add_system_to_stage(
|
2020-12-13 02:04:42 +00:00
|
|
|
&mut self,
|
2021-02-18 21:20:37 +00:00
|
|
|
stage_label: impl StageLabel,
|
2021-02-09 20:14:10 +00:00
|
|
|
system: impl Into<SystemDescriptor>,
|
2020-12-16 05:57:16 +00:00
|
|
|
) -> &mut Self {
|
2020-12-13 02:04:42 +00:00
|
|
|
let stage = self
|
2021-02-18 21:20:37 +00:00
|
|
|
.get_stage_mut::<SystemStage>(&stage_label)
|
|
|
|
.unwrap_or_else(move || {
|
2020-12-13 02:04:42 +00:00
|
|
|
panic!(
|
2021-02-18 21:20:37 +00:00
|
|
|
"Stage '{:?}' does not exist or is not a SystemStage",
|
|
|
|
stage_label
|
2020-12-13 02:04:42 +00:00
|
|
|
)
|
|
|
|
});
|
2021-02-09 20:14:10 +00:00
|
|
|
stage.add_system(system);
|
2020-12-13 02:04:42 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn stage<T: Stage, F: FnOnce(&mut T) -> &mut T>(
|
|
|
|
&mut self,
|
2021-02-18 21:20:37 +00:00
|
|
|
label: impl StageLabel,
|
2020-12-13 02:04:42 +00:00
|
|
|
func: F,
|
|
|
|
) -> &mut Self {
|
2021-02-18 21:20:37 +00:00
|
|
|
let stage = self.get_stage_mut::<T>(&label).unwrap_or_else(move || {
|
|
|
|
panic!("stage '{:?}' does not exist or is the wrong type", label)
|
|
|
|
});
|
2020-12-13 02:04:42 +00:00
|
|
|
func(stage);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
pub fn get_stage<T: Stage>(&self, label: &dyn StageLabel) -> Option<&T> {
|
2020-12-13 02:04:42 +00:00
|
|
|
self.stages
|
2021-02-18 21:20:37 +00:00
|
|
|
.get(label)
|
2020-12-13 02:04:42 +00:00
|
|
|
.and_then(|stage| stage.downcast_ref::<T>())
|
|
|
|
}
|
|
|
|
|
2021-02-18 21:20:37 +00:00
|
|
|
pub fn get_stage_mut<T: Stage>(&mut self, label: &dyn StageLabel) -> Option<&mut T> {
|
2020-12-13 02:04:42 +00:00
|
|
|
self.stages
|
2021-02-18 21:20:37 +00:00
|
|
|
.get_mut(label)
|
2020-12-13 02:04:42 +00:00
|
|
|
.and_then(|stage| stage.downcast_mut::<T>())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run_once(&mut self, world: &mut World, resources: &mut Resources) {
|
2021-02-18 21:20:37 +00:00
|
|
|
for label in self.stage_order.iter() {
|
2020-12-13 02:04:42 +00:00
|
|
|
#[cfg(feature = "trace")]
|
2021-02-18 21:20:37 +00:00
|
|
|
let stage_span =
|
|
|
|
bevy_utils::tracing::info_span!("stage", name = &format!("{:?}", label) as &str);
|
2020-12-13 02:04:42 +00:00
|
|
|
#[cfg(feature = "trace")]
|
|
|
|
let _stage_guard = stage_span.enter();
|
2021-02-18 21:20:37 +00:00
|
|
|
let stage = self.stages.get_mut(label).unwrap();
|
2020-12-13 02:04:42 +00:00
|
|
|
stage.run(world, resources);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Stage for Schedule {
|
|
|
|
fn run(&mut self, world: &mut World, resources: &mut Resources) {
|
|
|
|
loop {
|
2021-02-09 20:14:10 +00:00
|
|
|
match self.run_criteria.should_run(world, resources) {
|
2020-12-13 02:04:42 +00:00
|
|
|
ShouldRun::No => return,
|
|
|
|
ShouldRun::Yes => {
|
|
|
|
self.run_once(world, resources);
|
|
|
|
return;
|
|
|
|
}
|
2021-02-09 20:14:10 +00:00
|
|
|
ShouldRun::YesAndCheckAgain => {
|
2020-12-13 02:04:42 +00:00
|
|
|
self.run_once(world, resources);
|
|
|
|
}
|
2021-02-09 20:14:10 +00:00
|
|
|
ShouldRun::NoAndCheckAgain => {
|
|
|
|
panic!("`NoAndCheckAgain` would loop infinitely in this situation.")
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear_trackers_system(world: &mut World, resources: &mut Resources) {
|
|
|
|
world.clear_trackers();
|
|
|
|
resources.clear_trackers();
|
|
|
|
}
|
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
pub enum ShouldRun {
|
|
|
|
/// Yes, the system should run.
|
|
|
|
Yes,
|
|
|
|
/// No, the system should not run.
|
|
|
|
No,
|
|
|
|
/// Yes, the system should run, and afterwards the criteria should be checked again.
|
|
|
|
YesAndCheckAgain,
|
|
|
|
/// No, the system should not run right now, but the criteria should be checked again later.
|
|
|
|
NoAndCheckAgain,
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
pub(crate) struct RunCriteria {
|
|
|
|
criteria_system: Option<BoxedSystem<(), ShouldRun>>,
|
|
|
|
initialized: bool,
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
impl Default for RunCriteria {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
criteria_system: None,
|
|
|
|
initialized: false,
|
2020-12-13 02:04:42 +00:00
|
|
|
}
|
|
|
|
}
|
2021-02-09 20:14:10 +00:00
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
impl RunCriteria {
|
|
|
|
pub fn set(&mut self, criteria_system: BoxedSystem<(), ShouldRun>) {
|
|
|
|
self.criteria_system = Some(criteria_system);
|
|
|
|
self.initialized = false;
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
pub fn should_run(&mut self, world: &mut World, resources: &mut Resources) -> ShouldRun {
|
|
|
|
if let Some(ref mut run_criteria) = self.criteria_system {
|
|
|
|
if !self.initialized {
|
|
|
|
run_criteria.initialize(world, resources);
|
|
|
|
self.initialized = true;
|
2020-12-13 02:04:42 +00:00
|
|
|
}
|
2021-02-09 20:14:10 +00:00
|
|
|
let should_run = run_criteria.run((), world, resources);
|
|
|
|
run_criteria.apply_buffers(world, resources);
|
|
|
|
// don't run when no result is returned or false is returned
|
|
|
|
should_run.unwrap_or(ShouldRun::No)
|
|
|
|
} else {
|
|
|
|
ShouldRun::Yes
|
2020-12-13 02:04:42 +00:00
|
|
|
}
|
|
|
|
}
|
2021-02-09 20:14:10 +00:00
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
pub struct RunOnce {
|
|
|
|
ran: bool,
|
|
|
|
system_id: SystemId,
|
|
|
|
archetype_component_access: TypeAccess<ArchetypeComponent>,
|
|
|
|
component_access: TypeAccess<TypeId>,
|
|
|
|
resource_access: TypeAccess<TypeId>,
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
impl Default for RunOnce {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
ran: false,
|
|
|
|
system_id: SystemId::new(),
|
|
|
|
archetype_component_access: Default::default(),
|
|
|
|
component_access: Default::default(),
|
|
|
|
resource_access: Default::default(),
|
2020-12-13 02:04:42 +00:00
|
|
|
}
|
2021-02-09 20:14:10 +00:00
|
|
|
}
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
impl System for RunOnce {
|
|
|
|
type In = ();
|
|
|
|
type Out = ShouldRun;
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn name(&self) -> Cow<'static, str> {
|
|
|
|
Cow::Borrowed(std::any::type_name::<RunOnce>())
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn id(&self) -> SystemId {
|
|
|
|
self.system_id
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn update_access(&mut self, _world: &World) {}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn archetype_component_access(&self) -> &TypeAccess<ArchetypeComponent> {
|
|
|
|
&self.archetype_component_access
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn component_access(&self) -> &TypeAccess<TypeId> {
|
|
|
|
&self.component_access
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn resource_access(&self) -> &TypeAccess<TypeId> {
|
|
|
|
&self.resource_access
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn is_non_send(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
unsafe fn run_unsafe(
|
|
|
|
&mut self,
|
|
|
|
_input: Self::In,
|
|
|
|
_world: &World,
|
|
|
|
_resources: &Resources,
|
|
|
|
) -> Option<Self::Out> {
|
|
|
|
Some(if self.ran {
|
|
|
|
ShouldRun::No
|
|
|
|
} else {
|
|
|
|
self.ran = true;
|
|
|
|
ShouldRun::Yes
|
|
|
|
})
|
|
|
|
}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn apply_buffers(&mut self, _world: &mut World, _resources: &mut Resources) {}
|
2020-12-13 02:04:42 +00:00
|
|
|
|
2021-02-09 20:14:10 +00:00
|
|
|
fn initialize(&mut self, _world: &mut World, _resources: &mut Resources) {}
|
2020-12-13 02:04:42 +00:00
|
|
|
}
|