mirror of
https://github.com/bevyengine/bevy
synced 2024-12-18 17:13:10 +00:00
Turn apply_deferred
into a ZST System (#16642)
# Objective - Required by #16622 due to differing implementations of `System` by `FunctionSystem` and `ExclusiveFunctionSystem`. - Optimize the memory usage of instances of `apply_deferred` in system schedules. ## Solution By changing `apply_deferred` from being an ordinary system that ends up as an `ExclusiveFunctionSystem`, and instead into a ZST struct that implements `System` manually, we save ~320 bytes per instance of `apply_deferred` in any schedule. ## Testing - All current tests pass. --- ## Migration Guide - If you were previously calling the special `apply_deferred` system via `apply_deferred(world)`, don't.
This commit is contained in:
parent
67bd2b00e1
commit
f87b9fe20c
14 changed files with 166 additions and 57 deletions
|
@ -1839,7 +1839,7 @@ wasm = false
|
||||||
|
|
||||||
[package.metadata.example.apply_deferred]
|
[package.metadata.example.apply_deferred]
|
||||||
name = "Apply System Buffers"
|
name = "Apply System Buffers"
|
||||||
description = "Show how to use `apply_deferred` system"
|
description = "Show how to use `ApplyDeferred` system"
|
||||||
category = "ECS (Entity Component System)"
|
category = "ECS (Entity Component System)"
|
||||||
wasm = false
|
wasm = false
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ pub use bevy_ptr as ptr;
|
||||||
///
|
///
|
||||||
/// This includes the most common types in this crate, re-exported for your convenience.
|
/// This includes the most common types in this crate, re-exported for your convenience.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
#[expect(deprecated)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
bundle::Bundle,
|
bundle::Bundle,
|
||||||
|
@ -53,8 +54,8 @@ pub mod prelude {
|
||||||
query::{Added, AnyOf, Changed, Has, Or, QueryBuilder, QueryState, With, Without},
|
query::{Added, AnyOf, Changed, Has, Or, QueryBuilder, QueryState, With, Without},
|
||||||
removal_detection::RemovedComponents,
|
removal_detection::RemovedComponents,
|
||||||
schedule::{
|
schedule::{
|
||||||
apply_deferred, common_conditions::*, Condition, IntoSystemConfigs, IntoSystemSet,
|
apply_deferred, common_conditions::*, ApplyDeferred, Condition, IntoSystemConfigs,
|
||||||
IntoSystemSetConfigs, Schedule, Schedules, SystemSet,
|
IntoSystemSet, IntoSystemSetConfigs, Schedule, Schedules, SystemSet,
|
||||||
},
|
},
|
||||||
system::{
|
system::{
|
||||||
Commands, Deferred, EntityCommand, EntityCommands, In, InMut, InRef, IntoSystem, Local,
|
Commands, Deferred, EntityCommand, EntityCommands, In, InMut, InRef, IntoSystem, Local,
|
||||||
|
|
|
@ -293,7 +293,7 @@ where
|
||||||
/// Runs before all systems in `set`. If `self` has any systems that produce [`Commands`](crate::system::Commands)
|
/// Runs before all systems in `set`. If `self` has any systems that produce [`Commands`](crate::system::Commands)
|
||||||
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `set` will see their effect.
|
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `set` will see their effect.
|
||||||
///
|
///
|
||||||
/// If automatically inserting [`apply_deferred`](crate::schedule::apply_deferred) like
|
/// If automatically inserting [`ApplyDeferred`](crate::schedule::ApplyDeferred) like
|
||||||
/// this isn't desired, use [`before_ignore_deferred`](Self::before_ignore_deferred) instead.
|
/// this isn't desired, use [`before_ignore_deferred`](Self::before_ignore_deferred) instead.
|
||||||
///
|
///
|
||||||
/// Calling [`.chain`](Self::chain) is often more convenient and ensures that all systems are added to the schedule.
|
/// Calling [`.chain`](Self::chain) is often more convenient and ensures that all systems are added to the schedule.
|
||||||
|
@ -305,7 +305,7 @@ where
|
||||||
/// Run after all systems in `set`. If `set` has any systems that produce [`Commands`](crate::system::Commands)
|
/// Run after all systems in `set`. If `set` has any systems that produce [`Commands`](crate::system::Commands)
|
||||||
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `self` will see their effect.
|
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `self` will see their effect.
|
||||||
///
|
///
|
||||||
/// If automatically inserting [`apply_deferred`](crate::schedule::apply_deferred) like
|
/// If automatically inserting [`ApplyDeferred`](crate::schedule::ApplyDeferred) like
|
||||||
/// this isn't desired, use [`after_ignore_deferred`](Self::after_ignore_deferred) instead.
|
/// this isn't desired, use [`after_ignore_deferred`](Self::after_ignore_deferred) instead.
|
||||||
///
|
///
|
||||||
/// Calling [`.chain`](Self::chain) is often more convenient and ensures that all systems are added to the schedule.
|
/// Calling [`.chain`](Self::chain) is often more convenient and ensures that all systems are added to the schedule.
|
||||||
|
@ -429,7 +429,7 @@ where
|
||||||
///
|
///
|
||||||
/// Ordering constraints will be applied between the successive elements.
|
/// Ordering constraints will be applied between the successive elements.
|
||||||
///
|
///
|
||||||
/// If the preceding node on a edge has deferred parameters, a [`apply_deferred`](crate::schedule::apply_deferred)
|
/// If the preceding node on a edge has deferred parameters, a [`ApplyDeferred`](crate::schedule::ApplyDeferred)
|
||||||
/// will be inserted on the edge. If this behavior is not desired consider using
|
/// will be inserted on the edge. If this behavior is not desired consider using
|
||||||
/// [`chain_ignore_deferred`](Self::chain_ignore_deferred) instead.
|
/// [`chain_ignore_deferred`](Self::chain_ignore_deferred) instead.
|
||||||
fn chain(self) -> SystemConfigs {
|
fn chain(self) -> SystemConfigs {
|
||||||
|
@ -440,7 +440,7 @@ where
|
||||||
///
|
///
|
||||||
/// Ordering constraints will be applied between the successive elements.
|
/// Ordering constraints will be applied between the successive elements.
|
||||||
///
|
///
|
||||||
/// Unlike [`chain`](Self::chain) this will **not** add [`apply_deferred`](crate::schedule::apply_deferred) on the edges.
|
/// Unlike [`chain`](Self::chain) this will **not** add [`ApplyDeferred`](crate::schedule::ApplyDeferred) on the edges.
|
||||||
fn chain_ignore_deferred(self) -> SystemConfigs {
|
fn chain_ignore_deferred(self) -> SystemConfigs {
|
||||||
self.into_configs().chain_ignore_deferred()
|
self.into_configs().chain_ignore_deferred()
|
||||||
}
|
}
|
||||||
|
@ -610,7 +610,7 @@ where
|
||||||
/// Runs before all systems in `set`. If `self` has any systems that produce [`Commands`](crate::system::Commands)
|
/// Runs before all systems in `set`. If `self` has any systems that produce [`Commands`](crate::system::Commands)
|
||||||
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `set` will see their effect.
|
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `set` will see their effect.
|
||||||
///
|
///
|
||||||
/// If automatically inserting [`apply_deferred`](crate::schedule::apply_deferred) like
|
/// If automatically inserting [`ApplyDeferred`](crate::schedule::ApplyDeferred) like
|
||||||
/// this isn't desired, use [`before_ignore_deferred`](Self::before_ignore_deferred) instead.
|
/// this isn't desired, use [`before_ignore_deferred`](Self::before_ignore_deferred) instead.
|
||||||
fn before<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
|
fn before<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
|
||||||
self.into_configs().before(set)
|
self.into_configs().before(set)
|
||||||
|
@ -619,7 +619,7 @@ where
|
||||||
/// Runs before all systems in `set`. If `set` has any systems that produce [`Commands`](crate::system::Commands)
|
/// Runs before all systems in `set`. If `set` has any systems that produce [`Commands`](crate::system::Commands)
|
||||||
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `self` will see their effect.
|
/// or other [`Deferred`](crate::system::Deferred) operations, all systems in `self` will see their effect.
|
||||||
///
|
///
|
||||||
/// If automatically inserting [`apply_deferred`](crate::schedule::apply_deferred) like
|
/// If automatically inserting [`ApplyDeferred`](crate::schedule::ApplyDeferred) like
|
||||||
/// this isn't desired, use [`after_ignore_deferred`](Self::after_ignore_deferred) instead.
|
/// this isn't desired, use [`after_ignore_deferred`](Self::after_ignore_deferred) instead.
|
||||||
fn after<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
|
fn after<M>(self, set: impl IntoSystemSet<M>) -> SystemSetConfigs {
|
||||||
self.into_configs().after(set)
|
self.into_configs().after(set)
|
||||||
|
@ -672,7 +672,7 @@ where
|
||||||
///
|
///
|
||||||
/// Ordering constraints will be applied between the successive elements.
|
/// Ordering constraints will be applied between the successive elements.
|
||||||
///
|
///
|
||||||
/// Unlike [`chain`](Self::chain) this will **not** add [`apply_deferred`](crate::schedule::apply_deferred) on the edges.
|
/// Unlike [`chain`](Self::chain) this will **not** add [`ApplyDeferred`](crate::schedule::ApplyDeferred) on the edges.
|
||||||
fn chain_ignore_deferred(self) -> SystemSetConfigs {
|
fn chain_ignore_deferred(self) -> SystemSetConfigs {
|
||||||
self.into_configs().chain_ignore_deferred()
|
self.into_configs().chain_ignore_deferred()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@ mod multi_threaded;
|
||||||
mod simple;
|
mod simple;
|
||||||
mod single_threaded;
|
mod single_threaded;
|
||||||
|
|
||||||
|
use alloc::borrow::Cow;
|
||||||
|
use core::any::TypeId;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
multi_threaded::{MainThreadExecutor, MultiThreadedExecutor},
|
multi_threaded::{MainThreadExecutor, MultiThreadedExecutor},
|
||||||
simple::SimpleExecutor,
|
simple::SimpleExecutor,
|
||||||
|
@ -11,9 +14,13 @@ pub use self::{
|
||||||
use fixedbitset::FixedBitSet;
|
use fixedbitset::FixedBitSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
schedule::{BoxedCondition, NodeId},
|
archetype::ArchetypeComponentId,
|
||||||
system::BoxedSystem,
|
component::{ComponentId, Tick},
|
||||||
world::World,
|
prelude::{IntoSystemSet, SystemSet},
|
||||||
|
query::Access,
|
||||||
|
schedule::{BoxedCondition, InternedSystemSet, NodeId, SystemTypeSet},
|
||||||
|
system::{BoxedSystem, System, SystemIn},
|
||||||
|
world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Types that can run a [`SystemSchedule`] on a [`World`].
|
/// Types that can run a [`SystemSchedule`] on a [`World`].
|
||||||
|
@ -100,32 +107,132 @@ impl SystemSchedule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instructs the executor to call [`System::apply_deferred`](crate::system::System::apply_deferred)
|
/// See [`ApplyDeferred`].
|
||||||
/// on the systems that have run but not applied their [`Deferred`](crate::system::Deferred) system parameters
|
#[deprecated = "Use `ApplyDeferred` instead. This was previously a function but is now a marker struct System."]
|
||||||
/// (like [`Commands`](crate::prelude::Commands)) or other system buffers.
|
#[expect(non_upper_case_globals)]
|
||||||
|
pub const apply_deferred: ApplyDeferred = ApplyDeferred;
|
||||||
|
|
||||||
|
/// A special [`System`] that instructs the executor to call
|
||||||
|
/// [`System::apply_deferred`] on the systems that have run but not applied
|
||||||
|
/// their [`Deferred`] system parameters (like [`Commands`]) or other system buffers.
|
||||||
///
|
///
|
||||||
/// ## Scheduling
|
/// ## Scheduling
|
||||||
///
|
///
|
||||||
/// `apply_deferred` systems are scheduled *by default*
|
/// `ApplyDeferred` systems are scheduled *by default*
|
||||||
/// - later in the same schedule run (for example, if a system with `Commands` param
|
/// - later in the same schedule run (for example, if a system with `Commands` param
|
||||||
/// is scheduled in `Update`, all the changes will be visible in `PostUpdate`)
|
/// is scheduled in `Update`, all the changes will be visible in `PostUpdate`)
|
||||||
/// - between systems with dependencies if the dependency
|
/// - between systems with dependencies if the dependency [has deferred buffers]
|
||||||
/// [has deferred buffers](crate::system::System::has_deferred)
|
/// (if system `bar` directly or indirectly depends on `foo`, and `foo` uses
|
||||||
/// (if system `bar` directly or indirectly depends on `foo`, and `foo` uses `Commands` param,
|
/// `Commands` param, changes to the world in `foo` will be visible in `bar`)
|
||||||
/// changes to the world in `foo` will be visible in `bar`)
|
|
||||||
///
|
///
|
||||||
/// ## Notes
|
/// ## Notes
|
||||||
/// - This function (currently) does nothing if it's called manually or wrapped inside a [`PipeSystem`](crate::system::PipeSystem).
|
/// - This system (currently) does nothing if it's called manually or wrapped
|
||||||
/// - Modifying a [`Schedule`](super::Schedule) may change the order buffers are applied.
|
/// inside a [`PipeSystem`].
|
||||||
|
/// - Modifying a [`Schedule`] may change the order buffers are applied.
|
||||||
|
///
|
||||||
|
/// [`System::apply_deferred`]: crate::system::System::apply_deferred
|
||||||
|
/// [`Deferred`]: crate::system::Deferred
|
||||||
|
/// [`Commands`]: crate::prelude::Commands
|
||||||
|
/// [has deferred buffers]: crate::system::System::has_deferred
|
||||||
|
/// [`PipeSystem`]: crate::system::PipeSystem
|
||||||
|
/// [`Schedule`]: super::Schedule
|
||||||
#[doc(alias = "apply_system_buffers")]
|
#[doc(alias = "apply_system_buffers")]
|
||||||
#[allow(unused_variables)]
|
pub struct ApplyDeferred;
|
||||||
pub fn apply_deferred(world: &mut World) {}
|
|
||||||
|
|
||||||
/// Returns `true` if the [`System`](crate::system::System) is an instance of [`apply_deferred`].
|
/// Returns `true` if the [`System`] is an instance of [`ApplyDeferred`].
|
||||||
pub(super) fn is_apply_deferred(system: &BoxedSystem) -> bool {
|
pub(super) fn is_apply_deferred(system: &BoxedSystem) -> bool {
|
||||||
use crate::system::IntoSystem;
|
|
||||||
// deref to use `System::type_id` instead of `Any::type_id`
|
// deref to use `System::type_id` instead of `Any::type_id`
|
||||||
system.as_ref().type_id() == apply_deferred.system_type_id()
|
system.as_ref().type_id() == TypeId::of::<ApplyDeferred>()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl System for ApplyDeferred {
|
||||||
|
type In = ();
|
||||||
|
type Out = ();
|
||||||
|
|
||||||
|
fn name(&self) -> Cow<'static, str> {
|
||||||
|
Cow::Borrowed("bevy_ecs::apply_deferred")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn component_access(&self) -> &Access<ComponentId> {
|
||||||
|
// This system accesses no components.
|
||||||
|
const { &Access::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
|
||||||
|
// This system accesses no archetype components.
|
||||||
|
const { &Access::new() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_send(&self) -> bool {
|
||||||
|
// Although this system itself does nothing on its own, the system
|
||||||
|
// executor uses it to apply deferred commands. Commands must be allowed
|
||||||
|
// to access non-send resources, so this system must be non-send for
|
||||||
|
// scheduling purposes.
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_exclusive(&self) -> bool {
|
||||||
|
// This system is labeled exclusive because it is used by the system
|
||||||
|
// executor to find places where deferred commands should be applied,
|
||||||
|
// and commands can only be applied with exclusive access to the world.
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_deferred(&self) -> bool {
|
||||||
|
// This system itself doesn't have any commands to apply, but when it
|
||||||
|
// is pulled from the schedule to be ran, the executor will apply
|
||||||
|
// deferred commands from other systems.
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn run_unsafe(
|
||||||
|
&mut self,
|
||||||
|
_input: SystemIn<'_, Self>,
|
||||||
|
_world: UnsafeWorldCell,
|
||||||
|
) -> Self::Out {
|
||||||
|
// This system does nothing on its own. The executor will apply deferred
|
||||||
|
// commands from other systems instead of running this system.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&mut self, _input: SystemIn<'_, Self>, _world: &mut World) -> Self::Out {
|
||||||
|
// This system does nothing on its own. The executor will apply deferred
|
||||||
|
// commands from other systems instead of running this system.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_deferred(&mut self, _world: &mut World) {}
|
||||||
|
|
||||||
|
fn queue_deferred(&mut self, _world: DeferredWorld) {}
|
||||||
|
|
||||||
|
unsafe fn validate_param_unsafe(&mut self, _world: UnsafeWorldCell) -> bool {
|
||||||
|
// This system is always valid to run because it doesn't do anything,
|
||||||
|
// and only used as a marker for the executor.
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn initialize(&mut self, _world: &mut World) {}
|
||||||
|
|
||||||
|
fn update_archetype_component_access(&mut self, _world: UnsafeWorldCell) {}
|
||||||
|
|
||||||
|
fn check_change_tick(&mut self, _change_tick: Tick) {}
|
||||||
|
|
||||||
|
fn default_system_sets(&self) -> Vec<InternedSystemSet> {
|
||||||
|
vec![SystemTypeSet::<Self>::new().intern()]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_last_run(&self) -> Tick {
|
||||||
|
// This system is never run, so it has no last run tick.
|
||||||
|
Tick::MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_last_run(&mut self, _last_run: Tick) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoSystemSet<()> for ApplyDeferred {
|
||||||
|
type Set = SystemTypeSet<Self>;
|
||||||
|
|
||||||
|
fn into_system_set(self) -> Self::Set {
|
||||||
|
SystemTypeSet::<Self>::new()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// These functions hide the bottom of the callstack from `RUST_BACKTRACE=1` (assuming the default panic handler is used).
|
/// These functions hide the bottom of the callstack from `RUST_BACKTRACE=1` (assuming the default panic handler is used).
|
||||||
|
|
|
@ -145,7 +145,7 @@ fn evaluate_and_fold_conditions(conditions: &mut [BoxedCondition], world: &mut W
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[test]
|
#[test]
|
||||||
fn skip_automatic_sync_points() {
|
fn skip_automatic_sync_points() {
|
||||||
// Schedules automatically insert apply_deferred systems, but these should
|
// Schedules automatically insert ApplyDeferred systems, but these should
|
||||||
// not be executed as they only serve as markers and are not initialized
|
// not be executed as they only serve as markers and are not initialized
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
let mut sched = Schedule::default();
|
let mut sched = Schedule::default();
|
||||||
|
|
|
@ -23,9 +23,9 @@ pub(crate) enum DependencyKind {
|
||||||
Before,
|
Before,
|
||||||
/// A node that should be succeeded.
|
/// A node that should be succeeded.
|
||||||
After,
|
After,
|
||||||
/// A node that should be preceded and will **not** automatically insert an instance of `apply_deferred` on the edge.
|
/// A node that should be preceded and will **not** automatically insert an instance of `ApplyDeferred` on the edge.
|
||||||
BeforeNoSync,
|
BeforeNoSync,
|
||||||
/// A node that should be succeeded and will **not** automatically insert an instance of `apply_deferred` on the edge.
|
/// A node that should be succeeded and will **not** automatically insert an instance of `ApplyDeferred` on the edge.
|
||||||
AfterNoSync,
|
AfterNoSync,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,9 +213,9 @@ fn make_executor(kind: ExecutorKind) -> Box<dyn SystemExecutor> {
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum Chain {
|
pub enum Chain {
|
||||||
/// Run nodes in order. If there are deferred parameters in preceding systems a
|
/// Run nodes in order. If there are deferred parameters in preceding systems a
|
||||||
/// [`apply_deferred`] will be added on the edge.
|
/// [`ApplyDeferred`] will be added on the edge.
|
||||||
Yes,
|
Yes,
|
||||||
/// Run nodes in order. This will not add [`apply_deferred`] between nodes.
|
/// Run nodes in order. This will not add [`ApplyDeferred`] between nodes.
|
||||||
YesIgnoreDeferred,
|
YesIgnoreDeferred,
|
||||||
/// Nodes are allowed to run in any order.
|
/// Nodes are allowed to run in any order.
|
||||||
No,
|
No,
|
||||||
|
@ -367,7 +367,7 @@ impl Schedule {
|
||||||
|
|
||||||
/// Set whether the schedule applies deferred system buffers on final time or not. This is a catch-all
|
/// Set whether the schedule applies deferred system buffers on final time or not. This is a catch-all
|
||||||
/// in case a system uses commands but was not explicitly ordered before an instance of
|
/// in case a system uses commands but was not explicitly ordered before an instance of
|
||||||
/// [`apply_deferred`]. By default this
|
/// [`ApplyDeferred`]. By default this
|
||||||
/// setting is true, but may be disabled if needed.
|
/// setting is true, but may be disabled if needed.
|
||||||
pub fn set_apply_final_deferred(&mut self, apply_final_deferred: bool) -> &mut Self {
|
pub fn set_apply_final_deferred(&mut self, apply_final_deferred: bool) -> &mut Self {
|
||||||
self.executor.set_apply_final_deferred(apply_final_deferred);
|
self.executor.set_apply_final_deferred(apply_final_deferred);
|
||||||
|
@ -1191,13 +1191,13 @@ impl ScheduleGraph {
|
||||||
Ok(sync_point_graph)
|
Ok(sync_point_graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// add an [`apply_deferred`] system with no config
|
/// add an [`ApplyDeferred`] system with no config
|
||||||
fn add_auto_sync(&mut self) -> NodeId {
|
fn add_auto_sync(&mut self) -> NodeId {
|
||||||
let id = NodeId::System(self.systems.len());
|
let id = NodeId::System(self.systems.len());
|
||||||
|
|
||||||
self.systems
|
self.systems
|
||||||
.push(SystemNode::new(Box::new(IntoSystem::into_system(
|
.push(SystemNode::new(Box::new(IntoSystem::into_system(
|
||||||
apply_deferred,
|
ApplyDeferred,
|
||||||
))));
|
))));
|
||||||
self.system_conditions.push(Vec::new());
|
self.system_conditions.push(Vec::new());
|
||||||
|
|
||||||
|
@ -1998,7 +1998,7 @@ pub struct ScheduleBuildSettings {
|
||||||
///
|
///
|
||||||
/// Defaults to [`LogLevel::Warn`].
|
/// Defaults to [`LogLevel::Warn`].
|
||||||
pub hierarchy_detection: LogLevel,
|
pub hierarchy_detection: LogLevel,
|
||||||
/// Auto insert [`apply_deferred`] systems into the schedule,
|
/// Auto insert [`ApplyDeferred`] systems into the schedule,
|
||||||
/// when there are [`Deferred`](crate::prelude::Deferred)
|
/// when there are [`Deferred`](crate::prelude::Deferred)
|
||||||
/// in one system and there are ordering dependencies on that system. [`Commands`](crate::system::Commands) is one
|
/// in one system and there are ordering dependencies on that system. [`Commands`](crate::system::Commands) is one
|
||||||
/// such deferred buffer.
|
/// such deferred buffer.
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub use parallel_scope::*;
|
||||||
///
|
///
|
||||||
/// Since each command requires exclusive access to the `World`,
|
/// Since each command requires exclusive access to the `World`,
|
||||||
/// all queued commands are automatically applied in sequence
|
/// all queued commands are automatically applied in sequence
|
||||||
/// when the `apply_deferred` system runs (see [`apply_deferred`] documentation for more details).
|
/// when the `ApplyDeferred` system runs (see [`ApplyDeferred`] documentation for more details).
|
||||||
///
|
///
|
||||||
/// Each command can be used to modify the [`World`] in arbitrary ways:
|
/// Each command can be used to modify the [`World`] in arbitrary ways:
|
||||||
/// * spawning or despawning entities
|
/// * spawning or despawning entities
|
||||||
|
@ -43,7 +43,8 @@ pub use parallel_scope::*;
|
||||||
///
|
///
|
||||||
/// # Usage
|
/// # Usage
|
||||||
///
|
///
|
||||||
/// Add `mut commands: Commands` as a function argument to your system to get a copy of this struct that will be applied the next time a copy of [`apply_deferred`] runs.
|
/// Add `mut commands: Commands` as a function argument to your system to get a
|
||||||
|
/// copy of this struct that will be applied the next time a copy of [`ApplyDeferred`] runs.
|
||||||
/// Commands are almost always used as a [`SystemParam`](crate::system::SystemParam).
|
/// Commands are almost always used as a [`SystemParam`](crate::system::SystemParam).
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -75,7 +76,7 @@ pub use parallel_scope::*;
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`apply_deferred`]: crate::schedule::apply_deferred
|
/// [`ApplyDeferred`]: crate::schedule::ApplyDeferred
|
||||||
pub struct Commands<'w, 's> {
|
pub struct Commands<'w, 's> {
|
||||||
queue: InternalQueue<'s>,
|
queue: InternalQueue<'s>,
|
||||||
entities: &'w Entities,
|
entities: &'w Entities,
|
||||||
|
|
|
@ -110,7 +110,7 @@ impl SystemMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marks the system as having deferred buffers like [`Commands`](`super::Commands`)
|
/// Marks the system as having deferred buffers like [`Commands`](`super::Commands`)
|
||||||
/// This lets the scheduler insert [`apply_deferred`](`crate::prelude::apply_deferred`) systems automatically.
|
/// This lets the scheduler insert [`ApplyDeferred`](`crate::prelude::ApplyDeferred`) systems automatically.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_has_deferred(&mut self) {
|
pub fn set_has_deferred(&mut self) {
|
||||||
self.has_deferred = true;
|
self.has_deferred = true;
|
||||||
|
|
|
@ -323,7 +323,7 @@ mod tests {
|
||||||
query::{Added, Changed, Or, With, Without},
|
query::{Added, Changed, Or, With, Without},
|
||||||
removal_detection::RemovedComponents,
|
removal_detection::RemovedComponents,
|
||||||
schedule::{
|
schedule::{
|
||||||
apply_deferred, common_conditions::resource_exists, Condition, IntoSystemConfigs,
|
common_conditions::resource_exists, ApplyDeferred, Condition, IntoSystemConfigs,
|
||||||
Schedule,
|
Schedule,
|
||||||
},
|
},
|
||||||
system::{
|
system::{
|
||||||
|
@ -493,7 +493,7 @@ mod tests {
|
||||||
|
|
||||||
let mut schedule = Schedule::default();
|
let mut schedule = Schedule::default();
|
||||||
|
|
||||||
schedule.add_systems((incr_e_on_flip, apply_deferred, World::clear_trackers).chain());
|
schedule.add_systems((incr_e_on_flip, ApplyDeferred, World::clear_trackers).chain());
|
||||||
|
|
||||||
schedule.run(&mut world);
|
schedule.run(&mut world);
|
||||||
assert_eq!(world.resource::<Added>().0, 1);
|
assert_eq!(world.resource::<Added>().0, 1);
|
||||||
|
|
|
@ -210,14 +210,14 @@ pub unsafe trait SystemParam: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
|
/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
|
||||||
/// This is used to apply [`Commands`] during [`apply_deferred`](crate::prelude::apply_deferred).
|
/// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
|
||||||
///
|
///
|
||||||
/// [`Commands`]: crate::prelude::Commands
|
/// [`Commands`]: crate::prelude::Commands
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}
|
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}
|
||||||
|
|
||||||
/// Queues any deferred mutations to be applied at the next [`apply_deferred`](crate::prelude::apply_deferred).
|
/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}
|
fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}
|
||||||
|
@ -1149,12 +1149,12 @@ unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {
|
||||||
pub trait SystemBuffer: FromWorld + Send + 'static {
|
pub trait SystemBuffer: FromWorld + Send + 'static {
|
||||||
/// Applies any deferred mutations to the [`World`].
|
/// Applies any deferred mutations to the [`World`].
|
||||||
fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
|
fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
|
||||||
/// Queues any deferred mutations to be applied at the next [`apply_deferred`](crate::prelude::apply_deferred).
|
/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
|
||||||
fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld) {}
|
fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [`SystemParam`] that stores a buffer which gets applied to the [`World`] during
|
/// A [`SystemParam`] that stores a buffer which gets applied to the [`World`] during
|
||||||
/// [`apply_deferred`](crate::schedule::apply_deferred).
|
/// [`ApplyDeferred`](crate::schedule::ApplyDeferred).
|
||||||
/// This is used internally by [`Commands`] to defer `World` mutations.
|
/// This is used internally by [`Commands`] to defer `World` mutations.
|
||||||
///
|
///
|
||||||
/// [`Commands`]: crate::system::Commands
|
/// [`Commands`]: crate::system::Commands
|
||||||
|
@ -1197,7 +1197,7 @@ pub trait SystemBuffer: FromWorld + Send + 'static {
|
||||||
/// struct AlarmFlag(bool);
|
/// struct AlarmFlag(bool);
|
||||||
///
|
///
|
||||||
/// impl AlarmFlag {
|
/// impl AlarmFlag {
|
||||||
/// /// Sounds the alarm the next time buffers are applied via apply_deferred.
|
/// /// Sounds the alarm the next time buffers are applied via ApplyDeferred.
|
||||||
/// pub fn flag(&mut self) {
|
/// pub fn flag(&mut self) {
|
||||||
/// self.0 = true;
|
/// self.0 = true;
|
||||||
/// }
|
/// }
|
||||||
|
@ -1205,7 +1205,7 @@ pub trait SystemBuffer: FromWorld + Send + 'static {
|
||||||
///
|
///
|
||||||
/// impl SystemBuffer for AlarmFlag {
|
/// impl SystemBuffer for AlarmFlag {
|
||||||
/// // When `AlarmFlag` is used in a system, this function will get
|
/// // When `AlarmFlag` is used in a system, this function will get
|
||||||
/// // called the next time buffers are applied via apply_deferred.
|
/// // called the next time buffers are applied via ApplyDeferred.
|
||||||
/// fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
|
/// fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
|
||||||
/// if self.0 {
|
/// if self.0 {
|
||||||
/// world.resource_mut::<Alarm>().0 = true;
|
/// world.resource_mut::<Alarm>().0 = true;
|
||||||
|
@ -2337,12 +2337,12 @@ trait DynParamState: Sync + Send {
|
||||||
unsafe fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta);
|
unsafe fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta);
|
||||||
|
|
||||||
/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
|
/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
|
||||||
/// This is used to apply [`Commands`] during [`apply_deferred`](crate::prelude::apply_deferred).
|
/// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
|
||||||
///
|
///
|
||||||
/// [`Commands`]: crate::prelude::Commands
|
/// [`Commands`]: crate::prelude::Commands
|
||||||
fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
|
fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
|
||||||
|
|
||||||
/// Queues any deferred mutations to be applied at the next [`apply_deferred`](crate::prelude::apply_deferred).
|
/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
|
||||||
fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);
|
fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);
|
||||||
|
|
||||||
/// Refer to [`SystemParam::validate_param`].
|
/// Refer to [`SystemParam::validate_param`].
|
||||||
|
|
|
@ -410,7 +410,7 @@ impl Plugin for ScreenshotPlugin {
|
||||||
First,
|
First,
|
||||||
clear_screenshots
|
clear_screenshots
|
||||||
.after(event_update_system)
|
.after(event_update_system)
|
||||||
.before(apply_deferred),
|
.before(ApplyDeferred),
|
||||||
)
|
)
|
||||||
.add_systems(Update, trigger_screenshots)
|
.add_systems(Update, trigger_screenshots)
|
||||||
.register_type::<Screenshot>()
|
.register_type::<Screenshot>()
|
||||||
|
|
|
@ -83,7 +83,7 @@ pub trait BuildChildrenTransformExt {
|
||||||
///
|
///
|
||||||
/// Note that both the hierarchy and transform updates will only execute
|
/// Note that both the hierarchy and transform updates will only execute
|
||||||
/// the next time commands are applied
|
/// the next time commands are applied
|
||||||
/// (during [`apply_deferred`](bevy_ecs::schedule::apply_deferred)).
|
/// (during [`ApplyDeferred`](bevy_ecs::schedule::ApplyDeferred)).
|
||||||
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self;
|
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self;
|
||||||
|
|
||||||
/// Make this entity parentless while preserving this entity's [`GlobalTransform`]
|
/// Make this entity parentless while preserving this entity's [`GlobalTransform`]
|
||||||
|
@ -94,7 +94,7 @@ pub trait BuildChildrenTransformExt {
|
||||||
///
|
///
|
||||||
/// Note that both the hierarchy and transform updates will only execute
|
/// Note that both the hierarchy and transform updates will only execute
|
||||||
/// the next time commands are applied
|
/// the next time commands are applied
|
||||||
/// (during [`apply_deferred`](bevy_ecs::schedule::apply_deferred)).
|
/// (during [`ApplyDeferred`](bevy_ecs::schedule::ApplyDeferred)).
|
||||||
fn remove_parent_in_place(&mut self) -> &mut Self;
|
fn remove_parent_in_place(&mut self) -> &mut Self;
|
||||||
}
|
}
|
||||||
impl BuildChildrenTransformExt for EntityCommands<'_> {
|
impl BuildChildrenTransformExt for EntityCommands<'_> {
|
||||||
|
|
|
@ -461,7 +461,7 @@ mod tests {
|
||||||
event::Events,
|
event::Events,
|
||||||
prelude::{Commands, Component, In, Query, With},
|
prelude::{Commands, Component, In, Query, With},
|
||||||
query::Without,
|
query::Without,
|
||||||
schedule::{apply_deferred, IntoSystemConfigs, Schedule},
|
schedule::{ApplyDeferred, IntoSystemConfigs, Schedule},
|
||||||
system::RunSystemOnce,
|
system::RunSystemOnce,
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
|
@ -527,7 +527,7 @@ mod tests {
|
||||||
// UI is driven by calculated camera target info, so we need to run the camera system first
|
// UI is driven by calculated camera target info, so we need to run the camera system first
|
||||||
bevy_render::camera::camera_system::<OrthographicProjection>,
|
bevy_render::camera::camera_system::<OrthographicProjection>,
|
||||||
update_target_camera_system,
|
update_target_camera_system,
|
||||||
apply_deferred,
|
ApplyDeferred,
|
||||||
ui_layout_system,
|
ui_layout_system,
|
||||||
sync_simple_transforms,
|
sync_simple_transforms,
|
||||||
propagate_transforms,
|
propagate_transforms,
|
||||||
|
@ -1171,7 +1171,7 @@ mod tests {
|
||||||
// UI is driven by calculated camera target info, so we need to run the camera system first
|
// UI is driven by calculated camera target info, so we need to run the camera system first
|
||||||
bevy_render::camera::camera_system::<OrthographicProjection>,
|
bevy_render::camera::camera_system::<OrthographicProjection>,
|
||||||
update_target_camera_system,
|
update_target_camera_system,
|
||||||
apply_deferred,
|
ApplyDeferred,
|
||||||
ui_layout_system,
|
ui_layout_system,
|
||||||
)
|
)
|
||||||
.chain(),
|
.chain(),
|
||||||
|
|
Loading…
Reference in a new issue