Make RunOnce a non-manual System impl (#3922)

# Objective

- `RunOnce` was a manual `System` implementation.
- Adding run criteria to stages was yet to be systemyoten

## Solution

- Make it a normal function
- yeet

##  Changelog

- Replaced `RunOnce` with `ShouldRun::once`

## Migration guide

The run criterion `RunOnce`, which would make the controlled systems run only once, has been replaced with a new run criterion function `ShouldRun::once`. Replace all instances of `RunOnce` with `ShouldRun::once`.
This commit is contained in:
Daniel McNab 2022-05-04 18:41:37 +00:00
parent 3e24b725af
commit 9d440fbcb5
3 changed files with 23 additions and 58 deletions

View File

@ -4,7 +4,7 @@ use bevy_ecs::{
event::Events, event::Events,
prelude::{FromWorld, IntoExclusiveSystem}, prelude::{FromWorld, IntoExclusiveSystem},
schedule::{ schedule::{
IntoSystemDescriptor, RunOnce, Schedule, Stage, StageLabel, State, StateData, SystemSet, IntoSystemDescriptor, Schedule, ShouldRun, Stage, StageLabel, State, StateData, SystemSet,
SystemStage, SystemStage,
}, },
system::Resource, system::Resource,
@ -591,7 +591,7 @@ impl App {
.add_stage( .add_stage(
StartupSchedule, StartupSchedule,
Schedule::default() Schedule::default()
.with_run_criteria(RunOnce::default()) .with_run_criteria(ShouldRun::once)
.with_stage(StartupStage::PreStartup, SystemStage::parallel()) .with_stage(StartupStage::PreStartup, SystemStage::parallel())
.with_stage(StartupStage::Startup, SystemStage::parallel()) .with_stage(StartupStage::Startup, SystemStage::parallel())
.with_stage(StartupStage::PostStartup, SystemStage::parallel()), .with_stage(StartupStage::PostStartup, SystemStage::parallel()),

View File

@ -27,7 +27,7 @@ pub use system_set::*;
use std::fmt::Debug; use std::fmt::Debug;
use crate::{system::System, world::World}; use crate::{system::IntoSystem, world::World};
use bevy_utils::HashMap; use bevy_utils::HashMap;
/// A container of [`Stage`]s set to be run in a linear order. /// A container of [`Stage`]s set to be run in a linear order.
@ -76,7 +76,7 @@ impl Schedule {
} }
#[must_use] #[must_use]
pub fn with_run_criteria<S: System<In = (), Out = ShouldRun>>(mut self, system: S) -> Self { pub fn with_run_criteria<S: IntoSystem<(), ShouldRun, P>, P>(mut self, system: S) -> Self {
self.set_run_criteria(system); self.set_run_criteria(system);
self self
} }
@ -92,11 +92,9 @@ impl Schedule {
self self
} }
pub fn set_run_criteria<S: System<In = (), Out = ShouldRun>>( pub fn set_run_criteria<S: IntoSystem<(), ShouldRun, P>, P>(&mut self, system: S) -> &mut Self {
&mut self, self.run_criteria
system: S, .set(Box::new(IntoSystem::into_system(system)));
) -> &mut Self {
self.run_criteria.set(Box::new(system));
self self
} }

View File

@ -1,9 +1,6 @@
use crate::{ use crate::{
archetype::ArchetypeComponentId,
component::ComponentId,
query::Access,
schedule::{BoxedRunCriteriaLabel, GraphNode, RunCriteriaLabel}, schedule::{BoxedRunCriteriaLabel, GraphNode, RunCriteriaLabel},
system::{BoxedSystem, IntoSystem, System}, system::{BoxedSystem, IntoSystem, Local},
world::World, world::World,
}; };
use std::borrow::Cow; use std::borrow::Cow;
@ -44,6 +41,21 @@ pub enum ShouldRun {
NoAndCheckAgain, NoAndCheckAgain,
} }
impl ShouldRun {
/// A run criterion which returns [`ShouldRun::Yes`] exactly once.
///
/// This leads to the systems controlled by it only being
/// executed one time only.
pub fn once(mut ran: Local<bool>) -> ShouldRun {
if *ran {
ShouldRun::No
} else {
*ran = true;
ShouldRun::Yes
}
}
}
#[derive(Default)] #[derive(Default)]
pub(crate) struct BoxedRunCriteria { pub(crate) struct BoxedRunCriteria {
criteria_system: Option<BoxedSystem<(), ShouldRun>>, criteria_system: Option<BoxedSystem<(), ShouldRun>>,
@ -324,48 +336,3 @@ impl RunCriteria {
} }
} }
} }
#[derive(Default)]
pub struct RunOnce {
ran: bool,
archetype_component_access: Access<ArchetypeComponentId>,
component_access: Access<ComponentId>,
}
impl System for RunOnce {
type In = ();
type Out = ShouldRun;
fn name(&self) -> Cow<'static, str> {
Cow::Borrowed(std::any::type_name::<RunOnce>())
}
fn component_access(&self) -> &Access<ComponentId> {
&self.component_access
}
fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
&self.archetype_component_access
}
fn is_send(&self) -> bool {
true
}
unsafe fn run_unsafe(&mut self, _input: (), _world: &World) -> ShouldRun {
if self.ran {
ShouldRun::No
} else {
self.ran = true;
ShouldRun::Yes
}
}
fn apply_buffers(&mut self, _world: &mut World) {}
fn initialize(&mut self, _world: &mut World) {}
fn update_archetype_component_access(&mut self, _world: &World) {}
fn check_change_tick(&mut self, _change_tick: u32) {}
}